aheinecke@404: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
aheinecke@404:  * Software engineering by Intevation GmbH
aheinecke@404:  *
aheinecke@404:  * This file is Free Software under the GNU GPL (v>=2)
aheinecke@404:  * and comes with ABSOLUTELY NO WARRANTY!
aheinecke@404:  * See LICENSE.txt for details.
aheinecke@404:  */
wilde@319: /* Needed to get asprintf */
wilde@319: #define _GNU_SOURCE 1
wilde@319: 
wilde@134: #include <ctype.h>
wilde@319: #include <stdarg.h>
wilde@131: #include <stdbool.h>
aheinecke@59: #include <stdio.h>
aheinecke@59: #include <stdlib.h>
aheinecke@59: #include <string.h>
aheinecke@59: #include <assert.h>
aheinecke@59: 
aheinecke@160: #include <polarssl/base64.h>
aheinecke@160: 
aheinecke@251: #ifdef WIN32
aheinecke@251: #include <windows.h>
aheinecke@251: #endif
aheinecke@251: 
wilde@143: /* Remarks regarding the "Flawfinder: ignore" comments in this file:
wilde@143:  *
wilde@143:  * - strlen:
wilde@143:  *
wilde@143:  *   It's true that strlen might crash if input is not null
wilde@143:  *   terminated.  But by design there is not safe way to get the
wilde@143:  *   length of an string in C, and defining an additional length
wilde@143:  *   parameter for string parameter will only transfere the problem to
wilde@143:  *   the caller.
wilde@143:  */
wilde@143: 
aheinecke@59: static void
aheinecke@59: out_of_core(void)
aheinecke@59: {
aheinecke@59:     fputs("\nfatal: out of memory\n", stderr);
aheinecke@59:     exit(2);
aheinecke@59: }
aheinecke@59: void *
aheinecke@59: xmalloc( size_t n )
aheinecke@59: {
aheinecke@59:     void *p = malloc( n );
aheinecke@59:     if( !p )
aheinecke@59:         out_of_core();
aheinecke@59:     return p;
aheinecke@59: }
aheinecke@59: 
aheinecke@59: void *
aheinecke@59: xrealloc( void *a, size_t n )
aheinecke@59: {
aheinecke@59:     void *p = realloc( a, n );
aheinecke@59:     if( !p )
aheinecke@59:         out_of_core();
aheinecke@59:     return p;
aheinecke@59: }
aheinecke@59: 
aheinecke@59: char *
aheinecke@60: xstrndup( const char *string, const size_t len )
aheinecke@59: {
aheinecke@60:     char *p = xmalloc( len + 1 );
aheinecke@60:     memcpy( p, string, len );
aheinecke@60:     p[len] = '\0';
aheinecke@59:     return p;
aheinecke@59: }
aheinecke@59: 
aheinecke@59: unsigned int
aheinecke@59: strv_length (char **str_array)
aheinecke@59: {
aheinecke@59:     unsigned int i = 0;
aheinecke@59: 
aheinecke@59:     if (!str_array)
aheinecke@59:         return 0;
aheinecke@59: 
aheinecke@59:     while (str_array[i])
aheinecke@59:         ++i;
aheinecke@59: 
aheinecke@59:     return i;
aheinecke@59: }
aheinecke@59: 
wilde@116: void strv_append (char ***pArray, const char *string, const size_t len)
aheinecke@59: {
aheinecke@60:     unsigned int old_len = 0;
aheinecke@60: 
aheinecke@60:     if (!*pArray) {
aheinecke@60:         *pArray = xmalloc(2 * sizeof(char*));
aheinecke@60:         (*pArray)[0] = xstrndup(string, len);
aheinecke@60:         (*pArray)[1] = NULL;
aheinecke@60:         return;
aheinecke@60:     }
aheinecke@60:     old_len = strv_length(*pArray);
aheinecke@59:     *pArray = xrealloc(*pArray, sizeof(char**) * (old_len + 2));
aheinecke@59: 
aheinecke@60:     (*pArray)[old_len] = xstrndup(string, len);
aheinecke@60:     (*pArray)[old_len + 1] = NULL;
aheinecke@59: }
aheinecke@59: 
aheinecke@91: void
aheinecke@91: str_append_str(char **pDst, size_t *dst_len, const char *appendage, const size_t len)
aheinecke@59: {
aheinecke@59:     if (!appendage)
aheinecke@59:         return;
aheinecke@59: 
aheinecke@91:     if (!(*pDst)) {
aheinecke@60:         *pDst = xstrndup(appendage, len);
aheinecke@91:         *dst_len = len;
aheinecke@60:     } else {
aheinecke@91:         size_t new_size = (*dst_len) + len + 1;
aheinecke@91:         char *p_old = *pDst;
aheinecke@91:         *pDst = xmalloc(new_size);
aheinecke@91:         strncpy(*pDst, p_old, *dst_len);
aheinecke@91:         strncpy(*pDst + *dst_len, appendage, len);
aheinecke@91:         *dst_len = new_size - 1;
aheinecke@91:         (*pDst)[*dst_len] = '\0';
aheinecke@91:         free (p_old);
aheinecke@60:     }
aheinecke@59: }
aheinecke@59: 
aheinecke@59: void
wilde@116: strv_free (char **str_array)
aheinecke@59: {
aheinecke@59:   if (str_array)
aheinecke@59:     {
aheinecke@59:       int i;
aheinecke@59: 
aheinecke@59:       for (i = 0; str_array[i] != NULL; i++)
aheinecke@59:         free (str_array[i]);
aheinecke@59: 
aheinecke@59:       free (str_array);
aheinecke@59:     }
aheinecke@59: }
wilde@131: 
wilde@131: bool
wilde@131: str_equal (char *s1, char *s2)
wilde@131: {
wilde@143:   size_t l1 = strlen(s1);       /* Flawfinder: ignore */
wilde@143:   size_t l2 = strlen(s2);       /* Flawfinder: ignore */
wilde@131:   if ((l1 == l2) &&
wilde@136:       (strcmp(s1, s2) == 0))
wilde@131:     return true;
wilde@131:   else
wilde@131:     return false;
wilde@131: }
wilde@131: 
wilde@131: bool
wilde@131: str_starts_with (char *s1, char *s2)
wilde@131: {
wilde@143:   size_t l2 = strlen(s2);       /* Flawfinder: ignore */
wilde@143:   if (strncmp(s1, s2, l2) == 0)
wilde@131:     return true;
wilde@131:   else
wilde@131:     return false;
wilde@131: }
wilde@133: 
wilde@133: void
wilde@133: str_trim (char **s)
wilde@133: {
wilde@133:   size_t i;
wilde@135:   if (*s != NULL)
wilde@135:     {
wilde@135:       while (isspace(**s))
wilde@135:         (*s)++;
wilde@143:       i = strlen(*s);           /* Flawfinder: ignore */
wilde@135:       while (isspace((*s)[--i]))
wilde@135:         (*s)[i] = '\0';
wilde@135:     }
wilde@133: }
aheinecke@160: 
aheinecke@160: int str_base64_decode(char **dst, size_t *dst_size, char *src,
aheinecke@160:                       size_t src_size)
aheinecke@160: {
aheinecke@160:     int ret = -1;
aheinecke@160: 
aheinecke@160:     if (!dst || *dst) {
aheinecke@160:         return -1;
aheinecke@160:     }
aheinecke@160: 
aheinecke@160:     /* Check the needed size for the buffer */
aheinecke@160:     ret = base64_decode(NULL, dst_size,
aheinecke@160:                         (unsigned char *)src, src_size);
aheinecke@160: 
aheinecke@160:     if (ret != 0 && ret != POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL) {
aheinecke@160:         return ret;
aheinecke@160:     }
aheinecke@160: 
aheinecke@160:     *dst = xmalloc(*dst_size);
aheinecke@160:     memset (*dst, 0, *dst_size);
aheinecke@160: 
aheinecke@160:     ret = base64_decode((unsigned char *)*dst, dst_size,
aheinecke@160:                         (unsigned char *)src, src_size);
aheinecke@183:     if (ret) {
aheinecke@160:         free (*dst);
aheinecke@160:         *dst = NULL;
aheinecke@183:         *dst_size = 0;
aheinecke@160:     }
aheinecke@160:     return ret;
aheinecke@160: }
aheinecke@251: 
aheinecke@251: void
aheinecke@251: xfree (void *p)
aheinecke@251: {
aheinecke@251:   if (p)
aheinecke@251:     free (p);
aheinecke@251: }
aheinecke@251: 
wilde@319: int
wilde@319: xasprintf (char **strp, const char *fmt, ...)
wilde@319: {
wilde@319:   int ret;
wilde@319:   va_list ap;
wilde@319:   va_start(ap, fmt);
wilde@319:   ret = vasprintf(strp, fmt, ap);
wilde@319:   va_end(ap);
wilde@319: 
wilde@319:   if (ret == -1)
wilde@319:     out_of_core();
wilde@319: 
wilde@319:   return ret;
wilde@319: }
wilde@319: 
aheinecke@251: #ifdef WIN32
aheinecke@251: /* Adapted from GPGOL rev. e512053 */
aheinecke@251: char *
aheinecke@251: wchar_to_utf8 (const wchar_t *string, size_t len)
aheinecke@251: {
aheinecke@251:   int n, ilen;
aheinecke@251:   char *result;
aheinecke@251: 
aheinecke@251:   ilen = (int) len;
aheinecke@251:   if (ilen < 0)
aheinecke@251:     return NULL;
aheinecke@251: 
aheinecke@251:   /* Note, that CP_UTF8 is not defined in Windows versions earlier
aheinecke@251:      than NT.*/
aheinecke@251:   n = WideCharToMultiByte (CP_UTF8, 0, string, ilen, NULL, 0, NULL, NULL);
aheinecke@251:   if (n < 0)
aheinecke@251:     return NULL;
aheinecke@251: 
aheinecke@251:   result = xmalloc ((size_t)n+1);
aheinecke@251:   n = WideCharToMultiByte (CP_UTF8, 0, string, ilen, result, n, NULL, NULL);
aheinecke@251:   if (n < 0)
aheinecke@251:     {
aheinecke@251:       xfree (result);
aheinecke@251:       return NULL;
aheinecke@251:     }
aheinecke@288:   result[n] = 0;
aheinecke@251:   return result;
aheinecke@251: }
aheinecke@251: 
aheinecke@251: /* Adapted from GPGOL rev. e512053 */
aheinecke@251: wchar_t *
aheinecke@251: utf8_to_wchar (const char *string, size_t len)
aheinecke@251: {
aheinecke@251:   int n, ilen;
aheinecke@251:   wchar_t *result;
aheinecke@251: 
aheinecke@251:   ilen = (int) len;
aheinecke@251:   if (ilen < 0)
aheinecke@251:     return NULL;
aheinecke@251: 
aheinecke@251:   n = MultiByteToWideChar (CP_UTF8, 0, string, ilen, NULL, 0);
aheinecke@251:   if (n < 0 || n + 1 < 0)
aheinecke@251:     return NULL;
aheinecke@251: 
aheinecke@251:   result = xmalloc ((size_t)(n+1) * sizeof *result);
aheinecke@251:   n = MultiByteToWideChar (CP_UTF8, 0, string, ilen, result, n);
aheinecke@251:   if (n < 0)
aheinecke@251:     {
aheinecke@251:       xfree (result);
aheinecke@251:       return NULL;
aheinecke@251:     }
aheinecke@251:   result[n] = 0;
aheinecke@251:   return result;
aheinecke@251: }
aheinecke@251: #endif