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