GNUnet  0.10.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", __VA_ARGS__)
35 
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 {
128  struct MetaItem *next;
129 
133  struct MetaItem *prev;
134 
138  char *plugin_name;
139 
143  char *mime_type;
144 
148  char *data;
149 
153  size_t data_size;
154 
159 
164 };
165 
174 
179 
184  char *sbuf;
185 
189  size_t sbuf_size;
190 
194  unsigned int item_count;
195 };
196 
197 
205 {
206  return GNUNET_new(struct GNUNET_CONTAINER_MetaData);
207 }
208 
209 
215 static void
217 {
221  GNUNET_free(mi);
222 }
223 
224 
231 static void
233 {
234  if (NULL == md->sbuf)
235  return;
236  GNUNET_free(md->sbuf);
237  md->sbuf = NULL;
238  md->sbuf_size = 0;
239 }
240 
241 
247 void
249 {
250  struct MetaItem *pos;
251 
252  if (NULL == md)
253  return;
254  while (NULL != (pos = md->items_head))
255  {
257  meta_item_free(pos);
258  }
260  GNUNET_free(md);
261 }
262 
263 
269 void
271 {
272  struct MetaItem *mi;
273 
274  if (NULL == md)
275  return;
276  while (NULL != (mi = md->items_head))
277  {
279  meta_item_free(mi);
280  }
282  memset(md, 0, sizeof(struct GNUNET_CONTAINER_MetaData));
283 }
284 
285 
296 int
298  *md1,
299  const struct GNUNET_CONTAINER_MetaData
300  *md2)
301 {
302  struct MetaItem *i;
303  struct MetaItem *j;
304  int found;
305 
306  if (md1 == md2)
307  return GNUNET_YES;
308  if (md1->item_count != md2->item_count)
309  return GNUNET_NO;
310  for (i = md1->items_head; NULL != i; i = i->next)
311  {
312  found = GNUNET_NO;
313  for (j = md2->items_head; NULL != j; j = j->next)
314  {
315  if ((i->type == j->type) && (i->format == j->format) &&
316  (i->data_size == j->data_size) &&
317  (0 == memcmp(i->data, j->data, i->data_size)))
318  {
319  found = GNUNET_YES;
320  break;
321  }
322  if (j->data_size < i->data_size)
323  break; /* elements are sorted by (decreasing) size... */
324  }
325  if (GNUNET_NO == found)
326  return GNUNET_NO;
327  }
328  return GNUNET_YES;
329 }
330 
331 
350 int
352  const char *plugin_name,
355  const char *data_mime_type, const char *data,
356  size_t data_size)
357 {
358  struct MetaItem *pos;
359  struct MetaItem *mi;
360  char *p;
361 
362  if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
363  (EXTRACTOR_METAFORMAT_C_STRING == format))
364  GNUNET_break('\0' == data[data_size - 1]);
365 
366  for (pos = md->items_head; NULL != pos; pos = pos->next)
367  {
368  if (pos->data_size < data_size)
369  break; /* elements are sorted by size in the list */
370  if ((pos->type == type) && (pos->data_size == data_size) &&
371  (0 == memcmp(pos->data, data, data_size)))
372  {
373  if ((NULL == pos->mime_type) && (NULL != data_mime_type))
374  {
375  pos->mime_type = GNUNET_strdup(data_mime_type);
376  invalidate_sbuf(md);
377  }
378  if ((EXTRACTOR_METAFORMAT_C_STRING == pos->format) &&
379  (EXTRACTOR_METAFORMAT_UTF8 == format))
380  {
382  invalidate_sbuf(md);
383  }
384  return GNUNET_SYSERR;
385  }
386  }
387  md->item_count++;
388  mi = GNUNET_new(struct MetaItem);
389  mi->type = type;
390  mi->format = format;
391  mi->data_size = data_size;
392  if (NULL == pos)
394  md->items_tail,
395  mi);
396  else
398  md->items_tail,
399  pos->prev,
400  mi);
401  mi->mime_type =
402  (NULL == data_mime_type) ? NULL : GNUNET_strdup(data_mime_type);
403  mi->plugin_name = (NULL == plugin_name) ? NULL : GNUNET_strdup(plugin_name);
404  mi->data = GNUNET_malloc(data_size);
405  GNUNET_memcpy(mi->data, data, data_size);
406  /* change all dir separators to POSIX style ('/') */
407  if ((EXTRACTOR_METATYPE_FILENAME == type) ||
409  {
410  p = mi->data;
411  while (('\0' != *p) && (p < mi->data + data_size))
412  {
413  if ('\\' == *p)
414  *p = '/';
415  p++;
416  }
417  }
418  invalidate_sbuf(md);
419  return GNUNET_OK;
420 }
421 
422 
439 static int
440 merge_helper(void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type,
441  enum EXTRACTOR_MetaFormat format, const char *data_mime_type,
442  const char *data, size_t data_size)
443 {
444  struct GNUNET_CONTAINER_MetaData *md = cls;
445 
446  (void)GNUNET_CONTAINER_meta_data_insert(md, plugin_name, type, format,
447  data_mime_type, data, data_size);
448  return 0;
449 }
450 
451 
459 void
461  const struct GNUNET_CONTAINER_MetaData *in)
462 {
464 }
465 
466 
477 int
480  const char *data, size_t data_size)
481 {
482  struct MetaItem *pos;
483 
484  for (pos = md->items_head; NULL != pos; pos = pos->next)
485  {
486  if (pos->data_size < data_size)
487  break; /* items are sorted by (decreasing) size */
488  if ((pos->type == type) &&
489  ((NULL == data) ||
490  ((pos->data_size == data_size) &&
491  (0 == memcmp(pos->data, data, data_size)))))
492  {
494  meta_item_free(pos);
495  md->item_count--;
496  invalidate_sbuf(md);
497  return GNUNET_OK;
498  }
499  }
500  return GNUNET_SYSERR;
501 }
502 
503 
510 void
513 {
514  const char *dat;
515  struct GNUNET_TIME_Absolute t;
516 
520  NULL, 0);
522  GNUNET_CONTAINER_meta_data_insert(md, "<gnunet>",
524  EXTRACTOR_METAFORMAT_UTF8, "text/plain",
525  dat, strlen(dat) + 1);
526 }
527 
528 
537 int
540  void *iter_cls)
541 {
542  struct MetaItem *pos;
543 
544  if (NULL == md)
545  return 0;
546  if (NULL == iter)
547  return md->item_count;
548  for (pos = md->items_head; NULL != pos; pos = pos->next)
549  if (0 !=
550  iter(iter_cls, pos->plugin_name, pos->type, pos->format,
551  pos->mime_type, pos->data, pos->data_size))
552  return md->item_count;
553  return md->item_count;
554 }
555 
556 
567 char *
570 {
571  struct MetaItem *pos;
572 
573  if (NULL == md)
574  return NULL;
575  for (pos = md->items_head; NULL != pos; pos = pos->next)
576  if ((type == pos->type) &&
577  ((pos->format == EXTRACTOR_METAFORMAT_UTF8) ||
579  return GNUNET_strdup(pos->data);
580  return NULL;
581 }
582 
583 
595 char *
598  ...)
599 {
600  char *ret;
601  va_list args;
602  int type;
603 
604  if (NULL == md)
605  return NULL;
606  ret = NULL;
607  va_start(args, md);
608  while (1)
609  {
610  type = va_arg(args, int);
611  if (-1 == type)
612  break;
613  if (NULL != (ret = GNUNET_CONTAINER_meta_data_get_by_type(md, type)))
614  break;
615  }
616  va_end(args);
617  return ret;
618 }
619 
620 
629 size_t
631  * md, unsigned char **thumb)
632 {
633  struct MetaItem *pos;
634  struct MetaItem *match;
635 
636  if (NULL == md)
637  return 0;
638  match = NULL;
639  for (pos = md->items_head; NULL != pos; pos = pos->next)
640  {
641  if ((NULL != pos->mime_type) &&
642  (0 == strncasecmp("image/", pos->mime_type, strlen("image/"))) &&
644  {
645  if (NULL == match)
646  match = pos;
647  else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) &&
649  match = pos;
650  }
651  }
652  if ((NULL == match) || (0 == match->data_size))
653  return 0;
654  *thumb = GNUNET_malloc(match->data_size);
655  GNUNET_memcpy(*thumb, match->data, match->data_size);
656  return match->data_size;
657 }
658 
659 
668  *md)
669 {
671  struct MetaItem *pos;
672 
673  if (NULL == md)
674  return NULL;
676  for (pos = md->items_tail; NULL != pos; pos = pos->prev)
678  pos->format, pos->mime_type, pos->data,
679  pos->data_size);
680  return ret;
681 }
682 
683 
687 #define HEADER_COMPRESSED 0x80000000
688 
689 
693 #define HEADER_VERSION_MASK 0x7FFFFFFF
694 
695 
709  uint32_t version;
710 
714  uint32_t entries;
715 
719  uint32_t size;
720 
726 };
727 
728 
736  uint32_t type;
737 
741  uint32_t format;
742 
746  uint32_t data_size;
747 
751  uint32_t plugin_name_len;
752 
756  uint32_t mime_type_len;
757 };
758 
759 
774 ssize_t
776  *md, char **target, size_t max,
777  enum
779  opt)
780 {
781  struct GNUNET_CONTAINER_MetaData *vmd;
782  struct MetaItem *pos;
783  struct MetaDataHeader ihdr;
784  struct MetaDataHeader *hdr;
785  struct MetaDataEntry *ent;
786  char *dst;
787  unsigned int i;
788  uint64_t msize;
789  size_t off;
790  char *mdata;
791  char *cdata;
792  size_t mlen;
793  size_t plen;
794  size_t size;
795  size_t left;
796  size_t clen;
797  size_t rlen;
798  int comp;
799 
800  if (max < sizeof(struct MetaDataHeader))
801  return GNUNET_SYSERR; /* far too small */
802  if (NULL == md)
803  return 0;
804 
805  if (NULL != md->sbuf)
806  {
807  /* try to use serialization cache */
808  if (md->sbuf_size <= max)
809  {
810  if (NULL == *target)
811  *target = GNUNET_malloc(md->sbuf_size);
812  GNUNET_memcpy(*target, md->sbuf, md->sbuf_size);
813  return md->sbuf_size;
814  }
816  return GNUNET_SYSERR; /* can say that this will fail */
817  /* need to compute a partial serialization, sbuf useless ... */
818  }
819  dst = NULL;
820  msize = 0;
821  for (pos = md->items_tail; NULL != pos; pos = pos->prev)
822  {
823  msize += sizeof(struct MetaDataEntry);
824  msize += pos->data_size;
825  if (NULL != pos->plugin_name)
826  msize += strlen(pos->plugin_name) + 1;
827  if (NULL != pos->mime_type)
828  msize += strlen(pos->mime_type) + 1;
829  }
830  size = (size_t)msize;
831  if (size != msize)
832  {
833  GNUNET_break(0); /* integer overflow */
834  return GNUNET_SYSERR;
835  }
836  if (size >= GNUNET_MAX_MALLOC_CHECKED)
837  {
838  /* too large to be processed */
839  return GNUNET_SYSERR;
840  }
841  ent = GNUNET_malloc(size);
842  mdata = (char *)&ent[md->item_count];
843  off = size - (md->item_count * sizeof(struct MetaDataEntry));
844  i = 0;
845  for (pos = md->items_head; NULL != pos; pos = pos->next)
846  {
847  ent[i].type = htonl((uint32_t)pos->type);
848  ent[i].format = htonl((uint32_t)pos->format);
849  ent[i].data_size = htonl((uint32_t)pos->data_size);
850  if (NULL == pos->plugin_name)
851  plen = 0;
852  else
853  plen = strlen(pos->plugin_name) + 1;
854  ent[i].plugin_name_len = htonl((uint32_t)plen);
855  if (NULL == pos->mime_type)
856  mlen = 0;
857  else
858  mlen = strlen(pos->mime_type) + 1;
859  ent[i].mime_type_len = htonl((uint32_t)mlen);
860  off -= pos->data_size;
861  if ((EXTRACTOR_METAFORMAT_UTF8 == pos->format) ||
863  GNUNET_break('\0' == pos->data[pos->data_size - 1]);
864  GNUNET_memcpy(&mdata[off], pos->data, pos->data_size);
865  off -= plen;
866  if (NULL != pos->plugin_name)
867  GNUNET_memcpy(&mdata[off], pos->plugin_name, plen);
868  off -= mlen;
869  if (NULL != pos->mime_type)
870  GNUNET_memcpy(&mdata[off], pos->mime_type, mlen);
871  i++;
872  }
873  GNUNET_assert(0 == off);
874 
875  clen = 0;
876  cdata = NULL;
877  left = size;
878  i = 0;
879  for (pos = md->items_head; NULL != pos; pos = pos->next)
880  {
881  comp = GNUNET_NO;
883  comp = GNUNET_try_compression((const char *)&ent[i],
884  left,
885  &cdata,
886  &clen);
887 
888  if ((NULL == md->sbuf) && (0 == i))
889  {
890  /* fill 'sbuf'; this "modifies" md, but since this is only
891  * an internal cache we will cast away the 'const' instead
892  * of making the API look strange. */
893  vmd = (struct GNUNET_CONTAINER_MetaData *)md;
894  hdr = GNUNET_malloc(left + sizeof(struct MetaDataHeader));
895  hdr->size = htonl(left);
896  hdr->entries = htonl(md->item_count);
897  if (GNUNET_YES == comp)
898  {
899  GNUNET_assert(clen < left);
900  hdr->version = htonl(2 | HEADER_COMPRESSED);
901  GNUNET_memcpy(&hdr[1], cdata, clen);
902  vmd->sbuf_size = clen + sizeof(struct MetaDataHeader);
903  }
904  else
905  {
906  hdr->version = htonl(2);
907  GNUNET_memcpy(&hdr[1], &ent[0], left);
908  vmd->sbuf_size = left + sizeof(struct MetaDataHeader);
909  }
910  vmd->sbuf = (char *)hdr;
911  }
912 
913  if (((left + sizeof(struct MetaDataHeader)) <= max) ||
914  ((GNUNET_YES == comp) && (clen <= max)))
915  {
916  /* success, this now fits! */
917  if (GNUNET_YES == comp)
918  {
919  if (NULL == dst)
920  dst = GNUNET_malloc(clen + sizeof(struct MetaDataHeader));
921  hdr = (struct MetaDataHeader *)dst;
922  hdr->version = htonl(2 | HEADER_COMPRESSED);
923  hdr->size = htonl(left);
924  hdr->entries = htonl(md->item_count - i);
925  GNUNET_memcpy(&dst[sizeof(struct MetaDataHeader)], cdata, clen);
926  GNUNET_free(cdata);
927  cdata = NULL;
928  GNUNET_free(ent);
929  rlen = clen + sizeof(struct MetaDataHeader);
930  }
931  else
932  {
933  if (NULL == dst)
934  dst = GNUNET_malloc(left + sizeof(struct MetaDataHeader));
935  hdr = (struct MetaDataHeader *)dst;
936  hdr->version = htonl(2);
937  hdr->entries = htonl(md->item_count - i);
938  hdr->size = htonl(left);
939  GNUNET_memcpy(&dst[sizeof(struct MetaDataHeader)], &ent[i], left);
940  GNUNET_free(ent);
941  rlen = left + sizeof(struct MetaDataHeader);
942  }
943  if (NULL != *target)
944  {
945  if (GNUNET_YES == comp)
946  GNUNET_memcpy(*target, dst, clen + sizeof(struct MetaDataHeader));
947  else
948  GNUNET_memcpy(*target, dst, left + sizeof(struct MetaDataHeader));
949  GNUNET_free(dst);
950  }
951  else
952  {
953  *target = dst;
954  }
955  return rlen;
956  }
957 
959  {
960  /* does not fit! */
961  GNUNET_free(ent);
962  return GNUNET_SYSERR;
963  }
964 
965  /* next iteration: ignore the corresponding meta data at the
966  * end and try again without it */
967  left -= sizeof(struct MetaDataEntry);
968  left -= pos->data_size;
969  if (NULL != pos->plugin_name)
970  left -= strlen(pos->plugin_name) + 1;
971  if (NULL != pos->mime_type)
972  left -= strlen(pos->mime_type) + 1;
973 
974  GNUNET_free_non_null(cdata);
975  cdata = NULL;
976 
977  i++;
978  }
979  GNUNET_free(ent);
980 
981  /* nothing fit, only write header! */
982  ihdr.version = htonl(2);
983  ihdr.entries = htonl(0);
984  ihdr.size = htonl(0);
985  if (NULL == *target)
986  *target = (char *)GNUNET_new(struct MetaDataHeader);
987  GNUNET_memcpy(*target, &ihdr, sizeof(struct MetaDataHeader));
988  return sizeof(struct MetaDataHeader);
989 }
990 
991 
998 ssize_t
1001 {
1002  ssize_t ret;
1003  char *ptr;
1004 
1005  if (NULL != md->sbuf)
1006  return md->sbuf_size;
1007  ptr = NULL;
1008  ret =
1011  if (-1 != ret)
1012  GNUNET_free(ptr);
1013  return ret;
1014 }
1015 
1016 
1027 {
1028  struct GNUNET_CONTAINER_MetaData *md;
1029  struct MetaDataHeader hdr;
1030  struct MetaDataEntry ent;
1031  uint32_t ic;
1032  uint32_t i;
1033  char *data;
1034  const char *cdata;
1035  uint32_t version;
1036  uint32_t dataSize;
1037  int compressed;
1038  size_t left;
1039  uint32_t mlen;
1040  uint32_t plen;
1041  uint32_t dlen;
1042  const char *mdata;
1043  const char *meta_data;
1044  const char *plugin_name;
1045  const char *mime_type;
1047 
1048  if (size < sizeof(struct MetaDataHeader))
1049  return NULL;
1050  GNUNET_memcpy(&hdr, input, sizeof(struct MetaDataHeader));
1051  version = ntohl(hdr.version) & HEADER_VERSION_MASK;
1052  compressed = (ntohl(hdr.version) & HEADER_COMPRESSED) != 0;
1053 
1054  if (1 == version)
1055  return NULL; /* null pointer */
1056  if (2 != version)
1057  {
1058  GNUNET_break_op(0); /* unsupported version */
1059  return NULL;
1060  }
1061 
1062  ic = ntohl(hdr.entries);
1063  dataSize = ntohl(hdr.size);
1064  if (((sizeof(struct MetaDataEntry) * ic) > dataSize) ||
1065  ((0 != ic) &&
1066  (dataSize / ic < sizeof(struct MetaDataEntry))))
1067  {
1068  GNUNET_break_op(0);
1069  return NULL;
1070  }
1071 
1072  if (compressed)
1073  {
1074  if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
1075  {
1076  /* make sure we don't blow our memory limit because of a mal-formed
1077  * message... */
1078  GNUNET_break_op(0);
1079  return NULL;
1080  }
1081  data =
1082  GNUNET_decompress((const char *)&input[sizeof(struct MetaDataHeader)],
1083  size - sizeof(struct MetaDataHeader),
1084  dataSize);
1085  if (NULL == data)
1086  {
1087  GNUNET_break_op(0);
1088  return NULL;
1089  }
1090  cdata = data;
1091  }
1092  else
1093  {
1094  data = NULL;
1095  cdata = (const char *)&input[sizeof(struct MetaDataHeader)];
1096  if (dataSize != size - sizeof(struct MetaDataHeader))
1097  {
1098  GNUNET_break_op(0);
1099  return NULL;
1100  }
1101  }
1102 
1104  left = dataSize - ic * sizeof(struct MetaDataEntry);
1105  mdata = &cdata[ic * sizeof(struct MetaDataEntry)];
1106  for (i = 0; i < ic; i++)
1107  {
1108  GNUNET_memcpy(&ent, &cdata[i * sizeof(struct MetaDataEntry)],
1109  sizeof(struct MetaDataEntry));
1110  format = (enum EXTRACTOR_MetaFormat)ntohl(ent.format);
1111  if ((EXTRACTOR_METAFORMAT_UTF8 != format) &&
1113  (EXTRACTOR_METAFORMAT_BINARY != format))
1114  {
1115  GNUNET_break_op(0);
1116  break;
1117  }
1118  dlen = ntohl(ent.data_size);
1119  plen = ntohl(ent.plugin_name_len);
1120  mlen = ntohl(ent.mime_type_len);
1121  if (dlen > left)
1122  {
1123  GNUNET_break_op(0);
1124  break;
1125  }
1126  left -= dlen;
1127  meta_data = &mdata[left];
1128  if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
1129  (EXTRACTOR_METAFORMAT_C_STRING == format))
1130  {
1131  if (0 == dlen)
1132  {
1133  GNUNET_break_op(0);
1134  break;
1135  }
1136  if ('\0' != meta_data[dlen - 1])
1137  {
1138  GNUNET_break_op(0);
1139  break;
1140  }
1141  }
1142  if (plen > left)
1143  {
1144  GNUNET_break_op(0);
1145  break;
1146  }
1147  left -= plen;
1148  if ((plen > 0) && ('\0' != mdata[left + plen - 1]))
1149  {
1150  GNUNET_break_op(0);
1151  break;
1152  }
1153  if (0 == plen)
1154  plugin_name = NULL;
1155  else
1156  plugin_name = &mdata[left];
1157 
1158  if (mlen > left)
1159  {
1160  GNUNET_break_op(0);
1161  break;
1162  }
1163  left -= mlen;
1164  if ((mlen > 0) && ('\0' != mdata[left + mlen - 1]))
1165  {
1166  GNUNET_break_op(0);
1167  break;
1168  }
1169  if (0 == mlen)
1170  mime_type = NULL;
1171  else
1172  mime_type = &mdata[left];
1173  GNUNET_CONTAINER_meta_data_insert(md, plugin_name,
1174  (enum EXTRACTOR_MetaType)
1175  ntohl(ent.type), format, mime_type,
1176  meta_data, dlen);
1177  }
1178  GNUNET_free_non_null(data);
1179  return md;
1180 }
1181 
1182 
1183 /* 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 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.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#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:66
#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:741
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.