/**
 * Add meta data that libextractor finds to our meta data
 * container.
 *
 * @param cls closure, our meta data container
 * @param plugin_name name of the plugin that produced this value;
 *        special values can be used (i.e. '<zlib>' for zlib being
 *        used in the main libextractor library and yielding
 *        meta data).
 * @param type libextractor-type describing the meta data
 * @param format basic format information about data
 * @param data_mime_type mime-type of data (not of the original file);
 *        can be NULL (if mime-type is not known)
 * @param data actual meta-data found
 * @param data_len number of bytes in @a data
 * @return always 0 to continue extracting
 */
static int
add_to_md (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)
{
  struct GNUNET_CONTAINER_MetaData *md = cls;

  if ( ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
	(EXTRACTOR_METAFORMAT_C_STRING == format)) &&
       ('\0' != data[data_len - 1]) )
  {
    char zdata[data_len + 1];
    memcpy (zdata, data, data_len);
    zdata[data_len] = '\0';
    (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format,
					      data_mime_type, zdata, data_len + 1);
  }
  else
  {
    (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format,
					      data_mime_type, data, data_len);
  }
  return 0;
}
/**
 * Add meta data that libextractor finds to our meta data
 * container.
 *
 * @param cls closure, our meta data container
 * @param plugin_name name of the plugin that produced this value;
 *        special values can be used (i.e. '<zlib>' for zlib being
 *        used in the main libextractor library and yielding
 *        meta data).
 * @param type libextractor-type describing the meta data
 * @param format basic format information about data
 * @param data_mime_type mime-type of data (not of the original file);
 *        can be NULL (if mime-type is not known)
 * @param data actual meta-data found
 * @param data_len number of bytes in data
 * @return always 0 to continue extracting
 */
static int
add_to_md (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)
{
  struct GNUNET_CONTAINER_MetaData *md = cls;

  (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format,
                                            data_mime_type, data, data_len);
  return 0;
}
/**
 * Add the current time as the publication date
 * to the meta-data.
 *
 * @param md metadata to modify
 */
void
GNUNET_CONTAINER_meta_data_add_publication_date (struct
                                                 GNUNET_CONTAINER_MetaData *md)
{
  char *dat;
  struct GNUNET_TIME_Absolute t;

  t = GNUNET_TIME_absolute_get ();
  GNUNET_CONTAINER_meta_data_delete (md, EXTRACTOR_METATYPE_PUBLICATION_DATE,
                                     NULL, 0);
  dat = GNUNET_STRINGS_absolute_time_to_string (t);
  GNUNET_CONTAINER_meta_data_insert (md, "<gnunet>",
                                     EXTRACTOR_METATYPE_PUBLICATION_DATE,
                                     EXTRACTOR_METAFORMAT_UTF8, "text/plain",
                                     dat, strlen (dat) + 1);
  GNUNET_free (dat);
}
Exemple #4
0
/**
 * Set the MIMETYPE information for the given
 * metadata to "application/gnunet-directory".
 *
 * @param md metadata to add mimetype to
 */
void
GNUNET_FS_meta_data_make_directory (struct GNUNET_CONTAINER_MetaData *md)
{
  char *mime;

  mime =
      GNUNET_CONTAINER_meta_data_get_by_type (md, EXTRACTOR_METATYPE_MIMETYPE);
  if (mime != NULL)
  {
    GNUNET_break (0 == strcmp (mime, GNUNET_FS_DIRECTORY_MIME));
    GNUNET_free (mime);
    return;
  }
  GNUNET_CONTAINER_meta_data_insert (md, "<gnunet>",
                                     EXTRACTOR_METATYPE_MIMETYPE,
                                     EXTRACTOR_METAFORMAT_UTF8, "text/plain",
                                     GNUNET_FS_DIRECTORY_MIME,
                                     strlen (GNUNET_FS_DIRECTORY_MIME) + 1);
}
/**
 * Duplicate struct GNUNET_CONTAINER_MetaData.
 *
 * @param md what to duplicate
 * @return duplicate meta-data container
 */
struct GNUNET_CONTAINER_MetaData *
GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData
                                      *md)
{
  struct GNUNET_CONTAINER_MetaData *ret;
  struct MetaItem *pos;

  if (md == NULL)
    return NULL;
  ret = GNUNET_CONTAINER_meta_data_create ();
  pos = md->items;
  while (NULL != pos)
  {
    GNUNET_CONTAINER_meta_data_insert (ret, pos->plugin_name, pos->type,
                                       pos->format, pos->mime_type, pos->data,
                                       pos->data_size);
    pos = pos->next;
  }
  return ret;
}
/**
 * Copy "frequent" metadata items over to the
 * target metadata container, free the counters.
 *
 * @param cls the 'struct TrimContext'
 * @param key key of the entry
 * @param value the 'struct KeywordCounter'
 * @return GNUNET_YES (always)
 */
static int
migrate_and_drop_metadata (void *cls, const GNUNET_HashCode * key, void *value)
{
  struct TrimContext *tc = cls;
  struct MetaCounter *counter = value;

  if (counter->count >= tc->move_threshold)
  {
    if (NULL == tc->pos->meta)
      tc->pos->meta = GNUNET_CONTAINER_meta_data_create ();
    GNUNET_CONTAINER_meta_data_insert (tc->pos->meta,
				       counter->plugin_name,
				       counter->type,
				       counter->format,
				       counter->data_mime_type, counter->data,
				       counter->data_size); 
  }
  GNUNET_assert (GNUNET_YES ==
		 GNUNET_CONTAINER_multihashmap_remove (tc->metacounter,
						       key,
						       counter));
  GNUNET_free (counter);
  return GNUNET_YES;
}
/**
 * Called every time there is data to read from the scanner.
 * Calls the scanner progress handler.
 *
 * @param cls the closure (directory scanner object)
 * @param client always NULL
 * @param msg message from the helper process
 */
static int
process_helper_msgs (void *cls, 
		     void *client,
		     const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_FS_DirScanner *ds = cls;
  const char *filename;
  size_t left;

#if 0
  fprintf (stderr, "DMS parses %u-byte message of type %u\n",
	   (unsigned int) ntohs (msg->size),
	   (unsigned int) ntohs (msg->type));
#endif
  left = ntohs (msg->size) - sizeof (struct GNUNET_MessageHeader);
  filename = (const char*) &msg[1];
  switch (ntohs (msg->type))
  {
  case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_FILE:
    if (filename[left-1] != '\0')
    {
      GNUNET_break (0);
      break;
    }
    ds->progress_callback (ds->progress_callback_cls, 
			   filename, GNUNET_NO,
			   GNUNET_FS_DIRSCANNER_FILE_START);
    if (NULL == ds->toplevel)
      ds->toplevel = expand_tree (ds->pos,
				  filename, GNUNET_NO);
    else
      (void) expand_tree (ds->pos,
			  filename, GNUNET_NO);
    return GNUNET_OK;
  case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY:
    if (filename[left-1] != '\0')
    {
      GNUNET_break (0);
      break;
    }
    if (0 == strcmp ("..", filename))
    {
      if (NULL == ds->pos)
      {
	GNUNET_break (0);
	break;
      }
      ds->pos = ds->pos->parent;
      return GNUNET_OK;
    }
    ds->progress_callback (ds->progress_callback_cls, 
			   filename, GNUNET_YES,
			   GNUNET_FS_DIRSCANNER_FILE_START);
    ds->pos = expand_tree (ds->pos,
			   filename, GNUNET_YES);
    if (NULL == ds->toplevel)
      ds->toplevel = ds->pos;
    return GNUNET_OK;
  case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR:
    break;
  case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_SKIP_FILE:
    if ('\0' != filename[left-1])
      break;
    ds->progress_callback (ds->progress_callback_cls, 
			   filename, GNUNET_SYSERR,
			   GNUNET_FS_DIRSCANNER_FILE_IGNORED);
    return GNUNET_OK;
  case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE:
    if (0 != left)
    {
      GNUNET_break (0);
      break;
    }
    if (NULL == ds->toplevel)
    {
      GNUNET_break (0);
      break;
    }
    ds->progress_callback (ds->progress_callback_cls, 
			   NULL, GNUNET_SYSERR,
			   GNUNET_FS_DIRSCANNER_ALL_COUNTED);
    ds->pos = ds->toplevel;
    if (GNUNET_YES == ds->pos->is_directory)
      ds->pos = advance (ds->pos);
    return GNUNET_OK;
  case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA:
    {
      size_t nlen;
      const char *end;
      
      if (NULL == ds->pos)
      {
	GNUNET_break (0);
	break;
      }
      end = memchr (filename, 0, left);
      if (NULL == end)
      {
	GNUNET_break (0);
	break;
      }
      end++;
      nlen = end - filename;
      left -= nlen;
      if (0 != strcmp (filename,
		       ds->pos->filename))
      {
	GNUNET_break (0);
	break;
      }
      ds->progress_callback (ds->progress_callback_cls, 
			     filename, GNUNET_YES,
			     GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED);
      if (0 < left)
      {
	ds->pos->meta = GNUNET_CONTAINER_meta_data_deserialize (end, left);
	if (NULL == ds->pos->meta)
	{
	  GNUNET_break (0);
	  break;
	}
	/* having full filenames is too dangerous; always make sure we clean them up */
	GNUNET_CONTAINER_meta_data_delete (ds->pos->meta, 
					   EXTRACTOR_METATYPE_FILENAME,
					   NULL, 0);
	/* instead, put in our 'safer' original filename */
	GNUNET_CONTAINER_meta_data_insert (ds->pos->meta, "<libgnunetfs>",
					   EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME,
					   EXTRACTOR_METAFORMAT_UTF8, "text/plain",
					   ds->pos->short_filename, 
					   strlen (ds->pos->short_filename) + 1);
      }
      ds->pos->ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (ds->pos->meta);
      ds->pos = advance (ds->pos);      
      return GNUNET_OK;
    }
  case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED:
    if (NULL != ds->pos)
    {
      GNUNET_break (0);
      break;
    }
    if (0 != left)
    {
      GNUNET_break (0);
      break;
    }   
    if (NULL == ds->toplevel)
    {
      GNUNET_break (0);
      break;
    }
    ds->stop_task = GNUNET_SCHEDULER_add_now (&finish_scan,
					      ds);
    return GNUNET_OK;
  default:
    GNUNET_break (0);
    break;
  }
  ds->progress_callback (ds->progress_callback_cls, 
			 NULL, GNUNET_SYSERR,
			 GNUNET_FS_DIRSCANNER_INTERNAL_ERROR);
  return GNUNET_OK;
}
/**
 * Deserialize meta-data.  Initializes md.
 *
 * @param input buffer with the serialized metadata
 * @param size number of bytes available in input
 * @return MD on success, NULL on error (i.e.
 *         bad format)
 */
struct GNUNET_CONTAINER_MetaData *
GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size)
{
  struct GNUNET_CONTAINER_MetaData *md;
  struct MetaDataHeader hdr;
  struct MetaDataEntry ent;
  uint32_t ic;
  uint32_t i;
  char *data;
  const char *cdata;
  uint32_t version;
  uint32_t dataSize;
  int compressed;
  size_t left;
  uint32_t mlen;
  uint32_t plen;
  uint32_t dlen;
  const char *mdata;
  const char *meta_data;
  const char *plugin_name;
  const char *mime_type;
  enum EXTRACTOR_MetaFormat format;

  if (size < sizeof (struct MetaDataHeader))
    return NULL;
  memcpy (&hdr, input, sizeof (struct MetaDataHeader));
  version = ntohl (hdr.version) & HEADER_VERSION_MASK;
  compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0;

  if (version == 1)
    return NULL;                /* null pointer */
  if (version != 2)
  {
    GNUNET_break_op (0);        /* unsupported version */
    return NULL;
  }

  ic = ntohl (hdr.entries);
  dataSize = ntohl (hdr.size);
  if ((sizeof (struct MetaDataEntry) * ic) > dataSize)
  {
    GNUNET_break_op (0);
    return NULL;
  }

  if (compressed)
  {
    if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
    {
      /* make sure we don't blow our memory limit because of a mal-formed
       * message... */
      GNUNET_break_op (0);
      return NULL;
    }
    data =
        decompress ((const char *) &input[sizeof (struct MetaDataHeader)],
                    size - sizeof (struct MetaDataHeader), dataSize);
    if (data == NULL)
    {
      GNUNET_break_op (0);
      return NULL;
    }
    cdata = data;
  }
  else
  {
    data = NULL;
    cdata = (const char *) &input[sizeof (struct MetaDataHeader)];
    if (dataSize != size - sizeof (struct MetaDataHeader))
    {
      GNUNET_break_op (0);
      return NULL;
    }
  }

  md = GNUNET_CONTAINER_meta_data_create ();
  left = dataSize - ic * sizeof (struct MetaDataEntry);
  mdata = &cdata[ic * sizeof (struct MetaDataEntry)];
  for (i = 0; i < ic; i++)
  {
    memcpy (&ent, &cdata[i * sizeof (struct MetaDataEntry)],
            sizeof (struct MetaDataEntry));
    format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format);
    if ((format != EXTRACTOR_METAFORMAT_UTF8) &&
        (format != EXTRACTOR_METAFORMAT_C_STRING) &&
        (format != EXTRACTOR_METAFORMAT_BINARY))
    {
      GNUNET_break_op (0);
      break;
    }
    dlen = ntohl (ent.data_size);
    plen = ntohl (ent.plugin_name_len);
    mlen = ntohl (ent.mime_type_len);
    if (dlen > left)
    {
      GNUNET_break_op (0);
      break;
    }
    left -= dlen;
    meta_data = &mdata[left];
    if ((format == EXTRACTOR_METAFORMAT_UTF8) ||
        (format == EXTRACTOR_METAFORMAT_C_STRING))
    {
      if ((dlen == 0) || (mdata[left + dlen - 1] != '\0'))
      {
        GNUNET_break_op (0);
        break;
      }
    }
    if (plen > left)
    {
      GNUNET_break_op (0);
      break;
    }
    left -= plen;
    if ((plen > 0) && (mdata[left + plen - 1] != '\0'))
    {
      GNUNET_break_op (0);
      break;
    }
    if (plen == 0)
      plugin_name = NULL;
    else
      plugin_name = &mdata[left];

    if (mlen > left)
    {
      GNUNET_break_op (0);
      break;
    }
    left -= mlen;
    if ((mlen > 0) && (mdata[left + mlen - 1] != '\0'))
    {
      GNUNET_break_op (0);
      break;
    }
    if (mlen == 0)
      mime_type = NULL;
    else
      mime_type = &mdata[left];
    GNUNET_CONTAINER_meta_data_insert (md, plugin_name,
                                       (enum EXTRACTOR_MetaType)
                                       ntohl (ent.type), format, mime_type,
                                       meta_data, dlen);
  }
  GNUNET_free_non_null (data);
  return md;
}
/**
 * Create an entry for a file in a publish-structure.
 *
 * @param h handle to the file sharing subsystem
 * @param client_info initial value for the client-info value for this entry
 * @param filename name of the file or directory to publish
 * @param keywords under which keywords should this file be available
 *         directly; can be NULL
 * @param meta metadata for the file
 * @param do_index GNUNET_YES for index, GNUNET_NO for insertion,
 *                GNUNET_SYSERR for simulation
 * @param bo block options
 * @return publish structure entry for the file
 */
struct GNUNET_FS_FileInformation *
GNUNET_FS_file_information_create_from_file (struct GNUNET_FS_Handle *h,
                                             void *client_info,
                                             const char *filename,
                                             const struct GNUNET_FS_Uri
                                             *keywords,
                                             const struct
                                             GNUNET_CONTAINER_MetaData *meta,
                                             int do_index,
                                             const struct GNUNET_FS_BlockOptions
                                             *bo)
{
  struct FileInfo *fi;
  uint64_t fsize;
  struct GNUNET_FS_FileInformation *ret;
  const char *fn;
  const char *ss;

#if WINDOWS
  char fn_conv[MAX_PATH];
#endif

  /* FIXME: should includeSymLinks be GNUNET_NO or GNUNET_YES here? */
  if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fsize, GNUNET_NO, GNUNET_YES))
  {
    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
    return NULL;
  }
  fi = GNUNET_FS_make_file_reader_context_ (filename);
  if (fi == NULL)
  {
    GNUNET_break (0);
    return NULL;
  }
  ret =
      GNUNET_FS_file_information_create_from_reader (h, client_info,
                                                     fsize,
                                                     &GNUNET_FS_data_reader_file_,
                                                     fi, keywords, meta,
                                                     do_index, bo);
  if (ret == NULL)
    return NULL;
  ret->h = h;
  ret->filename = GNUNET_strdup (filename);
#if !WINDOWS
  fn = filename;
#else
  plibc_conv_to_win_path (filename, fn_conv);
  fn = fn_conv;
#endif
  while (NULL != (ss = strstr (fn, DIR_SEPARATOR_STR)))
    fn = ss + 1;
/* FIXME: If we assume that on other platforms CRT is UTF-8-aware, then
 * this should be changed to EXTRACTOR_METAFORMAT_UTF8
 */
#if !WINDOWS
  GNUNET_CONTAINER_meta_data_insert (ret->meta, "<gnunet>",
                                     EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME,
                                     EXTRACTOR_METAFORMAT_C_STRING,
                                     "text/plain", fn, strlen (fn) + 1);
#else
  GNUNET_CONTAINER_meta_data_insert (ret->meta, "<gnunet>",
                                     EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME,
                                     EXTRACTOR_METAFORMAT_UTF8,
                                     "text/plain", fn, strlen (fn) + 1);
#endif
  return ret;
}
Exemple #10
0
static int
testDirectory (unsigned int i)
{
  struct GNUNET_FS_DirectoryBuilder *db;
  char *data;
  size_t dlen;
  struct GNUNET_FS_Uri **uris;
  struct GNUNET_CONTAINER_MetaData **mds;
  struct GNUNET_CONTAINER_MetaData *meta;
  struct PCLS cls;
  char *emsg;
  int p;
  int q;
  char uri[512];
  char txt[128];
  int ret = 0;
  struct GNUNET_TIME_Absolute start;
  const char *s;

  cls.max = i;
  uris = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri *) * i);
  mds = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_MetaData *) * i);
  meta = GNUNET_CONTAINER_meta_data_create ();
  GNUNET_CONTAINER_meta_data_insert (meta, "<test>", EXTRACTOR_METATYPE_TITLE,
                                     EXTRACTOR_METAFORMAT_UTF8, "text/plain",
                                     "A title", strlen ("A title") + 1);
  GNUNET_CONTAINER_meta_data_insert (meta, "<test>",
                                     EXTRACTOR_METATYPE_AUTHOR_NAME,
                                     EXTRACTOR_METAFORMAT_UTF8, "text/plain",
                                     "An author", strlen ("An author") + 1);
  for (p = 0; p < i; p++)
  {
    mds[p] = GNUNET_CONTAINER_meta_data_create ();
    for (q = 0; q <= p; q++)
    {
      GNUNET_snprintf (txt, sizeof (txt), "%u -- %u\n", p, q);
      GNUNET_CONTAINER_meta_data_insert (mds[p], "<test>",
#if HAVE_EXTRACTOR_H
                                         q % EXTRACTOR_metatype_get_max (),
#else
                                         q % 128,
#endif
                                         EXTRACTOR_METAFORMAT_UTF8,
                                         "text/plain", txt, strlen (txt) + 1);
    }
    GNUNET_snprintf (uri, sizeof (uri),
                     "gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.%u",
                     p);
    emsg = NULL;
    uris[p] = GNUNET_FS_uri_parse (uri, &emsg);
    if (uris[p] == NULL)
    {
      GNUNET_CONTAINER_meta_data_destroy (mds[p]);
      while (--p > 0)
      {
        GNUNET_CONTAINER_meta_data_destroy (mds[p]);
        GNUNET_FS_uri_destroy (uris[p]);
      }
      GNUNET_free (mds);
      GNUNET_free (uris);
      GNUNET_free (emsg);
      GNUNET_CONTAINER_meta_data_destroy (meta);
      ABORT ();                 /* error in testcase */
    }
    GNUNET_assert (emsg == NULL);
  }
  start = GNUNET_TIME_absolute_get ();
  db = GNUNET_FS_directory_builder_create (meta);
  for (p = 0; p < i; p++)
    GNUNET_FS_directory_builder_add (db, uris[p], mds[p], NULL);
  GNUNET_FS_directory_builder_finish (db, &dlen, (void **) &data);
  s = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration
                                              (start),
					      GNUNET_YES);
  FPRINTF (stdout,
           "Creating directory with %u entires and total size %llu took %s\n",
           i, (unsigned long long) dlen, s);
  if (i < 100)
  {
    cls.pos = 0;
    cls.uri = uris;
    cls.md = mds;
    GNUNET_FS_directory_list_contents (dlen, data, 0, &processor, &cls);
    GNUNET_assert (cls.pos == i);
  }
  GNUNET_free (data);
  GNUNET_CONTAINER_meta_data_destroy (meta);
  for (p = 0; p < i; p++)
  {
    GNUNET_CONTAINER_meta_data_destroy (mds[p]);
    GNUNET_FS_uri_destroy (uris[p]);
  }
  GNUNET_free (uris);
  GNUNET_free (mds);
  return ret;
}
/**
 * Process a share item tree, moving frequent keywords up and
 * copying frequent metadata up.
 *
 * @param tc trim context with hash maps to use
 * @param tree tree to trim
 */
static void
share_tree_trim (struct TrimContext *tc,
		 struct GNUNET_FS_ShareTreeItem *tree)
{
  struct GNUNET_FS_ShareTreeItem *pos;
  unsigned int num_children;

  /* first, trim all children */
  num_children = 0;
  for (pos = tree->children_head; NULL != pos; pos = pos->next)
  {
    share_tree_trim (tc, pos);
    num_children++;
  }

  /* consider adding filename to directory meta data */
  if (tree->is_directory == GNUNET_YES)
  {
    const char *user = getenv ("USER");
    if ( (user == NULL) || 
	 (0 != strncasecmp (user, tree->short_filename, strlen(user))))
    {
      /* only use filename if it doesn't match $USER */
      if (NULL == tree->meta)
	tree->meta = GNUNET_CONTAINER_meta_data_create ();
      GNUNET_CONTAINER_meta_data_insert (tree->meta, "<libgnunetfs>",
					 EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME,
					 EXTRACTOR_METAFORMAT_UTF8,
					 "text/plain", tree->short_filename,
					 strlen (tree->short_filename) + 1);
    }
  }

  if (1 >= num_children)
    return; /* nothing to trim */
  
  /* now, count keywords and meta data in children */
  for (pos = tree->children_head; NULL != pos; pos = pos->next)
  {
    if (NULL != pos->meta)
      GNUNET_CONTAINER_meta_data_iterate (pos->meta, &add_to_meta_counter, tc->metacounter);    
    if (NULL != pos->ksk_uri)
      GNUNET_FS_uri_ksk_get_keywords (pos->ksk_uri, &add_to_keyword_counter, tc->keywordcounter);
  }

  /* calculate threshold for moving keywords / meta data */
  tc->move_threshold = 1 + (num_children / 2);

  /* remove high-frequency keywords from children */
  for (pos = tree->children_head; NULL != pos; pos = pos->next)
  {
    tc->pos = pos;
    if (NULL != pos->ksk_uri)
    {
      struct GNUNET_FS_Uri *ksk_uri_copy = GNUNET_FS_uri_dup (pos->ksk_uri);
      GNUNET_FS_uri_ksk_get_keywords (ksk_uri_copy, &remove_high_frequency_keywords, tc);
      GNUNET_FS_uri_destroy (ksk_uri_copy);
    }
  }

  /* add high-frequency meta data and keywords to parent */
  tc->pos = tree;
  GNUNET_CONTAINER_multihashmap_iterate (tc->keywordcounter, 
					 &migrate_and_drop_keywords,
					 tc);
  GNUNET_CONTAINER_multihashmap_iterate (tc->metacounter, 
					 &migrate_and_drop_metadata,
					 tc);
}
Exemple #12
0
int
main (int argc, char *argv[])
{
  int ok;
  struct GNUNET_HashCode rid1;
  struct GNUNET_HashCode id2;
  struct GNUNET_HashCode rid2;
  struct GNUNET_HashCode fid;
  struct GNUNET_HashCode id3;

  int old;
  int newVal;
  struct GNUNET_CONFIGURATION_Handle *cfg;
  char *name1;
  char *name2;
  char *name3;
  char *name1_unique;
  char *name2_unique;
  char *noname;
  int noname_is_a_dup;
  int notiCount, fakenotiCount;
  int count;
  static char m[1024 * 1024 * 10];

  memset (m, 'b', sizeof (m));
  m[sizeof (m) - 1] = '\0';

  GNUNET_log_setup ("test-pseudonym", "WARNING", NULL);
  ok = GNUNET_YES;
  GNUNET_CRYPTO_random_disable_entropy_gathering ();
  (void) GNUNET_DISK_directory_remove ("/tmp/gnunet-pseudonym-test");
  cfg = GNUNET_CONFIGURATION_create ();
  if (-1 == GNUNET_CONFIGURATION_parse (cfg, "test_pseudonym_data.conf"))
  {
    GNUNET_CONFIGURATION_destroy (cfg);
    GNUNET_break (0);
    return -1;
  }
  notiCount = 0;
  fakenotiCount = 0;
  count = 0;
  GNUNET_PSEUDONYM_discovery_callback_register (cfg, &fake_noti_callback,
                                                &fakenotiCount);
  GNUNET_PSEUDONYM_discovery_callback_register (cfg, &noti_callback,
                                                &notiCount);
  GNUNET_PSEUDONYM_discovery_callback_unregister (&false_callback, &count);
  GNUNET_PSEUDONYM_discovery_callback_unregister (&fake_noti_callback,
                                                  &fakenotiCount);

  /* ACTUAL TEST CODE */
  old = GNUNET_PSEUDONYM_list_all (cfg, NULL, NULL);
  meta = GNUNET_CONTAINER_meta_data_create ();
  GNUNET_CONTAINER_meta_data_insert (meta, "<test>", EXTRACTOR_METATYPE_TITLE,
                                     EXTRACTOR_METAFORMAT_UTF8, "text/plain",
                                     "test", strlen ("test") + 1);
  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &id1);
  GNUNET_PSEUDONYM_add (cfg, &id1, meta);
  CHECK (notiCount == 1);
  GNUNET_PSEUDONYM_add (cfg, &id1, meta);
  CHECK (notiCount == 2);
  newVal = GNUNET_PSEUDONYM_list_all (cfg, &iter, &ok);
  CHECK (old < newVal);
  old = newVal;
  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &id2);
  GNUNET_PSEUDONYM_add (cfg, &id2, meta);
  CHECK (notiCount == 3);
  newVal = GNUNET_PSEUDONYM_list_all (cfg, &iter, &ok);
  CHECK (old < newVal);
  GNUNET_assert (GNUNET_OK ==
                 GNUNET_CONTAINER_meta_data_insert (meta, "<test>",
                                                    EXTRACTOR_METATYPE_COMMENT,
                                                    EXTRACTOR_METAFORMAT_UTF8,
                                                    "text/plain", m,
                                                    strlen (m) + 1));
  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &id3);
  GNUNET_PSEUDONYM_add (cfg, &id3, meta);
  GNUNET_PSEUDONYM_get_info (cfg, &id3, NULL, NULL, &name3, NULL);
  CHECK (name3 != NULL);
  GNUNET_PSEUDONYM_get_info (cfg, &id2, NULL, NULL, &name2, NULL);
  CHECK (name2 != NULL);
  GNUNET_PSEUDONYM_get_info (cfg, &id1, NULL, NULL, &name1, NULL);
  CHECK (name1 != NULL);
  CHECK (0 == strcmp (name1, name2));
  name1_unique = GNUNET_PSEUDONYM_name_uniquify (cfg, &id1, name1, NULL);
  name2_unique = GNUNET_PSEUDONYM_name_uniquify (cfg, &id2, name2, NULL);
  CHECK (0 != strcmp (name1_unique, name2_unique));
  CHECK (GNUNET_SYSERR == GNUNET_PSEUDONYM_name_to_id (cfg, "fake", &rid2));
  CHECK (GNUNET_SYSERR == GNUNET_PSEUDONYM_name_to_id (cfg, name2, &rid2));
  CHECK (GNUNET_SYSERR == GNUNET_PSEUDONYM_name_to_id (cfg, name1, &rid1));
  CHECK (GNUNET_OK == GNUNET_PSEUDONYM_name_to_id (cfg, name2_unique, &rid2));
  CHECK (GNUNET_OK == GNUNET_PSEUDONYM_name_to_id (cfg, name1_unique, &rid1));
  CHECK (0 == memcmp (&id1, &rid1, sizeof (struct GNUNET_HashCode)));
  CHECK (0 == memcmp (&id2, &rid2, sizeof (struct GNUNET_HashCode)));

  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &fid);
  GNUNET_log_skip (1, GNUNET_NO);
  CHECK (0 == GNUNET_PSEUDONYM_rank (cfg, &fid, 0));
  GNUNET_log_skip (0, GNUNET_YES);
  CHECK (GNUNET_OK == GNUNET_PSEUDONYM_get_info (cfg, &fid, NULL, NULL, &noname, &noname_is_a_dup));
  CHECK (noname != NULL);
  CHECK (noname_is_a_dup == GNUNET_YES);
  CHECK (0 == GNUNET_PSEUDONYM_rank (cfg, &id1, 0));
  CHECK (5 == GNUNET_PSEUDONYM_rank (cfg, &id1, 5));
  CHECK (-5 == GNUNET_PSEUDONYM_rank (cfg, &id1, -10));
  CHECK (0 == GNUNET_PSEUDONYM_rank (cfg, &id1, 5));
  GNUNET_free (name1);
  GNUNET_free (name2);
  GNUNET_free (name1_unique);
  GNUNET_free (name2_unique);
  GNUNET_free (name3);
  GNUNET_free (noname);
  /* END OF TEST CODE */
FAILURE:
  GNUNET_PSEUDONYM_discovery_callback_unregister (&noti_callback, &notiCount);
  GNUNET_CONTAINER_meta_data_destroy (meta);
  GNUNET_CONFIGURATION_destroy (cfg);
  GNUNET_break (GNUNET_OK ==
                GNUNET_DISK_directory_remove ("/tmp/gnunet-pseudonym-test"));
  return (ok == GNUNET_YES) ? 0 : 1;
}
/**
 * Add an entry to a directory.
 *
 * @param bld directory to extend
 * @param uri uri of the entry (must not be a KSK)
 * @param md metadata of the entry
 * @param data raw data of the entry, can be NULL, otherwise
 *        data must point to exactly the number of bytes specified
 *        by the uri which must be of type LOC or CHK
 */
void
GNUNET_FS_directory_builder_add (struct GNUNET_FS_DirectoryBuilder *bld,
                                 const struct GNUNET_FS_Uri *uri,
                                 const struct GNUNET_CONTAINER_MetaData *md,
                                 const void *data)
{
    struct GNUNET_FS_Uri *curi;
    struct BuilderEntry *e;
    uint64_t fsize;
    uint32_t big;
    ssize_t ret;
    size_t mds;
    size_t mdxs;
    char *uris;
    char *ser;
    char *sptr;
    size_t slen;
    struct GNUNET_CONTAINER_MetaData *meta;
    const struct GNUNET_CONTAINER_MetaData *meta_use;

    GNUNET_assert (!GNUNET_FS_uri_test_ksk (uri));
    if (NULL != data)
    {
        GNUNET_assert (!GNUNET_FS_uri_test_sks (uri));
        if (GNUNET_FS_uri_test_chk (uri))
        {
            fsize = GNUNET_FS_uri_chk_get_file_size (uri);
        }
        else
        {
            curi = GNUNET_FS_uri_loc_get_uri (uri);
            GNUNET_assert (NULL != curi);
            fsize = GNUNET_FS_uri_chk_get_file_size (curi);
            GNUNET_FS_uri_destroy (curi);
        }
    }
    else
    {
        fsize = 0;                  /* not given */
    }
    if (fsize > MAX_INLINE_SIZE)
        fsize = 0;                  /* too large */
    uris = GNUNET_FS_uri_to_string (uri);
    slen = strlen (uris) + 1;
    mds = GNUNET_CONTAINER_meta_data_get_serialized_size (md);
    meta_use = md;
    meta = NULL;
    if (fsize > 0)
    {
        meta = GNUNET_CONTAINER_meta_data_duplicate (md);
        GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>",
                                           EXTRACTOR_METATYPE_GNUNET_FULL_DATA,
                                           EXTRACTOR_METAFORMAT_BINARY, NULL, data,
                                           fsize);
        mdxs = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
        if ((slen + sizeof (uint32_t) + mdxs - 1) / DBLOCK_SIZE ==
                (slen + sizeof (uint32_t) + mds - 1) / DBLOCK_SIZE)
        {
            /* adding full data would not cause us to cross
             * additional blocks, so add it! */
            meta_use = meta;
            mds = mdxs;
        }
    }

    if (mds > GNUNET_MAX_MALLOC_CHECKED / 2)
        mds = GNUNET_MAX_MALLOC_CHECKED / 2;
    e = GNUNET_malloc (sizeof (struct BuilderEntry) + slen + mds +
                       sizeof (uint32_t));
    ser = (char *) &e[1];
    memcpy (ser, uris, slen);
    GNUNET_free (uris);
    sptr = &ser[slen + sizeof (uint32_t)];
    ret =
        GNUNET_CONTAINER_meta_data_serialize (meta_use, &sptr, mds,
                GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
    if (NULL != meta)
        GNUNET_CONTAINER_meta_data_destroy (meta);
    if (ret == -1)
        mds = 0;
    else
        mds = ret;
    big = htonl (mds);
    memcpy (&ser[slen], &big, sizeof (uint32_t));
    e->len = slen + sizeof (uint32_t) + mds;
    e->next = bld->head;
    bld->head = e;
    bld->count++;
}