GNUnet  0.10.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_strings_lib.h"
33 #include <unicase.h>
34 #include <unistr.h>
35 #include <uniconv.h>
36 
37 #define LOG(kind,...) GNUNET_log_from (kind, "util-strings", __VA_ARGS__)
38 
39 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-strings", syscall)
40 
41 
63 size_t
64 GNUNET_STRINGS_buffer_fill (char *buffer, size_t size, unsigned int count, ...)
65 {
66  size_t needed;
67  size_t slen;
68  const char *s;
69  va_list ap;
70 
71  needed = 0;
72  va_start (ap, count);
73  while (count > 0)
74  {
75  s = va_arg (ap, const char *);
76 
77  slen = strlen (s) + 1;
78  if (buffer != NULL)
79  {
80  GNUNET_assert (needed + slen <= size);
81  GNUNET_memcpy (&buffer[needed], s, slen);
82  }
83  needed += slen;
84  count--;
85  }
86  va_end (ap);
87  return needed;
88 }
89 
90 
98 char *
100  unsigned int num_pids)
101 {
102  char *buf;
103  size_t off;
104  size_t plen = num_pids * 5 + 1;
105 
106  off = 0;
107  buf = GNUNET_malloc (plen);
108  for (unsigned int i = 0;
109  i < num_pids;
110  i++)
111  {
112  off += GNUNET_snprintf (&buf[off],
113  plen - off,
114  "%s%s",
115  GNUNET_i2s (&pids[i]),
116  (i == num_pids -1) ? "" : "-");
117  }
118  return buf;
119 }
120 
121 
135 unsigned int
136 GNUNET_STRINGS_buffer_tokenize (const char *buffer, size_t size,
137  unsigned int count, ...)
138 {
139  unsigned int start;
140  unsigned int needed;
141  const char **r;
142  va_list ap;
143 
144  needed = 0;
145  va_start (ap, count);
146  while (count > 0)
147  {
148  r = va_arg (ap, const char **);
149 
150  start = needed;
151  while ((needed < size) && (buffer[needed] != '\0'))
152  needed++;
153  if (needed == size)
154  {
155  va_end (ap);
156  return 0; /* error */
157  }
158  *r = &buffer[start];
159  needed++; /* skip 0-termination */
160  count--;
161  }
162  va_end (ap);
163  return needed;
164 }
165 
166 
173 char *
175 {
176  const char *unit = _( /* size unit */ "b");
177  char *ret;
178 
179  if (size > 5 * 1024)
180  {
181  size = size / 1024;
182  unit = "KiB";
183  if (size > 5 * 1024)
184  {
185  size = size / 1024;
186  unit = "MiB";
187  if (size > 5 * 1024)
188  {
189  size = size / 1024;
190  unit = "GiB";
191  if (size > 5 * 1024)
192  {
193  size = size / 1024;
194  unit = "TiB";
195  }
196  }
197  }
198  }
199  ret = GNUNET_malloc (32);
200  GNUNET_snprintf (ret, 32, "%llu %s", size, unit);
201  return ret;
202 }
203 
204 
217 size_t
218 GNUNET_strlcpy(char *dst, const char *src, size_t n)
219 {
220  size_t slen;
221 
222  GNUNET_assert (0 != n);
223  slen = strnlen (src, n - 1);
224  memcpy (dst, src, slen);
225  dst[slen] = '\0';
226  return slen;
227 }
228 
229 
234 {
238  const char *name;
239 
243  unsigned long long value;
244 };
245 
246 
258 static int
259 convert_with_table (const char *input,
260  const struct ConversionTable *table,
261  unsigned long long *output)
262 {
263  unsigned long long ret;
264  char *in;
265  const char *tok;
266  unsigned long long last;
267  unsigned int i;
268 
269  ret = 0;
270  last = 0;
271  in = GNUNET_strdup (input);
272  for (tok = strtok (in, " "); tok != NULL; tok = strtok (NULL, " "))
273  {
274  do
275  {
276  i = 0;
277  while ((table[i].name != NULL) && (0 != strcasecmp (table[i].name, tok)))
278  i++;
279  if (table[i].name != NULL)
280  {
281  last *= table[i].value;
282  break; /* next tok */
283  }
284  else
285  {
286  char *endptr;
287  ret += last;
288  errno = 0;
289  last = strtoull (tok, &endptr, 10);
290  if ((0 != errno) || (endptr == tok))
291  {
292  GNUNET_free (in);
293  return GNUNET_SYSERR; /* expected number */
294  }
295  if ('\0' == endptr[0])
296  break; /* next tok */
297  else
298  tok = endptr; /* and re-check (handles times like "10s") */
299  }
300  } while (GNUNET_YES);
301  }
302  ret += last;
303  *output = ret;
304  GNUNET_free (in);
305  return GNUNET_OK;
306 }
307 
308 
316 int
317 GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
318  unsigned long long *size)
319 {
320  static const struct ConversionTable table[] =
321  {
322  { "B", 1},
323  { "KiB", 1024},
324  { "kB", 1000},
325  { "MiB", 1024 * 1024},
326  { "MB", 1000 * 1000},
327  { "GiB", 1024 * 1024 * 1024},
328  { "GB", 1000 * 1000 * 1000},
329  { "TiB", 1024LL * 1024LL * 1024LL * 1024LL},
330  { "TB", 1000LL * 1000LL * 1000LL * 1024LL},
331  { "PiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL},
332  { "PB", 1000LL * 1000LL * 1000LL * 1024LL * 1000LL},
333  { "EiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL},
334  { "EB", 1000LL * 1000LL * 1000LL * 1024LL * 1000LL * 1000LL},
335  { NULL, 0}
336  };
337 
338  return convert_with_table (fancy_size,
339  table,
340  size);
341 }
342 
343 
352 int
354  struct GNUNET_TIME_Relative *rtime)
355 {
356  static const struct ConversionTable table[] =
357  {
358  { "us", 1},
359  { "ms", 1000 },
360  { "s", 1000 * 1000LL },
361  { "second", 1000 * 1000LL },
362  { "seconds", 1000 * 1000LL },
363  { "\"", 1000 * 1000LL },
364  { "m", 60 * 1000 * 1000LL},
365  { "min", 60 * 1000 * 1000LL},
366  { "minute", 60 * 1000 * 1000LL},
367  { "minutes", 60 * 1000 * 1000LL},
368  { "'", 60 * 1000 * 1000LL},
369  { "h", 60 * 60 * 1000 * 1000LL},
370  { "hour", 60 * 60 * 1000 * 1000LL},
371  { "hours", 60 * 60 * 1000 * 1000LL},
372  { "d", 24 * 60 * 60 * 1000LL * 1000LL},
373  { "day", 24 * 60 * 60 * 1000LL * 1000LL},
374  { "days", 24 * 60 * 60 * 1000LL * 1000LL},
375  { "week", 7 * 24 * 60 * 60 * 1000LL * 1000LL},
376  { "weeks", 7 * 24 * 60 * 60 * 1000LL * 1000LL},
377  { "year", 31536000000000LL /* year */ },
378  { "years", 31536000000000LL /* year */ },
379  { "a", 31536000000000LL /* year */ },
380  { NULL, 0}
381  };
382  int ret;
383  unsigned long long val;
384 
385  if (0 == strcasecmp ("forever", fancy_time))
386  {
388  return GNUNET_OK;
389  }
390  ret = convert_with_table (fancy_time,
391  table,
392  &val);
393  rtime->rel_value_us = (uint64_t) val;
394  return ret;
395 }
396 
397 
407 int
409  struct GNUNET_TIME_Absolute *atime)
410 {
411  struct tm tv;
412  time_t t;
413  const char *eos;
414 
415  if (0 == strcasecmp ("end of time",
416  fancy_time))
417  {
419  return GNUNET_OK;
420  }
421  eos = &fancy_time[strlen (fancy_time)];
422  memset (&tv, 0, sizeof (tv));
423  if ( (eos != strptime (fancy_time, "%a %b %d %H:%M:%S %Y", &tv)) &&
424  (eos != strptime (fancy_time, "%c", &tv)) &&
425  (eos != strptime (fancy_time, "%Ec", &tv)) &&
426  (eos != strptime (fancy_time, "%Y-%m-%d %H:%M:%S", &tv)) &&
427  (eos != strptime (fancy_time, "%Y-%m-%d %H:%M", &tv)) &&
428  (eos != strptime (fancy_time, "%x", &tv)) &&
429  (eos != strptime (fancy_time, "%Ex", &tv)) &&
430  (eos != strptime (fancy_time, "%Y-%m-%d", &tv)) &&
431  (eos != strptime (fancy_time, "%Y-%m", &tv)) &&
432  (eos != strptime (fancy_time, "%Y", &tv)) )
433  return GNUNET_SYSERR;
434  t = mktime (&tv);
435  atime->abs_value_us = (uint64_t) ((uint64_t) t * 1000LL * 1000LL);
436  return GNUNET_OK;
437 }
438 
439 
453 char *
454 GNUNET_STRINGS_conv (const char *input,
455  size_t len,
456  const char *input_charset,
457  const char *output_charset)
458 {
459  char *ret;
460  uint8_t *u8_string;
461  char *encoded_string;
462  size_t u8_string_length;
463  size_t encoded_string_length;
464 
465  u8_string = u8_conv_from_encoding (input_charset,
466  iconveh_error,
467  input, len,
468  NULL, NULL,
469  &u8_string_length);
470  if (NULL == u8_string)
471  {
472  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_from_encoding");
473  goto fail;
474  }
475  if (0 == strcmp (output_charset, "UTF-8"))
476  {
477  ret = GNUNET_malloc (u8_string_length + 1);
478  GNUNET_memcpy (ret, u8_string, u8_string_length);
479  ret[u8_string_length] = '\0';
480  free (u8_string);
481  return ret;
482  }
483  encoded_string = u8_conv_to_encoding (output_charset, iconveh_error,
484  u8_string, u8_string_length,
485  NULL, NULL,
486  &encoded_string_length);
487  free (u8_string);
488  if (NULL == encoded_string)
489  {
490  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_to_encoding");
491  goto fail;
492  }
493  ret = GNUNET_malloc (encoded_string_length + 1);
494  GNUNET_memcpy (ret, encoded_string, encoded_string_length);
495  ret[encoded_string_length] = '\0';
496  free (encoded_string);
497  return ret;
498  fail:
500  _("Character sets requested were `%s'->`%s'\n"),
501  "UTF-8", output_charset);
502  ret = GNUNET_malloc (len + 1);
503  GNUNET_memcpy (ret, input, len);
504  ret[len] = '\0';
505  return ret;
506 }
507 
508 
521 char *
522 GNUNET_STRINGS_to_utf8 (const char *input,
523  size_t len,
524  const char *charset)
525 {
526  return GNUNET_STRINGS_conv (input, len, charset, "UTF-8");
527 }
528 
529 
541 char *
542 GNUNET_STRINGS_from_utf8 (const char *input,
543  size_t len,
544  const char *charset)
545 {
546  return GNUNET_STRINGS_conv (input, len, "UTF-8", charset);
547 }
548 
549 
557 void
558 GNUNET_STRINGS_utf8_tolower (const char *input,
559  char *output)
560 {
561  uint8_t *tmp_in;
562  size_t len;
563 
564  tmp_in = u8_tolower ((uint8_t*)input, strlen ((char *) input),
565  NULL, UNINORM_NFD, NULL, &len);
566  GNUNET_memcpy(output, tmp_in, len);
567  output[len] = '\0';
568  free(tmp_in);
569 }
570 
571 
579 void
580 GNUNET_STRINGS_utf8_toupper(const char *input,
581  char *output)
582 {
583  uint8_t *tmp_in;
584  size_t len;
585 
586  tmp_in = u8_toupper ((uint8_t*)input, strlen ((char *) input),
587  NULL, UNINORM_NFD, NULL, &len);
588  GNUNET_memcpy (output, tmp_in, len);
589  output[len] = '\0';
590  free (tmp_in);
591 }
592 
593 
601 char *
603 {
604  char *buffer;
605 #ifndef MINGW
606  size_t len;
607  char *fm;
608  const char *fil_ptr;
609 #else
610  char *fn;
611  long lRet;
612 #endif
613 
614  if (fil == NULL)
615  return NULL;
616 
617 #ifndef MINGW
618  if (fil[0] == DIR_SEPARATOR)
619  /* absolute path, just copy */
620  return GNUNET_strdup (fil);
621  if (fil[0] == '~')
622  {
623  fm = getenv ("HOME");
624  if (fm == NULL)
625  {
627  _("Failed to expand `$HOME': environment variable `HOME' not set"));
628  return NULL;
629  }
630  fm = GNUNET_strdup (fm);
631  /* do not copy '~' */
632  fil_ptr = fil + 1;
633 
634  /* skip over dir seperator to be consistent */
635  if (fil_ptr[0] == DIR_SEPARATOR)
636  fil_ptr++;
637  }
638  else
639  {
640  /* relative path */
641  fil_ptr = fil;
642  len = 512;
643  fm = NULL;
644  while (1)
645  {
646  buffer = GNUNET_malloc (len);
647  if (getcwd (buffer, len) != NULL)
648  {
649  fm = buffer;
650  break;
651  }
652  if ((errno == ERANGE) && (len < 1024 * 1024 * 4))
653  {
654  len *= 2;
655  GNUNET_free (buffer);
656  continue;
657  }
658  GNUNET_free (buffer);
659  break;
660  }
661  if (fm == NULL)
662  {
664  "getcwd");
665  buffer = getenv ("PWD"); /* alternative */
666  if (buffer != NULL)
667  fm = GNUNET_strdup (buffer);
668  }
669  if (fm == NULL)
670  fm = GNUNET_strdup ("./"); /* give up */
671  }
672  GNUNET_asprintf (&buffer,
673  "%s%s%s",
674  fm,
675  (fm[strlen (fm) - 1] ==
676  DIR_SEPARATOR) ? "" : DIR_SEPARATOR_STR, fil_ptr);
677  GNUNET_free (fm);
678  return buffer;
679 #else
680  fn = GNUNET_malloc (MAX_PATH + 1);
681 
682  if ((lRet = plibc_conv_to_win_path (fil, fn)) != ERROR_SUCCESS)
683  {
684  SetErrnoFromWinError (lRet);
686  "plibc_conv_to_win_path");
687  return NULL;
688  }
689  /* is the path relative? */
690  if ( (0 != strncmp (fn + 1, ":\\", 2)) &&
691  (0 != strncmp (fn, "\\\\", 2)) )
692  {
693  char szCurDir[MAX_PATH + 1];
694 
695  lRet = GetCurrentDirectory (MAX_PATH + 1,
696  szCurDir);
697  if (lRet + strlen (fn) + 1 > (MAX_PATH + 1))
698  {
699  SetErrnoFromWinError (ERROR_BUFFER_OVERFLOW);
701  "GetCurrentDirectory");
702  return NULL;
703  }
704  GNUNET_asprintf (&buffer,
705  "%s\\%s",
706  szCurDir,
707  fn);
708  GNUNET_free (fn);
709  fn = buffer;
710  }
711 
712  return fn;
713 #endif
714 }
715 
716 
726 const char *
728  int do_round)
729 {
730  static char buf[128];
731  const char *unit = _( /* time unit */ "┬Ás");
732  uint64_t dval = delta.rel_value_us;
733 
734  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == delta.rel_value_us)
735  return _("forever");
736  if (0 == delta.rel_value_us)
737  return _("0 ms");
738  if ( ( (GNUNET_YES == do_round) &&
739  (dval > 5 * 1000) ) ||
740  (0 == (dval % 1000) ))
741  {
742  dval = dval / 1000;
743  unit = _( /* time unit */ "ms");
744  if ( ( (GNUNET_YES == do_round) &&
745  (dval > 5 * 1000) ) ||
746  (0 == (dval % 1000) ))
747  {
748  dval = dval / 1000;
749  unit = _( /* time unit */ "s");
750  if ( ( (GNUNET_YES == do_round) &&
751  (dval > 5 * 60) ) ||
752  (0 == (dval % 60) ) )
753  {
754  dval = dval / 60;
755  unit = _( /* time unit */ "m");
756  if ( ( (GNUNET_YES == do_round) &&
757  (dval > 5 * 60) ) ||
758  (0 == (dval % 60) ))
759  {
760  dval = dval / 60;
761  unit = _( /* time unit */ "h");
762  if ( ( (GNUNET_YES == do_round) &&
763  (dval > 5 * 24) ) ||
764  (0 == (dval % 24)) )
765  {
766  dval = dval / 24;
767  if (1 == dval)
768  unit = _( /* time unit */ "day");
769  else
770  unit = _( /* time unit */ "days");
771  }
772  }
773  }
774  }
775  }
776  GNUNET_snprintf (buf, sizeof (buf),
777  "%llu %s", dval, unit);
778  return buf;
779 }
780 
781 
791 const char *
793 {
794  static char buf[255];
795  time_t tt;
796  struct tm *tp;
797 
798  if (t.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
799  return _("end of time");
800  tt = t.abs_value_us / 1000LL / 1000LL;
801  tp = localtime (&tt);
802  /* This is hacky, but i don't know a way to detect libc character encoding.
803  * Just expect utf8 from glibc these days.
804  * As for msvcrt, use the wide variant, which always returns utf16
805  * (otherwise we'd have to detect current codepage or use W32API character
806  * set conversion routines to convert to UTF8).
807  */
808 #ifndef WINDOWS
809  strftime (buf, sizeof (buf), "%a %b %d %H:%M:%S %Y", tp);
810 #else
811  {
812  static wchar_t wbuf[255];
813  uint8_t *conved;
814  size_t ssize;
815 
816  wcsftime (wbuf, sizeof (wbuf) / sizeof (wchar_t),
817  L"%a %b %d %H:%M:%S %Y", tp);
818 
819  ssize = sizeof (buf);
820  conved = u16_to_u8 (wbuf, sizeof (wbuf) / sizeof (wchar_t),
821  (uint8_t *) buf, &ssize);
822  if (conved != (uint8_t *) buf)
823  {
824  GNUNET_strlcpy (buf, (char *) conved, sizeof (buf));
825  free (conved);
826  }
827  }
828 #endif
829  return buf;
830 }
831 
832 
844 const char *
846 {
847  const char *short_fn = filename;
848  const char *ss;
849 
850  while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR))
851  && (ss[1] != '\0'))
852  short_fn = 1 + ss;
853  return short_fn;
854 }
855 
856 
864 static unsigned int
865 getValue__ (unsigned char a)
866 {
867  unsigned int dec;
868 
869  switch (a)
870  {
871  case 'O':
872  case 'o':
873  a = '0';
874  break;
875  case 'i':
876  case 'I':
877  case 'l':
878  case 'L':
879  a = '1';
880  break;
881  /* also consider U to be V */
882  case 'u':
883  case 'U':
884  a = 'V';
885  break;
886  default:
887  break;
888  }
889  if ((a >= '0') && (a <= '9'))
890  return a - '0';
891  if ((a >= 'a') && (a <= 'z'))
892  a = toupper (a);
893  /* return (a - 'a' + 10); */
894  dec = 0;
895  if ((a >= 'A') && (a <= 'Z'))
896  {
897  if ('I' < a)
898  dec++;
899  if ('L' < a)
900  dec++;
901  if ('O' < a)
902  dec++;
903  if ('U' < a)
904  dec++;
905  return (a - 'A' + 10 - dec);
906  }
907  return -1;
908 }
909 
910 
923 char *
925  size_t size,
926  char *out,
927  size_t out_size)
928 {
932  static char *encTable__ = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
933  unsigned int wpos;
934  unsigned int rpos;
935  unsigned int bits;
936  unsigned int vbit;
937  const unsigned char *udata;
938 
939  udata = data;
940  if (out_size < (size * 8 + 4) / 5)
941  {
942  GNUNET_break (0);
943  return NULL;
944  }
945  vbit = 0;
946  wpos = 0;
947  rpos = 0;
948  bits = 0;
949  while ((rpos < size) || (vbit > 0))
950  {
951  if ((rpos < size) && (vbit < 5))
952  {
953  bits = (bits << 8) | udata[rpos++]; /* eat 8 more bits */
954  vbit += 8;
955  }
956  if (vbit < 5)
957  {
958  bits <<= (5 - vbit); /* zero-padding */
959  GNUNET_assert (vbit == ((size * 8) % 5));
960  vbit = 5;
961  }
962  if (wpos >= out_size)
963  {
964  GNUNET_break (0);
965  return NULL;
966  }
967  out[wpos++] = encTable__[(bits >> (vbit - 5)) & 31];
968  vbit -= 5;
969  }
970  GNUNET_assert (0 == vbit);
971  if (wpos < out_size)
972  out[wpos] = '\0';
973  return &out[wpos];
974 }
975 
976 
987 char *
989  size_t size)
990 {
991  char *str_buf;
992  size_t len = size * 8;
993  char *end;
994 
995  if (len % 5 > 0)
996  len += 5 - len % 5;
997  len /= 5;
998  str_buf = GNUNET_malloc (len + 1);
999  end = GNUNET_STRINGS_data_to_string (buf, size, str_buf, len);
1000  if (NULL == end)
1001  {
1002  GNUNET_free (str_buf);
1003  return NULL;
1004  }
1005  *end = '\0';
1006  return str_buf;
1007 }
1008 
1009 
1020 int
1021 GNUNET_STRINGS_string_to_data (const char *enc, size_t enclen,
1022  void *out, size_t out_size)
1023 {
1024  unsigned int rpos;
1025  unsigned int wpos;
1026  unsigned int bits;
1027  unsigned int vbit;
1028  int ret;
1029  int shift;
1030  unsigned char *uout;
1031  unsigned int encoded_len = out_size * 8;
1032 
1033  if (0 == enclen)
1034  {
1035  if (0 == out_size)
1036  return GNUNET_OK;
1037  return GNUNET_SYSERR;
1038  }
1039  uout = out;
1040  wpos = out_size;
1041  rpos = enclen;
1042  if ((encoded_len % 5) > 0)
1043  {
1044  vbit = encoded_len % 5; /* padding! */
1045  shift = 5 - vbit;
1046  bits = (ret = getValue__ (enc[--rpos])) >> shift;
1047  }
1048  else
1049  {
1050  vbit = 5;
1051  shift = 0;
1052  bits = (ret = getValue__ (enc[--rpos]));
1053  }
1054  if ((encoded_len + shift) / 5 != enclen)
1055  return GNUNET_SYSERR;
1056  if (-1 == ret)
1057  return GNUNET_SYSERR;
1058  while (wpos > 0)
1059  {
1060  if (0 == rpos)
1061  {
1062  GNUNET_break (0);
1063  return GNUNET_SYSERR;
1064  }
1065  bits = ((ret = getValue__ (enc[--rpos])) << vbit) | bits;
1066  if (-1 == ret)
1067  return GNUNET_SYSERR;
1068  vbit += 5;
1069  if (vbit >= 8)
1070  {
1071  uout[--wpos] = (unsigned char) bits;
1072  bits >>= 8;
1073  vbit -= 8;
1074  }
1075  }
1076  if ( (0 != rpos) ||
1077  (0 != vbit) )
1078  return GNUNET_SYSERR;
1079  return GNUNET_OK;
1080 }
1081 
1082 
1099 int
1100 GNUNET_STRINGS_parse_uri (const char *path,
1101  char **scheme_part,
1102  const char **path_part)
1103 {
1104  size_t len;
1105  size_t i;
1106  int end;
1107  int pp_state = 0;
1108  const char *post_scheme_part = NULL;
1109  len = strlen (path);
1110  for (end = 0, i = 0; !end && i < len; i++)
1111  {
1112  switch (pp_state)
1113  {
1114  case 0:
1115  if ( (path[i] == ':') && (i > 0) )
1116  {
1117  pp_state += 1;
1118  continue;
1119  }
1120  if (!((path[i] >= 'A' && path[i] <= 'Z') || (path[i] >= 'a' && path[i] <= 'z')
1121  || (path[i] >= '0' && path[i] <= '9') || path[i] == '+' || path[i] == '-'
1122  || (path[i] == '.')))
1123  end = 1;
1124  break;
1125  case 1:
1126  case 2:
1127  if (path[i] == '/')
1128  {
1129  pp_state += 1;
1130  continue;
1131  }
1132  end = 1;
1133  break;
1134  case 3:
1135  post_scheme_part = &path[i];
1136  end = 1;
1137  break;
1138  default:
1139  end = 1;
1140  }
1141  }
1142  if (post_scheme_part == NULL)
1143  return GNUNET_NO;
1144  if (scheme_part)
1145  {
1146  *scheme_part = GNUNET_malloc (post_scheme_part - path + 1);
1147  GNUNET_memcpy (*scheme_part, path, post_scheme_part - path);
1148  (*scheme_part)[post_scheme_part - path] = '\0';
1149  }
1150  if (path_part)
1151  *path_part = post_scheme_part;
1152  return GNUNET_YES;
1153 }
1154 
1155 
1170 int
1172  int can_be_uri,
1173  int *r_is_uri,
1174  char **r_uri_scheme)
1175 {
1176 #if WINDOWS
1177  size_t len;
1178 #endif
1179  const char *post_scheme_path;
1180  int is_uri;
1181  char * uri;
1182  /* consider POSIX paths to be absolute too, even on W32,
1183  * as plibc expansion will fix them for us.
1184  */
1185  if (filename[0] == '/')
1186  return GNUNET_YES;
1187  if (can_be_uri)
1188  {
1189  is_uri = GNUNET_STRINGS_parse_uri (filename, &uri, &post_scheme_path);
1190  if (r_is_uri)
1191  *r_is_uri = is_uri;
1192  if (is_uri)
1193  {
1194  if (r_uri_scheme)
1195  *r_uri_scheme = uri;
1196  else
1197  GNUNET_free_non_null (uri);
1198 #if WINDOWS
1199  len = strlen(post_scheme_path);
1200  /* Special check for file:///c:/blah
1201  * We want to parse 'c:/', not '/c:/'
1202  */
1203  if (post_scheme_path[0] == '/' && len >= 3 && post_scheme_path[2] == ':')
1204  post_scheme_path = &post_scheme_path[1];
1205 #endif
1206  return GNUNET_STRINGS_path_is_absolute (post_scheme_path, GNUNET_NO, NULL, NULL);
1207  }
1208  }
1209  else
1210  {
1211  if (r_is_uri)
1212  *r_is_uri = GNUNET_NO;
1213  }
1214 #if WINDOWS
1215  len = strlen (filename);
1216  if (len >= 3 &&
1217  ((filename[0] >= 'A' && filename[0] <= 'Z')
1218  || (filename[0] >= 'a' && filename[0] <= 'z'))
1219  && filename[1] == ':' && (filename[2] == '/' || filename[2] == '\\'))
1220  return GNUNET_YES;
1221 #endif
1222  return GNUNET_NO;
1223 }
1224 
1225 #if MINGW
1226 #define _IFMT 0170000 /* type of file */
1227 #define _IFLNK 0120000 /* symbolic link */
1228 #define S_ISLNK(m) (((m)&_IFMT) == _IFLNK)
1229 #endif
1230 
1231 
1240 int
1242  enum GNUNET_STRINGS_FilenameCheck checks)
1243 {
1244  struct stat st;
1245  if ( (NULL == filename) || (filename[0] == '\0') )
1246  return GNUNET_SYSERR;
1247  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_ABSOLUTE))
1248  if (!GNUNET_STRINGS_path_is_absolute (filename, GNUNET_NO, NULL, NULL))
1249  return GNUNET_NO;
1250  if (0 != (checks & (GNUNET_STRINGS_CHECK_EXISTS
1253  {
1254  if (0 != STAT (filename, &st))
1255  {
1256  if (0 != (checks & GNUNET_STRINGS_CHECK_EXISTS))
1257  return GNUNET_NO;
1258  else
1259  return GNUNET_SYSERR;
1260  }
1261  }
1262  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_DIRECTORY))
1263  if (!S_ISDIR (st.st_mode))
1264  return GNUNET_NO;
1265  if (0 != (checks & GNUNET_STRINGS_CHECK_IS_LINK))
1266  if (!S_ISLNK (st.st_mode))
1267  return GNUNET_NO;
1268  return GNUNET_YES;
1269 }
1270 
1271 
1284 int
1285 GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr,
1286  uint16_t addrlen,
1287  struct sockaddr_in6 *r_buf)
1288 {
1289  char zbuf[addrlen + 1];
1290  int ret;
1291  char *port_colon;
1292  unsigned int port;
1293  char dummy[2];
1294 
1295  if (addrlen < 6)
1296  return GNUNET_SYSERR;
1297  GNUNET_memcpy (zbuf, zt_addr, addrlen);
1298  if ('[' != zbuf[0])
1299  {
1301  _("IPv6 address did not start with `['\n"));
1302  return GNUNET_SYSERR;
1303  }
1304  zbuf[addrlen] = '\0';
1305  port_colon = strrchr (zbuf, ':');
1306  if (NULL == port_colon)
1307  {
1309  _("IPv6 address did contain ':' to separate port number\n"));
1310  return GNUNET_SYSERR;
1311  }
1312  if (']' != *(port_colon - 1))
1313  {
1315  _("IPv6 address did contain ']' before ':' to separate port number\n"));
1316  return GNUNET_SYSERR;
1317  }
1318  ret = SSCANF (port_colon,
1319  ":%u%1s",
1320  &port,
1321  dummy);
1322  if ( (1 != ret) || (port > 65535) )
1323  {
1325  _("IPv6 address did contain a valid port number after the last ':'\n"));
1326  return GNUNET_SYSERR;
1327  }
1328  *(port_colon-1) = '\0';
1329  memset (r_buf, 0, sizeof (struct sockaddr_in6));
1330  ret = inet_pton (AF_INET6, &zbuf[1], &r_buf->sin6_addr);
1331  if (ret <= 0)
1332  {
1334  _("Invalid IPv6 address `%s': %s\n"),
1335  &zbuf[1],
1336  STRERROR (errno));
1337  return GNUNET_SYSERR;
1338  }
1339  r_buf->sin6_port = htons (port);
1340  r_buf->sin6_family = AF_INET6;
1341 #if HAVE_SOCKADDR_IN_SIN_LEN
1342  r_buf->sin6_len = (u_char) sizeof (struct sockaddr_in6);
1343 #endif
1344  return GNUNET_OK;
1345 }
1346 
1347 
1359 int
1360 GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr,
1361  uint16_t addrlen,
1362  struct sockaddr_in *r_buf)
1363 {
1364  unsigned int temps[4];
1365  unsigned int port;
1366  unsigned int cnt;
1367  char dummy[2];
1368 
1369  if (addrlen < 9)
1370  return GNUNET_SYSERR;
1371  cnt = SSCANF (zt_addr,
1372  "%u.%u.%u.%u:%u%1s",
1373  &temps[0],
1374  &temps[1],
1375  &temps[2],
1376  &temps[3],
1377  &port,
1378  dummy);
1379  if (5 != cnt)
1380  return GNUNET_SYSERR;
1381  for (cnt = 0; cnt < 4; cnt++)
1382  if (temps[cnt] > 0xFF)
1383  return GNUNET_SYSERR;
1384  if (port > 65535)
1385  return GNUNET_SYSERR;
1386  r_buf->sin_family = AF_INET;
1387  r_buf->sin_port = htons (port);
1388  r_buf->sin_addr.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16) +
1389  (temps[2] << 8) + temps[3]);
1390 #if HAVE_SOCKADDR_IN_SIN_LEN
1391  r_buf->sin_len = (u_char) sizeof (struct sockaddr_in);
1392 #endif
1393  return GNUNET_OK;
1394 }
1395 
1396 
1408 int
1410  uint16_t addrlen,
1411  struct sockaddr_storage *r_buf)
1412 {
1413  if (addr[0] == '[')
1414  return GNUNET_STRINGS_to_address_ipv6 (addr,
1415  addrlen,
1416  (struct sockaddr_in6 *) r_buf);
1417  return GNUNET_STRINGS_to_address_ipv4 (addr,
1418  addrlen,
1419  (struct sockaddr_in *) r_buf);
1420 }
1421 
1422 
1432 size_t
1434  uint8_t *af,
1435  struct sockaddr **sa)
1436 {
1437  char *cp = GNUNET_strdup (addr);
1438 
1439  *af = AF_UNSPEC;
1440  if ('[' == *addr)
1441  {
1442  /* IPv6 */
1443  *sa = GNUNET_malloc (sizeof (struct sockaddr_in6));
1444  if (GNUNET_OK !=
1446  strlen (cp),
1447  (struct sockaddr_in6 *) *sa))
1448  {
1449  GNUNET_free (*sa);
1450  *sa = NULL;
1451  GNUNET_free (cp);
1452  return 0;
1453  }
1454  *af = AF_INET6;
1455  GNUNET_free (cp);
1456  return sizeof (struct sockaddr_in6);
1457  }
1458  else
1459  {
1460  /* IPv4 */
1461  *sa = GNUNET_malloc (sizeof (struct sockaddr_in));
1462  if (GNUNET_OK !=
1464  strlen (cp),
1465  (struct sockaddr_in *) *sa))
1466  {
1467  GNUNET_free (*sa);
1468  *sa = NULL;
1469  GNUNET_free (cp);
1470  return 0;
1471  }
1472  *af = AF_INET;
1473  GNUNET_free (cp);
1474  return sizeof (struct sockaddr_in);
1475  }
1476 }
1477 
1478 
1483 static char *const *
1485  char *const *argv)
1486 {
1487  size_t argvsize = 0;
1488  int i;
1489  char **new_argv;
1490  char *p;
1491  for (i = 0; i < argc; i++)
1492  argvsize += strlen (argv[i]) + 1 + sizeof (char *);
1493  new_argv = GNUNET_malloc (argvsize + sizeof (char *));
1494  p = (char *) &new_argv[argc + 1];
1495  for (i = 0; i < argc; i++)
1496  {
1497  new_argv[i] = p;
1498  strcpy (p, argv[i]);
1499  p += strlen (argv[i]) + 1;
1500  }
1501  new_argv[argc] = NULL;
1502  return (char *const *) new_argv;
1503 }
1504 
1505 
1520 int
1522  char *const *argv,
1523  int *u8argc,
1524  char *const **u8argv)
1525 {
1526 #if WINDOWS
1527  wchar_t *wcmd;
1528  wchar_t **wargv;
1529  int wargc;
1530  int i;
1531  char **split_u8argv;
1532 
1533  wcmd = GetCommandLineW ();
1534  if (NULL == wcmd)
1535  return GNUNET_SYSERR;
1536  wargv = CommandLineToArgvW (wcmd, &wargc);
1537  if (NULL == wargv)
1538  return GNUNET_SYSERR;
1539 
1540  split_u8argv = GNUNET_malloc (argc * sizeof (char *));
1541 
1542  for (i = 0; i < wargc; i++)
1543  {
1544  size_t strl;
1545  /* Hopefully it will allocate us NUL-terminated strings... */
1546  split_u8argv[i] = (char *) u16_to_u8 (wargv[i], wcslen (wargv[i]) + 1, NULL, &strl);
1547  if (NULL == split_u8argv[i])
1548  {
1549  int j;
1550  for (j = 0; j < i; j++)
1551  free (split_u8argv[j]);
1552  GNUNET_free (split_u8argv);
1553  LocalFree (wargv);
1554  return GNUNET_SYSERR;
1555  }
1556  }
1557 
1558  *u8argv = _make_continuous_arg_copy (wargc, split_u8argv);
1559  *u8argc = wargc;
1560 
1561  for (i = 0; i < wargc; i++)
1562  free (split_u8argv[i]);
1563  free (split_u8argv);
1564  return GNUNET_OK;
1565 #else
1566  char *const *new_argv = (char *const *) _make_continuous_arg_copy (argc, argv);
1567  *u8argv = new_argv;
1568  *u8argc = argc;
1569  return GNUNET_OK;
1570 #endif
1571 }
1572 
1573 
1583 static int
1584 parse_port_policy (const char *port_policy,
1585  struct GNUNET_STRINGS_PortPolicy *pp)
1586 {
1587  const char *pos;
1588  int s;
1589  int e;
1590  char eol[2];
1591 
1592  pos = port_policy;
1593  if ('!' == *pos)
1594  {
1596  pos++;
1597  }
1598  if (2 == sscanf (pos,
1599  "%u-%u%1s",
1600  &s,
1601  &e,
1602  eol))
1603  {
1604  if ( (0 == s) ||
1605  (s > 0xFFFF) ||
1606  (e < s) ||
1607  (e > 0xFFFF) )
1608  {
1610  _("Port not in range\n"));
1611  return GNUNET_SYSERR;
1612  }
1613  pp->start_port = (uint16_t) s;
1614  pp->end_port = (uint16_t) e;
1615  return GNUNET_OK;
1616  }
1617  if (1 == sscanf (pos,
1618  "%u%1s",
1619  &s,
1620  eol))
1621  {
1622  if ( (0 == s) ||
1623  (s > 0xFFFF) )
1624  {
1626  _("Port not in range\n"));
1627  return GNUNET_SYSERR;
1628  }
1629 
1630  pp->start_port = (uint16_t) s;
1631  pp->end_port = (uint16_t) s;
1632  return GNUNET_OK;
1633  }
1635  _("Malformed port policy `%s'\n"),
1636  port_policy);
1637  return GNUNET_SYSERR;
1638 }
1639 
1640 
1654 GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX)
1655 {
1656  unsigned int count;
1657  unsigned int i;
1658  unsigned int j;
1659  unsigned int len;
1660  int cnt;
1661  unsigned int pos;
1662  unsigned int temps[8];
1663  int slash;
1665  int colon;
1666  int end;
1667  char *routeList;
1668  char dummy[2];
1669 
1670  if (NULL == routeListX)
1671  return NULL;
1672  len = strlen (routeListX);
1673  if (0 == len)
1674  return NULL;
1675  routeList = GNUNET_strdup (routeListX);
1676  count = 0;
1677  for (i = 0; i < len; i++)
1678  if (routeList[i] == ';')
1679  count++;
1680  result = GNUNET_malloc (sizeof (struct GNUNET_STRINGS_IPv4NetworkPolicy) * (count + 1));
1681  i = 0;
1682  pos = 0;
1683  while (i < count)
1684  {
1685  for (colon = pos; ':' != routeList[colon]; colon++)
1686  if ( (';' == routeList[colon]) ||
1687  ('\0' == routeList[colon]) )
1688  break;
1689  for (end = colon; ';' != routeList[end]; end++)
1690  if ('\0' == routeList[end])
1691  break;
1692  if ('\0' == routeList[end])
1693  break;
1694  routeList[end] = '\0';
1695  if (':' == routeList[colon])
1696  {
1697  routeList[colon] = '\0';
1698  if (GNUNET_OK != parse_port_policy (&routeList[colon + 1],
1699  &result[i].pp))
1700  break;
1701  }
1702  cnt =
1703  SSCANF (&routeList[pos],
1704  "%u.%u.%u.%u/%u.%u.%u.%u%1s",
1705  &temps[0],
1706  &temps[1],
1707  &temps[2],
1708  &temps[3],
1709  &temps[4],
1710  &temps[5],
1711  &temps[6],
1712  &temps[7],
1713  dummy);
1714  if (8 == cnt)
1715  {
1716  for (j = 0; j < 8; j++)
1717  if (temps[j] > 0xFF)
1718  {
1720  _("Invalid format for IP: `%s'\n"),
1721  &routeList[pos]);
1722  GNUNET_free (result);
1723  GNUNET_free (routeList);
1724  return NULL;
1725  }
1726  result[i].network.s_addr =
1727  htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
1728  temps[3]);
1729  result[i].netmask.s_addr =
1730  htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
1731  temps[7]);
1732  pos = end + 1;
1733  i++;
1734  continue;
1735  }
1736  /* try second notation */
1737  cnt =
1738  SSCANF (&routeList[pos],
1739  "%u.%u.%u.%u/%u%1s",
1740  &temps[0],
1741  &temps[1],
1742  &temps[2],
1743  &temps[3],
1744  &slash,
1745  dummy);
1746  if (5 == cnt)
1747  {
1748  for (j = 0; j < 4; j++)
1749  if (temps[j] > 0xFF)
1750  {
1752  _("Invalid format for IP: `%s'\n"),
1753  &routeList[pos]);
1754  GNUNET_free (result);
1755  GNUNET_free (routeList);
1756  return NULL;
1757  }
1758  result[i].network.s_addr =
1759  htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
1760  temps[3]);
1761  if ((slash <= 32) && (slash >= 0))
1762  {
1763  result[i].netmask.s_addr = 0;
1764  while (slash > 0)
1765  {
1766  result[i].netmask.s_addr =
1767  (result[i].netmask.s_addr >> 1) + 0x80000000;
1768  slash--;
1769  }
1770  result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1771  pos = end + 1;
1772  i++;
1773  continue;
1774  }
1775  else
1776  {
1778  _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
1779  slash);
1780  GNUNET_free (result);
1781  GNUNET_free (routeList);
1782  return NULL; /* error */
1783  }
1784  }
1785  /* try third notation */
1786  slash = 32;
1787  cnt =
1788  SSCANF (&routeList[pos],
1789  "%u.%u.%u.%u%1s",
1790  &temps[0],
1791  &temps[1],
1792  &temps[2],
1793  &temps[3],
1794  dummy);
1795  if (4 == cnt)
1796  {
1797  for (j = 0; j < 4; j++)
1798  if (temps[j] > 0xFF)
1799  {
1801  _("Invalid format for IP: `%s'\n"),
1802  &routeList[pos]);
1803  GNUNET_free (result);
1804  GNUNET_free (routeList);
1805  return NULL;
1806  }
1807  result[i].network.s_addr =
1808  htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
1809  temps[3]);
1810  result[i].netmask.s_addr = 0;
1811  while (slash > 0)
1812  {
1813  result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
1814  slash--;
1815  }
1816  result[i].netmask.s_addr = htonl (result[i].netmask.s_addr);
1817  pos = end + 1;
1818  i++;
1819  continue;
1820  }
1822  _("Invalid format for IP: `%s'\n"),
1823  &routeList[pos]);
1824  GNUNET_free (result);
1825  GNUNET_free (routeList);
1826  return NULL; /* error */
1827  }
1828  if (pos < strlen (routeList))
1829  {
1831  _("Invalid format: `%s'\n"),
1832  &routeListX[pos]);
1833  GNUNET_free (result);
1834  GNUNET_free (routeList);
1835  return NULL; /* oops */
1836  }
1837  GNUNET_free (routeList);
1838  return result; /* ok */
1839 }
1840 
1841 
1854 GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX)
1855 {
1856  unsigned int count;
1857  unsigned int i;
1858  unsigned int len;
1859  unsigned int pos;
1860  int start;
1861  int slash;
1862  int ret;
1863  char *routeList;
1865  unsigned int bits;
1866  unsigned int off;
1867  int save;
1868  int colon;
1869  char dummy[2];
1870 
1871  if (NULL == routeListX)
1872  return NULL;
1873  len = strlen (routeListX);
1874  if (0 == len)
1875  return NULL;
1876  routeList = GNUNET_strdup (routeListX);
1877  count = 0;
1878  for (i = 0; i < len; i++)
1879  if (';' == routeList[i])
1880  count++;
1881  if (';' != routeList[len - 1])
1882  {
1884  _("Invalid network notation (does not end with ';': `%s')\n"),
1885  routeList);
1886  GNUNET_free (routeList);
1887  return NULL;
1888  }
1889 
1890  result = GNUNET_malloc (sizeof (struct GNUNET_STRINGS_IPv6NetworkPolicy) * (count + 1));
1891  i = 0;
1892  pos = 0;
1893  while (i < count)
1894  {
1895  start = pos;
1896  while (';' != routeList[pos])
1897  pos++;
1898  slash = pos;
1899  while ((slash >= start) && (routeList[slash] != '/'))
1900  slash--;
1901 
1902  if (slash < start)
1903  {
1904  memset (&result[i].netmask,
1905  0xFF,
1906  sizeof (struct in6_addr));
1907  slash = pos;
1908  }
1909  else
1910  {
1911  routeList[pos] = '\0';
1912  for (colon = pos; ':' != routeList[colon]; colon--)
1913  if ('/' == routeList[colon])
1914  break;
1915  if (':' == routeList[colon])
1916  {
1917  routeList[colon] = '\0';
1918  if (GNUNET_OK != parse_port_policy (&routeList[colon + 1],
1919  &result[i].pp))
1920  {
1921  GNUNET_free (result);
1922  GNUNET_free (routeList);
1923  return NULL;
1924  }
1925  }
1926  ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask);
1927  if (ret <= 0)
1928  {
1929  save = errno;
1930  if ( (1 != SSCANF (&routeList[slash + 1],
1931  "%u%1s",
1932  &bits,
1933  dummy)) ||
1934  (bits > 128) )
1935  {
1936  if (0 == ret)
1938  _("Wrong format `%s' for netmask\n"),
1939  &routeList[slash + 1]);
1940  else
1941  {
1942  errno = save;
1943  LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "inet_pton");
1944  }
1945  GNUNET_free (result);
1946  GNUNET_free (routeList);
1947  return NULL;
1948  }
1949  off = 0;
1950  while (bits > 8)
1951  {
1952  result[i].netmask.s6_addr[off++] = 0xFF;
1953  bits -= 8;
1954  }
1955  while (bits > 0)
1956  {
1957  result[i].netmask.s6_addr[off] =
1958  (result[i].netmask.s6_addr[off] >> 1) + 0x80;
1959  bits--;
1960  }
1961  }
1962  }
1963  routeList[slash] = '\0';
1964  ret = inet_pton (AF_INET6, &routeList[start], &result[i].network);
1965  if (ret <= 0)
1966  {
1967  if (0 == ret)
1969  _("Wrong format `%s' for network\n"),
1970  &routeList[slash + 1]);
1971  else
1973  "inet_pton");
1974  GNUNET_free (result);
1975  GNUNET_free (routeList);
1976  return NULL;
1977  }
1978  pos++;
1979  i++;
1980  }
1981  GNUNET_free (routeList);
1982  return result;
1983 }
1984 
1985 
1986 
1989 #define FILLCHAR '='
1990 static char *cvt =
1991  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/";
1992 
1993 
2003 size_t
2005  size_t len,
2006  char **output)
2007 {
2008  const char *data = in;
2009  size_t ret;
2010  char *opt;
2011 
2012  ret = 0;
2013  opt = GNUNET_malloc (2 + (len * 4 / 3) + 8);
2014  for (size_t i = 0; i < len; ++i)
2015  {
2016  char c;
2017 
2018  c = (data[i] >> 2) & 0x3f;
2019  opt[ret++] = cvt[(int) c];
2020  c = (data[i] << 4) & 0x3f;
2021  if (++i < len)
2022  c |= (data[i] >> 4) & 0x0f;
2023  opt[ret++] = cvt[(int) c];
2024  if (i < len)
2025  {
2026  c = (data[i] << 2) & 0x3f;
2027  if (++i < len)
2028  c |= (data[i] >> 6) & 0x03;
2029  opt[ret++] = cvt[(int) c];
2030  }
2031  else
2032  {
2033  ++i;
2034  opt[ret++] = FILLCHAR;
2035  }
2036  if (i < len)
2037  {
2038  c = data[i] & 0x3f;
2039  opt[ret++] = cvt[(int) c];
2040  }
2041  else
2042  {
2043  opt[ret++] = FILLCHAR;
2044  }
2045  }
2046  *output = opt;
2047  return ret;
2048 }
2049 
2050 #define cvtfind(a)( (((a) >= 'A')&&((a) <= 'Z'))? (a)-'A'\
2051  :(((a)>='a')&&((a)<='z')) ? (a)-'a'+26\
2052  :(((a)>='0')&&((a)<='9')) ? (a)-'0'+52\
2053  :((a) == '+') ? 62\
2054  :((a) == '/') ? 63 : -1)
2055 
2056 
2066 size_t
2068  size_t len,
2069  void **out)
2070 {
2071  char *output;
2072  size_t ret = 0;
2073 
2074 #define CHECK_CRLF while (data[i] == '\r' || data[i] == '\n') {\
2075  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "ignoring CR/LF\n"); \
2076  i++; \
2077  if (i >= len) goto END; \
2078  }
2079 
2080  output = GNUNET_malloc ((len * 3 / 4) + 8);
2082  "base64_decode decoding len=%d\n",
2083  (int) len);
2084  for (size_t i = 0; i < len; ++i)
2085  {
2086  char c;
2087  char c1;
2088 
2089  CHECK_CRLF;
2090  if (FILLCHAR == data[i])
2091  break;
2092  c = (char) cvtfind (data[i]);
2093  ++i;
2094  CHECK_CRLF;
2095  c1 = (char) cvtfind (data[i]);
2096  c = (c << 2) | ((c1 >> 4) & 0x3);
2097  output[ret++] = c;
2098  if (++i < len)
2099  {
2100  CHECK_CRLF;
2101  c = data[i];
2102  if (FILLCHAR == c)
2103  break;
2104  c = (char) cvtfind (c);
2105  c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
2106  output[ret++] = c1;
2107  }
2108  if (++i < len)
2109  {
2110  CHECK_CRLF;
2111  c1 = data[i];
2112  if (FILLCHAR == c1)
2113  break;
2114 
2115  c1 = (char) cvtfind (c1);
2116  c = ((c << 6) & 0xc0) | c1;
2117  output[ret++] = c;
2118  }
2119  }
2120 END:
2121  *out = output;
2122  return ret;
2123 }
2124 
2125 
2126 /* 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:243
struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
Parse an IPv4 network policy.
Definition: strings.c:1654
#define CHECK_CRLF
#define FILLCHAR
******************** Base64 encoding
Definition: strings.c:1989
static struct GNUNET_SCHEDULER_Task * tt
Task scheduled to handle timeout.
uint64_t rel_value_us
The actual value.
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:35
static int parse_port_policy(const char *port_policy, struct GNUNET_STRINGS_PortPolicy *pp)
Parse the given port policy.
Definition: strings.c:1584
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:454
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static struct in_addr dummy
Target "dummy" address.
int GNUNET_STRINGS_parse_uri(const char *path, char **scheme_part, const char **path_part)
Parse a path that might be an URI.
Definition: strings.c:1100
struct GNUNET_STRINGS_PortPolicy pp
Policy for port access.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
char * GNUNET_STRINGS_byte_size_fancy(unsigned long long size)
Convert a given filesize into a fancy human-readable format.
Definition: strings.c:174
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:259
struct GNUNET_STRINGS_IPv6NetworkPolicy * GNUNET_STRINGS_parse_ipv6_policy(const char *routeListX)
Parse an IPv6 network policy.
Definition: strings.c:1854
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1521
int GNUNET_STRINGS_path_is_absolute(const char *filename, int can_be_uri, int *r_is_uri, char **r_uri_scheme)
Check whether filename is absolute or not, and if it&#39;s an URI.
Definition: strings.c:1171
#define cvtfind(a)
Definition: strings.c:2050
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
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:353
#define STRERROR(i)
Definition: plibc.h:676
Check that the path is an absolute path.
network in CIDR notation for IPV6.
int negate_portrange
GNUNET_YES if the port range should be negated ("!" in policy).
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:408
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:317
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:1484
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define STAT(p, b)
Definition: plibc.h:663
static struct GNUNET_SCHEDULER_Task * t
Main task.
Check that it exists.
static int ret
Final status code.
Definition: gnunet-arm.c:89
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.
static char * cvt
Definition: strings.c:1990
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
struct in_addr network
IPv4 address.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
int GNUNET_STRINGS_to_address_ipv4(const char *zt_addr, uint16_t addrlen, struct sockaddr_in *r_buf)
Tries to convert &#39;zt_addr&#39; string to an IPv4 address.
Definition: strings.c:1360
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:136
cryptographic primitives for GNUnet
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
void GNUNET_STRINGS_utf8_toupper(const char *input, char *output)
Convert the utf-8 input string to uppercase.
Definition: strings.c:580
#define GNUNET_memcpy(dst, src, n)
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
static char * fn
Filename of the unique file.
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:99
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:727
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:542
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:64
Unit conversion table entry for &#39;convert_with_table&#39;.
Definition: strings.c:233
#define DIR_SEPARATOR
Definition: plibc.h:631
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:1433
static OpusDecoder * dec
OPUS decoder.
#define LOG(kind,...)
Definition: strings.c:37
int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows)
static unsigned int getValue__(unsigned char a)
Get the decoded value corresponding to a character according to Crockford Base32 encoding.
Definition: strings.c:865
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **out)
Decode from Base64.
Definition: strings.c:2067
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:2004
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:845
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
int GNUNET_STRINGS_check_filename(const char *filename, enum GNUNET_STRINGS_FilenameCheck checks)
Perform checks on filename.
Definition: strings.c:1241
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition: strings.c:602
char * getenv()
#define S_ISLNK(m)
Definition: disk.c:59
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:39
#define SSCANF
Definition: plibc.h:691
static uint16_t port
Port number.
Definition: gnunet-bcd.c:79
static OpusEncoder * enc
OPUS encoder.
int GNUNET_STRINGS_to_address_ipv6(const char *zt_addr, uint16_t addrlen, struct sockaddr_in6 *r_buf)
Tries to convert zt_addr string to an IPv6 address.
Definition: strings.c:1285
static int inet_pton(int af, const char *cp, struct in_addr *buf)
Convert IPv4 address from text to binary form.
#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:522
struct GNUNET_STRINGS_PortPolicy pp
Policy for port access.
struct in6_addr network
IPv6 address.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
Check that it is a link.
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:988
#define DIR_SEPARATOR_STR
Definition: plibc.h:632
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
"asctime", except for GNUnet time.
Definition: strings.c:792
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:218
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:238
static size_t strnlen(const char *s, size_t n)
int GNUNET_STRINGS_to_address_ip(const char *addr, uint16_t addrlen, struct sockaddr_storage *r_buf)
Tries to convert addr string to an IP (v4 or v6) address.
Definition: strings.c:1409
#define GNUNET_malloc(size)
Wrapper around malloc.
int GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert Crockford Base32hex encoding back to data.
Definition: strings.c:1021
char * GNUNET_STRINGS_data_to_string(const void *data, size_t size, char *out, size_t out_size)
Convert binary data to ASCII encoding using Crockford Base32 encoding.
Definition: strings.c:924
Check that it is a directory.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
void GNUNET_STRINGS_utf8_tolower(const char *input, char *output)
Convert the utf-8 input string to lowercase.
Definition: strings.c:558
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...