first batch of license fixes (boring)
[oweals/gnunet.git] / src / util / strings.c
index ba1a9164194b8afb8232544cddb029dde73525cc..e2f37c8ad78b8611c81976e5ceb7d74b94212630 100644 (file)
@@ -1,23 +1,17 @@
 /*
      This file is part of GNUnet.
-     (C) 2005-2013 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2005-2017 GNUnet e.V.
 
-     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 3, or (at your
-     option) any later version.
+     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 3 of the License,
+     or (at your option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Affero General Public License for more details.
 */
-
 /**
  * @file util/strings.c
  * @brief string functions
 #if HAVE_ICONV
 #include <iconv.h>
 #endif
-#include "gnunet_util_lib.h"
+#include "gnunet_crypto_lib.h"
+#include "gnunet_strings_lib.h"
 #include <unicase.h>
 #include <unistr.h>
 #include <uniconv.h>
 
-#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+#define LOG(kind,...) GNUNET_log_from (kind, "util-strings", __VA_ARGS__)
 
-#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
+#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-strings", syscall)
 
 
 /**
@@ -78,7 +73,7 @@ GNUNET_STRINGS_buffer_fill (char *buffer, size_t size, unsigned int count, ...)
     if (buffer != NULL)
     {
       GNUNET_assert (needed + slen <= size);
-      memcpy (&buffer[needed], s, slen);
+      GNUNET_memcpy (&buffer[needed], s, slen);
     }
     needed += slen;
     count--;
@@ -88,6 +83,37 @@ GNUNET_STRINGS_buffer_fill (char *buffer, size_t size, unsigned int count, ...)
 }
 
 
+/**
+ * Convert a peer path to a human-readable string.
+ *
+ * @param pids array of PIDs to convert to a string
+ * @param num_pids length of the @a pids array
+ * @return string representing the array of @a pids
+ */
+char *
+GNUNET_STRINGS_pp2s (const struct GNUNET_PeerIdentity *pids,
+                     unsigned int num_pids)
+{
+  char *buf;
+  size_t off;
+  size_t plen = num_pids * 5 + 1;
+
+  off = 0;
+  buf = GNUNET_malloc (plen);
+  for (unsigned int i = 0;
+       i < num_pids;
+       i++)
+  {
+    off += GNUNET_snprintf (&buf[off],
+                            plen - off,
+                            "%s%s",
+                            GNUNET_i2s (&pids[i]),
+                            (i == num_pids -1) ? "" : "-");
+  }
+  return buf;
+}
+
+
 /**
  * Given a buffer of a given size, find "count"
  * 0-terminated strings in the buffer and assign
@@ -305,14 +331,19 @@ GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time,
     { "\"", 1000  * 1000LL },
     { "m", 60 * 1000  * 1000LL},
     { "min", 60 * 1000  * 1000LL},
+    { "minute", 60 * 1000  * 1000LL},
     { "minutes", 60 * 1000  * 1000LL},
     { "'", 60 * 1000  * 1000LL},
     { "h", 60 * 60 * 1000  * 1000LL},
+    { "hour", 60 * 60 * 1000  * 1000LL},
+    { "hours", 60 * 60 * 1000  * 1000LL},
     { "d", 24 * 60 * 60 * 1000LL * 1000LL},
     { "day", 24 * 60 * 60 * 1000LL * 1000LL},
     { "days", 24 * 60 * 60 * 1000LL * 1000LL},
     { "week", 7 * 24 * 60 * 60 * 1000LL * 1000LL},
     { "weeks", 7 * 24 * 60 * 60 * 1000LL * 1000LL},
+    { "year", 31536000000000LL /* year */ },
+    { "years", 31536000000000LL /* year */ },
     { "a", 31536000000000LL /* year */ },
     { NULL, 0}
   };
@@ -348,7 +379,8 @@ GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time,
   struct tm tv;
   time_t t;
 
-  if (0 == strcasecmp ("end of time", fancy_time))
+  if (0 == strcasecmp ("end of time",
+                       fancy_time))
   {
     *atime = GNUNET_TIME_UNIT_FOREVER_ABS;
     return GNUNET_OK;
@@ -409,7 +441,7 @@ GNUNET_STRINGS_conv (const char *input,
   if (0 == strcmp (output_charset, "UTF-8"))
   {
     ret = GNUNET_malloc (u8_string_length + 1);
-    memcpy (ret, u8_string, u8_string_length);
+    GNUNET_memcpy (ret, u8_string, u8_string_length);
     ret[u8_string_length] = '\0';
     free (u8_string);
     return ret;
@@ -425,7 +457,7 @@ GNUNET_STRINGS_conv (const char *input,
     goto fail;
   }
   ret = GNUNET_malloc (encoded_string_length + 1);
-  memcpy (ret, encoded_string, encoded_string_length);
+  GNUNET_memcpy (ret, encoded_string, encoded_string_length);
   ret[encoded_string_length] = '\0';
   free (encoded_string);
   return ret;
@@ -434,7 +466,7 @@ GNUNET_STRINGS_conv (const char *input,
        _("Character sets requested were `%s'->`%s'\n"),
        "UTF-8", output_charset);
   ret = GNUNET_malloc (len + 1);
-  memcpy (ret, input, len);
+  GNUNET_memcpy (ret, input, len);
   ret[len] = '\0';
   return ret;
 }
@@ -497,7 +529,7 @@ GNUNET_STRINGS_utf8_tolower (const char *input,
 
   tmp_in = u8_tolower ((uint8_t*)input, strlen ((char *) input),
                        NULL, UNINORM_NFD, NULL, &len);
-  memcpy(output, tmp_in, len);
+  GNUNET_memcpy(output, tmp_in, len);
   output[len] = '\0';
   free(tmp_in);
 }
@@ -519,7 +551,7 @@ GNUNET_STRINGS_utf8_toupper(const char *input,
 
   tmp_in = u8_toupper ((uint8_t*)input, strlen ((char *) input),
                        NULL, UNINORM_NFD, NULL, &len);
-  memcpy (output, tmp_in, len);
+  GNUNET_memcpy (output, tmp_in, len);
   output[len] = '\0';
   free (tmp_in);
 }
@@ -538,7 +570,6 @@ GNUNET_STRINGS_filename_expand (const char *fil)
   char *buffer;
 #ifndef MINGW
   size_t len;
-  size_t n;
   char *fm;
   const char *fil_ptr;
 #else
@@ -595,7 +626,8 @@ GNUNET_STRINGS_filename_expand (const char *fil)
     }
     if (fm == NULL)
     {
-      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "getcwd");
+      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
+                    "getcwd");
       buffer = getenv ("PWD");  /* alternative */
       if (buffer != NULL)
         fm = GNUNET_strdup (buffer);
@@ -603,9 +635,9 @@ GNUNET_STRINGS_filename_expand (const char *fil)
     if (fm == NULL)
       fm = GNUNET_strdup ("./");        /* give up */
   }
-  n = strlen (fm) + 1 + strlen (fil_ptr) + 1;
-  buffer = GNUNET_malloc (n);
-  GNUNET_snprintf (buffer, n, "%s%s%s", fm,
+  GNUNET_asprintf (&buffer,
+                   "%s%s%s",
+                   fm,
                    (fm[strlen (fm) - 1] ==
                     DIR_SEPARATOR) ? "" : DIR_SEPARATOR_STR, fil_ptr);
   GNUNET_free (fm);
@@ -616,23 +648,29 @@ GNUNET_STRINGS_filename_expand (const char *fil)
   if ((lRet = plibc_conv_to_win_path (fil, fn)) != ERROR_SUCCESS)
   {
     SetErrnoFromWinError (lRet);
-    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "plibc_conv_to_win_path");
+    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
+                  "plibc_conv_to_win_path");
     return NULL;
   }
   /* is the path relative? */
-  if ((strncmp (fn + 1, ":\\", 2) != 0) && (strncmp (fn, "\\\\", 2) != 0))
+  if ( (0 != strncmp (fn + 1, ":\\", 2)) &&
+       (0 != strncmp (fn, "\\\\", 2)) )
   {
     char szCurDir[MAX_PATH + 1];
 
-    lRet = GetCurrentDirectory (MAX_PATH + 1, szCurDir);
+    lRet = GetCurrentDirectory (MAX_PATH + 1,
+                                szCurDir);
     if (lRet + strlen (fn) + 1 > (MAX_PATH + 1))
     {
       SetErrnoFromWinError (ERROR_BUFFER_OVERFLOW);
-      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "GetCurrentDirectory");
+      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
+                    "GetCurrentDirectory");
       return NULL;
     }
-    buffer = GNUNET_malloc (MAX_PATH + 1);
-    GNUNET_snprintf (buffer, MAX_PATH + 1, "%s\\%s", szCurDir, fn);
+    GNUNET_asprintf (&buffer,
+                     "%s\\%s",
+                     szCurDir,
+                     fn);
     GNUNET_free (fn);
     fn = buffer;
   }
@@ -775,6 +813,7 @@ GNUNET_STRINGS_get_short_name (const char *filename)
 {
   const char *short_fn = filename;
   const char *ss;
+
   while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR))
       && (ss[1] != '\0'))
     short_fn = 1 + ss;
@@ -846,10 +885,13 @@ getValue__ (unsigned char a)
  * @param out buffer to fill
  * @param out_size size of the buffer. Must be large enough to hold
  * (size * 8 + 4) / 5 bytes
- * @return pointer to the next byte in 'out' or NULL on error.
+ * @return pointer to the next byte in @a out or NULL on error.
  */
 char *
-GNUNET_STRINGS_data_to_string (const void *data, size_t size, char *out, size_t out_size)
+GNUNET_STRINGS_data_to_string (const void *data,
+                               size_t size,
+                               char *out,
+                               size_t out_size)
 {
   /**
    * 32 characters for encoding
@@ -861,8 +903,6 @@ GNUNET_STRINGS_data_to_string (const void *data, size_t size, char *out, size_t
   unsigned int vbit;
   const unsigned char *udata;
 
-  GNUNET_assert (data != NULL);
-  GNUNET_assert (out != NULL);
   udata = data;
   if (out_size < (size * 8 + 4) / 5)
   {
@@ -894,13 +934,46 @@ GNUNET_STRINGS_data_to_string (const void *data, size_t size, char *out, size_t
     out[wpos++] = encTable__[(bits >> (vbit - 5)) & 31];
     vbit -= 5;
   }
-  GNUNET_assert (vbit == 0);
+  GNUNET_assert (0 == vbit);
   if (wpos < out_size)
     out[wpos] = '\0';
   return &out[wpos];
 }
 
 
+/**
+ * Return the base32crockford encoding of the given buffer.
+ *
+ * The returned string will be freshly allocated, and must be free'd
+ * with GNUNET_free().
+ *
+ * @param buffer with data
+ * @param size size of the buffer
+ * @return freshly allocated, null-terminated string
+ */
+char *
+GNUNET_STRINGS_data_to_string_alloc (const void *buf,
+                                     size_t size)
+{
+  char *str_buf;
+  size_t len = size * 8;
+  char *end;
+
+  if (len % 5 > 0)
+    len += 5 - len % 5;
+  len /= 5;
+  str_buf = GNUNET_malloc (len + 1);
+  end = GNUNET_STRINGS_data_to_string (buf, size, str_buf, len);
+  if (NULL == end)
+  {
+    GNUNET_free (str_buf);
+    return NULL;
+  }
+  *end = '\0';
+  return str_buf;
+}
+
+
 /**
  * Convert Crockford Base32hex encoding back to data.
  * @a out_size must match exactly the size of the data before it was encoded.
@@ -991,11 +1064,13 @@ GNUNET_STRINGS_string_to_data (const char *enc, size_t enclen,
  *         (if they weren't NULL).
  */
 int
-GNUNET_STRINGS_parse_uri (const char *path, char **scheme_part,
-    const char **path_part)
+GNUNET_STRINGS_parse_uri (const char *path,
+                         char **scheme_part,
+                         const char **path_part)
 {
   size_t len;
-  int i, end;
+  size_t i;
+  int end;
   int pp_state = 0;
   const char *post_scheme_part = NULL;
   len = strlen (path);
@@ -1004,7 +1079,7 @@ GNUNET_STRINGS_parse_uri (const char *path, char **scheme_part,
     switch (pp_state)
     {
     case 0:
-      if (path[i] == ':' && i > 0)
+      if ( (path[i] == ':') && (i > 0) )
       {
         pp_state += 1;
         continue;
@@ -1036,7 +1111,7 @@ GNUNET_STRINGS_parse_uri (const char *path, char **scheme_part,
   if (scheme_part)
   {
     *scheme_part = GNUNET_malloc (post_scheme_part - path + 1);
-    memcpy (*scheme_part, path, post_scheme_part - path);
+    GNUNET_memcpy (*scheme_part, path, post_scheme_part - path);
     (*scheme_part)[post_scheme_part - path] = '\0';
   }
   if (path_part)
@@ -1162,7 +1237,7 @@ GNUNET_STRINGS_check_filename (const char *filename,
 
 
 /**
- * Tries to convert 'zt_addr' string to an IPv6 address.
+ * Tries to convert @a zt_addr string to an IPv6 address.
  * The string is expected to have the format "[ABCD::01]:80".
  *
  * @param zt_addr 0-terminated string. May be mangled by the function.
@@ -1185,7 +1260,7 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
 
   if (addrlen < 6)
     return GNUNET_SYSERR;
-  memcpy (zbuf, zt_addr, addrlen);
+  GNUNET_memcpy (zbuf, zt_addr, addrlen);
   if ('[' != zbuf[0])
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -1245,7 +1320,8 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
  *         the contents of @a r_buf are undefined.
  */
 int
-GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen,
+GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr,
+                               uint16_t addrlen,
                                struct sockaddr_in *r_buf)
 {
   unsigned int temps[4];
@@ -1254,7 +1330,13 @@ GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen,
 
   if (addrlen < 9)
     return GNUNET_SYSERR;
-  cnt = SSCANF (zt_addr, "%u.%u.%u.%u:%u", &temps[0], &temps[1], &temps[2], &temps[3], &port);
+  cnt = SSCANF (zt_addr,
+               "%u.%u.%u.%u:%u",
+               &temps[0],
+               &temps[1],
+               &temps[2],
+               &temps[3],
+               &port);
   if (5 != cnt)
     return GNUNET_SYSERR;
   for (cnt = 0; cnt < 4; cnt++)
@@ -1281,8 +1363,8 @@ GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen,
  * @param addrlen number of bytes in @a addr (if addr is 0-terminated,
  *        0-terminator should not be counted towards addrlen).
  * @param r_buf a buffer to fill.
- * @return #GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which
- *         case the contents of r_buf are undefined.
+ * @return #GNUNET_OK if conversion succeded. #GNUNET_SYSERR otherwise, in which
+ *         case the contents of @a r_buf are undefined.
  */
 int
 GNUNET_STRINGS_to_address_ip (const char *addr,
@@ -1299,6 +1381,62 @@ GNUNET_STRINGS_to_address_ip (const char *addr,
 }
 
 
+/**
+ * Parse an address given as a string into a
+ * `struct sockaddr`.
+ *
+ * @param addr the address
+ * @param[out] af set to the parsed address family (i.e. AF_INET)
+ * @param[out] sa set to the parsed address
+ * @return 0 on error, otherwise number of bytes in @a sa
+ */
+size_t
+GNUNET_STRINGS_parse_socket_addr (const char *addr,
+                                 uint8_t *af,
+                                 struct sockaddr **sa)
+{
+  char *cp = GNUNET_strdup (addr);
+
+  *af = AF_UNSPEC;
+  if ('[' == *addr)
+  {
+    /* IPv6 */
+    *sa = GNUNET_malloc (sizeof (struct sockaddr_in6));
+    if (GNUNET_OK !=
+       GNUNET_STRINGS_to_address_ipv6 (cp,
+                                       strlen (cp),
+                                       (struct sockaddr_in6 *) *sa))
+    {
+      GNUNET_free (*sa);
+      *sa = NULL;
+      GNUNET_free (cp);
+      return 0;
+    }
+    *af = AF_INET6;
+    GNUNET_free (cp);
+    return sizeof (struct sockaddr_in6);
+  }
+  else
+  {
+    /* IPv4 */
+    *sa = GNUNET_malloc (sizeof (struct sockaddr_in));
+    if (GNUNET_OK !=
+       GNUNET_STRINGS_to_address_ipv4 (cp,
+                                       strlen (cp),
+                                       (struct sockaddr_in *) *sa))
+    {
+      GNUNET_free (*sa);
+      *sa = NULL;
+      GNUNET_free (cp);
+      return 0;
+    }
+    *af = AF_INET;
+    GNUNET_free (cp);
+    return sizeof (struct sockaddr_in);
+  }
+}
+
+
 /**
  * Makes a copy of argv that consists of a single memory chunk that can be
  * freed with a single call to GNUNET_free();
@@ -1341,7 +1479,10 @@ _make_continuous_arg_copy (int argc,
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
  */
 int
-GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *const **u8argv)
+GNUNET_STRINGS_get_utf8_args (int argc,
+                             char *const *argv,
+                             int *u8argc,
+                             char *const **u8argv)
 {
 #if WINDOWS
   wchar_t *wcmd;