GNUnet  0.19.4
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  */
28 #include "platform.h"
29 #if HAVE_ICONV
30 #include <iconv.h>
31 #endif
32 #include "gnunet_util_lib.h"
33 #include <unicase.h>
34 #include <unistr.h>
35 #include <uniconv.h>
36 
37 #define LOG(kind, ...) GNUNET_log_from (kind, "util-strings", __VA_ARGS__)
38 
39 #define LOG_STRERROR(kind, syscall) \
40  GNUNET_log_from_strerror (kind, "util-strings", syscall)
41 
42 
43 size_t
45  size_t size,
46  unsigned int count, ...)
47 {
48  size_t needed;
49  va_list ap;
50 
51  needed = 0;
52  va_start (ap, count);
53  while (count > 0)
54  {
55  const char *s = va_arg (ap, const char *);
56  size_t slen = strlen (s) + 1;
57 
58  GNUNET_assert (slen <= size - needed);
59  if (NULL != buffer)
60  GNUNET_memcpy (&buffer[needed],
61  s,
62  slen);
63  needed += slen;
64  count--;
65  }
66  va_end (ap);
67  return needed;
68 }
69 
70 
71 unsigned int
72 GNUNET_STRINGS_buffer_tokenize (const char *buffer,
73  size_t size,
74  unsigned int count,
75  ...)
76 {
77  unsigned int start;
78  unsigned int needed;
79  const char **r;
80  va_list ap;
81 
82  needed = 0;
83  va_start (ap, count);
84  while (count > 0)
85  {
86  r = va_arg (ap, const char **);
87 
88  start = needed;
89  while ((needed < size) && (buffer[needed] != '\0'))
90  needed++;
91  if (needed == size)
92  {
93  va_end (ap);
94  return 0; /* error */
95  }
96  *r = &buffer[start];
97  needed++; /* skip 0-termination */
98  count--;
99  }
100  va_end (ap);
101  return needed;
102 }
103 
104 
105 char *
107 {
108  const char *unit = /* size unit */ "b";
109  char *ret;
110 
111  if (size > 5 * 1024)
112  {
113  size = size / 1024;
114  unit = "KiB";
115  if (size > 5 * 1024)
116  {
117  size = size / 1024;
118  unit = "MiB";
119  if (size > 5 * 1024)
120  {
121  size = size / 1024;
122  unit = "GiB";
123  if (size > 5 * 1024)
124  {
125  size = size / 1024;
126  unit = "TiB";
127  }
128  }
129  }
130  }
131  ret = GNUNET_malloc (32);
132  GNUNET_snprintf (ret, 32, "%llu %s", size, unit);
133  return ret;
134 }
135 
136 
137 size_t
138 GNUNET_strlcpy (char *dst,
139  const char *src,
140  size_t n)
141 {
142  size_t slen;
143 
144  GNUNET_assert (0 != n);
145  slen = strnlen (src, n - 1);
146  memcpy (dst, src, slen);
147  dst[slen] = '\0';
148  return slen;
149 }
150 
151 
156 {
160  const char *name;
161 
165  unsigned long long value;
166 };
167 
168 
180 static enum GNUNET_GenericReturnValue
181 convert_with_table (const char *input,
182  const struct ConversionTable *table,
183  unsigned long long *output)
184 {
185  unsigned long long ret;
186  char *in;
187  const char *tok;
188  unsigned long long last;
189  unsigned int i;
190  char *sptr;
191 
192  ret = 0;
193  last = 0;
194  in = GNUNET_strdup (input);
195  for (tok = strtok_r (in, " ", &sptr);
196  tok != NULL;
197  tok = strtok_r (NULL, " ", &sptr))
198  {
199  do
200  {
201  i = 0;
202  while ((table[i].name != NULL) && (0 != strcasecmp (table[i].name, tok)))
203  i++;
204  if (table[i].name != NULL)
205  {
206  last *= table[i].value;
207  break; /* next tok */
208  }
209  else
210  {
211  char *endptr;
212  ret += last;
213  errno = 0;
214  last = strtoull (tok, &endptr, 10);
215  if ((0 != errno) || (endptr == tok))
216  {
217  GNUNET_free (in);
218  return GNUNET_SYSERR; /* expected number */
219  }
220  if ('\0' == endptr[0])
221  break; /* next tok */
222  else
223  tok = endptr; /* and re-check (handles times like "10s") */
224  }
225  }
226  while (GNUNET_YES);
227  }
228  ret += last;
229  *output = ret;
230  GNUNET_free (in);
231  return GNUNET_OK;
232 }
233 
234 
236 GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
237  unsigned long long *size)
238 {
239  static const struct ConversionTable table[] =
240  { { "B", 1 },
241  { "KiB", 1024 },
242  { "kB", 1000 },
243  { "MiB", 1024 * 1024 },
244  { "MB", 1000 * 1000 },
245  { "GiB", 1024 * 1024 * 1024 },
246  { "GB", 1000 * 1000 * 1000 },
247  { "TiB", 1024LL * 1024LL * 1024LL * 1024LL },
248  { "TB", 1000LL * 1000LL * 1000LL * 1024LL },
249  { "PiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL },
250  { "PB", 1000LL * 1000LL * 1000LL * 1024LL * 1000LL },
251  { "EiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL },
252  { "EB", 1000LL * 1000LL * 1000LL * 1024LL * 1000LL * 1000LL },
253  { NULL, 0 } };
254 
255  return convert_with_table (fancy_size, table, size);
256 }
257 
258 
260 GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time,
261  struct GNUNET_TIME_Relative *rtime)
262 {
263  static const struct ConversionTable table[] =
264  { { "us", 1 },
265  { "ms", 1000 },
266  { "s", 1000 * 1000LL },
267  { "second", 1000 * 1000LL },
268  { "seconds", 1000 * 1000LL },
269  { "\"", 1000 * 1000LL },
270  { "m", 60 * 1000 * 1000LL },
271  { "min", 60 * 1000 * 1000LL },
272  { "minute", 60 * 1000 * 1000LL },
273  { "minutes", 60 * 1000 * 1000LL },
274  { "'", 60 * 1000 * 1000LL },
275  { "h", 60 * 60 * 1000 * 1000LL },
276  { "hour", 60 * 60 * 1000 * 1000LL },
277  { "hours", 60 * 60 * 1000 * 1000LL },
278  { "d", 24 * 60 * 60 * 1000LL * 1000LL },
279  { "day", 24 * 60 * 60 * 1000LL * 1000LL },
280  { "days", 24 * 60 * 60 * 1000LL * 1000LL },
281  { "week", 7 * 24 * 60 * 60 * 1000LL * 1000LL },
282  { "weeks", 7 * 24 * 60 * 60 * 1000LL * 1000LL },
283  { "year", 31536000000000LL /* year */ },
284  { "years", 31536000000000LL /* year */ },
285  { "a", 31536000000000LL /* year */ },
286  { NULL, 0 } };
287  int ret;
288  unsigned long long val;
289 
290  if (0 == strcasecmp ("forever", fancy_time))
291  {
293  return GNUNET_OK;
294  }
295  ret = convert_with_table (fancy_time, table, &val);
296  rtime->rel_value_us = (uint64_t) val;
297  return ret;
298 }
299 
300 
302 GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time,
303  struct GNUNET_TIME_Absolute *atime)
304 {
305  struct tm tv;
306  time_t t;
307  const char *eos;
308 
309  if (0 == strcasecmp ("end of time", fancy_time))
310  {
312  return GNUNET_OK;
313  }
314  eos = &fancy_time[strlen (fancy_time)];
315  memset (&tv, 0, sizeof(tv));
316  if ((eos != strptime (fancy_time, "%a %b %d %H:%M:%S %Y", &tv)) &&
317  (eos != strptime (fancy_time, "%c", &tv)) &&
318  (eos != strptime (fancy_time, "%Ec", &tv)) &&
319  (eos != strptime (fancy_time, "%Y-%m-%d %H:%M:%S", &tv)) &&
320  (eos != strptime (fancy_time, "%Y-%m-%d %H:%M", &tv)) &&
321  (eos != strptime (fancy_time, "%x", &tv)) &&
322  (eos != strptime (fancy_time, "%Ex", &tv)) &&
323  (eos != strptime (fancy_time, "%Y-%m-%d", &tv)) &&
324  (eos != strptime (fancy_time, "%Y-%m", &tv)) &&
325  (eos != strptime (fancy_time, "%Y", &tv)))
326  return GNUNET_SYSERR;
327  t = mktime (&tv);
328  atime->abs_value_us = (uint64_t) ((uint64_t) t * 1000LL * 1000LL);
329  return GNUNET_OK;
330 }
331 
332 
334 GNUNET_STRINGS_fancy_time_to_timestamp (const char *fancy_time,
335  struct GNUNET_TIME_Timestamp *atime)
336 {
337  return GNUNET_STRINGS_fancy_time_to_absolute (fancy_time,
338  &atime->abs_time);
339 }
340 
341 
342 char *
343 GNUNET_STRINGS_conv (const char *input,
344  size_t len,
345  const char *input_charset,
346  const char *output_charset)
347 {
348  char *ret;
349  uint8_t *u8_string;
350  char *encoded_string;
351  size_t u8_string_length;
352  size_t encoded_string_length;
353 
354  u8_string = u8_conv_from_encoding (input_charset,
355  iconveh_error,
356  input,
357  len,
358  NULL,
359  NULL,
360  &u8_string_length);
361  if (NULL == u8_string)
362  {
363  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_from_encoding");
364  goto fail;
365  }
366  if (0 == strcmp (output_charset, "UTF-8"))
367  {
368  ret = GNUNET_malloc (u8_string_length + 1);
369  GNUNET_memcpy (ret, u8_string, u8_string_length);
370  ret[u8_string_length] = '\0';
371  free (u8_string);
372  return ret;
373  }
374  encoded_string = u8_conv_to_encoding (output_charset,
375  iconveh_error,
376  u8_string,
377  u8_string_length,
378  NULL,
379  NULL,
380  &encoded_string_length);
381  free (u8_string);
382  if (NULL == encoded_string)
383  {
384  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_to_encoding");
385  goto fail;
386  }
387  ret = GNUNET_malloc (encoded_string_length + 1);
388  GNUNET_memcpy (ret, encoded_string, encoded_string_length);
389  ret[encoded_string_length] = '\0';
390  free (encoded_string);
391  return ret;
392  fail:
394  _ ("Character sets requested were `%s'->`%s'\n"),
395  "UTF-8",
396  output_charset);
397  ret = GNUNET_malloc (len + 1);
398  GNUNET_memcpy (ret, input, len);
399  ret[len] = '\0';
400  return ret;
401 }
402 
403 
404 char *
405 GNUNET_STRINGS_to_utf8 (const char *input,
406  size_t len,
407  const char *charset)
408 {
409  return GNUNET_STRINGS_conv (input,
410  len,
411  charset,
412  "UTF-8");
413 }
414 
415 
416 char *
417 GNUNET_STRINGS_from_utf8 (const char *input,
418  size_t len,
419  const char *charset)
420 {
421  return GNUNET_STRINGS_conv (input,
422  len,
423  "UTF-8",
424  charset);
425 }
426 
427 
428 char *
429 GNUNET_STRINGS_utf8_normalize (const char *input)
430 {
431  uint8_t *tmp;
432  size_t len;
433  char *output;
434  tmp = u8_normalize (UNINORM_NFC,
435  (uint8_t *) input,
436  strlen ((char*) input),
437  NULL,
438  &len);
439  if (NULL == tmp)
440  return NULL;
441  output = GNUNET_malloc (len + 1);
442  GNUNET_memcpy (output, tmp, len);
443  output[len] = '\0';
444  free (tmp);
445  return output;
446 }
447 
449 GNUNET_STRINGS_utf8_tolower (const char *input,
450  char *output)
451 {
452  uint8_t *tmp_in;
453  size_t len;
454 
455  tmp_in = u8_tolower ((uint8_t *) input,
456  strlen ((char *) input),
457  NULL,
458  UNINORM_NFD,
459  NULL,
460  &len);
461  if (NULL == tmp_in)
462  return GNUNET_SYSERR;
463  GNUNET_memcpy (output, tmp_in, len);
464  output[len] = '\0';
465  GNUNET_free (tmp_in);
466  return GNUNET_OK;
467 }
468 
469 
471 GNUNET_STRINGS_utf8_toupper (const char *input,
472  char *output)
473 {
474  uint8_t *tmp_in;
475  size_t len;
476 
477  tmp_in = u8_toupper ((uint8_t *) input,
478  strlen ((char *) input),
479  NULL,
480  UNINORM_NFD,
481  NULL,
482  &len);
483  if (NULL == tmp_in)
484  return GNUNET_SYSERR;
485  /* 0-terminator does not fit */
486  GNUNET_memcpy (output, tmp_in, len);
487  output[len] = '\0';
488  GNUNET_free (tmp_in);
489  return GNUNET_OK;
490 }
491 
492 
493 char *
495 {
496  char *buffer;
497  size_t len;
498  char *fm;
499  const char *fil_ptr;
500 
501  if (fil == NULL)
502  return NULL;
503 
504  if (fil[0] == DIR_SEPARATOR)
505  /* absolute path, just copy */
506  return GNUNET_strdup (fil);
507  if (fil[0] == '~')
508  {
509  fm = getenv ("HOME");
510  if (fm == NULL)
511  {
513  _ ("Failed to expand `$HOME': environment variable `HOME' not set"));
514  return NULL;
515  }
516  fm = GNUNET_strdup (fm);
517  /* do not copy '~' */
518  fil_ptr = fil + 1;
519 
520  /* skip over dir separator to be consistent */
521  if (fil_ptr[0] == DIR_SEPARATOR)
522  fil_ptr++;
523  }
524  else
525  {
526  /* relative path */
527  fil_ptr = fil;
528  len = 512;
529  fm = NULL;
530  while (1)
531  {
532  buffer = GNUNET_malloc (len);
533  if (getcwd (buffer, len) != NULL)
534  {
535  fm = buffer;
536  break;
537  }
538  if ((errno == ERANGE) && (len < 1024 * 1024 * 4))
539  {
540  len *= 2;
541  GNUNET_free (buffer);
542  continue;
543  }
544  GNUNET_free (buffer);
545  break;
546  }
547  if (fm == NULL)
548  {
550  buffer = getenv ("PWD"); /* alternative */
551  if (buffer != NULL)
552  fm = GNUNET_strdup (buffer);
553  }
554  if (fm == NULL)
555  fm = GNUNET_strdup ("./"); /* give up */
556  }
557  GNUNET_asprintf (&buffer,
558  "%s%s%s",
559  fm,
560  (fm[strlen (fm) - 1] == DIR_SEPARATOR) ? ""
562  fil_ptr);
563  GNUNET_free (fm);
564  return buffer;
565 }
566 
567 
568 const char *
570  int do_round)
571 {
572  static GNUNET_THREAD_LOCAL char buf[128];
573  const char *unit = /* time unit */ "µs";
574  uint64_t dval = delta.rel_value_us;
575 
576  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == delta.rel_value_us)
577  return "forever";
578  if (0 == delta.rel_value_us)
579  return "0 ms";
580  if (((GNUNET_YES == do_round) && (dval > 5 * 1000)) || (0 == (dval % 1000)))
581  {
582  dval = dval / 1000;
583  unit = /* time unit */ "ms";
584  if (((GNUNET_YES == do_round) && (dval > 5 * 1000)) || (0 == (dval % 1000)))
585  {
586  dval = dval / 1000;
587  unit = /* time unit */ "s";
588  if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
589  {
590  dval = dval / 60;
591  unit = /* time unit */ "m";
592  if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
593  {
594  dval = dval / 60;
595  unit = /* time unit */ "h";
596  if (((GNUNET_YES == do_round) && (dval > 5 * 24)) ||
597  (0 == (dval % 24)))
598  {
599  dval = dval / 24;
600  if (1 == dval)
601  unit = /* time unit */ "day";
602  else
603  unit = /* time unit */ "days";
604  }
605  }
606  }
607  }
608  }
609  GNUNET_snprintf (buf, sizeof(buf), "%llu %s",
610  (unsigned long long) dval, unit);
611  return buf;
612 }
613 
614 
615 const char *
617 {
618  static GNUNET_THREAD_LOCAL char buf[255];
619  time_t tt;
620  struct tm *tp;
621 
623  return "end of time";
624  tt = t.abs_value_us / 1000LL / 1000LL;
625  tp = localtime (&tt);
626  /* This is hacky, but i don't know a way to detect libc character encoding.
627  * Just expect utf8 from glibc these days.
628  * As for msvcrt, use the wide variant, which always returns utf16
629  * (otherwise we'd have to detect current codepage or use W32API character
630  * set conversion routines to convert to UTF8).
631  */
632  strftime (buf, sizeof(buf), "%a %b %d %H:%M:%S %Y", tp);
633 
634  return buf;
635 }
636 
637 
638 const char *
640 {
641  const char *short_fn = filename;
642  const char *ss;
643 
644  while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)) && (ss[1] != '\0'))
645  short_fn = 1 + ss;
646  return short_fn;
647 }
648 
649 
657 static unsigned int
658 getValue__ (unsigned char a)
659 {
660  unsigned int dec;
661 
662  switch (a)
663  {
664  case 'O':
665  case 'o':
666  a = '0';
667  break;
668 
669  case 'i':
670  case 'I':
671  case 'l':
672  case 'L':
673  a = '1';
674  break;
675 
676  /* also consider U to be V */
677  case 'u':
678  case 'U':
679  a = 'V';
680  break;
681 
682  default:
683  break;
684  }
685  if ((a >= '0') && (a <= '9'))
686  return a - '0';
687  if ((a >= 'a') && (a <= 'z'))
688  a = toupper (a);
689  /* return (a - 'a' + 10); */
690  dec = 0;
691  if ((a >= 'A') && (a <= 'Z'))
692  {
693  if ('I' < a)
694  dec++;
695  if ('L' < a)
696  dec++;
697  if ('O' < a)
698  dec++;
699  if ('U' < a)
700  dec++;
701  return(a - 'A' + 10 - dec);
702  }
703  return -1;
704 }
705 
706 
707 char *
709  size_t size,
710  char *out,
711  size_t out_size)
712 {
716  static char *encTable__ = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
717  unsigned int wpos;
718  unsigned int rpos;
719  unsigned int bits;
720  unsigned int vbit;
721  const unsigned char *udata;
722 
723  GNUNET_assert (size < SIZE_MAX / 8 - 4);
724  udata = data;
725  if (out_size < (size * 8 + 4) / 5)
726  {
727  GNUNET_break (0);
728  return NULL;
729  }
730  vbit = 0;
731  wpos = 0;
732  rpos = 0;
733  bits = 0;
734  while ((rpos < size) || (vbit > 0))
735  {
736  if ((rpos < size) && (vbit < 5))
737  {
738  bits = (bits << 8) | udata[rpos++]; /* eat 8 more bits */
739  vbit += 8;
740  }
741  if (vbit < 5)
742  {
743  bits <<= (5 - vbit); /* zero-padding */
744  GNUNET_assert (vbit == ((size * 8) % 5));
745  vbit = 5;
746  }
747  if (wpos >= out_size)
748  {
749  GNUNET_break (0);
750  return NULL;
751  }
752  out[wpos++] = encTable__[(bits >> (vbit - 5)) & 31];
753  vbit -= 5;
754  }
755  GNUNET_assert (0 == vbit);
756  if (wpos < out_size)
757  out[wpos] = '\0';
758  return &out[wpos];
759 }
760 
761 
762 char *
764 {
765  char *str_buf;
766  size_t len = size * 8;
767  char *end;
768 
769  if (len % 5 > 0)
770  len += 5 - len % 5;
771  len /= 5;
772  str_buf = GNUNET_malloc (len + 1);
774  size,
775  str_buf,
776  len);
777  if (NULL == end)
778  {
779  GNUNET_free (str_buf);
780  return NULL;
781  }
782  *end = '\0';
783  return str_buf;
784 }
785 
786 
789  size_t enclen,
790  void *out,
791  size_t out_size)
792 {
793  size_t rpos;
794  size_t wpos;
795  unsigned int bits;
796  unsigned int vbit;
797  int ret;
798  int shift;
799  unsigned char *uout;
800  size_t encoded_len;
801 
802  if (0 == enclen)
803  {
804  if (0 == out_size)
805  return GNUNET_OK;
806  return GNUNET_SYSERR;
807  }
808  GNUNET_assert (out_size < SIZE_MAX / 8);
809  encoded_len = out_size * 8;
810  uout = out;
811  wpos = out_size;
812  rpos = enclen;
813  if ((encoded_len % 5) > 0)
814  {
815  vbit = encoded_len % 5; /* padding! */
816  shift = 5 - vbit;
817  bits = (ret = getValue__ (enc[--rpos])) >> shift;
818  }
819  else
820  {
821  vbit = 5;
822  shift = 0;
823  bits = (ret = getValue__ (enc[--rpos]));
824  }
825  if ((encoded_len + shift) / 5 != enclen)
826  return GNUNET_SYSERR;
827  if (-1 == ret)
828  return GNUNET_SYSERR;
829  while (wpos > 0)
830  {
831  if (0 == rpos)
832  {
833  GNUNET_break (0);
834  return GNUNET_SYSERR;
835  }
836  bits = ((ret = getValue__ (enc[--rpos])) << vbit) | bits;
837  if (-1 == ret)
838  return GNUNET_SYSERR;
839  vbit += 5;
840  if (vbit >= 8)
841  {
842  uout[--wpos] = (unsigned char) bits;
843  bits >>= 8;
844  vbit -= 8;
845  }
846  }
847  if ((0 != rpos) || (0 != vbit))
848  return GNUNET_SYSERR;
849  return GNUNET_OK;
850 }
851 
852 
855  size_t enclen,
856  void **out,
857  size_t *out_size)
858 {
859  size_t size;
860  void *data;
861  int res;
862 
863  size = (enclen * 5) / 8;
865  {
866  GNUNET_break_op (0);
867  return GNUNET_SYSERR;
868  }
869  data = GNUNET_malloc (size);
871  enclen,
872  data,
873  size);
874  if ( (0 < size) &&
875  (GNUNET_OK != res) )
876  {
877  size--;
879  enclen,
880  data,
881  size);
882  }
883  if (GNUNET_OK != res)
884  {
885  GNUNET_break_op (0);
886  GNUNET_free (data);
887  return GNUNET_SYSERR;
888  }
889  *out = data;
890  *out_size = size;
891  return GNUNET_OK;
892 }
893 
894 
896 GNUNET_STRINGS_parse_uri (const char *path,
897  char **scheme_part,
898  const char **path_part)
899 {
900  size_t len;
901  size_t i;
902  int end;
903  int pp_state = 0;
904  const char *post_scheme_part = NULL;
905 
906  len = strlen (path);
907  for (end = 0, i = 0; ! end && i < len; i++)
908  {
909  switch (pp_state)
910  {
911  case 0:
912  if ((path[i] == ':') && (i > 0))
913  {
914  pp_state += 1;
915  continue;
916  }
917  if (! (((path[i] >= 'A') && (path[i] <= 'Z') ) ||
918  ((path[i] >= 'a') && (path[i] <= 'z') ) ||
919  ((path[i] >= '0') && (path[i] <= '9') ) || (path[i] == '+') ||
920  (path[i] == '-') || (path[i] == '.')))
921  end = 1;
922  break;
923 
924  case 1:
925  case 2:
926  if (path[i] == '/')
927  {
928  pp_state += 1;
929  continue;
930  }
931  end = 1;
932  break;
933 
934  case 3:
935  post_scheme_part = &path[i];
936  end = 1;
937  break;
938 
939  default:
940  end = 1;
941  }
942  }
943  if (post_scheme_part == NULL)
944  return GNUNET_NO;
945  if (scheme_part)
946  {
947  *scheme_part = GNUNET_malloc (post_scheme_part - path + 1);
948  GNUNET_memcpy (*scheme_part, path, post_scheme_part - path);
949  (*scheme_part)[post_scheme_part - path] = '\0';
950  }
951  if (path_part)
952  *path_part = post_scheme_part;
953  return GNUNET_YES;
954 }
955 
956 
959  int can_be_uri,
960  int *r_is_uri,
961  char **r_uri_scheme)
962 {
963  const char *post_scheme_path;
964  int is_uri;
965  char *uri;
966  /* consider POSIX paths to be absolute too, even on W32,
967  * as plibc expansion will fix them for us.
968  */
969  if (filename[0] == '/')
970  return GNUNET_YES;
971  if (can_be_uri)
972  {
973  is_uri = GNUNET_STRINGS_parse_uri (filename, &uri, &post_scheme_path);
974  if (r_is_uri)
975  *r_is_uri = is_uri;
976  if (is_uri)
977  {
978  if (r_uri_scheme)
979  *r_uri_scheme = uri;
980  else
981  GNUNET_free (uri);
982 
983  return GNUNET_STRINGS_path_is_absolute (post_scheme_path,
984  GNUNET_NO,
985  NULL,
986  NULL);
987  }
988  }
989  else
990  {
991  if (r_is_uri)
992  *r_is_uri = GNUNET_NO;
993  }
994 
995  return GNUNET_NO;
996 }
997 
998 
1001  enum GNUNET_STRINGS_FilenameCheck checks)
1002 {
1003  struct stat st;
1004 
1005  if ((NULL == filename) || (filename[0] == '\0'))
1006  return GNUNET_SYSERR;
1007  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_ABSOLUTE))
1008  if (! GNUNET_STRINGS_path_is_absolute (filename, GNUNET_NO, NULL, NULL))
1009  return GNUNET_NO;
1010  if (0 != (checks
1013  {
1014  if (0 != lstat (filename, &st))
1015  {
1016  if (0 != (checks & GNUNET_STRINGS_CHECK_EXISTS))
1017  return GNUNET_NO;
1018  else
1019  return GNUNET_SYSERR;
1020  }
1021  }
1022  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_DIRECTORY))
1023  if (! S_ISDIR (st.st_mode))
1024  return GNUNET_NO;
1025  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_LINK))
1026  if (! S_ISLNK (st.st_mode))
1027  return GNUNET_NO;
1028  return GNUNET_YES;
1029 }
1030 
1031 
1033 GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
1034  uint16_t addrlen,
1035  struct sockaddr_in6 *r_buf)
1036 {
1037  char zbuf[addrlen + 1];
1038  int ret;
1039  char *port_colon;
1040  unsigned int port;
1041  char dummy[2];
1042 
1043  if (addrlen < 6)
1044  return GNUNET_SYSERR;
1045  GNUNET_memcpy (zbuf, zt_addr, addrlen);
1046  if ('[' != zbuf[0])
1047  {
1049  _ ("IPv6 address did not start with `['\n"));
1050  return GNUNET_SYSERR;
1051  }
1052  zbuf[addrlen] = '\0';
1053  port_colon = strrchr (zbuf, ':');
1054  if (NULL == port_colon)
1055  {
1057  _ ("IPv6 address did contain ':' to separate port number\n"));
1058  return GNUNET_SYSERR;
1059  }
1060  if (']' != *(port_colon - 1))
1061  {
1062  GNUNET_log (
1064  _ ("IPv6 address did contain ']' before ':' to separate port number\n"));
1065  return GNUNET_SYSERR;
1066  }
1067  ret = sscanf (port_colon, ":%u%1s", &port, dummy);
1068  if ((1 != ret) || (port > 65535))
1069  {
1070  GNUNET_log (
1072  _ ("IPv6 address did contain a valid port number after the last ':'\n"));
1073  return GNUNET_SYSERR;
1074  }
1075  *(port_colon - 1) = '\0';
1076  memset (r_buf, 0, sizeof(struct sockaddr_in6));
1077  ret = inet_pton (AF_INET6, &zbuf[1], &r_buf->sin6_addr);
1078  if (ret <= 0)
1079  {
1081  _ ("Invalid IPv6 address `%s': %s\n"),
1082  &zbuf[1],
1083  strerror (errno));
1084  return GNUNET_SYSERR;
1085  }
1086  r_buf->sin6_port = htons (port);
1087  r_buf->sin6_family = AF_INET6;
1088 #if HAVE_SOCKADDR_IN_SIN_LEN
1089  r_buf->sin6_len = (u_char) sizeof(struct sockaddr_in6);
1090 #endif
1091  return GNUNET_OK;
1092 }
1093 
1094 
1096 GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr,
1097  uint16_t addrlen,
1098  struct sockaddr_in *r_buf)
1099 {
1100  unsigned int temps[4];
1101  unsigned int port;
1102  unsigned int cnt;
1103  char dummy[2];
1104 
1105  if (addrlen < 9)
1106  return GNUNET_SYSERR;
1107  cnt = sscanf (zt_addr,
1108  "%u.%u.%u.%u:%u%1s",
1109  &temps[0],
1110  &temps[1],
1111  &temps[2],
1112  &temps[3],
1113  &port,
1114  dummy);
1115  if (5 != cnt)
1116  return GNUNET_SYSERR;
1117  for (cnt = 0; cnt < 4; cnt++)
1118  if (temps[cnt] > 0xFF)
1119  return GNUNET_SYSERR;
1120  if (port > 65535)
1121  return GNUNET_SYSERR;
1122  r_buf->sin_family = AF_INET;
1123  r_buf->sin_port = htons (port);
1124  r_buf->sin_addr.s_addr =
1125  htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + temps[3]);
1126 #if HAVE_SOCKADDR_IN_SIN_LEN
1127  r_buf->sin_len = (u_char) sizeof(struct sockaddr_in);
1128 #endif
1129  return GNUNET_OK;
1130 }
1131 
1132 
1134 GNUNET_STRINGS_to_address_ip (const char *addr,
1135  uint16_t addrlen,
1136  struct sockaddr_storage *r_buf)
1137 {
1138  if (addr[0] == '[')
1139  return GNUNET_STRINGS_to_address_ipv6 (addr,
1140  addrlen,
1141  (struct sockaddr_in6 *) r_buf);
1142  return GNUNET_STRINGS_to_address_ipv4 (addr,
1143  addrlen,
1144  (struct sockaddr_in *) r_buf);
1145 }
1146 
1147 
1148 size_t
1150  uint8_t *af,
1151  struct sockaddr **sa)
1152 {
1153  char *cp = GNUNET_strdup (addr);
1154 
1155  *af = AF_UNSPEC;
1156  if ('[' == *addr)
1157  {
1158  /* IPv6 */
1159  *sa = GNUNET_malloc (sizeof(struct sockaddr_in6));
1160  if (GNUNET_OK !=
1162  strlen (cp),
1163  (struct sockaddr_in6 *) *sa))
1164  {
1165  GNUNET_free (*sa);
1166  *sa = NULL;
1167  GNUNET_free (cp);
1168  return 0;
1169  }
1170  *af = AF_INET6;
1171  GNUNET_free (cp);
1172  return sizeof(struct sockaddr_in6);
1173  }
1174  else
1175  {
1176  /* IPv4 */
1177  *sa = GNUNET_malloc (sizeof(struct sockaddr_in));
1178  if (GNUNET_OK !=
1180  strlen (cp),
1181  (struct sockaddr_in *) *sa))
1182  {
1183  GNUNET_free (*sa);
1184  *sa = NULL;
1185  GNUNET_free (cp);
1186  return 0;
1187  }
1188  *af = AF_INET;
1189  GNUNET_free (cp);
1190  return sizeof(struct sockaddr_in);
1191  }
1192 }
1193 
1194 
1199 static char *const *
1200 _make_continuous_arg_copy (int argc, char *const *argv)
1201 {
1202  size_t argvsize = 0;
1203  char **new_argv;
1204  char *p;
1205 
1206  for (int i = 0; i < argc; i++)
1207  argvsize += strlen (argv[i]) + 1 + sizeof(char *);
1208  new_argv = GNUNET_malloc (argvsize + sizeof(char *));
1209  p = (char *) &new_argv[argc + 1];
1210  for (int i = 0; i < argc; i++)
1211  {
1212  new_argv[i] = p;
1213  strcpy (p, argv[i]);
1214  p += strlen (argv[i]) + 1;
1215  }
1216  new_argv[argc] = NULL;
1217  return (char *const *) new_argv;
1218 }
1219 
1220 
1223  char *const *argv,
1224  int *u8argc,
1225  char *const **u8argv)
1226 {
1227  char *const *new_argv =
1228  (char *const *) _make_continuous_arg_copy (argc, argv);
1229  *u8argv = new_argv;
1230  *u8argc = argc;
1231  return GNUNET_OK;
1232 }
1233 
1234 
1244 static enum GNUNET_GenericReturnValue
1245 parse_port_policy (const char *port_policy,
1246  struct GNUNET_STRINGS_PortPolicy *pp)
1247 {
1248  const char *pos;
1249  int s;
1250  int e;
1251  char eol[2];
1252 
1253  pos = port_policy;
1254  if ('!' == *pos)
1255  {
1257  pos++;
1258  }
1259  if (2 == sscanf (pos, "%u-%u%1s", &s, &e, eol))
1260  {
1261  if ((0 == s) || (s > 0xFFFF) || (e < s) || (e > 0xFFFF))
1262  {
1263  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Port not in range\n"));
1264  return GNUNET_SYSERR;
1265  }
1266  pp->start_port = (uint16_t) s;
1267  pp->end_port = (uint16_t) e;
1268  return GNUNET_OK;
1269  }
1270  if (1 == sscanf (pos, "%u%1s", &s, eol))
1271  {
1272  if ((0 == s) || (s > 0xFFFF))
1273  {
1274  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Port not in range\n"));
1275  return GNUNET_SYSERR;
1276  }
1277 
1278  pp->start_port = (uint16_t) s;
1279  pp->end_port = (uint16_t) s;
1280  return GNUNET_OK;
1281  }
1283  _ ("Malformed port policy `%s'\n"),
1284  port_policy);
1285  return GNUNET_SYSERR;
1286 }
1287 
1288 
1290 GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1291 {
1292  unsigned int count;
1293  unsigned int i;
1294  unsigned int j;
1295  unsigned int len;
1296  int cnt;
1297  unsigned int pos;
1298  unsigned int temps[8];
1299  int slash;
1301  int colon;
1302  int end;
1303  char *routeList;
1304  char dummy[2];
1305 
1306  if (NULL == routeListX)
1307  return NULL;
1308  len = strlen (routeListX);
1309  if (0 == len)
1310  return NULL;
1311  routeList = GNUNET_strdup (routeListX);
1312  count = 0;
1313  for (i = 0; i < len; i++)
1314  if (routeList[i] == ';')
1315  count++;
1317  * (count + 1));
1318  i = 0;
1319  pos = 0;
1320  while (i < count)
1321  {
1322  for (colon = pos; ':' != routeList[colon]; colon++)
1323  if ((';' == routeList[colon]) || ('\0' == routeList[colon]))
1324  break;
1325  for (end = colon; ';' != routeList[end]; end++)
1326  if ('\0' == routeList[end])
1327  break;
1328  if ('\0' == routeList[end])
1329  break;
1330  routeList[end] = '\0';
1331  if (':' == routeList[colon])
1332  {
1333  routeList[colon] = '\0';
1334  if (GNUNET_OK != parse_port_policy (&routeList[colon + 1], &result[i].pp))
1335  break;
1336  }
1337  cnt = sscanf (&routeList[pos],
1338  "%u.%u.%u.%u/%u.%u.%u.%u%1s",
1339  &temps[0],
1340  &temps[1],
1341  &temps[2],
1342  &temps[3],
1343  &temps[4],
1344  &temps[5],
1345  &temps[6],
1346  &temps[7],
1347  dummy);
1348  if (8 == cnt)
1349  {
1350  for (j = 0; j < 8; j++)
1351  if (temps[j] > 0xFF)
1352  {
1354  _ ("Invalid format for IP: `%s'\n"),
1355  &routeList[pos]);
1356  GNUNET_free (result);
1357  GNUNET_free (routeList);
1358  return NULL;
1359  }
1360  result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16)
1361  + (temps[2] << 8) + temps[3]);
1362  result[i].netmask.s_addr = htonl ((temps[4] << 24) + (temps[5] << 16)
1363  + (temps[6] << 8) + temps[7]);
1364  pos = end + 1;
1365  i++;
1366  continue;
1367  }
1368  /* try second notation */
1369  cnt = sscanf (&routeList[pos],
1370  "%u.%u.%u.%u/%u%1s",
1371  &temps[0],
1372  &temps[1],
1373  &temps[2],
1374  &temps[3],
1375  &slash,
1376  dummy);
1377  if (5 == cnt)
1378  {
1379  for (j = 0; j < 4; j++)
1380  if (temps[j] > 0xFF)
1381  {
1383  _ ("Invalid format for IP: `%s'\n"),
1384  &routeList[pos]);
1385  GNUNET_free (result);
1386  GNUNET_free (routeList);
1387  return NULL;
1388  }
1389  result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16)
1390  + (temps[2] << 8) + temps[3]);
1391  if ((slash <= 32) && (slash >= 0))
1392  {
1393  result[i].netmask.s_addr = 0;
1394  while (slash > 0)
1395  {
1396  result[i].netmask.s_addr =
1397  (result[i].netmask.s_addr >> 1) + 0x80000000;
1398  slash--;
1399  }
1400  result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1401  pos = end + 1;
1402  i++;
1403  continue;
1404  }
1405  else
1406  {
1408  _ ("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
1409  slash);
1410  GNUNET_free (result);
1411  GNUNET_free (routeList);
1412  return NULL; /* error */
1413  }
1414  }
1415  /* try third notation */
1416  slash = 32;
1417  cnt = sscanf (&routeList[pos],
1418  "%u.%u.%u.%u%1s",
1419  &temps[0],
1420  &temps[1],
1421  &temps[2],
1422  &temps[3],
1423  dummy);
1424  if (4 == cnt)
1425  {
1426  for (j = 0; j < 4; j++)
1427  if (temps[j] > 0xFF)
1428  {
1430  _ ("Invalid format for IP: `%s'\n"),
1431  &routeList[pos]);
1432  GNUNET_free (result);
1433  GNUNET_free (routeList);
1434  return NULL;
1435  }
1436  result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16)
1437  + (temps[2] << 8) + temps[3]);
1438  result[i].netmask.s_addr = 0;
1439  while (slash > 0)
1440  {
1441  result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
1442  slash--;
1443  }
1444  result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1445  pos = end + 1;
1446  i++;
1447  continue;
1448  }
1450  _ ("Invalid format for IP: `%s'\n"),
1451  &routeList[pos]);
1452  GNUNET_free (result);
1453  GNUNET_free (routeList);
1454  return NULL; /* error */
1455  }
1456  if (pos < strlen (routeList))
1457  {
1459  _ ("Invalid format: `%s'\n"),
1460  &routeListX[pos]);
1461  GNUNET_free (result);
1462  GNUNET_free (routeList);
1463  return NULL; /* oops */
1464  }
1465  GNUNET_free (routeList);
1466  return result; /* ok */
1467 }
1468 
1469 
1471 GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX)
1472 {
1473  unsigned int count;
1474  unsigned int i;
1475  unsigned int len;
1476  unsigned int pos;
1477  int start;
1478  int slash;
1479  int ret;
1480  char *routeList;
1482  unsigned int bits;
1483  unsigned int off;
1484  int save;
1485  int colon;
1486  char dummy[2];
1487 
1488  if (NULL == routeListX)
1489  return NULL;
1490  len = strlen (routeListX);
1491  if (0 == len)
1492  return NULL;
1493  routeList = GNUNET_strdup (routeListX);
1494  count = 0;
1495  for (i = 0; i < len; i++)
1496  if (';' == routeList[i])
1497  count++;
1498  if (';' != routeList[len - 1])
1499  {
1501  _ ("Invalid network notation (does not end with ';': `%s')\n"),
1502  routeList);
1503  GNUNET_free (routeList);
1504  return NULL;
1505  }
1506 
1508  * (count + 1));
1509  i = 0;
1510  pos = 0;
1511  while (i < count)
1512  {
1513  start = pos;
1514  while (';' != routeList[pos])
1515  pos++;
1516  slash = pos;
1517  while ((slash >= start) && (routeList[slash] != '/'))
1518  slash--;
1519 
1520  if (slash < start)
1521  {
1522  memset (&result[i].netmask, 0xFF, sizeof(struct in6_addr));
1523  slash = pos;
1524  }
1525  else
1526  {
1527  routeList[pos] = '\0';
1528  for (colon = pos; ':' != routeList[colon]; colon--)
1529  if ('/' == routeList[colon])
1530  break;
1531  if (':' == routeList[colon])
1532  {
1533  routeList[colon] = '\0';
1534  if (GNUNET_OK !=
1535  parse_port_policy (&routeList[colon + 1], &result[i].pp))
1536  {
1537  GNUNET_free (result);
1538  GNUNET_free (routeList);
1539  return NULL;
1540  }
1541  }
1542  ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
1543  if (ret <= 0)
1544  {
1545  save = errno;
1546  if ((1 != sscanf (&routeList[slash + 1], "%u%1s", &bits, dummy)) ||
1547  (bits > 128))
1548  {
1549  if (0 == ret)
1551  _ ("Wrong format `%s' for netmask\n"),
1552  &routeList[slash + 1]);
1553  else
1554  {
1555  errno = save;
1556  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "inet_pton");
1557  }
1558  GNUNET_free (result);
1559  GNUNET_free (routeList);
1560  return NULL;
1561  }
1562  off = 0;
1563  while (bits > 8)
1564  {
1565  result[i].netmask.s6_addr[off++] = 0xFF;
1566  bits -= 8;
1567  }
1568  while (bits > 0)
1569  {
1570  result[i].netmask.s6_addr[off] =
1571  (result[i].netmask.s6_addr[off] >> 1) + 0x80;
1572  bits--;
1573  }
1574  }
1575  }
1576  routeList[slash] = '\0';
1577  ret = inet_pton (AF_INET6, &routeList[start], &result[i].network);
1578  if (ret <= 0)
1579  {
1580  if (0 == ret)
1582  _ ("Wrong format `%s' for network\n"),
1583  &routeList[slash + 1]);
1584  else
1585  LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton");
1586  GNUNET_free (result);
1587  GNUNET_free (routeList);
1588  return NULL;
1589  }
1590  pos++;
1591  i++;
1592  }
1593  GNUNET_free (routeList);
1594  return result;
1595 }
1596 
1597 
1600 #define FILLCHAR '='
1601 static char *cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1602  "abcdefghijklmnopqrstuvwxyz"
1603  "0123456789+/";
1604 
1605 
1606 size_t
1608  size_t len,
1609  char **output)
1610 {
1611  const char *data = in;
1612  size_t ret;
1613  char *opt;
1614 
1615  ret = 0;
1616  GNUNET_assert (len < SIZE_MAX / 4 * 3);
1617  opt = GNUNET_malloc (2 + (len * 4 / 3) + 8);
1618  for (size_t i = 0; i < len; ++i)
1619  {
1620  char c;
1621 
1622  c = (data[i] >> 2) & 0x3f;
1623  opt[ret++] = cvt[(int) c];
1624  c = (data[i] << 4) & 0x3f;
1625  if (++i < len)
1626  c |= (data[i] >> 4) & 0x0f;
1627  opt[ret++] = cvt[(int) c];
1628  if (i < len)
1629  {
1630  c = (data[i] << 2) & 0x3f;
1631  if (++i < len)
1632  c |= (data[i] >> 6) & 0x03;
1633  opt[ret++] = cvt[(int) c];
1634  }
1635  else
1636  {
1637  ++i;
1638  opt[ret++] = FILLCHAR;
1639  }
1640  if (i < len)
1641  {
1642  c = data[i] & 0x3f;
1643  opt[ret++] = cvt[(int) c];
1644  }
1645  else
1646  {
1647  opt[ret++] = FILLCHAR;
1648  }
1649  }
1650  *output = opt;
1651  return ret;
1652 }
1653 
1654 
1655 size_t
1657  size_t len,
1658  char **output)
1659 {
1660  char *enc;
1661  size_t pos;
1662 
1663  GNUNET_STRINGS_base64_encode (in, len, output);
1664  enc = *output;
1665  /* Replace with correct characters for base64url */
1666  pos = 0;
1667  while ('\0' != enc[pos])
1668  {
1669  if ('+' == enc[pos])
1670  enc[pos] = '-';
1671  if ('/' == enc[pos])
1672  enc[pos] = '_';
1673  if ('=' == enc[pos])
1674  {
1675  enc[pos] = '\0';
1676  break;
1677  }
1678  pos++;
1679  }
1680  return strlen (enc);
1681 }
1682 
1683 
1684 #define cvtfind(a) \
1685  ((((a) >= 'A') && ((a) <= 'Z')) \
1686  ? (a) - 'A' \
1687  : (((a) >= 'a') && ((a) <= 'z')) \
1688  ? (a) - 'a' + 26 \
1689  : (((a) >= '0') && ((a) <= '9')) \
1690  ? (a) - '0' + 52 \
1691  : ((a) == '+') ? 62 : ((a) == '/') ? 63 : -1)
1692 
1693 
1694 size_t
1696  size_t len,
1697  void **out)
1698 {
1699  char *output;
1700  size_t ret = 0;
1701 
1702 #define CHECK_CRLF \
1703  while (data[i] == '\r' || data[i] == '\n') \
1704  { \
1705  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, \
1706  "ignoring CR/LF\n"); \
1707  i++; \
1708  if (i >= len) \
1709  goto END; \
1710  }
1711 
1712  GNUNET_assert (len / 3 < SIZE_MAX);
1713  output = GNUNET_malloc ((len * 3 / 4) + 8);
1715  "base64_decode decoding len=%d\n",
1716  (int) len);
1717  for (size_t i = 0; i < len; ++i)
1718  {
1719  char c;
1720  char c1;
1721 
1722  CHECK_CRLF;
1723  if (FILLCHAR == data[i])
1724  break;
1725  c = (char) cvtfind (data[i]);
1726  ++i;
1727  CHECK_CRLF;
1728  c1 = (char) cvtfind (data[i]);
1729  c = (c << 2) | ((c1 >> 4) & 0x3);
1730  output[ret++] = c;
1731  if (++i < len)
1732  {
1733  CHECK_CRLF;
1734  c = data[i];
1735  if (FILLCHAR == c)
1736  break;
1737  c = (char) cvtfind (c);
1738  c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
1739  output[ret++] = c1;
1740  }
1741  if (++i < len)
1742  {
1743  CHECK_CRLF;
1744  c1 = data[i];
1745  if (FILLCHAR == c1)
1746  break;
1747 
1748  c1 = (char) cvtfind (c1);
1749  c = ((c << 6) & 0xc0) | c1;
1750  output[ret++] = c;
1751  }
1752  }
1753  END:
1754  *out = output;
1755  return ret;
1756 }
1757 
1758 
1759 size_t
1761  size_t len,
1762  void **out)
1763 {
1764  char *s;
1765  int padding;
1766  size_t ret;
1767 
1768  /* make enough space for padding */
1769  GNUNET_assert (len < SIZE_MAX - 3);
1770  s = GNUNET_malloc (len + 3);
1771  memcpy (s, data, len);
1772 
1773  for (int i = 0; i < strlen (s); i++)
1774  {
1775  if (s[i] == '-')
1776  s[i] = '+';
1777  if (s[i] == '_')
1778  s[i] = '/';
1779  }
1780  padding = len % 4;
1781  switch (padding) // Pad with trailing '='s
1782  {
1783  case 0:
1784  break; // No pad chars in this case
1785  case 2:
1786  memcpy (&s[len],
1787  "==",
1788  2);
1789  len += 2;
1790  break; // Two pad chars
1791  case 3:
1792  s[len] = '=';
1793  len++;
1794  break; // One pad char
1795  default:
1796  GNUNET_assert (0);
1797  break;
1798  }
1799  ret = GNUNET_STRINGS_base64_decode (s, len, out);
1800  GNUNET_free (s);
1801  return ret;
1802 }
1803 
1804 
1805 size_t
1807  size_t len,
1808  char **out)
1809 {
1810  const char *rpos = data;
1811  *out = GNUNET_malloc (len + 1); /* output should always fit into input */
1812  char *wpos = *out;
1813  size_t resl = 0;
1814 
1815  while ( ('\0' != *rpos) &&
1816  (data + len != rpos) )
1817  {
1818  unsigned int num;
1819  switch (*rpos)
1820  {
1821  case '%':
1822  if (rpos + 3 > data + len)
1823  {
1824  GNUNET_break_op (0);
1825  GNUNET_free (*out);
1826  return 0;
1827  }
1828  if (1 != sscanf (rpos + 1, "%2x", &num))
1829  break;
1830  *wpos = (char) ((unsigned char) num);
1831  wpos++;
1832  resl++;
1833  rpos += 3;
1834  break;
1835  /* TODO: add bad sequence handling */
1836  /* intentional fall through! */
1837  default:
1838  *wpos = *rpos;
1839  wpos++;
1840  resl++;
1841  rpos++;
1842  }
1843  }
1844  *wpos = '\0'; /* add 0-terminator */
1845  return resl;
1846 }
1847 
1848 
1849 size_t
1851  size_t len,
1852  char **out)
1853 {
1854  struct GNUNET_Buffer buf = { 0 };
1855  const uint8_t *i8 = (uint8_t *) data;
1856 
1857  while (0 != *i8)
1858  {
1859  if (0 == (0x80 & *i8))
1860  {
1861  /* traditional ASCII */
1862  if (isalnum (*i8) || (*i8 == '-') || (*i8 == '_') || (*i8 == '.') ||
1863  (*i8 == '~') )
1864  GNUNET_buffer_write (&buf, (const char*) i8, 1);
1865  else if (*i8 == ' ')
1866  GNUNET_buffer_write (&buf, "+", 1);
1867  else
1869  "%%%X%X",
1870  *i8 >> 4,
1871  *i8 & 15);
1872  i8++;
1873  continue;
1874  }
1875  if (0x80 + 0x40 == ((0x80 + 0x40 + 0x20) & *i8))
1876  {
1877  /* 2-byte value, percent-encode */
1879  "%%%X%X",
1880  *i8 >> 4,
1881  *i8 & 15);
1882  i8++;
1884  "%%%X%X",
1885  *i8 >> 4,
1886  *i8 & 15);
1887  i8++;
1888  continue;
1889  }
1890  if (0x80 + 0x40 + 0x20 == ((0x80 + 0x40 + 0x20 + 0x10) & *i8))
1891  {
1892  /* 3-byte value, percent-encode */
1893  for (unsigned int i = 0; i<3; i++)
1894  {
1896  "%%%X%X",
1897  *i8 >> 4,
1898  *i8 & 15);
1899  i8++;
1900  }
1901  continue;
1902  }
1903  if (0x80 + 0x40 + 0x20 + 0x10 == ((0x80 + 0x40 + 0x20 + 0x10 + 0x08) & *i8))
1904  {
1905  /* 4-byte value, percent-encode */
1906  for (unsigned int i = 0; i<4; i++)
1907  {
1909  "%%%X%X",
1910  *i8 >> 4,
1911  *i8 & 15);
1912  i8++;
1913  }
1914  continue;
1915  }
1916  if (0x80 + 0x40 + 0x20 + 0x10 + 0x08 == ((0x80 + 0x40 + 0x20 + 0x10 + 0x08
1917  + 0x04) & *i8))
1918  {
1919  /* 5-byte value, percent-encode (outside of UTF-8 modern standard, but so what) */
1920  for (unsigned int i = 0; i<5; i++)
1921  {
1923  "%%%X%X",
1924  *i8 >> 4,
1925  *i8 & 15);
1926  i8++;
1927  }
1928  continue;
1929  }
1930  if (0x80 + 0x40 + 0x20 + 0x10 + 0x08 + 0x04 == ((0x80 + 0x40 + 0x20 + 0x10
1931  + 0x08 + 0x04 + 0x02)
1932  & *i8))
1933  {
1934  /* 6-byte value, percent-encode (outside of UTF-8 modern standard, but so what) */
1935  for (unsigned int i = 0; i<6; i++)
1936  {
1938  "%%%X%X",
1939  *i8 >> 4,
1940  *i8 & 15);
1941  i8++;
1942  }
1943  continue;
1944  }
1945  /* really, really invalid UTF-8: fail */
1946  GNUNET_break (0);
1948  return 0;
1949  }
1950  *out = GNUNET_buffer_reap_str (&buf);
1951  return strlen (*out);
1952 }
1953 
1954 
1955 /* end of strings.c */
static size_t strnlen(const char *s, size_t n)
#define S_ISLNK(m)
Definition: disk.c:60
char * getenv()
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_SCHEDULER_Task * tt
Task scheduled to handle timeout.
Definition: gnunet-abd.c:76
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static struct Experiment * e
static int res
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
static struct GNUNET_SCHEDULER_Task * st
The shutdown task.
@ END
We're done processing.
static char * filename
static OpusDecoder * dec
OPUS decoder.
static OpusEncoder * enc
OPUS encoder.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
uint32_t data
The data value.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static int result
Global testing status.
static void do_round(void *cls)
Send out PUSHes and PULLs, possibly update #view, samplers.
static void save()
Write persistent statistics to disk.
static char buf[2048]
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
static struct GNUNET_SCHEDULER_Task * t
Main task.
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition: buffer.c:123
#define GNUNET_log(kind,...)
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.
void GNUNET_buffer_write(struct GNUNET_Buffer *buf, const char *data, size_t len)
Write bytes to the buffer.
Definition: buffer.c:86
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
void GNUNET_buffer_clear(struct GNUNET_Buffer *buf)
Free the backing memory of the given buffer.
Definition: buffer.c:164
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
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.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
enum GNUNET_GenericReturnValue GNUNET_STRINGS_string_to_data_alloc(const char *enc, size_t enclen, void **out, size_t *out_size)
Convert CrockfordBase32 encoding back to data.
Definition: strings.c:854
size_t GNUNET_STRINGS_base64url_decode(const char *data, size_t len, void **out)
Decode from Base64url.
Definition: strings.c:1760
struct GNUNET_STRINGS_IPv6NetworkPolicy * GNUNET_STRINGS_parse_ipv6_policy(const char *routeListX)
Parse an IPv6 network policy.
Definition: strings.c:1471
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:1149
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition: strings.c:494
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 CrockfordBase32.
Definition: strings.c:708
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:343
enum GNUNET_GenericReturnValue 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:1134
GNUNET_STRINGS_FilenameCheck
Flags for what we should check a file for.
enum GNUNET_GenericReturnValue GNUNET_STRINGS_to_address_ipv4(const char *zt_addr, uint16_t addrlen, struct sockaddr_in *r_buf)
Tries to convert zt_addr string to an IPv4 address.
Definition: strings.c:1096
enum GNUNET_GenericReturnValue GNUNET_STRINGS_utf8_toupper(const char *input, char *output)
Convert the utf-8 input string to upper case.
Definition: strings.c:471
char * GNUNET_STRINGS_utf8_normalize(const char *input)
Normalize the utf-8 input string to NFC.
Definition: strings.c:429
size_t GNUNET_STRINGS_urldecode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:1806
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:763
size_t GNUNET_STRINGS_urlencode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:1850
enum GNUNET_GenericReturnValue GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition: strings.c:788
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:72
char * GNUNET_STRINGS_byte_size_fancy(unsigned long long size)
Convert a given filesize into a fancy human-readable format.
Definition: strings.c:106
enum GNUNET_GenericReturnValue 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's an URI.
Definition: strings.c:958
size_t GNUNET_STRINGS_base64url_encode(const void *in, size_t len, char **output)
Encode into Base64url.
Definition: strings.c:1656
enum GNUNET_GenericReturnValue 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:896
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:44
enum GNUNET_GenericReturnValue 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:260
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **out)
Decode from Base64.
Definition: strings.c:1695
enum GNUNET_GenericReturnValue GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1222
enum GNUNET_GenericReturnValue 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:1033
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1607
enum GNUNET_GenericReturnValue GNUNET_STRINGS_utf8_tolower(const char *input, char *output)
Convert the utf-8 input string to lower case.
Definition: strings.c:449
enum GNUNET_GenericReturnValue GNUNET_STRINGS_check_filename(const char *filename, enum GNUNET_STRINGS_FilenameCheck checks)
Perform checks on filename.
Definition: strings.c:1000
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:639
struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
Parse an IPv4 network policy.
Definition: strings.c:1290
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:138
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:405
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:417
enum GNUNET_GenericReturnValue 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:236
@ GNUNET_STRINGS_CHECK_IS_ABSOLUTE
Check that the path is an absolute path.
@ GNUNET_STRINGS_CHECK_IS_DIRECTORY
Check that it is a directory.
@ GNUNET_STRINGS_CHECK_EXISTS
Check that it exists.
@ GNUNET_STRINGS_CHECK_IS_LINK
Check that it is a link.
enum GNUNET_GenericReturnValue GNUNET_STRINGS_fancy_time_to_timestamp(const char *fancy_time, struct GNUNET_TIME_Timestamp *atime)
Convert a given fancy human-readable time to our internal representation.
Definition: strings.c:334
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
bool GNUNET_TIME_absolute_is_never(struct GNUNET_TIME_Absolute abs)
Test if abs is never.
Definition: time.c:648
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:616
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:569
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
enum GNUNET_GenericReturnValue 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:302
static struct PeerEntry ** table
Table with our interned peer IDs.
Definition: peer.c:56
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define DIR_SEPARATOR
Definition: platform.h:165
#define DIR_SEPARATOR_STR
Definition: platform.h:166
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
#define SIZE_MAX
Definition: platform.h:208
#define GNUNET_THREAD_LOCAL
Definition: platform.h:247
const char * name
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
static enum GNUNET_GenericReturnValue parse_port_policy(const char *port_policy, struct GNUNET_STRINGS_PortPolicy *pp)
Parse the given port policy.
Definition: strings.c:1245
static enum GNUNET_GenericReturnValue 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:181
#define FILLCHAR
******************** Base64 encoding
Definition: strings.c:1600
#define CHECK_CRLF
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:1200
static unsigned int getValue__(unsigned char a)
Get the decoded value corresponding to a character according to Crockford Base32 encoding.
Definition: strings.c:658
#define cvtfind(a)
Definition: strings.c:1684
static char * cvt
Definition: strings.c:1601
#define LOG(kind,...)
Definition: strings.c:37
#define LOG_STRERROR(kind, syscall)
Definition: strings.c:39
Unit conversion table entry for 'convert_with_table'.
Definition: strings.c:156
const char * name
Name of the unit (or NULL for end of table).
Definition: strings.c:160
unsigned long long value
Factor to apply for this unit.
Definition: strings.c:165
Dynamically growing buffer.
IPV4 network in CIDR notation.
struct GNUNET_STRINGS_PortPolicy pp
Policy for port access.
struct in_addr netmask
IPv4 netmask.
network in CIDR notation for IPV6.
struct GNUNET_STRINGS_PortPolicy pp
Policy for port access.
struct in6_addr network
IPv6 address.
struct in6_addr netmask
IPv6 netmask.
uint16_t start_port
Starting port range (0 if none given).
int negate_portrange
GNUNET_YES if the port range should be negated ("!" in policy).
uint16_t end_port
End of port range (0 if none given).
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Rounded time for timestamps used by GNUnet, in seconds.
struct GNUNET_TIME_Absolute abs_time
The actual value.