-fixing 2352
[oweals/gnunet.git] / src / fs / fs_uri.c
index 5ddb48f2a1a52dea1edafb825ad6497057bbf1ef..0c2d64caca85186b4c5247e039e62ac935c994e1 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
 #include "platform.h"
 #include "gnunet_fs_service.h"
 #include "gnunet_signatures.h"
 #include "platform.h"
 #include "gnunet_fs_service.h"
 #include "gnunet_signatures.h"
-#include "fs.h"
+#include "fs_api.h"
+#include <unitypes.h>
+#include <unicase.h>
+#include <uniconv.h>
+#include <unistr.h>
+#include <unistdio.h>
+
 
 
 /**
 
 
 /**
  * @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 +131,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 +145,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 +193,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 +211,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 +270,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 +342,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 +359,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)) ||
-       (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 +406,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;
@@ -493,16 +496,16 @@ enc2bin (const char *input, void *data, size_t size)
   hbits = 0;
   len = 0;
   for (pos = 0; pos < size; pos++)
   hbits = 0;
   len = 0;
   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;
 }
 
@@ -514,19 +517,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.
@@ -539,8 +544,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;
@@ -553,95 +558,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;
@@ -662,8 +661,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;
@@ -671,10 +669,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"));
@@ -689,29 +687,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);
 }
 
@@ -721,7 +718,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)
@@ -739,10 +736,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;
@@ -752,16 +749,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;
+  }
 }
 
 
 }
 
 
@@ -774,13 +828,13 @@ 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;
 }
 
@@ -795,7 +849,7 @@ struct GNUNET_TIME_Absolute
 GNUNET_FS_uri_loc_get_expiration (const struct GNUNET_FS_Uri *uri)
 {
   GNUNET_assert (uri->type == loc);
 GNUNET_FS_uri_loc_get_expiration (const struct GNUNET_FS_Uri *uri)
 {
   GNUNET_assert (uri->type == loc);
-  return uri->data.loc.expirationTime; 
+  return uri->data.loc.expirationTime;
 }
 
 
 }
 
 
@@ -830,11 +884,11 @@ GNUNET_FS_uri_loc_get_uri (const struct GNUNET_FS_Uri *uri)
  */
 struct GNUNET_FS_Uri *
 GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *baseUri,
  */
 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;
@@ -842,28 +896,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;
@@ -873,9 +924,8 @@ 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;
 }
@@ -890,124 +940,38 @@ GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *baseUri,
  * @return an FS URI for the given namespace and identifier
  */
 struct GNUNET_FS_Uri *
  * @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)
+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;
 {
   struct GNUNET_FS_Uri *ns_uri;
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
-             
+
   ns_uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri));
   ns_uri->type = sks;
   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);
+  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;
 }
 
 
 /**
   ns_uri->data.sks.identifier = GNUNET_strdup (id);
   return ns_uri;
 }
 
 
 /**
- * Canonicalize a keyword.
- * 
- * @param in input string (the keyword)
- * @return canonicalized keyword
- */
-static char *
-canonicalize_keyword (const char *in)
-{
-  char *ret;
-  char *wpos;
-  const char *rpos;
-
-  ret = GNUNET_strdup (in);
-  wpos = ret;
-  rpos = in;
-  while ('\0' != *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++;
-         break;
-       default:
-         /* replace characters listed above with '_' */
-         *wpos = '_';
-         wpos++;
-       }
-      rpos++;
-    }
-  return ret;
-}
-
-
-/**
- * Canonicalize keyword URI.  Performs operations such
- * as decapitalization and removal of certain characters.
- * (useful for search).
+ * Create an SKS URI from a namespace ID and an identifier.
  *
  *
- * @param uri the URI to canonicalize 
- * @return canonicalized version of the URI, NULL on error
+ * @param nsid namespace ID
+ * @param id identifier
+ * @return an FS URI for the given namespace and identifier
  */
 struct GNUNET_FS_Uri *
  */
 struct GNUNET_FS_Uri *
-GNUNET_FS_uri_ksk_canonicalize (const struct GNUNET_FS_Uri *uri)
+GNUNET_FS_uri_sks_create_from_nsid (GNUNET_HashCode * nsid, const char *id)
 {
 {
-  struct GNUNET_FS_Uri *ret;
-  unsigned int kc;
-  unsigned int i;
-  char **kl;
+  struct GNUNET_FS_Uri *ns_uri;
 
 
-  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->type = ksk;
-  ret->data.ksk.keywordCount = kc;
-  ret->data.ksk.keywords = kl;
-  return ret;
+  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;
 }
 
 
 }
 
 
@@ -1022,7 +986,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;
@@ -1032,33 +996,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;
@@ -1083,27 +1051,33 @@ GNUNET_FS_uri_dup (const struct GNUNET_FS_Uri *uri)
   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;
 }
 
@@ -1126,8 +1100,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;
@@ -1138,66 +1111,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;
@@ -1222,8 +1196,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;
@@ -1236,12 +1209,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));
@@ -1249,24 +1222,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;
 }
 
@@ -1278,9 +1251,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;
@@ -1291,53 +1264,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;
+  }
 }
 
 
 }
 
 
@@ -1362,15 +1332,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;
 }
@@ -1386,10 +1356,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);
 }
 
@@ -1404,21 +1374,20 @@ 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;
+  char *unique_name;
 
   if (uri->type != sks)
     return NULL;
 
   if (uri->type != sks)
     return NULL;
-  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);
+  (void) GNUNET_PSEUDONYM_get_info (cfg, &uri->data.sks.namespace,
+                                   NULL, NULL, &name, NULL);
+  unique_name = GNUNET_PSEUDONYM_name_uniquify (cfg, &uri->data.sks.namespace, name, NULL);
   GNUNET_free (name);
   GNUNET_free (name);
+  GNUNET_asprintf (&ret, "%s: %s", unique_name, uri->data.sks.identifier);
+  GNUNET_free (unique_name);
   return ret;
 }
 
   return ret;
 }
 
@@ -1429,17 +1398,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=0;i < uri->data.ksk.keywordCount; i++)
+      GNUNET_assert (uri->data.ksk.keywords[i] != NULL);
+  }
 #endif
   return uri->type == ksk;
 }
 #endif
   return uri->type == ksk;
 }
@@ -1451,7 +1420,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;
@@ -1465,18 +1434,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 */
 }
 
@@ -1487,13 +1456,275 @@ 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;
 }
 
 
+/**
+ * Add a keyword as non-mandatory (with ' '-prefix) to the
+ * given keyword list at offset 'index'.  The array is
+ * guaranteed to be long enough.
+ * 
+ * @param s keyword to add
+ * @param array array to add the keyword to
+ * @param index offset where to add the keyword
+ */
+static void
+insert_non_mandatory_keyword (const char *s, char **array, int index)
+{
+  char *nkword;
+  GNUNET_asprintf (&nkword, " %s", /* space to mark as 'non mandatory' */ s);
+  array[index] = nkword;
+}
+
+
+/**
+ * Test if the given keyword 's' is already present in the 
+ * given array, ignoring the '+'-mandatory prefix in the array.
+ *
+ * @param s keyword to test
+ * @param array keywords to test against, with ' ' or '+' prefix to ignore
+ * @param array_length length of the array
+ * @return GNUNET_YES if the keyword exists, GNUNET_NO if not
+ */ 
+static int
+find_duplicate (const char *s, const char **array, int array_length)
+{
+  int j;
+
+  for (j = array_length - 1; j >= 0; j--)
+    if (0 == strcmp (&array[j][1], s))
+      return GNUNET_YES;
+  return GNUNET_NO;
+}
+
+
+/**
+ * FIXME: comment
+ */
+static char *
+normalize_metadata (enum EXTRACTOR_MetaFormat format, const char *data,
+    size_t data_len)
+{
+  uint8_t *free_str = NULL;
+  uint8_t *str_to_normalize = (uint8_t *) data;
+  uint8_t *normalized;
+  size_t r_len;
+  if (str_to_normalize == NULL)
+    return NULL;
+  /* Don't trust libextractor */
+  if (format == EXTRACTOR_METAFORMAT_UTF8)
+  {
+    free_str = (uint8_t *) u8_check ((const uint8_t *) data, data_len);
+    if (free_str == NULL)
+      free_str = NULL;
+    else
+      format = EXTRACTOR_METAFORMAT_C_STRING;
+  }
+  if (format == EXTRACTOR_METAFORMAT_C_STRING)
+  {
+    free_str = u8_strconv_from_encoding (data, locale_charset (), iconveh_escape_sequence);
+    if (free_str == NULL)
+      return NULL;
+  }
+
+  normalized = u8_tolower (str_to_normalize, strlen ((char *) str_to_normalize), NULL, UNINORM_NFD, NULL, &r_len);
+  /* free_str is allocated by libunistring internally, use free() */
+  if (free_str != NULL)
+    free (free_str);
+  if (normalized != NULL)
+  {
+    /* u8_tolower allocates a non-NULL-terminated string! */
+    free_str = GNUNET_malloc (r_len + 1);
+    memcpy (free_str, normalized, r_len);
+    free_str[r_len] = '\0';
+    free (normalized);
+    normalized = free_str;
+  }
+  return (char *) normalized;
+}
+
+/**
+ * Counts the number of UTF-8 characters (not bytes) in the string,
+ * returns that count.
+ */
+static size_t
+u8_strcount (const uint8_t *s)
+{
+  size_t count;
+  ucs4_t c;
+  GNUNET_assert (s != NULL);
+  if (s[0] == 0)
+    return 0;
+  for (count = 0; s != NULL; count++)
+    s = u8_next (&c, s);
+  return count - 1;
+}
+
+
+/**
+ * Break the filename up by matching [], () and {} pairs to make
+ * keywords. In case of nesting parentheses only the inner pair counts.
+ * You can't escape parentheses to scan something like "[blah\{foo]" to
+ * make a "blah{foo" keyword, this function is only a heuristic!
+ *
+ * @param s string to break down.
+ * @param array array to fill with enclosed tokens. If NULL, then tokens
+ *        are only counted.
+ * @param index index at which to start filling the array (entries prior
+ *        to it are used to check for duplicates). ignored if array == NULL.
+ * @return number of tokens counted (including duplicates), or number of
+ *         tokens extracted (excluding duplicates). 0 if there are no
+ *         matching parens in the string (when counting), or when all tokens 
+ *         were duplicates (when extracting).
+ */
+static int
+get_keywords_from_parens (const char *s, char **array, int index)
+{
+  int count = 0;
+  char *open_paren;
+  char *close_paren;
+  char *ss;
+  char tmp;
+
+  if (NULL == s)
+    return 0;
+  ss = GNUNET_strdup (s);
+  open_paren = ss - 1;
+  while (NULL != (open_paren = strpbrk (open_paren + 1, "[{(")))
+  {
+    int match = 0;
+
+    close_paren = strpbrk (open_paren + 1, "]})");
+    if (NULL == close_paren)
+      continue;
+    switch (open_paren[0])
+    {
+    case '[':
+      if (']' == close_paren[0])
+        match = 1;
+      break;
+    case '{':
+      if ('}' == close_paren[0])
+        match = 1;
+      break;
+    case '(':
+      if (')' == close_paren[0])
+        match = 1;
+      break;
+    default:
+      break;
+    }
+    if (match && (close_paren - open_paren > 1))
+    {
+      tmp = close_paren[0];
+      close_paren[0] = '\0';
+      /* Keywords must be at least 3 characters long */
+      if (u8_strcount ((const uint8_t *) &open_paren[1]) <= 2)
+      {
+        close_paren[0] = tmp;
+        continue;
+      }
+      if (NULL != array)
+      {
+        char *normalized;
+        if (GNUNET_NO == find_duplicate ((const char *) &open_paren[1],
+            (const char **) array, index + count))
+        {
+         insert_non_mandatory_keyword ((const char *) &open_paren[1], array,
+                                       index + count);
+          count++;
+        }
+        normalized = normalize_metadata (EXTRACTOR_METAFORMAT_UTF8,
+            &open_paren[1], close_paren - &open_paren[1]);
+        if (normalized != NULL)
+        {
+          if (GNUNET_NO == find_duplicate ((const char *) normalized,
+              (const char **) array, index + count))
+          {
+           insert_non_mandatory_keyword ((const char *) normalized, array,
+                                         index + count);
+            count++;
+          }
+          GNUNET_free (normalized);
+        }
+      }
+      else
+       count++;
+      close_paren[0] = tmp;
+    }   
+  }
+  GNUNET_free (ss);
+  return count;
+}
+
+
+/**
+ * Where to break up keywords
+ */
+#define TOKENS "_. /-!?#&+@\"\'\\;:,"
+
+/**
+ * Break the filename up by TOKENS to make
+ * keywords.
+ *
+ * @param s string to break down.
+ * @param array array to fill with tokens. If NULL, then tokens are only
+ *        counted.
+ * @param index index at which to start filling the array (entries prior
+ *        to it are used to check for duplicates). ignored if array == NULL.
+ * @return number of tokens (>1) counted (including duplicates), or number of
+ *         tokens extracted (excluding duplicates). 0 if there are no
+ *         separators in the string (when counting), or when all tokens were
+ *         duplicates (when extracting).
+ */
+static int
+get_keywords_from_tokens (const char *s, char **array, int index)
+{
+  char *p;
+  char *ss;
+  int seps = 0;
+
+  ss = GNUNET_strdup (s);
+  for (p = strtok (ss, TOKENS); p != NULL; p = strtok (NULL, TOKENS))
+  {
+    /* Keywords must be at least 3 characters long */
+    if (u8_strcount ((const uint8_t *) p) <= 2)
+      continue;
+    if (NULL != array)
+    {
+      char *normalized;
+      if (GNUNET_NO == find_duplicate (p, (const char **) array, index + seps))
+      {
+        insert_non_mandatory_keyword (p, array,
+                                     index + seps);
+       seps++;
+      }
+      normalized = normalize_metadata (EXTRACTOR_METAFORMAT_UTF8,
+          p, strlen (p));
+      if (normalized != NULL)
+      {
+        if (GNUNET_NO == find_duplicate ((const char *) normalized,
+            (const char **) array, index + seps))
+        {
+          insert_non_mandatory_keyword ((const char *) normalized, array,
+                                 index + seps);
+          seps++;
+        }
+        GNUNET_free (normalized);
+      }
+    }
+    else
+      seps++;
+  }
+  GNUNET_free (ss);
+  return seps;
+}
+#undef TOKENS
+
 /**
  * Function called on each value in the meta data.
  * Adds it to the URI.
 /**
  * Function called on each value in the meta data.
  * Adds it to the URI.
@@ -1504,7 +1735,7 @@ GNUNET_FS_uri_test_loc (const struct GNUNET_FS_Uri *uri)
  *        used in the main libextractor library and yielding
  *        meta data).
  * @param type libextractor-type describing the meta data
  *        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 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_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
@@ -1512,28 +1743,42 @@ GNUNET_FS_uri_test_loc (const struct GNUNET_FS_Uri *uri)
  * @return 0 (always)
  */
 static int
  * @return 0 (always)
  */
 static int
-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)
+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;
 {
   struct GNUNET_FS_Uri *uri = cls;
-  char *nkword;
-  int j;
-  
-  if ( (format != EXTRACTOR_METAFORMAT_UTF8) &&
-       (format != EXTRACTOR_METAFORMAT_C_STRING) )
+  char *normalized_data;
+
+  if ((format != EXTRACTOR_METAFORMAT_UTF8) &&
+      (format != EXTRACTOR_METAFORMAT_C_STRING))
     return 0;
     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;
-  nkword = GNUNET_malloc (strlen (data) + 2);
-  strcpy (nkword, " ");         /* not mandatory */
-  strcat (nkword, data);
-  uri->data.ksk.keywords[uri->data.ksk.keywordCount++] = nkword;
+  /* Keywords must be at least 3 characters long
+   * If given non-utf8 string it will, most likely, find it to be invalid,
+   * and will return the length of its valid part, skipping the keyword.
+   * If it does - fix the extractor, not this check!
+   */
+  if (u8_strcount ((const uint8_t *) data) <= 2)
+  {
+    return 0;
+  }
+  normalized_data = normalize_metadata (format, data, data_len);
+  if (!find_duplicate (data, (const char **) uri->data.ksk.keywords, uri->data.ksk.keywordCount))
+  {
+    insert_non_mandatory_keyword (data,
+                                 uri->data.ksk.keywords, uri->data.ksk.keywordCount);
+    uri->data.ksk.keywordCount++;
+  }
+  if (normalized_data != NULL)
+  {
+    if (!find_duplicate (normalized_data, (const char **) uri->data.ksk.keywords, uri->data.ksk.keywordCount))
+    {
+      insert_non_mandatory_keyword (normalized_data,
+                                   uri->data.ksk.keywords, uri->data.ksk.keywordCount);
+      uri->data.ksk.keywordCount++;
+    }
+    GNUNET_free (normalized_data);
+  }
   return 0;
 }
 
   return 0;
 }
 
@@ -1547,22 +1792,50 @@ gather_uri_data (void *cls,
  * @return NULL on error, otherwise a KSK URI
  */
 struct GNUNET_FS_Uri *
  * @return NULL on error, otherwise a KSK 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;
+  char *filename;
+  char *full_name = NULL;
+  char *ss;
+  int ent;
+  int tok_keywords = 0;
+  int paren_keywords = 0;
 
   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_iterate (md, NULL, NULL));
-  GNUNET_CONTAINER_meta_data_iterate (md, &gather_uri_data, ret);
+  ent = GNUNET_CONTAINER_meta_data_iterate (md, NULL, NULL);
+  if (ent > 0)
+  {
+    full_name = GNUNET_CONTAINER_meta_data_get_first_by_types (md,
+        EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME, -1);
+    if (NULL != full_name)
+    {
+      filename = full_name;
+      while (NULL != (ss = strstr (filename, DIR_SEPARATOR_STR)))
+        filename = ss + 1;
+      tok_keywords = get_keywords_from_tokens (filename, NULL, 0);
+      paren_keywords = get_keywords_from_parens (filename, NULL, 0);
+    }
+    /* x2 because there might be a normalized variant of every keyword */
+    ret->data.ksk.keywords = GNUNET_malloc (sizeof (char *) * (ent
+        + tok_keywords + paren_keywords) * 2);
+    GNUNET_CONTAINER_meta_data_iterate (md, &gather_uri_data, ret);
+  }
+  if (tok_keywords > 0)
+    ret->data.ksk.keywordCount += get_keywords_from_tokens (filename,
+        ret->data.ksk.keywords,
+        ret->data.ksk.keywordCount);
+  if (paren_keywords > 0)
+    ret->data.ksk.keywordCount += get_keywords_from_parens (filename,
+        ret->data.ksk.keywords,
+        ret->data.ksk.keywordCount);
+  if (ent > 0)
+    GNUNET_free_non_null (full_name);
   return ret;
   return ret;
-
 }
 
 
 }
 
 
@@ -1573,8 +1846,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 == '~')));
 }
 
 
 }
 
 
@@ -1587,7 +1861,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;
@@ -1601,50 +1875,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;
 }
 
@@ -1658,21 +1931,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;
 }
 
@@ -1686,7 +1956,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;
@@ -1697,13 +1967,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;
 }
 
@@ -1721,8 +1987,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;
@@ -1739,18 +2005,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;
 }
 
@@ -1772,20 +2038,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;
@@ -1802,24 +2067,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 */