/*
This file is part of GNUnet.
- Copyright (C) 2005-2013 GNUnet e.V.
+ 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 Affero 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.
+ Affero 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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ SPDX-License-Identifier: AGPL3.0-or-later
+*/
/**
* @file util/strings.c
* @brief string functions
#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)
/**
if (buffer != NULL)
{
GNUNET_assert (needed + slen <= size);
- memcpy (&buffer[needed], s, slen);
+ GNUNET_memcpy (&buffer[needed], s, slen);
}
needed += slen;
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
{ "us", 1},
{ "ms", 1000 },
{ "s", 1000 * 1000LL },
+ { "second", 1000 * 1000LL },
+ { "seconds", 1000 * 1000LL },
{ "\"", 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},
{
struct tm tv;
time_t t;
+ const char *eos;
- 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;
}
+ eos = &fancy_time[strlen (fancy_time)];
memset (&tv, 0, sizeof (tv));
- if ( (NULL == strptime (fancy_time, "%a %b %d %H:%M:%S %Y", &tv)) &&
- (NULL == strptime (fancy_time, "%c", &tv)) &&
- (NULL == strptime (fancy_time, "%Ec", &tv)) &&
- (NULL == strptime (fancy_time, "%Y-%m-%d %H:%M:%S", &tv)) &&
- (NULL == strptime (fancy_time, "%Y-%m-%d %H:%M", &tv)) &&
- (NULL == strptime (fancy_time, "%x", &tv)) &&
- (NULL == strptime (fancy_time, "%Ex", &tv)) &&
- (NULL == strptime (fancy_time, "%Y-%m-%d", &tv)) &&
- (NULL == strptime (fancy_time, "%Y-%m", &tv)) &&
- (NULL == strptime (fancy_time, "%Y", &tv)) )
+ if ( (eos != strptime (fancy_time, "%a %b %d %H:%M:%S %Y", &tv)) &&
+ (eos != strptime (fancy_time, "%c", &tv)) &&
+ (eos != strptime (fancy_time, "%Ec", &tv)) &&
+ (eos != strptime (fancy_time, "%Y-%m-%d %H:%M:%S", &tv)) &&
+ (eos != strptime (fancy_time, "%Y-%m-%d %H:%M", &tv)) &&
+ (eos != strptime (fancy_time, "%x", &tv)) &&
+ (eos != strptime (fancy_time, "%Ex", &tv)) &&
+ (eos != strptime (fancy_time, "%Y-%m-%d", &tv)) &&
+ (eos != strptime (fancy_time, "%Y-%m", &tv)) &&
+ (eos != strptime (fancy_time, "%Y", &tv)) )
return GNUNET_SYSERR;
t = mktime (&tv);
atime->abs_value_us = (uint64_t) ((uint64_t) t * 1000LL * 1000LL);
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;
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;
_("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;
}
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);
}
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);
}
char *buffer;
#ifndef MINGW
size_t len;
- size_t n;
char *fm;
const char *fil_ptr;
#else
}
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);
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);
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;
}
{
const char *short_fn = filename;
const char *ss;
+
while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR))
&& (ss[1] != '\0'))
short_fn = 1 + ss;
* (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);
switch (pp_state)
{
case 0:
- if (path[i] == ':' && i > 0)
+ if ( (path[i] == ':') && (i > 0) )
{
pp_state += 1;
continue;
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)
/**
- * 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.
int ret;
char *port_colon;
unsigned int port;
+ char dummy[2];
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,
_("IPv6 address did contain ']' before ':' to separate port number\n"));
return GNUNET_SYSERR;
}
- ret = SSCANF (port_colon, ":%u", &port);
+ ret = SSCANF (port_colon,
+ ":%u%1s",
+ &port,
+ dummy);
if ( (1 != ret) || (port > 65535) )
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
* 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];
unsigned int port;
unsigned int cnt;
+ char dummy[2];
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%1s",
+ &temps[0],
+ &temps[1],
+ &temps[2],
+ &temps[3],
+ &port,
+ dummy);
if (5 != cnt)
return GNUNET_SYSERR;
for (cnt = 0; cnt < 4; cnt++)
* @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,
}
+/**
+ * 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();
* @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;
}
if (2 == sscanf (pos,
"%u-%u%1s",
- &s, &e, eol))
+ &s,
+ &e,
+ eol))
{
if ( (0 == s) ||
(s > 0xFFFF) ||
int colon;
int end;
char *routeList;
-
+ char dummy[2];
+
if (NULL == routeListX)
return NULL;
len = strlen (routeListX);
}
cnt =
SSCANF (&routeList[pos],
- "%u.%u.%u.%u/%u.%u.%u.%u",
+ "%u.%u.%u.%u/%u.%u.%u.%u%1s",
&temps[0],
&temps[1],
&temps[2],
&temps[4],
&temps[5],
&temps[6],
- &temps[7]);
+ &temps[7],
+ dummy);
if (8 == cnt)
{
for (j = 0; j < 8; j++)
/* try second notation */
cnt =
SSCANF (&routeList[pos],
- "%u.%u.%u.%u/%u",
+ "%u.%u.%u.%u/%u%1s",
&temps[0],
&temps[1],
&temps[2],
&temps[3],
- &slash);
+ &slash,
+ dummy);
if (5 == cnt)
{
for (j = 0; j < 4; j++)
slash = 32;
cnt =
SSCANF (&routeList[pos],
- "%u.%u.%u.%u",
+ "%u.%u.%u.%u%1s",
&temps[0],
&temps[1],
&temps[2],
- &temps[3]);
+ &temps[3],
+ dummy);
if (4 == cnt)
{
for (j = 0; j < 4; j++)
unsigned int off;
int save;
int colon;
-
+ char dummy[2];
+
if (NULL == routeListX)
return NULL;
len = strlen (routeListX);
if (ret <= 0)
{
save = errno;
- if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits > 128))
+ if ( (1 != SSCANF (&routeList[slash + 1],
+ "%u%1s",
+ &bits,
+ dummy)) ||
+ (bits > 128) )
{
if (0 == ret)
LOG (GNUNET_ERROR_TYPE_WARNING,
/**
* Encode into Base64.
*
- * @param data the data to encode
+ * @param in the data to encode
* @param len the length of the input
* @param output where to write the output (*output should be NULL,
* is allocated)
* @return the size of the output
*/
size_t
-GNUNET_STRINGS_base64_encode (const char *data,
+GNUNET_STRINGS_base64_encode (const void *in,
size_t len,
char **output)
{
- size_t i;
- char c;
+ const char *data = in;
size_t ret;
char *opt;
ret = 0;
opt = GNUNET_malloc (2 + (len * 4 / 3) + 8);
- *output = opt;
- for (i = 0; i < len; ++i)
+ for (size_t i = 0; i < len; ++i)
{
+ char c;
+
c = (data[i] >> 2) & 0x3f;
opt[ret++] = cvt[(int) c];
c = (data[i] << 4) & 0x3f;
opt[ret++] = FILLCHAR;
}
}
- opt[ret++] = FILLCHAR;
+ *output = opt;
return ret;
}
*/
size_t
GNUNET_STRINGS_base64_decode (const char *data,
- size_t len, char **output)
+ size_t len,
+ void **out)
{
- size_t i;
- char c;
- char c1;
+ char *output;
size_t ret = 0;
#define CHECK_CRLF while (data[i] == '\r' || data[i] == '\n') {\
if (i >= len) goto END; \
}
- *output = GNUNET_malloc ((len * 3 / 4) + 8);
+ output = GNUNET_malloc ((len * 3 / 4) + 8);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"base64_decode decoding len=%d\n",
(int) len);
- for (i = 0; i < len; ++i)
+ for (size_t i = 0; i < len; ++i)
{
+ char c;
+ char c1;
+
CHECK_CRLF;
if (FILLCHAR == data[i])
break;
CHECK_CRLF;
c1 = (char) cvtfind (data[i]);
c = (c << 2) | ((c1 >> 4) & 0x3);
- (*output)[ret++] = c;
+ output[ret++] = c;
if (++i < len)
{
CHECK_CRLF;
break;
c = (char) cvtfind (c);
c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
- (*output)[ret++] = c1;
+ output[ret++] = c1;
}
if (++i < len)
{
c1 = (char) cvtfind (c1);
c = ((c << 6) & 0xc0) | c1;
- (*output)[ret++] = c;
+ output[ret++] = c;
}
}
END:
+ *out = output;
return ret;
}
-
-
-
/* end of strings.c */