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