- Remove filter_client_header() and filter_client_header(),
[privoxy.git] / encode.c
1 const char encode_rcs[] = "$Id: encode.c,v 1.10 2006/07/18 14:48:45 david__schmidt 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  *                Privoxy team. http://www.privoxy.org/
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.10  2006/07/18 14:48:45  david__schmidt
37  *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
38  *    with what was really the latest development (the v_3_0_branch branch)
39  *
40  *    Revision 1.8  2002/03/26 22:29:54  swa
41  *    we have a new homepage!
42  *
43  *    Revision 1.7  2002/03/24 13:25:43  swa
44  *    name change related issues
45  *
46  *    Revision 1.6  2002/03/13 00:27:04  jongfoster
47  *    Killing warnings
48  *
49  *    Revision 1.5  2002/03/07 03:46:53  oes
50  *    Fixed compiler warnings etc
51  *
52  *    Revision 1.4  2002/01/22 23:28:07  jongfoster
53  *    Adding convenience function html_encode_and_free_original()
54  *    Making all functions accept NULL paramaters - in this case, they
55  *    simply return NULL.  This allows error-checking to be deferred.
56  *
57  *    Revision 1.3  2001/11/13 00:16:40  jongfoster
58  *    Replacing references to malloc.h with the standard stdlib.h
59  *    (See ANSI or K&R 2nd Ed)
60  *
61  *    Revision 1.2  2001/05/17 22:52:35  oes
62  *     - Cleaned CRLF's from the sources and related files
63  *
64  *    Revision 1.1.1.1  2001/05/15 13:58:51  oes
65  *    Initial import of version 2.9.3 source tree
66  *
67  *
68  *********************************************************************/
69 \f
70
71 #include "config.h"
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76
77 #include "encode.h"
78
79 const char encode_h_rcs[] = ENCODE_H_VERSION;
80
81 /* Maps special characters in a URL to their equivalent % codes. */
82 static const char * const url_code_map[256] = {
83    NULL, "%01", "%02", "%03", "%04", "%05", "%06", "%07", "%08", "%09",
84    "%0A", "%0B", "%0C", "%0D", "%0E", "%0F", "%10", "%11", "%12", "%13",
85    "%14", "%15", "%16", "%17", "%18", "%19", "%1A", "%1B", "%1C", "%1D",
86    "%1E", "%1F", "+",   "%21", "%22", "%23", "%24", "%25", "%26", "%27",
87    "%28", "%29", NULL,  "%2B", "%2C", NULL,  NULL,  "%2F", NULL,  NULL,
88    NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  "%3A", "%3B",
89    "%3C", "%3D", "%3E", "%3F", 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,  "%5B", "%5C", "%5D", "%5E", NULL,  "%60", 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,  "%7B", "%7C", "%7D", "%7E", "%7F", "%80", "%81",
96    "%82", "%83", "%84", "%85", "%86", "%87", "%88", "%89", "%8A", "%8B",
97    "%8C", "%8D", "%8E", "%8F", "%90", "%91", "%92", "%93", "%94", "%95",
98    "%96", "%97", "%98", "%99", "%9A", "%9B", "%9C", "%9D", "%9E", "%9F",
99    "%A0", "%A1", "%A2", "%A3", "%A4", "%A5", "%A6", "%A7", "%A8", "%A9",
100    "%AA", "%AB", "%AC", "%AD", "%AE", "%AF", "%B0", "%B1", "%B2", "%B3",
101    "%B4", "%B5", "%B6", "%B7", "%B8", "%B9", "%BA", "%BB", "%BC", "%BD",
102    "%BE", "%BF", "%C0", "%C1", "%C2", "%C3", "%C4", "%C5", "%C6", "%C7",
103    "%C8", "%C9", "%CA", "%CB", "%CC", "%CD", "%CE", "%CF", "%D0", "%D1",
104    "%D2", "%D3", "%D4", "%D5", "%D6", "%D7", "%D8", "%D9", "%DA", "%DB",
105    "%DC", "%DD", "%DE", "%DF", "%E0", "%E1", "%E2", "%E3", "%E4", "%E5",
106    "%E6", "%E7", "%E8", "%E9", "%EA", "%EB", "%EC", "%ED", "%EE", "%EF",
107    "%F0", "%F1", "%F2", "%F3", "%F4", "%F5", "%F6", "%F7", "%F8", "%F9",
108    "%FA", "%FB", "%FC", "%FD", "%FE", "%FF"
109 };
110
111 /* Maps special characters in HTML to their equivalent entites. */
112 static const char * const html_code_map[256] = {
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,"&quot;",NULL,NULL,NULL,"&amp;",NULL,
117    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
118    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
119    "&lt;",NULL,"&gt;",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, NULL, NULL, NULL, NULL,
138    NULL, NULL, NULL, NULL, NULL, NULL
139 };
140
141 /* Maps special characters in a cookie to their equivalent % codes. */
142 static const char * const cookie_code_map[256] = {
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,
147    NULL, NULL, NULL, NULL, "%2C",NULL, NULL, NULL, NULL, NULL,
148    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "%3B",
149    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
150    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
151    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
152    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
153    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
154    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
155    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
156    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
157    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
158    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
159    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
160    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
161    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
162    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
163    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
164    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
165    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
166    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
167    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
168    NULL, NULL, NULL, NULL, NULL, NULL
169 };
170
171
172 /*********************************************************************
173  *
174  * Function    :  html_encode
175  *
176  * Description :  Encodes a string so it's not interpreted as
177  *                containing HTML tags or entities.
178  *                Replaces <, >, &, and " with the appropriate HTML
179  *                entities.
180  *
181  * Parameters  :
182  *          1  :  s = String to encode.  Null-terminated.
183  *
184  * Returns     :  Encoded string, newly allocated on the heap. 
185  *                Caller is responsible for freeing it with free().
186  *                If s is NULL, or on out-of memory, returns NULL.
187  *
188  *********************************************************************/
189 char * html_encode(const char *s)
190 {
191    char * buf;
192    
193    if (s == NULL)
194    {
195       return NULL;
196    }
197
198    /* each input char can expand to at most 6 chars */
199    buf = (char *) malloc((strlen(s) * 6) + 1);
200
201    if (buf)
202    {
203       char c;
204       char * p = buf;
205       while ( (c = *s++) != '\0')
206       {
207          const char * replace_with = html_code_map[(unsigned char) c];
208          if(replace_with != NULL)
209          {
210             strcpy(p, replace_with);
211             p += strlen(replace_with);
212          }
213          else
214          {
215             *p++ = c;
216          }
217       }
218
219       *p = '\0';
220    }
221
222    return(buf);
223 }
224
225
226 /*********************************************************************
227  *
228  * Function    :  html_encode_and_free_original
229  *
230  * Description :  Encodes a string so it's not interpreted as
231  *                containing HTML tags or entities.
232  *                Replaces <, >, &, and " with the appropriate HTML
233  *                entities.  Free()s original string.
234  *                If original string is NULL, simply returns NULL.
235  *
236  * Parameters  :
237  *          1  :  s = String to encode.  Null-terminated.
238  *
239  * Returns     :  Encoded string, newly allocated on the heap. 
240  *                Caller is responsible for freeing it with free().
241  *                If s is NULL, or on out-of memory, returns NULL.
242  *
243  *********************************************************************/
244 char * html_encode_and_free_original(char *s)
245 {
246    char * result;
247    
248    if (s == NULL)
249    {
250       return NULL;
251    }
252
253    result = html_encode(s);
254    free(s);
255
256    return result;
257 }
258
259
260 /*********************************************************************
261  *
262  * Function    :  cookie_encode
263  *
264  * Description :  Encodes a string so it can be used in a cookie.
265  *                Replaces " ", ",", and ";" with the appropriate
266  *                codes.
267  *
268  * Parameters  :
269  *          1  :  s = String to encode.  Null-terminated.
270  *
271  * Returns     :  Encoded string, newly allocated on the heap. 
272  *                Caller is responsible for freeing it with free().
273  *                If s is NULL, or on out-of memory, returns NULL.
274  *
275  *********************************************************************/
276 char * cookie_encode(const char *s)
277 {
278    char * buf;
279
280    if (s == NULL)
281    {
282       return NULL;
283    }
284
285    /* each input char can expand to at most 3 chars */
286    buf = (char *) malloc((strlen(s) * 3) + 1);
287
288    if (buf)
289    {
290       char c;
291       char * p = buf;
292       while ( (c = *s++) != '\0')
293       {
294          const char * replace_with = cookie_code_map[(unsigned char) c];
295          if (replace_with != NULL)
296          {
297             strcpy(p, replace_with);
298             p += strlen(replace_with);
299          }
300          else
301          {
302             *p++ = c;
303          }
304       }
305
306       *p = '\0';
307    }
308
309    return(buf);
310 }
311
312 /*********************************************************************
313  *
314  * Function    :  url_encode
315  *
316  * Description :  Encodes a string so it can be used in a URL
317  *                query string.  Replaces special characters with
318  *                the appropriate %xx codes.
319  *
320  * Parameters  :
321  *          1  :  s = String to encode.  Null-terminated.
322  *
323  * Returns     :  Encoded string, newly allocated on the heap. 
324  *                Caller is responsible for freeing it with free().
325  *                If s is NULL, or on out-of memory, returns NULL.
326  *
327  *********************************************************************/
328 char * url_encode(const char *s)
329 {
330    char * buf;
331
332    if (s == NULL)
333    {
334       return NULL;
335    }
336
337    /* each input char can expand to at most 3 chars */
338    buf = (char *) malloc((strlen(s) * 3) + 1);
339
340    if (buf)
341    {
342       char c;
343       char * p = buf;
344       while( (c = *s++) != '\0')
345       {
346          const char * replace_with = url_code_map[(unsigned char) c];
347          if (replace_with != NULL)
348          {
349             strcpy(p, replace_with);
350             p += strlen(replace_with);
351          }
352          else
353          {
354             *p++ = c;
355          }
356       }
357
358       *p = '\0';
359
360    }
361
362    return(buf);
363 }
364
365
366 /*********************************************************************
367  *
368  * Function    :  xdtoi
369  *
370  * Description :  Converts a single hex digit to an integer.
371  *
372  * Parameters  :
373  *          1  :  d = in the range of ['0'..'9', 'A'..'F', 'a'..'f']
374  *
375  * Returns     :  The integer value, or -1 for non-hex characters.
376  *
377  *********************************************************************/
378 static int xdtoi(const int d)
379 {
380    if ((d >= '0') && (d <= '9'))
381    {
382       return(d - '0');
383    }
384    else if ((d >= 'a') && (d <= 'f')) 
385    {
386       return(d - 'a' + 10);
387    }
388    else if ((d >= 'A') && (d <= 'F'))
389    {
390       return(d - 'A' + 10);
391    }
392    else
393    {
394       return(-1);
395    }
396 }
397
398
399 /*********************************************************************
400  *
401  * Function    :  xtoi
402  *
403  * Description :  Hex string to integer conversion.
404  *
405  * Parameters  :
406  *          1  :  s = a 2 digit hex string (e.g. "1f").  Only the
407  *                    first two characters will be looked at.
408  *
409  * Returns     :  The integer value, or 0 for non-hex strings.
410  *
411  *********************************************************************/
412 static int xtoi(const char *s)
413 {
414    int d1, d2;
415
416    d1 = xdtoi(*s);
417    if(d1 >= 0)
418    {
419       d2 = xdtoi(*(s+1));
420       if(d2 >= 0)
421       {
422          return (d1 << 4) + d2;
423       }
424    }
425
426    return 0;
427 }
428
429
430 /*********************************************************************
431  *
432  * Function    :  url_decode
433  *
434  * Description :  Decodes a URL query string, replacing %xx codes
435  *                with their decoded form.
436  *
437  * Parameters  :
438  *          1  :  s = String to decode.  Null-terminated.
439  *
440  * Returns     :  Decoded string, newly allocated on the heap. 
441  *                Caller is responsible for freeing it with free().
442  *
443  *********************************************************************/
444 char *url_decode(const char * s)
445 {
446    char *buf = malloc(strlen(s) + 1);
447    char *q = buf;
448
449    if (buf)
450    {
451       while (*s)
452       {
453          switch (*s)
454          {
455             case '+':
456                s++;
457                *q++ = ' ';
458                break;
459
460             case '%':
461                if ((*q = (char)xtoi(s + 1)) != '\0')
462                {
463                   s += 3;
464                   q++;
465                }
466                else
467                {
468                   /* malformed, just use it */
469                   *q++ = *s++;
470                }
471                break;
472
473             default:
474                *q++ = *s++;
475                break;
476          }
477       }
478       *q = '\0';
479    }
480
481    return(buf);
482
483 }
484
485
486 /*
487   Local Variables:
488   tab-width: 3
489   end:
490 */