GNUnet  0.11.x
strings.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2005-2017 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
27 #include "platform.h"
28 #if HAVE_ICONV
29 #include <iconv.h>
30 #endif
31 #include "gnunet_crypto_lib.h"
32 #include "gnunet_strings_lib.h"
33 #include <unicase.h>
34 #include <unistr.h>
35 #include <uniconv.h>
36 
37 #define LOG(kind, ...) GNUNET_log_from (kind, "util-strings", __VA_ARGS__)
38 
39 #define LOG_STRERROR(kind, syscall) \
40  GNUNET_log_from_strerror (kind, "util-strings", syscall)
41 
42 
64 size_t
66  size_t size,
67  unsigned int count, ...)
68 {
69  size_t needed;
70  va_list ap;
71 
72  needed = 0;
73  va_start (ap, count);
74  while (count > 0)
75  {
76  const char *s = va_arg (ap, const char *);
77  size_t slen = strlen (s) + 1;
78 
79  GNUNET_assert (slen <= size - needed);
80  if (NULL != buffer)
81  GNUNET_memcpy (&buffer[needed],
82  s,
83  slen);
84  needed += slen;
85  count--;
86  }
87  va_end (ap);
88  return needed;
89 }
90 
91 
99 char *
101  unsigned int num_pids)
102 {
103  char *buf;
104  size_t off;
105  size_t plen = num_pids * 5 + 1;
106 
107  GNUNET_assert (num_pids < UINT32_MAX / 5);
108  off = 0;
109  buf = GNUNET_malloc (plen);
110  for (unsigned int i = 0; i < num_pids; i++)
111  {
112  off += GNUNET_snprintf (&buf[off],
113  plen - off,
114  "%s%s",
115  GNUNET_i2s (&pids[i]),
116  (i == num_pids - 1) ? "" : "-");
117  }
118  return buf;
119 }
120 
121 
135 unsigned int
136 GNUNET_STRINGS_buffer_tokenize (const char *buffer,
137  size_t size,
138  unsigned int count,
139  ...)
140 {
141  unsigned int start;
142  unsigned int needed;
143  const char **r;
144  va_list ap;
145 
146  needed = 0;
147  va_start (ap, count);
148  while (count > 0)
149  {
150  r = va_arg (ap, const char **);
151 
152  start = needed;
153  while ((needed < size) && (buffer[needed] != '\0'))
154  needed++;
155  if (needed == size)
156  {
157  va_end (ap);
158  return 0; /* error */
159  }
160  *r = &buffer[start];
161  needed++; /* skip 0-termination */
162  count--;
163  }
164  va_end (ap);
165  return needed;
166 }
167 
168 
175 char *
177 {
178  const char *unit = _ (/* size unit */ "b");
179  char *ret;
180 
181  if (size > 5 * 1024)
182  {
183  size = size / 1024;
184  unit = "KiB";
185  if (size > 5 * 1024)
186  {
187  size = size / 1024;
188  unit = "MiB";
189  if (size > 5 * 1024)
190  {
191  size = size / 1024;
192  unit = "GiB";
193  if (size > 5 * 1024)
194  {
195  size = size / 1024;
196  unit = "TiB";
197  }
198  }
199  }
200  }
201  ret = GNUNET_malloc (32);
202  GNUNET_snprintf (ret, 32, "%llu %s", size, unit);
203  return ret;
204 }
205 
206 
219 size_t
220 GNUNET_strlcpy (char *dst, const char *src, size_t n)
221 {
222  size_t slen;
223 
224  GNUNET_assert (0 != n);
225  slen = strnlen (src, n - 1);
226  memcpy (dst, src, slen);
227  dst[slen] = '\0';
228  return slen;
229 }
230 
231 
236 {
240  const char *name;
241 
245  unsigned long long value;
246 };
247 
248 
260 static int
261 convert_with_table (const char *input,
262  const struct ConversionTable *table,
263  unsigned long long *output)
264 {
265  unsigned long long ret;
266  char *in;
267  const char *tok;
268  unsigned long long last;
269  unsigned int i;
270  char *sptr;
271 
272  ret = 0;
273  last = 0;
274  in = GNUNET_strdup (input);
275  for (tok = strtok_r (in, " ", &sptr);
276  tok != NULL;
277  tok = strtok_r (NULL, " ", &sptr))
278  {
279  do
280  {
281  i = 0;
282  while ((table[i].name != NULL) && (0 != strcasecmp (table[i].name, tok)))
283  i++;
284  if (table[i].name != NULL)
285  {
286  last *= table[i].value;
287  break; /* next tok */
288  }
289  else
290  {
291  char *endptr;
292  ret += last;
293  errno = 0;
294  last = strtoull (tok, &endptr, 10);
295  if ((0 != errno) || (endptr == tok))
296  {
297  GNUNET_free (in);
298  return GNUNET_SYSERR; /* expected number */
299  }
300  if ('\0' == endptr[0])
301  break; /* next tok */
302  else
303  tok = endptr; /* and re-check (handles times like "10s") */
304  }
305  }
306  while (GNUNET_YES);
307  }
308  ret += last;
309  *output = ret;
310  GNUNET_free (in);
311  return GNUNET_OK;
312 }
313 
314 
322 int
323 GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
324  unsigned long long *size)
325 {
326  static const struct ConversionTable table[] =
327  { { "B", 1 },
328  { "KiB", 1024 },
329  { "kB", 1000 },
330  { "MiB", 1024 * 1024 },
331  { "MB", 1000 * 1000 },
332  { "GiB", 1024 * 1024 * 1024 },
333  { "GB", 1000 * 1000 * 1000 },
334  { "TiB", 1024LL * 1024LL * 1024LL * 1024LL },
335  { "TB", 1000LL * 1000LL * 1000LL * 1024LL },
336  { "PiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL },
337  { "PB", 1000LL * 1000LL * 1000LL * 1024LL * 1000LL },
338  { "EiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL },
339  { "EB", 1000LL * 1000LL * 1000LL * 1024LL * 1000LL * 1000LL },
340  { NULL, 0 } };
341 
342  return convert_with_table (fancy_size, table, size);
343 }
344 
345 
354 int
356  struct GNUNET_TIME_Relative *rtime)
357 {
358  static const struct ConversionTable table[] =
359  { { "us", 1 },
360  { "ms", 1000 },
361  { "s", 1000 * 1000LL },
362  { "second", 1000 * 1000LL },
363  { "seconds", 1000 * 1000LL },
364  { "\"", 1000 * 1000LL },
365  { "m", 60 * 1000 * 1000LL },
366  { "min", 60 * 1000 * 1000LL },
367  { "minute", 60 * 1000 * 1000LL },
368  { "minutes", 60 * 1000 * 1000LL },
369  { "'", 60 * 1000 * 1000LL },
370  { "h", 60 * 60 * 1000 * 1000LL },
371  { "hour", 60 * 60 * 1000 * 1000LL },
372  { "hours", 60 * 60 * 1000 * 1000LL },
373  { "d", 24 * 60 * 60 * 1000LL * 1000LL },
374  { "day", 24 * 60 * 60 * 1000LL * 1000LL },
375  { "days", 24 * 60 * 60 * 1000LL * 1000LL },
376  { "week", 7 * 24 * 60 * 60 * 1000LL * 1000LL },
377  { "weeks", 7 * 24 * 60 * 60 * 1000LL * 1000LL },
378  { "year", 31536000000000LL /* year */ },
379  { "years", 31536000000000LL /* year */ },
380  { "a", 31536000000000LL /* year */ },
381  { NULL, 0 } };
382  int ret;
383  unsigned long long val;
384 
385  if (0 == strcasecmp ("forever", fancy_time))
386  {
388  return GNUNET_OK;
389  }
390  ret = convert_with_table (fancy_time, table, &val);
391  rtime->rel_value_us = (uint64_t) val;
392  return ret;
393 }
394 
395 
405 int
407  struct GNUNET_TIME_Absolute *atime)
408 {
409  struct tm tv;
410  time_t t;
411  const char *eos;
412 
413  if (0 == strcasecmp ("end of time", fancy_time))
414  {
416  return GNUNET_OK;
417  }
418  eos = &fancy_time[strlen (fancy_time)];
419  memset (&tv, 0, sizeof(tv));
420  if ((eos != strptime (fancy_time, "%a %b %d %H:%M:%S %Y", &tv)) &&
421  (eos != strptime (fancy_time, "%c", &tv)) &&
422  (eos != strptime (fancy_time, "%Ec", &tv)) &&
423  (eos != strptime (fancy_time, "%Y-%m-%d %H:%M:%S", &tv)) &&
424  (eos != strptime (fancy_time, "%Y-%m-%d %H:%M", &tv)) &&
425  (eos != strptime (fancy_time, "%x", &tv)) &&
426  (eos != strptime (fancy_time, "%Ex", &tv)) &&
427  (eos != strptime (fancy_time, "%Y-%m-%d", &tv)) &&
428  (eos != strptime (fancy_time, "%Y-%m", &tv)) &&
429  (eos != strptime (fancy_time, "%Y", &tv)))
430  return GNUNET_SYSERR;
431  t = mktime (&tv);
432  atime->abs_value_us = (uint64_t) ((uint64_t) t * 1000LL * 1000LL);
433  return GNUNET_OK;
434 }
435 
436 
450 char *
451 GNUNET_STRINGS_conv (const char *input,
452  size_t len,
453  const char *input_charset,
454  const char *output_charset)
455 {
456  char *ret;
457  uint8_t *u8_string;
458  char *encoded_string;
459  size_t u8_string_length;
460  size_t encoded_string_length;
461 
462  u8_string = u8_conv_from_encoding (input_charset,
463  iconveh_error,
464  input,
465  len,
466  NULL,
467  NULL,
468  &u8_string_length);
469  if (NULL == u8_string)
470  {
471  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_from_encoding");
472  goto fail;
473  }
474  if (0 == strcmp (output_charset, "UTF-8"))
475  {
476  ret = GNUNET_malloc (u8_string_length + 1);
477  GNUNET_memcpy (ret, u8_string, u8_string_length);
478  ret[u8_string_length] = '\0';
479  free (u8_string);
480  return ret;
481  }
482  encoded_string = u8_conv_to_encoding (output_charset,
483  iconveh_error,
484  u8_string,
485  u8_string_length,
486  NULL,
487  NULL,
488  &encoded_string_length);
489  free (u8_string);
490  if (NULL == encoded_string)
491  {
492  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_to_encoding");
493  goto fail;
494  }
495  ret = GNUNET_malloc (encoded_string_length + 1);
496  GNUNET_memcpy (ret, encoded_string, encoded_string_length);
497  ret[encoded_string_length] = '\0';
498  free (encoded_string);
499  return ret;
500 fail:
502  _ ("Character sets requested were `%s'->`%s'\n"),
503  "UTF-8",
504  output_charset);
505  ret = GNUNET_malloc (len + 1);
506  GNUNET_memcpy (ret, input, len);
507  ret[len] = '\0';
508  return ret;
509 }
510 
511 
524 char *
525 GNUNET_STRINGS_to_utf8 (const char *input,
526  size_t len,
527  const char *charset)
528 {
529  return GNUNET_STRINGS_conv (input,
530  len,
531  charset,
532  "UTF-8");
533 }
534 
535 
547 char *
548 GNUNET_STRINGS_from_utf8 (const char *input,
549  size_t len,
550  const char *charset)
551 {
552  return GNUNET_STRINGS_conv (input,
553  len,
554  "UTF-8",
555  charset);
556 }
557 
558 
566 void
567 GNUNET_STRINGS_utf8_tolower (const char *input, char *output)
568 {
569  uint8_t *tmp_in;
570  size_t len;
571 
572  tmp_in = u8_tolower ((uint8_t *) input,
573  strlen ((char *) input),
574  NULL,
575  UNINORM_NFD,
576  NULL,
577  &len);
578  GNUNET_memcpy (output, tmp_in, len);
579  output[len] = '\0';
580  free (tmp_in);
581 }
582 
583 
591 void
592 GNUNET_STRINGS_utf8_toupper (const char *input, char *output)
593 {
594  uint8_t *tmp_in;
595  size_t len;
596 
597  tmp_in = u8_toupper ((uint8_t *) input,
598  strlen ((char *) input),
599  NULL,
600  UNINORM_NFD,
601  NULL,
602  &len);
603  GNUNET_memcpy (output, tmp_in, len);
604  output[len] = '\0';
605  free (tmp_in);
606 }
607 
608 
616 char *
618 {
619  char *buffer;
620  size_t len;
621  char *fm;
622  const char *fil_ptr;
623 
624  if (fil == NULL)
625  return NULL;
626 
627  if (fil[0] == DIR_SEPARATOR)
628  /* absolute path, just copy */
629  return GNUNET_strdup (fil);
630  if (fil[0] == '~')
631  {
632  fm = getenv ("HOME");
633  if (fm == NULL)
634  {
636  _ ("Failed to expand `$HOME': environment variable `HOME' not set"));
637  return NULL;
638  }
639  fm = GNUNET_strdup (fm);
640  /* do not copy '~' */
641  fil_ptr = fil + 1;
642 
643  /* skip over dir seperator to be consistent */
644  if (fil_ptr[0] == DIR_SEPARATOR)
645  fil_ptr++;
646  }
647  else
648  {
649  /* relative path */
650  fil_ptr = fil;
651  len = 512;
652  fm = NULL;
653  while (1)
654  {
655  buffer = GNUNET_malloc (len);
656  if (getcwd (buffer, len) != NULL)
657  {
658  fm = buffer;
659  break;
660  }
661  if ((errno == ERANGE) && (len < 1024 * 1024 * 4))
662  {
663  len *= 2;
664  GNUNET_free (buffer);
665  continue;
666  }
667  GNUNET_free (buffer);
668  break;
669  }
670  if (fm == NULL)
671  {
673  buffer = getenv ("PWD"); /* alternative */
674  if (buffer != NULL)
675  fm = GNUNET_strdup (buffer);
676  }
677  if (fm == NULL)
678  fm = GNUNET_strdup ("./"); /* give up */
679  }
680  GNUNET_asprintf (&buffer,
681  "%s%s%s",
682  fm,
683  (fm[strlen (fm) - 1] == DIR_SEPARATOR) ? ""
685  fil_ptr);
686  GNUNET_free (fm);
687  return buffer;
688 }
689 
690 
700 const char *
702  int do_round)
703 {
704  static GNUNET_THREAD_LOCAL char buf[128];
705  const char *unit = _ (/* time unit */ "┬Ás");
706  uint64_t dval = delta.rel_value_us;
707 
708  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == delta.rel_value_us)
709  return _ ("forever");
710  if (0 == delta.rel_value_us)
711  return _ ("0 ms");
712  if (((GNUNET_YES == do_round) && (dval > 5 * 1000)) || (0 == (dval % 1000)))
713  {
714  dval = dval / 1000;
715  unit = _ (/* time unit */ "ms");
716  if (((GNUNET_YES == do_round) && (dval > 5 * 1000)) || (0 == (dval % 1000)))
717  {
718  dval = dval / 1000;
719  unit = _ (/* time unit */ "s");
720  if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
721  {
722  dval = dval / 60;
723  unit = _ (/* time unit */ "m");
724  if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
725  {
726  dval = dval / 60;
727  unit = _ (/* time unit */ "h");
728  if (((GNUNET_YES == do_round) && (dval > 5 * 24)) ||
729  (0 == (dval % 24)))
730  {
731  dval = dval / 24;
732  if (1 == dval)
733  unit = _ (/* time unit */ "day");
734  else
735  unit = _ (/* time unit */ "days");
736  }
737  }
738  }
739  }
740  }
741  GNUNET_snprintf (buf, sizeof(buf), "%llu %s", dval, unit);
742  return buf;
743 }
744 
745 
755 const char *
757 {
758  static GNUNET_THREAD_LOCAL char buf[255];
759  time_t tt;
760  struct tm *tp;
761 
762  if (t.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
763  return _ ("end of time");
764  tt = t.abs_value_us / 1000LL / 1000LL;
765  tp = localtime (&tt);
766  /* This is hacky, but i don't know a way to detect libc character encoding.
767  * Just expect utf8 from glibc these days.
768  * As for msvcrt, use the wide variant, which always returns utf16
769  * (otherwise we'd have to detect current codepage or use W32API character
770  * set conversion routines to convert to UTF8).
771  */strftime (buf, sizeof(buf), "%a %b %d %H:%M:%S %Y", tp);
772 
773  return buf;
774 }
775 
776 
788 const char *
790 {
791  const char *short_fn = filename;
792  const char *ss;
793 
794  while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)) && (ss[1] != '\0'))
795  short_fn = 1 + ss;
796  return short_fn;
797 }
798 
799 
807 static unsigned int
808 getValue__ (unsigned char a)
809 {
810  unsigned int dec;
811 
812  switch (a)
813  {
814  case 'O':
815  case 'o':
816  a = '0';
817  break;
818 
819  case 'i':
820  case 'I':
821  case 'l':
822  case 'L':
823  a = '1';
824  break;
825 
826  /* also consider U to be V */
827  case 'u':
828  case 'U':
829  a = 'V';
830  break;
831 
832  default:
833  break;
834  }
835  if ((a >= '0') && (a <= '9'))
836  return a - '0';
837  if ((a >= 'a') && (a <= 'z'))
838  a = toupper (a);
839  /* return (a - 'a' + 10); */
840  dec = 0;
841  if ((a >= 'A') && (a <= 'Z'))
842  {
843  if ('I' < a)
844  dec++;
845  if ('L' < a)
846  dec++;
847  if ('O' < a)
848  dec++;
849  if ('U' < a)
850  dec++;
851  return(a - 'A' + 10 - dec);
852  }
853  return -1;
854 }
855 
856 
869 char *
871  size_t size,
872  char *out,
873  size_t out_size)
874 {
878  static char *encTable__ = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
879  unsigned int wpos;
880  unsigned int rpos;
881  unsigned int bits;
882  unsigned int vbit;
883  const unsigned char *udata;
884 
885  GNUNET_assert (size < SIZE_MAX / 8 - 4);
886  udata = data;
887  if (out_size < (size * 8 + 4) / 5)
888  {
889  GNUNET_break (0);
890  return NULL;
891  }
892  vbit = 0;
893  wpos = 0;
894  rpos = 0;
895  bits = 0;
896  while ((rpos < size) || (vbit > 0))
897  {
898  if ((rpos < size) && (vbit < 5))
899  {
900  bits = (bits << 8) | udata[rpos++]; /* eat 8 more bits */
901  vbit += 8;
902  }
903  if (vbit < 5)
904  {
905  bits <<= (5 - vbit); /* zero-padding */
906  GNUNET_assert (vbit == ((size * 8) % 5));
907  vbit = 5;
908  }
909  if (wpos >= out_size)
910  {
911  GNUNET_break (0);
912  return NULL;
913  }
914  out[wpos++] = encTable__[(bits >> (vbit - 5)) & 31];
915  vbit -= 5;
916  }
917  GNUNET_assert (0 == vbit);
918  if (wpos < out_size)
919  out[wpos] = '\0';
920  return &out[wpos];
921 }
922 
923 
934 char *
936 {
937  char *str_buf;
938  size_t len = size * 8;
939  char *end;
940 
941  if (len % 5 > 0)
942  len += 5 - len % 5;
943  len /= 5;
944  str_buf = GNUNET_malloc (len + 1);
946  size,
947  str_buf,
948  len);
949  if (NULL == end)
950  {
951  GNUNET_free (str_buf);
952  return NULL;
953  }
954  *end = '\0';
955  return str_buf;
956 }
957 
958 
969 int
971  size_t enclen,
972  void *out,
973  size_t out_size)
974 {
975  size_t rpos;
976  size_t wpos;
977  unsigned int bits;
978  unsigned int vbit;
979  int ret;
980  int shift;
981  unsigned char *uout;
982  size_t encoded_len;
983 
984  if (0 == enclen)
985  {
986  if (0 == out_size)
987  return GNUNET_OK;
988  return GNUNET_SYSERR;
989  }
990  GNUNET_assert (out_size < SIZE_MAX / 8);
991  encoded_len = out_size * 8;
992  uout = out;
993  wpos = out_size;
994  rpos = enclen;
995  if ((encoded_len % 5) > 0)
996  {
997  vbit = encoded_len % 5; /* padding! */
998  shift = 5 - vbit;
999  bits = (ret = getValue__ (enc[--rpos])) >> shift;
1000  }
1001  else
1002  {
1003  vbit = 5;
1004  shift = 0;
1005  bits = (ret = getValue__ (enc[--rpos]));
1006  }
1007  if ((encoded_len + shift) / 5 != enclen)
1008  return GNUNET_SYSERR;
1009  if (-1 == ret)
1010  return GNUNET_SYSERR;
1011  while (wpos > 0)
1012  {
1013  if (0 == rpos)
1014  {
1015  GNUNET_break (0);
1016  return GNUNET_SYSERR;
1017  }
1018  bits = ((ret = getValue__ (enc[--rpos])) << vbit) | bits;
1019  if (-1 == ret)
1020  return GNUNET_SYSERR;
1021  vbit += 5;
1022  if (vbit >= 8)
1023  {
1024  uout[--wpos] = (unsigned char) bits;
1025  bits >>= 8;
1026  vbit -= 8;
1027  }
1028  }
1029  if ((0 != rpos) || (0 != vbit))
1030  return GNUNET_SYSERR;
1031  return GNUNET_OK;
1032 }
1033 
1034 
1051 int
1052 GNUNET_STRINGS_parse_uri (const char *path,
1053  char **scheme_part,
1054  const char **path_part)
1055 {
1056  size_t len;
1057  size_t i;
1058  int end;
1059  int pp_state = 0;
1060  const char *post_scheme_part = NULL;
1061 
1062  len = strlen (path);
1063  for (end = 0, i = 0; ! end && i < len; i++)
1064  {
1065  switch (pp_state)
1066  {
1067  case 0:
1068  if ((path[i] == ':') && (i > 0))
1069  {
1070  pp_state += 1;
1071  continue;
1072  }
1073  if (! (((path[i] >= 'A') && (path[i] <= 'Z') ) ||
1074  ((path[i] >= 'a') && (path[i] <= 'z') ) ||
1075  ((path[i] >= '0') && (path[i] <= '9') ) || (path[i] == '+') ||
1076  (path[i] == '-') || (path[i] == '.')))
1077  end = 1;
1078  break;
1079 
1080  case 1:
1081  case 2:
1082  if (path[i] == '/')
1083  {
1084  pp_state += 1;
1085  continue;
1086  }
1087  end = 1;
1088  break;
1089 
1090  case 3:
1091  post_scheme_part = &path[i];
1092  end = 1;
1093  break;
1094 
1095  default:
1096  end = 1;
1097  }
1098  }
1099  if (post_scheme_part == NULL)
1100  return GNUNET_NO;
1101  if (scheme_part)
1102  {
1103  *scheme_part = GNUNET_malloc (post_scheme_part - path + 1);
1104  GNUNET_memcpy (*scheme_part, path, post_scheme_part - path);
1105  (*scheme_part)[post_scheme_part - path] = '\0';
1106  }
1107  if (path_part)
1108  *path_part = post_scheme_part;
1109  return GNUNET_YES;
1110 }
1111 
1112 
1127 int
1129  int can_be_uri,
1130  int *r_is_uri,
1131  char **r_uri_scheme)
1132 {
1133  const char *post_scheme_path;
1134  int is_uri;
1135  char *uri;
1136  /* consider POSIX paths to be absolute too, even on W32,
1137  * as plibc expansion will fix them for us.
1138  */
1139  if (filename[0] == '/')
1140  return GNUNET_YES;
1141  if (can_be_uri)
1142  {
1143  is_uri = GNUNET_STRINGS_parse_uri (filename, &uri, &post_scheme_path);
1144  if (r_is_uri)
1145  *r_is_uri = is_uri;
1146  if (is_uri)
1147  {
1148  if (r_uri_scheme)
1149  *r_uri_scheme = uri;
1150  else
1151  GNUNET_free (uri);
1152 
1153  return GNUNET_STRINGS_path_is_absolute (post_scheme_path,
1154  GNUNET_NO,
1155  NULL,
1156  NULL);
1157  }
1158  }
1159  else
1160  {
1161  if (r_is_uri)
1162  *r_is_uri = GNUNET_NO;
1163  }
1164 
1165  return GNUNET_NO;
1166 }
1167 
1168 
1177 int
1179  enum GNUNET_STRINGS_FilenameCheck checks)
1180 {
1181  struct stat st;
1182 
1183  if ((NULL == filename) || (filename[0] == '\0'))
1184  return GNUNET_SYSERR;
1185  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_ABSOLUTE))
1186  if (! GNUNET_STRINGS_path_is_absolute (filename, GNUNET_NO, NULL, NULL))
1187  return GNUNET_NO;
1188  if (0 != (checks
1191  {
1192  if (0 != lstat (filename, &st))
1193  {
1194  if (0 != (checks & GNUNET_STRINGS_CHECK_EXISTS))
1195  return GNUNET_NO;
1196  else
1197  return GNUNET_SYSERR;
1198  }
1199  }
1200  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_DIRECTORY))
1201  if (! S_ISDIR (st.st_mode))
1202  return GNUNET_NO;
1203  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_LINK))
1204  if (! S_ISLNK (st.st_mode))
1205  return GNUNET_NO;
1206  return GNUNET_YES;
1207 }
1208 
1209 
1222 int
1223 GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
1224  uint16_t addrlen,
1225  struct sockaddr_in6 *r_buf)
1226 {
1227  char zbuf[addrlen + 1];
1228  int ret;
1229  char *port_colon;
1230  unsigned int port;
1231  char dummy[2];
1232 
1233  if (addrlen < 6)
1234  return GNUNET_SYSERR;
1235  GNUNET_memcpy (zbuf, zt_addr, addrlen);
1236  if ('[' != zbuf[0])
1237  {
1239  _ ("IPv6 address did not start with `['\n"));
1240  return GNUNET_SYSERR;
1241  }
1242  zbuf[addrlen] = '\0';
1243  port_colon = strrchr (zbuf, ':');
1244  if (NULL == port_colon)
1245  {
1247  _ ("IPv6 address did contain ':' to separate port number\n"));
1248  return GNUNET_SYSERR;
1249  }
1250  if (']' != *(port_colon - 1))
1251  {
1252  GNUNET_log (
1254  _ ("IPv6 address did contain ']' before ':' to separate port number\n"));
1255  return GNUNET_SYSERR;
1256  }
1257  ret = sscanf (port_colon, ":%u%1s", &port, dummy);
1258  if ((1 != ret) || (port > 65535))
1259  {
1260  GNUNET_log (
1262  _ ("IPv6 address did contain a valid port number after the last ':'\n"));
1263  return GNUNET_SYSERR;
1264  }
1265  *(port_colon - 1) = '\0';
1266  memset (r_buf, 0, sizeof(struct sockaddr_in6));
1267  ret = inet_pton (AF_INET6, &zbuf[1], &r_buf->sin6_addr);
1268  if (ret <= 0)
1269  {
1271  _ ("Invalid IPv6 address `%s': %s\n"),
1272  &zbuf[1],
1273  strerror (errno));
1274  return GNUNET_SYSERR;
1275  }
1276  r_buf->sin6_port = htons (port);
1277  r_buf->sin6_family = AF_INET6;
1278 #if HAVE_SOCKADDR_IN_SIN_LEN
1279  r_buf->sin6_len = (u_char) sizeof(struct sockaddr_in6);
1280 #endif
1281  return GNUNET_OK;
1282 }
1283 
1284 
1296 int
1297 GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr,
1298  uint16_t addrlen,
1299  struct sockaddr_in *r_buf)
1300 {
1301  unsigned int temps[4];
1302  unsigned int port;
1303  unsigned int cnt;
1304  char dummy[2];
1305 
1306  if (addrlen < 9)
1307  return GNUNET_SYSERR;
1308  cnt = sscanf (zt_addr,
1309  "%u.%u.%u.%u:%u%1s",
1310  &temps[0],
1311  &temps[1],
1312  &temps[2],
1313  &temps[3],
1314  &port,
1315  dummy);
1316  if (5 != cnt)
1317  return GNUNET_SYSERR;
1318  for (cnt = 0; cnt < 4; cnt++)
1319  if (temps[cnt] > 0xFF)
1320  return GNUNET_SYSERR;
1321  if (port > 65535)
1322  return GNUNET_SYSERR;
1323  r_buf->sin_family = AF_INET;
1324  r_buf->sin_port = htons (port);
1325  r_buf->sin_addr.s_addr =
1326  htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + temps[3]);
1327 #if HAVE_SOCKADDR_IN_SIN_LEN
1328  r_buf->sin_len = (u_char) sizeof(struct sockaddr_in);
1329 #endif
1330  return GNUNET_OK;
1331 }
1332 
1333 
1345 int
1347  uint16_t addrlen,
1348  struct sockaddr_storage *r_buf)
1349 {
1350  if (addr[0] == '[')
1351  return GNUNET_STRINGS_to_address_ipv6 (addr,
1352  addrlen,
1353  (struct sockaddr_in6 *) r_buf);
1354  return GNUNET_STRINGS_to_address_ipv4 (addr,
1355  addrlen,
1356  (struct sockaddr_in *) r_buf);
1357 }
1358 
1359 
1369 size_t
1371  uint8_t *af,
1372  struct sockaddr **sa)
1373 {
1374  char *cp = GNUNET_strdup (addr);
1375 
1376  *af = AF_UNSPEC;
1377  if ('[' == *addr)
1378  {
1379  /* IPv6 */
1380  *sa = GNUNET_malloc (sizeof(struct sockaddr_in6));
1381  if (GNUNET_OK !=
1383  strlen (cp),
1384  (struct sockaddr_in6 *) *sa))
1385  {
1386  GNUNET_free (*sa);
1387  *sa = NULL;
1388  GNUNET_free (cp);
1389  return 0;
1390  }
1391  *af = AF_INET6;
1392  GNUNET_free (cp);
1393  return sizeof(struct sockaddr_in6);
1394  }
1395  else
1396  {
1397  /* IPv4 */
1398  *sa = GNUNET_malloc (sizeof(struct sockaddr_in));
1399  if (GNUNET_OK !=
1401  strlen (cp),
1402  (struct sockaddr_in *) *sa))
1403  {
1404  GNUNET_free (*sa);
1405  *sa = NULL;
1406  GNUNET_free (cp);
1407  return 0;
1408  }
1409  *af = AF_INET;
1410  GNUNET_free (cp);
1411  return sizeof(struct sockaddr_in);
1412  }
1413 }
1414 
1415 
1420 static char *const *
1421 _make_continuous_arg_copy (int argc, char *const *argv)
1422 {
1423  size_t argvsize = 0;
1424  char **new_argv;
1425  char *p;
1426 
1427  for (int i = 0; i < argc; i++)
1428  argvsize += strlen (argv[i]) + 1 + sizeof(char *);
1429  new_argv = GNUNET_malloc (argvsize + sizeof(char *));
1430  p = (char *) &new_argv[argc + 1];
1431  for (int i = 0; i < argc; i++)
1432  {
1433  new_argv[i] = p;
1434  strcpy (p, argv[i]);
1435  p += strlen (argv[i]) + 1;
1436  }
1437  new_argv[argc] = NULL;
1438  return (char *const *) new_argv;
1439 }
1440 
1441 
1456 int
1458  char *const *argv,
1459  int *u8argc,
1460  char *const **u8argv)
1461 {
1462  char *const *new_argv =
1463  (char *const *) _make_continuous_arg_copy (argc, argv);
1464  *u8argv = new_argv;
1465  *u8argc = argc;
1466  return GNUNET_OK;
1467 }
1468 
1469 
1479 static int
1480 parse_port_policy (const char *port_policy,
1481  struct GNUNET_STRINGS_PortPolicy *pp)
1482 {
1483  const char *pos;
1484  int s;
1485  int e;
1486  char eol[2];
1487 
1488  pos = port_policy;
1489  if ('!' == *pos)
1490  {
1492  pos++;
1493  }
1494  if (2 == sscanf (pos, "%u-%u%1s", &s, &e, eol))
1495  {
1496  if ((0 == s) || (s > 0xFFFF) || (e < s) || (e > 0xFFFF))
1497  {
1498  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Port not in range\n"));
1499  return GNUNET_SYSERR;
1500  }
1501  pp->start_port = (uint16_t) s;
1502  pp->end_port = (uint16_t) e;
1503  return GNUNET_OK;
1504  }
1505  if (1 == sscanf (pos, "%u%1s", &s, eol))
1506  {
1507  if ((0 == s) || (s > 0xFFFF))
1508  {
1509  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Port not in range\n"));
1510  return GNUNET_SYSERR;
1511  }
1512 
1513  pp->start_port = (uint16_t) s;
1514  pp->end_port = (uint16_t) s;
1515  return GNUNET_OK;
1516  }
1518  _ ("Malformed port policy `%s'\n"),
1519  port_policy);
1520  return GNUNET_SYSERR;
1521 }
1522 
1523 
1537 GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1538 {
1539  unsigned int count;
1540  unsigned int i;
1541  unsigned int j;
1542  unsigned int len;
1543  int cnt;
1544  unsigned int pos;
1545  unsigned int temps[8];
1546  int slash;
1548  int colon;
1549  int end;
1550  char *routeList;
1551  char dummy[2];
1552 
1553  if (NULL == routeListX)
1554  return NULL;
1555  len = strlen (routeListX);
1556  if (0 == len)
1557  return NULL;
1558  routeList = GNUNET_strdup (routeListX);
1559  count = 0;
1560  for (i = 0; i < len; i++)
1561  if (routeList[i] == ';')
1562  count++;
1563  result = GNUNET_malloc (sizeof(struct GNUNET_STRINGS_IPv4NetworkPolicy)
1564  * (count + 1));
1565  i = 0;
1566  pos = 0;
1567  while (i < count)
1568  {
1569  for (colon = pos; ':' != routeList[colon]; colon++)
1570  if ((';' == routeList[colon]) || ('\0' == routeList[colon]))
1571  break;
1572  for (end = colon; ';' != routeList[end]; end++)
1573  if ('\0' == routeList[end])
1574  break;
1575  if ('\0' == routeList[end])
1576  break;
1577  routeList[end] = '\0';
1578  if (':' == routeList[colon])
1579  {
1580  routeList[colon] = '\0';
1581  if (GNUNET_OK != parse_port_policy (&routeList[colon + 1], &result[i].pp))
1582  break;
1583  }
1584  cnt = sscanf (&routeList[pos],
1585  "%u.%u.%u.%u/%u.%u.%u.%u%1s",
1586  &temps[0],
1587  &temps[1],
1588  &temps[2],
1589  &temps[3],
1590  &temps[4],
1591  &temps[5],
1592  &temps[6],
1593  &temps[7],
1594  dummy);
1595  if (8 == cnt)
1596  {
1597  for (j = 0; j < 8; j++)
1598  if (temps[j] > 0xFF)
1599  {
1601  _ ("Invalid format for IP: `%s'\n"),
1602  &routeList[pos]);
1603  GNUNET_free (result);
1604  GNUNET_free (routeList);
1605  return NULL;
1606  }
1607  result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16)
1608  + (temps[2] << 8) + temps[3]);
1609  result[i].netmask.s_addr = htonl ((temps[4] << 24) + (temps[5] << 16)
1610  + (temps[6] << 8) + temps[7]);
1611  pos = end + 1;
1612  i++;
1613  continue;
1614  }
1615  /* try second notation */
1616  cnt = sscanf (&routeList[pos],
1617  "%u.%u.%u.%u/%u%1s",
1618  &temps[0],
1619  &temps[1],
1620  &temps[2],
1621  &temps[3],
1622  &slash,
1623  dummy);
1624  if (5 == cnt)
1625  {
1626  for (j = 0; j < 4; j++)
1627  if (temps[j] > 0xFF)
1628  {
1630  _ ("Invalid format for IP: `%s'\n"),
1631  &routeList[pos]);
1632  GNUNET_free (result);
1633  GNUNET_free (routeList);
1634  return NULL;
1635  }
1636  result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16)
1637  + (temps[2] << 8) + temps[3]);
1638  if ((slash <= 32) && (slash >= 0))
1639  {
1640  result[i].netmask.s_addr = 0;
1641  while (slash > 0)
1642  {
1643  result[i].netmask.s_addr =
1644  (result[i].netmask.s_addr >> 1) + 0x80000000;
1645  slash--;
1646  }
1647  result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1648  pos = end + 1;
1649  i++;
1650  continue;
1651  }
1652  else
1653  {
1655  _ ("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
1656  slash);
1657  GNUNET_free (result);
1658  GNUNET_free (routeList);
1659  return NULL; /* error */
1660  }
1661  }
1662  /* try third notation */
1663  slash = 32;
1664  cnt = sscanf (&routeList[pos],
1665  "%u.%u.%u.%u%1s",
1666  &temps[0],
1667  &temps[1],
1668  &temps[2],
1669  &temps[3],
1670  dummy);
1671  if (4 == cnt)
1672  {
1673  for (j = 0; j < 4; j++)
1674  if (temps[j] > 0xFF)
1675  {
1677  _ ("Invalid format for IP: `%s'\n"),
1678  &routeList[pos]);
1679  GNUNET_free (result);
1680  GNUNET_free (routeList);
1681  return NULL;
1682  }
1683  result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16)
1684  + (temps[2] << 8) + temps[3]);
1685  result[i].netmask.s_addr = 0;
1686  while (slash > 0)
1687  {
1688  result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
1689  slash--;
1690  }
1691  result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1692  pos = end + 1;
1693  i++;
1694  continue;
1695  }
1697  _ ("Invalid format for IP: `%s'\n"),
1698  &routeList[pos]);
1699  GNUNET_free (result);
1700  GNUNET_free (routeList);
1701  return NULL; /* error */
1702  }
1703  if (pos < strlen (routeList))
1704  {
1706  _ ("Invalid format: `%s'\n"),
1707  &routeListX[pos]);
1708  GNUNET_free (result);
1709  GNUNET_free (routeList);
1710  return NULL; /* oops */
1711  }
1712  GNUNET_free (routeList);
1713  return result; /* ok */
1714 }
1715 
1716 
1729 GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX)
1730 {
1731  unsigned int count;
1732  unsigned int i;
1733  unsigned int len;
1734  unsigned int pos;
1735  int start;
1736  int slash;
1737  int ret;
1738  char *routeList;
1740  unsigned int bits;
1741  unsigned int off;
1742  int save;
1743  int colon;
1744  char dummy[2];
1745 
1746  if (NULL == routeListX)
1747  return NULL;
1748  len = strlen (routeListX);
1749  if (0 == len)
1750  return NULL;
1751  routeList = GNUNET_strdup (routeListX);
1752  count = 0;
1753  for (i = 0; i < len; i++)
1754  if (';' == routeList[i])
1755  count++;
1756  if (';' != routeList[len - 1])
1757  {
1759  _ ("Invalid network notation (does not end with ';': `%s')\n"),
1760  routeList);
1761  GNUNET_free (routeList);
1762  return NULL;
1763  }
1764 
1765  result = GNUNET_malloc (sizeof(struct GNUNET_STRINGS_IPv6NetworkPolicy)
1766  * (count + 1));
1767  i = 0;
1768  pos = 0;
1769  while (i < count)
1770  {
1771  start = pos;
1772  while (';' != routeList[pos])
1773  pos++;
1774  slash = pos;
1775  while ((slash >= start) && (routeList[slash] != '/'))
1776  slash--;
1777 
1778  if (slash < start)
1779  {
1780  memset (&result[i].netmask, 0xFF, sizeof(struct in6_addr));
1781  slash = pos;
1782  }
1783  else
1784  {
1785  routeList[pos] = '\0';
1786  for (colon = pos; ':' != routeList[colon]; colon--)
1787  if ('/' == routeList[colon])
1788  break;
1789  if (':' == routeList[colon])
1790  {
1791  routeList[colon] = '\0';
1792  if (GNUNET_OK !=
1793  parse_port_policy (&routeList[colon + 1], &result[i].pp))
1794  {
1795  GNUNET_free (result);
1796  GNUNET_free (routeList);
1797  return NULL;
1798  }
1799  }
1800  ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
1801  if (ret <= 0)
1802  {
1803  save = errno;
1804  if ((1 != sscanf (&routeList[slash + 1], "%u%1s", &bits, dummy)) ||
1805  (bits > 128))
1806  {
1807  if (0 == ret)
1809  _ ("Wrong format `%s' for netmask\n"),
1810  &routeList[slash + 1]);
1811  else
1812  {
1813  errno = save;
1814  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "inet_pton");
1815  }
1816  GNUNET_free (result);
1817  GNUNET_free (routeList);
1818  return NULL;
1819  }
1820  off = 0;
1821  while (bits > 8)
1822  {
1823  result[i].netmask.s6_addr[off++] = 0xFF;
1824  bits -= 8;
1825  }
1826  while (bits > 0)
1827  {
1828  result[i].netmask.s6_addr[off] =
1829  (result[i].netmask.s6_addr[off] >> 1) + 0x80;
1830  bits--;
1831  }
1832  }
1833  }
1834  routeList[slash] = '\0';
1835  ret = inet_pton (AF_INET6, &routeList[start], &result[i].network);
1836  if (ret <= 0)
1837  {
1838  if (0 == ret)
1840  _ ("Wrong format `%s' for network\n"),
1841  &routeList[slash + 1]);
1842  else
1843  LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
1844  GNUNET_free (result);
1845  GNUNET_free (routeList);
1846  return NULL;
1847  }
1848  pos++;
1849  i++;
1850  }
1851  GNUNET_free (routeList);
1852  return result;
1853 }
1854 
1855 
1858 #define FILLCHAR '='
1859 static char *cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1860  "abcdefghijklmnopqrstuvwxyz"
1861  "0123456789+/";
1862 
1863 
1873 size_t
1874 GNUNET_STRINGS_base64_encode (const void *in, size_t len, char **output)
1875 {
1876  const char *data = in;
1877  size_t ret;
1878  char *opt;
1879 
1880  ret = 0;
1881  GNUNET_assert (len / 4 < SIZE_MAX);
1882  opt = GNUNET_malloc (2 + (len * 4 / 3) + 8);
1883  for (size_t i = 0; i < len; ++i)
1884  {
1885  char c;
1886 
1887  c = (data[i] >> 2) & 0x3f;
1888  opt[ret++] = cvt[(int) c];
1889  c = (data[i] << 4) & 0x3f;
1890  if (++i < len)
1891  c |= (data[i] >> 4) & 0x0f;
1892  opt[ret++] = cvt[(int) c];
1893  if (i < len)
1894  {
1895  c = (data[i] << 2) & 0x3f;
1896  if (++i < len)
1897  c |= (data[i] >> 6) & 0x03;
1898  opt[ret++] = cvt[(int) c];
1899  }
1900  else
1901  {
1902  ++i;
1903  opt[ret++] = FILLCHAR;
1904  }
1905  if (i < len)
1906  {
1907  c = data[i] & 0x3f;
1908  opt[ret++] = cvt[(int) c];
1909  }
1910  else
1911  {
1912  opt[ret++] = FILLCHAR;
1913  }
1914  }
1915  *output = opt;
1916  return ret;
1917 }
1918 
1919 
1929 size_t
1930 GNUNET_STRINGS_base64url_encode (const void *in, size_t len, char **output)
1931 {
1932  char *enc;
1933  size_t pos;
1934 
1935  GNUNET_STRINGS_base64_encode (in, len, output);
1936  enc = *output;
1937  /* Replace with correct characters for base64url */
1938  pos = 0;
1939  while ('\0' != enc[pos])
1940  {
1941  if ('+' == enc[pos])
1942  enc[pos] = '-';
1943  if ('/' == enc[pos])
1944  enc[pos] = '_';
1945  if ('=' == enc[pos])
1946  {
1947  enc[pos] = '\0';
1948  break;
1949  }
1950  pos++;
1951  }
1952  return strlen (enc);
1953 }
1954 
1955 
1956 #define cvtfind(a) \
1957  ((((a) >= 'A') && ((a) <= 'Z')) \
1958  ? (a) - 'A' \
1959  : (((a) >= 'a') && ((a) <= 'z')) \
1960  ? (a) - 'a' + 26 \
1961  : (((a) >= '0') && ((a) <= '9')) \
1962  ? (a) - '0' + 52 \
1963  : ((a) == '+') ? 62 : ((a) == '/') ? 63 : -1)
1964 
1965 
1975 size_t
1976 GNUNET_STRINGS_base64_decode (const char *data, size_t len, void **out)
1977 {
1978  char *output;
1979  size_t ret = 0;
1980 
1981 #define CHECK_CRLF \
1982  while (data[i] == '\r' || data[i] == '\n') \
1983  { \
1984  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, \
1985  "ignoring CR/LF\n"); \
1986  i++; \
1987  if (i >= len) \
1988  goto END; \
1989  }
1990 
1991  GNUNET_assert (len / 3 < SIZE_MAX);
1992  output = GNUNET_malloc ((len * 3 / 4) + 8);
1994  "base64_decode decoding len=%d\n",
1995  (int) len);
1996  for (size_t i = 0; i < len; ++i)
1997  {
1998  char c;
1999  char c1;
2000 
2001  CHECK_CRLF;
2002  if (FILLCHAR == data[i])
2003  break;
2004  c = (char) cvtfind (data[i]);
2005  ++i;
2006  CHECK_CRLF;
2007  c1 = (char) cvtfind (data[i]);
2008  c = (c << 2) | ((c1 >> 4) & 0x3);
2009  output[ret++] = c;
2010  if (++i < len)
2011  {
2012  CHECK_CRLF;
2013  c = data[i];
2014  if (FILLCHAR == c)
2015  break;
2016  c = (char) cvtfind (c);
2017  c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
2018  output[ret++] = c1;
2019  }
2020  if (++i < len)
2021  {
2022  CHECK_CRLF;
2023  c1 = data[i];
2024  if (FILLCHAR == c1)
2025  break;
2026 
2027  c1 = (char) cvtfind (c1);
2028  c = ((c << 6) & 0xc0) | c1;
2029  output[ret++] = c;
2030  }
2031  }
2032 END:
2033  *out = output;
2034  return ret;
2035 }
2036 
2037 
2047 size_t
2048 GNUNET_STRINGS_base64url_decode (const char *data, size_t len, void **out)
2049 {
2050  char *s;
2051  int padding;
2052  size_t ret;
2053 
2054  /* make enough space for padding */
2055  GNUNET_assert (len < SIZE_MAX - 3);
2056  s = GNUNET_malloc (len + 3);
2057  memcpy (s, data, len);
2058 
2059  for (int i = 0; i < strlen (s); i++)
2060  {
2061  if (s[i] == '-')
2062  s[i] = '+';
2063  if (s[i] == '_')
2064  s[i] = '/';
2065  }
2066  padding = len % 4;
2067  switch (padding) // Pad with trailing '='s
2068  {
2069  case 0:
2070  break; // No pad chars in this case
2071  case 2:
2072  memcpy (&s[len],
2073  "==",
2074  2);
2075  len += 2;
2076  break; // Two pad chars
2077  case 3:
2078  s[len] = '=';
2079  len++;
2080  break; // One pad char
2081  default:
2082  GNUNET_assert (0);
2083  break;
2084  }
2085  ret = GNUNET_STRINGS_base64_decode (s, len, out);
2086  GNUNET_free (s);
2087  return ret;
2088 }
2089 
2090 
2091 /* end of strings.c */
static void do_round(void *cls)
Send out PUSHes and PULLs, possibly update #view, samplers.
unsigned long long value
Factor to apply for this unit.
Definition: strings.c:245
struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
Parse an IPv4 network policy.
Definition: strings.c:1537
#define CHECK_CRLF
#define FILLCHAR
******************** Base64 encoding
Definition: strings.c:1858
uint64_t rel_value_us
The actual value.
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:35
static int parse_port_policy(const char *port_policy, struct GNUNET_STRINGS_PortPolicy *pp)
Parse the given port policy.
Definition: strings.c:1480
char * GNUNET_STRINGS_conv(const char *input, size_t len, const char *input_charset, const char *output_charset)
Convert the len characters long character sequence given in input that is in the given input charset ...
Definition: strings.c:451
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
int GNUNET_STRINGS_parse_uri(const char *path, char **scheme_part, const char **path_part)
Parse a path that might be an URI.
Definition: strings.c:1052
struct GNUNET_STRINGS_PortPolicy pp
Policy for port access.
#define GNUNET_THREAD_LOCAL
Definition: platform.h:259
static struct GNUNET_SCHEDULER_Task * tt
Task scheduled to handle timeout.
Definition: gnunet-abd.c:76
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
char * GNUNET_STRINGS_byte_size_fancy(unsigned long long size)
Convert a given filesize into a fancy human-readable format.
Definition: strings.c:176
uint16_t start_port
Starting port range (0 if none given).
static int convert_with_table(const char *input, const struct ConversionTable *table, unsigned long long *output)
Convert a string of the form "4 X 5 Y" into a numeric value by interpreting "X" and "Y" as units and ...
Definition: strings.c:261
struct GNUNET_STRINGS_IPv6NetworkPolicy * GNUNET_STRINGS_parse_ipv6_policy(const char *routeListX)
Parse an IPv6 network policy.
Definition: strings.c:1729
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1457
int GNUNET_STRINGS_path_is_absolute(const char *filename, int can_be_uri, int *r_is_uri, char **r_uri_scheme)
Check whether filename is absolute or not, and if it&#39;s an URI.
Definition: strings.c:1128
#define cvtfind(a)
Definition: strings.c:1956
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int GNUNET_STRINGS_fancy_time_to_relative(const char *fancy_time, struct GNUNET_TIME_Relative *rtime)
Convert a given fancy human-readable time to our internal representation.
Definition: strings.c:355
Check that the path is an absolute path.
network in CIDR notation for IPV6.
int negate_portrange
GNUNET_YES if the port range should be negated ("!" in policy).
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
int GNUNET_STRINGS_fancy_time_to_absolute(const char *fancy_time, struct GNUNET_TIME_Absolute *atime)
Convert a given fancy human-readable time to our internal representation.
Definition: strings.c:406
static struct Experiment * e
struct in_addr netmask
IPv4 netmask.
We&#39;re done processing.
int GNUNET_STRINGS_fancy_size_to_bytes(const char *fancy_size, unsigned long long *size)
Convert a given fancy human-readable size to bytes.
Definition: strings.c:323
static char *const * _make_continuous_arg_copy(int argc, char *const *argv)
Makes a copy of argv that consists of a single memory chunk that can be freed with a single call to G...
Definition: strings.c:1421
static struct GNUNET_SCHEDULER_Task * t
Main task.
Check that it exists.
static void save()
Write persistent statistics to disk.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
struct in6_addr netmask
IPv6 netmask.
uint64_t abs_value_us
The actual value.
#define SIZE_MAX
Definition: platform.h:220
static char * cvt
Definition: strings.c:1859
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
size_t GNUNET_STRINGS_base64url_encode(const void *in, size_t len, char **output)
Encode into Base64url.
Definition: strings.c:1930
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:184
struct in_addr network
IPv4 address.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
int GNUNET_STRINGS_to_address_ipv4(const char *zt_addr, uint16_t addrlen, struct sockaddr_in *r_buf)
Tries to convert &#39;zt_addr&#39; string to an IPv4 address.
Definition: strings.c:1297
unsigned int GNUNET_STRINGS_buffer_tokenize(const char *buffer, size_t size, unsigned int count,...)
Given a buffer of a given size, find "count" 0-terminated strings in the buffer and assign the count ...
Definition: strings.c:136
cryptographic primitives for GNUnet
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
void GNUNET_STRINGS_utf8_toupper(const char *input, char *output)
Convert the utf-8 input string to uppercase.
Definition: strings.c:592
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
static struct PeerEntry ** table
Table with our interned peer IDs.
Definition: peer.c:55
char * GNUNET_STRINGS_pp2s(const struct GNUNET_PeerIdentity *pids, unsigned int num_pids)
Convert a peer path to a human-readable string.
Definition: strings.c:100
#define DIR_SEPARATOR_STR
Definition: platform.h:171
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:701
IPV4 network in CIDR notation.
static char buf[2048]
static char * filename
static int result
Global testing status.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
char * GNUNET_STRINGS_from_utf8(const char *input, size_t len, const char *charset)
Convert the len bytes-long UTF-8 string given in input to the given charset.
Definition: strings.c:548
size_t GNUNET_STRINGS_buffer_fill(char *buffer, size_t size, unsigned int count,...)
Fill a buffer of the given size with count 0-terminated strings (given as varargs).
Definition: strings.c:65
Unit conversion table entry for &#39;convert_with_table&#39;.
Definition: strings.c:235
size_t GNUNET_STRINGS_parse_socket_addr(const char *addr, uint8_t *af, struct sockaddr **sa)
Parse an address given as a string into a struct sockaddr.
Definition: strings.c:1370
static OpusDecoder * dec
OPUS decoder.
#define LOG(kind,...)
Definition: strings.c:37
static unsigned int getValue__(unsigned char a)
Get the decoded value corresponding to a character according to Crockford Base32 encoding.
Definition: strings.c:808
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **out)
Decode from Base64.
Definition: strings.c:1976
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1874
#define DIR_SEPARATOR
Definition: platform.h:170
const char * GNUNET_STRINGS_get_short_name(const char *filename)
"man basename" Returns a pointer to a part of filename (allocates nothing)!
Definition: strings.c:789
static unsigned int size
Size of the "table".
Definition: peer.c:67
int GNUNET_STRINGS_check_filename(const char *filename, enum GNUNET_STRINGS_FilenameCheck checks)
Perform checks on filename.
Definition: strings.c:1178
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition: strings.c:617
char * getenv()
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
#define S_ISLNK(m)
Definition: disk.c:61
The identity of the host (wraps the signing key of the peer).
uint16_t end_port
End of port range (0 if none given).
#define LOG_STRERROR(kind, syscall)
Definition: strings.c:39
static uint16_t port
Port number.
Definition: gnunet-bcd.c:82
static OpusEncoder * enc
OPUS encoder.
int GNUNET_STRINGS_to_address_ipv6(const char *zt_addr, uint16_t addrlen, struct sockaddr_in6 *r_buf)
Tries to convert zt_addr string to an IPv6 address.
Definition: strings.c:1223
#define GNUNET_log(kind,...)
GNUNET_STRINGS_FilenameCheck
Flags for what we should check a file for.
char * GNUNET_STRINGS_to_utf8(const char *input, size_t len, const char *charset)
Convert the len characters long character sequence given in input that is in the given charset to UTF...
Definition: strings.c:525
struct GNUNET_STRINGS_PortPolicy pp
Policy for port access.
struct in6_addr network
IPv6 address.
Time for absolute times used by GNUnet, in microseconds.
Check that it is a link.
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:935
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
"asctime", except for GNUnet time.
Definition: strings.c:756
uint32_t data
The data value.
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:220
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
const char * name
Name of the unit (or NULL for end of table).
Definition: strings.c:240
static size_t strnlen(const char *s, size_t n)
int GNUNET_STRINGS_to_address_ip(const char *addr, uint16_t addrlen, struct sockaddr_storage *r_buf)
Tries to convert addr string to an IP (v4 or v6) address.
Definition: strings.c:1346
size_t GNUNET_STRINGS_base64url_decode(const char *data, size_t len, void **out)
Decode from Base64url.
Definition: strings.c:2048
#define GNUNET_malloc(size)
Wrapper around malloc.
int GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert Crockford Base32hex encoding back to data.
Definition: strings.c:970
char * GNUNET_STRINGS_data_to_string(const void *data, size_t size, char *out, size_t out_size)
Convert binary data to ASCII encoding using Crockford Base32 encoding.
Definition: strings.c:870
Check that it is a directory.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
void GNUNET_STRINGS_utf8_tolower(const char *input, char *output)
Convert the utf-8 input string to lowercase.
Definition: strings.c:567
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...