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 {
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  }
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  }
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  return GNUNET_SYSERR;
968  }
969 
970  /* next iteration: ignore the corresponding meta data at the
971  * end and try again without it */
972  left -= sizeof(struct MetaDataEntry);
973  left -= pos->data_size;
974  if (NULL != pos->plugin_name)
975  left -= strlen (pos->plugin_name) + 1;
976  if (NULL != pos->mime_type)
977  left -= strlen (pos->mime_type) + 1;
978 
979  GNUNET_free_non_null (cdata);
980  cdata = NULL;
981 
982  i++;
983  }
984  GNUNET_free (ent);
985 
986  /* nothing fit, only write header! */
987  ihdr.version = htonl (2);
988  ihdr.entries = htonl (0);
989  ihdr.size = htonl (0);
990  if (NULL == *target)
991  *target = (char *) GNUNET_new (struct MetaDataHeader);
992  GNUNET_memcpy (*target, &ihdr, sizeof(struct MetaDataHeader));
993  return sizeof(struct MetaDataHeader);
994 }
995 
996 
1003 ssize_t
1006 {
1007  ssize_t ret;
1008  char *ptr;
1009 
1010  if (NULL != md->sbuf)
1011  return md->sbuf_size;
1012  ptr = NULL;
1013  ret =
1016  if (-1 != ret)
1017  GNUNET_free (ptr);
1018  return ret;
1019 }
1020 
1021 
1032 {
1033  struct GNUNET_CONTAINER_MetaData *md;
1034  struct MetaDataHeader hdr;
1035  struct MetaDataEntry ent;
1036  uint32_t ic;
1037  uint32_t i;
1038  char *data;
1039  const char *cdata;
1040  uint32_t version;
1041  uint32_t dataSize;
1042  int compressed;
1043  size_t left;
1044  uint32_t mlen;
1045  uint32_t plen;
1046  uint32_t dlen;
1047  const char *mdata;
1048  const char *meta_data;
1049  const char *plugin_name;
1050  const char *mime_type;
1052 
1053  if (size < sizeof(struct MetaDataHeader))
1054  return NULL;
1055  GNUNET_memcpy (&hdr, input, sizeof(struct MetaDataHeader));
1056  version = ntohl (hdr.version) & HEADER_VERSION_MASK;
1057  compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0;
1058 
1059  if (1 == version)
1060  return NULL; /* null pointer */
1061  if (2 != version)
1062  {
1063  GNUNET_break_op (0); /* unsupported version */
1064  return NULL;
1065  }
1066 
1067  ic = ntohl (hdr.entries);
1068  dataSize = ntohl (hdr.size);
1069  if (((sizeof(struct MetaDataEntry) * ic) > dataSize) ||
1070  ((0 != ic) &&
1071  (dataSize / ic < sizeof(struct MetaDataEntry))))
1072  {
1073  GNUNET_break_op (0);
1074  return NULL;
1075  }
1076 
1077  if (compressed)
1078  {
1079  if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
1080  {
1081  /* make sure we don't blow our memory limit because of a mal-formed
1082  * message... */
1083  GNUNET_break_op (0);
1084  return NULL;
1085  }
1086  data =
1087  GNUNET_decompress ((const char *) &input[sizeof(struct MetaDataHeader)],
1088  size - sizeof(struct MetaDataHeader),
1089  dataSize);
1090  if (NULL == data)
1091  {
1092  GNUNET_break_op (0);
1093  return NULL;
1094  }
1095  cdata = data;
1096  }
1097  else
1098  {
1099  data = NULL;
1100  cdata = (const char *) &input[sizeof(struct MetaDataHeader)];
1101  if (dataSize != size - sizeof(struct MetaDataHeader))
1102  {
1103  GNUNET_break_op (0);
1104  return NULL;
1105  }
1106  }
1107 
1109  left = dataSize - ic * sizeof(struct MetaDataEntry);
1110  mdata = &cdata[ic * sizeof(struct MetaDataEntry)];
1111  for (i = 0; i < ic; i++)
1112  {
1113  GNUNET_memcpy (&ent, &cdata[i * sizeof(struct MetaDataEntry)],
1114  sizeof(struct MetaDataEntry));
1115  format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format);
1116  if ((EXTRACTOR_METAFORMAT_UTF8 != format) &&
1118  (EXTRACTOR_METAFORMAT_BINARY != format))
1119  {
1120  GNUNET_break_op (0);
1121  break;
1122  }
1123  dlen = ntohl (ent.data_size);
1124  plen = ntohl (ent.plugin_name_len);
1125  mlen = ntohl (ent.mime_type_len);
1126  if (dlen > left)
1127  {
1128  GNUNET_break_op (0);
1129  break;
1130  }
1131  left -= dlen;
1132  meta_data = &mdata[left];
1133  if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
1134  (EXTRACTOR_METAFORMAT_C_STRING == format))
1135  {
1136  if (0 == dlen)
1137  {
1138  GNUNET_break_op (0);
1139  break;
1140  }
1141  if ('\0' != meta_data[dlen - 1])
1142  {
1143  GNUNET_break_op (0);
1144  break;
1145  }
1146  }
1147  if (plen > left)
1148  {
1149  GNUNET_break_op (0);
1150  break;
1151  }
1152  left -= plen;
1153  if ((plen > 0) && ('\0' != mdata[left + plen - 1]))
1154  {
1155  GNUNET_break_op (0);
1156  break;
1157  }
1158  if (0 == plen)
1159  plugin_name = NULL;
1160  else
1161  plugin_name = &mdata[left];
1162 
1163  if (mlen > left)
1164  {
1165  GNUNET_break_op (0);
1166  break;
1167  }
1168  left -= mlen;
1169  if ((mlen > 0) && ('\0' != mdata[left + mlen - 1]))
1170  {
1171  GNUNET_break_op (0);
1172  break;
1173  }
1174  if (0 == mlen)
1175  mime_type = NULL;
1176  else
1177  mime_type = &mdata[left];
1178  GNUNET_CONTAINER_meta_data_insert (md, plugin_name,
1179  (enum EXTRACTOR_MetaType)
1180  ntohl (ent.type), format, mime_type,
1181  meta_data, dlen);
1182  }
1183  GNUNET_free_non_null (data);
1184  return md;
1185 }
1186 
1187 
1188 /* 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_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#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.
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:118
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.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
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.
#define GNUNET_YES
Definition: gnunet_common.h:77
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:742
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.