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_buffer_lib.h"
33 #include "gnunet_strings_lib.h"
34 #include <unicase.h>
35 #include <unistr.h>
36 #include <uniconv.h>
37 
38 #define LOG(kind, ...) GNUNET_log_from (kind, "util-strings", __VA_ARGS__)
39 
40 #define LOG_STRERROR(kind, syscall) \
41  GNUNET_log_from_strerror (kind, "util-strings", syscall)
42 
43 
65 size_t
67  size_t size,
68  unsigned int count, ...)
69 {
70  size_t needed;
71  va_list ap;
72 
73  needed = 0;
74  va_start (ap, count);
75  while (count > 0)
76  {
77  const char *s = va_arg (ap, const char *);
78  size_t slen = strlen (s) + 1;
79 
80  GNUNET_assert (slen <= size - needed);
81  if (NULL != buffer)
82  GNUNET_memcpy (&buffer[needed],
83  s,
84  slen);
85  needed += slen;
86  count--;
87  }
88  va_end (ap);
89  return needed;
90 }
91 
92 
100 char *
102  unsigned int num_pids)
103 {
104  char *buf;
105  size_t off;
106  size_t plen = num_pids * 5 + 1;
107 
108  GNUNET_assert (num_pids < UINT32_MAX / 5);
109  off = 0;
110  buf = GNUNET_malloc (plen);
111  for (unsigned int i = 0; i < num_pids; i++)
112  {
113  off += GNUNET_snprintf (&buf[off],
114  plen - off,
115  "%s%s",
116  GNUNET_i2s (&pids[i]),
117  (i == num_pids - 1) ? "" : "-");
118  }
119  return buf;
120 }
121 
122 
136 unsigned int
137 GNUNET_STRINGS_buffer_tokenize (const char *buffer,
138  size_t size,
139  unsigned int count,
140  ...)
141 {
142  unsigned int start;
143  unsigned int needed;
144  const char **r;
145  va_list ap;
146 
147  needed = 0;
148  va_start (ap, count);
149  while (count > 0)
150  {
151  r = va_arg (ap, const char **);
152 
153  start = needed;
154  while ((needed < size) && (buffer[needed] != '\0'))
155  needed++;
156  if (needed == size)
157  {
158  va_end (ap);
159  return 0; /* error */
160  }
161  *r = &buffer[start];
162  needed++; /* skip 0-termination */
163  count--;
164  }
165  va_end (ap);
166  return needed;
167 }
168 
169 
176 char *
178 {
179  const char *unit = _ (/* size unit */ "b");
180  char *ret;
181 
182  if (size > 5 * 1024)
183  {
184  size = size / 1024;
185  unit = "KiB";
186  if (size > 5 * 1024)
187  {
188  size = size / 1024;
189  unit = "MiB";
190  if (size > 5 * 1024)
191  {
192  size = size / 1024;
193  unit = "GiB";
194  if (size > 5 * 1024)
195  {
196  size = size / 1024;
197  unit = "TiB";
198  }
199  }
200  }
201  }
202  ret = GNUNET_malloc (32);
203  GNUNET_snprintf (ret, 32, "%llu %s", size, unit);
204  return ret;
205 }
206 
207 
220 size_t
221 GNUNET_strlcpy (char *dst, const char *src, size_t n)
222 {
223  size_t slen;
224 
225  GNUNET_assert (0 != n);
226  slen = strnlen (src, n - 1);
227  memcpy (dst, src, slen);
228  dst[slen] = '\0';
229  return slen;
230 }
231 
232 
237 {
241  const char *name;
242 
246  unsigned long long value;
247 };
248 
249 
261 static int
262 convert_with_table (const char *input,
263  const struct ConversionTable *table,
264  unsigned long long *output)
265 {
266  unsigned long long ret;
267  char *in;
268  const char *tok;
269  unsigned long long last;
270  unsigned int i;
271  char *sptr;
272 
273  ret = 0;
274  last = 0;
275  in = GNUNET_strdup (input);
276  for (tok = strtok_r (in, " ", &sptr);
277  tok != NULL;
278  tok = strtok_r (NULL, " ", &sptr))
279  {
280  do
281  {
282  i = 0;
283  while ((table[i].name != NULL) && (0 != strcasecmp (table[i].name, tok)))
284  i++;
285  if (table[i].name != NULL)
286  {
287  last *= table[i].value;
288  break; /* next tok */
289  }
290  else
291  {
292  char *endptr;
293  ret += last;
294  errno = 0;
295  last = strtoull (tok, &endptr, 10);
296  if ((0 != errno) || (endptr == tok))
297  {
298  GNUNET_free (in);
299  return GNUNET_SYSERR; /* expected number */
300  }
301  if ('\0' == endptr[0])
302  break; /* next tok */
303  else
304  tok = endptr; /* and re-check (handles times like "10s") */
305  }
306  }
307  while (GNUNET_YES);
308  }
309  ret += last;
310  *output = ret;
311  GNUNET_free (in);
312  return GNUNET_OK;
313 }
314 
315 
323 int
324 GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
325  unsigned long long *size)
326 {
327  static const struct ConversionTable table[] =
328  { { "B", 1 },
329  { "KiB", 1024 },
330  { "kB", 1000 },
331  { "MiB", 1024 * 1024 },
332  { "MB", 1000 * 1000 },
333  { "GiB", 1024 * 1024 * 1024 },
334  { "GB", 1000 * 1000 * 1000 },
335  { "TiB", 1024LL * 1024LL * 1024LL * 1024LL },
336  { "TB", 1000LL * 1000LL * 1000LL * 1024LL },
337  { "PiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL },
338  { "PB", 1000LL * 1000LL * 1000LL * 1024LL * 1000LL },
339  { "EiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL },
340  { "EB", 1000LL * 1000LL * 1000LL * 1024LL * 1000LL * 1000LL },
341  { NULL, 0 } };
342 
343  return convert_with_table (fancy_size, table, size);
344 }
345 
346 
355 int
357  struct GNUNET_TIME_Relative *rtime)
358 {
359  static const struct ConversionTable table[] =
360  { { "us", 1 },
361  { "ms", 1000 },
362  { "s", 1000 * 1000LL },
363  { "second", 1000 * 1000LL },
364  { "seconds", 1000 * 1000LL },
365  { "\"", 1000 * 1000LL },
366  { "m", 60 * 1000 * 1000LL },
367  { "min", 60 * 1000 * 1000LL },
368  { "minute", 60 * 1000 * 1000LL },
369  { "minutes", 60 * 1000 * 1000LL },
370  { "'", 60 * 1000 * 1000LL },
371  { "h", 60 * 60 * 1000 * 1000LL },
372  { "hour", 60 * 60 * 1000 * 1000LL },
373  { "hours", 60 * 60 * 1000 * 1000LL },
374  { "d", 24 * 60 * 60 * 1000LL * 1000LL },
375  { "day", 24 * 60 * 60 * 1000LL * 1000LL },
376  { "days", 24 * 60 * 60 * 1000LL * 1000LL },
377  { "week", 7 * 24 * 60 * 60 * 1000LL * 1000LL },
378  { "weeks", 7 * 24 * 60 * 60 * 1000LL * 1000LL },
379  { "year", 31536000000000LL /* year */ },
380  { "years", 31536000000000LL /* year */ },
381  { "a", 31536000000000LL /* year */ },
382  { NULL, 0 } };
383  int ret;
384  unsigned long long val;
385 
386  if (0 == strcasecmp ("forever", fancy_time))
387  {
389  return GNUNET_OK;
390  }
391  ret = convert_with_table (fancy_time, table, &val);
392  rtime->rel_value_us = (uint64_t) val;
393  return ret;
394 }
395 
396 
406 int
408  struct GNUNET_TIME_Absolute *atime)
409 {
410  struct tm tv;
411  time_t t;
412  const char *eos;
413 
414  if (0 == strcasecmp ("end of time", fancy_time))
415  {
417  return GNUNET_OK;
418  }
419  eos = &fancy_time[strlen (fancy_time)];
420  memset (&tv, 0, sizeof(tv));
421  if ((eos != strptime (fancy_time, "%a %b %d %H:%M:%S %Y", &tv)) &&
422  (eos != strptime (fancy_time, "%c", &tv)) &&
423  (eos != strptime (fancy_time, "%Ec", &tv)) &&
424  (eos != strptime (fancy_time, "%Y-%m-%d %H:%M:%S", &tv)) &&
425  (eos != strptime (fancy_time, "%Y-%m-%d %H:%M", &tv)) &&
426  (eos != strptime (fancy_time, "%x", &tv)) &&
427  (eos != strptime (fancy_time, "%Ex", &tv)) &&
428  (eos != strptime (fancy_time, "%Y-%m-%d", &tv)) &&
429  (eos != strptime (fancy_time, "%Y-%m", &tv)) &&
430  (eos != strptime (fancy_time, "%Y", &tv)))
431  return GNUNET_SYSERR;
432  t = mktime (&tv);
433  atime->abs_value_us = (uint64_t) ((uint64_t) t * 1000LL * 1000LL);
434  return GNUNET_OK;
435 }
436 
437 
451 char *
452 GNUNET_STRINGS_conv (const char *input,
453  size_t len,
454  const char *input_charset,
455  const char *output_charset)
456 {
457  char *ret;
458  uint8_t *u8_string;
459  char *encoded_string;
460  size_t u8_string_length;
461  size_t encoded_string_length;
462 
463  u8_string = u8_conv_from_encoding (input_charset,
464  iconveh_error,
465  input,
466  len,
467  NULL,
468  NULL,
469  &u8_string_length);
470  if (NULL == u8_string)
471  {
472  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_from_encoding");
473  goto fail;
474  }
475  if (0 == strcmp (output_charset, "UTF-8"))
476  {
477  ret = GNUNET_malloc (u8_string_length + 1);
478  GNUNET_memcpy (ret, u8_string, u8_string_length);
479  ret[u8_string_length] = '\0';
480  free (u8_string);
481  return ret;
482  }
483  encoded_string = u8_conv_to_encoding (output_charset,
484  iconveh_error,
485  u8_string,
486  u8_string_length,
487  NULL,
488  NULL,
489  &encoded_string_length);
490  free (u8_string);
491  if (NULL == encoded_string)
492  {
493  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_to_encoding");
494  goto fail;
495  }
496  ret = GNUNET_malloc (encoded_string_length + 1);
497  GNUNET_memcpy (ret, encoded_string, encoded_string_length);
498  ret[encoded_string_length] = '\0';
499  free (encoded_string);
500  return ret;
501 fail:
503  _ ("Character sets requested were `%s'->`%s'\n"),
504  "UTF-8",
505  output_charset);
506  ret = GNUNET_malloc (len + 1);
507  GNUNET_memcpy (ret, input, len);
508  ret[len] = '\0';
509  return ret;
510 }
511 
512 
525 char *
526 GNUNET_STRINGS_to_utf8 (const char *input,
527  size_t len,
528  const char *charset)
529 {
530  return GNUNET_STRINGS_conv (input,
531  len,
532  charset,
533  "UTF-8");
534 }
535 
536 
548 char *
549 GNUNET_STRINGS_from_utf8 (const char *input,
550  size_t len,
551  const char *charset)
552 {
553  return GNUNET_STRINGS_conv (input,
554  len,
555  "UTF-8",
556  charset);
557 }
558 
559 
567 void
568 GNUNET_STRINGS_utf8_tolower (const char *input, char *output)
569 {
570  uint8_t *tmp_in;
571  size_t len;
572 
573  tmp_in = u8_tolower ((uint8_t *) input,
574  strlen ((char *) input),
575  NULL,
576  UNINORM_NFD,
577  NULL,
578  &len);
579  GNUNET_memcpy (output, tmp_in, len);
580  output[len] = '\0';
581  free (tmp_in);
582 }
583 
584 
592 void
593 GNUNET_STRINGS_utf8_toupper (const char *input, char *output)
594 {
595  uint8_t *tmp_in;
596  size_t len;
597 
598  tmp_in = u8_toupper ((uint8_t *) input,
599  strlen ((char *) input),
600  NULL,
601  UNINORM_NFD,
602  NULL,
603  &len);
604  GNUNET_memcpy (output, tmp_in, len);
605  output[len] = '\0';
606  free (tmp_in);
607 }
608 
609 
617 char *
619 {
620  char *buffer;
621  size_t len;
622  char *fm;
623  const char *fil_ptr;
624 
625  if (fil == NULL)
626  return NULL;
627 
628  if (fil[0] == DIR_SEPARATOR)
629  /* absolute path, just copy */
630  return GNUNET_strdup (fil);
631  if (fil[0] == '~')
632  {
633  fm = getenv ("HOME");
634  if (fm == NULL)
635  {
637  _ ("Failed to expand `$HOME': environment variable `HOME' not set"));
638  return NULL;
639  }
640  fm = GNUNET_strdup (fm);
641  /* do not copy '~' */
642  fil_ptr = fil + 1;
643 
644  /* skip over dir seperator to be consistent */
645  if (fil_ptr[0] == DIR_SEPARATOR)
646  fil_ptr++;
647  }
648  else
649  {
650  /* relative path */
651  fil_ptr = fil;
652  len = 512;
653  fm = NULL;
654  while (1)
655  {
656  buffer = GNUNET_malloc (len);
657  if (getcwd (buffer, len) != NULL)
658  {
659  fm = buffer;
660  break;
661  }
662  if ((errno == ERANGE) && (len < 1024 * 1024 * 4))
663  {
664  len *= 2;
665  GNUNET_free (buffer);
666  continue;
667  }
668  GNUNET_free (buffer);
669  break;
670  }
671  if (fm == NULL)
672  {
674  buffer = getenv ("PWD"); /* alternative */
675  if (buffer != NULL)
676  fm = GNUNET_strdup (buffer);
677  }
678  if (fm == NULL)
679  fm = GNUNET_strdup ("./"); /* give up */
680  }
681  GNUNET_asprintf (&buffer,
682  "%s%s%s",
683  fm,
684  (fm[strlen (fm) - 1] == DIR_SEPARATOR) ? ""
686  fil_ptr);
687  GNUNET_free (fm);
688  return buffer;
689 }
690 
691 
701 const char *
703  int do_round)
704 {
705  static GNUNET_THREAD_LOCAL char buf[128];
706  const char *unit = _ (/* time unit */ "┬Ás");
707  uint64_t dval = delta.rel_value_us;
708 
709  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == delta.rel_value_us)
710  return _ ("forever");
711  if (0 == delta.rel_value_us)
712  return _ ("0 ms");
713  if (((GNUNET_YES == do_round) && (dval > 5 * 1000)) || (0 == (dval % 1000)))
714  {
715  dval = dval / 1000;
716  unit = _ (/* time unit */ "ms");
717  if (((GNUNET_YES == do_round) && (dval > 5 * 1000)) || (0 == (dval % 1000)))
718  {
719  dval = dval / 1000;
720  unit = _ (/* time unit */ "s");
721  if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
722  {
723  dval = dval / 60;
724  unit = _ (/* time unit */ "m");
725  if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
726  {
727  dval = dval / 60;
728  unit = _ (/* time unit */ "h");
729  if (((GNUNET_YES == do_round) && (dval > 5 * 24)) ||
730  (0 == (dval % 24)))
731  {
732  dval = dval / 24;
733  if (1 == dval)
734  unit = _ (/* time unit */ "day");
735  else
736  unit = _ (/* time unit */ "days");
737  }
738  }
739  }
740  }
741  }
742  GNUNET_snprintf (buf, sizeof(buf), "%llu %s", dval, unit);
743  return buf;
744 }
745 
746 
756 const char *
758 {
759  static GNUNET_THREAD_LOCAL char buf[255];
760  time_t tt;
761  struct tm *tp;
762 
763  if (t.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
764  return _ ("end of time");
765  tt = t.abs_value_us / 1000LL / 1000LL;
766  tp = localtime (&tt);
767  /* This is hacky, but i don't know a way to detect libc character encoding.
768  * Just expect utf8 from glibc these days.
769  * As for msvcrt, use the wide variant, which always returns utf16
770  * (otherwise we'd have to detect current codepage or use W32API character
771  * set conversion routines to convert to UTF8).
772  */strftime (buf, sizeof(buf), "%a %b %d %H:%M:%S %Y", tp);
773 
774  return buf;
775 }
776 
777 
789 const char *
791 {
792  const char *short_fn = filename;
793  const char *ss;
794 
795  while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)) && (ss[1] != '\0'))
796  short_fn = 1 + ss;
797  return short_fn;
798 }
799 
800 
808 static unsigned int
809 getValue__ (unsigned char a)
810 {
811  unsigned int dec;
812 
813  switch (a)
814  {
815  case 'O':
816  case 'o':
817  a = '0';
818  break;
819 
820  case 'i':
821  case 'I':
822  case 'l':
823  case 'L':
824  a = '1';
825  break;
826 
827  /* also consider U to be V */
828  case 'u':
829  case 'U':
830  a = 'V';
831  break;
832 
833  default:
834  break;
835  }
836  if ((a >= '0') && (a <= '9'))
837  return a - '0';
838  if ((a >= 'a') && (a <= 'z'))
839  a = toupper (a);
840  /* return (a - 'a' + 10); */
841  dec = 0;
842  if ((a >= 'A') && (a <= 'Z'))
843  {
844  if ('I' < a)
845  dec++;
846  if ('L' < a)
847  dec++;
848  if ('O' < a)
849  dec++;
850  if ('U' < a)
851  dec++;
852  return(a - 'A' + 10 - dec);
853  }
854  return -1;
855 }
856 
857 
870 char *
872  size_t size,
873  char *out,
874  size_t out_size)
875 {
879  static char *encTable__ = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
880  unsigned int wpos;
881  unsigned int rpos;
882  unsigned int bits;
883  unsigned int vbit;
884  const unsigned char *udata;
885 
886  GNUNET_assert (size < SIZE_MAX / 8 - 4);
887  udata = data;
888  if (out_size < (size * 8 + 4) / 5)
889  {
890  GNUNET_break (0);
891  return NULL;
892  }
893  vbit = 0;
894  wpos = 0;
895  rpos = 0;
896  bits = 0;
897  while ((rpos < size) || (vbit > 0))
898  {
899  if ((rpos < size) && (vbit < 5))
900  {
901  bits = (bits << 8) | udata[rpos++]; /* eat 8 more bits */
902  vbit += 8;
903  }
904  if (vbit < 5)
905  {
906  bits <<= (5 - vbit); /* zero-padding */
907  GNUNET_assert (vbit == ((size * 8) % 5));
908  vbit = 5;
909  }
910  if (wpos >= out_size)
911  {
912  GNUNET_break (0);
913  return NULL;
914  }
915  out[wpos++] = encTable__[(bits >> (vbit - 5)) & 31];
916  vbit -= 5;
917  }
918  GNUNET_assert (0 == vbit);
919  if (wpos < out_size)
920  out[wpos] = '\0';
921  return &out[wpos];
922 }
923 
924 
935 char *
937 {
938  char *str_buf;
939  size_t len = size * 8;
940  char *end;
941 
942  if (len % 5 > 0)
943  len += 5 - len % 5;
944  len /= 5;
945  str_buf = GNUNET_malloc (len + 1);
947  size,
948  str_buf,
949  len);
950  if (NULL == end)
951  {
952  GNUNET_free (str_buf);
953  return NULL;
954  }
955  *end = '\0';
956  return str_buf;
957 }
958 
959 
970 int
972  size_t enclen,
973  void *out,
974  size_t out_size)
975 {
976  size_t rpos;
977  size_t wpos;
978  unsigned int bits;
979  unsigned int vbit;
980  int ret;
981  int shift;
982  unsigned char *uout;
983  size_t encoded_len;
984 
985  if (0 == enclen)
986  {
987  if (0 == out_size)
988  return GNUNET_OK;
989  return GNUNET_SYSERR;
990  }
991  GNUNET_assert (out_size < SIZE_MAX / 8);
992  encoded_len = out_size * 8;
993  uout = out;
994  wpos = out_size;
995  rpos = enclen;
996  if ((encoded_len % 5) > 0)
997  {
998  vbit = encoded_len % 5; /* padding! */
999  shift = 5 - vbit;
1000  bits = (ret = getValue__ (enc[--rpos])) >> shift;
1001  }
1002  else
1003  {
1004  vbit = 5;
1005  shift = 0;
1006  bits = (ret = getValue__ (enc[--rpos]));
1007  }
1008  if ((encoded_len + shift) / 5 != enclen)
1009  return GNUNET_SYSERR;
1010  if (-1 == ret)
1011  return GNUNET_SYSERR;
1012  while (wpos > 0)
1013  {
1014  if (0 == rpos)
1015  {
1016  GNUNET_break (0);
1017  return GNUNET_SYSERR;
1018  }
1019  bits = ((ret = getValue__ (enc[--rpos])) << vbit) | bits;
1020  if (-1 == ret)
1021  return GNUNET_SYSERR;
1022  vbit += 5;
1023  if (vbit >= 8)
1024  {
1025  uout[--wpos] = (unsigned char) bits;
1026  bits >>= 8;
1027  vbit -= 8;
1028  }
1029  }
1030  if ((0 != rpos) || (0 != vbit))
1031  return GNUNET_SYSERR;
1032  return GNUNET_OK;
1033 }
1034 
1035 
1052 int
1053 GNUNET_STRINGS_parse_uri (const char *path,
1054  char **scheme_part,
1055  const char **path_part)
1056 {
1057  size_t len;
1058  size_t i;
1059  int end;
1060  int pp_state = 0;
1061  const char *post_scheme_part = NULL;
1062 
1063  len = strlen (path);
1064  for (end = 0, i = 0; ! end && i < len; i++)
1065  {
1066  switch (pp_state)
1067  {
1068  case 0:
1069  if ((path[i] == ':') && (i > 0))
1070  {
1071  pp_state += 1;
1072  continue;
1073  }
1074  if (! (((path[i] >= 'A') && (path[i] <= 'Z') ) ||
1075  ((path[i] >= 'a') && (path[i] <= 'z') ) ||
1076  ((path[i] >= '0') && (path[i] <= '9') ) || (path[i] == '+') ||
1077  (path[i] == '-') || (path[i] == '.')))
1078  end = 1;
1079  break;
1080 
1081  case 1:
1082  case 2:
1083  if (path[i] == '/')
1084  {
1085  pp_state += 1;
1086  continue;
1087  }
1088  end = 1;
1089  break;
1090 
1091  case 3:
1092  post_scheme_part = &path[i];
1093  end = 1;
1094  break;
1095 
1096  default:
1097  end = 1;
1098  }
1099  }
1100  if (post_scheme_part == NULL)
1101  return GNUNET_NO;
1102  if (scheme_part)
1103  {
1104  *scheme_part = GNUNET_malloc (post_scheme_part - path + 1);
1105  GNUNET_memcpy (*scheme_part, path, post_scheme_part - path);
1106  (*scheme_part)[post_scheme_part - path] = '\0';
1107  }
1108  if (path_part)
1109  *path_part = post_scheme_part;
1110  return GNUNET_YES;
1111 }
1112 
1113 
1128 int
1130  int can_be_uri,
1131  int *r_is_uri,
1132  char **r_uri_scheme)
1133 {
1134  const char *post_scheme_path;
1135  int is_uri;
1136  char *uri;
1137  /* consider POSIX paths to be absolute too, even on W32,
1138  * as plibc expansion will fix them for us.
1139  */
1140  if (filename[0] == '/')
1141  return GNUNET_YES;
1142  if (can_be_uri)
1143  {
1144  is_uri = GNUNET_STRINGS_parse_uri (filename, &uri, &post_scheme_path);
1145  if (r_is_uri)
1146  *r_is_uri = is_uri;
1147  if (is_uri)
1148  {
1149  if (r_uri_scheme)
1150  *r_uri_scheme = uri;
1151  else
1152  GNUNET_free (uri);
1153 
1154  return GNUNET_STRINGS_path_is_absolute (post_scheme_path,
1155  GNUNET_NO,
1156  NULL,
1157  NULL);
1158  }
1159  }
1160  else
1161  {
1162  if (r_is_uri)
1163  *r_is_uri = GNUNET_NO;
1164  }
1165 
1166  return GNUNET_NO;
1167 }
1168 
1169 
1178 int
1180  enum GNUNET_STRINGS_FilenameCheck checks)
1181 {
1182  struct stat st;
1183 
1184  if ((NULL == filename) || (filename[0] == '\0'))
1185  return GNUNET_SYSERR;
1186  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_ABSOLUTE))
1187  if (! GNUNET_STRINGS_path_is_absolute (filename, GNUNET_NO, NULL, NULL))
1188  return GNUNET_NO;
1189  if (0 != (checks
1192  {
1193  if (0 != lstat (filename, &st))
1194  {
1195  if (0 != (checks & GNUNET_STRINGS_CHECK_EXISTS))
1196  return GNUNET_NO;
1197  else
1198  return GNUNET_SYSERR;
1199  }
1200  }
1201  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_DIRECTORY))
1202  if (! S_ISDIR (st.st_mode))
1203  return GNUNET_NO;
1204  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_LINK))
1205  if (! S_ISLNK (st.st_mode))
1206  return GNUNET_NO;
1207  return GNUNET_YES;
1208 }
1209 
1210 
1223 int
1224 GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
1225  uint16_t addrlen,
1226  struct sockaddr_in6 *r_buf)
1227 {
1228  char zbuf[addrlen + 1];
1229  int ret;
1230  char *port_colon;
1231  unsigned int port;
1232  char dummy[2];
1233 
1234  if (addrlen < 6)
1235  return GNUNET_SYSERR;
1236  GNUNET_memcpy (zbuf, zt_addr, addrlen);
1237  if ('[' != zbuf[0])
1238  {
1240  _ ("IPv6 address did not start with `['\n"));
1241  return GNUNET_SYSERR;
1242  }
1243  zbuf[addrlen] = '\0';
1244  port_colon = strrchr (zbuf, ':');
1245  if (NULL == port_colon)
1246  {
1248  _ ("IPv6 address did contain ':' to separate port number\n"));
1249  return GNUNET_SYSERR;
1250  }
1251  if (']' != *(port_colon - 1))
1252  {
1253  GNUNET_log (
1255  _ ("IPv6 address did contain ']' before ':' to separate port number\n"));
1256  return GNUNET_SYSERR;
1257  }
1258  ret = sscanf (port_colon, ":%u%1s", &port, dummy);
1259  if ((1 != ret) || (port > 65535))
1260  {
1261  GNUNET_log (
1263  _ ("IPv6 address did contain a valid port number after the last ':'\n"));
1264  return GNUNET_SYSERR;
1265  }
1266  *(port_colon - 1) = '\0';
1267  memset (r_buf, 0, sizeof(struct sockaddr_in6));
1268  ret = inet_pton (AF_INET6, &zbuf[1], &r_buf->sin6_addr);
1269  if (ret <= 0)
1270  {
1272  _ ("Invalid IPv6 address `%s': %s\n"),
1273  &zbuf[1],
1274  strerror (errno));
1275  return GNUNET_SYSERR;
1276  }
1277  r_buf->sin6_port = htons (port);
1278  r_buf->sin6_family = AF_INET6;
1279 #if HAVE_SOCKADDR_IN_SIN_LEN
1280  r_buf->sin6_len = (u_char) sizeof(struct sockaddr_in6);
1281 #endif
1282  return GNUNET_OK;
1283 }
1284 
1285 
1297 int
1298 GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr,
1299  uint16_t addrlen,
1300  struct sockaddr_in *r_buf)
1301 {
1302  unsigned int temps[4];
1303  unsigned int port;
1304  unsigned int cnt;
1305  char dummy[2];
1306 
1307  if (addrlen < 9)
1308  return GNUNET_SYSERR;
1309  cnt = sscanf (zt_addr,
1310  "%u.%u.%u.%u:%u%1s",
1311  &temps[0],
1312  &temps[1],
1313  &temps[2],
1314  &temps[3],
1315  &port,
1316  dummy);
1317  if (5 != cnt)
1318  return GNUNET_SYSERR;
1319  for (cnt = 0; cnt < 4; cnt++)
1320  if (temps[cnt] > 0xFF)
1321  return GNUNET_SYSERR;
1322  if (port > 65535)
1323  return GNUNET_SYSERR;
1324  r_buf->sin_family = AF_INET;
1325  r_buf->sin_port = htons (port);
1326  r_buf->sin_addr.s_addr =
1327  htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + temps[3]);
1328 #if HAVE_SOCKADDR_IN_SIN_LEN
1329  r_buf->sin_len = (u_char) sizeof(struct sockaddr_in);
1330 #endif
1331  return GNUNET_OK;
1332 }
1333 
1334 
1346 int
1348  uint16_t addrlen,
1349  struct sockaddr_storage *r_buf)
1350 {
1351  if (addr[0] == '[')
1352  return GNUNET_STRINGS_to_address_ipv6 (addr,
1353  addrlen,
1354  (struct sockaddr_in6 *) r_buf);
1355  return GNUNET_STRINGS_to_address_ipv4 (addr,
1356  addrlen,
1357  (struct sockaddr_in *) r_buf);
1358 }
1359 
1360 
1370 size_t
1372  uint8_t *af,
1373  struct sockaddr **sa)
1374 {
1375  char *cp = GNUNET_strdup (addr);
1376 
1377  *af = AF_UNSPEC;
1378  if ('[' == *addr)
1379  {
1380  /* IPv6 */
1381  *sa = GNUNET_malloc (sizeof(struct sockaddr_in6));
1382  if (GNUNET_OK !=
1384  strlen (cp),
1385  (struct sockaddr_in6 *) *sa))
1386  {
1387  GNUNET_free (*sa);
1388  *sa = NULL;
1389  GNUNET_free (cp);
1390  return 0;
1391  }
1392  *af = AF_INET6;
1393  GNUNET_free (cp);
1394  return sizeof(struct sockaddr_in6);
1395  }
1396  else
1397  {
1398  /* IPv4 */
1399  *sa = GNUNET_malloc (sizeof(struct sockaddr_in));
1400  if (GNUNET_OK !=
1402  strlen (cp),
1403  (struct sockaddr_in *) *sa))
1404  {
1405  GNUNET_free (*sa);
1406  *sa = NULL;
1407  GNUNET_free (cp);
1408  return 0;
1409  }
1410  *af = AF_INET;
1411  GNUNET_free (cp);
1412  return sizeof(struct sockaddr_in);
1413  }
1414 }
1415 
1416 
1421 static char *const *
1422 _make_continuous_arg_copy (int argc, char *const *argv)
1423 {
1424  size_t argvsize = 0;
1425  char **new_argv;
1426  char *p;
1427 
1428  for (int i = 0; i < argc; i++)
1429  argvsize += strlen (argv[i]) + 1 + sizeof(char *);
1430  new_argv = GNUNET_malloc (argvsize + sizeof(char *));
1431  p = (char *) &new_argv[argc + 1];
1432  for (int i = 0; i < argc; i++)
1433  {
1434  new_argv[i] = p;
1435  strcpy (p, argv[i]);
1436  p += strlen (argv[i]) + 1;
1437  }
1438  new_argv[argc] = NULL;
1439  return (char *const *) new_argv;
1440 }
1441 
1442 
1457 int
1459  char *const *argv,
1460  int *u8argc,
1461  char *const **u8argv)
1462 {
1463  char *const *new_argv =
1464  (char *const *) _make_continuous_arg_copy (argc, argv);
1465  *u8argv = new_argv;
1466  *u8argc = argc;
1467  return GNUNET_OK;
1468 }
1469 
1470 
1480 static int
1481 parse_port_policy (const char *port_policy,
1482  struct GNUNET_STRINGS_PortPolicy *pp)
1483 {
1484  const char *pos;
1485  int s;
1486  int e;
1487  char eol[2];
1488 
1489  pos = port_policy;
1490  if ('!' == *pos)
1491  {
1493  pos++;
1494  }
1495  if (2 == sscanf (pos, "%u-%u%1s", &s, &e, eol))
1496  {
1497  if ((0 == s) || (s > 0xFFFF) || (e < s) || (e > 0xFFFF))
1498  {
1499  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Port not in range\n"));
1500  return GNUNET_SYSERR;
1501  }
1502  pp->start_port = (uint16_t) s;
1503  pp->end_port = (uint16_t) e;
1504  return GNUNET_OK;
1505  }
1506  if (1 == sscanf (pos, "%u%1s", &s, eol))
1507  {
1508  if ((0 == s) || (s > 0xFFFF))
1509  {
1510  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Port not in range\n"));
1511  return GNUNET_SYSERR;
1512  }
1513 
1514  pp->start_port = (uint16_t) s;
1515  pp->end_port = (uint16_t) s;
1516  return GNUNET_OK;
1517  }
1519  _ ("Malformed port policy `%s'\n"),
1520  port_policy);
1521  return GNUNET_SYSERR;
1522 }
1523 
1524 
1538 GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1539 {
1540  unsigned int count;
1541  unsigned int i;
1542  unsigned int j;
1543  unsigned int len;
1544  int cnt;
1545  unsigned int pos;
1546  unsigned int temps[8];
1547  int slash;
1549  int colon;
1550  int end;
1551  char *routeList;
1552  char dummy[2];
1553 
1554  if (NULL == routeListX)
1555  return NULL;
1556  len = strlen (routeListX);
1557  if (0 == len)
1558  return NULL;
1559  routeList = GNUNET_strdup (routeListX);
1560  count = 0;
1561  for (i = 0; i < len; i++)
1562  if (routeList[i] == ';')
1563  count++;
1564  result = GNUNET_malloc (sizeof(struct GNUNET_STRINGS_IPv4NetworkPolicy)
1565  * (count + 1));
1566  i = 0;
1567  pos = 0;
1568  while (i < count)
1569  {
1570  for (colon = pos; ':' != routeList[colon]; colon++)
1571  if ((';' == routeList[colon]) || ('\0' == routeList[colon]))
1572  break;
1573  for (end = colon; ';' != routeList[end]; end++)
1574  if ('\0' == routeList[end])
1575  break;
1576  if ('\0' == routeList[end])
1577  break;
1578  routeList[end] = '\0';
1579  if (':' == routeList[colon])
1580  {
1581  routeList[colon] = '\0';
1582  if (GNUNET_OK != parse_port_policy (&routeList[colon + 1], &result[i].pp))
1583  break;
1584  }
1585  cnt = sscanf (&routeList[pos],
1586  "%u.%u.%u.%u/%u.%u.%u.%u%1s",
1587  &temps[0],
1588  &temps[1],
1589  &temps[2],
1590  &temps[3],
1591  &temps[4],
1592  &temps[5],
1593  &temps[6],
1594  &temps[7],
1595  dummy);
1596  if (8 == cnt)
1597  {
1598  for (j = 0; j < 8; j++)
1599  if (temps[j] > 0xFF)
1600  {
1602  _ ("Invalid format for IP: `%s'\n"),
1603  &routeList[pos]);
1604  GNUNET_free (result);
1605  GNUNET_free (routeList);
1606  return NULL;
1607  }
1608  result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16)
1609  + (temps[2] << 8) + temps[3]);
1610  result[i].netmask.s_addr = htonl ((temps[4] << 24) + (temps[5] << 16)
1611  + (temps[6] << 8) + temps[7]);
1612  pos = end + 1;
1613  i++;
1614  continue;
1615  }
1616  /* try second notation */
1617  cnt = sscanf (&routeList[pos],
1618  "%u.%u.%u.%u/%u%1s",
1619  &temps[0],
1620  &temps[1],
1621  &temps[2],
1622  &temps[3],
1623  &slash,
1624  dummy);
1625  if (5 == cnt)
1626  {
1627  for (j = 0; j < 4; j++)
1628  if (temps[j] > 0xFF)
1629  {
1631  _ ("Invalid format for IP: `%s'\n"),
1632  &routeList[pos]);
1633  GNUNET_free (result);
1634  GNUNET_free (routeList);
1635  return NULL;
1636  }
1637  result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16)
1638  + (temps[2] << 8) + temps[3]);
1639  if ((slash <= 32) && (slash >= 0))
1640  {
1641  result[i].netmask.s_addr = 0;
1642  while (slash > 0)
1643  {
1644  result[i].netmask.s_addr =
1645  (result[i].netmask.s_addr >> 1) + 0x80000000;
1646  slash--;
1647  }
1648  result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1649  pos = end + 1;
1650  i++;
1651  continue;
1652  }
1653  else
1654  {
1656  _ ("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
1657  slash);
1658  GNUNET_free (result);
1659  GNUNET_free (routeList);
1660  return NULL; /* error */
1661  }
1662  }
1663  /* try third notation */
1664  slash = 32;
1665  cnt = sscanf (&routeList[pos],
1666  "%u.%u.%u.%u%1s",
1667  &temps[0],
1668  &temps[1],
1669  &temps[2],
1670  &temps[3],
1671  dummy);
1672  if (4 == cnt)
1673  {
1674  for (j = 0; j < 4; j++)
1675  if (temps[j] > 0xFF)
1676  {
1678  _ ("Invalid format for IP: `%s'\n"),
1679  &routeList[pos]);
1680  GNUNET_free (result);
1681  GNUNET_free (routeList);
1682  return NULL;
1683  }
1684  result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16)
1685  + (temps[2] << 8) + temps[3]);
1686  result[i].netmask.s_addr = 0;
1687  while (slash > 0)
1688  {
1689  result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
1690  slash--;
1691  }
1692  result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1693  pos = end + 1;
1694  i++;
1695  continue;
1696  }
1698  _ ("Invalid format for IP: `%s'\n"),
1699  &routeList[pos]);
1700  GNUNET_free (result);
1701  GNUNET_free (routeList);
1702  return NULL; /* error */
1703  }
1704  if (pos < strlen (routeList))
1705  {
1707  _ ("Invalid format: `%s'\n"),
1708  &routeListX[pos]);
1709  GNUNET_free (result);
1710  GNUNET_free (routeList);
1711  return NULL; /* oops */
1712  }
1713  GNUNET_free (routeList);
1714  return result; /* ok */
1715 }
1716 
1717 
1730 GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX)
1731 {
1732  unsigned int count;
1733  unsigned int i;
1734  unsigned int len;
1735  unsigned int pos;
1736  int start;
1737  int slash;
1738  int ret;
1739  char *routeList;
1741  unsigned int bits;
1742  unsigned int off;
1743  int save;
1744  int colon;
1745  char dummy[2];
1746 
1747  if (NULL == routeListX)
1748  return NULL;
1749  len = strlen (routeListX);
1750  if (0 == len)
1751  return NULL;
1752  routeList = GNUNET_strdup (routeListX);
1753  count = 0;
1754  for (i = 0; i < len; i++)
1755  if (';' == routeList[i])
1756  count++;
1757  if (';' != routeList[len - 1])
1758  {
1760  _ ("Invalid network notation (does not end with ';': `%s')\n"),
1761  routeList);
1762  GNUNET_free (routeList);
1763  return NULL;
1764  }
1765 
1766  result = GNUNET_malloc (sizeof(struct GNUNET_STRINGS_IPv6NetworkPolicy)
1767  * (count + 1));
1768  i = 0;
1769  pos = 0;
1770  while (i < count)
1771  {
1772  start = pos;
1773  while (';' != routeList[pos])
1774  pos++;
1775  slash = pos;
1776  while ((slash >= start) && (routeList[slash] != '/'))
1777  slash--;
1778 
1779  if (slash < start)
1780  {
1781  memset (&result[i].netmask, 0xFF, sizeof(struct in6_addr));
1782  slash = pos;
1783  }
1784  else
1785  {
1786  routeList[pos] = '\0';
1787  for (colon = pos; ':' != routeList[colon]; colon--)
1788  if ('/' == routeList[colon])
1789  break;
1790  if (':' == routeList[colon])
1791  {
1792  routeList[colon] = '\0';
1793  if (GNUNET_OK !=
1794  parse_port_policy (&routeList[colon + 1], &result[i].pp))
1795  {
1796  GNUNET_free (result);
1797  GNUNET_free (routeList);
1798  return NULL;
1799  }
1800  }
1801  ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
1802  if (ret <= 0)
1803  {
1804  save = errno;
1805  if ((1 != sscanf (&routeList[slash + 1], "%u%1s", &bits, dummy)) ||
1806  (bits > 128))
1807  {
1808  if (0 == ret)
1810  _ ("Wrong format `%s' for netmask\n"),
1811  &routeList[slash + 1]);
1812  else
1813  {
1814  errno = save;
1815  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "inet_pton");
1816  }
1817  GNUNET_free (result);
1818  GNUNET_free (routeList);
1819  return NULL;
1820  }
1821  off = 0;
1822  while (bits > 8)
1823  {
1824  result[i].netmask.s6_addr[off++] = 0xFF;
1825  bits -= 8;
1826  }
1827  while (bits > 0)
1828  {
1829  result[i].netmask.s6_addr[off] =
1830  (result[i].netmask.s6_addr[off] >> 1) + 0x80;
1831  bits--;
1832  }
1833  }
1834  }
1835  routeList[slash] = '\0';
1836  ret = inet_pton (AF_INET6, &routeList[start], &result[i].network);
1837  if (ret <= 0)
1838  {
1839  if (0 == ret)
1841  _ ("Wrong format `%s' for network\n"),
1842  &routeList[slash + 1]);
1843  else
1844  LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
1845  GNUNET_free (result);
1846  GNUNET_free (routeList);
1847  return NULL;
1848  }
1849  pos++;
1850  i++;
1851  }
1852  GNUNET_free (routeList);
1853  return result;
1854 }
1855 
1856 
1859 #define FILLCHAR '='
1860 static char *cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1861  "abcdefghijklmnopqrstuvwxyz"
1862  "0123456789+/";
1863 
1864 
1874 size_t
1875 GNUNET_STRINGS_base64_encode (const void *in, size_t len, char **output)
1876 {
1877  const char *data = in;
1878  size_t ret;
1879  char *opt;
1880 
1881  ret = 0;
1882  GNUNET_assert (len / 4 < SIZE_MAX);
1883  opt = GNUNET_malloc (2 + (len * 4 / 3) + 8);
1884  for (size_t i = 0; i < len; ++i)
1885  {
1886  char c;
1887 
1888  c = (data[i] >> 2) & 0x3f;
1889  opt[ret++] = cvt[(int) c];
1890  c = (data[i] << 4) & 0x3f;
1891  if (++i < len)
1892  c |= (data[i] >> 4) & 0x0f;
1893  opt[ret++] = cvt[(int) c];
1894  if (i < len)
1895  {
1896  c = (data[i] << 2) & 0x3f;
1897  if (++i < len)
1898  c |= (data[i] >> 6) & 0x03;
1899  opt[ret++] = cvt[(int) c];
1900  }
1901  else
1902  {
1903  ++i;
1904  opt[ret++] = FILLCHAR;
1905  }
1906  if (i < len)
1907  {
1908  c = data[i] & 0x3f;
1909  opt[ret++] = cvt[(int) c];
1910  }
1911  else
1912  {
1913  opt[ret++] = FILLCHAR;
1914  }
1915  }
1916  *output = opt;
1917  return ret;
1918 }
1919 
1920 
1930 size_t
1931 GNUNET_STRINGS_base64url_encode (const void *in, size_t len, char **output)
1932 {
1933  char *enc;
1934  size_t pos;
1935 
1936  GNUNET_STRINGS_base64_encode (in, len, output);
1937  enc = *output;
1938  /* Replace with correct characters for base64url */
1939  pos = 0;
1940  while ('\0' != enc[pos])
1941  {
1942  if ('+' == enc[pos])
1943  enc[pos] = '-';
1944  if ('/' == enc[pos])
1945  enc[pos] = '_';
1946  if ('=' == enc[pos])
1947  {
1948  enc[pos] = '\0';
1949  break;
1950  }
1951  pos++;
1952  }
1953  return strlen (enc);
1954 }
1955 
1956 
1957 #define cvtfind(a) \
1958  ((((a) >= 'A') && ((a) <= 'Z')) \
1959  ? (a) - 'A' \
1960  : (((a) >= 'a') && ((a) <= 'z')) \
1961  ? (a) - 'a' + 26 \
1962  : (((a) >= '0') && ((a) <= '9')) \
1963  ? (a) - '0' + 52 \
1964  : ((a) == '+') ? 62 : ((a) == '/') ? 63 : -1)
1965 
1966 
1976 size_t
1977 GNUNET_STRINGS_base64_decode (const char *data, size_t len, void **out)
1978 {
1979  char *output;
1980  size_t ret = 0;
1981 
1982 #define CHECK_CRLF \
1983  while (data[i] == '\r' || data[i] == '\n') \
1984  { \
1985  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, \
1986  "ignoring CR/LF\n"); \
1987  i++; \
1988  if (i >= len) \
1989  goto END; \
1990  }
1991 
1992  GNUNET_assert (len / 3 < SIZE_MAX);
1993  output = GNUNET_malloc ((len * 3 / 4) + 8);
1995  "base64_decode decoding len=%d\n",
1996  (int) len);
1997  for (size_t i = 0; i < len; ++i)
1998  {
1999  char c;
2000  char c1;
2001 
2002  CHECK_CRLF;
2003  if (FILLCHAR == data[i])
2004  break;
2005  c = (char) cvtfind (data[i]);
2006  ++i;
2007  CHECK_CRLF;
2008  c1 = (char) cvtfind (data[i]);
2009  c = (c << 2) | ((c1 >> 4) & 0x3);
2010  output[ret++] = c;
2011  if (++i < len)
2012  {
2013  CHECK_CRLF;
2014  c = data[i];
2015  if (FILLCHAR == c)
2016  break;
2017  c = (char) cvtfind (c);
2018  c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
2019  output[ret++] = c1;
2020  }
2021  if (++i < len)
2022  {
2023  CHECK_CRLF;
2024  c1 = data[i];
2025  if (FILLCHAR == c1)
2026  break;
2027 
2028  c1 = (char) cvtfind (c1);
2029  c = ((c << 6) & 0xc0) | c1;
2030  output[ret++] = c;
2031  }
2032  }
2033 END:
2034  *out = output;
2035  return ret;
2036 }
2037 
2038 
2048 size_t
2049 GNUNET_STRINGS_base64url_decode (const char *data, size_t len, void **out)
2050 {
2051  char *s;
2052  int padding;
2053  size_t ret;
2054 
2055  /* make enough space for padding */
2056  GNUNET_assert (len < SIZE_MAX - 3);
2057  s = GNUNET_malloc (len + 3);
2058  memcpy (s, data, len);
2059 
2060  for (int i = 0; i < strlen (s); i++)
2061  {
2062  if (s[i] == '-')
2063  s[i] = '+';
2064  if (s[i] == '_')
2065  s[i] = '/';
2066  }
2067  padding = len % 4;
2068  switch (padding) // Pad with trailing '='s
2069  {
2070  case 0:
2071  break; // No pad chars in this case
2072  case 2:
2073  memcpy (&s[len],
2074  "==",
2075  2);
2076  len += 2;
2077  break; // Two pad chars
2078  case 3:
2079  s[len] = '=';
2080  len++;
2081  break; // One pad char
2082  default:
2083  GNUNET_assert (0);
2084  break;
2085  }
2086  ret = GNUNET_STRINGS_base64_decode (s, len, out);
2087  GNUNET_free (s);
2088  return ret;
2089 }
2090 
2091 
2101 size_t
2102 GNUNET_STRINGS_urldecode (const char *data, size_t len, char **out)
2103 {
2104  const char *rpos = data;
2105  *out = GNUNET_malloc (len + 1); /* output should always fit into input */
2106  char *wpos = *out;
2107  size_t resl = 0;
2108 
2109  while ('\0' != *rpos)
2110  {
2111  unsigned int num;
2112  switch (*rpos)
2113  {
2114  case '%':
2115  if (1 != sscanf (rpos + 1, "%2x", &num))
2116  break;
2117  *wpos = (char) ((unsigned char) num);
2118  wpos++;
2119  resl++;
2120  rpos += 3;
2121  break;
2122  /* TODO: add bad sequence handling */
2123  /* intentional fall through! */
2124  default:
2125  *wpos = *rpos;
2126  wpos++;
2127  resl++;
2128  rpos++;
2129  }
2130  }
2131  *wpos = '\0'; /* add 0-terminator */
2132  return resl;
2133 }
2134 
2135 
2145 size_t
2146 GNUNET_STRINGS_urlencode (const char *data, size_t len, char **out)
2147 {
2148  struct GNUNET_Buffer buf = { 0 };
2149  const uint8_t *i8 = (uint8_t *) data;
2150 
2151  while (0 != *i8)
2152  {
2153  if (0 == (0x80 & *i8))
2154  {
2155  /* traditional ASCII */
2156  if (isalnum (*i8) || (*i8 == '-') || (*i8 == '_') || (*i8 == '.') ||
2157  (*i8 == '~') )
2158  GNUNET_buffer_write (&buf, (const char*) i8, 1);
2159  else if (*i8 == ' ')
2160  GNUNET_buffer_write (&buf, "+", 1);
2161  else
2163  "%%%X%X",
2164  *i8 >> 4,
2165  *i8 & 15);
2166  i8++;
2167  continue;
2168  }
2169  if (0x80 + 0x40 == ((0x80 + 0x40 + 0x20) & *i8))
2170  {
2171  /* 2-byte value, percent-encode */
2173  "%%%X%X",
2174  *i8 >> 4,
2175  *i8 & 15);
2176  i8++;
2178  "%%%X%X",
2179  *i8 >> 4,
2180  *i8 & 15);
2181  i8++;
2182  continue;
2183  }
2184  if (0x80 + 0x40 + 0x20 == ((0x80 + 0x40 + 0x20 + 0x10) & *i8))
2185  {
2186  /* 3-byte value, percent-encode */
2187  for (unsigned int i = 0; i<3; i++)
2188  {
2190  "%%%X%X",
2191  *i8 >> 4,
2192  *i8 & 15);
2193  i8++;
2194  }
2195  continue;
2196  }
2197  if (0x80 + 0x40 + 0x20 + 0x10 == ((0x80 + 0x40 + 0x20 + 0x10 + 0x08) & *i8))
2198  {
2199  /* 4-byte value, percent-encode */
2200  for (unsigned int i = 0; i<4; i++)
2201  {
2203  "%%%X%X",
2204  *i8 >> 4,
2205  *i8 & 15);
2206  i8++;
2207  }
2208  continue;
2209  }
2210  if (0x80 + 0x40 + 0x20 + 0x10 + 0x08 == ((0x80 + 0x40 + 0x20 + 0x10 + 0x08
2211  + 0x04) & *i8))
2212  {
2213  /* 5-byte value, percent-encode (outside of UTF-8 modern standard, but so what) */
2214  for (unsigned int i = 0; i<5; i++)
2215  {
2217  "%%%X%X",
2218  *i8 >> 4,
2219  *i8 & 15);
2220  i8++;
2221  }
2222  continue;
2223  }
2224  if (0x80 + 0x40 + 0x20 + 0x10 + 0x08 + 0x04 == ((0x80 + 0x40 + 0x20 + 0x10
2225  + 0x08 + 0x04 + 0x02)
2226  & *i8))
2227  {
2228  /* 6-byte value, percent-encode (outside of UTF-8 modern standard, but so what) */
2229  for (unsigned int i = 0; i<6; i++)
2230  {
2232  "%%%X%X",
2233  *i8 >> 4,
2234  *i8 & 15);
2235  i8++;
2236  }
2237  continue;
2238  }
2239  /* really, really invalid UTF-8: fail */
2240  GNUNET_break (0);
2241  GNUNET_buffer_clear (&buf);
2242  return 0;
2243  }
2244  *out = GNUNET_buffer_reap_str (&buf);
2245  return strlen (*out);
2246 }
2247 
2248 
2249 /* 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:246
struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
Parse an IPv4 network policy.
Definition: strings.c:1538
#define CHECK_CRLF
size_t GNUNET_STRINGS_urldecode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:2102
#define FILLCHAR
******************** Base64 encoding
Definition: strings.c:1859
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:1481
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:452
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:1053
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:177
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:262
struct GNUNET_STRINGS_IPv6NetworkPolicy * GNUNET_STRINGS_parse_ipv6_policy(const char *routeListX)
Parse an IPv6 network policy.
Definition: strings.c:1730
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:1458
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:1129
#define cvtfind(a)
Definition: strings.c:1957
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition: buffer.c:123
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:356
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.
void GNUNET_buffer_write(struct GNUNET_Buffer *buf, const char *data, size_t len)
Write bytes to the buffer.
Definition: buffer.c:86
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:407
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:324
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:1422
static struct GNUNET_SCHEDULER_Task * t
Main task.
Check that it exists.
void GNUNET_buffer_write_fstr(struct GNUNET_Buffer *buf, const char *fmt,...)
Write a 0-terminated formatted string to a buffer, excluding the 0-terminator.
Definition: buffer.c:209
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:1860
#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:1931
#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:1298
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:137
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:593
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:101
#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:702
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:549
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:66
Unit conversion table entry for &#39;convert_with_table&#39;.
Definition: strings.c:236
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:1371
static OpusDecoder * dec
OPUS decoder.
#define LOG(kind,...)
Definition: strings.c:38
static unsigned int getValue__(unsigned char a)
Get the decoded value corresponding to a character according to Crockford Base32 encoding.
Definition: strings.c:809
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **out)
Decode from Base64.
Definition: strings.c:1977
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1875
#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:790
static unsigned int size
Size of the "table".
Definition: peer.c:67
size_t GNUNET_STRINGS_urlencode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:2146
int GNUNET_STRINGS_check_filename(const char *filename, enum GNUNET_STRINGS_FilenameCheck checks)
Perform checks on filename.
Definition: strings.c:1179
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition: strings.c:618
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:40
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:1224
#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:526
void GNUNET_buffer_clear(struct GNUNET_Buffer *buf)
Free the backing memory of the given buffer.
Definition: buffer.c:164
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.
Common buffer management functions.
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:936
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
"asctime", except for GNUnet time.
Definition: strings.c:757
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:221
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:241
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:1347
size_t GNUNET_STRINGS_base64url_decode(const char *data, size_t len, void **out)
Decode from Base64url.
Definition: strings.c:2049
#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:971
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:871
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:568
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...