LCOV - code coverage report
Current view: top level - src - conversion.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 100 170 58.8 %
Date: 2016-09-12 13:07:23 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /* conversion.c - String conversion helper functions.
       2             :    Copyright (C) 2000 Werner Koch (dd9jn)
       3             :    Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH
       4             : 
       5             :    This file is part of GPGME.
       6             : 
       7             :    GPGME is free software; you can redistribute it and/or modify it
       8             :    under the terms of the GNU Lesser General Public License as
       9             :    published by the Free Software Foundation; either version 2.1 of
      10             :    the License, or (at your option) any later version.
      11             : 
      12             :    GPGME is distributed in the hope that it will be useful, but
      13             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :    Lesser General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU Lesser General Public
      18             :    License along with this program; if not, write to the Free Software
      19             :    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      20             :    02111-1307, USA.  */
      21             : 
      22             : #if HAVE_CONFIG_H
      23             : #include <config.h>
      24             : #endif
      25             : 
      26             : #include <stdlib.h>
      27             : #include <string.h>
      28             : #ifdef HAVE_SYS_TYPES_H
      29             :   /* Solaris 8 needs sys/types.h before time.h.  */
      30             : # include <sys/types.h>
      31             : #endif
      32             : #include <time.h>
      33             : #include <errno.h>
      34             : 
      35             : #include "gpgme.h"
      36             : #include "util.h"
      37             : #include "debug.h"
      38             : 
      39             : #define atoi_1(p)   (*(p) - '0' )
      40             : #define atoi_2(p)   ((atoi_1(p) * 10) + atoi_1((p)+1))
      41             : #define atoi_4(p)   ((atoi_2(p) * 100) + atoi_2((p)+2))
      42             : 
      43             : 
      44             : 
      45             : /* Convert two hexadecimal digits from STR to the value they
      46             :    represent.  Returns -1 if one of the characters is not a
      47             :    hexadecimal digit.  */
      48             : int
      49         143 : _gpgme_hextobyte (const char *str)
      50             : {
      51         143 :   int val = 0;
      52             :   int i;
      53             : 
      54             : #define NROFHEXDIGITS 2
      55         429 :   for (i = 0; i < NROFHEXDIGITS; i++)
      56             :     {
      57         286 :       if (*str >= '0' && *str <= '9')
      58         248 :         val += *str - '0';
      59          38 :       else if (*str >= 'A' && *str <= 'F')
      60          36 :         val += 10 + *str - 'A';
      61           2 :       else if (*str >= 'a' && *str <= 'f')
      62           2 :         val += 10 + *str - 'a';
      63             :       else
      64           0 :         return -1;
      65         286 :       if (i < NROFHEXDIGITS - 1)
      66         143 :         val *= 16;
      67         286 :       str++;
      68             :     }
      69         143 :   return val;
      70             : }
      71             : 
      72             : 
      73             : /* Decode the C formatted string SRC and store the result in the
      74             :    buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
      75             :    large enough buffer is allocated with malloc and *DESTP is set to
      76             :    the result.  Currently, LEN is only used to specify if allocation
      77             :    is desired or not, the caller is expected to make sure that *DESTP
      78             :    is large enough if LEN is not zero.  */
      79             : gpgme_error_t
      80         363 : _gpgme_decode_c_string (const char *src, char **destp, size_t len)
      81             : {
      82             :   char *dest;
      83             : 
      84             :   /* Set up the destination buffer.  */
      85         363 :   if (len)
      86             :     {
      87         357 :       if (len < strlen (src) + 1)
      88           0 :         return gpg_error (GPG_ERR_INTERNAL);
      89             : 
      90         357 :       dest = *destp;
      91             :     }
      92             :   else
      93             :     {
      94             :       /* The converted string will never be larger than the original
      95             :          string.  */
      96           6 :       dest = malloc (strlen (src) + 1);
      97           6 :       if (!dest)
      98           0 :         return gpg_error_from_syserror ();
      99             : 
     100           6 :       *destp = dest;
     101             :     }
     102             : 
     103             :   /* Convert the string.  */
     104       13776 :   while (*src)
     105             :     {
     106       13050 :       if (*src != '\\')
     107             :         {
     108       13048 :           *(dest++) = *(src++);
     109       13048 :           continue;
     110             :         }
     111             : 
     112           2 :       switch (src[1])
     113             :         {
     114             : #define DECODE_ONE(match,result)        \
     115             :         case match:                     \
     116             :           src += 2;                     \
     117             :           *(dest++) = result;           \
     118             :           break;
     119             : 
     120           0 :           DECODE_ONE ('\'', '\'');
     121           0 :           DECODE_ONE ('\"', '\"');
     122           0 :           DECODE_ONE ('\?', '\?');
     123           0 :           DECODE_ONE ('\\', '\\');
     124           0 :           DECODE_ONE ('a', '\a');
     125           0 :           DECODE_ONE ('b', '\b');
     126           0 :           DECODE_ONE ('f', '\f');
     127           0 :           DECODE_ONE ('n', '\n');
     128           0 :           DECODE_ONE ('r', '\r');
     129           0 :           DECODE_ONE ('t', '\t');
     130           0 :           DECODE_ONE ('v', '\v');
     131             : 
     132             :         case 'x':
     133             :           {
     134           2 :             int val = _gpgme_hextobyte (&src[2]);
     135             : 
     136           2 :             if (val == -1)
     137             :               {
     138             :                 /* Should not happen.  */
     139           0 :                 *(dest++) = *(src++);
     140           0 :                 *(dest++) = *(src++);
     141           0 :                 if (*src)
     142           0 :                   *(dest++) = *(src++);
     143           0 :                 if (*src)
     144           0 :                   *(dest++) = *(src++);
     145             :               }
     146             :             else
     147             :               {
     148           2 :                 if (!val)
     149             :                   {
     150             :                     /* A binary zero is not representable in a C
     151             :                        string.  */
     152           0 :                     *(dest++) = '\\';
     153           0 :                     *(dest++) = '0';
     154             :                   }
     155             :                 else
     156           2 :                   *((unsigned char *) dest++) = val;
     157           2 :                 src += 4;
     158             :               }
     159             :           }
     160           2 :           break;
     161             : 
     162             :         default:
     163             :           {
     164             :             /* Should not happen.  */
     165           0 :             *(dest++) = *(src++);
     166           0 :             *(dest++) = *(src++);
     167             :           }
     168             :         }
     169             :     }
     170         363 :   *(dest++) = 0;
     171             : 
     172         363 :   return 0;
     173             : }
     174             : 
     175             : 
     176             : /* Decode the percent escaped string SRC and store the result in the
     177             :    buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
     178             :    large enough buffer is allocated with malloc and *DESTP is set to
     179             :    the result.  Currently, LEN is only used to specify if allocation
     180             :    is desired or not, the caller is expected to make sure that *DESTP
     181             :    is large enough if LEN is not zero.  If BINARY is 1, then '\0'
     182             :    characters are allowed in the output.  */
     183             : gpgme_error_t
     184        1022 : _gpgme_decode_percent_string (const char *src, char **destp, size_t len,
     185             :                               int binary)
     186             : {
     187             :   char *dest;
     188             : 
     189             :   /* Set up the destination buffer.  */
     190        1022 :   if (len)
     191             :     {
     192         971 :       if (len < strlen (src) + 1)
     193           0 :         return gpg_error (GPG_ERR_INTERNAL);
     194             : 
     195         971 :       dest = *destp;
     196             :     }
     197             :   else
     198             :     {
     199             :       /* The converted string will never be larger than the original
     200             :          string.  */
     201          51 :       dest = malloc (strlen (src) + 1);
     202          51 :       if (!dest)
     203           0 :         return gpg_error_from_syserror ();
     204             : 
     205          51 :       *destp = dest;
     206             :     }
     207             : 
     208             :   /* Convert the string.  */
     209       33327 :   while (*src)
     210             :     {
     211       31283 :       if (*src != '%')
     212             :         {
     213       31183 :           *(dest++) = *(src++);
     214       31183 :           continue;
     215             :         }
     216             :       else
     217             :         {
     218         100 :           int val = _gpgme_hextobyte (&src[1]);
     219             : 
     220         100 :           if (val == -1)
     221             :             {
     222             :               /* Should not happen.  */
     223           0 :               *(dest++) = *(src++);
     224           0 :               if (*src)
     225           0 :                 *(dest++) = *(src++);
     226           0 :               if (*src)
     227           0 :                 *(dest++) = *(src++);
     228             :             }
     229             :           else
     230             :             {
     231         100 :               if (!val && !binary)
     232             :                 {
     233             :                   /* A binary zero is not representable in a C
     234             :                      string.  */
     235           0 :                   *(dest++) = '\\';
     236           0 :                   *(dest++) = '0';
     237             :                 }
     238             :               else
     239         100 :                 *((unsigned char *) dest++) = val;
     240         100 :               src += 3;
     241             :             }
     242             :         }
     243             :     }
     244        1022 :   *(dest++) = 0;
     245             : 
     246        1022 :   return 0;
     247             : }
     248             : 
     249             : 
     250             : /* Encode the string SRC with percent escaping and store the result in
     251             :    the buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
     252             :    large enough buffer is allocated with malloc and *DESTP is set to
     253             :    the result.  Currently, LEN is only used to specify if allocation
     254             :    is desired or not, the caller is expected to make sure that *DESTP
     255             :    is large enough if LEN is not zero.  If BINARY is 1, then '\0'
     256             :    characters are allowed in the output.  */
     257             : gpgme_error_t
     258           0 : _gpgme_encode_percent_string (const char *src, char **destp, size_t len)
     259             : {
     260             :   size_t destlen;
     261             :   char *dest;
     262             :   const char *str;
     263             : 
     264           0 :   destlen = 0;
     265           0 :   str = src;
     266             :   /* We percent-escape the + character because the user might need a
     267             :      "percent plus" escaped string (special gpg format).  But we
     268             :      percent-escape the space character, which works with and without
     269             :      the special plus format.  */
     270           0 :   while (*str)
     271             :     {
     272           0 :       if (*str == '+' || *str == '\"' || *str == '%'
     273           0 :           || *(const unsigned char *)str <= 0x20)
     274           0 :         destlen += 3;
     275             :       else
     276           0 :         destlen++;
     277           0 :       str++;
     278             :     }
     279             :   /* Terminating nul byte.  */
     280           0 :   destlen++;
     281             : 
     282             :   /* Set up the destination buffer.  */
     283           0 :   if (len)
     284             :     {
     285           0 :       if (len < destlen)
     286           0 :         return gpg_error (GPG_ERR_INTERNAL);
     287             : 
     288           0 :       dest = *destp;
     289             :     }
     290             :   else
     291             :     {
     292             :       /* The converted string will never be larger than the original
     293             :          string.  */
     294           0 :       dest = malloc (destlen);
     295           0 :       if (!dest)
     296           0 :         return gpg_error_from_syserror ();
     297             : 
     298           0 :       *destp = dest;
     299             :     }
     300             : 
     301             :   /* Convert the string.  */
     302           0 :   while (*src)
     303             :     {
     304           0 :       if (*src == '+' || *src == '\"' || *src == '%'
     305           0 :           || *(const unsigned char *)src <= 0x20)
     306             :         {
     307           0 :           snprintf (dest, 4, "%%%02X", *(unsigned char *)src);
     308           0 :           dest += 3;
     309             :         }
     310             :       else
     311           0 :         *(dest++) = *src;
     312           0 :       src++;
     313             :     }
     314           0 :   *(dest++) = 0;
     315             : 
     316           0 :   return 0;
     317             : }
     318             : 
     319             : 
     320             : /* Split a string into space delimited fields and remove leading and
     321             :  * trailing spaces from each field.  A pointer to the each field is
     322             :  * stored in ARRAY.  Stop splitting at ARRAYSIZE fields.  The function
     323             :  * modifies STRING.  The number of parsed fields is returned.
     324             :  */
     325             : int
     326          29 : _gpgme_split_fields (char *string, char **array, int arraysize)
     327             : {
     328          29 :   int n = 0;
     329             :   char *p, *pend;
     330             : 
     331          29 :   for (p = string; *p == ' '; p++)
     332             :     ;
     333             :   do
     334             :     {
     335         118 :       if (n == arraysize)
     336           0 :         break;
     337         118 :       array[n++] = p;
     338         118 :       pend = strchr (p, ' ');
     339         118 :       if (!pend)
     340          29 :         break;
     341          89 :       *pend++ = 0;
     342          89 :       for (p = pend; *p == ' '; p++)
     343             :         ;
     344             :     }
     345          89 :   while (*p);
     346             : 
     347          29 :   return n;
     348             : }
     349             : 
     350             : /* Convert the field STRING into an unsigned long value.  Check for
     351             :  * trailing garbage.  */
     352             : gpgme_error_t
     353         110 : _gpgme_strtoul_field (const char *string, unsigned long *result)
     354             : {
     355             :   char *endp;
     356             : 
     357         110 :   gpg_err_set_errno (0);
     358         110 :   *result = strtoul (string, &endp, 0);
     359         110 :   if (errno)
     360           0 :     return gpg_error_from_syserror ();
     361         110 :   if (endp == string || *endp)
     362           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     363         110 :   return 0;
     364             : }
     365             : 
     366             : 
     367             : /* Convert STRING into an offset value.  Note that this functions only
     368             :  * allows for a base-10 length.  This function is similar to atoi()
     369             :  * and thus there is no error checking.  */
     370             : gpgme_off_t
     371          64 : _gpgme_string_to_off (const char *string)
     372             : {
     373          64 :   gpgme_off_t value = 0;
     374             : 
     375         128 :   while (*string == ' ' || *string == '\t')
     376           0 :     string++;
     377         156 :   for (; *string >= '0' && *string <= '9'; string++)
     378             :     {
     379          92 :       value *= 10;
     380          92 :       value += atoi_1 (string);
     381             :     }
     382          64 :   return value;
     383             : }
     384             : 
     385             : 
     386             : #ifdef HAVE_W32_SYSTEM
     387             : static time_t
     388             : _gpgme_timegm (struct tm *tm)
     389             : {
     390             :   /* This one is thread safe.  */
     391             :   SYSTEMTIME st;
     392             :   FILETIME ft;
     393             :   unsigned long long cnsecs;
     394             : 
     395             :   st.wYear   = tm->tm_year + 1900;
     396             :   st.wMonth  = tm->tm_mon  + 1;
     397             :   st.wDay    = tm->tm_mday;
     398             :   st.wHour   = tm->tm_hour;
     399             :   st.wMinute = tm->tm_min;
     400             :   st.wSecond = tm->tm_sec;
     401             :   st.wMilliseconds = 0; /* Not available.  */
     402             :   st.wDayOfWeek = 0;    /* Ignored.  */
     403             : 
     404             :   /* System time is UTC thus the conversion is pretty easy.  */
     405             :   if (!SystemTimeToFileTime (&st, &ft))
     406             :     {
     407             :       gpg_err_set_errno (EINVAL);
     408             :       return (time_t)(-1);
     409             :     }
     410             : 
     411             :   cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
     412             :             | ft.dwLowDateTime);
     413             :   cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01.  */
     414             :   return (time_t)(cnsecs / 10000000ULL);
     415             : }
     416             : #endif
     417             : 
     418             : 
     419             : /* Parse the string TIMESTAMP into a time_t.  The string may either be
     420             :    seconds since Epoch or in the ISO 8601 format like
     421             :    "20390815T143012".  Returns 0 for an empty string or seconds since
     422             :    Epoch. Leading spaces are skipped. If ENDP is not NULL, it will
     423             :    point to the next non-parsed character in TIMESTRING. */
     424             : time_t
     425         868 : _gpgme_parse_timestamp (const char *timestamp, char **endp)
     426             : {
     427             :   /* Need to skip leading spaces, because that is what strtoul does
     428             :      but not our ISO 8601 checking code. */
     429        1834 :   while (*timestamp && *timestamp== ' ')
     430          98 :     timestamp++;
     431         868 :   if (!*timestamp)
     432         371 :     return 0;
     433             : 
     434         497 :   if (strlen (timestamp) >= 15 && timestamp[8] == 'T')
     435             :     {
     436             :       struct tm buf;
     437             :       int year;
     438             : 
     439          15 :       year = atoi_4 (timestamp);
     440          15 :       if (year < 1900)
     441           0 :         return (time_t)(-1);
     442             : 
     443          15 :       if (endp)
     444           3 :         *endp = (char*)(timestamp + 15);
     445             : 
     446             :       /* Fixme: We would better use a configure test to see whether
     447             :          mktime can handle dates beyond 2038. */
     448             :       if (sizeof (time_t) <= 4 && year >= 2038)
     449             :         return (time_t)2145914603; /* 2037-12-31 23:23:23 */
     450             : 
     451          15 :       memset (&buf, 0, sizeof buf);
     452          15 :       buf.tm_year = year - 1900;
     453          15 :       buf.tm_mon = atoi_2 (timestamp+4) - 1;
     454          15 :       buf.tm_mday = atoi_2 (timestamp+6);
     455          15 :       buf.tm_hour = atoi_2 (timestamp+9);
     456          15 :       buf.tm_min = atoi_2 (timestamp+11);
     457          15 :       buf.tm_sec = atoi_2 (timestamp+13);
     458             : 
     459             : #ifdef HAVE_W32_SYSTEM
     460             :       return _gpgme_timegm (&buf);
     461             : #else
     462             : #ifdef HAVE_TIMEGM
     463          15 :       return timegm (&buf);
     464             : #else
     465             :       {
     466             :         time_t tim;
     467             : 
     468             :         putenv ("TZ=UTC");
     469             :         tim = mktime (&buf);
     470             : #ifdef __GNUC__
     471             : #warning fixme: we must somehow reset TZ here.  It is not threadsafe anyway.
     472             : #endif
     473             :         return tim;
     474             :       }
     475             : #endif /* !HAVE_TIMEGM */
     476             : #endif /* !HAVE_W32_SYSTEM */
     477             :     }
     478             :   else
     479         482 :     return (time_t)strtoul (timestamp, endp, 10);
     480             : }
     481             : 
     482             : 
     483             : /* The GPG backend uses OpenPGP algorithm numbers which we need to map
     484             :    to our algorithm numbers.  This function MUST not change ERRNO. */
     485             : int
     486         489 : _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol)
     487             : {
     488         489 :   if (protocol == GPGME_PROTOCOL_OPENPGP)
     489             :     {
     490         479 :       switch (algo)
     491             :         {
     492         479 :         case 1: case 2: case 3: case 16: case 17: break;
     493           0 :         case 18: algo = GPGME_PK_ECDH; break;
     494           0 :         case 19: algo = GPGME_PK_ECDSA; break;
     495           0 :         case 20: break;
     496           0 :         case 22: algo = GPGME_PK_EDDSA; break;
     497           0 :         default: algo = 0; break; /* Unknown.  */
     498             :         }
     499             :     }
     500             : 
     501         489 :   return algo;
     502             : }

Generated by: LCOV version 1.11