Fixing gcc [CygWin] compiler warnings
[privoxy.git] / encode.c
1 const char encode_rcs[] = "$Id: encode.c,v 1.3 2001/11/13 00:16:40 jongfoster Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/encode.c,v $
5  *
6  * Purpose     :  Functions to encode and decode URLs, and also to
7  *                encode cookies and HTML text.
8  *
9  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
10  *                IJBSWA team.  http://ijbswa.sourceforge.net
11  *
12  *                Based on the Internet Junkbuster originally written
13  *                by and Copyright (C) 1997 Anonymous Coders and 
14  *                Junkbusters Corporation.  http://www.junkbusters.com
15  *
16  *                This program is free software; you can redistribute it 
17  *                and/or modify it under the terms of the GNU General
18  *                Public License as published by the Free Software
19  *                Foundation; either version 2 of the License, or (at
20  *                your option) any later version.
21  *
22  *                This program is distributed in the hope that it will
23  *                be useful, but WITHOUT ANY WARRANTY; without even the
24  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
25  *                PARTICULAR PURPOSE.  See the GNU General Public
26  *                License for more details.
27  *
28  *                The GNU General Public License should be included with
29  *                this file.  If not, you can view it at
30  *                http://www.gnu.org/copyleft/gpl.html
31  *                or write to the Free Software Foundation, Inc., 59
32  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
33  *
34  * Revisions   :
35  *    $Log: encode.c,v $
36  *    Revision 1.3  2001/11/13 00:16:40  jongfoster
37  *    Replacing references to malloc.h with the standard stdlib.h
38  *    (See ANSI or K&R 2nd Ed)
39  *
40  *    Revision 1.2  2001/05/17 22:52:35  oes
41  *     - Cleaned CRLF's from the sources and related files
42  *
43  *    Revision 1.1.1.1  2001/05/15 13:58:51  oes
44  *    Initial import of version 2.9.3 source tree
45  *
46  *
47  *********************************************************************/
48 \f
49
50 #include "config.h"
51
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55
56 #include "encode.h"
57
58 const char encode_h_rcs[] = ENCODE_H_VERSION;
59
60 /* Maps special characters in a URL to their equivalent % codes. */
61 static const char * const url_code_map[256] = {
62    NULL, "%01", "%02", "%03", "%04", "%05", "%06", "%07", "%08", "%09",
63    "%0A", "%0B", "%0C", "%0D", "%0E", "%0F", "%10", "%11", "%12", "%13",
64    "%14", "%15", "%16", "%17", "%18", "%19", "%1A", "%1B", "%1C", "%1D",
65    "%1E", "%1F", "+",   "%21", "%22", "%23", "%24", "%25", "%26", "%27",
66    "%28", "%29", NULL,  "%2B", "%2C", NULL,  NULL,  "%2F", NULL,  NULL,
67    NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  "%3A", "%3B",
68    "%3C", "%3D", "%3E", "%3F", NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
69    NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
70    NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
71    NULL,  "%5B", "%5C", "%5D", "%5E", NULL,  "%60", NULL,  NULL,  NULL,
72    NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
73    NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
74    NULL,  NULL,  NULL,  "%7B", "%7C", "%7D", "%7E", "%7F", "%80", "%81",
75    "%82", "%83", "%84", "%85", "%86", "%87", "%88", "%89", "%8A", "%8B",
76    "%8C", "%8D", "%8E", "%8F", "%90", "%91", "%92", "%93", "%94", "%95",
77    "%96", "%97", "%98", "%99", "%9A", "%9B", "%9C", "%9D", "%9E", "%9F",
78    "%A0", "%A1", "%A2", "%A3", "%A4", "%A5", "%A6", "%A7", "%A8", "%A9",
79    "%AA", "%AB", "%AC", "%AD", "%AE", "%AF", "%B0", "%B1", "%B2", "%B3",
80    "%B4", "%B5", "%B6", "%B7", "%B8", "%B9", "%BA", "%BB", "%BC", "%BD",
81    "%BE", "%BF", "%C0", "%C1", "%C2", "%C3", "%C4", "%C5", "%C6", "%C7",
82    "%C8", "%C9", "%CA", "%CB", "%CC", "%CD", "%CE", "%CF", "%D0", "%D1",
83    "%D2", "%D3", "%D4", "%D5", "%D6", "%D7", "%D8", "%D9", "%DA", "%DB",
84    "%DC", "%DD", "%DE", "%DF", "%E0", "%E1", "%E2", "%E3", "%E4", "%E5",
85    "%E6", "%E7", "%E8", "%E9", "%EA", "%EB", "%EC", "%ED", "%EE", "%EF",
86    "%F0", "%F1", "%F2", "%F3", "%F4", "%F5", "%F6", "%F7", "%F8", "%F9",
87    "%FA", "%FB", "%FC", "%FD", "%FE", "%FF"
88 };
89
90 /* Maps special characters in HTML to their equivalent entites. */
91 static const char * const html_code_map[256] = {
92    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
93    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
94    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
95    NULL, NULL, NULL, NULL,"&quot;",NULL,NULL,NULL,"&amp;",NULL,
96    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
97    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
98    "&lt;",NULL,"&gt;",NULL,NULL, NULL, NULL, NULL, NULL, NULL,
99    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
100    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
101    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
102    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
103    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
104    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
105    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
106    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
107    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
108    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
109    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
110    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
111    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
112    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
113    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
114    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
115    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
116    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
117    NULL, NULL, NULL, NULL, NULL, NULL
118 };
119
120 /* Maps special characters in a cookie to their equivalent % codes. */
121 static const char * const cookie_code_map[256] = {
122    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
123    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
124    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
125    NULL, NULL, "+",  NULL, NULL, NULL, NULL, NULL, NULL, NULL,
126    NULL, NULL, NULL, NULL, "%2C",NULL, NULL, NULL, NULL, NULL,
127    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "%3B",
128    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
129    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
130    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
131    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
132    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
133    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
134    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
135    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
136    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
137    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
138    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
139    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
140    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
141    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
142    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
143    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
144    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
145    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
146    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
147    NULL, NULL, NULL, NULL, NULL, NULL
148 };
149
150
151 /*********************************************************************
152  *
153  * Function    :  html_encode
154  *
155  * Description :  Encodes a string so it's not interpreted as
156  *                containing HTML tags or entities.
157  *                Replaces <, >, &, and " with the appropriate HTML
158  *                entities.
159  *
160  * Parameters  :
161  *          1  :  s = String to encode.  Null-terminated.
162  *
163  * Returns     :  Encoded string, newly allocated on the heap. 
164  *                Caller is responsible for freeing it with free().
165  *                If s is NULL, or on out-of memory, returns NULL.
166  *
167  *********************************************************************/
168 char * html_encode(const char *s)
169 {
170    char * buf;
171    
172    if (s == NULL)
173    {
174       return NULL;
175    }
176
177    /* each input char can expand to at most 6 chars */
178    buf = (char *) malloc((strlen(s) * 6) + 1);
179
180    if (buf)
181    {
182       char c;
183       char * p = buf;
184       while ( (c = *s++) != '\0')
185       {
186          const char * replace_with = html_code_map[(unsigned char) c];
187          if(replace_with != NULL)
188          {
189             strcpy(p, replace_with);
190             p += strlen(replace_with);
191          }
192          else
193          {
194             *p++ = c;
195          }
196       }
197
198       *p = '\0';
199    }
200
201    return(buf);
202 }
203
204
205 /*********************************************************************
206  *
207  * Function    :  html_encode_and_free_original
208  *
209  * Description :  Encodes a string so it's not interpreted as
210  *                containing HTML tags or entities.
211  *                Replaces <, >, &, and " with the appropriate HTML
212  *                entities.  Free()s original string.
213  *                If original string is NULL, simply returns NULL.
214  *
215  * Parameters  :
216  *          1  :  s = String to encode.  Null-terminated.
217  *
218  * Returns     :  Encoded string, newly allocated on the heap. 
219  *                Caller is responsible for freeing it with free().
220  *                If s is NULL, or on out-of memory, returns NULL.
221  *
222  *********************************************************************/
223 char * html_encode_and_free_original(char *s)
224 {
225    char * result;
226    
227    if (s == NULL)
228    {
229       return NULL;
230    }
231
232    result = html_encode(s);
233    free(s);
234
235    return result;
236 }
237
238
239 /*********************************************************************
240  *
241  * Function    :  cookie_encode
242  *
243  * Description :  Encodes a string so it can be used in a cookie.
244  *                Replaces " ", ",", and ";" with the appropriate
245  *                codes.
246  *
247  * Parameters  :
248  *          1  :  s = String to encode.  Null-terminated.
249  *
250  * Returns     :  Encoded string, newly allocated on the heap. 
251  *                Caller is responsible for freeing it with free().
252  *                If s is NULL, or on out-of memory, returns NULL.
253  *
254  *********************************************************************/
255 char * cookie_encode(const char *s)
256 {
257    char * buf;
258
259    if (s == NULL)
260    {
261       return NULL;
262    }
263
264    /* each input char can expand to at most 3 chars */
265    buf = (char *) malloc((strlen(s) * 3) + 1);
266
267    if (buf)
268    {
269       char c;
270       char * p = buf;
271       while ( (c = *s++) != '\0')
272       {
273          const char * replace_with = cookie_code_map[(unsigned char) c];
274          if (replace_with != NULL)
275          {
276             strcpy(p, replace_with);
277             p += strlen(replace_with);
278          }
279          else
280          {
281             *p++ = c;
282          }
283       }
284
285       *p = '\0';
286    }
287
288    return(buf);
289 }
290
291 /*********************************************************************
292  *
293  * Function    :  url_encode
294  *
295  * Description :  Encodes a string so it can be used in a URL
296  *                query string.  Replaces special characters with
297  *                the appropriate %xx codes.
298  *
299  * Parameters  :
300  *          1  :  s = String to encode.  Null-terminated.
301  *
302  * Returns     :  Encoded string, newly allocated on the heap. 
303  *                Caller is responsible for freeing it with free().
304  *                If s is NULL, or on out-of memory, returns NULL.
305  *
306  *********************************************************************/
307 char * url_encode(const char *s)
308 {
309    char * buf;
310
311    if (s == NULL)
312    {
313       return NULL;
314    }
315
316    /* each input char can expand to at most 3 chars */
317    buf = (char *) malloc((strlen(s) * 3) + 1);
318
319    if (buf)
320    {
321       char c;
322       char * p = buf;
323       while( (c = *s++) != '\0')
324       {
325          const char * replace_with = url_code_map[(unsigned char) c];
326          if (replace_with != NULL)
327          {
328             strcpy(p, replace_with);
329             p += strlen(replace_with);
330          }
331          else
332          {
333             *p++ = c;
334          }
335       }
336
337       *p = '\0';
338
339    }
340
341    return(buf);
342 }
343
344
345 /*********************************************************************
346  *
347  * Function    :  xdtoi
348  *
349  * Description :  Converts a single hex digit to an integer.
350  *
351  * Parameters  :
352  *          1  :  d = in the range of ['0'..'9', 'A'..'F', 'a'..'f']
353  *
354  * Returns     :  The integer value, or -1 for non-hex characters.
355  *
356  *********************************************************************/
357 static int xdtoi(char d)
358 {
359    if ((d >= '0') && (d <= '9'))
360    {
361       return(d - '0');
362    }
363    else if ((d >= 'a') && (d <= 'f')) 
364    {
365       return(d - 'a' + 10);
366    }
367    else if ((d >= 'A') && (d <= 'F'))
368    {
369       return(d - 'A' + 10);
370    }
371    else
372    {
373       return(-1);
374    }
375 }
376
377
378 /*********************************************************************
379  *
380  * Function    :  xtoi
381  *
382  * Description :  Hex string to integer conversion.
383  *
384  * Parameters  :
385  *          1  :  s = a 2 digit hex string (e.g. "1f").  Only the
386  *                    first two characters will be looked at.
387  *
388  * Returns     :  The integer value, or 0 for non-hex strings.
389  *
390  *********************************************************************/
391 static int xtoi(const char *s)
392 {
393    int d1, d2;
394
395    d1 = xdtoi(*s++);
396    if(d1 >= 0)
397    {
398       d2 = xdtoi(*s);
399       if(d2 >= 0)
400       {
401          return (d1 << 4) + d2;
402       }
403    }
404
405    return 0;
406 }
407
408
409 /*********************************************************************
410  *
411  * Function    :  url_decode
412  *
413  * Description :  Decodes a URL query string, replacing %xx codes
414  *                with their decoded form.
415  *
416  * Parameters  :
417  *          1  :  s = String to decode.  Null-terminated.
418  *
419  * Returns     :  Decoded string, newly allocated on the heap. 
420  *                Caller is responsible for freeing it with free().
421  *
422  *********************************************************************/
423 char *url_decode(const char * s)
424 {
425    char *buf = malloc(strlen(s) + 1);
426    char *q = buf;
427
428    if (buf)
429    {
430       while (*s)
431       {
432          switch (*s)
433          {
434             case '+':
435                s++;
436                *q++ = ' ';
437                break;
438
439             case '%':
440                if ((*q = xtoi(s + 1)))
441                {
442                   s += 3;
443                   q++;
444                }
445                else
446                {
447                   /* malformed, just use it */
448                   *q++ = *s++;
449                }
450                break;
451
452             default:
453                *q++ = *s++;
454                break;
455          }
456       }
457       *q = '\0';
458    }
459
460    return(buf);
461
462 }
463
464
465 /*
466   Local Variables:
467   tab-width: 3
468   end:
469 */