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.c794
1 files changed, 399 insertions, 395 deletions
diff --git a/src/util/container_meta_data.c b/src/util/container_meta_data.c
index 16173cca9..1ea77f63a 100644
--- a/src/util/container_meta_data.c
+++ b/src/util/container_meta_data.c
@@ -32,6 +32,8 @@
32#include <extractor.h> 32#include <extractor.h>
33#include <zlib.h> 33#include <zlib.h>
34 34
35#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
36
35/** 37/**
36 * Meta data item. 38 * Meta data item.
37 */ 39 */
@@ -160,10 +162,10 @@ GNUNET_CONTAINER_meta_data_destroy (struct GNUNET_CONTAINER_MetaData *md)
160 if (md == NULL) 162 if (md == NULL)
161 return; 163 return;
162 while (NULL != (item = md->items)) 164 while (NULL != (item = md->items))
163 { 165 {
164 md->items = item->next; 166 md->items = item->next;
165 meta_item_free (item); 167 meta_item_free (item);
166 } 168 }
167 GNUNET_free_non_null (md->sbuf); 169 GNUNET_free_non_null (md->sbuf);
168 GNUNET_free (md); 170 GNUNET_free (md);
169} 171}
@@ -182,10 +184,10 @@ GNUNET_CONTAINER_meta_data_clear (struct GNUNET_CONTAINER_MetaData *md)
182 if (md == NULL) 184 if (md == NULL)
183 return; 185 return;
184 while (NULL != (item = md->items)) 186 while (NULL != (item = md->items))
185 { 187 {
186 md->items = item->next; 188 md->items = item->next;
187 meta_item_free (item); 189 meta_item_free (item);
188 } 190 }
189 GNUNET_free_non_null (md->sbuf); 191 GNUNET_free_non_null (md->sbuf);
190 memset (md, 0, sizeof (struct GNUNET_CONTAINER_MetaData)); 192 memset (md, 0, sizeof (struct GNUNET_CONTAINER_MetaData));
191} 193}
@@ -204,9 +206,9 @@ GNUNET_CONTAINER_meta_data_clear (struct GNUNET_CONTAINER_MetaData *md)
204 */ 206 */
205int 207int
206GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData 208GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData
207 *md1, 209 *md1,
208 const struct GNUNET_CONTAINER_MetaData 210 const struct GNUNET_CONTAINER_MetaData
209 *md2) 211 *md2)
210{ 212{
211 struct MetaItem *i; 213 struct MetaItem *i;
212 struct MetaItem *j; 214 struct MetaItem *j;
@@ -219,24 +221,24 @@ GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData
219 221
220 i = md1->items; 222 i = md1->items;
221 while (NULL != i) 223 while (NULL != i)
222 {
223 found = GNUNET_NO;
224 j = md2->items;
225 while (NULL != j)
226 { 224 {
227 if ((i->type == j->type) && (i->format == j->format) && 225 found = GNUNET_NO;
228 (i->data_size == j->data_size) && 226 j = md2->items;
229 (0 == memcmp (i->data, j->data, i->data_size))) 227 while (NULL != j)
230 { 228 {
231 found = GNUNET_YES; 229 if ((i->type == j->type) && (i->format == j->format) &&
232 break; 230 (i->data_size == j->data_size) &&
233 } 231 (0 == memcmp (i->data, j->data, i->data_size)))
234 j = j->next; 232 {
233 found = GNUNET_YES;
234 break;
235 }
236 j = j->next;
237 }
238 if (found == GNUNET_NO)
239 return GNUNET_NO;
240 i = i->next;
235 } 241 }
236 if (found == GNUNET_NO)
237 return GNUNET_NO;
238 i = i->next;
239 }
240 return GNUNET_YES; 242 return GNUNET_YES;
241} 243}
242 244
@@ -261,11 +263,11 @@ GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData
261 */ 263 */
262int 264int
263GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md, 265GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
264 const char *plugin_name, 266 const char *plugin_name,
265 enum EXTRACTOR_MetaType type, 267 enum EXTRACTOR_MetaType type,
266 enum EXTRACTOR_MetaFormat format, 268 enum EXTRACTOR_MetaFormat format,
267 const char *data_mime_type, const char *data, 269 const char *data_mime_type,
268 size_t data_len) 270 const char *data, size_t data_len)
269{ 271{
270 struct MetaItem *prev; 272 struct MetaItem *prev;
271 struct MetaItem *pos; 273 struct MetaItem *pos;
@@ -275,28 +277,28 @@ GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
275 prev = NULL; 277 prev = NULL;
276 pos = md->items; 278 pos = md->items;
277 while (NULL != pos) 279 while (NULL != pos)
278 {
279 if (pos->data_size < data_len)
280 break;
281 if ((pos->type == type) && (pos->data_size == data_len) &&
282 (0 == memcmp (pos->data, data, data_len)))
283 { 280 {
284 if ((pos->mime_type == NULL) && (data_mime_type != NULL)) 281 if (pos->data_size < data_len)
285 { 282 break;
286 pos->mime_type = GNUNET_strdup (data_mime_type); 283 if ((pos->type == type) && (pos->data_size == data_len) &&
287 invalidate_sbuf (md); 284 (0 == memcmp (pos->data, data, data_len)))
288 } 285 {
289 if ((pos->format == EXTRACTOR_METAFORMAT_C_STRING) && 286 if ((pos->mime_type == NULL) && (data_mime_type != NULL))
290 (format == EXTRACTOR_METAFORMAT_UTF8)) 287 {
291 { 288 pos->mime_type = GNUNET_strdup (data_mime_type);
292 pos->format = EXTRACTOR_METAFORMAT_UTF8; 289 invalidate_sbuf (md);
293 invalidate_sbuf (md); 290 }
294 } 291 if ((pos->format == EXTRACTOR_METAFORMAT_C_STRING) &&
295 return GNUNET_SYSERR; 292 (format == EXTRACTOR_METAFORMAT_UTF8))
293 {
294 pos->format = EXTRACTOR_METAFORMAT_UTF8;
295 invalidate_sbuf (md);
296 }
297 return GNUNET_SYSERR;
298 }
299 prev = pos;
300 pos = pos->next;
296 } 301 }
297 prev = pos;
298 pos = pos->next;
299 }
300 md->item_count++; 302 md->item_count++;
301 i = GNUNET_malloc (sizeof (struct MetaItem)); 303 i = GNUNET_malloc (sizeof (struct MetaItem));
302 i->type = type; 304 i->type = type;
@@ -308,23 +310,23 @@ GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
308 else 310 else
309 prev->next = i; 311 prev->next = i;
310 i->mime_type = 312 i->mime_type =
311 (data_mime_type == NULL) ? NULL : GNUNET_strdup (data_mime_type); 313 (data_mime_type == NULL) ? NULL : GNUNET_strdup (data_mime_type);
312 i->plugin_name = (plugin_name == NULL) ? NULL : GNUNET_strdup (plugin_name); 314 i->plugin_name = (plugin_name == NULL) ? NULL : GNUNET_strdup (plugin_name);
313 i->data = GNUNET_malloc (data_len); 315 i->data = GNUNET_malloc (data_len);
314 memcpy (i->data, data, data_len); 316 memcpy (i->data, data, data_len);
315 /* change OS native dir separators to unix '/' and others to '_' */ 317 /* change OS native dir separators to unix '/' and others to '_' */
316 if (type == EXTRACTOR_METATYPE_FILENAME) 318 if (type == EXTRACTOR_METATYPE_FILENAME)
317 {
318 p = i->data;
319 while ((*p != '\0') && (p < i->data + data_len))
320 { 319 {
321 if (*p == DIR_SEPARATOR) 320 p = i->data;
322 *p = '/'; 321 while ((*p != '\0') && (p < i->data + data_len))
323 else if (*p == '\\') 322 {
324 *p = '_'; 323 if (*p == DIR_SEPARATOR)
325 p++; 324 *p = '/';
325 else if (*p == '\\')
326 *p = '_';
327 p++;
328 }
326 } 329 }
327 }
328 invalidate_sbuf (md); 330 invalidate_sbuf (md);
329 return GNUNET_OK; 331 return GNUNET_OK;
330} 332}
@@ -347,14 +349,14 @@ GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
347 * @return 0 (to continue) 349 * @return 0 (to continue)
348 */ 350 */
349static int 351static int
350merge_helper (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, 352merge_helper (void *cls, const char *plugin_name,
351 enum EXTRACTOR_MetaFormat format, const char *data_mime_type, 353 enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format,
352 const char *data, size_t data_len) 354 const char *data_mime_type, const char *data, size_t data_len)
353{ 355{
354 struct GNUNET_CONTAINER_MetaData *md = cls; 356 struct GNUNET_CONTAINER_MetaData *md = cls;
355 357
356 (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format, 358 (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format,
357 data_mime_type, data, data_len); 359 data_mime_type, data, data_len);
358 return 0; 360 return 0;
359} 361}
360 362
@@ -368,7 +370,7 @@ merge_helper (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type,
368 */ 370 */
369void 371void
370GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md, 372GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md,
371 const struct GNUNET_CONTAINER_MetaData *in) 373 const struct GNUNET_CONTAINER_MetaData *in)
372{ 374{
373 GNUNET_CONTAINER_meta_data_iterate (in, &merge_helper, md); 375 GNUNET_CONTAINER_meta_data_iterate (in, &merge_helper, md);
374} 376}
@@ -386,8 +388,8 @@ GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md,
386 */ 388 */
387int 389int
388GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md, 390GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md,
389 enum EXTRACTOR_MetaType type, 391 enum EXTRACTOR_MetaType type,
390 const char *data, size_t data_len) 392 const char *data, size_t data_len)
391{ 393{
392 struct MetaItem *pos; 394 struct MetaItem *pos;
393 struct MetaItem *prev; 395 struct MetaItem *prev;
@@ -395,24 +397,24 @@ GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md,
395 prev = NULL; 397 prev = NULL;
396 pos = md->items; 398 pos = md->items;
397 while (NULL != pos) 399 while (NULL != pos)
398 {
399 if ((pos->type == type) &&
400 ((data == NULL) ||
401 ((pos->data_size == data_len) &&
402 (0 == memcmp (pos->data, data, data_len)))))
403 { 400 {
404 if (prev == NULL) 401 if ((pos->type == type) &&
405 md->items = pos->next; 402 ((data == NULL) ||
406 else 403 ((pos->data_size == data_len) &&
407 prev->next = pos->next; 404 (0 == memcmp (pos->data, data, data_len)))))
408 meta_item_free (pos); 405 {
409 md->item_count--; 406 if (prev == NULL)
410 invalidate_sbuf (md); 407 md->items = pos->next;
411 return GNUNET_OK; 408 else
409 prev->next = pos->next;
410 meta_item_free (pos);
411 md->item_count--;
412 invalidate_sbuf (md);
413 return GNUNET_OK;
414 }
415 prev = pos;
416 pos = pos->next;
412 } 417 }
413 prev = pos;
414 pos = pos->next;
415 }
416 return GNUNET_SYSERR; 418 return GNUNET_SYSERR;
417} 419}
418 420
@@ -425,19 +427,20 @@ GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md,
425 */ 427 */
426void 428void
427GNUNET_CONTAINER_meta_data_add_publication_date (struct 429GNUNET_CONTAINER_meta_data_add_publication_date (struct
428 GNUNET_CONTAINER_MetaData *md) 430 GNUNET_CONTAINER_MetaData
431 *md)
429{ 432{
430 char *dat; 433 char *dat;
431 struct GNUNET_TIME_Absolute t; 434 struct GNUNET_TIME_Absolute t;
432 435
433 t = GNUNET_TIME_absolute_get (); 436 t = GNUNET_TIME_absolute_get ();
434 GNUNET_CONTAINER_meta_data_delete (md, EXTRACTOR_METATYPE_PUBLICATION_DATE, 437 GNUNET_CONTAINER_meta_data_delete (md, EXTRACTOR_METATYPE_PUBLICATION_DATE,
435 NULL, 0); 438 NULL, 0);
436 dat = GNUNET_STRINGS_absolute_time_to_string (t); 439 dat = GNUNET_STRINGS_absolute_time_to_string (t);
437 GNUNET_CONTAINER_meta_data_insert (md, "<gnunet>", 440 GNUNET_CONTAINER_meta_data_insert (md, "<gnunet>",
438 EXTRACTOR_METATYPE_PUBLICATION_DATE, 441 EXTRACTOR_METATYPE_PUBLICATION_DATE,
439 EXTRACTOR_METAFORMAT_UTF8, "text/plain", 442 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
440 dat, strlen (dat) + 1); 443 dat, strlen (dat) + 1);
441 GNUNET_free (dat); 444 GNUNET_free (dat);
442} 445}
443 446
@@ -451,9 +454,9 @@ GNUNET_CONTAINER_meta_data_add_publication_date (struct
451 * @return number of entries 454 * @return number of entries
452 */ 455 */
453int 456int
454GNUNET_CONTAINER_meta_data_iterate (const struct GNUNET_CONTAINER_MetaData *md, 457GNUNET_CONTAINER_meta_data_iterate (const struct GNUNET_CONTAINER_MetaData
455 EXTRACTOR_MetaDataProcessor iter, 458 *md, EXTRACTOR_MetaDataProcessor iter,
456 void *iter_cls) 459 void *iter_cls)
457{ 460{
458 struct MetaItem *pos; 461 struct MetaItem *pos;
459 462
@@ -463,13 +466,13 @@ GNUNET_CONTAINER_meta_data_iterate (const struct GNUNET_CONTAINER_MetaData *md,
463 return md->item_count; 466 return md->item_count;
464 pos = md->items; 467 pos = md->items;
465 while (NULL != pos) 468 while (NULL != pos)
466 { 469 {
467 if (0 != 470 if (0 !=
468 iter (iter_cls, pos->plugin_name, pos->type, pos->format, 471 iter (iter_cls, pos->plugin_name, pos->type, pos->format,
469 pos->mime_type, pos->data, pos->data_size)) 472 pos->mime_type, pos->data, pos->data_size))
470 return md->item_count; 473 return md->item_count;
471 pos = pos->next; 474 pos = pos->next;
472 } 475 }
473 return md->item_count; 476 return md->item_count;
474} 477}
475 478
@@ -486,7 +489,7 @@ GNUNET_CONTAINER_meta_data_iterate (const struct GNUNET_CONTAINER_MetaData *md,
486 */ 489 */
487char * 490char *
488GNUNET_CONTAINER_meta_data_get_by_type (const struct GNUNET_CONTAINER_MetaData 491GNUNET_CONTAINER_meta_data_get_by_type (const struct GNUNET_CONTAINER_MetaData
489 *md, enum EXTRACTOR_MetaType type) 492 *md, enum EXTRACTOR_MetaType type)
490{ 493{
491 struct MetaItem *pos; 494 struct MetaItem *pos;
492 495
@@ -494,13 +497,13 @@ GNUNET_CONTAINER_meta_data_get_by_type (const struct GNUNET_CONTAINER_MetaData
494 return NULL; 497 return NULL;
495 pos = md->items; 498 pos = md->items;
496 while (NULL != pos) 499 while (NULL != pos)
497 { 500 {
498 if ((type == pos->type) && 501 if ((type == pos->type) &&
499 ((pos->format == EXTRACTOR_METAFORMAT_UTF8) || 502 ((pos->format == EXTRACTOR_METAFORMAT_UTF8) ||
500 (pos->format == EXTRACTOR_METAFORMAT_C_STRING))) 503 (pos->format == EXTRACTOR_METAFORMAT_C_STRING)))
501 return GNUNET_strdup (pos->data); 504 return GNUNET_strdup (pos->data);
502 pos = pos->next; 505 pos = pos->next;
503 } 506 }
504 return NULL; 507 return NULL;
505} 508}
506 509
@@ -518,8 +521,8 @@ GNUNET_CONTAINER_meta_data_get_by_type (const struct GNUNET_CONTAINER_MetaData
518 */ 521 */
519char * 522char *
520GNUNET_CONTAINER_meta_data_get_first_by_types (const struct 523GNUNET_CONTAINER_meta_data_get_first_by_types (const struct
521 GNUNET_CONTAINER_MetaData *md, 524 GNUNET_CONTAINER_MetaData *md,
522 ...) 525 ...)
523{ 526{
524 char *ret; 527 char *ret;
525 va_list args; 528 va_list args;
@@ -530,15 +533,15 @@ GNUNET_CONTAINER_meta_data_get_first_by_types (const struct
530 ret = NULL; 533 ret = NULL;
531 va_start (args, md); 534 va_start (args, md);
532 while (1) 535 while (1)
533 { 536 {
534 type = va_arg (args, enum EXTRACTOR_MetaType); 537 type = va_arg (args, enum EXTRACTOR_MetaType);
535 538
536 if (type == -1) 539 if (type == -1)
537 break; 540 break;
538 ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type); 541 ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type);
539 if (ret != NULL) 542 if (ret != NULL)
540 break; 543 break;
541 } 544 }
542 va_end (args); 545 va_end (args);
543 return ret; 546 return ret;
544} 547}
@@ -553,8 +556,9 @@ GNUNET_CONTAINER_meta_data_get_first_by_types (const struct
553 * @return number of bytes in thumbnail, 0 if not available 556 * @return number of bytes in thumbnail, 0 if not available
554 */ 557 */
555size_t 558size_t
556GNUNET_CONTAINER_meta_data_get_thumbnail (const struct GNUNET_CONTAINER_MetaData 559GNUNET_CONTAINER_meta_data_get_thumbnail (const struct
557 * md, unsigned char **thumb) 560 GNUNET_CONTAINER_MetaData * md,
561 unsigned char **thumb)
558{ 562{
559 struct MetaItem *pos; 563 struct MetaItem *pos;
560 struct MetaItem *match; 564 struct MetaItem *match;
@@ -564,19 +568,19 @@ GNUNET_CONTAINER_meta_data_get_thumbnail (const struct GNUNET_CONTAINER_MetaData
564 match = NULL; 568 match = NULL;
565 pos = md->items; 569 pos = md->items;
566 while (NULL != pos) 570 while (NULL != pos)
567 {
568 if ((NULL != pos->mime_type) &&
569 (0 == strncasecmp ("image/", pos->mime_type, strlen ("image/"))) &&
570 (pos->format == EXTRACTOR_METAFORMAT_BINARY))
571 { 571 {
572 if (match == NULL) 572 if ((NULL != pos->mime_type) &&
573 match = pos; 573 (0 == strncasecmp ("image/", pos->mime_type, strlen ("image/"))) &&
574 else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) && 574 (pos->format == EXTRACTOR_METAFORMAT_BINARY))
575 (pos->type == EXTRACTOR_METATYPE_THUMBNAIL)) 575 {
576 match = pos; 576 if (match == NULL)
577 match = pos;
578 else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) &&
579 (pos->type == EXTRACTOR_METATYPE_THUMBNAIL))
580 match = pos;
581 }
582 pos = pos->next;
577 } 583 }
578 pos = pos->next;
579 }
580 if ((match == NULL) || (match->data_size == 0)) 584 if ((match == NULL) || (match->data_size == 0))
581 return 0; 585 return 0;
582 *thumb = GNUNET_malloc (match->data_size); 586 *thumb = GNUNET_malloc (match->data_size);
@@ -593,7 +597,7 @@ GNUNET_CONTAINER_meta_data_get_thumbnail (const struct GNUNET_CONTAINER_MetaData
593 */ 597 */
594struct GNUNET_CONTAINER_MetaData * 598struct GNUNET_CONTAINER_MetaData *
595GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData 599GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData
596 *md) 600 *md)
597{ 601{
598 struct GNUNET_CONTAINER_MetaData *ret; 602 struct GNUNET_CONTAINER_MetaData *ret;
599 struct MetaItem *pos; 603 struct MetaItem *pos;
@@ -603,12 +607,12 @@ GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData
603 ret = GNUNET_CONTAINER_meta_data_create (); 607 ret = GNUNET_CONTAINER_meta_data_create ();
604 pos = md->items; 608 pos = md->items;
605 while (NULL != pos) 609 while (NULL != pos)
606 { 610 {
607 GNUNET_CONTAINER_meta_data_insert (ret, pos->plugin_name, pos->type, 611 GNUNET_CONTAINER_meta_data_insert (ret, pos->plugin_name, pos->type,
608 pos->format, pos->mime_type, pos->data, 612 pos->format, pos->mime_type,
609 pos->data_size); 613 pos->data, pos->data_size);
610 pos = pos->next; 614 pos = pos->next;
611 } 615 }
612 return ret; 616 return ret;
613} 617}
614 618
@@ -629,7 +633,7 @@ GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData
629 */ 633 */
630static int 634static int
631try_compression (const char *data, size_t oldSize, char **result, 635try_compression (const char *data, size_t oldSize, char **result,
632 size_t * newSize) 636 size_t * newSize)
633{ 637{
634 char *tmp; 638 char *tmp;
635 uLongf dlen; 639 uLongf dlen;
@@ -644,14 +648,14 @@ try_compression (const char *data, size_t oldSize, char **result,
644 tmp = GNUNET_malloc (dlen); 648 tmp = GNUNET_malloc (dlen);
645 if (Z_OK == 649 if (Z_OK ==
646 compress2 ((Bytef *) tmp, &dlen, (const Bytef *) data, oldSize, 9)) 650 compress2 ((Bytef *) tmp, &dlen, (const Bytef *) data, oldSize, 9))
647 {
648 if (dlen < oldSize)
649 { 651 {
650 *result = tmp; 652 if (dlen < oldSize)
651 *newSize = dlen; 653 {
652 return GNUNET_YES; 654 *result = tmp;
655 *newSize = dlen;
656 return GNUNET_YES;
657 }
653 } 658 }
654 }
655 GNUNET_free (tmp); 659 GNUNET_free (tmp);
656 return GNUNET_NO; 660 return GNUNET_NO;
657} 661}
@@ -752,10 +756,10 @@ struct MetaDataEntry
752 */ 756 */
753ssize_t 757ssize_t
754GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData 758GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
755 *md, char **target, size_t max, 759 *md, char **target, size_t max,
756 enum 760 enum
757 GNUNET_CONTAINER_MetaDataSerializationOptions 761 GNUNET_CONTAINER_MetaDataSerializationOptions
758 opt) 762 opt)
759{ 763{
760 struct GNUNET_CONTAINER_MetaData *vmd; 764 struct GNUNET_CONTAINER_MetaData *vmd;
761 struct MetaItem *pos; 765 struct MetaItem *pos;
@@ -777,79 +781,79 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
777 int comp; 781 int comp;
778 782
779 if (max < sizeof (struct MetaDataHeader)) 783 if (max < sizeof (struct MetaDataHeader))
780 return GNUNET_SYSERR; /* far too small */ 784 return GNUNET_SYSERR; /* far too small */
781 if (md == NULL) 785 if (md == NULL)
782 return 0; 786 return 0;
783 787
784 if (md->sbuf != NULL) 788 if (md->sbuf != NULL)
785 {
786 /* try to use serialization cache */
787 if (md->sbuf_size <= max)
788 { 789 {
789 if (NULL == *target) 790 /* try to use serialization cache */
790 *target = GNUNET_malloc (md->sbuf_size); 791 if (md->sbuf_size <= max)
791 memcpy (*target, md->sbuf, md->sbuf_size); 792 {
792 return md->sbuf_size; 793 if (NULL == *target)
794 *target = GNUNET_malloc (md->sbuf_size);
795 memcpy (*target, md->sbuf, md->sbuf_size);
796 return md->sbuf_size;
797 }
798 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
799 return GNUNET_SYSERR; /* can say that this will fail */
800 /* need to compute a partial serialization, sbuf useless ... */
793 } 801 }
794 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
795 return GNUNET_SYSERR; /* can say that this will fail */
796 /* need to compute a partial serialization, sbuf useless ... */
797 }
798 dst = NULL; 802 dst = NULL;
799 msize = 0; 803 msize = 0;
800 pos = md->items; 804 pos = md->items;
801 while (NULL != pos) 805 while (NULL != pos)
802 { 806 {
803 msize += sizeof (struct MetaDataEntry); 807 msize += sizeof (struct MetaDataEntry);
804 msize += pos->data_size; 808 msize += pos->data_size;
805 if (pos->plugin_name != NULL) 809 if (pos->plugin_name != NULL)
806 msize += strlen (pos->plugin_name) + 1; 810 msize += strlen (pos->plugin_name) + 1;
807 if (pos->mime_type != NULL) 811 if (pos->mime_type != NULL)
808 msize += strlen (pos->mime_type) + 1; 812 msize += strlen (pos->mime_type) + 1;
809 pos = pos->next; 813 pos = pos->next;
810 } 814 }
811 size = (size_t) msize; 815 size = (size_t) msize;
812 if (size != msize) 816 if (size != msize)
813 { 817 {
814 GNUNET_break (0); /* integer overflow */ 818 GNUNET_break (0); /* integer overflow */
815 return GNUNET_SYSERR; 819 return GNUNET_SYSERR;
816 } 820 }
817 if (size >= GNUNET_MAX_MALLOC_CHECKED) 821 if (size >= GNUNET_MAX_MALLOC_CHECKED)
818 { 822 {
819 /* too large to be processed */ 823 /* too large to be processed */
820 return GNUNET_SYSERR; 824 return GNUNET_SYSERR;
821 } 825 }
822 ent = GNUNET_malloc (size); 826 ent = GNUNET_malloc (size);
823 mdata = (char *) &ent[md->item_count]; 827 mdata = (char *) &ent[md->item_count];
824 off = size - (md->item_count * sizeof (struct MetaDataEntry)); 828 off = size - (md->item_count * sizeof (struct MetaDataEntry));
825 i = 0; 829 i = 0;
826 pos = md->items; 830 pos = md->items;
827 while (NULL != pos) 831 while (NULL != pos)
828 { 832 {
829 ent[i].type = htonl ((uint32_t) pos->type); 833 ent[i].type = htonl ((uint32_t) pos->type);
830 ent[i].format = htonl ((uint32_t) pos->format); 834 ent[i].format = htonl ((uint32_t) pos->format);
831 ent[i].data_size = htonl ((uint32_t) pos->data_size); 835 ent[i].data_size = htonl ((uint32_t) pos->data_size);
832 if (pos->plugin_name == NULL) 836 if (pos->plugin_name == NULL)
833 plen = 0; 837 plen = 0;
834 else 838 else
835 plen = strlen (pos->plugin_name) + 1; 839 plen = strlen (pos->plugin_name) + 1;
836 ent[i].plugin_name_len = htonl ((uint32_t) plen); 840 ent[i].plugin_name_len = htonl ((uint32_t) plen);
837 if (pos->mime_type == NULL) 841 if (pos->mime_type == NULL)
838 mlen = 0; 842 mlen = 0;
839 else 843 else
840 mlen = strlen (pos->mime_type) + 1; 844 mlen = strlen (pos->mime_type) + 1;
841 ent[i].mime_type_len = htonl ((uint32_t) mlen); 845 ent[i].mime_type_len = htonl ((uint32_t) mlen);
842 off -= pos->data_size; 846 off -= pos->data_size;
843 memcpy (&mdata[off], pos->data, pos->data_size); 847 memcpy (&mdata[off], pos->data, pos->data_size);
844 off -= plen; 848 off -= plen;
845 if (pos->plugin_name != NULL) 849 if (pos->plugin_name != NULL)
846 memcpy (&mdata[off], pos->plugin_name, plen); 850 memcpy (&mdata[off], pos->plugin_name, plen);
847 off -= mlen; 851 off -= mlen;
848 if (pos->mime_type != NULL) 852 if (pos->mime_type != NULL)
849 memcpy (&mdata[off], pos->mime_type, mlen); 853 memcpy (&mdata[off], pos->mime_type, mlen);
850 i++; 854 i++;
851 pos = pos->next; 855 pos = pos->next;
852 } 856 }
853 GNUNET_assert (off == 0); 857 GNUNET_assert (off == 0);
854 858
855 clen = 0; 859 clen = 0;
@@ -858,95 +862,95 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
858 i = 0; 862 i = 0;
859 pos = md->items; 863 pos = md->items;
860 while (pos != NULL) 864 while (pos != NULL)
861 {
862 comp = GNUNET_NO;
863 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS))
864 comp = try_compression ((const char *) &ent[i], left, &cdata, &clen);
865
866 if ((md->sbuf == NULL) && (i == 0))
867 {
868 /* fill 'sbuf'; this "modifies" md, but since this is only
869 * an internal cache we will cast away the 'const' instead
870 * of making the API look strange. */
871 vmd = (struct GNUNET_CONTAINER_MetaData *) md;
872 hdr = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
873 hdr->size = htonl (left);
874 hdr->entries = htonl (md->item_count);
875 if (GNUNET_YES == comp)
876 {
877 GNUNET_assert (clen < left);
878 hdr->version = htonl (2 | HEADER_COMPRESSED);
879 memcpy (&hdr[1], cdata, clen);
880 vmd->sbuf_size = clen + sizeof (struct MetaDataHeader);
881 }
882 else
883 {
884 hdr->version = htonl (2);
885 memcpy (&hdr[1], &ent[0], left);
886 vmd->sbuf_size = left + sizeof (struct MetaDataHeader);
887 }
888 vmd->sbuf = (char *) hdr;
889 }
890
891 if (((left + sizeof (struct MetaDataHeader)) <= max) ||
892 ((comp == GNUNET_YES) && (clen <= max)))
893 {
894 /* success, this now fits! */
895 if (GNUNET_YES == comp)
896 {
897 if (dst == NULL)
898 dst = GNUNET_malloc (clen + sizeof (struct MetaDataHeader));
899 hdr = (struct MetaDataHeader *) dst;
900 hdr->version = htonl (2 | HEADER_COMPRESSED);
901 hdr->size = htonl (left);
902 hdr->entries = htonl (md->item_count - i);
903 memcpy (&dst[sizeof (struct MetaDataHeader)], cdata, clen);
904 GNUNET_free (cdata);
905 GNUNET_free (ent);
906 rlen = clen + sizeof (struct MetaDataHeader);
907 }
908 else
909 {
910 if (dst == NULL)
911 dst = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
912 hdr = (struct MetaDataHeader *) dst;
913 hdr->version = htonl (2);
914 hdr->entries = htonl (md->item_count - i);
915 hdr->size = htonl (left);
916 memcpy (&dst[sizeof (struct MetaDataHeader)], &ent[i], left);
917 GNUNET_free (ent);
918 rlen = left + sizeof (struct MetaDataHeader);
919 }
920 if (NULL != *target)
921 {
922 memcpy (*target, dst, clen + sizeof (struct MetaDataHeader));
923 GNUNET_free (dst);
924 }
925 else
926 {
927 *target = dst;
928 }
929 return rlen;
930 }
931
932 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
933 { 865 {
934 /* does not fit! */ 866 comp = GNUNET_NO;
935 GNUNET_free (ent); 867 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS))
936 return GNUNET_SYSERR; 868 comp = try_compression ((const char *) &ent[i], left, &cdata, &clen);
869
870 if ((md->sbuf == NULL) && (i == 0))
871 {
872 /* fill 'sbuf'; this "modifies" md, but since this is only
873 * an internal cache we will cast away the 'const' instead
874 * of making the API look strange. */
875 vmd = (struct GNUNET_CONTAINER_MetaData *) md;
876 hdr = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
877 hdr->size = htonl (left);
878 hdr->entries = htonl (md->item_count);
879 if (GNUNET_YES == comp)
880 {
881 GNUNET_assert (clen < left);
882 hdr->version = htonl (2 | HEADER_COMPRESSED);
883 memcpy (&hdr[1], cdata, clen);
884 vmd->sbuf_size = clen + sizeof (struct MetaDataHeader);
885 }
886 else
887 {
888 hdr->version = htonl (2);
889 memcpy (&hdr[1], &ent[0], left);
890 vmd->sbuf_size = left + sizeof (struct MetaDataHeader);
891 }
892 vmd->sbuf = (char *) hdr;
893 }
894
895 if (((left + sizeof (struct MetaDataHeader)) <= max) ||
896 ((comp == GNUNET_YES) && (clen <= max)))
897 {
898 /* success, this now fits! */
899 if (GNUNET_YES == comp)
900 {
901 if (dst == NULL)
902 dst = GNUNET_malloc (clen + sizeof (struct MetaDataHeader));
903 hdr = (struct MetaDataHeader *) dst;
904 hdr->version = htonl (2 | HEADER_COMPRESSED);
905 hdr->size = htonl (left);
906 hdr->entries = htonl (md->item_count - i);
907 memcpy (&dst[sizeof (struct MetaDataHeader)], cdata, clen);
908 GNUNET_free (cdata);
909 GNUNET_free (ent);
910 rlen = clen + sizeof (struct MetaDataHeader);
911 }
912 else
913 {
914 if (dst == NULL)
915 dst = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
916 hdr = (struct MetaDataHeader *) dst;
917 hdr->version = htonl (2);
918 hdr->entries = htonl (md->item_count - i);
919 hdr->size = htonl (left);
920 memcpy (&dst[sizeof (struct MetaDataHeader)], &ent[i], left);
921 GNUNET_free (ent);
922 rlen = left + sizeof (struct MetaDataHeader);
923 }
924 if (NULL != *target)
925 {
926 memcpy (*target, dst, clen + sizeof (struct MetaDataHeader));
927 GNUNET_free (dst);
928 }
929 else
930 {
931 *target = dst;
932 }
933 return rlen;
934 }
935
936 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
937 {
938 /* does not fit! */
939 GNUNET_free (ent);
940 return GNUNET_SYSERR;
941 }
942
943 /* next iteration: ignore the corresponding meta data at the
944 * end and try again without it */
945 left -= sizeof (struct MetaDataEntry);
946 left -= pos->data_size;
947 if (pos->plugin_name != NULL)
948 left -= strlen (pos->plugin_name) + 1;
949 if (pos->mime_type != NULL)
950 left -= strlen (pos->mime_type) + 1;
951 pos = pos->next;
952 i++;
937 } 953 }
938
939 /* next iteration: ignore the corresponding meta data at the
940 * end and try again without it */
941 left -= sizeof (struct MetaDataEntry);
942 left -= pos->data_size;
943 if (pos->plugin_name != NULL)
944 left -= strlen (pos->plugin_name) + 1;
945 if (pos->mime_type != NULL)
946 left -= strlen (pos->mime_type) + 1;
947 pos = pos->next;
948 i++;
949 }
950 GNUNET_free (ent); 954 GNUNET_free (ent);
951 955
952 /* nothing fit, only write header! */ 956 /* nothing fit, only write header! */
@@ -968,7 +972,7 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
968 */ 972 */
969ssize_t 973ssize_t
970GNUNET_CONTAINER_meta_data_get_serialized_size (const struct 974GNUNET_CONTAINER_meta_data_get_serialized_size (const struct
971 GNUNET_CONTAINER_MetaData *md) 975 GNUNET_CONTAINER_MetaData *md)
972{ 976{
973 ssize_t ret; 977 ssize_t ret;
974 char *ptr; 978 char *ptr;
@@ -977,8 +981,8 @@ GNUNET_CONTAINER_meta_data_get_serialized_size (const struct
977 return md->sbuf_size; 981 return md->sbuf_size;
978 ptr = NULL; 982 ptr = NULL;
979 ret = 983 ret =
980 GNUNET_CONTAINER_meta_data_serialize (md, &ptr, GNUNET_MAX_MALLOC_CHECKED, 984 GNUNET_CONTAINER_meta_data_serialize (md, &ptr, GNUNET_MAX_MALLOC_CHECKED,
981 GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL); 985 GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL);
982 if (ret != -1) 986 if (ret != -1)
983 GNUNET_free (ptr); 987 GNUNET_free (ptr);
984 return ret; 988 return ret;
@@ -1005,14 +1009,14 @@ decompress (const char *input, size_t inputSize, size_t outputSize)
1005 output = GNUNET_malloc (olen); 1009 output = GNUNET_malloc (olen);
1006 if (Z_OK == 1010 if (Z_OK ==
1007 uncompress ((Bytef *) output, &olen, (const Bytef *) input, inputSize)) 1011 uncompress ((Bytef *) output, &olen, (const Bytef *) input, inputSize))
1008 { 1012 {
1009 return output; 1013 return output;
1010 } 1014 }
1011 else 1015 else
1012 { 1016 {
1013 GNUNET_free (output); 1017 GNUNET_free (output);
1014 return NULL; 1018 return NULL;
1015 } 1019 }
1016} 1020}
1017 1021
1018 1022
@@ -1054,121 +1058,121 @@ GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size)
1054 compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0; 1058 compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0;
1055 1059
1056 if (version == 1) 1060 if (version == 1)
1057 return NULL; /* null pointer */ 1061 return NULL; /* null pointer */
1058 if (version != 2) 1062 if (version != 2)
1059 { 1063 {
1060 GNUNET_break_op (0); /* unsupported version */ 1064 GNUNET_break_op (0); /* unsupported version */
1061 return NULL; 1065 return NULL;
1062 } 1066 }
1063 1067
1064 ic = ntohl (hdr.entries); 1068 ic = ntohl (hdr.entries);
1065 dataSize = ntohl (hdr.size); 1069 dataSize = ntohl (hdr.size);
1066 if ((sizeof (struct MetaDataEntry) * ic) > dataSize) 1070 if ((sizeof (struct MetaDataEntry) * ic) > dataSize)
1067 {
1068 GNUNET_break_op (0);
1069 return NULL;
1070 }
1071
1072 if (compressed)
1073 {
1074 if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
1075 { 1071 {
1076 /* make sure we don't blow our memory limit because of a mal-formed
1077 * message... */
1078 GNUNET_break_op (0); 1072 GNUNET_break_op (0);
1079 return NULL; 1073 return NULL;
1080 } 1074 }
1081 data = 1075
1082 decompress ((const char *) &input[sizeof (struct MetaDataHeader)], 1076 if (compressed)
1083 size - sizeof (struct MetaDataHeader), dataSize);
1084 if (data == NULL)
1085 { 1077 {
1086 GNUNET_break_op (0); 1078 if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
1087 return NULL; 1079 {
1080 /* make sure we don't blow our memory limit because of a mal-formed
1081 * message... */
1082 GNUNET_break_op (0);
1083 return NULL;
1084 }
1085 data =
1086 decompress ((const char *) &input[sizeof (struct MetaDataHeader)],
1087 size - sizeof (struct MetaDataHeader), dataSize);
1088 if (data == NULL)
1089 {
1090 GNUNET_break_op (0);
1091 return NULL;
1092 }
1093 cdata = data;
1088 } 1094 }
1089 cdata = data;
1090 }
1091 else 1095 else
1092 {
1093 data = NULL;
1094 cdata = (const char *) &input[sizeof (struct MetaDataHeader)];
1095 if (dataSize != size - sizeof (struct MetaDataHeader))
1096 { 1096 {
1097 GNUNET_break_op (0); 1097 data = NULL;
1098 return NULL; 1098 cdata = (const char *) &input[sizeof (struct MetaDataHeader)];
1099 if (dataSize != size - sizeof (struct MetaDataHeader))
1100 {
1101 GNUNET_break_op (0);
1102 return NULL;
1103 }
1099 } 1104 }
1100 }
1101 1105
1102 md = GNUNET_CONTAINER_meta_data_create (); 1106 md = GNUNET_CONTAINER_meta_data_create ();
1103 left = dataSize - ic * sizeof (struct MetaDataEntry); 1107 left = dataSize - ic * sizeof (struct MetaDataEntry);
1104 mdata = &cdata[ic * sizeof (struct MetaDataEntry)]; 1108 mdata = &cdata[ic * sizeof (struct MetaDataEntry)];
1105 for (i = 0; i < ic; i++) 1109 for (i = 0; i < ic; i++)
1106 {
1107 memcpy (&ent, &cdata[i * sizeof (struct MetaDataEntry)],
1108 sizeof (struct MetaDataEntry));
1109 format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format);
1110 if ((format != EXTRACTOR_METAFORMAT_UTF8) &&
1111 (format != EXTRACTOR_METAFORMAT_C_STRING) &&
1112 (format != EXTRACTOR_METAFORMAT_BINARY))
1113 {
1114 GNUNET_break_op (0);
1115 break;
1116 }
1117 dlen = ntohl (ent.data_size);
1118 plen = ntohl (ent.plugin_name_len);
1119 mlen = ntohl (ent.mime_type_len);
1120 if (dlen > left)
1121 {
1122 GNUNET_break_op (0);
1123 break;
1124 }
1125 left -= dlen;
1126 meta_data = &mdata[left];
1127 if ((format == EXTRACTOR_METAFORMAT_UTF8) ||
1128 (format == EXTRACTOR_METAFORMAT_C_STRING))
1129 {
1130 if ((dlen == 0) || (mdata[left + dlen - 1] != '\0'))
1131 {
1132 GNUNET_break_op (0);
1133 break;
1134 }
1135 }
1136 if (plen > left)
1137 {
1138 GNUNET_break_op (0);
1139 break;
1140 }
1141 left -= plen;
1142 if ((plen > 0) && (mdata[left + plen - 1] != '\0'))
1143 { 1110 {
1144 GNUNET_break_op (0); 1111 memcpy (&ent, &cdata[i * sizeof (struct MetaDataEntry)],
1145 break; 1112 sizeof (struct MetaDataEntry));
1146 } 1113 format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format);
1147 if (plen == 0) 1114 if ((format != EXTRACTOR_METAFORMAT_UTF8) &&
1148 plugin_name = NULL; 1115 (format != EXTRACTOR_METAFORMAT_C_STRING) &&
1149 else 1116 (format != EXTRACTOR_METAFORMAT_BINARY))
1150 plugin_name = &mdata[left]; 1117 {
1151 1118 GNUNET_break_op (0);
1152 if (mlen > left) 1119 break;
1153 { 1120 }
1154 GNUNET_break_op (0); 1121 dlen = ntohl (ent.data_size);
1155 break; 1122 plen = ntohl (ent.plugin_name_len);
1156 } 1123 mlen = ntohl (ent.mime_type_len);
1157 left -= mlen; 1124 if (dlen > left)
1158 if ((mlen > 0) && (mdata[left + mlen - 1] != '\0')) 1125 {
1159 { 1126 GNUNET_break_op (0);
1160 GNUNET_break_op (0); 1127 break;
1161 break; 1128 }
1129 left -= dlen;
1130 meta_data = &mdata[left];
1131 if ((format == EXTRACTOR_METAFORMAT_UTF8) ||
1132 (format == EXTRACTOR_METAFORMAT_C_STRING))
1133 {
1134 if ((dlen == 0) || (mdata[left + dlen - 1] != '\0'))
1135 {
1136 GNUNET_break_op (0);
1137 break;
1138 }
1139 }
1140 if (plen > left)
1141 {
1142 GNUNET_break_op (0);
1143 break;
1144 }
1145 left -= plen;
1146 if ((plen > 0) && (mdata[left + plen - 1] != '\0'))
1147 {
1148 GNUNET_break_op (0);
1149 break;
1150 }
1151 if (plen == 0)
1152 plugin_name = NULL;
1153 else
1154 plugin_name = &mdata[left];
1155
1156 if (mlen > left)
1157 {
1158 GNUNET_break_op (0);
1159 break;
1160 }
1161 left -= mlen;
1162 if ((mlen > 0) && (mdata[left + mlen - 1] != '\0'))
1163 {
1164 GNUNET_break_op (0);
1165 break;
1166 }
1167 if (mlen == 0)
1168 mime_type = NULL;
1169 else
1170 mime_type = &mdata[left];
1171 GNUNET_CONTAINER_meta_data_insert (md, plugin_name,
1172 (enum EXTRACTOR_MetaType)
1173 ntohl (ent.type), format, mime_type,
1174 meta_data, dlen);
1162 } 1175 }
1163 if (mlen == 0)
1164 mime_type = NULL;
1165 else
1166 mime_type = &mdata[left];
1167 GNUNET_CONTAINER_meta_data_insert (md, plugin_name,
1168 (enum EXTRACTOR_MetaType)
1169 ntohl (ent.type), format, mime_type,
1170 meta_data, dlen);
1171 }
1172 GNUNET_free_non_null (data); 1176 GNUNET_free_non_null (data);
1173 return md; 1177 return md;
1174} 1178}