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 separator 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",
743  (unsigned long long) dval, unit);
744  return buf;
745 }
746 
747 
757 const char *
759 {
760  static GNUNET_THREAD_LOCAL char buf[255];
761  time_t tt;
762  struct tm *tp;
763 
764  if (t.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
765  return "end of time";
766  tt = t.abs_value_us / 1000LL / 1000LL;
767  tp = localtime (&tt);
768  /* This is hacky, but i don't know a way to detect libc character encoding.
769  * Just expect utf8 from glibc these days.
770  * As for msvcrt, use the wide variant, which always returns utf16
771  * (otherwise we'd have to detect current codepage or use W32API character
772  * set conversion routines to convert to UTF8).
773  */strftime (buf, sizeof(buf), "%a %b %d %H:%M:%S %Y", tp);
774 
775  return buf;
776 }
777 
778 
790 const char *
792 {
793  const char *short_fn = filename;
794  const char *ss;
795 
796  while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)) && (ss[1] != '\0'))
797  short_fn = 1 + ss;
798  return short_fn;
799 }
800 
801 
809 static unsigned int
810 getValue__ (unsigned char a)
811 {
812  unsigned int dec;
813 
814  switch (a)
815  {
816  case 'O':
817  case 'o':
818  a = '0';
819  break;
820 
821  case 'i':
822  case 'I':
823  case 'l':
824  case 'L':
825  a = '1';
826  break;
827 
828  /* also consider U to be V */
829  case 'u':
830  case 'U':
831  a = 'V';
832  break;
833 
834  default:
835  break;
836  }
837  if ((a >= '0') && (a <= '9'))
838  return a - '0';
839  if ((a >= 'a') && (a <= 'z'))
840  a = toupper (a);
841  /* return (a - 'a' + 10); */
842  dec = 0;
843  if ((a >= 'A') && (a <= 'Z'))
844  {
845  if ('I' < a)
846  dec++;
847  if ('L' < a)
848  dec++;
849  if ('O' < a)
850  dec++;
851  if ('U' < a)
852  dec++;
853  return(a - 'A' + 10 - dec);
854  }
855  return -1;
856 }
857 
858 
871 char *
873  size_t size,
874  char *out,
875  size_t out_size)
876 {
880  static char *encTable__ = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
881  unsigned int wpos;
882  unsigned int rpos;
883  unsigned int bits;
884  unsigned int vbit;
885  const unsigned char *udata;
886 
887  GNUNET_assert (size < SIZE_MAX / 8 - 4);
888  udata = data;
889  if (out_size < (size * 8 + 4) / 5)
890  {
891  GNUNET_break (0);
892  return NULL;
893  }
894  vbit = 0;
895  wpos = 0;
896  rpos = 0;
897  bits = 0;
898  while ((rpos < size) || (vbit > 0))
899  {
900  if ((rpos < size) && (vbit < 5))
901  {
902  bits = (bits << 8) | udata[rpos++]; /* eat 8 more bits */
903  vbit += 8;
904  }
905  if (vbit < 5)
906  {
907  bits <<= (5 - vbit); /* zero-padding */
908  GNUNET_assert (vbit == ((size * 8) % 5));
909  vbit = 5;
910  }
911  if (wpos >= out_size)
912  {
913  GNUNET_break (0);
914  return NULL;
915  }
916  out[wpos++] = encTable__[(bits >> (vbit - 5)) & 31];
917  vbit -= 5;
918  }
919  GNUNET_assert (0 == vbit);
920  if (wpos < out_size)
921  out[wpos] = '\0';
922  return &out[wpos];
923 }
924 
925 
936 char *
938 {
939  char *str_buf;
940  size_t len = size * 8;
941  char *end;
942 
943  if (len % 5 > 0)
944  len += 5 - len % 5;
945  len /= 5;
946  str_buf = GNUNET_malloc (len + 1);
948  size,
949  str_buf,
950  len);
951  if (NULL == end)
952  {
953  GNUNET_free (str_buf);
954  return NULL;
955  }
956  *end = '\0';
957  return str_buf;
958 }
959 
960 
971 int
973  size_t enclen,
974  void *out,
975  size_t out_size)
976 {
977  size_t rpos;
978  size_t wpos;
979  unsigned int bits;
980  unsigned int vbit;
981  int ret;
982  int shift;
983  unsigned char *uout;
984  size_t encoded_len;
985 
986  if (0 == enclen)
987  {
988  if (0 == out_size)
989  return GNUNET_OK;
990  return GNUNET_SYSERR;
991  }
992  GNUNET_assert (out_size < SIZE_MAX / 8);
993  encoded_len = out_size * 8;
994  uout = out;
995  wpos = out_size;
996  rpos = enclen;
997  if ((encoded_len % 5) > 0)
998  {
999  vbit = encoded_len % 5; /* padding! */
1000  shift = 5 - vbit;
1001  bits = (ret = getValue__ (enc[--rpos])) >> shift;
1002  }
1003  else
1004  {
1005  vbit = 5;
1006  shift = 0;
1007  bits = (ret = getValue__ (enc[--rpos]));
1008  }
1009  if ((encoded_len + shift) / 5 != enclen)
1010  return GNUNET_SYSERR;
1011  if (-1 == ret)
1012  return GNUNET_SYSERR;
1013  while (wpos > 0)
1014  {
1015  if (0 == rpos)
1016  {
1017  GNUNET_break (0);
1018  return GNUNET_SYSERR;
1019  }
1020  bits = ((ret = getValue__ (enc[--rpos])) << vbit) | bits;
1021  if (-1 == ret)
1022  return GNUNET_SYSERR;
1023  vbit += 5;
1024  if (vbit >= 8)
1025  {
1026  uout[--wpos] = (unsigned char) bits;
1027  bits >>= 8;
1028  vbit -= 8;
1029  }
1030  }
1031  if ((0 != rpos) || (0 != vbit))
1032  return GNUNET_SYSERR;
1033  return GNUNET_OK;
1034 }
1035 
1036 
1053 int
1054 GNUNET_STRINGS_parse_uri (const char *path,
1055  char **scheme_part,
1056  const char **path_part)
1057 {
1058  size_t len;
1059  size_t i;
1060  int end;
1061  int pp_state = 0;
1062  const char *post_scheme_part = NULL;
1063 
1064  len = strlen (path);
1065  for (end = 0, i = 0; ! end && i < len; i++)
1066  {
1067  switch (pp_state)
1068  {
1069  case 0:
1070  if ((path[i] == ':') && (i > 0))
1071  {
1072  pp_state += 1;
1073  continue;
1074  }
1075  if (! (((path[i] >= 'A') && (path[i] <= 'Z') ) ||
1076  ((path[i] >= 'a') && (path[i] <= 'z') ) ||
1077  ((path[i] >= '0') && (path[i] <= '9') ) || (path[i] == '+') ||
1078  (path[i] == '-') || (path[i] == '.')))
1079  end = 1;
1080  break;
1081 
1082  case 1:
1083  case 2:
1084  if (path[i] == '/')
1085  {
1086  pp_state += 1;
1087  continue;
1088  }
1089  end = 1;
1090  break;
1091 
1092  case 3:
1093  post_scheme_part = &path[i];
1094  end = 1;
1095  break;
1096 
1097  default:
1098  end = 1;
1099  }
1100  }
1101  if (post_scheme_part == NULL)
1102  return GNUNET_NO;
1103  if (scheme_part)
1104  {
1105  *scheme_part = GNUNET_malloc (post_scheme_part - path + 1);
1106  GNUNET_memcpy (*scheme_part, path, post_scheme_part - path);
1107  (*scheme_part)[post_scheme_part - path] = '\0';
1108  }
1109  if (path_part)
1110  *path_part = post_scheme_part;
1111  return GNUNET_YES;
1112 }
1113 
1114 
1129 int
1131  int can_be_uri,
1132  int *r_is_uri,
1133  char **r_uri_scheme)
1134 {
1135  const char *post_scheme_path;
1136  int is_uri;
1137  char *uri;
1138  /* consider POSIX paths to be absolute too, even on W32,
1139  * as plibc expansion will fix them for us.
1140  */
1141  if (filename[0] == '/')
1142  return GNUNET_YES;
1143  if (can_be_uri)
1144  {
1145  is_uri = GNUNET_STRINGS_parse_uri (filename, &uri, &post_scheme_path);
1146  if (r_is_uri)
1147  *r_is_uri = is_uri;
1148  if (is_uri)
1149  {
1150  if (r_uri_scheme)
1151  *r_uri_scheme = uri;
1152  else
1153  GNUNET_free (uri);
1154 
1155  return GNUNET_STRINGS_path_is_absolute (post_scheme_path,
1156  GNUNET_NO,
1157  NULL,
1158  NULL);
1159  }
1160  }
1161  else
1162  {
1163  if (r_is_uri)
1164  *r_is_uri = GNUNET_NO;
1165  }
1166 
1167  return GNUNET_NO;
1168 }
1169 
1170 
1179 int
1181  enum GNUNET_STRINGS_FilenameCheck checks)
1182 {
1183  struct stat st;
1184 
1185  if ((NULL == filename) || (filename[0] == '\0'))
1186  return GNUNET_SYSERR;
1187  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_ABSOLUTE))
1188  if (! GNUNET_STRINGS_path_is_absolute (filename, GNUNET_NO, NULL, NULL))
1189  return GNUNET_NO;
1190  if (0 != (checks
1193  {
1194  if (0 != lstat (filename, &st))
1195  {
1196  if (0 != (checks & GNUNET_STRINGS_CHECK_EXISTS))
1197  return GNUNET_NO;
1198  else
1199  return GNUNET_SYSERR;
1200  }
1201  }
1202  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_DIRECTORY))
1203  if (! S_ISDIR (st.st_mode))
1204  return GNUNET_NO;
1205  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_LINK))
1206  if (! S_ISLNK (st.st_mode))
1207  return GNUNET_NO;
1208  return GNUNET_YES;
1209 }
1210 
1211 
1224 int
1225 GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
1226  uint16_t addrlen,
1227  struct sockaddr_in6 *r_buf)
1228 {
1229  char zbuf[addrlen + 1];
1230  int ret;
1231  char *port_colon;
1232  unsigned int port;
1233  char dummy[2];
1234 
1235  if (addrlen < 6)
1236  return GNUNET_SYSERR;
1237  GNUNET_memcpy (zbuf, zt_addr, addrlen);
1238  if ('[' != zbuf[0])
1239  {
1241  _ ("IPv6 address did not start with `['\n"));
1242  return GNUNET_SYSERR;
1243  }
1244  zbuf[addrlen] = '\0';
1245  port_colon = strrchr (zbuf, ':');
1246  if (NULL == port_colon)
1247  {
1249  _ ("IPv6 address did contain ':' to separate port number\n"));
1250  return GNUNET_SYSERR;
1251  }
1252  if (']' != *(port_colon - 1))
1253  {
1254  GNUNET_log (
1256  _ ("IPv6 address did contain ']' before ':' to separate port number\n"));
1257  return GNUNET_SYSERR;
1258  }
1259  ret = sscanf (port_colon, ":%u%1s", &port, dummy);
1260  if ((1 != ret) || (port > 65535))
1261  {
1262  GNUNET_log (
1264  _ ("IPv6 address did contain a valid port number after the last ':'\n"));
1265  return GNUNET_SYSERR;
1266  }
1267  *(port_colon - 1) = '\0';
1268  memset (r_buf, 0, sizeof(struct sockaddr_in6));
1269  ret = inet_pton (AF_INET6, &zbuf[1], &r_buf->sin6_addr);
1270  if (ret <= 0)
1271  {
1273  _ ("Invalid IPv6 address `%s': %s\n"),
1274  &zbuf[1],
1275  strerror (errno));
1276  return GNUNET_SYSERR;
1277  }
1278  r_buf->sin6_port = htons (port);
1279  r_buf->sin6_family = AF_INET6;
1280 #if HAVE_SOCKADDR_IN_SIN_LEN
1281  r_buf->sin6_len = (u_char) sizeof(struct sockaddr_in6);
1282 #endif
1283  return GNUNET_OK;
1284 }
1285 
1286 
1298 int
1299 GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr,
1300  uint16_t addrlen,
1301  struct sockaddr_in *r_buf)
1302 {
1303  unsigned int temps[4];
1304  unsigned int port;
1305  unsigned int cnt;
1306  char dummy[2];
1307 
1308  if (addrlen < 9)
1309  return GNUNET_SYSERR;
1310  cnt = sscanf (zt_addr,
1311  "%u.%u.%u.%u:%u%1s",
1312  &temps[0],
1313  &temps[1],
1314  &temps[2],
1315  &temps[3],
1316  &port,
1317  dummy);
1318  if (5 != cnt)
1319  return GNUNET_SYSERR;
1320  for (cnt = 0; cnt < 4; cnt++)
1321  if (temps[cnt] > 0xFF)
1322  return GNUNET_SYSERR;
1323  if (port > 65535)
1324  return GNUNET_SYSERR;
1325  r_buf->sin_family = AF_INET;
1326  r_buf->sin_port = htons (port);
1327  r_buf->sin_addr.s_addr =
1328  htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + temps[3]);
1329 #if HAVE_SOCKADDR_IN_SIN_LEN
1330  r_buf->sin_len = (u_char) sizeof(struct sockaddr_in);
1331 #endif
1332  return GNUNET_OK;
1333 }
1334 
1335 
1347 int
1349  uint16_t addrlen,
1350  struct sockaddr_storage *r_buf)
1351 {
1352  if (addr[0] == '[')
1353  return GNUNET_STRINGS_to_address_ipv6 (addr,
1354  addrlen,
1355  (struct sockaddr_in6 *) r_buf);
1356  return GNUNET_STRINGS_to_address_ipv4 (addr,
1357  addrlen,
1358  (struct sockaddr_in *) r_buf);
1359 }
1360 
1361 
1371 size_t
1373  uint8_t *af,
1374  struct sockaddr **sa)
1375 {
1376  char *cp = GNUNET_strdup (addr);
1377 
1378  *af = AF_UNSPEC;
1379  if ('[' == *addr)
1380  {
1381  /* IPv6 */
1382  *sa = GNUNET_malloc (sizeof(struct sockaddr_in6));
1383  if (GNUNET_OK !=
1385  strlen (cp),
1386  (struct sockaddr_in6 *) *sa))
1387  {
1388  GNUNET_free (*sa);
1389  *sa = NULL;
1390  GNUNET_free (cp);
1391  return 0;
1392  }
1393  *af = AF_INET6;
1394  GNUNET_free (cp);
1395  return sizeof(struct sockaddr_in6);
1396  }
1397  else
1398  {
1399  /* IPv4 */
1400  *sa = GNUNET_malloc (sizeof(struct sockaddr_in));
1401  if (GNUNET_OK !=
1403  strlen (cp),
1404  (struct sockaddr_in *) *sa))
1405  {
1406  GNUNET_free (*sa);
1407  *sa = NULL;
1408  GNUNET_free (cp);
1409  return 0;
1410  }
1411  *af = AF_INET;
1412  GNUNET_free (cp);
1413  return sizeof(struct sockaddr_in);
1414  }
1415 }
1416 
1417 
1422 static char *const *
1423 _make_continuous_arg_copy (int argc, char *const *argv)
1424 {
1425  size_t argvsize = 0;
1426  char **new_argv;
1427  char *p;
1428 
1429  for (int i = 0; i < argc; i++)
1430  argvsize += strlen (argv[i]) + 1 + sizeof(char *);
1431  new_argv = GNUNET_malloc (argvsize + sizeof(char *));
1432  p = (char *) &new_argv[argc + 1];
1433  for (int i = 0; i < argc; i++)
1434  {
1435  new_argv[i] = p;
1436  strcpy (p, argv[i]);
1437  p += strlen (argv[i]) + 1;
1438  }
1439  new_argv[argc] = NULL;
1440  return (char *const *) new_argv;
1441 }
1442 
1443 
1458 int
1460  char *const *argv,
1461  int *u8argc,
1462  char *const **u8argv)
1463 {
1464  char *const *new_argv =
1465  (char *const *) _make_continuous_arg_copy (argc, argv);
1466  *u8argv = new_argv;
1467  *u8argc = argc;
1468  return GNUNET_OK;
1469 }
1470 
1471 
1481 static int
1482 parse_port_policy (const char *port_policy,
1483  struct GNUNET_STRINGS_PortPolicy *pp)
1484 {
1485  const char *pos;
1486  int s;
1487  int e;
1488  char eol[2];
1489 
1490  pos = port_policy;
1491  if ('!' == *pos)
1492  {
1494  pos++;
1495  }
1496  if (2 == sscanf (pos, "%u-%u%1s", &s, &e, eol))
1497  {
1498  if ((0 == s) || (s > 0xFFFF) || (e < s) || (e > 0xFFFF))
1499  {
1500  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Port not in range\n"));
1501  return GNUNET_SYSERR;
1502  }
1503  pp->start_port = (uint16_t) s;
1504  pp->end_port = (uint16_t) e;
1505  return GNUNET_OK;
1506  }
1507  if (1 == sscanf (pos, "%u%1s", &s, eol))
1508  {
1509  if ((0 == s) || (s > 0xFFFF))
1510  {
1511  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Port not in range\n"));
1512  return GNUNET_SYSERR;
1513  }
1514 
1515  pp->start_port = (uint16_t) s;
1516  pp->end_port = (uint16_t) s;
1517  return GNUNET_OK;
1518  }
1520  _ ("Malformed port policy `%s'\n"),
1521  port_policy);
1522  return GNUNET_SYSERR;
1523 }
1524 
1525 
1539 GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1540 {
1541  unsigned int count;
1542  unsigned int i;
1543  unsigned int j;
1544  unsigned int len;
1545  int cnt;
1546  unsigned int pos;
1547  unsigned int temps[8];
1548  int slash;
1550  int colon;
1551  int end;
1552  char *routeList;
1553  char dummy[2];
1554 
1555  if (NULL == routeListX)
1556  return NULL;
1557  len = strlen (routeListX);
1558  if (0 == len)
1559  return NULL;
1560  routeList = GNUNET_strdup (routeListX);
1561  count = 0;
1562  for (i = 0; i < len; i++)
1563  if (routeList[i] == ';')
1564  count++;
1565  result = GNUNET_malloc (sizeof(struct GNUNET_STRINGS_IPv4NetworkPolicy)
1566  * (count + 1));
1567  i = 0;
1568  pos = 0;
1569  while (i < count)
1570  {
1571  for (colon = pos; ':' != routeList[colon]; colon++)
1572  if ((';' == routeList[colon]) || ('\0' == routeList[colon]))
1573  break;
1574  for (end = colon; ';' != routeList[end]; end++)
1575  if ('\0' == routeList[end])
1576  break;
1577  if ('\0' == routeList[end])
1578  break;
1579  routeList[end] = '\0';
1580  if (':' == routeList[colon])
1581  {
1582  routeList[colon] = '\0';
1583  if (GNUNET_OK != parse_port_policy (&routeList[colon + 1], &result[i].pp))
1584  break;
1585  }
1586  cnt = sscanf (&routeList[pos],
1587  "%u.%u.%u.%u/%u.%u.%u.%u%1s",
1588  &temps[0],
1589  &temps[1],
1590  &temps[2],
1591  &temps[3],
1592  &temps[4],
1593  &temps[5],
1594  &temps[6],
1595  &temps[7],
1596  dummy);
1597  if (8 == cnt)
1598  {
1599  for (j = 0; j < 8; j++)
1600  if (temps[j] > 0xFF)
1601  {
1603  _ ("Invalid format for IP: `%s'\n"),
1604  &routeList[pos]);
1605  GNUNET_free (result);
1606  GNUNET_free (routeList);
1607  return NULL;
1608  }
1609  result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16)
1610  + (temps[2] << 8) + temps[3]);
1611  result[i].netmask.s_addr = htonl ((temps[4] << 24) + (temps[5] << 16)
1612  + (temps[6] << 8) + temps[7]);
1613  pos = end + 1;
1614  i++;
1615  continue;
1616  }
1617  /* try second notation */
1618  cnt = sscanf (&routeList[pos],
1619  "%u.%u.%u.%u/%u%1s",
1620  &temps[0],
1621  &temps[1],
1622  &temps[2],
1623  &temps[3],
1624  &slash,
1625  dummy);
1626  if (5 == cnt)
1627  {
1628  for (j = 0; j < 4; j++)
1629  if (temps[j] > 0xFF)
1630  {
1632  _ ("Invalid format for IP: `%s'\n"),
1633  &routeList[pos]);
1634  GNUNET_free (result);
1635  GNUNET_free (routeList);
1636  return NULL;
1637  }
1638  result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16)
1639  + (temps[2] << 8) + temps[3]);
1640  if ((slash <= 32) && (slash >= 0))
1641  {
1642  result[i].netmask.s_addr = 0;
1643  while (slash > 0)
1644  {
1645  result[i].netmask.s_addr =
1646  (result[i].netmask.s_addr >> 1) + 0x80000000;
1647  slash--;
1648  }
1649  result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1650  pos = end + 1;
1651  i++;
1652  continue;
1653  }
1654  else
1655  {
1657  _ ("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
1658  slash);
1659  GNUNET_free (result);
1660  GNUNET_free (routeList);
1661  return NULL; /* error */
1662  }
1663  }
1664  /* try third notation */
1665  slash = 32;
1666  cnt = sscanf (&routeList[pos],
1667  "%u.%u.%u.%u%1s",
1668  &temps[0],
1669  &temps[1],
1670  &temps[2],
1671  &temps[3],
1672  dummy);
1673  if (4 == cnt)
1674  {
1675  for (j = 0; j < 4; j++)
1676  if (temps[j] > 0xFF)
1677  {
1679  _ ("Invalid format for IP: `%s'\n"),
1680  &routeList[pos]);
1681  GNUNET_free (result);
1682  GNUNET_free (routeList);
1683  return NULL;
1684  }
1685  result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16)
1686  + (temps[2] << 8) + temps[3]);
1687  result[i].netmask.s_addr = 0;
1688  while (slash > 0)
1689  {
1690  result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
1691  slash--;
1692  }
1693  result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1694  pos = end + 1;
1695  i++;
1696  continue;
1697  }
1699  _ ("Invalid format for IP: `%s'\n"),
1700  &routeList[pos]);
1701  GNUNET_free (result);
1702  GNUNET_free (routeList);
1703  return NULL; /* error */
1704  }
1705  if (pos < strlen (routeList))
1706  {
1708  _ ("Invalid format: `%s'\n"),
1709  &routeListX[pos]);
1710  GNUNET_free (result);
1711  GNUNET_free (routeList);
1712  return NULL; /* oops */
1713  }
1714  GNUNET_free (routeList);
1715  return result; /* ok */
1716 }
1717 
1718 
1731 GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX)
1732 {
1733  unsigned int count;
1734  unsigned int i;
1735  unsigned int len;
1736  unsigned int pos;
1737  int start;
1738  int slash;
1739  int ret;
1740  char *routeList;
1742  unsigned int bits;
1743  unsigned int off;
1744  int save;
1745  int colon;
1746  char dummy[2];
1747 
1748  if (NULL == routeListX)
1749  return NULL;
1750  len = strlen (routeListX);
1751  if (0 == len)
1752  return NULL;
1753  routeList = GNUNET_strdup (routeListX);
1754  count = 0;
1755  for (i = 0; i < len; i++)
1756  if (';' == routeList[i])
1757  count++;
1758  if (';' != routeList[len - 1])
1759  {
1761  _ ("Invalid network notation (does not end with ';': `%s')\n"),
1762  routeList);
1763  GNUNET_free (routeList);
1764  return NULL;
1765  }
1766 
1767  result = GNUNET_malloc (sizeof(struct GNUNET_STRINGS_IPv6NetworkPolicy)
1768  * (count + 1));
1769  i = 0;
1770  pos = 0;
1771  while (i < count)
1772  {
1773  start = pos;
1774  while (';' != routeList[pos])
1775  pos++;
1776  slash = pos;
1777  while ((slash >= start) && (routeList[slash] != '/'))
1778  slash--;
1779 
1780  if (slash < start)
1781  {
1782  memset (&result[i].netmask, 0xFF, sizeof(struct in6_addr));
1783  slash = pos;
1784  }
1785  else
1786  {
1787  routeList[pos] = '\0';
1788  for (colon = pos; ':' != routeList[colon]; colon--)
1789  if ('/' == routeList[colon])
1790  break;
1791  if (':' == routeList[colon])
1792  {
1793  routeList[colon] = '\0';
1794  if (GNUNET_OK !=
1795  parse_port_policy (&routeList[colon + 1], &result[i].pp))
1796  {
1797  GNUNET_free (result);
1798  GNUNET_free (routeList);
1799  return NULL;
1800  }
1801  }
1802  ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
1803  if (ret <= 0)
1804  {
1805  save = errno;
1806  if ((1 != sscanf (&routeList[slash + 1], "%u%1s", &bits, dummy)) ||
1807  (bits > 128))
1808  {
1809  if (0 == ret)
1811  _ ("Wrong format `%s' for netmask\n"),
1812  &routeList[slash + 1]);
1813  else
1814  {
1815  errno = save;
1816  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "inet_pton");
1817  }
1818  GNUNET_free (result);
1819  GNUNET_free (routeList);
1820  return NULL;
1821  }
1822  off = 0;
1823  while (bits > 8)
1824  {
1825  result[i].netmask.s6_addr[off++] = 0xFF;
1826  bits -= 8;
1827  }
1828  while (bits > 0)
1829  {
1830  result[i].netmask.s6_addr[off] =
1831  (result[i].netmask.s6_addr[off] >> 1) + 0x80;
1832  bits--;
1833  }
1834  }
1835  }
1836  routeList[slash] = '\0';
1837  ret = inet_pton (AF_INET6, &routeList[start], &result[i].network);
1838  if (ret <= 0)
1839  {
1840  if (0 == ret)
1842  _ ("Wrong format `%s' for network\n"),
1843  &routeList[slash + 1]);
1844  else
1845  LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
1846  GNUNET_free (result);
1847  GNUNET_free (routeList);
1848  return NULL;
1849  }
1850  pos++;
1851  i++;
1852  }
1853  GNUNET_free (routeList);
1854  return result;
1855 }
1856 
1857 
1860 #define FILLCHAR '='
1861 static char *cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1862  "abcdefghijklmnopqrstuvwxyz"
1863  "0123456789+/";
1864 
1865 
1875 size_t
1876 GNUNET_STRINGS_base64_encode (const void *in, size_t len, char **output)
1877 {
1878  const char *data = in;
1879  size_t ret;
1880  char *opt;
1881 
1882  ret = 0;
1883  GNUNET_assert (len / 4 < SIZE_MAX);
1884  opt = GNUNET_malloc (2 + (len * 4 / 3) + 8);
1885  for (size_t i = 0; i < len; ++i)
1886  {
1887  char c;
1888 
1889  c = (data[i] >> 2) & 0x3f;
1890  opt[ret++] = cvt[(int) c];
1891  c = (data[i] << 4) & 0x3f;
1892  if (++i < len)
1893  c |= (data[i] >> 4) & 0x0f;
1894  opt[ret++] = cvt[(int) c];
1895  if (i < len)
1896  {
1897  c = (data[i] << 2) & 0x3f;
1898  if (++i < len)
1899  c |= (data[i] >> 6) & 0x03;
1900  opt[ret++] = cvt[(int) c];
1901  }
1902  else
1903  {
1904  ++i;
1905  opt[ret++] = FILLCHAR;
1906  }
1907  if (i < len)
1908  {
1909  c = data[i] & 0x3f;
1910  opt[ret++] = cvt[(int) c];
1911  }
1912  else
1913  {
1914  opt[ret++] = FILLCHAR;
1915  }
1916  }
1917  *output = opt;
1918  return ret;
1919 }
1920 
1921 
1931 size_t
1932 GNUNET_STRINGS_base64url_encode (const void *in, size_t len, char **output)
1933 {
1934  char *enc;
1935  size_t pos;
1936 
1937  GNUNET_STRINGS_base64_encode (in, len, output);
1938  enc = *output;
1939  /* Replace with correct characters for base64url */
1940  pos = 0;
1941  while ('\0' != enc[pos])
1942  {
1943  if ('+' == enc[pos])
1944  enc[pos] = '-';
1945  if ('/' == enc[pos])
1946  enc[pos] = '_';
1947  if ('=' == enc[pos])
1948  {
1949  enc[pos] = '\0';
1950  break;
1951  }
1952  pos++;
1953  }
1954  return strlen (enc);
1955 }
1956 
1957 
1958 #define cvtfind(a) \
1959  ((((a) >= 'A') && ((a) <= 'Z')) \
1960  ? (a) - 'A' \
1961  : (((a) >= 'a') && ((a) <= 'z')) \
1962  ? (a) - 'a' + 26 \
1963  : (((a) >= '0') && ((a) <= '9')) \
1964  ? (a) - '0' + 52 \
1965  : ((a) == '+') ? 62 : ((a) == '/') ? 63 : -1)
1966 
1967 
1977 size_t
1978 GNUNET_STRINGS_base64_decode (const char *data, size_t len, void **out)
1979 {
1980  char *output;
1981  size_t ret = 0;
1982 
1983 #define CHECK_CRLF \
1984  while (data[i] == '\r' || data[i] == '\n') \
1985  { \
1986  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, \
1987  "ignoring CR/LF\n"); \
1988  i++; \
1989  if (i >= len) \
1990  goto END; \
1991  }
1992 
1993  GNUNET_assert (len / 3 < SIZE_MAX);
1994  output = GNUNET_malloc ((len * 3 / 4) + 8);
1996  "base64_decode decoding len=%d\n",
1997  (int) len);
1998  for (size_t i = 0; i < len; ++i)
1999  {
2000  char c;
2001  char c1;
2002 
2003  CHECK_CRLF;
2004  if (FILLCHAR == data[i])
2005  break;
2006  c = (char) cvtfind (data[i]);
2007  ++i;
2008  CHECK_CRLF;
2009  c1 = (char) cvtfind (data[i]);
2010  c = (c << 2) | ((c1 >> 4) & 0x3);
2011  output[ret++] = c;
2012  if (++i < len)
2013  {
2014  CHECK_CRLF;
2015  c = data[i];
2016  if (FILLCHAR == c)
2017  break;
2018  c = (char) cvtfind (c);
2019  c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
2020  output[ret++] = c1;
2021  }
2022  if (++i < len)
2023  {
2024  CHECK_CRLF;
2025  c1 = data[i];
2026  if (FILLCHAR == c1)
2027  break;
2028 
2029  c1 = (char) cvtfind (c1);
2030  c = ((c << 6) & 0xc0) | c1;
2031  output[ret++] = c;
2032  }
2033  }
2034 END:
2035  *out = output;
2036  return ret;
2037 }
2038 
2039 
2049 size_t
2050 GNUNET_STRINGS_base64url_decode (const char *data, size_t len, void **out)
2051 {
2052  char *s;
2053  int padding;
2054  size_t ret;
2055 
2056  /* make enough space for padding */
2057  GNUNET_assert (len < SIZE_MAX - 3);
2058  s = GNUNET_malloc (len + 3);
2059  memcpy (s, data, len);
2060 
2061  for (int i = 0; i < strlen (s); i++)
2062  {
2063  if (s[i] == '-')
2064  s[i] = '+';
2065  if (s[i] == '_')
2066  s[i] = '/';
2067  }
2068  padding = len % 4;
2069  switch (padding) // Pad with trailing '='s
2070  {
2071  case 0:
2072  break; // No pad chars in this case
2073  case 2:
2074  memcpy (&s[len],
2075  "==",
2076  2);
2077  len += 2;
2078  break; // Two pad chars
2079  case 3:
2080  s[len] = '=';
2081  len++;
2082  break; // One pad char
2083  default:
2084  GNUNET_assert (0);
2085  break;
2086  }
2087  ret = GNUNET_STRINGS_base64_decode (s, len, out);
2088  GNUNET_free (s);
2089  return ret;
2090 }
2091 
2092 
2102 size_t
2103 GNUNET_STRINGS_urldecode (const char *data, size_t len, char **out)
2104 {
2105  const char *rpos = data;
2106  *out = GNUNET_malloc (len + 1); /* output should always fit into input */
2107  char *wpos = *out;
2108  size_t resl = 0;
2109 
2110  while ('\0' != *rpos)
2111  {
2112  unsigned int num;
2113  switch (*rpos)
2114  {
2115  case '%':
2116  if (1 != sscanf (rpos + 1, "%2x", &num))
2117  break;
2118  *wpos = (char) ((unsigned char) num);
2119  wpos++;
2120  resl++;
2121  rpos += 3;
2122  break;
2123  /* TODO: add bad sequence handling */
2124  /* intentional fall through! */
2125  default:
2126  *wpos = *rpos;
2127  wpos++;
2128  resl++;
2129  rpos++;
2130  }
2131  }
2132  *wpos = '\0'; /* add 0-terminator */
2133  return resl;
2134 }
2135 
2136 
2146 size_t
2147 GNUNET_STRINGS_urlencode (const char *data, size_t len, char **out)
2148 {
2149  struct GNUNET_Buffer buf = { 0 };
2150  const uint8_t *i8 = (uint8_t *) data;
2151 
2152  while (0 != *i8)
2153  {
2154  if (0 == (0x80 & *i8))
2155  {
2156  /* traditional ASCII */
2157  if (isalnum (*i8) || (*i8 == '-') || (*i8 == '_') || (*i8 == '.') ||
2158  (*i8 == '~') )
2159  GNUNET_buffer_write (&buf, (const char*) i8, 1);
2160  else if (*i8 == ' ')
2161  GNUNET_buffer_write (&buf, "+", 1);
2162  else
2164  "%%%X%X",
2165  *i8 >> 4,
2166  *i8 & 15);
2167  i8++;
2168  continue;
2169  }
2170  if (0x80 + 0x40 == ((0x80 + 0x40 + 0x20) & *i8))
2171  {
2172  /* 2-byte value, percent-encode */
2174  "%%%X%X",
2175  *i8 >> 4,
2176  *i8 & 15);
2177  i8++;
2179  "%%%X%X",
2180  *i8 >> 4,
2181  *i8 & 15);
2182  i8++;
2183  continue;
2184  }
2185  if (0x80 + 0x40 + 0x20 == ((0x80 + 0x40 + 0x20 + 0x10) & *i8))
2186  {
2187  /* 3-byte value, percent-encode */
2188  for (unsigned int i = 0; i<3; i++)
2189  {
2191  "%%%X%X",
2192  *i8 >> 4,
2193  *i8 & 15);
2194  i8++;
2195  }
2196  continue;
2197  }
2198  if (0x80 + 0x40 + 0x20 + 0x10 == ((0x80 + 0x40 + 0x20 + 0x10 + 0x08) & *i8))
2199  {
2200  /* 4-byte value, percent-encode */
2201  for (unsigned int i = 0; i<4; i++)
2202  {
2204  "%%%X%X",
2205  *i8 >> 4,
2206  *i8 & 15);
2207  i8++;
2208  }
2209  continue;
2210  }
2211  if (0x80 + 0x40 + 0x20 + 0x10 + 0x08 == ((0x80 + 0x40 + 0x20 + 0x10 + 0x08
2212  + 0x04) & *i8))
2213  {
2214  /* 5-byte value, percent-encode (outside of UTF-8 modern standard, but so what) */
2215  for (unsigned int i = 0; i<5; i++)
2216  {
2218  "%%%X%X",
2219  *i8 >> 4,
2220  *i8 & 15);
2221  i8++;
2222  }
2223  continue;
2224  }
2225  if (0x80 + 0x40 + 0x20 + 0x10 + 0x08 + 0x04 == ((0x80 + 0x40 + 0x20 + 0x10
2226  + 0x08 + 0x04 + 0x02)
2227  & *i8))
2228  {
2229  /* 6-byte value, percent-encode (outside of UTF-8 modern standard, but so what) */
2230  for (unsigned int i = 0; i<6; i++)
2231  {
2233  "%%%X%X",
2234  *i8 >> 4,
2235  *i8 & 15);
2236  i8++;
2237  }
2238  continue;
2239  }
2240  /* really, really invalid UTF-8: fail */
2241  GNUNET_break (0);
2242  GNUNET_buffer_clear (&buf);
2243  return 0;
2244  }
2245  *out = GNUNET_buffer_reap_str (&buf);
2246  return strlen (*out);
2247 }
2248 
2249 
2250 /* 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:1539
#define CHECK_CRLF
size_t GNUNET_STRINGS_urldecode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:2103
#define FILLCHAR
******************** Base64 encoding
Definition: strings.c:1860
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:1482
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:1054
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
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:1731
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:1459
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:1130
#define cvtfind(a)
Definition: strings.c:1958
#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.
void GNUNET_buffer_write_fstr(struct GNUNET_Buffer *buf, const char *fmt,...) __attribute__((format(printf
Write a 0-terminated formatted string to a buffer, excluding the 0-terminator.
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:1423
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:1861
#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:1932
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:184
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
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:1299
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
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:1372
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:810
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **out)
Decode from Base64.
Definition: strings.c:1978
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1876
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#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:791
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:2147
int GNUNET_STRINGS_check_filename(const char *filename, enum GNUNET_STRINGS_FilenameCheck checks)
Perform checks on filename.
Definition: strings.c:1180
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:1225
#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:937
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
"asctime", except for GNUnet time.
Definition: strings.c:758
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:1348
size_t GNUNET_STRINGS_base64url_decode(const char *data, size_t len, void **out)
Decode from Base64url.
Definition: strings.c:2050
#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:972
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:872
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...