6fae8e713236ab9fc9a7bb04196348122f700ee1
[oweals/gnunet.git] / src / util / strings.c
1 /*
2      This file is part of GNUnet.
3      (C) 2005, 2006 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 2, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file util/strings.c
23  * @brief string functions
24  * @author Nils Durner
25  * @author Christian Grothoff
26  */
27
28 #include "platform.h"
29 #if HAVE_ICONV
30 #include <iconv.h>
31 #endif
32 #include "gnunet_common.h"
33 #include "gnunet_strings_lib.h"
34 #include <unicase.h>
35 #include <unistr.h>
36 #include <uniconv.h>
37
38 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
39
40 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", 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       memcpy (&buffer[needed], s, slen);
83     }
84     needed += slen;
85     count--;
86   }
87   va_end (ap);
88   return needed;
89 }
90
91
92 /**
93  * Given a buffer of a given size, find "count"
94  * 0-terminated strings in the buffer and assign
95  * the count (varargs) of type "const char**" to the
96  * locations of the respective strings in the
97  * buffer.
98  *
99  * @param buffer the buffer to parse
100  * @param size size of the buffer
101  * @param count number of strings to locate
102  * @return offset of the character after the last 0-termination
103  *         in the buffer, or 0 on error.
104  */
105 unsigned int
106 GNUNET_STRINGS_buffer_tokenize (const char *buffer, size_t size,
107                                 unsigned int count, ...)
108 {
109   unsigned int start;
110   unsigned int needed;
111   const char **r;
112   va_list ap;
113
114   needed = 0;
115   va_start (ap, count);
116   while (count > 0)
117   {
118     r = va_arg (ap, const char **);
119
120     start = needed;
121     while ((needed < size) && (buffer[needed] != '\0'))
122       needed++;
123     if (needed == size)
124     {
125       va_end (ap);
126       return 0;                 /* error */
127     }
128     *r = &buffer[start];
129     needed++;                   /* skip 0-termination */
130     count--;
131   }
132   va_end (ap);
133   return needed;
134 }
135
136
137 /**
138  * Convert a given filesize into a fancy human-readable format.
139  *
140  * @param size number of bytes
141  * @return fancy representation of the size (possibly rounded) for humans
142  */
143 char *
144 GNUNET_STRINGS_byte_size_fancy (unsigned long long size)
145 {
146   const char *unit = _( /* size unit */ "b");
147   char *ret;
148
149   if (size > 5 * 1024)
150   {
151     size = size / 1024;
152     unit = "KiB";
153     if (size > 5 * 1024)
154     {
155       size = size / 1024;
156       unit = "MiB";
157       if (size > 5 * 1024)
158       {
159         size = size / 1024;
160         unit = "GiB";
161         if (size > 5 * 1024)
162         {
163           size = size / 1024;
164           unit = "TiB";
165         }
166       }
167     }
168   }
169   ret = GNUNET_malloc (32);
170   GNUNET_snprintf (ret, 32, "%llu %s", size, unit);
171   return ret;
172 }
173
174
175 /**
176  * Unit conversion table entry for 'convert_with_table'.
177  */
178 struct ConversionTable
179 {
180   /**
181    * Name of the unit (or NULL for end of table).
182    */
183   const char *name;
184
185   /**
186    * Factor to apply for this unit.
187    */
188   unsigned long long value;
189 };
190
191
192 /**
193  * Convert a string of the form "4 X 5 Y" into a numeric value
194  * by interpreting "X" and "Y" as units and then multiplying
195  * the numbers with the values associated with the respective
196  * unit from the conversion table.
197  *
198  * @param input input string to parse
199  * @param table table with the conversion of unit names to numbers
200  * @param output where to store the result
201  * @return GNUNET_OK on success, GNUNET_SYSERR on error
202  */
203 static int
204 convert_with_table (const char *input,
205                     const struct ConversionTable *table,
206                     unsigned long long *output)
207 {
208   unsigned long long ret;
209   char *in;
210   const char *tok;
211   unsigned long long last;
212   unsigned int i;
213
214   ret = 0;
215   last = 0;
216   in = GNUNET_strdup (input);
217   for (tok = strtok (in, " "); tok != NULL; tok = strtok (NULL, " "))
218   {
219     i = 0;
220     while ((table[i].name != NULL) && (0 != strcasecmp (table[i].name, tok)))
221       i++;
222     if (table[i].name != NULL)
223       last *= table[i].value;
224     else
225     {
226       ret += last;
227       last = 0;
228       if (1 != SSCANF (tok, "%llu", &last))
229       {
230         GNUNET_free (in);
231         return GNUNET_SYSERR;   /* expected number */
232       }
233     }
234   }
235   ret += last;
236   *output = ret;
237   GNUNET_free (in);
238   return GNUNET_OK;
239 }
240
241
242 /**
243  * Convert a given fancy human-readable size to bytes.
244  *
245  * @param fancy_size human readable string (i.e. 1 MB)
246  * @param size set to the size in bytes
247  * @return GNUNET_OK on success, GNUNET_SYSERR on error
248  */
249 int
250 GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
251                                     unsigned long long *size)
252 {
253   static const struct ConversionTable table[] =
254   {
255     { "B", 1},
256     { "KiB", 1024},
257     { "kB", 1000},
258     { "MiB", 1024 * 1024},
259     { "MB", 1000 * 1000},
260     { "GiB", 1024 * 1024 * 1024},
261     { "GB", 1000 * 1000 * 1000},
262     { "TiB", 1024LL * 1024LL * 1024LL * 1024LL},
263     { "TB", 1000LL * 1000LL * 1000LL * 1024LL},
264     { "PiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL},
265     { "PB", 1000LL * 1000LL * 1000LL * 1024LL * 1000LL},
266     { "EiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL},
267     { "EB", 1000LL * 1000LL * 1000LL * 1024LL * 1000LL * 1000LL},
268     { NULL, 0}
269   };
270
271   return convert_with_table (fancy_size,
272                              table,
273                              size);
274 }
275
276
277 /**
278  * Convert a given fancy human-readable time to our internal
279  * representation.
280  *
281  * @param fancy_time human readable string (i.e. 1 minute)
282  * @param rtime set to the relative time
283  * @return GNUNET_OK on success, GNUNET_SYSERR on error
284  */
285 int
286 GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time,
287                                        struct GNUNET_TIME_Relative *rtime)
288 {
289   static const struct ConversionTable table[] =
290   {
291     { "ms", 1},
292     { "s", 1000},
293     { "\"", 1000},
294     { "m", 60 * 1000},
295     { "min", 60 * 1000},
296     { "minutes", 60 * 1000},
297     { "'", 60 * 1000},
298     { "h", 60 * 60 * 1000},
299     { "d", 24 * 60 * 60 * 1000},
300     { "day", 24 * 60 * 60 * 1000},
301     { "days", 24 * 60 * 60 * 1000},
302     { "a", 31536000000LL /* year */ },
303     { NULL, 0}
304   };
305   int ret;
306   unsigned long long val;
307
308   if (0 == strcasecmp ("forever", fancy_time))
309   {
310     *rtime = GNUNET_TIME_UNIT_FOREVER_REL;
311     return GNUNET_OK;
312   }
313   ret = convert_with_table (fancy_time,
314                             table,
315                             &val);
316   rtime->rel_value = (uint64_t) val;
317   return ret;
318 }
319
320
321 /**
322  * Convert a given fancy human-readable time to our internal
323  * representation.
324  *
325  * @param fancy_time human readable string (i.e. %Y-%m-%d %H:%M:%S)
326  * @param atime set to the absolute time
327  * @return GNUNET_OK on success, GNUNET_SYSERR on error
328  */
329 int
330 GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time,
331                                        struct GNUNET_TIME_Absolute *atime)
332 {
333   struct tm tv;
334   time_t t;
335
336   if (0 == strcasecmp ("end of time", fancy_time))
337   {
338     *atime = GNUNET_TIME_UNIT_FOREVER_ABS;
339     return GNUNET_OK;
340   }
341   memset (&tv, 0, sizeof (tv));
342   if ( (NULL == strptime (fancy_time, "%a %b %d %H:%M:%S %Y", &tv)) &&
343        (NULL == strptime (fancy_time, "%c", &tv)) &&
344        (NULL == strptime (fancy_time, "%Ec", &tv)) &&
345        (NULL == strptime (fancy_time, "%Y-%m-%d %H:%M:%S", &tv)) &&
346        (NULL == strptime (fancy_time, "%Y-%m-%d %H:%M", &tv)) &&
347        (NULL == strptime (fancy_time, "%x", &tv)) &&
348        (NULL == strptime (fancy_time, "%Ex", &tv)) &&
349        (NULL == strptime (fancy_time, "%Y-%m-%d", &tv)) &&
350        (NULL == strptime (fancy_time, "%Y-%m", &tv)) &&
351        (NULL == strptime (fancy_time, "%Y", &tv)) )
352     return GNUNET_SYSERR;
353   t = mktime (&tv);
354   atime->abs_value = (uint64_t) ((uint64_t) t * 1000LL);
355 #if LINUX
356   atime->abs_value -= 1000LL * timezone;
357 #endif
358   return GNUNET_OK;
359 }
360
361
362 /**
363  * Convert the len characters long character sequence
364  * given in input that is in the given input charset
365  * to a string in given output charset.
366  * @return the converted string (0-terminated),
367  *  if conversion fails, a copy of the orignal
368  *  string is returned.
369  */
370 char *
371 GNUNET_STRINGS_conv (const char *input, size_t len, const char *input_charset, const char *output_charset)
372 {
373   char *ret;
374
375   uint8_t *u8_string;
376   char *encoded_string;
377   size_t u8_string_length;
378   size_t encoded_string_length;
379
380   u8_string = u8_conv_from_encoding (input_charset, iconveh_error, input, len, NULL, NULL, &u8_string_length);
381   if (NULL == u8_string)
382   {
383     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_from_encoding");
384     LOG (GNUNET_ERROR_TYPE_WARNING, _("Character sets requested were `%s'->`%s'\n"),
385          input_charset, "UTF-8");
386     ret = GNUNET_malloc (len + 1);
387     memcpy (ret, input, len);
388     ret[len] = '\0';
389     return ret;
390   }
391   if (strcmp (output_charset, "UTF-8") == 0)
392   {
393     ret = GNUNET_malloc (u8_string_length + 1);
394     memcpy (ret, u8_string, u8_string_length);
395     ret[u8_string_length] = '\0';
396     free (u8_string);
397     return ret;
398   }
399   encoded_string = u8_conv_to_encoding (output_charset, iconveh_error, u8_string, u8_string_length, NULL, NULL, &encoded_string_length);
400   free (u8_string);
401   if (NULL == encoded_string)
402   {
403     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_to_encoding");
404     LOG (GNUNET_ERROR_TYPE_WARNING, _("Character sets requested were `%s'->`%s'\n"),
405          "UTF-8", output_charset);
406     ret = GNUNET_malloc (len + 1);
407     memcpy (ret, input, len);
408     ret[len] = '\0';
409     return ret;
410   }
411   ret = GNUNET_malloc (encoded_string_length + 1);
412   memcpy (ret, encoded_string, encoded_string_length);
413   ret[encoded_string_length] = '\0';
414   free (encoded_string);
415   return ret;
416 }
417
418
419 /**
420  * Convert the len characters long character sequence
421  * given in input that is in the given charset
422  * to UTF-8.
423  * @return the converted string (0-terminated),
424  *  if conversion fails, a copy of the orignal
425  *  string is returned.
426  */
427 char *
428 GNUNET_STRINGS_to_utf8 (const char *input, size_t len, const char *charset)
429 {
430   return GNUNET_STRINGS_conv (input, len, charset, "UTF-8");
431 }
432
433
434 /**
435  * Convert the len bytes-long UTF-8 string
436  * given in input to the given charset.
437  *
438  * @return the converted string (0-terminated),
439  *  if conversion fails, a copy of the orignal
440  *  string is returned.
441  */
442 char *
443 GNUNET_STRINGS_from_utf8 (const char *input, size_t len, const char *charset)
444 {
445   return GNUNET_STRINGS_conv (input, len, "UTF-8", charset);
446 }
447
448
449 /**
450  * Convert the utf-8 input string to lowercase
451  * Output needs to be allocated appropriately
452  *
453  * @param input input string
454  * @param output output buffer
455  */
456 void
457 GNUNET_STRINGS_utf8_tolower(const char* input, char** output)
458 {
459   uint8_t *tmp_in;
460   size_t len;
461
462   tmp_in = u8_tolower ((uint8_t*)input, strlen ((char *) input),
463                        NULL, UNINORM_NFD, NULL, &len);
464   memcpy(*output, tmp_in, len);
465   (*output)[len] = '\0';
466   free(tmp_in);
467 }
468
469
470 /**
471  * Convert the utf-8 input string to uppercase
472  * Output needs to be allocated appropriately
473  *
474  * @param input input string
475  * @param output output buffer
476  */
477 void
478 GNUNET_STRINGS_utf8_toupper(const char* input, char** output)
479 {
480   uint8_t *tmp_in;
481   size_t len;
482
483   tmp_in = u8_toupper ((uint8_t*)input, strlen ((char *) input),
484                        NULL, UNINORM_NFD, NULL, &len);
485   memcpy(*output, tmp_in, len);
486   (*output)[len] = '\0';
487   free(tmp_in);
488 }
489
490
491 /**
492  * Complete filename (a la shell) from abbrevition.
493  * @param fil the name of the file, may contain ~/ or
494  *        be relative to the current directory
495  * @returns the full file name,
496  *          NULL is returned on error
497  */
498 char *
499 GNUNET_STRINGS_filename_expand (const char *fil)
500 {
501   char *buffer;
502 #ifndef MINGW
503   size_t len;
504   size_t n;
505   char *fm;
506   const char *fil_ptr;
507 #else
508   char *fn;
509   long lRet;
510 #endif
511
512   if (fil == NULL)
513     return NULL;
514
515 #ifndef MINGW
516   if (fil[0] == DIR_SEPARATOR)
517     /* absolute path, just copy */
518     return GNUNET_strdup (fil);
519   if (fil[0] == '~')
520   {
521     fm = getenv ("HOME");
522     if (fm == NULL)
523     {
524       LOG (GNUNET_ERROR_TYPE_WARNING,
525            _("Failed to expand `$HOME': environment variable `HOME' not set"));
526       return NULL;
527     }
528     fm = GNUNET_strdup (fm);
529     /* do not copy '~' */
530     fil_ptr = fil + 1;
531
532     /* skip over dir seperator to be consistent */
533     if (fil_ptr[0] == DIR_SEPARATOR)
534       fil_ptr++;
535   }
536   else
537   {
538     /* relative path */
539     fil_ptr = fil;
540     len = 512;
541     fm = NULL;
542     while (1)
543     {
544       buffer = GNUNET_malloc (len);
545       if (getcwd (buffer, len) != NULL)
546       {
547         fm = buffer;
548         break;
549       }
550       if ((errno == ERANGE) && (len < 1024 * 1024 * 4))
551       {
552         len *= 2;
553         GNUNET_free (buffer);
554         continue;
555       }
556       GNUNET_free (buffer);
557       break;
558     }
559     if (fm == NULL)
560     {
561       LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "getcwd");
562       buffer = getenv ("PWD");  /* alternative */
563       if (buffer != NULL)
564         fm = GNUNET_strdup (buffer);
565     }
566     if (fm == NULL)
567       fm = GNUNET_strdup ("./");        /* give up */
568   }
569   n = strlen (fm) + 1 + strlen (fil_ptr) + 1;
570   buffer = GNUNET_malloc (n);
571   GNUNET_snprintf (buffer, n, "%s%s%s", fm,
572                    (fm[strlen (fm) - 1] ==
573                     DIR_SEPARATOR) ? "" : DIR_SEPARATOR_STR, fil_ptr);
574   GNUNET_free (fm);
575   return buffer;
576 #else
577   fn = GNUNET_malloc (MAX_PATH + 1);
578
579   if ((lRet = plibc_conv_to_win_path (fil, fn)) != ERROR_SUCCESS)
580   {
581     SetErrnoFromWinError (lRet);
582     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "plibc_conv_to_win_path");
583     return NULL;
584   }
585   /* is the path relative? */
586   if ((strncmp (fn + 1, ":\\", 2) != 0) && (strncmp (fn, "\\\\", 2) != 0))
587   {
588     char szCurDir[MAX_PATH + 1];
589
590     lRet = GetCurrentDirectory (MAX_PATH + 1, szCurDir);
591     if (lRet + strlen (fn) + 1 > (MAX_PATH + 1))
592     {
593       SetErrnoFromWinError (ERROR_BUFFER_OVERFLOW);
594       LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "GetCurrentDirectory");
595       return NULL;
596     }
597     buffer = GNUNET_malloc (MAX_PATH + 1);
598     GNUNET_snprintf (buffer, MAX_PATH + 1, "%s\\%s", szCurDir, fn);
599     GNUNET_free (fn);
600     fn = buffer;
601   }
602
603   return fn;
604 #endif
605 }
606
607
608 /**
609  * Give relative time in human-readable fancy format.
610  * This is one of the very few calls in the entire API that is
611  * NOT reentrant!
612  *
613  * @param delta time in milli seconds
614  * @param do_round are we allowed to round a bit?
615  * @return time as human-readable string
616  */
617 const char *
618 GNUNET_STRINGS_relative_time_to_string (struct GNUNET_TIME_Relative delta,
619                                         int do_round)
620 {
621   static char buf[128];
622   const char *unit = _( /* time unit */ "ms");
623   uint64_t dval = delta.rel_value;
624
625   if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value == delta.rel_value)
626     return _("forever");
627   if (0 == delta.rel_value)
628     return _("0 ms");
629   if ( ( (GNUNET_YES == do_round) && 
630          (dval > 5 * 1000) ) || 
631        (0 == (dval % 1000) ))
632   {
633     dval = dval / 1000;
634     unit = _( /* time unit */ "s");
635     if ( ( (GNUNET_YES == do_round) &&
636            (dval > 5 * 60) ) ||
637          (0 == (dval % 60) ) )
638     {
639       dval = dval / 60;
640       unit = _( /* time unit */ "m");
641       if ( ( (GNUNET_YES == do_round) &&
642              (dval > 5 * 60) ) || 
643            (0 == (dval % 60) ))
644       {
645         dval = dval / 60;
646         unit = _( /* time unit */ "h");
647         if ( ( (GNUNET_YES == do_round) &&
648                (dval > 5 * 24) ) ||
649              (0 == (dval % 24)) )
650         {
651           dval = dval / 24;
652           if (1 == dval)
653             unit = _( /* time unit */ "day");
654           else
655             unit = _( /* time unit */ "days");
656         }
657       }
658     }
659   }
660   GNUNET_snprintf (buf, sizeof (buf),
661                    "%llu %s", dval, unit);
662   return buf;
663 }
664
665
666 /**
667  * "asctime", except for GNUnet time.
668  * This is one of the very few calls in the entire API that is
669  * NOT reentrant!
670  *
671  * @param t time to convert
672  * @return absolute time in human-readable format
673  */
674 const char *
675 GNUNET_STRINGS_absolute_time_to_string (struct GNUNET_TIME_Absolute t)
676 {
677   static char buf[255];
678   time_t tt;
679   struct tm *tp;
680
681   if (t.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value)
682     return _("end of time");
683   tt = t.abs_value / 1000;
684   tp = gmtime (&tt);
685   strftime (buf, sizeof (buf), "%a %b %d %H:%M:%S %Y", tp);
686   return buf;
687 }
688
689
690 /**
691  * "man basename"
692  * Returns a pointer to a part of filename (allocates nothing)!
693  *
694  * @param filename filename to extract basename from
695  * @return short (base) name of the file (that is, everything following the
696  *         last directory separator in filename. If filename ends with a
697  *         directory separator, the result will be a zero-length string.
698  *         If filename has no directory separators, the result is filename
699  *         itself.
700  */
701 const char *
702 GNUNET_STRINGS_get_short_name (const char *filename)
703 {
704   const char *short_fn = filename;
705   const char *ss;
706   while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR))
707       && (ss[1] != '\0'))
708     short_fn = 1 + ss;
709   return short_fn;
710 }
711
712
713 /**
714  * Get the numeric value corresponding to a character.
715  *
716  * @param a a character
717  * @return corresponding numeric value
718  */
719 static unsigned int
720 getValue__ (unsigned char a)
721 {
722   if ((a >= '0') && (a <= '9'))
723     return a - '0';
724   if ((a >= 'A') && (a <= 'V'))
725     return (a - 'A' + 10);
726   return -1;
727 }
728
729
730 /**
731  * Convert binary data to ASCII encoding.  The ASCII encoding is rather
732  * GNUnet specific.  It was chosen such that it only uses characters
733  * in [0-9A-V], can be produced without complex arithmetics and uses a
734  * small number of characters.  
735  * Does not append 0-terminator, but returns a pointer to the place where
736  * it should be placed, if needed.
737  *
738  * @param data data to encode
739  * @param size size of data (in bytes)
740  * @param out buffer to fill
741  * @param out_size size of the buffer. Must be large enough to hold
742  * ((size*8) + (((size*8) % 5) > 0 ? 5 - ((size*8) % 5) : 0)) / 5 bytes
743  * @return pointer to the next byte in 'out' or NULL on error.
744  */
745 char *
746 GNUNET_STRINGS_data_to_string (const unsigned char *data, size_t size, char *out, size_t out_size)
747 {
748   /**
749    * 32 characters for encoding 
750    */
751   static char *encTable__ = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
752   unsigned int wpos;
753   unsigned int rpos;
754   unsigned int bits;
755   unsigned int vbit;
756
757   GNUNET_assert (data != NULL);
758   GNUNET_assert (out != NULL);
759   if (out_size < (((size*8) + ((size*8) % 5)) % 5))
760   {
761     GNUNET_break (0);
762     return NULL;
763   }
764   vbit = 0;
765   wpos = 0;
766   rpos = 0;
767   bits = 0;
768   while ((rpos < size) || (vbit > 0))
769   {
770     if ((rpos < size) && (vbit < 5))
771     {
772       bits = (bits << 8) | data[rpos++];   /* eat 8 more bits */
773       vbit += 8;
774     }
775     if (vbit < 5)
776     {
777       bits <<= (5 - vbit);      /* zero-padding */
778       GNUNET_assert (vbit == ((size * 8) % 5));
779       vbit = 5;
780     }
781     if (wpos >= out_size)
782     {
783       GNUNET_break (0);
784       return NULL;
785     }
786     out[wpos++] = encTable__[(bits >> (vbit - 5)) & 31];
787     vbit -= 5;
788   }
789   if (wpos != out_size)
790   {
791     GNUNET_break (0);
792     return NULL;
793   }
794   GNUNET_assert (vbit == 0);
795   return &out[wpos];
796 }
797
798
799 /**
800  * Convert ASCII encoding back to data
801  * out_size must match exactly the size of the data before it was encoded.
802  *
803  * @param enc the encoding
804  * @param enclen number of characters in 'enc' (without 0-terminator, which can be missing)
805  * @param out location where to store the decoded data
806  * @param out_size sizeof the output buffer
807  * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong encoding
808  */
809 int
810 GNUNET_STRINGS_string_to_data (const char *enc, size_t enclen,
811                               unsigned char *out, size_t out_size)
812 {
813   unsigned int rpos;
814   unsigned int wpos;
815   unsigned int bits;
816   unsigned int vbit;
817   int ret;
818   int shift;
819   int encoded_len = out_size * 8;
820   if (encoded_len % 5 > 0)
821   {
822     vbit = encoded_len % 5; /* padding! */
823     shift = 5 - vbit;
824   }
825   else
826   {
827     vbit = 0;
828     shift = 0;
829   }
830   if ((encoded_len + shift) / 5 != enclen)
831     return GNUNET_SYSERR;
832
833   wpos = out_size;
834   rpos = enclen;
835   bits = (ret = getValue__ (enc[--rpos])) >> (5 - encoded_len % 5);
836   if (-1 == ret)
837     return GNUNET_SYSERR;
838   while (wpos > 0)
839   {
840     GNUNET_assert (rpos > 0);
841     bits = ((ret = getValue__ (enc[--rpos])) << vbit) | bits;
842     if (-1 == ret)
843       return GNUNET_SYSERR;
844     vbit += 5;
845     if (vbit >= 8)
846     {
847       out[--wpos] = (unsigned char) bits;
848       bits >>= 8;
849       vbit -= 8;
850     }
851   }
852   GNUNET_assert (rpos == 0);
853   GNUNET_assert (vbit == 0);
854   return GNUNET_OK;
855 }
856
857
858 /**
859  * Parse a path that might be an URI.
860  *
861  * @param path path to parse. Must be NULL-terminated.
862  * @param scheme_part a pointer to 'char *' where a pointer to a string that
863  *        represents the URI scheme will be stored. Can be NULL. The string is
864  *        allocated by the function, and should be freed by GNUNET_free() when
865  *        it is no longer needed.
866  * @param path_part a pointer to 'const char *' where a pointer to the path
867  *        part of the URI will be stored. Can be NULL. Points to the same block
868  *        of memory as 'path', and thus must not be freed. Might point to '\0',
869  *        if path part is zero-length.
870  * @return GNUNET_YES if it's an URI, GNUNET_NO otherwise. If 'path' is not
871  *         an URI, '* scheme_part' and '*path_part' will remain unchanged
872  *         (if they weren't NULL).
873  */
874 int
875 GNUNET_STRINGS_parse_uri (const char *path, char **scheme_part,
876     const char **path_part)
877 {
878   size_t len;
879   int i, end;
880   int pp_state = 0;
881   const char *post_scheme_part = NULL;
882   len = strlen (path);
883   for (end = 0, i = 0; !end && i < len; i++)
884   {
885     switch (pp_state)
886     {
887     case 0:
888       if (path[i] == ':' && i > 0)
889       {
890         pp_state += 1;
891         continue;
892       }
893       if (!((path[i] >= 'A' && path[i] <= 'Z') || (path[i] >= 'a' && path[i] <= 'z')
894           || (path[i] >= '0' && path[i] <= '9') || path[i] == '+' || path[i] == '-'
895           || (path[i] == '.')))
896         end = 1;
897       break;
898     case 1:
899     case 2:
900       if (path[i] == '/')
901       {
902         pp_state += 1;
903         continue;
904       }
905       end = 1;
906       break;
907     case 3:
908       post_scheme_part = &path[i];
909       end = 1;
910       break;
911     default:
912       end = 1;
913     }
914   }
915   if (post_scheme_part == NULL)
916     return GNUNET_NO;
917   if (scheme_part)
918   {
919     *scheme_part = GNUNET_malloc (post_scheme_part - path + 1);
920     memcpy (*scheme_part, path, post_scheme_part - path);
921     (*scheme_part)[post_scheme_part - path] = '\0';
922   }
923   if (path_part)
924     *path_part = post_scheme_part;
925   return GNUNET_YES;
926 }
927
928
929 /**
930  * Check whether 'filename' is absolute or not, and if it's an URI
931  *
932  * @param filename filename to check
933  * @param can_be_uri GNUNET_YES to check for being URI, GNUNET_NO - to
934  *        assume it's not URI
935  * @param r_is_uri a pointer to an int that is set to GNUNET_YES if 'filename'
936  *        is URI and to GNUNET_NO otherwise. Can be NULL. If 'can_be_uri' is
937  *        not GNUNET_YES, *r_is_uri is set to GNUNET_NO.
938  * @param r_uri_scheme a pointer to a char * that is set to a pointer to URI scheme.
939  *        The string is allocated by the function, and should be freed with
940  *        GNUNET_free (). Can be NULL.
941  * @return GNUNET_YES if 'filename' is absolute, GNUNET_NO otherwise.
942  */
943 int
944 GNUNET_STRINGS_path_is_absolute (const char *filename, int can_be_uri,
945     int *r_is_uri, char **r_uri_scheme)
946 {
947 #if WINDOWS
948   size_t len;
949 #endif
950   const char *post_scheme_path;
951   int is_uri;
952   char * uri;
953   /* consider POSIX paths to be absolute too, even on W32,
954    * as plibc expansion will fix them for us.
955    */
956   if (filename[0] == '/')
957     return GNUNET_YES;
958   if (can_be_uri)
959   {
960     is_uri = GNUNET_STRINGS_parse_uri (filename, &uri, &post_scheme_path);
961     if (r_is_uri)
962       *r_is_uri = is_uri;
963     if (is_uri)
964     {
965       if (r_uri_scheme)
966         *r_uri_scheme = uri;
967       else
968         GNUNET_free_non_null (uri);
969 #if WINDOWS
970       len = strlen(post_scheme_path);
971       /* Special check for file:///c:/blah
972        * We want to parse 'c:/', not '/c:/'
973        */
974       if (post_scheme_path[0] == '/' && len >= 3 && post_scheme_path[2] == ':')
975         post_scheme_path = &post_scheme_path[1];
976 #endif
977       return GNUNET_STRINGS_path_is_absolute (post_scheme_path, GNUNET_NO, NULL, NULL);
978     }
979   }
980   else
981   {
982     if (r_is_uri)
983       *r_is_uri = GNUNET_NO;
984   }
985 #if WINDOWS
986   len = strlen (filename);
987   if (len >= 3 &&
988       ((filename[0] >= 'A' && filename[0] <= 'Z')
989       || (filename[0] >= 'a' && filename[0] <= 'z'))
990       && filename[1] == ':' && (filename[2] == '/' || filename[2] == '\\'))
991     return GNUNET_YES;
992 #endif
993   return GNUNET_NO;
994 }
995
996 #if MINGW
997 #define         _IFMT           0170000 /* type of file */
998 #define         _IFLNK          0120000 /* symbolic link */
999 #define  S_ISLNK(m)     (((m)&_IFMT) == _IFLNK)
1000 #endif
1001
1002
1003 /**
1004  * Perform 'checks' on 'filename'
1005  * 
1006  * @param filename file to check
1007  * @param checks checks to perform
1008  * @return GNUNET_YES if all checks pass, GNUNET_NO if at least one of them
1009  *         fails, GNUNET_SYSERR when a check can't be performed
1010  */
1011 int
1012 GNUNET_STRINGS_check_filename (const char *filename,
1013                                enum GNUNET_STRINGS_FilenameCheck checks)
1014 {
1015   struct stat st;
1016   if ( (NULL == filename) || (filename[0] == '\0') )
1017     return GNUNET_SYSERR;
1018   if (0 != (checks & GNUNET_STRINGS_CHECK_IS_ABSOLUTE))
1019     if (!GNUNET_STRINGS_path_is_absolute (filename, GNUNET_NO, NULL, NULL))
1020       return GNUNET_NO;
1021   if (0 != (checks & (GNUNET_STRINGS_CHECK_EXISTS
1022                       | GNUNET_STRINGS_CHECK_IS_DIRECTORY
1023                       | GNUNET_STRINGS_CHECK_IS_LINK)))
1024   {
1025     if (0 != STAT (filename, &st))
1026     {
1027       if (0 != (checks & GNUNET_STRINGS_CHECK_EXISTS))
1028         return GNUNET_NO;
1029       else
1030         return GNUNET_SYSERR;
1031     }
1032   }
1033   if (0 != (checks & GNUNET_STRINGS_CHECK_IS_DIRECTORY))
1034     if (!S_ISDIR (st.st_mode))
1035       return GNUNET_NO;
1036   if (0 != (checks & GNUNET_STRINGS_CHECK_IS_LINK))
1037     if (!S_ISLNK (st.st_mode))
1038       return GNUNET_NO;
1039   return GNUNET_YES;
1040 }
1041
1042
1043 /**
1044  * Tries to convert 'zt_addr' string to an IPv6 address.
1045  * The string is expected to have the format "[ABCD::01]:80".
1046  * 
1047  * @param zt_addr 0-terminated string. May be mangled by the function.
1048  * @param addrlen length of zt_addr (not counting 0-terminator).
1049  * @param r_buf a buffer to fill. Initially gets filled with zeroes,
1050  *        then its sin6_port, sin6_family and sin6_addr are set appropriately.
1051  * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which
1052  *         case the contents of r_buf are undefined.
1053  */
1054 int
1055 GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr, 
1056                                 uint16_t addrlen,
1057                                 struct sockaddr_in6 *r_buf)
1058 {
1059   char zbuf[addrlen + 1];
1060   int ret;
1061   char *port_colon;
1062   unsigned int port;
1063
1064   if (addrlen < 6)
1065     return GNUNET_SYSERR;  
1066   memcpy (zbuf, zt_addr, addrlen);
1067   if ('[' != zbuf[0])
1068   {
1069     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1070                 _("IPv6 address did not start with `['\n"));
1071     return GNUNET_SYSERR;
1072   }
1073   zbuf[addrlen] = '\0';
1074   port_colon = strrchr (zbuf, ':');
1075   if (NULL == port_colon)
1076   {
1077     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1078                 _("IPv6 address did contain ':' to separate port number\n"));
1079     return GNUNET_SYSERR;
1080   }
1081   if (']' != *(port_colon - 1))
1082   {
1083     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1084                 _("IPv6 address did contain ']' before ':' to separate port number\n"));
1085     return GNUNET_SYSERR;
1086   }
1087   ret = SSCANF (port_colon, ":%u", &port);
1088   if ( (1 != ret) || (port > 65535) )
1089   {
1090     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1091                 _("IPv6 address did contain a valid port number after the last ':'\n"));
1092     return GNUNET_SYSERR;
1093   }
1094   *(port_colon-1) = '\0';
1095   memset (r_buf, 0, sizeof (struct sockaddr_in6));
1096   ret = inet_pton (AF_INET6, &zbuf[1], &r_buf->sin6_addr);
1097   if (ret <= 0)
1098   {
1099     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1100                 _("Invalid IPv6 address `%s': %s\n"),
1101                 &zbuf[1],
1102                 STRERROR (errno));
1103     return GNUNET_SYSERR;
1104   }
1105   r_buf->sin6_port = htons (port);
1106   r_buf->sin6_family = AF_INET6;
1107 #if HAVE_SOCKADDR_IN_SIN_LEN
1108   r_buf->sin6_len = (u_char) sizeof (struct sockaddr_in6);
1109 #endif
1110   return GNUNET_OK;
1111 }
1112
1113
1114 /**
1115  * Tries to convert 'zt_addr' string to an IPv4 address.
1116  * The string is expected to have the format "1.2.3.4:80".
1117  * 
1118  * @param zt_addr 0-terminated string. May be mangled by the function.
1119  * @param addrlen length of zt_addr (not counting 0-terminator).
1120  * @param r_buf a buffer to fill.
1121  * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which case
1122  *         the contents of r_buf are undefined.
1123  */
1124 int
1125 GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen,
1126                                 struct sockaddr_in *r_buf)
1127 {
1128   unsigned int temps[4];
1129   unsigned int port;
1130   unsigned int cnt;
1131
1132   if (addrlen < 9)
1133     return GNUNET_SYSERR;
1134   cnt = SSCANF (zt_addr, "%u.%u.%u.%u:%u", &temps[0], &temps[1], &temps[2], &temps[3], &port);
1135   if (5 != cnt)
1136     return GNUNET_SYSERR;
1137   for (cnt = 0; cnt < 4; cnt++)
1138     if (temps[cnt] > 0xFF)
1139       return GNUNET_SYSERR;
1140   if (port > 65535)
1141     return GNUNET_SYSERR;
1142   r_buf->sin_family = AF_INET;
1143   r_buf->sin_port = htons (port);
1144   r_buf->sin_addr.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16) +
1145                                   (temps[2] << 8) + temps[3]);
1146 #if HAVE_SOCKADDR_IN_SIN_LEN
1147   r_buf->sin_len = (u_char) sizeof (struct sockaddr_in);
1148 #endif
1149   return GNUNET_OK;
1150 }
1151
1152
1153 /**
1154  * Tries to convert 'addr' string to an IP (v4 or v6) address.
1155  * Will automatically decide whether to treat 'addr' as v4 or v6 address.
1156  * 
1157  * @param addr a string, may not be 0-terminated.
1158  * @param addrlen number of bytes in addr (if addr is 0-terminated,
1159  *        0-terminator should not be counted towards addrlen).
1160  * @param r_buf a buffer to fill.
1161  * @return GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which
1162  *         case the contents of r_buf are undefined.
1163  */
1164 int
1165 GNUNET_STRINGS_to_address_ip (const char *addr, 
1166                               uint16_t addrlen,
1167                               struct sockaddr_storage *r_buf)
1168 {
1169   if (addr[0] == '[')
1170     return GNUNET_STRINGS_to_address_ipv6 (addr, addrlen, (struct sockaddr_in6 *) r_buf);
1171   return GNUNET_STRINGS_to_address_ipv4 (addr, addrlen, (struct sockaddr_in *) r_buf);
1172 }
1173
1174
1175 /**
1176  * Makes a copy of argv that consists of a single memory chunk that can be
1177  * freed with a single call to GNUNET_free ();
1178  */
1179 static char *const *
1180 _make_continuous_arg_copy (int argc, char *const *argv)
1181 {
1182   size_t argvsize = 0;
1183   int i;
1184   char **new_argv;
1185   char *p;
1186   for (i = 0; i < argc; i++)
1187     argvsize += strlen (argv[i]) + 1 + sizeof (char *);
1188   new_argv = GNUNET_malloc (argvsize + sizeof (char *));
1189   p = (char *) &new_argv[argc + 1];
1190   for (i = 0; i < argc; i++)
1191   {
1192     new_argv[i] = p;
1193     strcpy (p, argv[i]);
1194     p += strlen (argv[i]) + 1;
1195   }
1196   new_argv[argc] = NULL;
1197   return (char *const *) new_argv;
1198 }
1199
1200
1201 /**
1202  * Returns utf-8 encoded arguments.
1203  * Does nothing (returns a copy of argc and argv) on any platform
1204  * other than W32.
1205  * Returned argv has u8argv[u8argc] == NULL.
1206  * Returned argv is a single memory block, and can be freed with a single
1207  *   GNUNET_free () call.
1208  *
1209  * @param argc argc (as given by main())
1210  * @param argv argv (as given by main())
1211  * @param u8argc a location to store new argc in (though it's th same as argc)
1212  * @param u8argv a location to store new argv in
1213  * @return GNUNET_OK on success, GNUNET_SYSERR on failure
1214  */
1215 int
1216 GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *const **u8argv)
1217 {
1218 #if WINDOWS
1219   wchar_t *wcmd;
1220   wchar_t **wargv;
1221   int wargc;
1222   int i;
1223   char **split_u8argv;
1224
1225   wcmd = GetCommandLineW ();
1226   if (NULL == wcmd)
1227     return GNUNET_SYSERR;
1228   wargv = CommandLineToArgvW (wcmd, &wargc);
1229   if (NULL == wargv)
1230     return GNUNET_SYSERR;
1231
1232   split_u8argv = GNUNET_malloc (argc * sizeof (char *));
1233
1234   for (i = 0; i < wargc; i++)
1235   {
1236     size_t strl;
1237     /* Hopefully it will allocate us NUL-terminated strings... */
1238     split_u8argv[i] = (char *) u16_to_u8 (wargv[i], wcslen (wargv[i]) + 1, NULL, &strl);
1239     if (split_u8argv == NULL)
1240     {
1241       int j;
1242       for (j = 0; j < i; j++)
1243         free (split_u8argv[j]);
1244       GNUNET_free (split_u8argv);
1245       LocalFree (wargv);
1246       return GNUNET_SYSERR;
1247     }
1248   }
1249
1250   *u8argv = _make_continuous_arg_copy (wargc, split_u8argv);
1251   *u8argc = wargc;
1252
1253   for (i = 0; i < wargc; i++)
1254     free (split_u8argv[i]);
1255   free (split_u8argv);
1256   return GNUNET_OK;
1257 #else
1258   char *const *new_argv = (char *const *) _make_continuous_arg_copy (argc, argv);
1259   *u8argv = new_argv;
1260   *u8argc = argc;
1261   return GNUNET_OK;
1262 #endif
1263 }
1264
1265 /* end of strings.c */