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