arg
[oweals/gnunet.git] / src / fs / fs_uri.c
index 2e1ec92c84368fb284a73da8ab7a70d42525885e..4b249d6bf37f3bd20550f11d9f34dc94a00b7eca 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
-     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
@@ -240,6 +240,7 @@ percent_decode_keyword (const char *in, char **emsg)
   return ret;
 }
 
+#define GNUNET_FS_URI_KSK_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX
 
 /**
  * Parse a KSK URI.
@@ -263,9 +264,9 @@ uri_ksk_parse (const char *s, char **emsg)
 
   GNUNET_assert (s != NULL);
   slen = strlen (s);
-  pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX);
+  pos = strlen (GNUNET_FS_URI_KSK_PREFIX);
   if ( (slen <= pos) ||
-       (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX, 
+       (0 != strncmp (s, GNUNET_FS_URI_KSK_PREFIX,
                      pos) ) )
     return NULL;       /* not KSK URI */
   if ( (s[slen - 1] == '+') ||
@@ -337,6 +338,8 @@ CLEANUP:
 }
 
 
+#define GNUNET_FS_URI_SKS_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX
+
 /**
  * Parse an SKS URI.
  *
@@ -356,9 +359,9 @@ uri_sks_parse (const char *s, char **emsg)
 
   GNUNET_assert (s != NULL);
   slen = strlen (s);
-  pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX);
+  pos = strlen ( GNUNET_FS_URI_SKS_PREFIX);
   if ( (slen <= pos) ||
-       (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX, 
+       (0 != strncmp (s, GNUNET_FS_URI_SKS_PREFIX,
                      pos) ) )
     return NULL; /* not an SKS URI */
   if ( (slen < pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) ||
@@ -382,6 +385,8 @@ uri_sks_parse (const char *s, char **emsg)
   return ret;
 }
 
+#define GNUNET_FS_URI_CHK_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX
+
 
 /**
  * Parse a CHK URI.
@@ -401,12 +406,13 @@ uri_chk_parse (const char *s, char **emsg)
   char h1[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)];
   char h2[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)];
 
+  if (NULL == s)
+    return NULL;
   GNUNET_assert (s != NULL);
-
   slen = strlen (s);
-  pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX);
+  pos = strlen (GNUNET_FS_URI_CHK_PREFIX);
   if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
-       (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX, 
+       (0 != strncmp (s,  GNUNET_FS_URI_CHK_PREFIX, 
                      pos) ) )
     return NULL; /* not a CHK URI */
   if ( (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
@@ -527,6 +533,8 @@ struct LocUriAssembly
 };
 
 
+#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.
@@ -553,9 +561,9 @@ uri_loc_parse (const char *s, char **emsg)
 
   GNUNET_assert (s != NULL);
   slen = strlen (s);
-  pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX);
+  pos = strlen ( GNUNET_FS_URI_LOC_PREFIX);
   if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
-       (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX, 
+       (0 != strncmp (s,  GNUNET_FS_URI_LOC_PREFIX,
                      pos) ) )
     return NULL; /* not an SKS URI */
   if ( (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
@@ -630,7 +638,7 @@ uri_loc_parse (const char *s, char **emsg)
     }
   ass.purpose.size = htonl(sizeof(struct LocUriAssembly));
   ass.purpose.purpose = htonl(GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT);
-  et.value = exptime;
+  et.abs_value = exptime;
   ass.exptime = GNUNET_TIME_absolute_hton (et);
   if (GNUNET_OK != 
       GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT,
@@ -765,6 +773,70 @@ GNUNET_FS_uri_ksk_get_keywords (const struct GNUNET_FS_Uri *uri,
 }
 
 
+/**
+ * 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))
+       {
+         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;
+       }
+    }
+}
+
+
 /**
  * Obtain the identity of the peer offering the data
  *
@@ -830,7 +902,7 @@ 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_CONFIGURATION_Handle *cfg,
+                         const struct GNUNET_CONFIGURATION_Handle *cfg,
                          struct GNUNET_TIME_Absolute expiration_time)
 {
   struct GNUNET_FS_Uri *uri;
@@ -909,6 +981,27 @@ GNUNET_FS_uri_sks_create (struct GNUNET_FS_Namespace *ns,
 }
 
 
+/**
+ * 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.
  * 
@@ -939,7 +1032,6 @@ canonicalize_keyword (const char *in)
        case '\n':
        case '\r':
          /* skip characters listed above */
-         rpos++;
          break;
        case 'b':
        case 'c':
@@ -964,6 +1056,7 @@ canonicalize_keyword (const char *in)
          /* convert characters listed above to lower case */
          *wpos = tolower( (unsigned char)*rpos);
          wpos++;
+         break;
        case '!':
        case '.':
        case '?':
@@ -976,6 +1069,7 @@ canonicalize_keyword (const char *in)
          /* replace characters listed above with '_' */
          *wpos = '_';
          wpos++;
+         break;
        }
       rpos++;
     }
@@ -1062,7 +1156,7 @@ GNUNET_FS_uri_ksk_merge (const struct GNUNET_FS_Uri *u1,
            break;
          }
       if (0 == found)
-       kl[kc++] = GNUNET_strdup (kp - 1);
+       kl[kc++] = GNUNET_strdup (kp);
     }
   ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
   ret->type = ksk;
@@ -1091,8 +1185,14 @@ GNUNET_FS_uri_dup (const struct GNUNET_FS_Uri *uri)
   switch (ret->type)
     {
     case ksk:
+      if (ret->data.ksk.keywordCount >= GNUNET_MAX_MALLOC_CHECKED / sizeof (char*))
+       {
+         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++)
@@ -1145,6 +1245,7 @@ GNUNET_FS_uri_ksk_create (const char *keywords,
 
   if (keywords == NULL)
     {
+      *emsg = GNUNET_strdup (_("No keywords specified!\n"));
       GNUNET_break (0);
       return NULL;
     }
@@ -1536,9 +1637,9 @@ gather_uri_data (void *cls,
   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;
   return 0;
 }
@@ -1556,19 +1657,20 @@ struct GNUNET_FS_Uri *
 GNUNET_FS_uri_ksk_create_from_meta_data (const struct GNUNET_CONTAINER_MetaData *md)
 {
   struct GNUNET_FS_Uri *ret;
+  int ent;
 
   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)
+    {
+      ret->data.ksk.keywords
+       = GNUNET_malloc (sizeof (char *) * ent);                     
+      GNUNET_CONTAINER_meta_data_iterate (md, &gather_uri_data, ret);
+    }
   return ret;
-
 }
 
 
@@ -1756,7 +1858,7 @@ bin2enc (const void *data, size_t size)
         }
     }
   if (hbits > 0)
-    ret[len++] = tbl[bits & 63];
+    ret[len] = tbl[bits & 63];
   return ret;
 }
 
@@ -1791,7 +1893,7 @@ uri_loc_to_string (const struct GNUNET_FS_Uri *uri)
                    (unsigned long long) GNUNET_ntohll (uri->data.loc.fi.file_length),
                    peerId,
                   peerSig,
-                  (unsigned long long) uri->data.loc.expirationTime.value);
+                  (unsigned long long) uri->data.loc.expirationTime.abs_value);
   GNUNET_free (peerSig);
   GNUNET_free (peerId);
   return ret;