LCOV - code coverage report
Current view: top level - src - conversion.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 75 141 53.2 %
Date: 2015-11-05 17:14:26 Functions: 5 6 83.3 %

          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          44 : _gpgme_hextobyte (const char *str)
      50             : {
      51          44 :   int val = 0;
      52             :   int i;
      53             : 
      54             : #define NROFHEXDIGITS 2
      55         132 :   for (i = 0; i < NROFHEXDIGITS; i++)
      56             :     {
      57          88 :       if (*str >= '0' && *str <= '9')
      58          65 :         val += *str - '0';
      59          23 :       else if (*str >= 'A' && *str <= 'F')
      60          21 :         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          88 :       if (i < NROFHEXDIGITS - 1)
      66          44 :         val *= 16;
      67          88 :       str++;
      68             :     }
      69          44 :   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         190 : _gpgme_decode_c_string (const char *src, char **destp, size_t len)
      81             : {
      82             :   char *dest;
      83             : 
      84             :   /* Set up the destination buffer.  */
      85         190 :   if (len)
      86             :     {
      87         184 :       if (len < strlen (src) + 1)
      88           0 :         return gpg_error (GPG_ERR_INTERNAL);
      89             : 
      90         184 :       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        7218 :   while (*src)
     105             :     {
     106        6838 :       if (*src != '\\')
     107             :         {
     108        6836 :           *(dest++) = *(src++);
     109        6836 :           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         190 :   *(dest++) = 0;
     171             : 
     172         190 :   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         459 : _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         459 :   if (len)
     191             :     {
     192         453 :       if (len < strlen (src) + 1)
     193           0 :         return gpg_error (GPG_ERR_INTERNAL);
     194             : 
     195         453 :       dest = *destp;
     196             :     }
     197             :   else
     198             :     {
     199             :       /* The converted string will never be larger than the original
     200             :          string.  */
     201           6 :       dest = malloc (strlen (src) + 1);
     202           6 :       if (!dest)
     203           0 :         return gpg_error_from_syserror ();
     204             : 
     205           6 :       *destp = dest;
     206             :     }
     207             : 
     208             :   /* Convert the string.  */
     209       12956 :   while (*src)
     210             :     {
     211       12038 :       if (*src != '%')
     212             :         {
     213       12021 :           *(dest++) = *(src++);
     214       12021 :           continue;
     215             :         }
     216             :       else
     217             :         {
     218          17 :           int val = _gpgme_hextobyte (&src[1]);
     219             : 
     220          17 :           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          17 :               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          17 :                 *((unsigned char *) dest++) = val;
     240          17 :               src += 3;
     241             :             }
     242             :         }
     243             :     }
     244         459 :   *(dest++) = 0;
     245             : 
     246         459 :   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             : #ifdef HAVE_W32_SYSTEM
     321             : static time_t
     322             : _gpgme_timegm (struct tm *tm)
     323             : {
     324             :   /* This one is thread safe.  */
     325             :   SYSTEMTIME st;
     326             :   FILETIME ft;
     327             :   unsigned long long cnsecs;
     328             : 
     329             :   st.wYear   = tm->tm_year + 1900;
     330             :   st.wMonth  = tm->tm_mon  + 1;
     331             :   st.wDay    = tm->tm_mday;
     332             :   st.wHour   = tm->tm_hour;
     333             :   st.wMinute = tm->tm_min;
     334             :   st.wSecond = tm->tm_sec;
     335             :   st.wMilliseconds = 0; /* Not available.  */
     336             :   st.wDayOfWeek = 0;    /* Ignored.  */
     337             : 
     338             :   /* System time is UTC thus the conversion is pretty easy.  */
     339             :   if (!SystemTimeToFileTime (&st, &ft))
     340             :     {
     341             :       gpg_err_set_errno (EINVAL);
     342             :       return (time_t)(-1);
     343             :     }
     344             : 
     345             :   cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
     346             :             | ft.dwLowDateTime);
     347             :   cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01.  */
     348             :   return (time_t)(cnsecs / 10000000ULL);
     349             : }
     350             : #endif
     351             : 
     352             : 
     353             : /* Parse the string TIMESTAMP into a time_t.  The string may either be
     354             :    seconds since Epoch or in the ISO 8601 format like
     355             :    "20390815T143012".  Returns 0 for an empty string or seconds since
     356             :    Epoch. Leading spaces are skipped. If ENDP is not NULL, it will
     357             :    point to the next non-parsed character in TIMESTRING. */
     358             : time_t
     359         376 : _gpgme_parse_timestamp (const char *timestamp, char **endp)
     360             : {
     361             :   /* Need to skip leading spaces, because that is what strtoul does
     362             :      but not our ISO 8601 checking code. */
     363         776 :   while (*timestamp && *timestamp== ' ')
     364          24 :     timestamp++;
     365         376 :   if (!*timestamp)
     366         168 :     return 0;
     367             : 
     368         208 :   if (strlen (timestamp) >= 15 && timestamp[8] == 'T')
     369             :     {
     370             :       struct tm buf;
     371             :       int year;
     372             : 
     373          15 :       year = atoi_4 (timestamp);
     374          15 :       if (year < 1900)
     375           0 :         return (time_t)(-1);
     376             : 
     377          15 :       if (endp)
     378           3 :         *endp = (char*)(timestamp + 15);
     379             : 
     380             :       /* Fixme: We would better use a configure test to see whether
     381             :          mktime can handle dates beyond 2038. */
     382             :       if (sizeof (time_t) <= 4 && year >= 2038)
     383             :         return (time_t)2145914603; /* 2037-12-31 23:23:23 */
     384             : 
     385          15 :       memset (&buf, 0, sizeof buf);
     386          15 :       buf.tm_year = year - 1900;
     387          15 :       buf.tm_mon = atoi_2 (timestamp+4) - 1;
     388          15 :       buf.tm_mday = atoi_2 (timestamp+6);
     389          15 :       buf.tm_hour = atoi_2 (timestamp+9);
     390          15 :       buf.tm_min = atoi_2 (timestamp+11);
     391          15 :       buf.tm_sec = atoi_2 (timestamp+13);
     392             : 
     393             : #ifdef HAVE_W32_SYSTEM
     394             :       return _gpgme_timegm (&buf);
     395             : #else
     396             : #ifdef HAVE_TIMEGM
     397          15 :       return timegm (&buf);
     398             : #else
     399             :       {
     400             :         time_t tim;
     401             : 
     402             :         putenv ("TZ=UTC");
     403             :         tim = mktime (&buf);
     404             : #ifdef __GNUC__
     405             : #warning fixme: we must somehow reset TZ here.  It is not threadsafe anyway.
     406             : #endif
     407             :         return tim;
     408             :       }
     409             : #endif /* !HAVE_TIMEGM */
     410             : #endif /* !HAVE_W32_SYSTEM */
     411             :     }
     412             :   else
     413         193 :     return (time_t)strtoul (timestamp, endp, 10);
     414             : }
     415             : 
     416             : 
     417             : /* The GPG backend uses OpenPGP algorithm numbers which we need to map
     418             :    to our algorithm numbers.  This function MUST not change ERRNO. */
     419             : int
     420         219 : _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol)
     421             : {
     422         219 :   if (protocol == GPGME_PROTOCOL_OPENPGP)
     423             :     {
     424         209 :       switch (algo)
     425             :         {
     426         209 :         case 1: case 2: case 3: case 16: case 17: break;
     427           0 :         case 18: algo = GPGME_PK_ECDH; break;
     428           0 :         case 19: algo = GPGME_PK_ECDSA; break;
     429           0 :         case 20: break;
     430           0 :         case 22: algo = GPGME_PK_EDDSA; break;
     431           0 :         default: algo = 0; break; /* Unknown.  */
     432             :         }
     433             :     }
     434             : 
     435         219 :   return algo;
     436             : }

Generated by: LCOV version 1.11