Fixing a compiler warning
[privoxy.git] / encode.c
1 const char encode_rcs[] = "$Id: encode.c,v 1.2 2001/05/17 22:52:35 oes 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.2  2001/05/17 22:52:35  oes
37  *     - Cleaned CRLF's from the sources and related files
38  *
39  *    Revision 1.1.1.1  2001/05/15 13:58:51  oes
40  *    Initial import of version 2.9.3 source tree
41  *
42  *
43  *********************************************************************/
44 \f
45
46 #include "config.h"
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51
52 #include "encode.h"
53
54 const char encode_h_rcs[] = ENCODE_H_VERSION;
55
56 /* Maps special characters in a URL to their equivalent % codes. */
57 static const char * const url_code_map[256] = {
58    NULL, "%01", "%02", "%03", "%04", "%05", "%06", "%07", "%08", "%09",
59    "%0A", "%0B", "%0C", "%0D", "%0E", "%0F", "%10", "%11", "%12", "%13",
60    "%14", "%15", "%16", "%17", "%18", "%19", "%1A", "%1B", "%1C", "%1D",
61    "%1E", "%1F", "+",   "%21", "%22", "%23", "%24", "%25", "%26", "%27",
62    "%28", "%29", NULL,  "%2B", "%2C", NULL,  NULL,  "%2F", NULL,  NULL,
63    NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  "%3A", "%3B",
64    "%3C", "%3D", "%3E", "%3F", NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
65    NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
66    NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
67    NULL,  "%5B", "%5C", "%5D", "%5E", NULL,  "%60", NULL,  NULL,  NULL,
68    NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
69    NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,
70    NULL,  NULL,  NULL,  "%7B", "%7C", "%7D", "%7E", "%7F", "%80", "%81",
71    "%82", "%83", "%84", "%85", "%86", "%87", "%88", "%89", "%8A", "%8B",
72    "%8C", "%8D", "%8E", "%8F", "%90", "%91", "%92", "%93", "%94", "%95",
73    "%96", "%97", "%98", "%99", "%9A", "%9B", "%9C", "%9D", "%9E", "%9F",
74    "%A0", "%A1", "%A2", "%A3", "%A4", "%A5", "%A6", "%A7", "%A8", "%A9",
75    "%AA", "%AB", "%AC", "%AD", "%AE", "%AF", "%B0", "%B1", "%B2", "%B3",
76    "%B4", "%B5", "%B6", "%B7", "%B8", "%B9", "%BA", "%BB", "%BC", "%BD",
77    "%BE", "%BF", "%C0", "%C1", "%C2", "%C3", "%C4", "%C5", "%C6", "%C7",
78    "%C8", "%C9", "%CA", "%CB", "%CC", "%CD", "%CE", "%CF", "%D0", "%D1",
79    "%D2", "%D3", "%D4", "%D5", "%D6", "%D7", "%D8", "%D9", "%DA", "%DB",
80    "%DC", "%DD", "%DE", "%DF", "%E0", "%E1", "%E2", "%E3", "%E4", "%E5",
81    "%E6", "%E7", "%E8", "%E9", "%EA", "%EB", "%EC", "%ED", "%EE", "%EF",
82    "%F0", "%F1", "%F2", "%F3", "%F4", "%F5", "%F6", "%F7", "%F8", "%F9",
83    "%FA", "%FB", "%FC", "%FD", "%FE", "%FF"
84 };
85
86 /* Maps special characters in HTML to their equivalent entites. */
87 static const char * const html_code_map[256] = {
88    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
89    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
90    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
91    NULL, NULL, NULL, NULL,"&quot;",NULL,NULL,NULL,"&amp;",NULL,
92    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
93    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
94    "&lt;",NULL,"&gt;",NULL,NULL, NULL, NULL, NULL, NULL, NULL,
95    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
96    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
97    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
98    NULL, NULL, NULL, 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
114 };
115
116 /* Maps special characters in a cookie to their equivalent % codes. */
117 static const char * const cookie_code_map[256] = {
118    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
119    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
120    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
121    NULL, NULL, "+",  NULL, NULL, NULL, NULL, NULL, NULL, NULL,
122    NULL, NULL, NULL, NULL, "%2C",NULL, NULL, NULL, NULL, NULL,
123    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "%3B",
124    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
125    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
126    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
127    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
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
144 };
145
146
147 /*********************************************************************
148  *
149  * Function    :  html_encode
150  *
151  * Description :  Encodes a string so it's not interpreted as
152  *                containing HTML tags or entities.
153  *                Replaces <, >, &, and " with the appropriate HTML
154  *                entities.
155  *
156  * Parameters  :
157  *          1  :  s = String to encode.  Null-terminated.
158  *
159  * Returns     :  Encoded string, newly allocated on the heap. 
160  *                Caller is responsible for freeing it with free().
161  *
162  *********************************************************************/
163 char * html_encode(const char *s)
164 {
165    /* each input char can expand to at most 6 chars */
166    char * buf = (char *) malloc((strlen(s) * 6) + 1);
167
168    if (buf)
169    {
170       char c;
171       char * p = buf;
172       while ( (c = *s++) != '\0')
173       {
174          const char * replace_with = html_code_map[(unsigned char) c];
175          if(replace_with != NULL)
176          {
177             strcpy(p, replace_with);
178             p += strlen(replace_with);
179          }
180          else
181          {
182             *p++ = c;
183          }
184       }
185
186       *p = '\0';
187    }
188
189    return(buf);
190 }
191
192 /*********************************************************************
193  *
194  * Function    :  cookie_encode
195  *
196  * Description :  Encodes a string so it can be used in a cookie.
197  *                Replaces " ", ",", and ";" with the appropriate
198  *                codes.
199  *
200  * Parameters  :
201  *          1  :  s = String to encode.  Null-terminated.
202  *
203  * Returns     :  Encoded string, newly allocated on the heap. 
204  *                Caller is responsible for freeing it with free().
205  *
206  *********************************************************************/
207 char * cookie_encode(const char *s)
208 {
209    /* each input char can expand to at most 3 chars */
210    char * buf = (char *) malloc((strlen(s) * 3) + 1);
211
212    if (buf)
213    {
214       char c;
215       char * p = buf;
216       while ( (c = *s++) != '\0')
217       {
218          const char * replace_with = cookie_code_map[(unsigned char) c];
219          if (replace_with != NULL)
220          {
221             strcpy(p, replace_with);
222             p += strlen(replace_with);
223          }
224          else
225          {
226             *p++ = c;
227          }
228       }
229
230       *p = '\0';
231    }
232
233    return(buf);
234 }
235
236 /*********************************************************************
237  *
238  * Function    :  url_encode
239  *
240  * Description :  Encodes a string so it can be used in a URL
241  *                query string.  Replaces special characters with
242  *                the appropriate %xx codes.
243  *
244  * Parameters  :
245  *          1  :  s = String to encode.  Null-terminated.
246  *
247  * Returns     :  Encoded string, newly allocated on the heap. 
248  *                Caller is responsible for freeing it with free().
249  *
250  *********************************************************************/
251 char * url_encode(const char *s)
252 {
253    /* each input char can expand to at most 3 chars */
254    char * buf = (char *) malloc((strlen(s) * 3) + 1);
255
256    if (buf)
257    {
258       char c;
259       char * p = buf;
260       while( (c = *s++) != '\0')
261       {
262          const char * replace_with = url_code_map[(unsigned char) c];
263          if (replace_with != NULL)
264          {
265             strcpy(p, replace_with);
266             p += strlen(replace_with);
267          }
268          else
269          {
270             *p++ = c;
271          }
272       }
273
274       *p = '\0';
275
276    }
277
278    return(buf);
279 }
280
281
282 /*********************************************************************
283  *
284  * Function    :  xdtoi
285  *
286  * Description :  Converts a single hex digit to an integer.
287  *
288  * Parameters  :
289  *          1  :  d = in the range of ['0'..'9', 'A'..'F', 'a'..'f']
290  *
291  * Returns     :  The integer value, or -1 for non-hex characters.
292  *
293  *********************************************************************/
294 static int xdtoi(char d)
295 {
296    if ((d >= '0') && (d <= '9'))
297    {
298       return(d - '0');
299    }
300    else if ((d >= 'a') && (d <= 'f')) 
301    {
302       return(d - 'a' + 10);
303    }
304    else if ((d >= 'A') && (d <= 'F'))
305    {
306       return(d - 'A' + 10);
307    }
308    else
309    {
310       return(-1);
311    }
312 }
313
314
315 /*********************************************************************
316  *
317  * Function    :  xtoi
318  *
319  * Description :  Hex string to integer conversion.
320  *
321  * Parameters  :
322  *          1  :  s = a 2 digit hex string (e.g. "1f").  Only the
323  *                    first two characters will be looked at.
324  *
325  * Returns     :  The integer value, or 0 for non-hex strings.
326  *
327  *********************************************************************/
328 static int xtoi(const char *s)
329 {
330    int d1, d2;
331
332    d1 = xdtoi(*s++);
333    if(d1 >= 0)
334    {
335       d2 = xdtoi(*s);
336       if(d2 >= 0)
337       {
338          return (d1 << 4) + d2;
339       }
340    }
341
342    return 0;
343 }
344
345
346 /*********************************************************************
347  *
348  * Function    :  url_decode
349  *
350  * Description :  Decodes a URL query string, replacing %xx codes
351  *                with their decoded form.
352  *
353  * Parameters  :
354  *          1  :  s = String to decode.  Null-terminated.
355  *
356  * Returns     :  Decoded string, newly allocated on the heap. 
357  *                Caller is responsible for freeing it with free().
358  *
359  *********************************************************************/
360 char *url_decode(const char * s)
361 {
362    char *buf = malloc(strlen(s) + 1);
363    char *q = buf;
364
365    if (buf)
366    {
367       while (*s)
368       {
369          switch (*s)
370          {
371             case '+':
372                s++;
373                *q++ = ' ';
374                break;
375
376             case '%':
377                if ((*q = xtoi(s + 1)))
378                {
379                   s += 3;
380                   q++;
381                }
382                else
383                {
384                   /* malformed, just use it */
385                   *q++ = *s++;
386                }
387                break;
388
389             default:
390                *q++ = *s++;
391                break;
392          }
393       }
394       *q = '\0';
395    }
396
397    return(buf);
398
399 }
400
401
402 /*
403   Local Variables:
404   tab-width: 3
405   end:
406 */