117df5286ffa5b98c84801f8df69e1b3a57eae87
[gpgme.git] / gpgme / conversion.c
1 /* conversion.c - String conversion helper functions.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003 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 General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (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    General Public License for more details.
16  
17    You should have received a copy of the GNU General Public License
18    along with GPGME; if not, write to the Free Software Foundation,
19    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "gpgme.h"
29 #include "util.h"
30
31 \f
32 /* Convert two hexadecimal digits from STR to the value they
33    represent.  Returns -1 if one of the characters is not a
34    hexadecimal digit.  */
35 int
36 _gpgme_hextobyte (const unsigned char *str)
37 {
38   int val = 0;
39   int i;
40
41 #define NROFHEXDIGITS 2
42   for (i = 0; i < NROFHEXDIGITS; i++)
43     {
44       if (*str >= '0' && *str <= '9')
45         val += *str - '0';
46       else if (*str >= 'A' && *str <= 'F')
47         val += 10 + *str - 'A';
48       else if (*str >= 'a' && *str <= 'f')
49         val += 10 + *str - 'a';
50       else
51         return -1;
52       if (i < NROFHEXDIGITS - 1)
53         val *= 16;
54       str++;
55     }
56   return val;
57 }
58
59
60 /* Decode the C formatted string SRC and store the result in the
61    buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
62    large enough buffer is allocated with malloc and *DESTP is set to
63    the result.  Currently, LEN is only used to specify if allocation
64    is desired or not, the caller is expected to make sure that *DESTP
65    is large enough if LEN is not zero.  */
66 gpgme_error_t
67 _gpgme_decode_c_string (const char *src, char **destp, int len)
68 {
69   char *dest;
70
71   /* Set up the destination buffer.  */
72   if (len)
73     {
74       if (len < strlen (src) + 1)
75         return GPGME_General_Error;
76
77       dest = *destp;
78     }
79   else
80     {
81       /* The converted string will never be larger than the original
82          string.  */
83       dest = malloc (strlen (src) + 1);
84       if (!dest)
85         return GPGME_Out_Of_Core;
86
87       *destp = dest;
88     }
89
90   /* Convert the string.  */
91   while (*src)
92     {
93       if (*src != '\\')
94         {
95           *(dest++) = *(src++);
96           continue;
97         }
98
99       switch (src[1])
100         {
101 #define DECODE_ONE(match,result)        \
102         case match:                     \
103           src += 2;                     \
104           *(dest++) = result;           \
105           break;
106
107           DECODE_ONE ('\'', '\'');
108           DECODE_ONE ('\"', '\"');
109           DECODE_ONE ('\?', '\?');
110           DECODE_ONE ('\\', '\\');
111           DECODE_ONE ('a', '\a');
112           DECODE_ONE ('b', '\b');
113           DECODE_ONE ('f', '\f');
114           DECODE_ONE ('n', '\n');
115           DECODE_ONE ('r', '\r');
116           DECODE_ONE ('t', '\t');
117           DECODE_ONE ('v', '\v');
118
119         case 'x':
120           {
121             int val = _gpgme_hextobyte (&src[2]);
122
123             if (val == -1)
124               {
125                 /* Should not happen.  */
126                 *(dest++) = *(src++);
127                 *(dest++) = *(src++);
128                 if (*src)
129                   *(dest++) = *(src++);
130                 if (*src)
131                   *(dest++) = *(src++);
132               }
133             else
134               {
135                 if (!val)
136                   {
137                     /* A binary zero is not representable in a C
138                        string.  */
139                     *(dest++) = '\\';
140                     *(dest++) = '0'; 
141                   }
142                 else 
143                   *((unsigned char *) dest++) = val;
144                 src += 4;
145               }
146           }
147           break;
148
149         default:
150           {
151             /* Should not happen.  */
152             *(dest++) = *(src++);
153             *(dest++) = *(src++);
154           }
155         } 
156     }
157   *(dest++) = 0;
158
159   return 0;
160 }
161
162
163 /* Decode the percent escaped string SRC and store the result in the
164    buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
165    large enough buffer is allocated with malloc and *DESTP is set to
166    the result.  Currently, LEN is only used to specify if allocation
167    is desired or not, the caller is expected to make sure that *DESTP
168    is large enough if LEN is not zero.  */
169 gpgme_error_t
170 _gpgme_decode_percent_string (const char *src, char **destp, int len)
171 {
172   char *dest;
173
174   /* Set up the destination buffer.  */
175   if (len)
176     {
177       if (len < strlen (src) + 1)
178         return GPGME_General_Error;
179
180       dest = *destp;
181     }
182   else
183     {
184       /* The converted string will never be larger than the original
185          string.  */
186       dest = malloc (strlen (src) + 1);
187       if (!dest)
188         return GPGME_Out_Of_Core;
189
190       *destp = dest;
191     }
192
193   /* Convert the string.  */
194   while (*src)
195     {
196       if (*src != '%')
197         {
198           *(dest++) = *(src++);
199           continue;
200         }
201       else
202         {
203           int val = _gpgme_hextobyte (&src[1]);
204           
205           if (val == -1)
206             {
207               /* Should not happen.  */
208               *(dest++) = *(src++);
209               if (*src)
210                 *(dest++) = *(src++);
211               if (*src)
212                 *(dest++) = *(src++);
213             }
214           else
215             {
216               if (!val)
217                 {
218                   /* A binary zero is not representable in a C
219                      string.  */
220                   *(dest++) = '\\';
221                   *(dest++) = '0'; 
222                 }
223               else 
224                 *((unsigned char *) dest++) = val;
225               src += 3;
226             }
227         }
228     }
229   *(dest++) = 0;
230
231   return 0;
232 }
233
234 \f
235 static struct
236 {
237   char *name;
238   gpgme_error_t err;
239 } gnupg_errors[] =
240   {
241     { "EOF", GPGME_EOF },
242     { "No_Error", GPGME_No_Error },
243     { "General_Error", GPGME_General_Error },
244     { "Out_Of_Core", GPGME_Out_Of_Core },
245     { "Invalid_Value", GPGME_Invalid_Value },
246     { "IO_Error", GPGME_General_Error },
247     { "Resource_Limit", GPGME_General_Error },
248     { "Internal_Error", GPGME_General_Error },
249     { "Bad_Certificate", GPGME_Invalid_Key },
250     { "Bad_Certificate_Chain", GPGME_General_Error },
251     { "Missing_Certificate", GPGME_No_Public_Key },
252     { "No_Data", GPGME_No_Data },
253     { "Bad_Signature", GPGME_Bad_Signature },
254     { "Not_Implemented", GPGME_Not_Implemented },
255     { "Conflict", GPGME_Conflict },
256     { "Bug", GPGME_General_Error },
257     { "Read_Error", GPGME_General_Error },
258     { "Write_Error", GPGME_General_Error },
259     { "Invalid_Line", GPGME_General_Error },
260     { "Incomplete_Line", GPGME_General_Error },
261     { "Invalid_Response", GPGME_General_Error },
262     { "Agent_Error", GPGME_General_Error },
263     { "No_Public_Key", GPGME_No_Public_Key },
264     { "No_Secret_Key", GPGME_No_Secret_Key },
265     { "File_Open_Error", GPGME_General_Error },
266     { "File_Create_Error", GPGME_General_Error },
267     { "File_Error", GPGME_General_Error },
268     { "Not_Supported", GPGME_General_Error },
269     { "Invalid_Data", GPGME_General_Error },
270     { "Assuan_Server_Fault", GPGME_General_Error },
271     { "Assuan_Error", GPGME_General_Error },
272     { "Invalid_Session_Key", GPGME_General_Error },
273     { "Invalid_Sexp", GPGME_General_Error },
274     { "Unsupported_Algorithm", GPGME_Unsupported_Algorithm },
275     { "No_PIN_Entry", GPGME_Invalid_Engine },
276     { "PIN_Entry_Error", GPGME_Invalid_Engine },
277     { "Bad_PIN", GPGME_Bad_Passphrase },
278     { "Bad_Passphrase", GPGME_Bad_Passphrase },
279     { "Invalid_Name", GPGME_General_Error },
280     { "Bad_Public_Key", GPGME_General_Error },
281     { "Bad_Secret_Key", GPGME_General_Error },
282     { "Bad_Data", GPGME_General_Error },
283     { "Invalid_Parameter", GPGME_General_Error },
284     { "Tribute_to_D_A", GPGME_General_Error },
285     { "No_Dirmngr", GPGME_Invalid_Engine },
286     { "Dirmngr_Error", GPGME_General_Error },
287     { "Certificate_Revoked", GPGME_Key_Revoked },
288     { "No_CRL_Known", GPGME_No_CRL_Known },
289     { "CRL_Too_Old", GPGME_CRL_Too_Old },
290     { "Line_Too_Long", GPGME_General_Error },
291     { "Not_Trusted", GPGME_Key_Not_Trusted },
292     { "Canceled", GPGME_Canceled },
293     { "Bad_CA_Certificate", GPGME_General_Error },
294     { "Certificate_Expired", GPGME_Key_Expired },
295     { "Certificate_Too_Young", GPGME_Invalid_Key },
296     { "Unsupported_Certificate", GPGME_General_Error },
297     { "Unknown_Sexp", GPGME_General_Error },
298     { "Unsupported_Protection", GPGME_General_Error },
299     { "Corrupted_Protection", GPGME_General_Error },
300     { "Ambiguous_Name", GPGME_Ambiguous_Specification },
301     { "Card_Error", GPGME_General_Error },
302     { "Card_Reset", GPGME_General_Error },
303     { "Card_Removed", GPGME_General_Error },
304     { "Invalid_Card", GPGME_General_Error },
305     { "Card_Not_Present", GPGME_General_Error },
306     { "No_PKCS15_App", GPGME_General_Error },
307     { "Not_Confirmed", GPGME_General_Error },
308     { "Configuration_Error", GPGME_General_Error },
309     { "No_Policy_Match", GPGME_Policy_Mismatch },
310     { "Invalid_Index", GPGME_General_Error },
311     { "Invalid_Id", GPGME_General_Error },
312     { "No_Scdaemon", GPGME_Invalid_Engine },
313     { "Scdaemon_Error", GPGME_General_Error },
314     { "Unsupported_Protocol", GPGME_General_Error },
315     { "Bad_PIN_Method", GPGME_General_Error },
316     { "Card_Not_Initialized", GPGME_General_Error },
317     { "Unsupported_Operation", GPGME_General_Error },
318     { "Wrong_Key_Usage", GPGME_Wrong_Key_Usage }
319   };
320     
321
322 gpgme_error_t
323 _gpgme_map_gnupg_error (char *err)
324 {
325   int i;
326
327   for (i = 0; i < DIM (gnupg_errors); i++)
328     if (!strcmp (gnupg_errors[i].name, err))
329       return gnupg_errors[i].err;
330
331   return GPGME_General_Error;
332 }