GNUnet  0.11.x
container_meta_data.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
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/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #if HAVE_EXTRACTOR_H
30 #include <extractor.h>
31 #endif
32 #include <zlib.h>
33 
34 #define LOG(kind, ...) GNUNET_log_from (kind, "util-container-meta-data", \
35  __VA_ARGS__)
36 
37 
53 int
55  size_t old_size,
56  char **result,
57  size_t *new_size)
58 {
59  char *tmp;
60  uLongf dlen;
61 
62  *result = NULL;
63  *new_size = 0;
64 #ifdef compressBound
65  dlen = compressBound (old_size);
66 #else
67  dlen = old_size + (old_size / 100) + 20;
68  /* documentation says 100.1% oldSize + 12 bytes, but we
69  * should be able to overshoot by more to be safe */
70 #endif
71  tmp = GNUNET_malloc (dlen);
72  if (Z_OK ==
73  compress2 ((Bytef *) tmp,
74  &dlen,
75  (const Bytef *) data,
76  old_size, 9))
77  {
78  if (dlen < old_size)
79  {
80  *result = tmp;
81  *new_size = dlen;
82  return GNUNET_YES;
83  }
84  }
85  GNUNET_free (tmp);
86  return GNUNET_NO;
87 }
88 
89 
100 char *
101 GNUNET_decompress (const char *input,
102  size_t input_size,
103  size_t output_size)
104 {
105  char *output;
106  uLongf olen;
107 
108  olen = output_size;
109  output = GNUNET_malloc (olen);
110  if (Z_OK ==
111  uncompress ((Bytef *) output,
112  &olen,
113  (const Bytef *) input,
114  input_size))
115  return output;
116  GNUNET_free (output);
117  return NULL;
118 }
119 
120 
124 struct MetaItem
125 {
129  struct MetaItem *next;
130 
134  struct MetaItem *prev;
135 
139  char *plugin_name;
140 
144  char *mime_type;
145 
149  char *data;
150 
154  size_t data_size;
155 
160 
165 };
166 
171 {
176 
181 
186  char *sbuf;
187 
191  size_t sbuf_size;
192 
196  unsigned int item_count;
197 };
198 
199 
207 {
208  return GNUNET_new (struct GNUNET_CONTAINER_MetaData);
209 }
210 
211 
217 static void
219 {
220  GNUNET_free (mi->plugin_name);
221  GNUNET_free (mi->mime_type);
222  GNUNET_free (mi->data);
223  GNUNET_free (mi);
224 }
225 
226 
233 static void
235 {
236  if (NULL == md->sbuf)
237  return;
238  GNUNET_free (md->sbuf);
239  md->sbuf = NULL;
240  md->sbuf_size = 0;
241 }
242 
243 
249 void
251 {
252  struct MetaItem *pos;
253 
254  if (NULL == md)
255  return;
256  while (NULL != (pos = md->items_head))
257  {
259  meta_item_free (pos);
260  }
261  GNUNET_free (md->sbuf);
262  GNUNET_free (md);
263 }
264 
265 
271 void
273 {
274  struct MetaItem *mi;
275 
276  if (NULL == md)
277  return;
278  while (NULL != (mi = md->items_head))
279  {
281  meta_item_free (mi);
282  }
283  GNUNET_free (md->sbuf);
284  memset (md, 0, sizeof(struct GNUNET_CONTAINER_MetaData));
285 }
286 
287 
298 int
300  *md1,
301  const struct GNUNET_CONTAINER_MetaData
302  *md2)
303 {
304  struct MetaItem *i;
305  struct MetaItem *j;
306  int found;
307 
308  if (md1 == md2)
309  return GNUNET_YES;
310  if (md1->item_count != md2->item_count)
311  return GNUNET_NO;
312  for (i = md1->items_head; NULL != i; i = i->next)
313  {
314  found = GNUNET_NO;
315  for (j = md2->items_head; NULL != j; j = j->next)
316  {
317  if ((i->type == j->type) && (i->format == j->format) &&
318  (i->data_size == j->data_size) &&
319  (0 == memcmp (i->data, j->data, i->data_size)))
320  {
321  found = GNUNET_YES;
322  break;
323  }
324  if (j->data_size < i->data_size)
325  break; /* elements are sorted by (decreasing) size... */
326  }
327  if (GNUNET_NO == found)
328  return GNUNET_NO;
329  }
330  return GNUNET_YES;
331 }
332 
333 
352 int
354  const char *plugin_name,
357  const char *data_mime_type, const char *data,
358  size_t data_size)
359 {
360  struct MetaItem *pos;
361  struct MetaItem *mi;
362  char *p;
363 
364  if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
365  (EXTRACTOR_METAFORMAT_C_STRING == format))
366  GNUNET_break ('\0' == data[data_size - 1]);
367 
368  for (pos = md->items_head; NULL != pos; pos = pos->next)
369  {
370  if (pos->data_size < data_size)
371  break; /* elements are sorted by size in the list */
372  if ((pos->type == type) && (pos->data_size == data_size) &&
373  (0 == memcmp (pos->data, data, data_size)))
374  {
375  if ((NULL == pos->mime_type) && (NULL != data_mime_type))
376  {
377  pos->mime_type = GNUNET_strdup (data_mime_type);
378  invalidate_sbuf (md);
379  }
380  if ((EXTRACTOR_METAFORMAT_C_STRING == pos->format) &&
381  (EXTRACTOR_METAFORMAT_UTF8 == format))
382  {
384  invalidate_sbuf (md);
385  }
386  return GNUNET_SYSERR;
387  }
388  }
389  md->item_count++;
390  mi = GNUNET_new (struct MetaItem);
391  mi->type = type;
392  mi->format = format;
393  mi->data_size = data_size;
394  if (NULL == pos)
396  md->items_tail,
397  mi);
398  else
400  md->items_tail,
401  pos->prev,
402  mi);
403  mi->mime_type =
404  (NULL == data_mime_type) ? NULL : GNUNET_strdup (data_mime_type);
405  mi->plugin_name = (NULL == plugin_name) ? NULL : GNUNET_strdup (plugin_name);
406  mi->data = GNUNET_malloc (data_size);
407  GNUNET_memcpy (mi->data, data, data_size);
408  /* change all dir separators to POSIX style ('/') */
409  if ((EXTRACTOR_METATYPE_FILENAME == type) ||
411  {
412  p = mi->data;
413  while (('\0' != *p) && (p < mi->data + data_size))
414  {
415  if ('\\' == *p)
416  *p = '/';
417  p++;
418  }
419  }
420  invalidate_sbuf (md);
421  return GNUNET_OK;
422 }
423 
424 
441 static int
442 merge_helper (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type,
443  enum EXTRACTOR_MetaFormat format, const char *data_mime_type,
444  const char *data, size_t data_size)
445 {
446  struct GNUNET_CONTAINER_MetaData *md = cls;
447 
448  (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format,
449  data_mime_type, data, data_size);
450  return 0;
451 }
452 
453 
461 void
463  const struct GNUNET_CONTAINER_MetaData *in)
464 {
466 }
467 
468 
479 int
482  const char *data, size_t data_size)
483 {
484  struct MetaItem *pos;
485 
486  for (pos = md->items_head; NULL != pos; pos = pos->next)
487  {
488  if (pos->data_size < data_size)
489  break; /* items are sorted by (decreasing) size */
490  if ((pos->type == type) &&
491  ((NULL == data) ||
492  ((pos->data_size == data_size) &&
493  (0 == memcmp (pos->data, data, data_size)))))
494  {
496  meta_item_free (pos);
497  md->item_count--;
498  invalidate_sbuf (md);
499  return GNUNET_OK;
500  }
501  }
502  return GNUNET_SYSERR;
503 }
504 
505 
512 void
515 {
516  const char *dat;
517  struct GNUNET_TIME_Absolute t;
518 
522  NULL, 0);
524  GNUNET_CONTAINER_meta_data_insert (md, "<gnunet>",
526  EXTRACTOR_METAFORMAT_UTF8, "text/plain",
527  dat, strlen (dat) + 1);
528 }
529 
530 
539 int
542  void *iter_cls)
543 {
544  struct MetaItem *pos;
545 
546  if (NULL == md)
547  return 0;
548  if (NULL == iter)
549  return md->item_count;
550  for (pos = md->items_head; NULL != pos; pos = pos->next)
551  if (0 !=
552  iter (iter_cls, pos->plugin_name, pos->type, pos->format,
553  pos->mime_type, pos->data, pos->data_size))
554  return md->item_count;
555  return md->item_count;
556 }
557 
558 
569 char *
573 {
574  struct MetaItem *pos;
575 
576  if (NULL == md)
577  return NULL;
578  for (pos = md->items_head; NULL != pos; pos = pos->next)
579  if ((type == pos->type) &&
580  ((pos->format == EXTRACTOR_METAFORMAT_UTF8) ||
582  return GNUNET_strdup (pos->data);
583  return NULL;
584 }
585 
586 
598 char *
601  ...)
602 {
603  char *ret;
604  va_list args;
605  int type;
606 
607  if (NULL == md)
608  return NULL;
609  ret = NULL;
610  va_start (args, md);
611  while (1)
612  {
613  type = va_arg (args, int);
614  if (-1 == type)
615  break;
616  if (NULL != (ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type)))
617  break;
618  }
619  va_end (args);
620  return ret;
621 }
622 
623 
632 size_t
634  *md, unsigned char **thumb)
635 {
636  struct MetaItem *pos;
637  struct MetaItem *match;
638 
639  if (NULL == md)
640  return 0;
641  match = NULL;
642  for (pos = md->items_head; NULL != pos; pos = pos->next)
643  {
644  if ((NULL != pos->mime_type) &&
645  (0 == strncasecmp ("image/", pos->mime_type, strlen ("image/"))) &&
647  {
648  if (NULL == match)
649  match = pos;
650  else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) &&
652  match = pos;
653  }
654  }
655  if ((NULL == match) || (0 == match->data_size))
656  return 0;
657  *thumb = GNUNET_malloc (match->data_size);
658  GNUNET_memcpy (*thumb, match->data, match->data_size);
659  return match->data_size;
660 }
661 
662 
671  *md)
672 {
674  struct MetaItem *pos;
675 
676  if (NULL == md)
677  return NULL;
679  for (pos = md->items_tail; NULL != pos; pos = pos->prev)
681  pos->format, pos->mime_type, pos->data,
682  pos->data_size);
683  return ret;
684 }
685 
686 
690 #define HEADER_COMPRESSED 0x80000000
691 
692 
696 #define HEADER_VERSION_MASK 0x7FFFFFFF
697 
698 
703 {
713  uint32_t version;
714 
718  uint32_t entries;
719 
723  uint32_t size;
724 
730 };
731 
732 
737 {
741  uint32_t type;
742 
746  uint32_t format;
747 
751  uint32_t data_size;
752 
756  uint32_t plugin_name_len;
757 
761  uint32_t mime_type_len;
762 };
763 
764 
779 ssize_t
781  *md, char **target, size_t max,
782  enum
784  opt)
785 {
786  struct GNUNET_CONTAINER_MetaData *vmd;
787  struct MetaItem *pos;
788  struct MetaDataHeader ihdr;
789  struct MetaDataHeader *hdr;
790  struct MetaDataEntry *ent;
791  char *dst;
792  unsigned int i;
793  uint64_t msize;
794  size_t off;
795  char *mdata;
796  char *cdata;
797  size_t mlen;
798  size_t plen;
799  size_t size;
800  size_t left;
801  size_t clen;
802  size_t rlen;
803  int comp;
804 
805  if (max < sizeof(struct MetaDataHeader))
806  return GNUNET_SYSERR; /* far too small */
807  if (NULL == md)
808  return 0;
809 
810  if (NULL != md->sbuf)
811  {
812  /* try to use serialization cache */
813  if (md->sbuf_size <= max)
814  {
815  if (NULL == *target)
816  *target = GNUNET_malloc (md->sbuf_size);
817  GNUNET_memcpy (*target, md->sbuf, md->sbuf_size);
818  return md->sbuf_size;
819  }
821  return GNUNET_SYSERR; /* can say that this will fail */
822  /* need to compute a partial serialization, sbuf useless ... */
823  }
824  dst = NULL;
825  msize = 0;
826  for (pos = md->items_tail; NULL != pos; pos = pos->prev)
827  {
828  msize += sizeof(struct MetaDataEntry);
829  msize += pos->data_size;
830  if (NULL != pos->plugin_name)
831  msize += strlen (pos->plugin_name) + 1;
832  if (NULL != pos->mime_type)
833  msize += strlen (pos->mime_type) + 1;
834  }
835  size = (size_t) msize;
836  if (size != msize)
837  {
838  GNUNET_break (0); /* integer overflow */
839  return GNUNET_SYSERR;
840  }
841  if (size >= GNUNET_MAX_MALLOC_CHECKED)
842  {
843  /* too large to be processed */
844  return GNUNET_SYSERR;
845  }
846  ent = GNUNET_malloc (size);
847  mdata = (char *) &ent[md->item_count];
848  off = size - (md->item_count * sizeof(struct MetaDataEntry));
849  i = 0;
850  for (pos = md->items_head; NULL != pos; pos = pos->next)
851  {
852  ent[i].type = htonl ((uint32_t) pos->type);
853  ent[i].format = htonl ((uint32_t) pos->format);
854  ent[i].data_size = htonl ((uint32_t) pos->data_size);
855  if (NULL == pos->plugin_name)
856  plen = 0;
857  else
858  plen = strlen (pos->plugin_name) + 1;
859  ent[i].plugin_name_len = htonl ((uint32_t) plen);
860  if (NULL == pos->mime_type)
861  mlen = 0;
862  else
863  mlen = strlen (pos->mime_type) + 1;
864  ent[i].mime_type_len = htonl ((uint32_t) mlen);
865  off -= pos->data_size;
866  if ((EXTRACTOR_METAFORMAT_UTF8 == pos->format) ||
868  GNUNET_break ('\0' == pos->data[pos->data_size - 1]);
869  GNUNET_memcpy (&mdata[off], pos->data, pos->data_size);
870  off -= plen;
871  if (NULL != pos->plugin_name)
872  GNUNET_memcpy (&mdata[off], pos->plugin_name, plen);
873  off -= mlen;
874  if (NULL != pos->mime_type)
875  GNUNET_memcpy (&mdata[off], pos->mime_type, mlen);
876  i++;
877  }
878  GNUNET_assert (0 == off);
879 
880  clen = 0;
881  cdata = NULL;
882  left = size;
883  i = 0;
884  for (pos = md->items_head; NULL != pos; pos = pos->next)
885  {
886  comp = GNUNET_NO;
888  comp = GNUNET_try_compression ((const char *) &ent[i],
889  left,
890  &cdata,
891  &clen);
892 
893  if ((NULL == md->sbuf) && (0 == i))
894  {
895  /* fill 'sbuf'; this "modifies" md, but since this is only
896  * an internal cache we will cast away the 'const' instead
897  * of making the API look strange. */
898  vmd = (struct GNUNET_CONTAINER_MetaData *) md;
899  hdr = GNUNET_malloc (left + sizeof(struct MetaDataHeader));
900  hdr->size = htonl (left);
901  hdr->entries = htonl (md->item_count);
902  if (GNUNET_YES == comp)
903  {
904  GNUNET_assert (clen < left);
905  hdr->version = htonl (2 | HEADER_COMPRESSED);
906  GNUNET_memcpy (&hdr[1], cdata, clen);
907  vmd->sbuf_size = clen + sizeof(struct MetaDataHeader);
908  }
909  else
910  {
911  hdr->version = htonl (2);
912  GNUNET_memcpy (&hdr[1], &ent[0], left);
913  vmd->sbuf_size = left + sizeof(struct MetaDataHeader);
914  }
915  vmd->sbuf = (char *) hdr;
916  }
917 
918  if (((left + sizeof(struct MetaDataHeader)) <= max) ||
919  ((GNUNET_YES == comp) && (clen <= max)))
920  {
921  /* success, this now fits! */
922  if (GNUNET_YES == comp)
923  {
924  if (NULL == dst)
925  dst = GNUNET_malloc (clen + sizeof(struct MetaDataHeader));
926  hdr = (struct MetaDataHeader *) dst;
927  hdr->version = htonl (2 | HEADER_COMPRESSED);
928  hdr->size = htonl (left);
929  hdr->entries = htonl (md->item_count - i);
930  GNUNET_memcpy (&dst[sizeof(struct MetaDataHeader)], cdata, clen);
931  GNUNET_free (cdata);
932  cdata = NULL;
933  GNUNET_free (ent);
934  rlen = clen + sizeof(struct MetaDataHeader);
935  }
936  else
937  {
938  if (NULL == dst)
939  dst = GNUNET_malloc (left + sizeof(struct MetaDataHeader));
940  hdr = (struct MetaDataHeader *) dst;
941  hdr->version = htonl (2);
942  hdr->entries = htonl (md->item_count - i);
943  hdr->size = htonl (left);
944  GNUNET_memcpy (&dst[sizeof(struct MetaDataHeader)], &ent[i], left);
945  GNUNET_free (ent);
946  rlen = left + sizeof(struct MetaDataHeader);
947  }
948  if (NULL != *target)
949  {
950  if (GNUNET_YES == comp)
951  GNUNET_memcpy (*target, dst, clen + sizeof(struct MetaDataHeader));
952  else
953  GNUNET_memcpy (*target, dst, left + sizeof(struct MetaDataHeader));
954  GNUNET_free (dst);
955  }
956  else
957  {
958  *target = dst;
959  }
960  return rlen;
961  }
962 
964  {
965  /* does not fit! */
966  GNUNET_free (ent);
967  if (NULL != cdata)
968  GNUNET_free (cdata);
969  cdata = NULL;
970  return GNUNET_SYSERR;
971  }
972 
973  /* next iteration: ignore the corresponding meta data at the
974  * end and try again without it */
975  left -= sizeof(struct MetaDataEntry);
976  left -= pos->data_size;
977  if (NULL != pos->plugin_name)
978  left -= strlen (pos->plugin_name) + 1;
979  if (NULL != pos->mime_type)
980  left -= strlen (pos->mime_type) + 1;
981 
982  if (NULL != cdata)
983  GNUNET_free (cdata);
984  cdata = NULL;
985  i++;
986  }
987  GNUNET_free (ent);
988 
989  /* nothing fit, only write header! */
990  ihdr.version = htonl (2);
991  ihdr.entries = htonl (0);
992  ihdr.size = htonl (0);
993  if (NULL == *target)
994  *target = (char *) GNUNET_new (struct MetaDataHeader);
995  GNUNET_memcpy (*target, &ihdr, sizeof(struct MetaDataHeader));
996  return sizeof(struct MetaDataHeader);
997 }
998 
999 
1006 ssize_t
1009 {
1010  ssize_t ret;
1011  char *ptr;
1012 
1013  if (NULL != md->sbuf)
1014  return md->sbuf_size;
1015  ptr = NULL;
1016  ret =
1019  if (-1 != ret)
1020  GNUNET_free (ptr);
1021  return ret;
1022 }
1023 
1024 
1035 {
1036  struct GNUNET_CONTAINER_MetaData *md;
1037  struct MetaDataHeader hdr;
1038  struct MetaDataEntry ent;
1039  uint32_t ic;
1040  uint32_t i;
1041  char *data;
1042  const char *cdata;
1043  uint32_t version;
1044  uint32_t dataSize;
1045  int compressed;
1046  size_t left;
1047  uint32_t mlen;
1048  uint32_t plen;
1049  uint32_t dlen;
1050  const char *mdata;
1051  const char *meta_data;
1052  const char *plugin_name;
1053  const char *mime_type;
1055 
1056  if (size < sizeof(struct MetaDataHeader))
1057  return NULL;
1058  GNUNET_memcpy (&hdr, input, sizeof(struct MetaDataHeader));
1059  version = ntohl (hdr.version) & HEADER_VERSION_MASK;
1060  compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0;
1061 
1062  if (1 == version)
1063  return NULL; /* null pointer */
1064  if (2 != version)
1065  {
1066  GNUNET_break_op (0); /* unsupported version */
1067  return NULL;
1068  }
1069 
1070  ic = ntohl (hdr.entries);
1071  dataSize = ntohl (hdr.size);
1072  if (((sizeof(struct MetaDataEntry) * ic) > dataSize) ||
1073  ((0 != ic) &&
1074  (dataSize / ic < sizeof(struct MetaDataEntry))))
1075  {
1076  GNUNET_break_op (0);
1077  return NULL;
1078  }
1079 
1080  if (compressed)
1081  {
1082  if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
1083  {
1084  /* make sure we don't blow our memory limit because of a mal-formed
1085  * message... */
1086  GNUNET_break_op (0);
1087  return NULL;
1088  }
1089  data =
1090  GNUNET_decompress ((const char *) &input[sizeof(struct MetaDataHeader)],
1091  size - sizeof(struct MetaDataHeader),
1092  dataSize);
1093  if (NULL == data)
1094  {
1095  GNUNET_break_op (0);
1096  return NULL;
1097  }
1098  cdata = data;
1099  }
1100  else
1101  {
1102  data = NULL;
1103  cdata = (const char *) &input[sizeof(struct MetaDataHeader)];
1104  if (dataSize != size - sizeof(struct MetaDataHeader))
1105  {
1106  GNUNET_break_op (0);
1107  return NULL;
1108  }
1109  }
1110 
1112  left = dataSize - ic * sizeof(struct MetaDataEntry);
1113  mdata = &cdata[ic * sizeof(struct MetaDataEntry)];
1114  for (i = 0; i < ic; i++)
1115  {
1116  GNUNET_memcpy (&ent, &cdata[i * sizeof(struct MetaDataEntry)],
1117  sizeof(struct MetaDataEntry));
1118  format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format);
1119  if ((EXTRACTOR_METAFORMAT_UTF8 != format) &&
1121  (EXTRACTOR_METAFORMAT_BINARY != format))
1122  {
1123  GNUNET_break_op (0);
1124  break;
1125  }
1126  dlen = ntohl (ent.data_size);
1127  plen = ntohl (ent.plugin_name_len);
1128  mlen = ntohl (ent.mime_type_len);
1129  if (dlen > left)
1130  {
1131  GNUNET_break_op (0);
1132  break;
1133  }
1134  left -= dlen;
1135  meta_data = &mdata[left];
1136  if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
1137  (EXTRACTOR_METAFORMAT_C_STRING == format))
1138  {
1139  if (0 == dlen)
1140  {
1141  GNUNET_break_op (0);
1142  break;
1143  }
1144  if ('\0' != meta_data[dlen - 1])
1145  {
1146  GNUNET_break_op (0);
1147  break;
1148  }
1149  }
1150  if (plen > left)
1151  {
1152  GNUNET_break_op (0);
1153  break;
1154  }
1155  left -= plen;
1156  if ((plen > 0) && ('\0' != mdata[left + plen - 1]))
1157  {
1158  GNUNET_break_op (0);
1159  break;
1160  }
1161  if (0 == plen)
1162  plugin_name = NULL;
1163  else
1164  plugin_name = &mdata[left];
1165 
1166  if (mlen > left)
1167  {
1168  GNUNET_break_op (0);
1169  break;
1170  }
1171  left -= mlen;
1172  if ((mlen > 0) && ('\0' != mdata[left + mlen - 1]))
1173  {
1174  GNUNET_break_op (0);
1175  break;
1176  }
1177  if (0 == mlen)
1178  mime_type = NULL;
1179  else
1180  mime_type = &mdata[left];
1181  GNUNET_CONTAINER_meta_data_insert (md, plugin_name,
1182  (enum EXTRACTOR_MetaType)
1183  ntohl (ent.type), format, mime_type,
1184  meta_data, dlen);
1185  }
1186  GNUNET_free (data);
1187  return md;
1188 }
1189 
1190 
1191 /* end of container_meta_data.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
ssize_t GNUNET_CONTAINER_meta_data_get_serialized_size(const struct GNUNET_CONTAINER_MetaData *md)
Get the size of the full meta-data in serialized form.
EXTRACTOR_MetaFormat
Format in which the extracted meta data is presented.
void GNUNET_CONTAINER_meta_data_clear(struct GNUNET_CONTAINER_MetaData *md)
Remove all items in the container.
ssize_t GNUNET_CONTAINER_meta_data_serialize(const struct GNUNET_CONTAINER_MetaData *md, char **target, size_t max, enum GNUNET_CONTAINER_MetaDataSerializationOptions opt)
Serialize meta-data to target.
If not enough space is available, it is acceptable to only serialize some of the metadata.
#define HEADER_COMPRESSED
Flag in &#39;version&#39; that indicates compressed meta-data.
Some kind of binary format, see given Mime type.
char * data
The actual meta data.
struct MetaItem * items_head
Head of linked list of the meta data items.
void GNUNET_CONTAINER_meta_data_add_publication_date(struct GNUNET_CONTAINER_MetaData *md)
Add the current time as the publication date to the meta-data.
GNUNET_CONTAINER_MetaDataSerializationOptions
Options for metadata serialization.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
size_t GNUNET_CONTAINER_meta_data_get_thumbnail(const struct GNUNET_CONTAINER_MetaData *md, unsigned char **thumb)
Get a thumbnail from the meta-data (if present).
enum EXTRACTOR_MetaType type
Type of the meta data.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_deserialize(const char *input, size_t size)
Deserialize meta-data.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static int merge_helper(void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_size)
Merge given meta data.
0-terminated, UTF-8 encoded string.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
char * GNUNET_CONTAINER_meta_data_get_by_type(const struct GNUNET_CONTAINER_MetaData *md, enum EXTRACTOR_MetaType type)
Get the first MD entry of the given type.
EXTRACTOR_MetaType
Enumeration defining various sources of keywords.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct MetaItem * prev
This is a doubly linked list.
char * GNUNET_CONTAINER_meta_data_get_first_by_types(const struct GNUNET_CONTAINER_MetaData *md,...)
Get the first matching MD entry of the given types.
size_t data_size
Number of bytes in &#39;data&#39;.
uint32_t size
Size of the decompressed meta data.
char * plugin_name
Name of the extracting plugin.
#define max(x, y)
Meta data to associate with a file, directory or namespace.
int(* EXTRACTOR_MetaDataProcessor)(void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_len)
Type of a function that libextractor calls for each meta data item found.
char * mime_type
Mime-type of data.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
void GNUNET_CONTAINER_meta_data_merge(struct GNUNET_CONTAINER_MetaData *md, const struct GNUNET_CONTAINER_MetaData *in)
Extend metadata.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_create()
Create a fresh struct CONTAINER_MetaData token.
uint32_t version
The version of the MD serialization.
Speed is of the essence, do not allow compression.
void GNUNET_CONTAINER_meta_data_destroy(struct GNUNET_CONTAINER_MetaData *md)
Free meta data.
static int result
Global testing status.
#define GNUNET_CONTAINER_DLL_insert_after(head, tail, other, element)
Insert an element into a DLL after the given other element.
size_t sbuf_size
Number of bytes in &#39;sbuf&#39;.
uint32_t mime_type_len
Number of bytes in the mime type including 0-terminator.
char * sbuf
Complete serialized and compressed buffer of the items.
#define HEADER_VERSION_MASK
Bits in &#39;version&#39; that give the version number.
int GNUNET_CONTAINER_meta_data_insert(struct GNUNET_CONTAINER_MetaData *md, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_size)
Extend metadata.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:86
int GNUNET_CONTAINER_meta_data_delete(struct GNUNET_CONTAINER_MetaData *md, enum EXTRACTOR_MetaType type, const char *data, size_t data_size)
Remove an item.
char * GNUNET_decompress(const char *input, size_t input_size, size_t output_size)
Decompress input, return the decompressed data as output.
static unsigned int size
Size of the "table".
Definition: peer.c:67
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
struct MetaItem * next
This is a doubly linked list.
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
int GNUNET_CONTAINER_meta_data_test_equal(const struct GNUNET_CONTAINER_MetaData *md1, const struct GNUNET_CONTAINER_MetaData *md2)
Test if two MDs are equal.
Meta data item.
Header for serialized meta data.
uint32_t plugin_name_len
Number of bytes in the plugin name including 0-terminator.
int GNUNET_CONTAINER_meta_data_iterate(const struct GNUNET_CONTAINER_MetaData *md, EXTRACTOR_MetaDataProcessor iter, void *iter_cls)
Iterate over MD entries.
static void meta_item_free(struct MetaItem *mi)
Free meta data item.
unsigned int item_count
Number of items in the linked list.
static void invalidate_sbuf(struct GNUNET_CONTAINER_MetaData *md)
The meta data has changed, invalidate its serialization buffer.
uint32_t format
Meta data format.
Time for absolute times used by GNUnet, in microseconds.
uint32_t type
Meta data type.
uint32_t data_size
Number of bytes of meta data.
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:758
Entry of serialized meta data.
int GNUNET_try_compression(const char *data, size_t old_size, char **result, size_t *new_size)
Try to compress the given block of data using libz.
enum EXTRACTOR_MetaFormat format
Format of the meta data.
uint32_t data
The data value.
struct MetaItem * items_tail
Tail of linked list of the meta data items.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
uint32_t entries
How many MD entries are there?
struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_duplicate(const struct GNUNET_CONTAINER_MetaData *md)
Duplicate a struct GNUNET_CONTAINER_MetaData.