plibc: win32 related, socket
[oweals/gnunet.git] / src / util / strings.c
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  */
20 /**
21  * @file util/strings.c
22  * @brief string functions
23  * @author Nils Durner
24  * @author Christian Grothoff
25  */
26
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) \
40   GNUNET_log_from_strerror(kind, "util-strings", syscall)
41
42
43 /**
44  * Fill a buffer of the given size with
45  * count 0-terminated strings (given as varargs).
46  * If "buffer" is NULL, only compute the amount of
47  * space required (sum of "strlen(arg)+1").
48  *
49  * Unlike using "snprintf" with "%s", this function
50  * will add 0-terminators after each string.  The
51  * #GNUNET_string_buffer_tokenize() function can be
52  * used to parse the buffer back into individual
53  * strings.
54  *
55  * @param buffer the buffer to fill with strings, can
56  *               be NULL in which case only the necessary
57  *               amount of space will be calculated
58  * @param size number of bytes available in buffer
59  * @param count number of strings that follow
60  * @param ... count 0-terminated strings to copy to buffer
61  * @return number of bytes written to the buffer
62  *         (or number of bytes that would have been written)
63  */
64 size_t
65 GNUNET_STRINGS_buffer_fill(char *buffer, size_t size, unsigned int count, ...)
66 {
67   size_t needed;
68   size_t slen;
69   const char *s;
70   va_list ap;
71
72   needed = 0;
73   va_start(ap, count);
74   while (count > 0)
75     {
76       s = va_arg(ap, const char *);
77
78       slen = strlen(s) + 1;
79       if (buffer != NULL)
80         {
81           GNUNET_assert(needed + slen <= size);
82           GNUNET_memcpy(&buffer[needed], s, slen);
83         }
84       needed += slen;
85       count--;
86     }
87   va_end(ap);
88   return needed;
89 }
90
91
92 /**
93  * Convert a peer path to a human-readable string.
94  *
95  * @param pids array of PIDs to convert to a string
96  * @param num_pids length of the @a pids array
97  * @return string representing the array of @a pids
98  */
99 char *
100 GNUNET_STRINGS_pp2s(const struct GNUNET_PeerIdentity *pids,
101                     unsigned int num_pids)
102 {
103   char *buf;
104   size_t off;
105   size_t plen = num_pids * 5 + 1;
106
107   off = 0;
108   buf = GNUNET_malloc(plen);
109   for (unsigned int i = 0; i < num_pids; i++)
110     {
111       off += GNUNET_snprintf(&buf[off],
112                              plen - off,
113                              "%s%s",
114                              GNUNET_i2s(&pids[i]),
115                              (i == num_pids - 1) ? "" : "-");
116     }
117   return buf;
118 }
119
120
121 /**
122  * Given a buffer of a given size, find "count"
123  * 0-terminated strings in the buffer and assign
124  * the count (varargs) of type "const char**" to the
125  * locations of the respective strings in the
126  * buffer.
127  *
128  * @param buffer the buffer to parse
129  * @param size size of the buffer
130  * @param count number of strings to locate
131  * @return offset of the character after the last 0-termination
132  *         in the buffer, or 0 on error.
133  */
134 unsigned int
135 GNUNET_STRINGS_buffer_tokenize(const char *buffer,
136                                size_t size,
137                                unsigned int count,
138                                ...)
139 {
140   unsigned int start;
141   unsigned int needed;
142   const char **r;
143   va_list ap;
144
145   needed = 0;
146   va_start(ap, count);
147   while (count > 0)
148     {
149       r = va_arg(ap, const char **);
150
151       start = needed;
152       while ((needed < size) && (buffer[needed] != '\0'))
153         needed++;
154       if (needed == size)
155         {
156           va_end(ap);
157           return 0; /* error */
158         }
159       *r = &buffer[start];
160       needed++; /* skip 0-termination */
161       count--;
162     }
163   va_end(ap);
164   return needed;
165 }
166
167
168 /**
169  * Convert a given filesize into a fancy human-readable format.
170  *
171  * @param size number of bytes
172  * @return fancy representation of the size (possibly rounded) for humans
173  */
174 char *
175 GNUNET_STRINGS_byte_size_fancy(unsigned long long size)
176 {
177   const char *unit = _(/* size unit */ "b");
178   char *ret;
179
180   if (size > 5 * 1024)
181     {
182       size = size / 1024;
183       unit = "KiB";
184       if (size > 5 * 1024)
185         {
186           size = size / 1024;
187           unit = "MiB";
188           if (size > 5 * 1024)
189             {
190               size = size / 1024;
191               unit = "GiB";
192               if (size > 5 * 1024)
193                 {
194                   size = size / 1024;
195                   unit = "TiB";
196                 }
197             }
198         }
199     }
200   ret = GNUNET_malloc(32);
201   GNUNET_snprintf(ret, 32, "%llu %s", size, unit);
202   return ret;
203 }
204
205
206 /**
207  * Like strlcpy but portable. The given string @a src is copied until its null
208  * byte or until @a n - 1 bytes have been read. The destination buffer is
209  * guaranteed to be null-terminated.
210  *
211  * @param dst destination of the copy (must be @a n bytes long)
212  * @param src source of the copy (at most @a n - 1 bytes will be read)
213  * @param n the length of the string to copy, including its terminating null
214  *          byte
215  * @return the length of the string that was copied, excluding the terminating
216  *         null byte
217  */
218 size_t
219 GNUNET_strlcpy(char *dst, const char *src, size_t n)
220 {
221   size_t slen;
222
223   GNUNET_assert(0 != n);
224   slen = strnlen(src, n - 1);
225   memcpy(dst, src, slen);
226   dst[slen] = '\0';
227   return slen;
228 }
229
230
231 /**
232  * Unit conversion table entry for 'convert_with_table'.
233  */
234 struct ConversionTable {
235   /**
236    * Name of the unit (or NULL for end of table).
237    */
238   const char *name;
239
240   /**
241    * Factor to apply for this unit.
242    */
243   unsigned long long value;
244 };
245
246
247 /**
248  * Convert a string of the form "4 X 5 Y" into a numeric value
249  * by interpreting "X" and "Y" as units and then multiplying
250  * the numbers with the values associated with the respective
251  * unit from the conversion table.
252  *
253  * @param input input string to parse
254  * @param table table with the conversion of unit names to numbers
255  * @param output where to store the result
256  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
257  */
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         }
301       while (GNUNET_YES);
302     }
303   ret += last;
304   *output = ret;
305   GNUNET_free(in);
306   return GNUNET_OK;
307 }
308
309
310 /**
311  * Convert a given fancy human-readable size to bytes.
312  *
313  * @param fancy_size human readable string (i.e. 1 MB)
314  * @param size set to the size in bytes
315  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
316  */
317 int
318 GNUNET_STRINGS_fancy_size_to_bytes(const char *fancy_size,
319                                    unsigned long long *size)
320 {
321   static const struct ConversionTable table[] =
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   return convert_with_table(fancy_size, table, size);
338 }
339
340
341 /**
342  * Convert a given fancy human-readable time to our internal
343  * representation.
344  *
345  * @param fancy_time human readable string (i.e. 1 minute)
346  * @param rtime set to the relative time
347  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
348  */
349 int
350 GNUNET_STRINGS_fancy_time_to_relative(const char *fancy_time,
351                                       struct GNUNET_TIME_Relative *rtime)
352 {
353   static const struct ConversionTable table[] =
354   { { "us", 1 },
355     { "ms", 1000 },
356     { "s", 1000 * 1000LL },
357     { "second", 1000 * 1000LL },
358     { "seconds", 1000 * 1000LL },
359     { "\"", 1000 * 1000LL },
360     { "m", 60 * 1000 * 1000LL },
361     { "min", 60 * 1000 * 1000LL },
362     { "minute", 60 * 1000 * 1000LL },
363     { "minutes", 60 * 1000 * 1000LL },
364     { "'", 60 * 1000 * 1000LL },
365     { "h", 60 * 60 * 1000 * 1000LL },
366     { "hour", 60 * 60 * 1000 * 1000LL },
367     { "hours", 60 * 60 * 1000 * 1000LL },
368     { "d", 24 * 60 * 60 * 1000LL * 1000LL },
369     { "day", 24 * 60 * 60 * 1000LL * 1000LL },
370     { "days", 24 * 60 * 60 * 1000LL * 1000LL },
371     { "week", 7 * 24 * 60 * 60 * 1000LL * 1000LL },
372     { "weeks", 7 * 24 * 60 * 60 * 1000LL * 1000LL },
373     { "year", 31536000000000LL /* year */ },
374     { "years", 31536000000000LL /* year */ },
375     { "a", 31536000000000LL /* year */ },
376     { NULL, 0 } };
377   int ret;
378   unsigned long long val;
379
380   if (0 == strcasecmp("forever", fancy_time))
381     {
382       *rtime = GNUNET_TIME_UNIT_FOREVER_REL;
383       return GNUNET_OK;
384     }
385   ret = convert_with_table(fancy_time, table, &val);
386   rtime->rel_value_us = (uint64_t)val;
387   return ret;
388 }
389
390
391 /**
392  * Convert a given fancy human-readable time to our internal
393  * representation. The human-readable time is expected to be
394  * in local time, whereas the returned value will be in UTC.
395  *
396  * @param fancy_time human readable string (i.e. %Y-%m-%d %H:%M:%S)
397  * @param atime set to the absolute time
398  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
399  */
400 int
401 GNUNET_STRINGS_fancy_time_to_absolute(const char *fancy_time,
402                                       struct GNUNET_TIME_Absolute *atime)
403 {
404   struct tm tv;
405   time_t t;
406   const char *eos;
407
408   if (0 == strcasecmp("end of time", fancy_time))
409     {
410       *atime = GNUNET_TIME_UNIT_FOREVER_ABS;
411       return GNUNET_OK;
412     }
413   eos = &fancy_time[strlen(fancy_time)];
414   memset(&tv, 0, sizeof(tv));
415   if ((eos != strptime(fancy_time, "%a %b %d %H:%M:%S %Y", &tv)) &&
416       (eos != strptime(fancy_time, "%c", &tv)) &&
417       (eos != strptime(fancy_time, "%Ec", &tv)) &&
418       (eos != strptime(fancy_time, "%Y-%m-%d %H:%M:%S", &tv)) &&
419       (eos != strptime(fancy_time, "%Y-%m-%d %H:%M", &tv)) &&
420       (eos != strptime(fancy_time, "%x", &tv)) &&
421       (eos != strptime(fancy_time, "%Ex", &tv)) &&
422       (eos != strptime(fancy_time, "%Y-%m-%d", &tv)) &&
423       (eos != strptime(fancy_time, "%Y-%m", &tv)) &&
424       (eos != strptime(fancy_time, "%Y", &tv)))
425     return GNUNET_SYSERR;
426   t = mktime(&tv);
427   atime->abs_value_us = (uint64_t)((uint64_t)t * 1000LL * 1000LL);
428   return GNUNET_OK;
429 }
430
431
432 /**
433  * Convert the len characters long character sequence
434  * given in input that is in the given input charset
435  * to a string in given output charset.
436  *
437  * @param input input string
438  * @param len number of bytes in @a input
439  * @param input_charset character set used for @a input
440  * @param output_charset desired character set for the return value
441  * @return the converted string (0-terminated),
442  *  if conversion fails, a copy of the orignal
443  *  string is returned.
444  */
445 char *
446 GNUNET_STRINGS_conv(const char *input,
447                     size_t len,
448                     const char *input_charset,
449                     const char *output_charset)
450 {
451   char *ret;
452   uint8_t *u8_string;
453   char *encoded_string;
454   size_t u8_string_length;
455   size_t encoded_string_length;
456
457   u8_string = u8_conv_from_encoding(input_charset,
458                                     iconveh_error,
459                                     input,
460                                     len,
461                                     NULL,
462                                     NULL,
463                                     &u8_string_length);
464   if (NULL == u8_string)
465     {
466       LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "u8_conv_from_encoding");
467       goto fail;
468     }
469   if (0 == strcmp(output_charset, "UTF-8"))
470     {
471       ret = GNUNET_malloc(u8_string_length + 1);
472       GNUNET_memcpy(ret, u8_string, u8_string_length);
473       ret[u8_string_length] = '\0';
474       free(u8_string);
475       return ret;
476     }
477   encoded_string = u8_conv_to_encoding(output_charset,
478                                        iconveh_error,
479                                        u8_string,
480                                        u8_string_length,
481                                        NULL,
482                                        NULL,
483                                        &encoded_string_length);
484   free(u8_string);
485   if (NULL == encoded_string)
486     {
487       LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "u8_conv_to_encoding");
488       goto fail;
489     }
490   ret = GNUNET_malloc(encoded_string_length + 1);
491   GNUNET_memcpy(ret, encoded_string, encoded_string_length);
492   ret[encoded_string_length] = '\0';
493   free(encoded_string);
494   return ret;
495 fail:
496   LOG(GNUNET_ERROR_TYPE_WARNING,
497       _("Character sets requested were `%s'->`%s'\n"),
498       "UTF-8",
499       output_charset);
500   ret = GNUNET_malloc(len + 1);
501   GNUNET_memcpy(ret, input, len);
502   ret[len] = '\0';
503   return ret;
504 }
505
506
507 /**
508  * Convert the len characters long character sequence
509  * given in input that is in the given charset
510  * to UTF-8.
511  *
512  * @param input the input string (not necessarily 0-terminated)
513  * @param len the number of bytes in the @a input
514  * @param charset character set to convert from
515  * @return the converted string (0-terminated),
516  *  if conversion fails, a copy of the orignal
517  *  string is returned.
518  */
519 char *
520 GNUNET_STRINGS_to_utf8(const char *input, size_t len, const char *charset)
521 {
522   return GNUNET_STRINGS_conv(input, len, charset, "UTF-8");
523 }
524
525
526 /**
527  * Convert the len bytes-long UTF-8 string
528  * given in input to the given charset.
529  *
530  * @param input the input string (not necessarily 0-terminated)
531  * @param len the number of bytes in the @a input
532  * @param charset character set to convert to
533  * @return the converted string (0-terminated),
534  *  if conversion fails, a copy of the orignal
535  *  string is returned.
536  */
537 char *
538 GNUNET_STRINGS_from_utf8(const char *input, size_t len, const char *charset)
539 {
540   return GNUNET_STRINGS_conv(input, len, "UTF-8", charset);
541 }
542
543
544 /**
545  * Convert the utf-8 input string to lowercase.
546  * Output needs to be allocated appropriately.
547  *
548  * @param input input string
549  * @param output output buffer
550  */
551 void
552 GNUNET_STRINGS_utf8_tolower(const char *input, char *output)
553 {
554   uint8_t *tmp_in;
555   size_t len;
556
557   tmp_in = u8_tolower((uint8_t *)input,
558                       strlen((char *)input),
559                       NULL,
560                       UNINORM_NFD,
561                       NULL,
562                       &len);
563   GNUNET_memcpy(output, tmp_in, len);
564   output[len] = '\0';
565   free(tmp_in);
566 }
567
568
569 /**
570  * Convert the utf-8 input string to uppercase.
571  * Output needs to be allocated appropriately.
572  *
573  * @param input input string
574  * @param output output buffer
575  */
576 void
577 GNUNET_STRINGS_utf8_toupper(const char *input, char *output)
578 {
579   uint8_t *tmp_in;
580   size_t len;
581
582   tmp_in = u8_toupper((uint8_t *)input,
583                       strlen((char *)input),
584                       NULL,
585                       UNINORM_NFD,
586                       NULL,
587                       &len);
588   GNUNET_memcpy(output, tmp_in, len);
589   output[len] = '\0';
590   free(tmp_in);
591 }
592
593
594 /**
595  * Complete filename (a la shell) from abbrevition.
596  * @param fil the name of the file, may contain ~/ or
597  *        be relative to the current directory
598  * @returns the full file name,
599  *          NULL is returned on error
600  */
601 char *
602 GNUNET_STRINGS_filename_expand(const char *fil)
603 {
604   char *buffer;
605
606 #ifndef MINGW
607   size_t len;
608   char *fm;
609   const char *fil_ptr;
610 #else
611   char *fn;
612   long lRet;
613 #endif
614
615   if (fil == NULL)
616     return NULL;
617
618 #ifndef MINGW
619   if (fil[0] == DIR_SEPARATOR)
620     /* absolute path, just copy */
621     return GNUNET_strdup(fil);
622   if (fil[0] == '~')
623     {
624       fm = getenv("HOME");
625       if (fm == NULL)
626         {
627           LOG(GNUNET_ERROR_TYPE_WARNING,
628               _("Failed to expand `$HOME': environment variable `HOME' not set"));
629           return NULL;
630         }
631       fm = GNUNET_strdup(fm);
632       /* do not copy '~' */
633       fil_ptr = fil + 1;
634
635       /* skip over dir seperator to be consistent */
636       if (fil_ptr[0] == DIR_SEPARATOR)
637         fil_ptr++;
638     }
639   else
640     {
641       /* relative path */
642       fil_ptr = fil;
643       len = 512;
644       fm = NULL;
645       while (1)
646         {
647           buffer = GNUNET_malloc(len);
648           if (getcwd(buffer, len) != NULL)
649             {
650               fm = buffer;
651               break;
652             }
653           if ((errno == ERANGE) && (len < 1024 * 1024 * 4))
654             {
655               len *= 2;
656               GNUNET_free(buffer);
657               continue;
658             }
659           GNUNET_free(buffer);
660           break;
661         }
662       if (fm == NULL)
663         {
664           LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "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] == DIR_SEPARATOR) ? ""
676                   : DIR_SEPARATOR_STR,
677                   fil_ptr);
678   GNUNET_free(fm);
679   return buffer;
680 #else
681   fn = GNUNET_malloc(MAX_PATH + 1);
682
683   if ((lRet = plibc_conv_to_win_path(fil, fn)) != ERROR_SUCCESS)
684     {
685       SetErrnoFromWinError(lRet);
686       LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "plibc_conv_to_win_path");
687       return NULL;
688     }
689   /* is the path relative? */
690   if ((0 != strncmp(fn + 1, ":\\", 2)) && (0 != strncmp(fn, "\\\\", 2)))
691     {
692       char szCurDir[MAX_PATH + 1];
693
694       lRet = GetCurrentDirectory(MAX_PATH + 1, szCurDir);
695       if (lRet + strlen(fn) + 1 > (MAX_PATH + 1))
696         {
697           SetErrnoFromWinError(ERROR_BUFFER_OVERFLOW);
698           LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "GetCurrentDirectory");
699           return NULL;
700         }
701       GNUNET_asprintf(&buffer, "%s\\%s", szCurDir, fn);
702       GNUNET_free(fn);
703       fn = buffer;
704     }
705
706   return fn;
707 #endif
708 }
709
710
711 /**
712  * Give relative time in human-readable fancy format.
713  * This is one of the very few calls in the entire API that is
714  * NOT reentrant!
715  *
716  * @param delta time in milli seconds
717  * @param do_round are we allowed to round a bit?
718  * @return time as human-readable string
719  */
720 const char *
721 GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta,
722                                        int do_round)
723 {
724   static char buf[128];
725   const char *unit = _(/* time unit */ "µs");
726   uint64_t dval = delta.rel_value_us;
727
728   if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == delta.rel_value_us)
729     return _("forever");
730   if (0 == delta.rel_value_us)
731     return _("0 ms");
732   if (((GNUNET_YES == do_round) && (dval > 5 * 1000)) || (0 == (dval % 1000)))
733     {
734       dval = dval / 1000;
735       unit = _(/* time unit */ "ms");
736       if (((GNUNET_YES == do_round) && (dval > 5 * 1000)) || (0 == (dval % 1000)))
737         {
738           dval = dval / 1000;
739           unit = _(/* time unit */ "s");
740           if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
741             {
742               dval = dval / 60;
743               unit = _(/* time unit */ "m");
744               if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
745                 {
746                   dval = dval / 60;
747                   unit = _(/* time unit */ "h");
748                   if (((GNUNET_YES == do_round) && (dval > 5 * 24)) ||
749                       (0 == (dval % 24)))
750                     {
751                       dval = dval / 24;
752                       if (1 == dval)
753                         unit = _(/* time unit */ "day");
754                       else
755                         unit = _(/* time unit */ "days");
756                     }
757                 }
758             }
759         }
760     }
761   GNUNET_snprintf(buf, sizeof(buf), "%llu %s", dval, unit);
762   return buf;
763 }
764
765
766 /**
767  * "asctime", except for GNUnet time.  Converts a GNUnet internal
768  * absolute time (which is in UTC) to a string in local time.
769  * Note that the returned value will be overwritten if this function
770  * is called again.
771  *
772  * @param t the absolute time to convert
773  * @return timestamp in human-readable form in local time
774  */
775 const char *
776 GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
777 {
778   static char buf[255];
779   time_t tt;
780   struct tm *tp;
781
782   if (t.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
783     return _("end of time");
784   tt = t.abs_value_us / 1000LL / 1000LL;
785   tp = localtime(&tt);
786   /* This is hacky, but i don't know a way to detect libc character encoding.
787    * Just expect utf8 from glibc these days.
788    * As for msvcrt, use the wide variant, which always returns utf16
789    * (otherwise we'd have to detect current codepage or use W32API character
790    * set conversion routines to convert to UTF8).
791    */
792 #ifndef WINDOWS
793   strftime(buf, sizeof(buf), "%a %b %d %H:%M:%S %Y", tp);
794 #else
795   {
796     static wchar_t wbuf[255];
797     uint8_t *conved;
798     size_t ssize;
799
800     wcsftime(wbuf,
801              sizeof(wbuf) / sizeof(wchar_t),
802              L"%a %b %d %H:%M:%S %Y",
803              tp);
804
805     ssize = sizeof(buf);
806     conved = u16_to_u8(wbuf,
807                        sizeof(wbuf) / sizeof(wchar_t),
808                        (uint8_t *)buf,
809                        &ssize);
810     if (conved != (uint8_t *)buf)
811       {
812         GNUNET_strlcpy(buf, (char *)conved, sizeof(buf));
813         free(conved);
814       }
815   }
816 #endif
817   return buf;
818 }
819
820
821 /**
822  * "man basename"
823  * Returns a pointer to a part of filename (allocates nothing)!
824  *
825  * @param filename filename to extract basename from
826  * @return short (base) name of the file (that is, everything following the
827  *         last directory separator in filename. If filename ends with a
828  *         directory separator, the result will be a zero-length string.
829  *         If filename has no directory separators, the result is filename
830  *         itself.
831  */
832 const char *
833 GNUNET_STRINGS_get_short_name(const char *filename)
834 {
835   const char *short_fn = filename;
836   const char *ss;
837
838   while (NULL != (ss = strstr(short_fn, DIR_SEPARATOR_STR)) && (ss[1] != '\0'))
839     short_fn = 1 + ss;
840   return short_fn;
841 }
842
843
844 /**
845  * Get the decoded value corresponding to a character according to Crockford
846  * Base32 encoding.
847  *
848  * @param a a character
849  * @return corresponding numeric value
850  */
851 static unsigned int
852 getValue__(unsigned char a)
853 {
854   unsigned int dec;
855
856   switch (a)
857     {
858     case 'O':
859     case 'o':
860       a = '0';
861       break;
862
863     case 'i':
864     case 'I':
865     case 'l':
866     case 'L':
867       a = '1';
868       break;
869
870     /* also consider U to be V */
871     case 'u':
872     case 'U':
873       a = 'V';
874       break;
875
876     default:
877       break;
878     }
879   if ((a >= '0') && (a <= '9'))
880     return a - '0';
881   if ((a >= 'a') && (a <= 'z'))
882     a = toupper(a);
883   /* return (a - 'a' + 10); */
884   dec = 0;
885   if ((a >= 'A') && (a <= 'Z'))
886     {
887       if ('I' < a)
888         dec++;
889       if ('L' < a)
890         dec++;
891       if ('O' < a)
892         dec++;
893       if ('U' < a)
894         dec++;
895       return(a - 'A' + 10 - dec);
896     }
897   return -1;
898 }
899
900
901 /**
902  * Convert binary data to ASCII encoding using Crockford Base32 encoding.
903  * Returns a pointer to the byte after the last byte in the string, that
904  * is where the 0-terminator was placed if there was room.
905  *
906  * @param data data to encode
907  * @param size size of data (in bytes)
908  * @param out buffer to fill
909  * @param out_size size of the buffer. Must be large enough to hold
910  * (size * 8 + 4) / 5 bytes
911  * @return pointer to the next byte in @a out or NULL on error.
912  */
913 char *
914 GNUNET_STRINGS_data_to_string(const void *data,
915                               size_t size,
916                               char *out,
917                               size_t out_size)
918 {
919   /**
920    * 32 characters for encoding
921    */
922   static char *encTable__ = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
923   unsigned int wpos;
924   unsigned int rpos;
925   unsigned int bits;
926   unsigned int vbit;
927   const unsigned char *udata;
928
929   udata = data;
930   if (out_size < (size * 8 + 4) / 5)
931     {
932       GNUNET_break(0);
933       return NULL;
934     }
935   vbit = 0;
936   wpos = 0;
937   rpos = 0;
938   bits = 0;
939   while ((rpos < size) || (vbit > 0))
940     {
941       if ((rpos < size) && (vbit < 5))
942         {
943           bits = (bits << 8) | udata[rpos++]; /* eat 8 more bits */
944           vbit += 8;
945         }
946       if (vbit < 5)
947         {
948           bits <<= (5 - vbit); /* zero-padding */
949           GNUNET_assert(vbit == ((size * 8) % 5));
950           vbit = 5;
951         }
952       if (wpos >= out_size)
953         {
954           GNUNET_break(0);
955           return NULL;
956         }
957       out[wpos++] = encTable__[(bits >> (vbit - 5)) & 31];
958       vbit -= 5;
959     }
960   GNUNET_assert(0 == vbit);
961   if (wpos < out_size)
962     out[wpos] = '\0';
963   return &out[wpos];
964 }
965
966
967 /**
968  * Return the base32crockford encoding of the given buffer.
969  *
970  * The returned string will be freshly allocated, and must be free'd
971  * with GNUNET_free().
972  *
973  * @param buffer with data
974  * @param size size of the buffer
975  * @return freshly allocated, null-terminated string
976  */
977 char *
978 GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
979 {
980   char *str_buf;
981   size_t len = size * 8;
982   char *end;
983
984   if (len % 5 > 0)
985     len += 5 - len % 5;
986   len /= 5;
987   str_buf = GNUNET_malloc(len + 1);
988   end = GNUNET_STRINGS_data_to_string(buf, size, str_buf, len);
989   if (NULL == end)
990     {
991       GNUNET_free(str_buf);
992       return NULL;
993     }
994   *end = '\0';
995   return str_buf;
996 }
997
998
999 /**
1000  * Convert Crockford Base32hex encoding back to data.
1001  * @a out_size must match exactly the size of the data before it was encoded.
1002  *
1003  * @param enc the encoding
1004  * @param enclen number of characters in @a enc (without 0-terminator, which can be missing)
1005  * @param out location where to store the decoded data
1006  * @param out_size size of the output buffer @a out
1007  * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding
1008  */
1009 int
1010 GNUNET_STRINGS_string_to_data(const char *enc,
1011                               size_t enclen,
1012                               void *out,
1013                               size_t out_size)
1014 {
1015   unsigned int rpos;
1016   unsigned int wpos;
1017   unsigned int bits;
1018   unsigned int vbit;
1019   int ret;
1020   int shift;
1021   unsigned char *uout;
1022   unsigned int encoded_len = out_size * 8;
1023
1024   if (0 == enclen)
1025     {
1026       if (0 == out_size)
1027         return GNUNET_OK;
1028       return GNUNET_SYSERR;
1029     }
1030   uout = out;
1031   wpos = out_size;
1032   rpos = enclen;
1033   if ((encoded_len % 5) > 0)
1034     {
1035       vbit = encoded_len % 5; /* padding! */
1036       shift = 5 - vbit;
1037       bits = (ret = getValue__(enc[--rpos])) >> shift;
1038     }
1039   else
1040     {
1041       vbit = 5;
1042       shift = 0;
1043       bits = (ret = getValue__(enc[--rpos]));
1044     }
1045   if ((encoded_len + shift) / 5 != enclen)
1046     return GNUNET_SYSERR;
1047   if (-1 == ret)
1048     return GNUNET_SYSERR;
1049   while (wpos > 0)
1050     {
1051       if (0 == rpos)
1052         {
1053           GNUNET_break(0);
1054           return GNUNET_SYSERR;
1055         }
1056       bits = ((ret = getValue__(enc[--rpos])) << vbit) | bits;
1057       if (-1 == ret)
1058         return GNUNET_SYSERR;
1059       vbit += 5;
1060       if (vbit >= 8)
1061         {
1062           uout[--wpos] = (unsigned char)bits;
1063           bits >>= 8;
1064           vbit -= 8;
1065         }
1066     }
1067   if ((0 != rpos) || (0 != vbit))
1068     return GNUNET_SYSERR;
1069   return GNUNET_OK;
1070 }
1071
1072
1073 /**
1074  * Parse a path that might be an URI.
1075  *
1076  * @param path path to parse. Must be NULL-terminated.
1077  * @param scheme_part a pointer to 'char *' where a pointer to a string that
1078  *        represents the URI scheme will be stored. Can be NULL. The string is
1079  *        allocated by the function, and should be freed by GNUNET_free() when
1080  *        it is no longer needed.
1081  * @param path_part a pointer to 'const char *' where a pointer to the path
1082  *        part of the URI will be stored. Can be NULL. Points to the same block
1083  *        of memory as 'path', and thus must not be freed. Might point to '\0',
1084  *        if path part is zero-length.
1085  * @return GNUNET_YES if it's an URI, GNUNET_NO otherwise. If 'path' is not
1086  *         an URI, '* scheme_part' and '*path_part' will remain unchanged
1087  *         (if they weren't NULL).
1088  */
1089 int
1090 GNUNET_STRINGS_parse_uri(const char *path,
1091                          char **scheme_part,
1092                          const char **path_part)
1093 {
1094   size_t len;
1095   size_t i;
1096   int end;
1097   int pp_state = 0;
1098   const char *post_scheme_part = NULL;
1099
1100   len = strlen(path);
1101   for (end = 0, i = 0; !end && i < len; i++)
1102     {
1103       switch (pp_state)
1104         {
1105         case 0:
1106           if ((path[i] == ':') && (i > 0))
1107             {
1108               pp_state += 1;
1109               continue;
1110             }
1111           if (!((path[i] >= 'A' && path[i] <= 'Z') ||
1112                 (path[i] >= 'a' && path[i] <= 'z') ||
1113                 (path[i] >= '0' && path[i] <= '9') || path[i] == '+' ||
1114                 path[i] == '-' || (path[i] == '.')))
1115             end = 1;
1116           break;
1117
1118         case 1:
1119         case 2:
1120           if (path[i] == '/')
1121             {
1122               pp_state += 1;
1123               continue;
1124             }
1125           end = 1;
1126           break;
1127
1128         case 3:
1129           post_scheme_part = &path[i];
1130           end = 1;
1131           break;
1132
1133         default:
1134           end = 1;
1135         }
1136     }
1137   if (post_scheme_part == NULL)
1138     return GNUNET_NO;
1139   if (scheme_part)
1140     {
1141       *scheme_part = GNUNET_malloc(post_scheme_part - path + 1);
1142       GNUNET_memcpy(*scheme_part, path, post_scheme_part - path);
1143       (*scheme_part)[post_scheme_part - path] = '\0';
1144     }
1145   if (path_part)
1146     *path_part = post_scheme_part;
1147   return GNUNET_YES;
1148 }
1149
1150
1151 /**
1152  * Check whether @a filename is absolute or not, and if it's an URI
1153  *
1154  * @param filename filename to check
1155  * @param can_be_uri #GNUNET_YES to check for being URI, #GNUNET_NO - to
1156  *        assume it's not URI
1157  * @param r_is_uri a pointer to an int that is set to #GNUNET_YES if @a filename
1158  *        is URI and to #GNUNET_NO otherwise. Can be NULL. If @a can_be_uri is
1159  *        not #GNUNET_YES, `* r_is_uri` is set to #GNUNET_NO.
1160  * @param r_uri_scheme a pointer to a char * that is set to a pointer to URI scheme.
1161  *        The string is allocated by the function, and should be freed with
1162  *        GNUNET_free(). Can be NULL.
1163  * @return #GNUNET_YES if @a filename is absolute, #GNUNET_NO otherwise.
1164  */
1165 int
1166 GNUNET_STRINGS_path_is_absolute(const char *filename,
1167                                 int can_be_uri,
1168                                 int *r_is_uri,
1169                                 char **r_uri_scheme)
1170 {
1171 #if WINDOWS
1172   size_t len;
1173 #endif
1174   const char *post_scheme_path;
1175   int is_uri;
1176   char *uri;
1177   /* consider POSIX paths to be absolute too, even on W32,
1178    * as plibc expansion will fix them for us.
1179    */
1180   if (filename[0] == '/')
1181     return GNUNET_YES;
1182   if (can_be_uri)
1183     {
1184       is_uri = GNUNET_STRINGS_parse_uri(filename, &uri, &post_scheme_path);
1185       if (r_is_uri)
1186         *r_is_uri = is_uri;
1187       if (is_uri)
1188         {
1189           if (r_uri_scheme)
1190             *r_uri_scheme = uri;
1191           else
1192             GNUNET_free_non_null(uri);
1193 #if WINDOWS
1194           len = strlen(post_scheme_path);
1195           /* Special check for file:///c:/blah
1196            * We want to parse 'c:/', not '/c:/'
1197            */
1198           if (post_scheme_path[0] == '/' && len >= 3 && post_scheme_path[2] == ':')
1199             post_scheme_path = &post_scheme_path[1];
1200 #endif
1201           return GNUNET_STRINGS_path_is_absolute(post_scheme_path,
1202                                                  GNUNET_NO,
1203                                                  NULL,
1204                                                  NULL);
1205         }
1206     }
1207   else
1208     {
1209       if (r_is_uri)
1210         *r_is_uri = GNUNET_NO;
1211     }
1212 #if WINDOWS
1213   len = strlen(filename);
1214   if (len >= 3 &&
1215       ((filename[0] >= 'A' && filename[0] <= 'Z') ||
1216        (filename[0] >= 'a' && filename[0] <= 'z')) &&
1217       filename[1] == ':' && (filename[2] == '/' || filename[2] == '\\'))
1218     return GNUNET_YES;
1219 #endif
1220   return GNUNET_NO;
1221 }
1222
1223 #if MINGW
1224 #define _IFMT 0170000 /* type of file */
1225 #define _IFLNK 0120000 /* symbolic link */
1226 #define S_ISLNK(m) (((m) & _IFMT) == _IFLNK)
1227 #endif
1228
1229
1230 /**
1231  * Perform @a checks on @a filename.
1232  *
1233  * @param filename file to check
1234  * @param checks checks to perform
1235  * @return #GNUNET_YES if all checks pass, #GNUNET_NO if at least one of them
1236  *         fails, #GNUNET_SYSERR when a check can't be performed
1237  */
1238 int
1239 GNUNET_STRINGS_check_filename(const char *filename,
1240                               enum GNUNET_STRINGS_FilenameCheck checks)
1241 {
1242   struct stat st;
1243
1244   if ((NULL == filename) || (filename[0] == '\0'))
1245     return GNUNET_SYSERR;
1246   if (0 != (checks & GNUNET_STRINGS_CHECK_IS_ABSOLUTE))
1247     if (!GNUNET_STRINGS_path_is_absolute(filename, GNUNET_NO, NULL, NULL))
1248       return GNUNET_NO;
1249   if (0 != (checks &
1250             (GNUNET_STRINGS_CHECK_EXISTS | GNUNET_STRINGS_CHECK_IS_DIRECTORY |
1251              GNUNET_STRINGS_CHECK_IS_LINK)))
1252     {
1253       if (0 != stat(filename, &st))
1254         {
1255           if (0 != (checks & GNUNET_STRINGS_CHECK_EXISTS))
1256             return GNUNET_NO;
1257           else
1258             return GNUNET_SYSERR;
1259         }
1260     }
1261   if (0 != (checks & GNUNET_STRINGS_CHECK_IS_DIRECTORY))
1262     if (!S_ISDIR(st.st_mode))
1263       return GNUNET_NO;
1264   if (0 != (checks & GNUNET_STRINGS_CHECK_IS_LINK))
1265     if (!S_ISLNK(st.st_mode))
1266       return GNUNET_NO;
1267   return GNUNET_YES;
1268 }
1269
1270
1271 /**
1272  * Tries to convert @a zt_addr string to an IPv6 address.
1273  * The string is expected to have the format "[ABCD::01]:80".
1274  *
1275  * @param zt_addr 0-terminated string. May be mangled by the function.
1276  * @param addrlen length of @a zt_addr (not counting 0-terminator).
1277  * @param r_buf a buffer to fill. Initially gets filled with zeroes,
1278  *        then its sin6_port, sin6_family and sin6_addr are set appropriately.
1279  * @return #GNUNET_OK if conversion succeded.
1280  *         #GNUNET_SYSERR otherwise, in which
1281  *         case the contents of @a r_buf are undefined.
1282  */
1283 int
1284 GNUNET_STRINGS_to_address_ipv6(const char *zt_addr,
1285                                uint16_t addrlen,
1286                                struct sockaddr_in6 *r_buf)
1287 {
1288   char zbuf[addrlen + 1];
1289   int ret;
1290   char *port_colon;
1291   unsigned int port;
1292   char dummy[2];
1293
1294   if (addrlen < 6)
1295     return GNUNET_SYSERR;
1296   GNUNET_memcpy(zbuf, zt_addr, addrlen);
1297   if ('[' != zbuf[0])
1298     {
1299       GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1300                  _("IPv6 address did not start with `['\n"));
1301       return GNUNET_SYSERR;
1302     }
1303   zbuf[addrlen] = '\0';
1304   port_colon = strrchr(zbuf, ':');
1305   if (NULL == port_colon)
1306     {
1307       GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1308                  _("IPv6 address did contain ':' to separate port number\n"));
1309       return GNUNET_SYSERR;
1310     }
1311   if (']' != *(port_colon - 1))
1312     {
1313       GNUNET_log(
1314         GNUNET_ERROR_TYPE_WARNING,
1315         _("IPv6 address did contain ']' before ':' to separate port number\n"));
1316       return GNUNET_SYSERR;
1317     }
1318   ret = sscanf(port_colon, ":%u%1s", &port, dummy);
1319   if ((1 != ret) || (port > 65535))
1320     {
1321       GNUNET_log(
1322         GNUNET_ERROR_TYPE_WARNING,
1323         _("IPv6 address did contain a valid port number after the last ':'\n"));
1324       return GNUNET_SYSERR;
1325     }
1326   *(port_colon - 1) = '\0';
1327   memset(r_buf, 0, sizeof(struct sockaddr_in6));
1328   ret = inet_pton(AF_INET6, &zbuf[1], &r_buf->sin6_addr);
1329   if (ret <= 0)
1330     {
1331       GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1332                  _("Invalid IPv6 address `%s': %s\n"),
1333                  &zbuf[1],
1334                  strerror(errno));
1335       return GNUNET_SYSERR;
1336     }
1337   r_buf->sin6_port = htons(port);
1338   r_buf->sin6_family = AF_INET6;
1339 #if HAVE_SOCKADDR_IN_SIN_LEN
1340   r_buf->sin6_len = (u_char)sizeof(struct sockaddr_in6);
1341 #endif
1342   return GNUNET_OK;
1343 }
1344
1345
1346 /**
1347  * Tries to convert 'zt_addr' string to an IPv4 address.
1348  * The string is expected to have the format "1.2.3.4:80".
1349  *
1350  * @param zt_addr 0-terminated string. May be mangled by the function.
1351  * @param addrlen length of @a zt_addr (not counting 0-terminator).
1352  * @param r_buf a buffer to fill.
1353  * @return #GNUNET_OK if conversion succeded.
1354  *         #GNUNET_SYSERR otherwise, in which case
1355  *         the contents of @a r_buf are undefined.
1356  */
1357 int
1358 GNUNET_STRINGS_to_address_ipv4(const char *zt_addr,
1359                                uint16_t addrlen,
1360                                struct sockaddr_in *r_buf)
1361 {
1362   unsigned int temps[4];
1363   unsigned int port;
1364   unsigned int cnt;
1365   char dummy[2];
1366
1367   if (addrlen < 9)
1368     return GNUNET_SYSERR;
1369   cnt = sscanf(zt_addr,
1370                "%u.%u.%u.%u:%u%1s",
1371                &temps[0],
1372                &temps[1],
1373                &temps[2],
1374                &temps[3],
1375                &port,
1376                dummy);
1377   if (5 != cnt)
1378     return GNUNET_SYSERR;
1379   for (cnt = 0; cnt < 4; cnt++)
1380     if (temps[cnt] > 0xFF)
1381       return GNUNET_SYSERR;
1382   if (port > 65535)
1383     return GNUNET_SYSERR;
1384   r_buf->sin_family = AF_INET;
1385   r_buf->sin_port = htons(port);
1386   r_buf->sin_addr.s_addr =
1387     htonl((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + temps[3]);
1388 #if HAVE_SOCKADDR_IN_SIN_LEN
1389   r_buf->sin_len = (u_char)sizeof(struct sockaddr_in);
1390 #endif
1391   return GNUNET_OK;
1392 }
1393
1394
1395 /**
1396  * Tries to convert @a addr string to an IP (v4 or v6) address.
1397  * Will automatically decide whether to treat 'addr' as v4 or v6 address.
1398  *
1399  * @param addr a string, may not be 0-terminated.
1400  * @param addrlen number of bytes in @a addr (if addr is 0-terminated,
1401  *        0-terminator should not be counted towards addrlen).
1402  * @param r_buf a buffer to fill.
1403  * @return #GNUNET_OK if conversion succeded. #GNUNET_SYSERR otherwise, in which
1404  *         case the contents of @a r_buf are undefined.
1405  */
1406 int
1407 GNUNET_STRINGS_to_address_ip(const char *addr,
1408                              uint16_t addrlen,
1409                              struct sockaddr_storage *r_buf)
1410 {
1411   if (addr[0] == '[')
1412     return GNUNET_STRINGS_to_address_ipv6(addr,
1413                                           addrlen,
1414                                           (struct sockaddr_in6 *)r_buf);
1415   return GNUNET_STRINGS_to_address_ipv4(addr,
1416                                         addrlen,
1417                                         (struct sockaddr_in *)r_buf);
1418 }
1419
1420
1421 /**
1422  * Parse an address given as a string into a
1423  * `struct sockaddr`.
1424  *
1425  * @param addr the address
1426  * @param[out] af set to the parsed address family (i.e. AF_INET)
1427  * @param[out] sa set to the parsed address
1428  * @return 0 on error, otherwise number of bytes in @a sa
1429  */
1430 size_t
1431 GNUNET_STRINGS_parse_socket_addr(const char *addr,
1432                                  uint8_t *af,
1433                                  struct sockaddr **sa)
1434 {
1435   char *cp = GNUNET_strdup(addr);
1436
1437   *af = AF_UNSPEC;
1438   if ('[' == *addr)
1439     {
1440       /* IPv6 */
1441       *sa = GNUNET_malloc(sizeof(struct sockaddr_in6));
1442       if (GNUNET_OK !=
1443           GNUNET_STRINGS_to_address_ipv6(cp,
1444                                          strlen(cp),
1445                                          (struct sockaddr_in6 *)*sa))
1446         {
1447           GNUNET_free(*sa);
1448           *sa = NULL;
1449           GNUNET_free(cp);
1450           return 0;
1451         }
1452       *af = AF_INET6;
1453       GNUNET_free(cp);
1454       return sizeof(struct sockaddr_in6);
1455     }
1456   else
1457     {
1458       /* IPv4 */
1459       *sa = GNUNET_malloc(sizeof(struct sockaddr_in));
1460       if (GNUNET_OK !=
1461           GNUNET_STRINGS_to_address_ipv4(cp,
1462                                          strlen(cp),
1463                                          (struct sockaddr_in *)*sa))
1464         {
1465           GNUNET_free(*sa);
1466           *sa = NULL;
1467           GNUNET_free(cp);
1468           return 0;
1469         }
1470       *af = AF_INET;
1471       GNUNET_free(cp);
1472       return sizeof(struct sockaddr_in);
1473     }
1474 }
1475
1476
1477 /**
1478  * Makes a copy of argv that consists of a single memory chunk that can be
1479  * freed with a single call to GNUNET_free();
1480  */
1481 static char *const *
1482 _make_continuous_arg_copy(int argc, char *const *argv)
1483 {
1484   size_t argvsize = 0;
1485   int i;
1486   char **new_argv;
1487   char *p;
1488
1489   for (i = 0; i < argc; i++)
1490     argvsize += strlen(argv[i]) + 1 + sizeof(char *);
1491   new_argv = GNUNET_malloc(argvsize + sizeof(char *));
1492   p = (char *)&new_argv[argc + 1];
1493   for (i = 0; i < argc; i++)
1494     {
1495       new_argv[i] = p;
1496       strcpy(p, argv[i]);
1497       p += strlen(argv[i]) + 1;
1498     }
1499   new_argv[argc] = NULL;
1500   return (char *const *)new_argv;
1501 }
1502
1503
1504 /**
1505  * Returns utf-8 encoded arguments.
1506  * Does nothing (returns a copy of argc and argv) on any platform
1507  * other than W32.
1508  * Returned argv has u8argv[u8argc] == NULL.
1509  * Returned argv is a single memory block, and can be freed with a single
1510  *   GNUNET_free() call.
1511  *
1512  * @param argc argc (as given by main())
1513  * @param argv argv (as given by main())
1514  * @param u8argc a location to store new argc in (though it's th same as argc)
1515  * @param u8argv a location to store new argv in
1516  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1517  */
1518 int
1519 GNUNET_STRINGS_get_utf8_args(int argc,
1520                              char *const *argv,
1521                              int *u8argc,
1522                              char *const **u8argv)
1523 {
1524 #if WINDOWS
1525   wchar_t *wcmd;
1526   wchar_t **wargv;
1527   int wargc;
1528   int i;
1529   char **split_u8argv;
1530
1531   wcmd = GetCommandLineW();
1532   if (NULL == wcmd)
1533     return GNUNET_SYSERR;
1534   wargv = CommandLineToArgvW(wcmd, &wargc);
1535   if (NULL == wargv)
1536     return GNUNET_SYSERR;
1537
1538   split_u8argv = GNUNET_malloc(argc * sizeof(char *));
1539
1540   for (i = 0; i < wargc; i++)
1541     {
1542       size_t strl;
1543       /* Hopefully it will allocate us NUL-terminated strings... */
1544       split_u8argv[i] =
1545         (char *)u16_to_u8(wargv[i], wcslen(wargv[i]) + 1, NULL, &strl);
1546       if (NULL == split_u8argv[i])
1547         {
1548           int j;
1549           for (j = 0; j < i; j++)
1550             free(split_u8argv[j]);
1551           GNUNET_free(split_u8argv);
1552           LocalFree(wargv);
1553           return GNUNET_SYSERR;
1554         }
1555     }
1556
1557   *u8argv = _make_continuous_arg_copy(wargc, split_u8argv);
1558   *u8argc = wargc;
1559
1560   for (i = 0; i < wargc; i++)
1561     free(split_u8argv[i]);
1562   free(split_u8argv);
1563   return GNUNET_OK;
1564 #else
1565   char *const *new_argv =
1566     (char *const *)_make_continuous_arg_copy(argc, argv);
1567   *u8argv = new_argv;
1568   *u8argc = argc;
1569   return GNUNET_OK;
1570 #endif
1571 }
1572
1573
1574 /**
1575  * Parse the given port policy.  The format is
1576  * "[!]SPORT[-DPORT]".
1577  *
1578  * @param port_policy string to parse
1579  * @param pp policy to fill in
1580  * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
1581  *         @a port_policy is malformed
1582  */
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     {
1595       pp->negate_portrange = GNUNET_YES;
1596       pos++;
1597     }
1598   if (2 == sscanf(pos, "%u-%u%1s", &s, &e, eol))
1599     {
1600       if ((0 == s) || (s > 0xFFFF) || (e < s) || (e > 0xFFFF))
1601         {
1602           GNUNET_log(GNUNET_ERROR_TYPE_WARNING, _("Port not in range\n"));
1603           return GNUNET_SYSERR;
1604         }
1605       pp->start_port = (uint16_t)s;
1606       pp->end_port = (uint16_t)e;
1607       return GNUNET_OK;
1608     }
1609   if (1 == sscanf(pos, "%u%1s", &s, eol))
1610     {
1611       if ((0 == s) || (s > 0xFFFF))
1612         {
1613           GNUNET_log(GNUNET_ERROR_TYPE_WARNING, _("Port not in range\n"));
1614           return GNUNET_SYSERR;
1615         }
1616
1617       pp->start_port = (uint16_t)s;
1618       pp->end_port = (uint16_t)s;
1619       return GNUNET_OK;
1620     }
1621   GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1622              _("Malformed port policy `%s'\n"),
1623              port_policy);
1624   return GNUNET_SYSERR;
1625 }
1626
1627
1628 /**
1629  * Parse an IPv4 network policy. The argument specifies a list of
1630  * subnets. The format is
1631  * <tt>(network[/netmask][:SPORT[-DPORT]];)*</tt> (no whitespace, must
1632  * be terminated with a semicolon). The network must be given in
1633  * dotted-decimal notation. The netmask can be given in CIDR notation
1634  * (/16) or in dotted-decimal (/255.255.0.0).
1635  *
1636  * @param routeListX a string specifying the IPv4 subnets
1637  * @return the converted list, terminated with all zeros;
1638  *         NULL if the synatx is flawed
1639  */
1640 struct GNUNET_STRINGS_IPv4NetworkPolicy *
1641 GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
1642 {
1643   unsigned int count;
1644   unsigned int i;
1645   unsigned int j;
1646   unsigned int len;
1647   int cnt;
1648   unsigned int pos;
1649   unsigned int temps[8];
1650   int slash;
1651   struct GNUNET_STRINGS_IPv4NetworkPolicy *result;
1652   int colon;
1653   int end;
1654   char *routeList;
1655   char dummy[2];
1656
1657   if (NULL == routeListX)
1658     return NULL;
1659   len = strlen(routeListX);
1660   if (0 == len)
1661     return NULL;
1662   routeList = GNUNET_strdup(routeListX);
1663   count = 0;
1664   for (i = 0; i < len; i++)
1665     if (routeList[i] == ';')
1666       count++;
1667   result = GNUNET_malloc(sizeof(struct GNUNET_STRINGS_IPv4NetworkPolicy) *
1668                          (count + 1));
1669   i = 0;
1670   pos = 0;
1671   while (i < count)
1672     {
1673       for (colon = pos; ':' != routeList[colon]; colon++)
1674         if ((';' == routeList[colon]) || ('\0' == routeList[colon]))
1675           break;
1676       for (end = colon; ';' != routeList[end]; end++)
1677         if ('\0' == routeList[end])
1678           break;
1679       if ('\0' == routeList[end])
1680         break;
1681       routeList[end] = '\0';
1682       if (':' == routeList[colon])
1683         {
1684           routeList[colon] = '\0';
1685           if (GNUNET_OK != parse_port_policy(&routeList[colon + 1], &result[i].pp))
1686             break;
1687         }
1688       cnt = sscanf(&routeList[pos],
1689                    "%u.%u.%u.%u/%u.%u.%u.%u%1s",
1690                    &temps[0],
1691                    &temps[1],
1692                    &temps[2],
1693                    &temps[3],
1694                    &temps[4],
1695                    &temps[5],
1696                    &temps[6],
1697                    &temps[7],
1698                    dummy);
1699       if (8 == cnt)
1700         {
1701           for (j = 0; j < 8; j++)
1702             if (temps[j] > 0xFF)
1703               {
1704                 LOG(GNUNET_ERROR_TYPE_WARNING,
1705                     _("Invalid format for IP: `%s'\n"),
1706                     &routeList[pos]);
1707                 GNUNET_free(result);
1708                 GNUNET_free(routeList);
1709                 return NULL;
1710               }
1711           result[i].network.s_addr = htonl((temps[0] << 24) + (temps[1] << 16) +
1712                                            (temps[2] << 8) + temps[3]);
1713           result[i].netmask.s_addr = htonl((temps[4] << 24) + (temps[5] << 16) +
1714                                            (temps[6] << 8) + temps[7]);
1715           pos = end + 1;
1716           i++;
1717           continue;
1718         }
1719       /* try second notation */
1720       cnt = sscanf(&routeList[pos],
1721                    "%u.%u.%u.%u/%u%1s",
1722                    &temps[0],
1723                    &temps[1],
1724                    &temps[2],
1725                    &temps[3],
1726                    &slash,
1727                    dummy);
1728       if (5 == cnt)
1729         {
1730           for (j = 0; j < 4; j++)
1731             if (temps[j] > 0xFF)
1732               {
1733                 LOG(GNUNET_ERROR_TYPE_WARNING,
1734                     _("Invalid format for IP: `%s'\n"),
1735                     &routeList[pos]);
1736                 GNUNET_free(result);
1737                 GNUNET_free(routeList);
1738                 return NULL;
1739               }
1740           result[i].network.s_addr = htonl((temps[0] << 24) + (temps[1] << 16) +
1741                                            (temps[2] << 8) + temps[3]);
1742           if ((slash <= 32) && (slash >= 0))
1743             {
1744               result[i].netmask.s_addr = 0;
1745               while (slash > 0)
1746                 {
1747                   result[i].netmask.s_addr =
1748                     (result[i].netmask.s_addr >> 1) + 0x80000000;
1749                   slash--;
1750                 }
1751               result[i].netmask.s_addr = htonl(result[i].netmask.s_addr);
1752               pos = end + 1;
1753               i++;
1754               continue;
1755             }
1756           else
1757             {
1758               LOG(GNUNET_ERROR_TYPE_WARNING,
1759                   _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
1760                   slash);
1761               GNUNET_free(result);
1762               GNUNET_free(routeList);
1763               return NULL; /* error */
1764             }
1765         }
1766       /* try third notation */
1767       slash = 32;
1768       cnt = sscanf(&routeList[pos],
1769                    "%u.%u.%u.%u%1s",
1770                    &temps[0],
1771                    &temps[1],
1772                    &temps[2],
1773                    &temps[3],
1774                    dummy);
1775       if (4 == cnt)
1776         {
1777           for (j = 0; j < 4; j++)
1778             if (temps[j] > 0xFF)
1779               {
1780                 LOG(GNUNET_ERROR_TYPE_WARNING,
1781                     _("Invalid format for IP: `%s'\n"),
1782                     &routeList[pos]);
1783                 GNUNET_free(result);
1784                 GNUNET_free(routeList);
1785                 return NULL;
1786               }
1787           result[i].network.s_addr = htonl((temps[0] << 24) + (temps[1] << 16) +
1788                                            (temps[2] << 8) + temps[3]);
1789           result[i].netmask.s_addr = 0;
1790           while (slash > 0)
1791             {
1792               result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000;
1793               slash--;
1794             }
1795           result[i].netmask.s_addr = htonl(result[i].netmask.s_addr);
1796           pos = end + 1;
1797           i++;
1798           continue;
1799         }
1800       LOG(GNUNET_ERROR_TYPE_WARNING,
1801           _("Invalid format for IP: `%s'\n"),
1802           &routeList[pos]);
1803       GNUNET_free(result);
1804       GNUNET_free(routeList);
1805       return NULL; /* error */
1806     }
1807   if (pos < strlen(routeList))
1808     {
1809       LOG(GNUNET_ERROR_TYPE_WARNING,
1810           _("Invalid format: `%s'\n"),
1811           &routeListX[pos]);
1812       GNUNET_free(result);
1813       GNUNET_free(routeList);
1814       return NULL; /* oops */
1815     }
1816   GNUNET_free(routeList);
1817   return result; /* ok */
1818 }
1819
1820
1821 /**
1822  * Parse an IPv6 network policy. The argument specifies a list of
1823  * subnets. The format is <tt>(network[/netmask[:SPORT[-DPORT]]];)*</tt>
1824  * (no whitespace, must be terminated with a semicolon). The network
1825  * must be given in colon-hex notation.  The netmask must be given in
1826  * CIDR notation (/16) or can be omitted to specify a single host.
1827  * Note that the netmask is mandatory if ports are specified.
1828  *
1829  * @param routeListX a string specifying the policy
1830  * @return the converted list, 0-terminated, NULL if the synatx is flawed
1831  */
1832 struct GNUNET_STRINGS_IPv6NetworkPolicy *
1833 GNUNET_STRINGS_parse_ipv6_policy(const char *routeListX)
1834 {
1835   unsigned int count;
1836   unsigned int i;
1837   unsigned int len;
1838   unsigned int pos;
1839   int start;
1840   int slash;
1841   int ret;
1842   char *routeList;
1843   struct GNUNET_STRINGS_IPv6NetworkPolicy *result;
1844   unsigned int bits;
1845   unsigned int off;
1846   int save;
1847   int colon;
1848   char dummy[2];
1849
1850   if (NULL == routeListX)
1851     return NULL;
1852   len = strlen(routeListX);
1853   if (0 == len)
1854     return NULL;
1855   routeList = GNUNET_strdup(routeListX);
1856   count = 0;
1857   for (i = 0; i < len; i++)
1858     if (';' == routeList[i])
1859       count++;
1860   if (';' != routeList[len - 1])
1861     {
1862       LOG(GNUNET_ERROR_TYPE_WARNING,
1863           _("Invalid network notation (does not end with ';': `%s')\n"),
1864           routeList);
1865       GNUNET_free(routeList);
1866       return NULL;
1867     }
1868
1869   result = GNUNET_malloc(sizeof(struct GNUNET_STRINGS_IPv6NetworkPolicy) *
1870                          (count + 1));
1871   i = 0;
1872   pos = 0;
1873   while (i < count)
1874     {
1875       start = pos;
1876       while (';' != routeList[pos])
1877         pos++;
1878       slash = pos;
1879       while ((slash >= start) && (routeList[slash] != '/'))
1880         slash--;
1881
1882       if (slash < start)
1883         {
1884           memset(&result[i].netmask, 0xFF, sizeof(struct in6_addr));
1885           slash = pos;
1886         }
1887       else
1888         {
1889           routeList[pos] = '\0';
1890           for (colon = pos; ':' != routeList[colon]; colon--)
1891             if ('/' == routeList[colon])
1892               break;
1893           if (':' == routeList[colon])
1894             {
1895               routeList[colon] = '\0';
1896               if (GNUNET_OK !=
1897                   parse_port_policy(&routeList[colon + 1], &result[i].pp))
1898                 {
1899                   GNUNET_free(result);
1900                   GNUNET_free(routeList);
1901                   return NULL;
1902                 }
1903             }
1904           ret = inet_pton(AF_INET6, &routeList[slash + 1], &result[i].netmask);
1905           if (ret <= 0)
1906             {
1907               save = errno;
1908               if ((1 != sscanf(&routeList[slash + 1], "%u%1s", &bits, dummy)) ||
1909                   (bits > 128))
1910                 {
1911                   if (0 == ret)
1912                     LOG(GNUNET_ERROR_TYPE_WARNING,
1913                         _("Wrong format `%s' for netmask\n"),
1914                         &routeList[slash + 1]);
1915                   else
1916                     {
1917                       errno = save;
1918                       LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "inet_pton");
1919                     }
1920                   GNUNET_free(result);
1921                   GNUNET_free(routeList);
1922                   return NULL;
1923                 }
1924               off = 0;
1925               while (bits > 8)
1926                 {
1927                   result[i].netmask.s6_addr[off++] = 0xFF;
1928                   bits -= 8;
1929                 }
1930               while (bits > 0)
1931                 {
1932                   result[i].netmask.s6_addr[off] =
1933                     (result[i].netmask.s6_addr[off] >> 1) + 0x80;
1934                   bits--;
1935                 }
1936             }
1937         }
1938       routeList[slash] = '\0';
1939       ret = inet_pton(AF_INET6, &routeList[start], &result[i].network);
1940       if (ret <= 0)
1941         {
1942           if (0 == ret)
1943             LOG(GNUNET_ERROR_TYPE_WARNING,
1944                 _("Wrong format `%s' for network\n"),
1945                 &routeList[slash + 1]);
1946           else
1947             LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "inet_pton");
1948           GNUNET_free(result);
1949           GNUNET_free(routeList);
1950           return NULL;
1951         }
1952       pos++;
1953       i++;
1954     }
1955   GNUNET_free(routeList);
1956   return result;
1957 }
1958
1959
1960 /** ******************** Base64 encoding ***********/
1961
1962 #define FILLCHAR '='
1963 static char *cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1964                    "abcdefghijklmnopqrstuvwxyz"
1965                    "0123456789+/";
1966
1967
1968 /**
1969  * Encode into Base64.
1970  *
1971  * @param in the data to encode
1972  * @param len the length of the input
1973  * @param output where to write the output (*output should be NULL,
1974  *   is allocated)
1975  * @return the size of the output
1976  */
1977 size_t
1978 GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
1979 {
1980   const char *data = in;
1981   size_t ret;
1982   char *opt;
1983
1984   ret = 0;
1985   opt = GNUNET_malloc(2 + (len * 4 / 3) + 8);
1986   for (size_t i = 0; i < len; ++i)
1987     {
1988       char c;
1989
1990       c = (data[i] >> 2) & 0x3f;
1991       opt[ret++] = cvt[(int)c];
1992       c = (data[i] << 4) & 0x3f;
1993       if (++i < len)
1994         c |= (data[i] >> 4) & 0x0f;
1995       opt[ret++] = cvt[(int)c];
1996       if (i < len)
1997         {
1998           c = (data[i] << 2) & 0x3f;
1999           if (++i < len)
2000             c |= (data[i] >> 6) & 0x03;
2001           opt[ret++] = cvt[(int)c];
2002         }
2003       else
2004         {
2005           ++i;
2006           opt[ret++] = FILLCHAR;
2007         }
2008       if (i < len)
2009         {
2010           c = data[i] & 0x3f;
2011           opt[ret++] = cvt[(int)c];
2012         }
2013       else
2014         {
2015           opt[ret++] = FILLCHAR;
2016         }
2017     }
2018   *output = opt;
2019   return ret;
2020 }
2021
2022 #define cvtfind(a)                        \
2023   ((((a) >= 'A') && ((a) <= 'Z'))         \
2024    ? (a) - 'A'                          \
2025    : (((a) >= 'a') && ((a) <= 'z'))     \
2026    ? (a) - 'a' + 26                 \
2027    : (((a) >= '0') && ((a) <= '9')) \
2028    ? (a) - '0' + 52             \
2029    : ((a) == '+') ? 62 : ((a) == '/') ? 63 : -1)
2030
2031
2032 /**
2033  * Decode from Base64.
2034  *
2035  * @param data the data to encode
2036  * @param len the length of the input
2037  * @param output where to write the output (*output should be NULL,
2038  *   is allocated)
2039  * @return the size of the output
2040  */
2041 size_t
2042 GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **out)
2043 {
2044   char *output;
2045   size_t ret = 0;
2046
2047 #define CHECK_CRLF                                                \
2048   while (data[i] == '\r' || data[i] == '\n')                      \
2049     {                                                               \
2050       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, \
2051                  "ignoring CR/LF\n");                              \
2052       i++;                                                          \
2053       if (i >= len)                                                 \
2054       goto END;                                                   \
2055     }
2056
2057   output = GNUNET_malloc((len * 3 / 4) + 8);
2058   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2059              "base64_decode decoding len=%d\n",
2060              (int)len);
2061   for (size_t i = 0; i < len; ++i)
2062     {
2063       char c;
2064       char c1;
2065
2066       CHECK_CRLF;
2067       if (FILLCHAR == data[i])
2068         break;
2069       c = (char)cvtfind(data[i]);
2070       ++i;
2071       CHECK_CRLF;
2072       c1 = (char)cvtfind(data[i]);
2073       c = (c << 2) | ((c1 >> 4) & 0x3);
2074       output[ret++] = c;
2075       if (++i < len)
2076         {
2077           CHECK_CRLF;
2078           c = data[i];
2079           if (FILLCHAR == c)
2080             break;
2081           c = (char)cvtfind(c);
2082           c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
2083           output[ret++] = c1;
2084         }
2085       if (++i < len)
2086         {
2087           CHECK_CRLF;
2088           c1 = data[i];
2089           if (FILLCHAR == c1)
2090             break;
2091
2092           c1 = (char)cvtfind(c1);
2093           c = ((c << 6) & 0xc0) | c1;
2094           output[ret++] = c;
2095         }
2096     }
2097 END:
2098   *out = output;
2099   return ret;
2100 }
2101
2102
2103 /* end of strings.c */