curly wars / auto-indentation
[oweals/gnunet.git] / src / fs / fs_uri.c
index 61fb7d61df382afdd0686dc2fdeebceeaaa59323..48fabc1fbf24a73b87a02741f443654b6518a034 100644 (file)
@@ -4,7 +4,7 @@
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
  * @param uri uri to convert to a unique key
  * @param key wherer to store the unique key
  */
  * @param uri uri to convert to a unique key
  * @param key wherer to store the unique key
  */
-void 
-GNUNET_FS_uri_to_key (const struct GNUNET_FS_Uri *uri,
-                     GNUNET_HashCode * key)
+void
+GNUNET_FS_uri_to_key (const struct GNUNET_FS_Uri *uri, GNUNET_HashCode * key)
 {
   switch (uri->type)
 {
   switch (uri->type)
-    {
-    case chk:
-      *key = uri->data.chk.chk.query;
-      return;
-    case sks:
-      GNUNET_CRYPTO_hash (uri->data.sks.identifier,
-                         strlen (uri->data.sks.identifier), key);
-      break;
-    case ksk:
-      if (uri->data.ksk.keywordCount > 0)
-        GNUNET_CRYPTO_hash (uri->data.ksk.keywords[0],
-                           strlen (uri->data.ksk.keywords[0]), key);
-      break;
-    case loc:
-      GNUNET_CRYPTO_hash (&uri->data.loc.fi,
-                         sizeof (struct FileIdentifier) +
-                         sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), key);
-      break;
-    default:
-      memset (key, 0, sizeof (GNUNET_HashCode));
-      break;
-    }
+  {
+  case chk:
+    *key = uri->data.chk.chk.query;
+    return;
+  case sks:
+    GNUNET_CRYPTO_hash (uri->data.sks.identifier,
+                        strlen (uri->data.sks.identifier), key);
+    break;
+  case ksk:
+    if (uri->data.ksk.keywordCount > 0)
+      GNUNET_CRYPTO_hash (uri->data.ksk.keywords[0],
+                          strlen (uri->data.ksk.keywords[0]), key);
+    break;
+  case loc:
+    GNUNET_CRYPTO_hash (&uri->data.loc.fi,
+                        sizeof (struct FileIdentifier) +
+                        sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                        key);
+    break;
+  default:
+    memset (key, 0, sizeof (GNUNET_HashCode));
+    break;
+  }
 }
 
 
 }
 
 
@@ -125,7 +125,7 @@ GNUNET_FS_uri_to_key (const struct GNUNET_FS_Uri *uri,
  * Convert keyword URI to a human readable format
  * (i.e. the search query that was used in the first place)
  *
  * Convert keyword URI to a human readable format
  * (i.e. the search query that was used in the first place)
  *
- * @param uri ksk uri to convert to a string 
+ * @param uri ksk uri to convert to a string
  * @return string with the keywords
  */
 char *
  * @return string with the keywords
  */
 char *
@@ -139,45 +139,45 @@ GNUNET_FS_uri_ksk_to_string_fancy (const struct GNUNET_FS_Uri *uri)
   unsigned int keywordCount;
 
   if ((uri == NULL) || (uri->type != ksk))
   unsigned int keywordCount;
 
   if ((uri == NULL) || (uri->type != ksk))
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
   keywords = uri->data.ksk.keywords;
   keywordCount = uri->data.ksk.keywordCount;
   n = keywordCount + 1;
   for (i = 0; i < keywordCount; i++)
   keywords = uri->data.ksk.keywords;
   keywordCount = uri->data.ksk.keywordCount;
   n = keywordCount + 1;
   for (i = 0; i < keywordCount; i++)
-    {
-      keyword = keywords[i];
-      n += strlen (keyword) - 1;
-      if (NULL != strstr (&keyword[1], " "))
-        n += 2;
-      if (keyword[0] == '+')
-        n++;
-    }
+  {
+    keyword = keywords[i];
+    n += strlen (keyword) - 1;
+    if (NULL != strstr (&keyword[1], " "))
+      n += 2;
+    if (keyword[0] == '+')
+      n++;
+  }
   ret = GNUNET_malloc (n);
   strcpy (ret, "");
   for (i = 0; i < keywordCount; i++)
   ret = GNUNET_malloc (n);
   strcpy (ret, "");
   for (i = 0; i < keywordCount; i++)
+  {
+    keyword = keywords[i];
+    if (NULL != strstr (&keyword[1], " "))
     {
     {
-      keyword = keywords[i];
-      if (NULL != strstr (&keyword[1], " "))
-        {
-          strcat (ret, "\"");
-          if (keyword[0] == '+')
-            strcat (ret, keyword);
-          else
-            strcat (ret, &keyword[1]);
-          strcat (ret, "\"");
-        }
+      strcat (ret, "\"");
+      if (keyword[0] == '+')
+        strcat (ret, keyword);
       else
       else
-        {
-          if (keyword[0] == '+')
-            strcat (ret, keyword);
-          else
-            strcat (ret, &keyword[1]);
-        }
-      strcat (ret, " ");
+        strcat (ret, &keyword[1]);
+      strcat (ret, "\"");
+    }
+    else
+    {
+      if (keyword[0] == '+')
+        strcat (ret, keyword);
+      else
+        strcat (ret, &keyword[1]);
     }
     }
+    strcat (ret, " ");
+  }
   return ret;
 }
 
   return ret;
 }
 
@@ -187,7 +187,7 @@ GNUNET_FS_uri_ksk_to_string_fancy (const struct GNUNET_FS_Uri *uri)
  * spaces), return a copy of the keyword without %-encoding and
  * without double-quotes (%22).  Also, add a space at the beginning
  * if there is not a '+'.
  * spaces), return a copy of the keyword without %-encoding and
  * without double-quotes (%22).  Also, add a space at the beginning
  * if there is not a '+'.
- * 
+ *
  * @param in string with %-encoding
  * @param emsg where to store the parser error message (if any)
  * @return decodded string with leading space (or preserved plus)
  * @param in string with %-encoding
  * @param emsg where to store the parser error message (if any)
  * @return decodded string with leading space (or preserved plus)
@@ -205,41 +205,42 @@ percent_decode_keyword (const char *in, char **emsg)
   rpos = 0;
   wpos = 0;
   while (out[rpos] != '\0')
   rpos = 0;
   wpos = 0;
   while (out[rpos] != '\0')
+  {
+    if (out[rpos] == '%')
     {
     {
-      if (out[rpos] == '%')
-        {
-          if (1 != sscanf (&out[rpos + 1], "%2X", &hx))
-            {
-              GNUNET_free (out);
-             *emsg = GNUNET_strdup (_("`%' must be followed by HEX number"));
-              return NULL;
-            }
-          rpos += 3;
-          if (hx == '"')
-            continue;           /* skip double quote */
-          out[wpos++] = (char) hx;
-        }
-      else
-        {
-          out[wpos++] = out[rpos++];
-        }
+      if (1 != sscanf (&out[rpos + 1], "%2X", &hx))
+      {
+        GNUNET_free (out);
+        *emsg = GNUNET_strdup (_("`%' must be followed by HEX number"));
+        return NULL;
+      }
+      rpos += 3;
+      if (hx == '"')
+        continue;               /* skip double quote */
+      out[wpos++] = (char) hx;
     }
     }
-  out[wpos] = '\0';
-  if (out[0] == '+')
+    else
     {
     {
-      ret = GNUNET_strdup (out);
+      out[wpos++] = out[rpos++];
     }
     }
+  }
+  out[wpos] = '\0';
+  if (out[0] == '+')
+  {
+    ret = GNUNET_strdup (out);
+  }
   else
   else
-    {
-      /* need to prefix with space */
-      ret = GNUNET_malloc (strlen (out) + 2);
-      strcpy (ret, " ");
-      strcat (ret, out);
-    }
+  {
+    /* need to prefix with space */
+    ret = GNUNET_malloc (strlen (out) + 2);
+    strcpy (ret, " ");
+    strcat (ret, out);
+  }
   GNUNET_free (out);
   return ret;
 }
 
   GNUNET_free (out);
   return ret;
 }
 
+#define GNUNET_FS_URI_KSK_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX
 
 /**
  * Parse a KSK URI.
 
 /**
  * Parse a KSK URI.
@@ -263,67 +264,65 @@ uri_ksk_parse (const char *s, char **emsg)
 
   GNUNET_assert (s != NULL);
   slen = strlen (s);
 
   GNUNET_assert (s != NULL);
   slen = strlen (s);
-  pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX);
-  if ( (slen <= pos) ||
-       (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX, 
-                     pos) ) )
-    return NULL;       /* not KSK URI */
-  if ( (s[slen - 1] == '+') ||
-       (s[pos] == '+') )
-    {
-      *emsg = GNUNET_strdup (_("Malformed KSK URI (must not begin or end with `+')"));
-      return NULL;
-    }
+  pos = strlen (GNUNET_FS_URI_KSK_PREFIX);
+  if ((slen <= pos) || (0 != strncmp (s, GNUNET_FS_URI_KSK_PREFIX, pos)))
+    return NULL;                /* not KSK URI */
+  if ((s[slen - 1] == '+') || (s[pos] == '+'))
+  {
+    *emsg =
+        GNUNET_strdup (_("Malformed KSK URI (must not begin or end with `+')"));
+    return NULL;
+  }
   max = 1;
   saw_quote = 0;
   for (i = pos; i < slen; i++)
   max = 1;
   saw_quote = 0;
   for (i = pos; i < slen; i++)
+  {
+    if ((s[i] == '%') && (&s[i] == strstr (&s[i], "%22")))
     {
     {
-      if ((s[i] == '%') && (&s[i] == strstr (&s[i], "%22")))
-        {
-          saw_quote = (saw_quote + 1) % 2;
-          i += 3;
-          continue;
-        }
-      if ((s[i] == '+') && (saw_quote == 0))
-        {
-          max++;
-          if (s[i - 1] == '+')
-           {
-             *emsg = GNUNET_strdup (_("`++' not allowed in KSK URI")); 
-             return NULL;
-           }
-        }
+      saw_quote = (saw_quote + 1) % 2;
+      i += 3;
+      continue;
     }
     }
-  if (saw_quote == 1)
+    if ((s[i] == '+') && (saw_quote == 0))
     {
     {
-      *emsg = GNUNET_strdup (_("Quotes not balanced in KSK URI")); 
-      return NULL;
+      max++;
+      if (s[i - 1] == '+')
+      {
+        *emsg = GNUNET_strdup (_("`++' not allowed in KSK URI"));
+        return NULL;
+      }
     }
     }
+  }
+  if (saw_quote == 1)
+  {
+    *emsg = GNUNET_strdup (_("Quotes not balanced in KSK URI"));
+    return NULL;
+  }
   iret = max;
   dup = GNUNET_strdup (s);
   keywords = GNUNET_malloc (max * sizeof (char *));
   for (i = slen - 1; i >= pos; i--)
   iret = max;
   dup = GNUNET_strdup (s);
   keywords = GNUNET_malloc (max * sizeof (char *));
   for (i = slen - 1; i >= pos; i--)
+  {
+    if ((s[i] == '%') && (&s[i] == strstr (&s[i], "%22")))
     {
     {
-      if ((s[i] == '%') && (&s[i] == strstr (&s[i], "%22")))
-        {
-          saw_quote = (saw_quote + 1) % 2;
-          i += 3;
-          continue;
-        }
-      if ((dup[i] == '+') && (saw_quote == 0))
-        {
-          keywords[--max] = percent_decode_keyword (&dup[i + 1], emsg);
-          if (NULL == keywords[max])
-           goto CLEANUP;          
-          dup[i] = '\0';
-        }
+      saw_quote = (saw_quote + 1) % 2;
+      i += 3;
+      continue;
     }
     }
+    if ((dup[i] == '+') && (saw_quote == 0))
+    {
+      keywords[--max] = percent_decode_keyword (&dup[i + 1], emsg);
+      if (NULL == keywords[max])
+        goto CLEANUP;
+      dup[i] = '\0';
+    }
+  }
   keywords[--max] = percent_decode_keyword (&dup[pos], emsg);
   if (NULL == keywords[max])
     goto CLEANUP;
   GNUNET_assert (max == 0);
   GNUNET_free (dup);
   keywords[--max] = percent_decode_keyword (&dup[pos], emsg);
   if (NULL == keywords[max])
     goto CLEANUP;
   GNUNET_assert (max == 0);
   GNUNET_free (dup);
-  ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
+  ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
   ret->type = ksk;
   ret->data.ksk.keywordCount = iret;
   ret->data.ksk.keywords = keywords;
   ret->type = ksk;
   ret->data.ksk.keywordCount = iret;
   ret->data.ksk.keywords = keywords;
@@ -337,6 +336,8 @@ CLEANUP:
 }
 
 
 }
 
 
+#define GNUNET_FS_URI_SKS_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX
+
 /**
  * Parse an SKS URI.
  *
 /**
  * Parse an SKS URI.
  *
@@ -352,36 +353,37 @@ uri_sks_parse (const char *s, char **emsg)
   char *identifier;
   unsigned int pos;
   size_t slen;
   char *identifier;
   unsigned int pos;
   size_t slen;
-  char enc[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)];
+  char enc[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)];
 
   GNUNET_assert (s != NULL);
   slen = strlen (s);
 
   GNUNET_assert (s != NULL);
   slen = strlen (s);
-  pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX);
-  if ( (slen <= pos) ||
-       (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX, 
-                     pos) ) )
-    return NULL; /* not an SKS URI */
-  if ( (slen < pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
-       (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '/') )
-    {
-      *emsg = GNUNET_strdup (_("Malformed SKS URI"));
-      return NULL;
-    }
-  memcpy (enc, &s[pos], sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
-  enc[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)-1] = '\0';
+  pos = strlen (GNUNET_FS_URI_SKS_PREFIX);
+  if ((slen <= pos) || (0 != strncmp (s, GNUNET_FS_URI_SKS_PREFIX, pos)))
+    return NULL;                /* not an SKS URI */
+  if ((slen < pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) ||
+      (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '/'))
+  {
+    *emsg = GNUNET_strdup (_("Malformed SKS URI"));
+    return NULL;
+  }
+  memcpy (enc, &s[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
+  enc[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
   if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (enc, &namespace))
   if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (enc, &namespace))
-    {
-      *emsg = GNUNET_strdup (_("Malformed SKS URI"));
-      return NULL;
-    }
-  identifier = GNUNET_strdup (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)]);
-  ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
+  {
+    *emsg = GNUNET_strdup (_("Malformed SKS URI"));
+    return NULL;
+  }
+  identifier =
+      GNUNET_strdup (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)]);
+  ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
   ret->type = sks;
   ret->data.sks.namespace = namespace;
   ret->data.sks.identifier = identifier;
   return ret;
 }
 
   ret->type = sks;
   ret->data.sks.namespace = namespace;
   ret->data.sks.identifier = identifier;
   return ret;
 }
 
+#define GNUNET_FS_URI_CHK_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX
+
 
 /**
  * Parse a CHK URI.
 
 /**
  * Parse a CHK URI.
@@ -398,45 +400,40 @@ uri_chk_parse (const char *s, char **emsg)
   unsigned int pos;
   unsigned long long flen;
   size_t slen;
   unsigned int pos;
   unsigned long long flen;
   size_t slen;
-  char h1[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)];
-  char h2[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)];
+  char h1[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)];
+  char h2[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)];
 
 
+  if (NULL == s)
+    return NULL;
   GNUNET_assert (s != NULL);
   GNUNET_assert (s != NULL);
-
   slen = strlen (s);
   slen = strlen (s);
-  pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX);
-  if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
-       (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX, 
-                     pos) ) )
-    return NULL; /* not a CHK URI */
-  if ( (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
-       (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.') )
-    {
-      *emsg = GNUNET_strdup (_("Malformed CHK URI"));
-      return NULL;
-    }
-  memcpy (h1,
-         &s[pos], 
-         sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
-  h1[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)-1] = '\0';
-  memcpy (h2,
-         &s[pos + sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)],
-         sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
-  h2[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)-1] = '\0';
-  
-  if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h1,
-                                              &fi.chk.key)) ||
-      (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h2,
-                                              &fi.chk.query)) ||
-      (1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2],
-                    "%llu", 
-                   &flen)) )
-    {
-      *emsg = GNUNET_strdup (_("Malformed CHK URI"));
-      return NULL;
-    }
+  pos = strlen (GNUNET_FS_URI_CHK_PREFIX);
+  if ((slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
+      (0 != strncmp (s, GNUNET_FS_URI_CHK_PREFIX, pos)))
+    return NULL;                /* not a CHK URI */
+  if ((s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
+      (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.'))
+  {
+    *emsg = GNUNET_strdup (_("Malformed CHK URI"));
+    return NULL;
+  }
+  memcpy (h1, &s[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
+  h1[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
+  memcpy (h2, &s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)],
+          sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
+  h2[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
+
+  if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h1, &fi.chk.key)) ||
+      (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h2, &fi.chk.query)) ||
+      (1 !=
+       SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2],
+               "%llu", &flen)))
+  {
+    *emsg = GNUNET_strdup (_("Malformed CHK URI"));
+    return NULL;
+  }
   fi.file_length = GNUNET_htonll (flen);
   fi.file_length = GNUNET_htonll (flen);
-  ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
+  ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
   ret->type = chk;
   ret->data.chk = fi;
   return ret;
   ret->type = chk;
   ret->data.chk = fi;
   return ret;
@@ -470,7 +467,7 @@ c2v (unsigned char a)
 /**
  * Convert string back to binary data.
  *
 /**
  * Convert string back to binary data.
  *
- * @param input '\0'-terminated string
+ * @param input '\\0'-terminated string
  * @param data where to write binary data
  * @param size how much data should be converted
  * @return number of characters processed from input,
  * @param data where to write binary data
  * @param size how much data should be converted
  * @return number of characters processed from input,
@@ -492,18 +489,17 @@ enc2bin (const char *input, void *data, size_t size)
   bits = 0;
   hbits = 0;
   len = 0;
   bits = 0;
   hbits = 0;
   len = 0;
-  pos = 0;
   for (pos = 0; pos < size; pos++)
   for (pos = 0; pos < size; pos++)
+  {
+    while (hbits < 8)
     {
     {
-      while (hbits < 8)
-        {
-          bits |= (c2v (input[len++]) << hbits);
-          hbits += 6;
-        }
-      (((unsigned char *) data)[pos]) = (unsigned char) bits;
-      bits >>= 8;
-      hbits -= 8;
+      bits |= (c2v (input[len++]) << hbits);
+      hbits += 6;
     }
     }
+    (((unsigned char *) data)[pos]) = (unsigned char) bits;
+    bits >>= 8;
+    hbits -= 8;
+  }
   return len;
 }
 
   return len;
 }
 
@@ -515,19 +511,21 @@ enc2bin (const char *input, void *data, size_t size)
  * verify the signature of a location
  * URI.
  */
  * verify the signature of a location
  * URI.
  */
-struct LocUriAssembly 
+struct LocUriAssembly
 {
   struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
 
   struct GNUNET_TIME_AbsoluteNBO exptime;
 
   struct FileIdentifier fi;
 {
   struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
 
   struct GNUNET_TIME_AbsoluteNBO exptime;
 
   struct FileIdentifier fi;
-  
+
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded peer;
 
 };
 
 
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded peer;
 
 };
 
 
+#define GNUNET_FS_URI_LOC_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX
+
 /**
  * Parse a LOC URI.
  * Also verifies validity of the location URI.
 /**
  * Parse a LOC URI.
  * Also verifies validity of the location URI.
@@ -540,8 +538,8 @@ static struct GNUNET_FS_Uri *
 uri_loc_parse (const char *s, char **emsg)
 {
   struct GNUNET_FS_Uri *uri;
 uri_loc_parse (const char *s, char **emsg)
 {
   struct GNUNET_FS_Uri *uri;
-  char h1[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)];
-  char h2[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)];
+  char h1[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)];
+  char h2[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)];
   unsigned int pos;
   unsigned int npos;
   unsigned long long exptime;
   unsigned int pos;
   unsigned int npos;
   unsigned long long exptime;
@@ -554,95 +552,89 @@ uri_loc_parse (const char *s, char **emsg)
 
   GNUNET_assert (s != NULL);
   slen = strlen (s);
 
   GNUNET_assert (s != NULL);
   slen = strlen (s);
-  pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX);
-  if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
-       (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX, 
-                     pos) ) )
-    return NULL; /* not an SKS URI */
-  if ( (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
-       (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.') )
-    {
-      *emsg = GNUNET_strdup (_("SKS URI malformed"));
-      return NULL;
-    }
-  memcpy (h1,
-         &s[pos], 
-         sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
-  h1[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)-1] = '\0';
-  memcpy (h2,
-         &s[pos + sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)],
-         sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
-  h2[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)-1] = '\0';
-  
-  if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h1,
-                                                   &ass.fi.chk.key)) ||
-      (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h2,
-                                                   &ass.fi.chk.query)) ||
-      (1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2],
-                    "%llu", 
-                   &flen)) )
-    {
-      *emsg = GNUNET_strdup (_("SKS URI malformed"));
-      return NULL;
-    }
+  pos = strlen (GNUNET_FS_URI_LOC_PREFIX);
+  if ((slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
+      (0 != strncmp (s, GNUNET_FS_URI_LOC_PREFIX, pos)))
+    return NULL;                /* not an SKS URI */
+  if ((s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
+      (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.'))
+  {
+    *emsg = GNUNET_strdup (_("SKS URI malformed"));
+    return NULL;
+  }
+  memcpy (h1, &s[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
+  h1[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
+  memcpy (h2, &s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)],
+          sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
+  h2[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
+
+  if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h1, &ass.fi.chk.key)) ||
+      (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h2, &ass.fi.chk.query)) ||
+      (1 !=
+       SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2],
+               "%llu", &flen)))
+  {
+    *emsg = GNUNET_strdup (_("SKS URI malformed"));
+    return NULL;
+  }
   ass.fi.file_length = GNUNET_htonll (flen);
 
   npos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2;
   while ((s[npos] != '\0') && (s[npos] != '.'))
     npos++;
   if (s[npos] == '\0')
   ass.fi.file_length = GNUNET_htonll (flen);
 
   npos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2;
   while ((s[npos] != '\0') && (s[npos] != '.'))
     npos++;
   if (s[npos] == '\0')
-    {
-      *emsg = GNUNET_strdup (_("SKS URI malformed"));
-      goto ERR;
-    }
+  {
+    *emsg = GNUNET_strdup (_("SKS URI malformed"));
+    goto ERR;
+  }
   npos++;
   npos++;
-  ret = enc2bin (&s[npos], 
-                &ass.peer,
-                sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
+  ret =
+      enc2bin (&s[npos], &ass.peer,
+               sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
   if (ret == -1)
   if (ret == -1)
-    {
-      *emsg = GNUNET_strdup (_("SKS URI malformed (could not decode public key)"));
-      goto ERR;
-    }
+  {
+    *emsg =
+        GNUNET_strdup (_("SKS URI malformed (could not decode public key)"));
+    goto ERR;
+  }
   npos += ret;
   if (s[npos++] != '.')
   npos += ret;
   if (s[npos++] != '.')
-    {
-      *emsg = GNUNET_strdup (_("SKS URI malformed (could not find signature)"));
-      goto ERR;
-    }
-  ret = enc2bin (&s[npos],
-                &sig,
-                sizeof (struct GNUNET_CRYPTO_RsaSignature));
+  {
+    *emsg = GNUNET_strdup (_("SKS URI malformed (could not find signature)"));
+    goto ERR;
+  }
+  ret = enc2bin (&s[npos], &sig, sizeof (struct GNUNET_CRYPTO_RsaSignature));
   if (ret == -1)
   if (ret == -1)
-    {
-      *emsg = GNUNET_strdup (_("SKS URI malformed (could not decode signature)"));
-      goto ERR;
-    }
-    npos += ret;
+  {
+    *emsg = GNUNET_strdup (_("SKS URI malformed (could not decode signature)"));
+    goto ERR;
+  }
+  npos += ret;
   if (s[npos++] != '.')
   if (s[npos++] != '.')
-    {
-      *emsg = GNUNET_strdup (_("SKS URI malformed"));
-      goto ERR;
-    }
+  {
+    *emsg = GNUNET_strdup (_("SKS URI malformed"));
+    goto ERR;
+  }
   if (1 != SSCANF (&s[npos], "%llu", &exptime))
   if (1 != SSCANF (&s[npos], "%llu", &exptime))
-    {
-      *emsg = GNUNET_strdup (_("SKS URI malformed (could not parse expiration time)"));
-      goto ERR;
-    }
-  ass.purpose.size = htonl(sizeof(struct LocUriAssembly));
-  ass.purpose.purpose = htonl(GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT);
-  et.value = exptime;
+  {
+    *emsg =
+        GNUNET_strdup (_
+                       ("SKS URI malformed (could not parse expiration time)"));
+    goto ERR;
+  }
+  ass.purpose.size = htonl (sizeof (struct LocUriAssembly));
+  ass.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT);
+  et.abs_value = exptime;
   ass.exptime = GNUNET_TIME_absolute_hton (et);
   ass.exptime = GNUNET_TIME_absolute_hton (et);
-  if (GNUNET_OK != 
+  if (GNUNET_OK !=
       GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT,
       GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT,
-                               &ass.purpose,
-                               &sig,
-                               &ass.peer))
-    {
-      *emsg = GNUNET_strdup (_("SKS URI malformed (signature failed validation)"));
-      goto ERR;
-    }
-  uri = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
+                                &ass.purpose, &sig, &ass.peer))
+  {
+    *emsg =
+        GNUNET_strdup (_("SKS URI malformed (signature failed validation)"));
+    goto ERR;
+  }
+  uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
   uri->type = loc;
   uri->data.loc.fi = ass.fi;
   uri->data.loc.peer = ass.peer;
   uri->type = loc;
   uri->data.loc.fi = ass.fi;
   uri->data.loc.peer = ass.peer;
@@ -663,8 +655,7 @@ ERR:
  * @return NULL on error
  */
 struct GNUNET_FS_Uri *
  * @return NULL on error
  */
 struct GNUNET_FS_Uri *
-GNUNET_FS_uri_parse (const char *uri,
-                    char **emsg)
+GNUNET_FS_uri_parse (const char *uri, char **emsg)
 {
   struct GNUNET_FS_Uri *ret;
   char *msg;
 {
   struct GNUNET_FS_Uri *ret;
   char *msg;
@@ -672,10 +663,10 @@ GNUNET_FS_uri_parse (const char *uri,
   if (NULL == emsg)
     emsg = &msg;
   *emsg = NULL;
   if (NULL == emsg)
     emsg = &msg;
   *emsg = NULL;
-  if ( (NULL != (ret = uri_chk_parse (uri, emsg))) ||
-       (NULL != (ret = uri_ksk_parse (uri, emsg))) ||
-       (NULL != (ret = uri_sks_parse (uri, emsg))) ||
-       (NULL != (ret = uri_loc_parse (uri, emsg))) )
+  if ((NULL != (ret = uri_chk_parse (uri, emsg))) ||
+      (NULL != (ret = uri_ksk_parse (uri, emsg))) ||
+      (NULL != (ret = uri_sks_parse (uri, emsg))) ||
+      (NULL != (ret = uri_loc_parse (uri, emsg))))
     return ret;
   if (NULL == *emsg)
     *emsg = GNUNET_strdup (_("Unrecognized URI type"));
     return ret;
   if (NULL == *emsg)
     *emsg = GNUNET_strdup (_("Unrecognized URI type"));
@@ -690,29 +681,28 @@ GNUNET_FS_uri_parse (const char *uri,
  *
  * @param uri uri to free
  */
  *
  * @param uri uri to free
  */
-void 
+void
 GNUNET_FS_uri_destroy (struct GNUNET_FS_Uri *uri)
 {
   unsigned int i;
 
   GNUNET_assert (uri != NULL);
   switch (uri->type)
 GNUNET_FS_uri_destroy (struct GNUNET_FS_Uri *uri)
 {
   unsigned int i;
 
   GNUNET_assert (uri != NULL);
   switch (uri->type)
-    {
-    case ksk:
-      for (i = 0; i < uri->data.ksk.keywordCount; i++)
-        GNUNET_free (uri->data.ksk.keywords[i]);
-      GNUNET_array_grow (uri->data.ksk.keywords, uri->data.ksk.keywordCount,
-                         0);
-      break;
-    case sks:
-      GNUNET_free (uri->data.sks.identifier);
-      break;
-    case loc:
-      break;
-    default:
-      /* do nothing */
-      break;
-    }
+  {
+  case ksk:
+    for (i = 0; i < uri->data.ksk.keywordCount; i++)
+      GNUNET_free (uri->data.ksk.keywords[i]);
+    GNUNET_array_grow (uri->data.ksk.keywords, uri->data.ksk.keywordCount, 0);
+    break;
+  case sks:
+    GNUNET_free (uri->data.sks.identifier);
+    break;
+  case loc:
+    break;
+  default:
+    /* do nothing */
+    break;
+  }
   GNUNET_free (uri);
 }
 
   GNUNET_free (uri);
 }
 
@@ -722,7 +712,7 @@ GNUNET_FS_uri_destroy (struct GNUNET_FS_Uri *uri)
  * @param uri ksk uri to get the number of keywords from
  * @return 0 if this is not a keyword URI
  */
  * @param uri ksk uri to get the number of keywords from
  * @return 0 if this is not a keyword URI
  */
-unsigned int 
+unsigned int
 GNUNET_FS_uri_ksk_get_keyword_count (const struct GNUNET_FS_Uri *uri)
 {
   if (uri->type != ksk)
 GNUNET_FS_uri_ksk_get_keyword_count (const struct GNUNET_FS_Uri *uri)
 {
   if (uri->type != ksk)
@@ -740,10 +730,10 @@ GNUNET_FS_uri_ksk_get_keyword_count (const struct GNUNET_FS_Uri *uri)
  * @return -1 if this is not a keyword URI, otherwise number of
  *   keywords iterated over until iterator aborted
  */
  * @return -1 if this is not a keyword URI, otherwise number of
  *   keywords iterated over until iterator aborted
  */
-int 
+int
 GNUNET_FS_uri_ksk_get_keywords (const struct GNUNET_FS_Uri *uri,
 GNUNET_FS_uri_ksk_get_keywords (const struct GNUNET_FS_Uri *uri,
-                               GNUNET_FS_KeywordIterator iterator, 
-                               void *iterator_cls)
+                                GNUNET_FS_KeywordIterator iterator,
+                                void *iterator_cls)
 {
   unsigned int i;
   char *keyword;
 {
   unsigned int i;
   char *keyword;
@@ -753,16 +743,73 @@ GNUNET_FS_uri_ksk_get_keywords (const struct GNUNET_FS_Uri *uri,
   if (iterator == NULL)
     return uri->data.ksk.keywordCount;
   for (i = 0; i < uri->data.ksk.keywordCount; i++)
   if (iterator == NULL)
     return uri->data.ksk.keywordCount;
   for (i = 0; i < uri->data.ksk.keywordCount; i++)
+  {
+    keyword = uri->data.ksk.keywords[i];
+    /* first character of keyword indicates
+     * if it is mandatory or not */
+    if (GNUNET_OK != iterator (iterator_cls, &keyword[1], keyword[0] == '+'))
+      return i;
+  }
+  return i;
+}
+
+
+/**
+ * Add the given keyword to the set of keywords represented by the URI.
+ * Does nothing if the keyword is already present.
+ *
+ * @param uri ksk uri to modify
+ * @param keyword keyword to add
+ * @param is_mandatory is this keyword mandatory?
+ */
+void
+GNUNET_FS_uri_ksk_add_keyword (struct GNUNET_FS_Uri *uri, const char *keyword,
+                               int is_mandatory)
+{
+  unsigned int i;
+  const char *old;
+  char *n;
+
+  GNUNET_assert (uri->type == ksk);
+  for (i = 0; i < uri->data.ksk.keywordCount; i++)
+  {
+    old = uri->data.ksk.keywords[i];
+    if (0 == strcmp (&old[1], keyword))
+      return;
+  }
+  GNUNET_asprintf (&n, is_mandatory ? "+%s" : " %s", keyword);
+  GNUNET_array_append (uri->data.ksk.keywords, uri->data.ksk.keywordCount, n);
+}
+
+
+/**
+ * Remove the given keyword from the set of keywords represented by the URI.
+ * Does nothing if the keyword is not present.
+ *
+ * @param uri ksk uri to modify
+ * @param keyword keyword to add
+ */
+void
+GNUNET_FS_uri_ksk_remove_keyword (struct GNUNET_FS_Uri *uri,
+                                  const char *keyword)
+{
+  unsigned int i;
+  char *old;
+
+  GNUNET_assert (uri->type == ksk);
+  for (i = 0; i < uri->data.ksk.keywordCount; i++)
+  {
+    old = uri->data.ksk.keywords[i];
+    if (0 == strcmp (&old[1], keyword))
     {
     {
-      keyword = uri->data.ksk.keywords[i];
-      /* first character of keyword indicates
-         if it is mandatory or not */
-      if (GNUNET_OK != iterator (iterator_cls,
-                                &keyword[1],
-                                keyword[0] == '+'))
-        return i;
+      uri->data.ksk.keywords[i] =
+          uri->data.ksk.keywords[uri->data.ksk.keywordCount - 1];
+      GNUNET_array_grow (uri->data.ksk.keywords, uri->data.ksk.keywordCount,
+                         uri->data.ksk.keywordCount - 1);
+      GNUNET_free (old);
+      return;
     }
     }
-  return i;
+  }
 }
 
 
 }
 
 
@@ -775,17 +822,32 @@ GNUNET_FS_uri_ksk_get_keywords (const struct GNUNET_FS_Uri *uri,
  */
 int
 GNUNET_FS_uri_loc_get_peer_identity (const struct GNUNET_FS_Uri *uri,
  */
 int
 GNUNET_FS_uri_loc_get_peer_identity (const struct GNUNET_FS_Uri *uri,
-                                    struct GNUNET_PeerIdentity * peer)
+                                     struct GNUNET_PeerIdentity *peer)
 {
   if (uri->type != loc)
     return GNUNET_SYSERR;
   GNUNET_CRYPTO_hash (&uri->data.loc.peer,
 {
   if (uri->type != loc)
     return GNUNET_SYSERR;
   GNUNET_CRYPTO_hash (&uri->data.loc.peer,
-                     sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                     &peer->hashPubKey);
+                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                      &peer->hashPubKey);
   return GNUNET_OK;
 }
 
 
   return GNUNET_OK;
 }
 
 
+/**
+ * Obtain the expiration of the LOC URI.
+ *
+ * @param uri location URI to get the expiration from
+ * @return expiration time of the URI
+ */
+struct GNUNET_TIME_Absolute
+GNUNET_FS_uri_loc_get_expiration (const struct GNUNET_FS_Uri *uri)
+{
+  GNUNET_assert (uri->type == loc);
+  return uri->data.loc.expirationTime;
+}
+
+
+
 /**
  * Obtain the URI of the content itself.
  *
 /**
  * Obtain the URI of the content itself.
  *
@@ -809,18 +871,18 @@ GNUNET_FS_uri_loc_get_uri (const struct GNUNET_FS_Uri *uri)
 /**
  * Construct a location URI (this peer will be used for the location).
  *
 /**
  * Construct a location URI (this peer will be used for the location).
  *
- * @param baseURI content offered by the sender
+ * @param baseUri content offered by the sender
  * @param cfg configuration information (used to find our hostkey)
  * @param expiration_time how long will the content be offered?
  * @return the location URI, NULL on error
  */
 struct GNUNET_FS_Uri *
 GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *baseUri,
  * @param cfg configuration information (used to find our hostkey)
  * @param expiration_time how long will the content be offered?
  * @return the location URI, NULL on error
  */
 struct GNUNET_FS_Uri *
 GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *baseUri,
-                         struct GNUNET_CONFIGURATION_Handle *cfg,
-                         struct GNUNET_TIME_Absolute expiration_time)
+                          const struct GNUNET_CONFIGURATION_Handle *cfg,
+                          struct GNUNET_TIME_Absolute expiration_time)
 {
   struct GNUNET_FS_Uri *uri;
 {
   struct GNUNET_FS_Uri *uri;
-  struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;  
+  struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
   char *keyfile;
   struct LocUriAssembly ass;
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
   char *keyfile;
   struct LocUriAssembly ass;
@@ -828,28 +890,25 @@ GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *baseUri,
   if (baseUri->type != chk)
     return NULL;
   if (GNUNET_OK !=
   if (baseUri->type != chk)
     return NULL;
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (cfg,
-                                              "GNUNETD",
-                                              "HOSTKEY", &keyfile))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  _
-                  ("Lacking key configuration settings.\n"));
-      return NULL;
-    }
+      GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY",
+                                               &keyfile))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Lacking key configuration settings.\n"));
+    return NULL;
+  }
   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
   if (my_private_key == NULL)
   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
   if (my_private_key == NULL)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  _("Could not access hostkey file `%s'.\n"),
-                 keyfile);
-      GNUNET_free (keyfile);
-      return NULL;
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Could not access hostkey file `%s'.\n"), keyfile);
+    GNUNET_free (keyfile);
+    return NULL;
+  }
   GNUNET_free (keyfile);
   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
   GNUNET_free (keyfile);
   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
-  ass.purpose.size = htonl(sizeof(struct LocUriAssembly));
-  ass.purpose.purpose = htonl(GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT);
+  ass.purpose.size = htonl (sizeof (struct LocUriAssembly));
+  ass.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT);
   ass.exptime = GNUNET_TIME_absolute_hton (expiration_time);
   ass.fi = baseUri->data.chk;
   ass.peer = my_public_key;
   ass.exptime = GNUNET_TIME_absolute_hton (expiration_time);
   ass.fi = baseUri->data.chk;
   ass.peer = my_public_key;
@@ -859,17 +918,60 @@ GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *baseUri,
   uri->data.loc.expirationTime = expiration_time;
   uri->data.loc.peer = my_public_key;
   GNUNET_assert (GNUNET_OK ==
   uri->data.loc.expirationTime = expiration_time;
   uri->data.loc.peer = my_public_key;
   GNUNET_assert (GNUNET_OK ==
-                GNUNET_CRYPTO_rsa_sign (my_private_key,
-                                        &ass.purpose,
-                                        &uri->data.loc.contentSignature));
+                 GNUNET_CRYPTO_rsa_sign (my_private_key, &ass.purpose,
+                                         &uri->data.loc.contentSignature));
   GNUNET_CRYPTO_rsa_key_free (my_private_key);
   return uri;
 }
 
 
   GNUNET_CRYPTO_rsa_key_free (my_private_key);
   return uri;
 }
 
 
+/**
+ * Create an SKS URI from a namespace and an identifier.
+ *
+ * @param ns namespace
+ * @param id identifier
+ * @param emsg where to store an error message
+ * @return an FS URI for the given namespace and identifier
+ */
+struct GNUNET_FS_Uri *
+GNUNET_FS_uri_sks_create (struct GNUNET_FS_Namespace *ns, const char *id,
+                          char **emsg)
+{
+  struct GNUNET_FS_Uri *ns_uri;
+  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
+
+  ns_uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
+  ns_uri->type = sks;
+  GNUNET_CRYPTO_rsa_key_get_public (ns->key, &pk);
+  GNUNET_CRYPTO_hash (&pk, sizeof (pk), &ns_uri->data.sks.namespace);
+  ns_uri->data.sks.identifier = GNUNET_strdup (id);
+  return ns_uri;
+}
+
+
+/**
+ * Create an SKS URI from a namespace ID and an identifier.
+ *
+ * @param nsid namespace ID
+ * @param id identifier
+ * @return an FS URI for the given namespace and identifier
+ */
+struct GNUNET_FS_Uri *
+GNUNET_FS_uri_sks_create_from_nsid (GNUNET_HashCode * nsid, const char *id)
+{
+  struct GNUNET_FS_Uri *ns_uri;
+
+  ns_uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
+  ns_uri->type = sks;
+  ns_uri->data.sks.namespace = *nsid;
+  ns_uri->data.sks.identifier = GNUNET_strdup (id);
+  return ns_uri;
+}
+
+
 /**
  * Canonicalize a keyword.
 /**
  * Canonicalize a keyword.
- * 
+ *
  * @param in input string (the keyword)
  * @return canonicalized keyword
  */
  * @param in input string (the keyword)
  * @return canonicalized keyword
  */
@@ -884,58 +986,63 @@ canonicalize_keyword (const char *in)
   wpos = ret;
   rpos = in;
   while ('\0' != *rpos)
   wpos = ret;
   rpos = in;
   while ('\0' != *rpos)
+  {
+    switch (tolower ((unsigned char) *rpos))
     {
     {
-      switch (tolower(*rpos))
-       {
-       case 'a':
-       case 'e':
-       case 'i':
-       case 'o':
-       case 'u':
-       case ' ':
-       case '\t':
-       case '\n':
-       case '\r':
-         /* skip characters listed above */
-         rpos++;
-         break;
-       case 'b':
-       case 'c':
-       case 'd':
-       case 'f':
-       case 'g':
-       case 'h':
-       case 'j':
-       case 'k':
-       case 'l':
-       case 'm':
-       case 'n':
-       case 'p':
-       case 'r':
-       case 's':
-       case 't':
-       case 'v':
-       case 'w':
-       case 'x':
-       case 'y':
-       case 'z':
-         /* convert characters listed above to lower case */
-         *wpos = tolower(*rpos);
-         wpos++;
-       case '!':
-       case '.':
-       case '?':
-       case '-':
-         /* keep characters listed above without changes */
-         *wpos = *rpos;
-         wpos++;
-       default:
-         /* replace characters listed above with '_' */
-         *wpos = '_';
-         wpos++;
-       }
-      rpos++;
+    case 'a':
+    case 'e':
+    case 'i':
+    case 'o':
+    case 'u':
+    case ' ':
+    case '\t':
+    case '\n':
+    case '\r':
+      /* skip characters listed above */
+      break;
+    case 'b':
+    case 'c':
+    case 'd':
+    case 'f':
+    case 'g':
+    case 'h':
+    case 'j':
+    case 'k':
+    case 'l':
+    case 'm':
+    case 'n':
+    case 'p':
+    case 'r':
+    case 's':
+    case 't':
+    case 'v':
+    case 'w':
+    case 'x':
+    case 'y':
+    case 'z':
+      /* convert characters listed above to lower case */
+      *wpos = tolower ((unsigned char) *rpos);
+      wpos++;
+      break;
+    case '!':
+    case '.':
+    case '?':
+    case '-':
+      /* keep characters listed above without changes */
+      *wpos = *rpos;
+      wpos++;
+      break;
+    default:
+      if (isspace ((unsigned char) *rpos) || isdigit ((unsigned char) *rpos))
+        break;
+      /* replace characters listed above with '_' */
+      *wpos = '_';
+      wpos++;
+      break;
     }
     }
+    rpos++;
+  }
+  *wpos = '\0';
   return ret;
 }
 
   return ret;
 }
 
@@ -945,7 +1052,7 @@ canonicalize_keyword (const char *in)
  * as decapitalization and removal of certain characters.
  * (useful for search).
  *
  * as decapitalization and removal of certain characters.
  * (useful for search).
  *
- * @param uri the URI to canonicalize 
+ * @param uri the URI to canonicalize
  * @return canonicalized version of the URI, NULL on error
  */
 struct GNUNET_FS_Uri *
  * @return canonicalized version of the URI, NULL on error
  */
 struct GNUNET_FS_Uri *
@@ -954,16 +1061,33 @@ GNUNET_FS_uri_ksk_canonicalize (const struct GNUNET_FS_Uri *uri)
   struct GNUNET_FS_Uri *ret;
   unsigned int kc;
   unsigned int i;
   struct GNUNET_FS_Uri *ret;
   unsigned int kc;
   unsigned int i;
-  char **kl;
+  const char *in;
+  char *sb;
+  char *cc;
+  const char *tok;
 
 
-  kc = uri->data.ksk.keywordCount;
-  kl = GNUNET_malloc (kc*sizeof(char*));
-  for (i=0;i<kc;i++)
-    kl[i] = canonicalize_keyword (uri->data.ksk.keywords[i]);
-  ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
+  ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
   ret->type = ksk;
   ret->type = ksk;
-  ret->data.ksk.keywordCount = kc;
-  ret->data.ksk.keywords = kl;
+  kc = uri->data.ksk.keywordCount;
+  for (i = 0; i < kc; i++)
+  {
+    in = uri->data.ksk.keywords[i];
+    GNUNET_FS_uri_ksk_add_keyword (ret, &in[1],
+                                   (in[0] == '+') ? GNUNET_YES : GNUNET_NO);
+    sb = GNUNET_strdup (&in[1]);
+#define DELIMS " \\|\"'`/&@-_,.;!?+-*^$#~=[]{}()<>"
+    for (tok = strtok (sb, DELIMS); NULL != tok; tok = strtok (NULL, DELIMS))
+#undef DELIMS
+    {
+      if (strlen (tok) < 3)
+        continue;
+      GNUNET_FS_uri_ksk_add_keyword (ret, tok, GNUNET_NO);
+      cc = canonicalize_keyword (tok);
+      if (strlen (cc) > 2)
+        GNUNET_FS_uri_ksk_add_keyword (ret, cc, GNUNET_NO);
+    }
+    GNUNET_free (sb);
+  }
   return ret;
 }
 
   return ret;
 }
 
@@ -979,7 +1103,7 @@ GNUNET_FS_uri_ksk_canonicalize (const struct GNUNET_FS_Uri *uri)
  */
 struct GNUNET_FS_Uri *
 GNUNET_FS_uri_ksk_merge (const struct GNUNET_FS_Uri *u1,
  */
 struct GNUNET_FS_Uri *
 GNUNET_FS_uri_ksk_merge (const struct GNUNET_FS_Uri *u1,
-                        const struct GNUNET_FS_Uri *u2)
+                         const struct GNUNET_FS_Uri *u2)
 {
   struct GNUNET_FS_Uri *ret;
   unsigned int kc;
 {
   struct GNUNET_FS_Uri *ret;
   unsigned int kc;
@@ -989,33 +1113,37 @@ GNUNET_FS_uri_ksk_merge (const struct GNUNET_FS_Uri *u1,
   const char *kp;
   char **kl;
 
   const char *kp;
   char **kl;
 
-  if ( (u1->type != ksk) ||
-       (u2->type != ksk) )
-    {
-      GNUNET_break (0);
-      return NULL;
-    } 
+  if ((u1 == NULL) && (u2 == NULL))
+    return NULL;
+  if (u1 == NULL)
+    return GNUNET_FS_uri_dup (u2);
+  if (u2 == NULL)
+    return GNUNET_FS_uri_dup (u1);
+  if ((u1->type != ksk) || (u2->type != ksk))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
   kc = u1->data.ksk.keywordCount;
   kc = u1->data.ksk.keywordCount;
-  kl = GNUNET_malloc ((kc+u2->data.ksk.keywordCount)*sizeof(char*));
-  for (i=0;i<u1->data.ksk.keywordCount;i++)
+  kl = GNUNET_malloc ((kc + u2->data.ksk.keywordCount) * sizeof (char *));
+  for (i = 0; i < u1->data.ksk.keywordCount; i++)
     kl[i] = GNUNET_strdup (u1->data.ksk.keywords[i]);
     kl[i] = GNUNET_strdup (u1->data.ksk.keywords[i]);
-  for (i=0;i<u2->data.ksk.keywordCount;i++)
-    {
-      kp = u2->data.ksk.keywords[i];
-      found = 0;
-      for (j=0;j<u1->data.ksk.keywordCount;j++)
-       if (0 == strcmp(kp + 1,
-                       kl[j]+1))
-         {
-           found = 1;
-           if (kp[0] == '+')
-             kl[j][0] = '+';
-           break;
-         }
-      if (0 == found)
-       kl[kc++] = GNUNET_strdup (kp - 1);
-    }
-  ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
+  for (i = 0; i < u2->data.ksk.keywordCount; i++)
+  {
+    kp = u2->data.ksk.keywords[i];
+    found = 0;
+    for (j = 0; j < u1->data.ksk.keywordCount; j++)
+      if (0 == strcmp (kp + 1, kl[j] + 1))
+      {
+        found = 1;
+        if (kp[0] == '+')
+          kl[j][0] = '+';
+        break;
+      }
+    if (0 == found)
+      kl[kc++] = GNUNET_strdup (kp);
+  }
+  ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
   ret->type = ksk;
   ret->data.ksk.keywordCount = kc;
   ret->data.ksk.keywords = kl;
   ret->type = ksk;
   ret->data.ksk.keywordCount = kc;
   ret->data.ksk.keywords = kl;
@@ -1035,30 +1163,38 @@ GNUNET_FS_uri_dup (const struct GNUNET_FS_Uri *uri)
   struct GNUNET_FS_Uri *ret;
   unsigned int i;
 
   struct GNUNET_FS_Uri *ret;
   unsigned int i;
 
+  if (uri == NULL)
+    return NULL;
   ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
   memcpy (ret, uri, sizeof (struct GNUNET_FS_Uri));
   switch (ret->type)
   ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
   memcpy (ret, uri, sizeof (struct GNUNET_FS_Uri));
   switch (ret->type)
+  {
+  case ksk:
+    if (ret->data.ksk.keywordCount >=
+        GNUNET_MAX_MALLOC_CHECKED / sizeof (char *))
     {
     {
-    case ksk:
-      if (ret->data.ksk.keywordCount > 0)
-        {
-          ret->data.ksk.keywords
-            = GNUNET_malloc (ret->data.ksk.keywordCount * sizeof (char *));
-          for (i = 0; i < ret->data.ksk.keywordCount; i++)
-            ret->data.ksk.keywords[i] =
-              GNUNET_strdup (uri->data.ksk.keywords[i]);
-        }
-      else
-        ret->data.ksk.keywords = NULL;  /* just to be sure */
-      break;
-    case sks:
-      ret->data.sks.identifier = GNUNET_strdup (uri->data.sks.identifier);
-      break;
-    case loc:
-      break;
-    default:
-      break;
+      GNUNET_break (0);
+      GNUNET_free (ret);
+      return NULL;
+    }
+    if (ret->data.ksk.keywordCount > 0)
+    {
+      ret->data.ksk.keywords =
+          GNUNET_malloc (ret->data.ksk.keywordCount * sizeof (char *));
+      for (i = 0; i < ret->data.ksk.keywordCount; i++)
+        ret->data.ksk.keywords[i] = GNUNET_strdup (uri->data.ksk.keywords[i]);
     }
     }
+    else
+      ret->data.ksk.keywords = NULL;    /* just to be sure */
+    break;
+  case sks:
+    ret->data.sks.identifier = GNUNET_strdup (uri->data.sks.identifier);
+    break;
+  case loc:
+    break;
+  default:
+    break;
+  }
   return ret;
 }
 
   return ret;
 }
 
@@ -1081,8 +1217,7 @@ GNUNET_FS_uri_dup (const struct GNUNET_FS_Uri *uri)
  *  if keywords is not legal (i.e. empty).
  */
 struct GNUNET_FS_Uri *
  *  if keywords is not legal (i.e. empty).
  */
 struct GNUNET_FS_Uri *
-GNUNET_FS_uri_ksk_create (const char *keywords,
-                         char **emsg)
+GNUNET_FS_uri_ksk_create (const char *keywords, char **emsg)
 {
   char **keywordarr;
   unsigned int num_Words;
 {
   char **keywordarr;
   unsigned int num_Words;
@@ -1093,66 +1228,67 @@ GNUNET_FS_uri_ksk_create (const char *keywords,
   int saw_quote;
 
   if (keywords == NULL)
   int saw_quote;
 
   if (keywords == NULL)
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
+  {
+    *emsg = GNUNET_strdup (_("No keywords specified!\n"));
+    GNUNET_break (0);
+    return NULL;
+  }
   searchString = GNUNET_strdup (keywords);
   num_Words = 0;
   inWord = 0;
   saw_quote = 0;
   pos = searchString;
   while ('\0' != *pos)
   searchString = GNUNET_strdup (keywords);
   num_Words = 0;
   inWord = 0;
   saw_quote = 0;
   pos = searchString;
   while ('\0' != *pos)
+  {
+    if ((saw_quote == 0) && (isspace ((unsigned char) *pos)))
     {
     {
-      if ((saw_quote == 0) && (isspace (*pos)))
-        {
-          inWord = 0;
-        }
-      else if (0 == inWord)
-        {
-          inWord = 1;
-          ++num_Words;
-        }
-      if ('"' == *pos)
-        saw_quote = (saw_quote + 1) % 2;
-      pos++;
+      inWord = 0;
     }
     }
-  if (num_Words == 0)
+    else if (0 == inWord)
     {
     {
-      GNUNET_free (searchString);
-      *emsg = GNUNET_strdup (_("No keywords specified!\n"));
-      return NULL;
+      inWord = 1;
+      ++num_Words;
     }
     }
+    if ('"' == *pos)
+      saw_quote = (saw_quote + 1) % 2;
+    pos++;
+  }
+  if (num_Words == 0)
+  {
+    GNUNET_free (searchString);
+    *emsg = GNUNET_strdup (_("No keywords specified!\n"));
+    return NULL;
+  }
   if (saw_quote != 0)
   if (saw_quote != 0)
-    {
-      GNUNET_free (searchString);
-      *emsg = GNUNET_strdup (_("Number of double-quotes not balanced!\n"));
-      return NULL;
-    }
+  {
+    GNUNET_free (searchString);
+    *emsg = GNUNET_strdup (_("Number of double-quotes not balanced!\n"));
+    return NULL;
+  }
   keywordarr = GNUNET_malloc (num_Words * sizeof (char *));
   num_Words = 0;
   inWord = 0;
   pos = searchString;
   while ('\0' != *pos)
   keywordarr = GNUNET_malloc (num_Words * sizeof (char *));
   num_Words = 0;
   inWord = 0;
   pos = searchString;
   while ('\0' != *pos)
+  {
+    if ((saw_quote == 0) && (isspace ((unsigned char) *pos)))
     {
     {
-      if ((saw_quote == 0) && (isspace (*pos)))
-        {
-          inWord = 0;
-          *pos = '\0';
-        }
-      else if (0 == inWord)
-        {
-          keywordarr[num_Words] = pos;
-          inWord = 1;
-          ++num_Words;
-        }
-      if ('"' == *pos)
-        saw_quote = (saw_quote + 1) % 2;
-      pos++;
+      inWord = 0;
+      *pos = '\0';
+    }
+    else if (0 == inWord)
+    {
+      keywordarr[num_Words] = pos;
+      inWord = 1;
+      ++num_Words;
     }
     }
+    if ('"' == *pos)
+      saw_quote = (saw_quote + 1) % 2;
+    pos++;
+  }
   uri =
   uri =
-    GNUNET_FS_uri_ksk_create_from_args (num_Words,
-                                       (const char **) keywordarr);
+      GNUNET_FS_uri_ksk_create_from_args (num_Words,
+                                          (const char **) keywordarr);
   GNUNET_free (keywordarr);
   GNUNET_free (searchString);
   return uri;
   GNUNET_free (keywordarr);
   GNUNET_free (searchString);
   return uri;
@@ -1177,8 +1313,7 @@ GNUNET_FS_uri_ksk_create (const char *keywords,
  *  if keywords is not legal (i.e. empty).
  */
 struct GNUNET_FS_Uri *
  *  if keywords is not legal (i.e. empty).
  */
 struct GNUNET_FS_Uri *
-GNUNET_FS_uri_ksk_create_from_args (unsigned int argc,
-                                   const char **argv)
+GNUNET_FS_uri_ksk_create_from_args (unsigned int argc, const char **argv)
 {
   unsigned int i;
   struct GNUNET_FS_Uri *uri;
 {
   unsigned int i;
   struct GNUNET_FS_Uri *uri;
@@ -1191,12 +1326,12 @@ GNUNET_FS_uri_ksk_create_from_args (unsigned int argc,
   if (argc == 0)
     return NULL;
   /* allow URI to be given as one and only keyword and
   if (argc == 0)
     return NULL;
   /* allow URI to be given as one and only keyword and
-     handle accordingly */
+   * handle accordingly */
   emsg = NULL;
   emsg = NULL;
-  if ( (argc == 1) &&
-       (strlen(argv[0]) > strlen(GNUNET_FS_URI_PREFIX)) &&
-       (0 == strncmp(argv[0], GNUNET_FS_URI_PREFIX, strlen(GNUNET_FS_URI_PREFIX)) ) &&
-       (NULL != (uri = GNUNET_FS_uri_parse(argv[0], &emsg)) ) )
+  if ((argc == 1) && (strlen (argv[0]) > strlen (GNUNET_FS_URI_PREFIX)) &&
+      (0 ==
+       strncmp (argv[0], GNUNET_FS_URI_PREFIX, strlen (GNUNET_FS_URI_PREFIX)))
+      && (NULL != (uri = GNUNET_FS_uri_parse (argv[0], &emsg))))
     return uri;
   GNUNET_free_non_null (emsg);
   uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
     return uri;
   GNUNET_free_non_null (emsg);
   uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
@@ -1204,24 +1339,24 @@ GNUNET_FS_uri_ksk_create_from_args (unsigned int argc,
   uri->data.ksk.keywordCount = argc;
   uri->data.ksk.keywords = GNUNET_malloc (argc * sizeof (char *));
   for (i = 0; i < argc; i++)
   uri->data.ksk.keywordCount = argc;
   uri->data.ksk.keywords = GNUNET_malloc (argc * sizeof (char *));
   for (i = 0; i < argc; i++)
+  {
+    keyword = argv[i];
+    if (keyword[0] == '+')
+      val = GNUNET_strdup (keyword);
+    else
+      GNUNET_asprintf (&val, " %s", keyword);
+    r = val;
+    w = val;
+    while ('\0' != *r)
     {
     {
-      keyword = argv[i];
-      if (keyword[0] == '+')
-       val = GNUNET_strdup (keyword);
+      if ('"' == *r)
+        r++;
       else
       else
-        GNUNET_asprintf (&val, " %s", keyword);
-      r = val;
-      w = val;
-      while ('\0' != *r)
-        {
-          if ('"' == *r)
-            r++;
-          else
-            *(w++) = *(r++);
-        }
-      *w = '\0';
-      uri->data.ksk.keywords[i] = val;
+        *(w++) = *(r++);
     }
     }
+    *w = '\0';
+    uri->data.ksk.keywords[i] = val;
+  }
   return uri;
 }
 
   return uri;
 }
 
@@ -1233,9 +1368,9 @@ GNUNET_FS_uri_ksk_create_from_args (unsigned int argc,
  * @param u2 the other URI
  * @return GNUNET_YES if the URIs are equal
  */
  * @param u2 the other URI
  * @return GNUNET_YES if the URIs are equal
  */
-int 
+int
 GNUNET_FS_uri_test_equal (const struct GNUNET_FS_Uri *u1,
 GNUNET_FS_uri_test_equal (const struct GNUNET_FS_Uri *u1,
-                         const struct GNUNET_FS_Uri *u2)
+                          const struct GNUNET_FS_Uri *u2)
 {
   int ret;
   unsigned int i;
 {
   int ret;
   unsigned int i;
@@ -1246,53 +1381,50 @@ GNUNET_FS_uri_test_equal (const struct GNUNET_FS_Uri *u1,
   if (u1->type != u2->type)
     return GNUNET_NO;
   switch (u1->type)
   if (u1->type != u2->type)
     return GNUNET_NO;
   switch (u1->type)
-    {
-    case chk:
-      if (0 == memcmp (&u1->data.chk,
-                       &u2->data.chk,
-                      sizeof (struct FileIdentifier)))
-        return GNUNET_YES;
-      return GNUNET_NO;
-    case sks:
-      if ((0 == memcmp (&u1->data.sks.namespace,
-                        &u2->data.sks.namespace,
-                        sizeof (GNUNET_HashCode))) &&
-          (0 == strcmp (u1->data.sks.identifier,
-                        u2->data.sks.identifier)))
-
-        return GNUNET_YES;
+  {
+  case chk:
+    if (0 ==
+        memcmp (&u1->data.chk, &u2->data.chk, sizeof (struct FileIdentifier)))
+      return GNUNET_YES;
+    return GNUNET_NO;
+  case sks:
+    if ((0 ==
+         memcmp (&u1->data.sks.namespace, &u2->data.sks.namespace,
+                 sizeof (GNUNET_HashCode))) &&
+        (0 == strcmp (u1->data.sks.identifier, u2->data.sks.identifier)))
+
+      return GNUNET_YES;
+    return GNUNET_NO;
+  case ksk:
+    if (u1->data.ksk.keywordCount != u2->data.ksk.keywordCount)
       return GNUNET_NO;
       return GNUNET_NO;
-    case ksk:
-      if (u1->data.ksk.keywordCount != u2->data.ksk.keywordCount)
-        return GNUNET_NO;
-      for (i = 0; i < u1->data.ksk.keywordCount; i++)
+    for (i = 0; i < u1->data.ksk.keywordCount; i++)
+    {
+      ret = GNUNET_NO;
+      for (j = 0; j < u2->data.ksk.keywordCount; j++)
+      {
+        if (0 == strcmp (u1->data.ksk.keywords[i], u2->data.ksk.keywords[j]))
         {
         {
-          ret = GNUNET_NO;
-          for (j = 0; j < u2->data.ksk.keywordCount; j++)
-            {
-              if (0 == strcmp (u1->data.ksk.keywords[i],
-                               u2->data.ksk.keywords[j]))
-                {
-                  ret = GNUNET_YES;
-                  break;
-                }
-            }
-          if (ret == GNUNET_NO)
-            return GNUNET_NO;
+          ret = GNUNET_YES;
+          break;
         }
         }
-      return GNUNET_YES;
-    case loc:
-      if (memcmp (&u1->data.loc,
-                  &u2->data.loc,
-                  sizeof (struct FileIdentifier) +
-                  sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
-                  sizeof (struct GNUNET_TIME_Absolute) +
-                  sizeof (unsigned short) + sizeof (unsigned short)) != 0)
+      }
+      if (ret == GNUNET_NO)
         return GNUNET_NO;
         return GNUNET_NO;
-      return GNUNET_YES;
-    default:
-      return GNUNET_NO;
     }
     }
+    return GNUNET_YES;
+  case loc:
+    if (memcmp
+        (&u1->data.loc, &u2->data.loc,
+         sizeof (struct FileIdentifier) +
+         sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
+         sizeof (struct GNUNET_TIME_Absolute) + sizeof (unsigned short) +
+         sizeof (unsigned short)) != 0)
+      return GNUNET_NO;
+    return GNUNET_YES;
+  default:
+    return GNUNET_NO;
+  }
 }
 
 
 }
 
 
@@ -1317,15 +1449,15 @@ GNUNET_FS_uri_test_sks (const struct GNUNET_FS_Uri *uri)
  * @param nsid where to store the ID of the namespace
  * @return GNUNET_OK on success
  */
  * @param nsid where to store the ID of the namespace
  * @return GNUNET_OK on success
  */
-int 
+int
 GNUNET_FS_uri_sks_get_namespace (const struct GNUNET_FS_Uri *uri,
 GNUNET_FS_uri_sks_get_namespace (const struct GNUNET_FS_Uri *uri,
-                                GNUNET_HashCode * nsid)
+                                 GNUNET_HashCode * nsid)
 {
 {
-  if (! GNUNET_FS_uri_test_sks (uri))
-    {
-      GNUNET_break (0);
-      return GNUNET_SYSERR;
-    }
+  if (!GNUNET_FS_uri_test_sks (uri))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
   *nsid = uri->data.sks.namespace;
   return GNUNET_OK;
 }
   *nsid = uri->data.sks.namespace;
   return GNUNET_OK;
 }
@@ -1341,10 +1473,10 @@ char *
 GNUNET_FS_uri_sks_get_content_id (const struct GNUNET_FS_Uri *uri)
 {
   if (!GNUNET_FS_uri_test_sks (uri))
 GNUNET_FS_uri_sks_get_content_id (const struct GNUNET_FS_Uri *uri)
 {
   if (!GNUNET_FS_uri_test_sks (uri))
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
   return GNUNET_strdup (uri->data.sks.identifier);
 }
 
   return GNUNET_strdup (uri->data.sks.identifier);
 }
 
@@ -1359,7 +1491,7 @@ GNUNET_FS_uri_sks_get_content_id (const struct GNUNET_FS_Uri *uri)
  */
 char *
 GNUNET_FS_uri_sks_to_string_fancy (struct GNUNET_CONFIGURATION_Handle *cfg,
  */
 char *
 GNUNET_FS_uri_sks_to_string_fancy (struct GNUNET_CONFIGURATION_Handle *cfg,
-                                  const struct GNUNET_FS_Uri *uri)
+                                   const struct GNUNET_FS_Uri *uri)
 {
   char *ret;
   char *name;
 {
   char *ret;
   char *name;
@@ -1369,10 +1501,7 @@ GNUNET_FS_uri_sks_to_string_fancy (struct GNUNET_CONFIGURATION_Handle *cfg,
   name = GNUNET_PSEUDONYM_id_to_name (cfg, &uri->data.sks.namespace);
   if (name == NULL)
     return GNUNET_FS_uri_to_string (uri);
   name = GNUNET_PSEUDONYM_id_to_name (cfg, &uri->data.sks.namespace);
   if (name == NULL)
     return GNUNET_FS_uri_to_string (uri);
-  GNUNET_asprintf (&ret,
-                  "%s: %s",
-                  name,
-                  uri->data.sks.identifier);
+  GNUNET_asprintf (&ret, "%s: %s", name, uri->data.sks.identifier);
   GNUNET_free (name);
   return ret;
 }
   GNUNET_free (name);
   return ret;
 }
@@ -1384,17 +1513,17 @@ GNUNET_FS_uri_sks_to_string_fancy (struct GNUNET_CONFIGURATION_Handle *cfg,
  * @param uri the uri
  * @return GNUNET_YES if this is a KSK uri
  */
  * @param uri the uri
  * @return GNUNET_YES if this is a KSK uri
  */
-int 
+int
 GNUNET_FS_uri_test_ksk (const struct GNUNET_FS_Uri *uri)
 {
 #if EXTRA_CHECKS
   unsigned int i;
 
   if (uri->type == ksk)
 GNUNET_FS_uri_test_ksk (const struct GNUNET_FS_Uri *uri)
 {
 #if EXTRA_CHECKS
   unsigned int i;
 
   if (uri->type == ksk)
-    {
-      for (i = uri->data.ksk.keywordCount - 1; i >= 0; i--)
-        GNUNET_assert (uri->data.ksk.keywords[i] != NULL);
-    }
+  {
+    for (i = uri->data.ksk.keywordCount - 1; i >= 0; i--)
+      GNUNET_assert (uri->data.ksk.keywords[i] != NULL);
+  }
 #endif
   return uri->type == ksk;
 }
 #endif
   return uri->type == ksk;
 }
@@ -1406,7 +1535,7 @@ GNUNET_FS_uri_test_ksk (const struct GNUNET_FS_Uri *uri)
  * @param uri the uri to check
  * @return GNUNET_YES if this is a CHK uri
  */
  * @param uri the uri to check
  * @return GNUNET_YES if this is a CHK uri
  */
-int 
+int
 GNUNET_FS_uri_test_chk (const struct GNUNET_FS_Uri *uri)
 {
   return uri->type == chk;
 GNUNET_FS_uri_test_chk (const struct GNUNET_FS_Uri *uri)
 {
   return uri->type == chk;
@@ -1420,18 +1549,18 @@ GNUNET_FS_uri_test_chk (const struct GNUNET_FS_Uri *uri)
  * @param uri the CHK URI to inspect
  * @return size of the file as specified in the CHK URI
  */
  * @param uri the CHK URI to inspect
  * @return size of the file as specified in the CHK URI
  */
-uint64_t 
-GNUNET_FS_uri_chk_get_file_size (const struct GNUNET_FS_Uri *uri)
+uint64_t
+GNUNET_FS_uri_chk_get_file_size (const struct GNUNET_FS_Uri * uri)
 {
   switch (uri->type)
 {
   switch (uri->type)
-    {
-    case chk:
-      return GNUNET_ntohll (uri->data.chk.file_length);
-    case loc:
-      return GNUNET_ntohll (uri->data.loc.fi.file_length);
-    default:
-      GNUNET_assert (0);
-    }
+  {
+  case chk:
+    return GNUNET_ntohll (uri->data.chk.file_length);
+  case loc:
+    return GNUNET_ntohll (uri->data.loc.fi.file_length);
+  default:
+    GNUNET_assert (0);
+  }
   return 0;                     /* unreachable */
 }
 
   return 0;                     /* unreachable */
 }
 
@@ -1442,7 +1571,7 @@ GNUNET_FS_uri_chk_get_file_size (const struct GNUNET_FS_Uri *uri)
  * @param uri the uri to check
  * @return GNUNET_YES if this is a LOC uri
  */
  * @param uri the uri to check
  * @return GNUNET_YES if this is a LOC uri
  */
-int 
+int
 GNUNET_FS_uri_test_loc (const struct GNUNET_FS_Uri *uri)
 {
   return uri->type == loc;
 GNUNET_FS_uri_test_loc (const struct GNUNET_FS_Uri *uri)
 {
   return uri->type == loc;
@@ -1454,27 +1583,37 @@ GNUNET_FS_uri_test_loc (const struct GNUNET_FS_Uri *uri)
  * Adds it to the URI.
  *
  * @param cls URI to update
  * Adds it to the URI.
  *
  * @param cls URI to update
- * @param type type of the meta data
- * @param data value of the meta data
- * @return GNUNET_OK (always)
+ * @param plugin_name name of the plugin that produced this value;
+ *        special values can be used (i.e. '&lt;zlib&gt;' 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 0 (always)
  */
 static int
  */
 static int
-gather_uri_data (void *cls,
-                EXTRACTOR_KeywordType type, 
-                const char *data)
+gather_uri_data (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_FS_Uri *uri = cls;
   char *nkword;
   int j;
 {
   struct GNUNET_FS_Uri *uri = cls;
   char *nkword;
   int j;
-  
+
+  if ((format != EXTRACTOR_METAFORMAT_UTF8) &&
+      (format != EXTRACTOR_METAFORMAT_C_STRING))
+    return 0;
   for (j = uri->data.ksk.keywordCount - 1; j >= 0; j--)
     if (0 == strcmp (&uri->data.ksk.keywords[j][1], data))
       return GNUNET_OK;
   for (j = uri->data.ksk.keywordCount - 1; j >= 0; j--)
     if (0 == strcmp (&uri->data.ksk.keywords[j][1], data))
       return GNUNET_OK;
-  nkword = GNUNET_malloc (strlen (data) + 2);
-  strcpy (nkword, " ");         /* not mandatory */
-  strcat (nkword, data);
+  GNUNET_asprintf (&nkword, " %s",      /* space to mark as 'non mandatory' */
+                   data);
   uri->data.ksk.keywords[uri->data.ksk.keywordCount++] = nkword;
   uri->data.ksk.keywords[uri->data.ksk.keywordCount++] = nkword;
-  return GNUNET_OK;
+  return 0;
 }
 
 
 }
 
 
@@ -1482,25 +1621,28 @@ gather_uri_data (void *cls,
  * Construct a keyword-URI from meta-data (take all entries
  * in the meta-data and construct one large keyword URI
  * that lists all keywords that can be found in the meta-data).
  * Construct a keyword-URI from meta-data (take all entries
  * in the meta-data and construct one large keyword URI
  * that lists all keywords that can be found in the meta-data).
- * @deprecated
+ *
+ * @param md metadata to use
+ * @return NULL on error, otherwise a KSK URI
  */
 struct GNUNET_FS_Uri *
  */
 struct GNUNET_FS_Uri *
-GNUNET_FS_uri_ksk_create_from_meta_data (const struct GNUNET_CONTAINER_MetaData *md)
+GNUNET_FS_uri_ksk_create_from_meta_data (const struct GNUNET_CONTAINER_MetaData
+                                         *md)
 {
   struct GNUNET_FS_Uri *ret;
 {
   struct GNUNET_FS_Uri *ret;
+  int ent;
 
   if (md == NULL)
     return NULL;
   ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
   ret->type = ksk;
 
   if (md == NULL)
     return NULL;
   ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
   ret->type = ksk;
-  ret->data.ksk.keywordCount = 0;
-  ret->data.ksk.keywords = NULL;
-  ret->data.ksk.keywords
-    = GNUNET_malloc (sizeof (char *) *
-                     GNUNET_CONTAINER_meta_data_get_contents (md, NULL, NULL));
-  GNUNET_CONTAINER_meta_data_get_contents (md, &gather_uri_data, ret);
+  ent = GNUNET_CONTAINER_meta_data_iterate (md, NULL, NULL);
+  if (ent > 0)
+  {
+    ret->data.ksk.keywords = GNUNET_malloc (sizeof (char *) * ent);
+    GNUNET_CONTAINER_meta_data_iterate (md, &gather_uri_data, ret);
+  }
   return ret;
   return ret;
-
 }
 
 
 }
 
 
@@ -1511,8 +1653,9 @@ GNUNET_FS_uri_ksk_create_from_meta_data (const struct GNUNET_CONTAINER_MetaData
 static int
 needs_percent (char c)
 {
 static int
 needs_percent (char c)
 {
-  return (!((isalnum (c)) ||
-            (c == '-') || (c == '_') || (c == '.') || (c == '~')));
+  return (!
+          ((isalnum ((unsigned char) c)) || (c == '-') || (c == '_') ||
+           (c == '.') || (c == '~')));
 }
 
 
 }
 
 
@@ -1525,7 +1668,7 @@ needs_percent (char c)
 static char *
 uri_ksk_to_string (const struct GNUNET_FS_Uri *uri)
 {
 static char *
 uri_ksk_to_string (const struct GNUNET_FS_Uri *uri)
 {
-  char ** keywords; 
+  char **keywords;
   unsigned int keywordCount;
   size_t n;
   char *ret;
   unsigned int keywordCount;
   size_t n;
   char *ret;
@@ -1539,50 +1682,49 @@ uri_ksk_to_string (const struct GNUNET_FS_Uri *uri)
     return NULL;
   keywords = uri->data.ksk.keywords;
   keywordCount = uri->data.ksk.keywordCount;
     return NULL;
   keywords = uri->data.ksk.keywords;
   keywordCount = uri->data.ksk.keywordCount;
-  n =
-    keywordCount + strlen (GNUNET_FS_URI_PREFIX) +
-    strlen (GNUNET_FS_URI_KSK_INFIX) + 1;
+  n = keywordCount + strlen (GNUNET_FS_URI_PREFIX) +
+      strlen (GNUNET_FS_URI_KSK_INFIX) + 1;
   for (i = 0; i < keywordCount; i++)
   for (i = 0; i < keywordCount; i++)
+  {
+    keyword = keywords[i];
+    slen = strlen (keyword);
+    n += slen;
+    for (j = 0; j < slen; j++)
     {
     {
-      keyword = keywords[i];
-      slen = strlen (keyword);
-      n += slen;
-      for (j = 0; j < slen; j++)
-        {
-          if ((j == 0) && (keyword[j] == ' '))
-            {
-              n--;
-              continue;         /* skip leading space */
-            }
-          if (needs_percent (keyword[j]))
-            n += 2;             /* will use %-encoding */
-        }
+      if ((j == 0) && (keyword[j] == ' '))
+      {
+        n--;
+        continue;               /* skip leading space */
+      }
+      if (needs_percent (keyword[j]))
+        n += 2;                 /* will use %-encoding */
     }
     }
+  }
   ret = GNUNET_malloc (n);
   strcpy (ret, GNUNET_FS_URI_PREFIX);
   strcat (ret, GNUNET_FS_URI_KSK_INFIX);
   wpos = strlen (ret);
   for (i = 0; i < keywordCount; i++)
   ret = GNUNET_malloc (n);
   strcpy (ret, GNUNET_FS_URI_PREFIX);
   strcat (ret, GNUNET_FS_URI_KSK_INFIX);
   wpos = strlen (ret);
   for (i = 0; i < keywordCount; i++)
+  {
+    keyword = keywords[i];
+    slen = strlen (keyword);
+    for (j = 0; j < slen; j++)
     {
     {
-      keyword = keywords[i];
-      slen = strlen (keyword);
-      for (j = 0; j < slen; j++)
-        {
-          if ((j == 0) && (keyword[j] == ' '))
-            continue;           /* skip leading space */
-          if (needs_percent (keyword[j]))
-            {
-              sprintf (&ret[wpos], "%%%02X", keyword[j]);
-              wpos += 3;
-            }
-          else
-            {
-              ret[wpos++] = keyword[j];
-            }
-        }
-      if (i != keywordCount - 1)
-        ret[wpos++] = '+';
+      if ((j == 0) && (keyword[j] == ' '))
+        continue;               /* skip leading space */
+      if (needs_percent (keyword[j]))
+      {
+        sprintf (&ret[wpos], "%%%02X", keyword[j]);
+        wpos += 3;
+      }
+      else
+      {
+        ret[wpos++] = keyword[j];
+      }
     }
     }
+    if (i != keywordCount - 1)
+      ret[wpos++] = '+';
+  }
   return ret;
 }
 
   return ret;
 }
 
@@ -1596,21 +1738,18 @@ uri_ksk_to_string (const struct GNUNET_FS_Uri *uri)
 static char *
 uri_sks_to_string (const struct GNUNET_FS_Uri *uri)
 {
 static char *
 uri_sks_to_string (const struct GNUNET_FS_Uri *uri)
 {
-  const GNUNET_HashCode * namespace;
+  const GNUNET_HashCode *namespace;
   const char *identifier;
   char *ret;
   struct GNUNET_CRYPTO_HashAsciiEncoded ns;
   const char *identifier;
   char *ret;
   struct GNUNET_CRYPTO_HashAsciiEncoded ns;
-  
+
   if (uri->type != sks)
     return NULL;
   namespace = &uri->data.sks.namespace;
   identifier = uri->data.sks.identifier;
   GNUNET_CRYPTO_hash_to_enc (namespace, &ns);
   if (uri->type != sks)
     return NULL;
   namespace = &uri->data.sks.namespace;
   identifier = uri->data.sks.identifier;
   GNUNET_CRYPTO_hash_to_enc (namespace, &ns);
-  GNUNET_asprintf (&ret,
-                   "%s%s%s/%s",
-                   GNUNET_FS_URI_PREFIX, 
-                  GNUNET_FS_URI_SKS_INFIX,
-                   (const char *) &ns, identifier);
+  GNUNET_asprintf (&ret, "%s%s%s/%s", GNUNET_FS_URI_PREFIX,
+                   GNUNET_FS_URI_SKS_INFIX, (const char *) &ns, identifier);
   return ret;
 }
 
   return ret;
 }
 
@@ -1624,7 +1763,7 @@ uri_sks_to_string (const struct GNUNET_FS_Uri *uri)
 static char *
 uri_chk_to_string (const struct GNUNET_FS_Uri *uri)
 {
 static char *
 uri_chk_to_string (const struct GNUNET_FS_Uri *uri)
 {
-  const struct FileIdentifier * fi;
+  const struct FileIdentifier *fi;
   char *ret;
   struct GNUNET_CRYPTO_HashAsciiEncoded keyhash;
   struct GNUNET_CRYPTO_HashAsciiEncoded queryhash;
   char *ret;
   struct GNUNET_CRYPTO_HashAsciiEncoded keyhash;
   struct GNUNET_CRYPTO_HashAsciiEncoded queryhash;
@@ -1635,13 +1774,9 @@ uri_chk_to_string (const struct GNUNET_FS_Uri *uri)
   GNUNET_CRYPTO_hash_to_enc (&fi->chk.key, &keyhash);
   GNUNET_CRYPTO_hash_to_enc (&fi->chk.query, &queryhash);
 
   GNUNET_CRYPTO_hash_to_enc (&fi->chk.key, &keyhash);
   GNUNET_CRYPTO_hash_to_enc (&fi->chk.query, &queryhash);
 
-  GNUNET_asprintf (&ret,
-                   "%s%s%s.%s.%llu",
-                   GNUNET_FS_URI_PREFIX,
-                   GNUNET_FS_URI_CHK_INFIX,
-                   (const char *) &keyhash, 
-                  (const char *) &queryhash,
-                   GNUNET_ntohll (fi->file_length));
+  GNUNET_asprintf (&ret, "%s%s%s.%s.%llu", GNUNET_FS_URI_PREFIX,
+                   GNUNET_FS_URI_CHK_INFIX, (const char *) &keyhash,
+                   (const char *) &queryhash, GNUNET_ntohll (fi->file_length));
   return ret;
 }
 
   return ret;
 }
 
@@ -1659,8 +1794,8 @@ bin2enc (const void *data, size_t size)
    * 64 characters for encoding, 6 bits per character
    */
   static char *tbl =
    * 64 characters for encoding, 6 bits per character
    */
   static char *tbl =
-    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_=";
-  
+      "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_=";
+
   size_t len;
   size_t pos;
   unsigned int bits;
   size_t len;
   size_t pos;
   unsigned int bits;
@@ -1677,18 +1812,18 @@ bin2enc (const void *data, size_t size)
   bits = 0;
   hbits = 0;
   for (pos = 0; pos < size; pos++)
   bits = 0;
   hbits = 0;
   for (pos = 0; pos < size; pos++)
+  {
+    bits |= ((((const unsigned char *) data)[pos]) << hbits);
+    hbits += 8;
+    while (hbits >= 6)
     {
     {
-      bits |= ((((const unsigned char *) data)[pos]) << hbits);
-      hbits += 8;
-      while (hbits >= 6)
-        {
-          ret[len++] = tbl[bits & 63];
-          bits >>= 6;
-          hbits -= 6;
-        }
+      ret[len++] = tbl[bits & 63];
+      bits >>= 6;
+      hbits -= 6;
     }
     }
+  }
   if (hbits > 0)
   if (hbits > 0)
-    ret[len++] = tbl[bits & 63];
+    ret[len] = tbl[bits & 63];
   return ret;
 }
 
   return ret;
 }
 
@@ -1710,20 +1845,19 @@ uri_loc_to_string (const struct GNUNET_FS_Uri *uri)
 
   GNUNET_CRYPTO_hash_to_enc (&uri->data.loc.fi.chk.key, &keyhash);
   GNUNET_CRYPTO_hash_to_enc (&uri->data.loc.fi.chk.query, &queryhash);
 
   GNUNET_CRYPTO_hash_to_enc (&uri->data.loc.fi.chk.key, &keyhash);
   GNUNET_CRYPTO_hash_to_enc (&uri->data.loc.fi.chk.query, &queryhash);
-  peerId = bin2enc (&uri->data.loc.peer,
-                   sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
-  peerSig = bin2enc (&uri->data.loc.contentSignature, 
-                    sizeof (struct GNUNET_CRYPTO_RsaSignature));
-  GNUNET_asprintf (&ret,
-                   "%s%s%s.%s.%llu.%s.%s.%llu",
-                   GNUNET_FS_URI_PREFIX,
-                   GNUNET_FS_URI_LOC_INFIX,
-                   (const char *) &keyhash,
+  peerId =
+      bin2enc (&uri->data.loc.peer,
+               sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
+  peerSig =
+      bin2enc (&uri->data.loc.contentSignature,
+               sizeof (struct GNUNET_CRYPTO_RsaSignature));
+  GNUNET_asprintf (&ret, "%s%s%s.%s.%llu.%s.%s.%llu", GNUNET_FS_URI_PREFIX,
+                   GNUNET_FS_URI_LOC_INFIX, (const char *) &keyhash,
                    (const char *) &queryhash,
                    (const char *) &queryhash,
-                   (unsigned long long) GNUNET_ntohll (uri->data.loc.fi.file_length),
-                   peerId,
-                  peerSig,
-                  (unsigned long long) uri->data.loc.expirationTime.value);
+                   (unsigned long long) GNUNET_ntohll (uri->data.loc.
+                                                       fi.file_length), peerId,
+                   peerSig,
+                   (unsigned long long) uri->data.loc.expirationTime.abs_value);
   GNUNET_free (peerSig);
   GNUNET_free (peerId);
   return ret;
   GNUNET_free (peerSig);
   GNUNET_free (peerId);
   return ret;
@@ -1740,24 +1874,24 @@ char *
 GNUNET_FS_uri_to_string (const struct GNUNET_FS_Uri *uri)
 {
   if (uri == NULL)
 GNUNET_FS_uri_to_string (const struct GNUNET_FS_Uri *uri)
 {
   if (uri == NULL)
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
   switch (uri->type)
   switch (uri->type)
-    {
-    case ksk:
-      return uri_ksk_to_string (uri);
-    case sks:
-      return uri_sks_to_string (uri);
-    case chk:
-      return uri_chk_to_string (uri);
-    case loc:
-      return uri_loc_to_string (uri);
-    default:
-      GNUNET_break (0);
-      return NULL;
-    }
+  {
+  case ksk:
+    return uri_ksk_to_string (uri);
+  case sks:
+    return uri_sks_to_string (uri);
+  case chk:
+    return uri_chk_to_string (uri);
+  case loc:
+    return uri_loc_to_string (uri);
+  default:
+    GNUNET_break (0);
+    return NULL;
+  }
 }
 
 /* end of fs_uri.c */
 }
 
 /* end of fs_uri.c */