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