If all the data we got decompressed OK, but zlib wants more, filter what we got inste...
[privoxy.git] / parsers.c
1 const char parsers_rcs[] = "$Id: parsers.c,v 1.171 2009/06/01 15:33:33 fabiankeil Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/parsers.c,v $
5  *
6  * Purpose     :  Declares functions to parse/crunch headers and pages.
7  *                Functions declared include:
8  *                   `add_to_iob', `client_cookie_adder', `client_from',
9  *                   `client_referrer', `client_send_cookie', `client_ua',
10  *                   `client_uagent', `client_x_forwarded',
11  *                   `client_x_forwarded_adder', `client_xtra_adder',
12  *                   `content_type', `crumble', `destroy_list', `enlist',
13  *                   `flush_socket', ``get_header', `sed', `filter_header'
14  *                   `server_content_encoding', `server_content_disposition',
15  *                   `server_last_modified', `client_accept_language',
16  *                   `crunch_client_header', `client_if_modified_since',
17  *                   `client_if_none_match', `get_destination_from_headers',
18  *                   `parse_header_time', `decompress_iob' and `server_set_cookie'.
19  *
20  * Copyright   :  Written by and Copyright (C) 2001-2009 the
21  *                Privoxy team. http://www.privoxy.org/
22  *
23  *                Based on the Internet Junkbuster originally written
24  *                by and Copyright (C) 1997 Anonymous Coders and
25  *                Junkbusters Corporation.  http://www.junkbusters.com
26  *
27  *                This program is free software; you can redistribute it
28  *                and/or modify it under the terms of the GNU General
29  *                Public License as published by the Free Software
30  *                Foundation; either version 2 of the License, or (at
31  *                your option) any later version.
32  *
33  *                This program is distributed in the hope that it will
34  *                be useful, but WITHOUT ANY WARRANTY; without even the
35  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
36  *                PARTICULAR PURPOSE.  See the GNU General Public
37  *                License for more details.
38  *
39  *                The GNU General Public License should be included with
40  *                this file.  If not, you can view it at
41  *                http://www.gnu.org/copyleft/gpl.html
42  *                or write to the Free Software Foundation, Inc., 59
43  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
44  *
45  *********************************************************************/
46
47
48 #include "config.h"
49
50 #ifndef _WIN32
51 #include <stdio.h>
52 #include <sys/types.h>
53 #endif
54
55 #include <stdlib.h>
56 #include <ctype.h>
57 #include <assert.h>
58 #include <string.h>
59
60 #ifdef __GLIBC__
61 /*
62  * Convince GNU's libc to provide a strptime prototype.
63  */
64 #define __USE_XOPEN
65 #endif /*__GLIBC__ */
66 #include <time.h>
67
68 #ifdef FEATURE_ZLIB
69 #include <zlib.h>
70 #endif
71
72 #if !defined(_WIN32) && !defined(__OS2__)
73 #include <unistd.h>
74 #endif
75
76 #include "project.h"
77
78 #ifdef FEATURE_PTHREAD
79 #include "jcc.h"
80 /* jcc.h is for mutex semapores only */
81 #endif /* def FEATURE_PTHREAD */
82 #include "list.h"
83 #include "parsers.h"
84 #include "ssplit.h"
85 #include "errlog.h"
86 #include "jbsockets.h"
87 #include "miscutil.h"
88 #include "list.h"
89 #include "actions.h"
90 #include "filters.h"
91
92 #ifndef HAVE_STRPTIME
93 #include "strptime.h"
94 #endif
95
96 const char parsers_h_rcs[] = PARSERS_H_VERSION;
97
98 /* Fix a problem with Solaris.  There should be no effect on other
99  * platforms.
100  * Solaris's isspace() is a macro which uses its argument directly
101  * as an array index.  Therefore we need to make sure that high-bit
102  * characters generate +ve values, and ideally we also want to make
103  * the argument match the declared parameter type of "int".
104  *
105  * Why did they write a character function that can't take a simple
106  * "char" argument?  Doh!
107  */
108 #define ijb_isupper(__X) isupper((int)(unsigned char)(__X))
109 #define ijb_tolower(__X) tolower((int)(unsigned char)(__X))
110
111 static char *get_header_line(struct iob *iob);
112 static jb_err scan_headers(struct client_state *csp);
113 static jb_err header_tagger(struct client_state *csp, char *header);
114 static jb_err parse_header_time(const char *header_time, time_t *result);
115
116 static jb_err crumble                   (struct client_state *csp, char **header);
117 static jb_err filter_header             (struct client_state *csp, char **header);
118 static jb_err client_connection         (struct client_state *csp, char **header);
119 static jb_err client_referrer           (struct client_state *csp, char **header);
120 static jb_err client_uagent             (struct client_state *csp, char **header);
121 static jb_err client_ua                 (struct client_state *csp, char **header);
122 static jb_err client_from               (struct client_state *csp, char **header);
123 static jb_err client_send_cookie        (struct client_state *csp, char **header);
124 static jb_err client_x_forwarded        (struct client_state *csp, char **header);
125 static jb_err client_accept_encoding    (struct client_state *csp, char **header);
126 static jb_err client_te                 (struct client_state *csp, char **header);
127 static jb_err client_max_forwards       (struct client_state *csp, char **header);
128 static jb_err client_host               (struct client_state *csp, char **header);
129 static jb_err client_if_modified_since  (struct client_state *csp, char **header);
130 static jb_err client_accept_language    (struct client_state *csp, char **header);
131 static jb_err client_if_none_match      (struct client_state *csp, char **header);
132 static jb_err crunch_client_header      (struct client_state *csp, char **header);
133 static jb_err client_x_filter           (struct client_state *csp, char **header);
134 static jb_err client_range              (struct client_state *csp, char **header);
135 static jb_err server_set_cookie         (struct client_state *csp, char **header);
136 static jb_err server_connection         (struct client_state *csp, char **header);
137 static jb_err server_content_type       (struct client_state *csp, char **header);
138 static jb_err server_adjust_content_length(struct client_state *csp, char **header);
139 static jb_err server_content_md5        (struct client_state *csp, char **header);
140 static jb_err server_content_encoding   (struct client_state *csp, char **header);
141 static jb_err server_transfer_coding    (struct client_state *csp, char **header);
142 static jb_err server_http               (struct client_state *csp, char **header);
143 static jb_err crunch_server_header      (struct client_state *csp, char **header);
144 static jb_err server_last_modified      (struct client_state *csp, char **header);
145 static jb_err server_content_disposition(struct client_state *csp, char **header);
146
147 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
148 static jb_err server_save_content_length(struct client_state *csp, char **header);
149 static jb_err server_keep_alive(struct client_state *csp, char **header);
150 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
151
152 static jb_err client_host_adder       (struct client_state *csp);
153 static jb_err client_xtra_adder       (struct client_state *csp);
154 static jb_err client_x_forwarded_for_adder(struct client_state *csp);
155 static jb_err client_connection_header_adder(struct client_state *csp);
156 static jb_err server_connection_adder(struct client_state *csp);
157 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
158 static jb_err server_proxy_connection_adder(struct client_state *csp);
159 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
160
161 static jb_err create_forged_referrer(char **header, const char *hostport);
162 static jb_err create_fake_referrer(char **header, const char *fake_referrer);
163 static jb_err handle_conditional_hide_referrer_parameter(char **header,
164    const char *host, const int parameter_conditional_block);
165 static const char *get_appropiate_connection_header(const struct client_state *csp);
166
167 /*
168  * List of functions to run on a list of headers.
169  */
170 struct parsers
171 {
172    /** The header prefix to match */
173    const char *str;
174    
175    /** The length of the prefix to match */
176    const size_t len;
177    
178    /** The function to apply to this line */
179    const parser_func_ptr parser;
180 };
181
182 static const struct parsers client_patterns[] = {
183    { "referer:",                  8,   client_referrer },
184    { "user-agent:",              11,   client_uagent },
185    { "ua-",                       3,   client_ua },
186    { "from:",                     5,   client_from },
187    { "cookie:",                   7,   client_send_cookie },
188    { "x-forwarded-for:",         16,   client_x_forwarded },
189    { "Accept-Encoding:",         16,   client_accept_encoding },
190    { "TE:",                       3,   client_te },
191    { "Host:",                     5,   client_host },
192    { "if-modified-since:",       18,   client_if_modified_since },
193 #ifndef FEATURE_CONNECTION_KEEP_ALIVE
194    { "Keep-Alive:",              11,   crumble },
195 #endif
196    { "connection:",              11,   client_connection },
197    { "proxy-connection:",        17,   crumble },
198    { "max-forwards:",            13,   client_max_forwards },
199    { "Accept-Language:",         16,   client_accept_language },
200    { "if-none-match:",           14,   client_if_none_match },
201    { "Range:",                    6,   client_range },
202    { "Request-Range:",           14,   client_range },
203    { "If-Range:",                 9,   client_range },
204    { "X-Filter:",                 9,   client_x_filter },
205    { "*",                         0,   crunch_client_header },
206    { "*",                         0,   filter_header },
207    { NULL,                        0,   NULL }
208 };
209
210 static const struct parsers server_patterns[] = {
211    { "HTTP/",                     5, server_http },
212    { "set-cookie:",              11, server_set_cookie },
213    { "connection:",              11, server_connection },
214    { "Content-Type:",            13, server_content_type },
215    { "Content-MD5:",             12, server_content_md5 },
216    { "Content-Encoding:",        17, server_content_encoding },
217 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
218    { "Content-Length:",          15, server_save_content_length },
219    { "Keep-Alive:",              11, server_keep_alive },
220 #else
221    { "Keep-Alive:",              11, crumble },
222 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
223    { "Transfer-Encoding:",       18, server_transfer_coding },
224    { "content-disposition:",     20, server_content_disposition },
225    { "Last-Modified:",           14, server_last_modified },
226    { "*",                         0, crunch_server_header },
227    { "*",                         0, filter_header },
228    { NULL,                        0, NULL }
229 };
230
231 static const add_header_func_ptr add_client_headers[] = {
232    client_host_adder,
233    client_x_forwarded_for_adder,
234    client_xtra_adder,
235    /* Temporarily disabled:    client_accept_encoding_adder, */
236    client_connection_header_adder,
237    NULL
238 };
239
240 static const add_header_func_ptr add_server_headers[] = {
241    server_connection_adder,
242 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
243    server_proxy_connection_adder,
244 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
245    NULL
246 };
247
248 /*********************************************************************
249  *
250  * Function    :  flush_socket
251  *
252  * Description :  Write any pending "buffered" content.
253  *
254  * Parameters  :
255  *          1  :  fd = file descriptor of the socket to read
256  *          2  :  iob = The I/O buffer to flush, usually csp->iob.
257  *
258  * Returns     :  On success, the number of bytes written are returned (zero
259  *                indicates nothing was written).  On error, -1 is returned,
260  *                and errno is set appropriately.  If count is zero and the
261  *                file descriptor refers to a regular file, 0 will be
262  *                returned without causing any other effect.  For a special
263  *                file, the results are not portable.
264  *
265  *********************************************************************/
266 long flush_socket(jb_socket fd, struct iob *iob)
267 {
268    long len = iob->eod - iob->cur;
269
270    if (len <= 0)
271    {
272       return(0);
273    }
274
275    if (write_socket(fd, iob->cur, (size_t)len))
276    {
277       return(-1);
278    }
279    iob->eod = iob->cur = iob->buf;
280    return(len);
281
282 }
283
284
285 /*********************************************************************
286  *
287  * Function    :  add_to_iob
288  *
289  * Description :  Add content to the buffered page, expanding the
290  *                buffer if necessary.
291  *
292  * Parameters  :
293  *          1  :  csp = Current client state (buffers, headers, etc...)
294  *          2  :  buf = holds the content to be added to the page
295  *          3  :  n = number of bytes to be added
296  *
297  * Returns     :  JB_ERR_OK on success, JB_ERR_MEMORY if out-of-memory
298  *                or buffer limit reached.
299  *
300  *********************************************************************/
301 jb_err add_to_iob(struct client_state *csp, char *buf, long n)
302 {
303    struct iob *iob = csp->iob;
304    size_t used, offset, need, want;
305    char *p;
306
307    if (n <= 0) return JB_ERR_OK;
308
309    used   = (size_t)(iob->eod - iob->buf);
310    offset = (size_t)(iob->cur - iob->buf);
311    need   = used + (size_t)n + 1;
312
313    /*
314     * If the buffer can't hold the new data, extend it first.
315     * Use the next power of two if possible, else use the actual need.
316     */
317    if (need > csp->config->buffer_limit)
318    {
319       log_error(LOG_LEVEL_INFO,
320          "Buffer limit reached while extending the buffer (iob). Needed: %d. Limit: %d",
321          need, csp->config->buffer_limit);
322       return JB_ERR_MEMORY;
323    }
324
325    if (need > iob->size)
326    {
327       for (want = csp->iob->size ? csp->iob->size : 512; want <= need;) want *= 2;
328       
329       if (want <= csp->config->buffer_limit && NULL != (p = (char *)realloc(iob->buf, want)))
330       {
331          iob->size = want;
332       }
333       else if (NULL != (p = (char *)realloc(iob->buf, need)))
334       {
335          iob->size = need;
336       }
337       else
338       {
339          log_error(LOG_LEVEL_ERROR, "Extending the buffer (iob) failed: %E");
340          return JB_ERR_MEMORY;
341       }
342
343       /* Update the iob pointers */
344       iob->cur = p + offset;
345       iob->eod = p + used;
346       iob->buf = p;
347    }
348
349    /* copy the new data into the iob buffer */
350    memcpy(iob->eod, buf, (size_t)n);
351
352    /* point to the end of the data */
353    iob->eod += n;
354
355    /* null terminate == cheap insurance */
356    *iob->eod = '\0';
357
358    return JB_ERR_OK;
359
360 }
361
362
363 #ifdef FEATURE_ZLIB
364 /*********************************************************************
365  *
366  * Function    :  decompress_iob
367  *
368  * Description :  Decompress buffered page, expanding the
369  *                buffer as necessary.  csp->iob->cur
370  *                should point to the the beginning of the
371  *                compressed data block.
372  *
373  * Parameters  :
374  *          1  :  csp = Current client state (buffers, headers, etc...)
375  *
376  * Returns     :  JB_ERR_OK on success,
377  *                JB_ERR_MEMORY if out-of-memory limit reached, and
378  *                JB_ERR_COMPRESS if error decompressing buffer.
379  *
380  *********************************************************************/
381 jb_err decompress_iob(struct client_state *csp)
382 {
383    char  *buf;       /* new, uncompressed buffer */
384    char  *cur;       /* Current iob position (to keep the original 
385                       * iob->cur unmodified if we return early) */
386    size_t bufsize;   /* allocated size of the new buffer */
387    size_t old_size;  /* Content size before decompression */
388    size_t skip_size; /* Number of bytes at the beginning of the iob
389                         that we should NOT decompress. */
390    int status;       /* return status of the inflate() call */
391    z_stream zstr;    /* used by calls to zlib */
392
393    assert(csp->iob->cur - csp->iob->buf > 0);
394    assert(csp->iob->eod - csp->iob->cur > 0);
395
396    bufsize = csp->iob->size;
397    skip_size = (size_t)(csp->iob->cur - csp->iob->buf);
398    old_size = (size_t)(csp->iob->eod - csp->iob->cur);
399
400    cur = csp->iob->cur;
401
402    if (bufsize < (size_t)10)
403    {
404       /*
405        * This is to protect the parsing of gzipped data,
406        * but it should(?) be valid for deflated data also.
407        */
408       log_error(LOG_LEVEL_ERROR, "Buffer too small decompressing iob");
409       return JB_ERR_COMPRESS;
410    }
411
412    if (csp->content_type & CT_GZIP)
413    {
414       /*
415        * Our task is slightly complicated by the facts that data
416        * compressed by gzip does not include a zlib header, and
417        * that there is no easily accessible interface in zlib to
418        * handle a gzip header. We strip off the gzip header by
419        * hand, and later inform zlib not to expect a header.
420        */
421
422       /*
423        * Strip off the gzip header. Please see RFC 1952 for more
424        * explanation of the appropriate fields.
425        */
426       if ((*cur++ != (char)0x1f)
427        || (*cur++ != (char)0x8b)
428        || (*cur++ != Z_DEFLATED))
429       {
430          log_error(LOG_LEVEL_ERROR, "Invalid gzip header when decompressing");
431          return JB_ERR_COMPRESS;
432       }
433       else
434       {
435          int flags = *cur++;
436          /*
437           * XXX: These magic numbers should be replaced
438           * with macros to give a better idea what they do.
439           */
440          if (flags & 0xe0)
441          {
442             /* The gzip header has reserved bits set; bail out. */
443             log_error(LOG_LEVEL_ERROR, "Invalid gzip header flags when decompressing");
444             return JB_ERR_COMPRESS;
445          }
446          cur += 6;
447
448          /* Skip extra fields if necessary. */
449          if (flags & 0x04)
450          {
451             /*
452              * Skip a given number of bytes, specified
453              * as a 16-bit little-endian value.
454              *
455              * XXX: this code is untested and should probably be removed.
456              */
457             int skip_bytes;
458             skip_bytes = *cur++;
459             skip_bytes += *cur++ << 8;
460
461             /*
462              * The number of bytes to skip should be positive
463              * and we'd like to stay in the buffer.
464              */
465             if ((skip_bytes < 0) || (skip_bytes >= (csp->iob->eod - cur)))
466             {
467                log_error(LOG_LEVEL_ERROR,
468                   "Unreasonable amount of bytes to skip (%d). Stopping decompression",
469                   skip_bytes);
470                return JB_ERR_COMPRESS;
471             }
472             log_error(LOG_LEVEL_INFO,
473                "Skipping %d bytes for gzip compression. Does this sound right?",
474                skip_bytes);
475             cur += skip_bytes;
476          }
477
478          /* Skip the filename if necessary. */
479          if (flags & 0x08)
480          {
481             /* A null-terminated string is supposed to follow. */
482             while (*cur++ && (cur < csp->iob->eod));
483
484          }
485
486          /* Skip the comment if necessary. */
487          if (flags & 0x10)
488          {
489             /* A null-terminated string is supposed to follow. */
490             while (*cur++ && (cur < csp->iob->eod));
491          }
492
493          /* Skip the CRC if necessary. */
494          if (flags & 0x02)
495          {
496             cur += 2;
497          }
498
499          if (cur >= csp->iob->eod)
500          {
501             /*
502              * If the current position pointer reached or passed
503              * the buffer end, we were obviously tricked to skip
504              * too much.
505              */
506             log_error(LOG_LEVEL_ERROR,
507                "Malformed gzip header detected. Aborting decompression.");
508             return JB_ERR_COMPRESS;
509          }
510       }
511    }
512    else if (csp->content_type & CT_DEFLATE)
513    {
514       /*
515        * XXX: The debug level should be lowered
516        * before the next stable release.
517        */
518       log_error(LOG_LEVEL_INFO, "Decompressing deflated iob: %d", *cur);
519       /*
520        * In theory (that is, according to RFC 1950), deflate-compressed
521        * data should begin with a two-byte zlib header and have an
522        * adler32 checksum at the end. It seems that in practice only
523        * the raw compressed data is sent. Note that this means that
524        * we are not RFC 1950-compliant here, but the advantage is that
525        * this actually works. :)
526        *
527        * We add a dummy null byte to tell zlib where the data ends,
528        * and later inform it not to expect a header.
529        *
530        * Fortunately, add_to_iob() has thoughtfully null-terminated
531        * the buffer; we can just increment the end pointer to include
532        * the dummy byte.  
533        */
534       csp->iob->eod++;
535    }
536    else
537    {
538       log_error(LOG_LEVEL_ERROR,
539          "Unable to determine compression format for decompression");
540       return JB_ERR_COMPRESS;
541    }
542
543    /* Set up the fields required by zlib. */
544    zstr.next_in  = (Bytef *)cur;
545    zstr.avail_in = (unsigned int)(csp->iob->eod - cur);
546    zstr.zalloc   = Z_NULL;
547    zstr.zfree    = Z_NULL;
548    zstr.opaque   = Z_NULL;
549
550    /*
551     * Passing -MAX_WBITS to inflateInit2 tells the library
552     * that there is no zlib header.
553     */
554    if (inflateInit2(&zstr, -MAX_WBITS) != Z_OK)
555    {
556       log_error(LOG_LEVEL_ERROR, "Error initializing decompression");
557       return JB_ERR_COMPRESS;
558    }
559
560    /*
561     * Next, we allocate new storage for the inflated data.
562     * We don't modify the existing iob yet, so in case there
563     * is error in decompression we can recover gracefully.
564     */
565    buf = zalloc(bufsize);
566    if (NULL == buf)
567    {
568       log_error(LOG_LEVEL_ERROR, "Out of memory decompressing iob");
569       return JB_ERR_MEMORY;
570    }
571
572    assert(bufsize >= skip_size);
573    memcpy(buf, csp->iob->buf, skip_size);
574    zstr.avail_out = bufsize - skip_size;
575    zstr.next_out  = (Bytef *)buf + skip_size;
576
577    /* Try to decompress the whole stream in one shot. */
578    while (Z_BUF_ERROR == (status = inflate(&zstr, Z_FINISH)))
579    {
580       /* We need to allocate more memory for the output buffer. */
581
582       char *tmpbuf;                /* used for realloc'ing the buffer */
583       size_t oldbufsize = bufsize; /* keep track of the old bufsize */
584
585       if (0 == zstr.avail_in)
586       {
587          /*
588           * If zlib wants more data then there's a problem, because
589           * the complete compressed file should have been buffered.
590           */
591          log_error(LOG_LEVEL_ERROR,
592             "Unexpected end of compressed iob. Using what we got so far.");
593          break;
594       }
595
596       /*
597        * If we tried the limit and still didn't have enough
598        * memory, just give up.
599        */
600       if (bufsize == csp->config->buffer_limit)
601       {
602          log_error(LOG_LEVEL_ERROR, "Buffer limit reached while decompressing iob");
603          return JB_ERR_MEMORY;
604       }
605
606       /* Try doubling the buffer size each time. */
607       bufsize *= 2;
608
609       /* Don't exceed the buffer limit. */
610       if (bufsize > csp->config->buffer_limit)
611       {
612          bufsize = csp->config->buffer_limit;
613       }
614     
615       /* Try to allocate the new buffer. */
616       tmpbuf = realloc(buf, bufsize);
617       if (NULL == tmpbuf)
618       {
619          log_error(LOG_LEVEL_ERROR, "Out of memory decompressing iob");
620          freez(buf);
621          return JB_ERR_MEMORY;
622       }
623       else
624       {
625          char *oldnext_out = (char *)zstr.next_out;
626
627          /*
628           * Update the fields for inflate() to use the new
629           * buffer, which may be in a location different from
630           * the old one.
631           */
632          zstr.avail_out += bufsize - oldbufsize;
633          zstr.next_out   = (Bytef *)tmpbuf + bufsize - zstr.avail_out;
634
635          /*
636           * Compare with an uglier method of calculating these values
637           * that doesn't require the extra oldbufsize variable.
638           */
639          assert(zstr.avail_out == tmpbuf + bufsize - (char *)zstr.next_out);
640          assert((char *)zstr.next_out == tmpbuf + ((char *)oldnext_out - buf));
641          assert(zstr.avail_out > 0U);
642
643          buf = tmpbuf;
644       }
645    }
646
647    if (Z_STREAM_ERROR == inflateEnd(&zstr))
648    {
649       log_error(LOG_LEVEL_ERROR,
650          "Inconsistent stream state after decompression: %s", zstr.msg);
651       /*
652        * XXX: Intentionally no return.
653        *
654        * According to zlib.h, Z_STREAM_ERROR is returned
655        * "if the stream state was inconsistent".
656        *
657        * I assume in this case inflate()'s status
658        * would also be something different than Z_STREAM_END
659        * so this check should be redundant, but lets see.
660        */
661    }
662
663    if ((status != Z_STREAM_END) && (0 != zstr.avail_in))
664    {
665       /*
666        * We failed to decompress the stream and it's
667        * not simply because of missing data.
668        */
669       log_error(LOG_LEVEL_ERROR,
670          "Unexpected error while decompressing to the buffer (iob): %s",
671          zstr.msg);
672       return JB_ERR_COMPRESS;
673    }
674
675    /*
676     * Finally, we can actually update the iob, since the
677     * decompression was successful. First, free the old
678     * buffer.
679     */
680    freez(csp->iob->buf);
681
682    /* Now, update the iob to use the new buffer. */
683    csp->iob->buf  = buf;
684    csp->iob->cur  = csp->iob->buf + skip_size;
685    csp->iob->eod  = (char *)zstr.next_out;
686    csp->iob->size = bufsize;
687   
688    /*
689     * Make sure the new uncompressed iob obeys some minimal
690     * consistency conditions.
691     */
692    if ((csp->iob->buf <  csp->iob->cur)
693     && (csp->iob->cur <= csp->iob->eod)
694     && (csp->iob->eod <= csp->iob->buf + csp->iob->size))
695    {
696       const size_t new_size = (size_t)(csp->iob->eod - csp->iob->cur);
697       if (new_size > (size_t)0)
698       {
699          log_error(LOG_LEVEL_RE_FILTER,
700             "Decompression successful. Old size: %d, new size: %d.",
701             old_size, new_size);
702       }
703       else
704       {
705          /* zlib thinks this is OK, so lets do the same. */
706          log_error(LOG_LEVEL_INFO, "Decompression didn't result in any content.");
707       }
708    }
709    else
710    {
711       /* It seems that zlib did something weird. */
712       log_error(LOG_LEVEL_ERROR,
713          "Unexpected error decompressing the buffer (iob): %d==%d, %d>%d, %d<%d",
714          csp->iob->cur, csp->iob->buf + skip_size, csp->iob->eod, csp->iob->buf,
715          csp->iob->eod, csp->iob->buf + csp->iob->size);
716       return JB_ERR_COMPRESS;
717    }
718
719    return JB_ERR_OK;
720
721 }
722 #endif /* defined(FEATURE_ZLIB) */
723
724
725 /*********************************************************************
726  *
727  * Function    :  string_move
728  *
729  * Description :  memmove wrapper to move the last part of a string
730  *                towards the beginning, overwriting the part in
731  *                the middle. strlcpy() can't be used here as the
732  *                strings overlap.
733  *
734  * Parameters  :
735  *          1  :  dst = Destination to overwrite
736  *          2  :  src = Source to move.
737  *
738  * Returns     :  N/A
739  *
740  *********************************************************************/
741 static void string_move(char *dst, char *src)
742 {
743    assert(dst < src);
744
745    /* +1 to copy the terminating nul as well. */
746    memmove(dst, src, strlen(src)+1);
747 }
748
749
750 /*********************************************************************
751  *
752  * Function    :  normalize_lws
753  *
754  * Description :  Reduces unquoted linear white space in headers
755  *                to a single space in accordance with RFC 2616 2.2.
756  *                This simplifies parsing and filtering later on.
757  *
758  *                XXX: Remove log messages before
759  *                     the next stable release?
760  *
761  * Parameters  :
762  *          1  :  header = A header with linear white space to reduce.
763  *
764  * Returns     :  N/A
765  *
766  *********************************************************************/
767 static void normalize_lws(char *header)
768 {
769    char *p = header;
770
771    while (*p != '\0')
772    {
773       if (ijb_isspace(*p) && ijb_isspace(*(p+1)))
774       {
775          char *q = p+1;
776
777          while (ijb_isspace(*q))
778          {
779             q++;
780          }
781          log_error(LOG_LEVEL_HEADER, "Reducing white space in '%s'", header);
782          string_move(p+1, q);
783       }
784
785       if (*p == '\t')
786       {
787          log_error(LOG_LEVEL_HEADER,
788             "Converting tab to space in '%s'", header);
789          *p = ' ';
790       }
791       else if (*p == '"')
792       {
793          char *end_of_token = strstr(p+1, "\"");
794
795          if (NULL != end_of_token)
796          {
797             /* Don't mess with quoted text. */
798             p = end_of_token;
799          }
800          else
801          {
802             log_error(LOG_LEVEL_HEADER,
803                "Ignoring single quote in '%s'", header);
804          }
805       }
806       p++;
807    }
808
809    p = strchr(header, ':');
810    if ((p != NULL) && (p != header) && ijb_isspace(*(p-1)))
811    {
812       /*
813        * There's still space before the colon.
814        * We don't want it.
815        */
816       string_move(p-1, p);
817    }
818 }
819
820
821 /*********************************************************************
822  *
823  * Function    :  get_header
824  *
825  * Description :  This (odd) routine will parse the csp->iob
826  *                to get the next complete header.
827  *
828  * Parameters  :
829  *          1  :  iob = The I/O buffer to parse, usually csp->iob.
830  *
831  * Returns     :  Any one of the following:
832  *
833  * 1) a pointer to a dynamically allocated string that contains a header line
834  * 2) NULL  indicating that the end of the header was reached
835  * 3) ""    indicating that the end of the iob was reached before finding
836  *          a complete header line.
837  *
838  *********************************************************************/
839 char *get_header(struct iob *iob)
840 {
841    char *header;
842
843    header = get_header_line(iob);
844
845    if ((header == NULL) || (*header == '\0'))
846    {
847       /*
848        * No complete header read yet, tell the client.
849        */
850       return header;
851    }
852
853    while ((iob->cur[0] == ' ') || (iob->cur[0] == '\t'))
854    {
855       /*
856        * Header spans multiple lines, append the next one.
857        */
858       char *continued_header;
859       
860       continued_header = get_header_line(iob);
861       if ((continued_header == NULL) || (*continued_header == '\0'))
862       {
863          /*
864           * No complete header read yet, return what we got.
865           * XXX: Should "unread" header instead.
866           */
867          log_error(LOG_LEVEL_INFO,
868             "Failed to read a multi-line header properly: '%s'",
869             header);
870          break;
871       }
872
873       if (JB_ERR_OK != string_join(&header, continued_header))
874       {
875          log_error(LOG_LEVEL_FATAL,
876             "Out of memory while appending multiple headers.");
877       }
878       else
879       {
880          /* XXX: remove before next stable release. */
881          log_error(LOG_LEVEL_HEADER,
882             "Merged multiple header lines to: '%s'",
883             header);
884       }
885    }
886
887    normalize_lws(header);
888
889    return header;
890
891 }
892
893
894 /*********************************************************************
895  *
896  * Function    :  get_header_line
897  *
898  * Description :  This (odd) routine will parse the csp->iob
899  *                to get the next header line.
900  *
901  * Parameters  :
902  *          1  :  iob = The I/O buffer to parse, usually csp->iob.
903  *
904  * Returns     :  Any one of the following:
905  *
906  * 1) a pointer to a dynamically allocated string that contains a header line
907  * 2) NULL  indicating that the end of the header was reached
908  * 3) ""    indicating that the end of the iob was reached before finding
909  *          a complete header line.
910  *
911  *********************************************************************/
912 static char *get_header_line(struct iob *iob)
913 {
914    char *p, *q, *ret;
915
916    if ((iob->cur == NULL)
917       || ((p = strchr(iob->cur, '\n')) == NULL))
918    {
919       return(""); /* couldn't find a complete header */
920    }
921
922    *p = '\0';
923
924    ret = strdup(iob->cur);
925    if (ret == NULL)
926    {
927       /* FIXME No way to handle error properly */
928       log_error(LOG_LEVEL_FATAL, "Out of memory in get_header_line()");
929    }
930    assert(ret != NULL);
931
932    iob->cur = p+1;
933
934    if ((q = strchr(ret, '\r')) != NULL) *q = '\0';
935
936    /* is this a blank line (i.e. the end of the header) ? */
937    if (*ret == '\0')
938    {
939       freez(ret);
940       return NULL;
941    }
942
943    return ret;
944
945 }
946
947
948 /*********************************************************************
949  *
950  * Function    :  get_header_value
951  *
952  * Description :  Get the value of a given header from a chained list
953  *                of header lines or return NULL if no such header is
954  *                present in the list.
955  *
956  * Parameters  :
957  *          1  :  header_list = pointer to list
958  *          2  :  header_name = string with name of header to look for.
959  *                              Trailing colon required, capitalization
960  *                              doesn't matter.
961  *
962  * Returns     :  NULL if not found, else value of header
963  *
964  *********************************************************************/
965 char *get_header_value(const struct list *header_list, const char *header_name)
966 {
967    struct list_entry *cur_entry;
968    char *ret = NULL;
969    size_t length = 0;
970
971    assert(header_list);
972    assert(header_name);
973    length = strlen(header_name);
974
975    for (cur_entry = header_list->first; cur_entry ; cur_entry = cur_entry->next)
976    {
977       if (cur_entry->str)
978       {
979          if (!strncmpic(cur_entry->str, header_name, length))
980          {
981             /*
982              * Found: return pointer to start of value
983              */
984             ret = cur_entry->str + length;
985             while (*ret && ijb_isspace(*ret)) ret++;
986             return ret;
987          }
988       }
989    }
990
991    /* 
992     * Not found
993     */
994    return NULL;
995
996 }
997
998
999 /*********************************************************************
1000  *
1001  * Function    :  scan_headers
1002  *
1003  * Description :  Scans headers, applies tags and updates action bits. 
1004  *
1005  * Parameters  :
1006  *          1  :  csp = Current client state (buffers, headers, etc...)
1007  *
1008  * Returns     :  JB_ERR_OK
1009  *
1010  *********************************************************************/
1011 static jb_err scan_headers(struct client_state *csp)
1012 {
1013    struct list_entry *h; /* Header */
1014    jb_err err = JB_ERR_OK;
1015
1016    for (h = csp->headers->first; (err == JB_ERR_OK) && (h != NULL) ; h = h->next)
1017    {
1018       /* Header crunch()ed in previous run? -> ignore */
1019       if (h->str == NULL) continue;
1020       log_error(LOG_LEVEL_HEADER, "scan: %s", h->str);
1021       err = header_tagger(csp, h->str);
1022    }
1023
1024    return err;
1025 }
1026
1027
1028 /*********************************************************************
1029  *
1030  * Function    :  sed
1031  *
1032  * Description :  add, delete or modify lines in the HTTP header streams.
1033  *                On entry, it receives a linked list of headers space
1034  *                that was allocated dynamically (both the list nodes
1035  *                and the header contents).
1036  *
1037  *                As a side effect it frees the space used by the original
1038  *                header lines.
1039  *
1040  * Parameters  :
1041  *          1  :  csp = Current client state (buffers, headers, etc...)
1042  *          2  :  filter_server_headers = Boolean to switch between
1043  *                                        server and header filtering.
1044  *
1045  * Returns     :  JB_ERR_OK in case off success, or
1046  *                JB_ERR_MEMORY on out-of-memory error.
1047  *
1048  *********************************************************************/
1049 jb_err sed(struct client_state *csp, int filter_server_headers)
1050 {
1051    /* XXX: use more descriptive names. */
1052    struct list_entry *p;
1053    const struct parsers *v;
1054    const add_header_func_ptr *f;
1055    jb_err err = JB_ERR_OK;
1056
1057    if (filter_server_headers)
1058    {
1059       v = server_patterns;
1060       f = add_server_headers;
1061    }
1062    else
1063    {
1064       v = client_patterns;
1065       f = add_client_headers;
1066    }
1067
1068    scan_headers(csp);
1069
1070    while ((err == JB_ERR_OK) && (v->str != NULL))
1071    {
1072       for (p = csp->headers->first; (err == JB_ERR_OK) && (p != NULL); p = p->next)
1073       {
1074          /* Header crunch()ed in previous run? -> ignore */
1075          if (p->str == NULL) continue;
1076
1077          /* Does the current parser handle this header? */
1078          if ((strncmpic(p->str, v->str, v->len) == 0) ||
1079              (v->len == CHECK_EVERY_HEADER_REMAINING))
1080          {
1081             err = v->parser(csp, &(p->str));
1082          }
1083       }
1084       v++;
1085    }
1086
1087    /* place additional headers on the csp->headers list */
1088    while ((err == JB_ERR_OK) && (*f))
1089    {
1090       err = (*f)(csp);
1091       f++;
1092    }
1093
1094    return err;
1095 }
1096
1097
1098 /*********************************************************************
1099  *
1100  * Function    :  update_server_headers
1101  *
1102  * Description :  Updates server headers after the body has been modified.
1103  *
1104  * Parameters  :
1105  *          1  :  csp = Current client state (buffers, headers, etc...)
1106  *
1107  * Returns     :  JB_ERR_OK in case off success, or
1108  *                JB_ERR_MEMORY on out-of-memory error.
1109  *
1110  *********************************************************************/
1111 jb_err update_server_headers(struct client_state *csp)
1112 {
1113    jb_err err = JB_ERR_OK;
1114
1115    static const struct parsers server_patterns_light[] = {
1116       { "Content-Length:",    15, server_adjust_content_length },
1117       { "Transfer-Encoding:", 18, server_transfer_coding },
1118 #ifdef FEATURE_ZLIB
1119       { "Content-Encoding:",  17, server_content_encoding },
1120 #endif /* def FEATURE_ZLIB */
1121       { NULL,                  0, NULL }
1122    };
1123
1124    if (strncmpic(csp->http->cmd, "HEAD", 4))
1125    {
1126       const struct parsers *v;
1127       struct list_entry *p;
1128
1129       for (v = server_patterns_light; (err == JB_ERR_OK) && (v->str != NULL); v++)
1130       {
1131          for (p = csp->headers->first; (err == JB_ERR_OK) && (p != NULL); p = p->next)
1132          {
1133             /* Header crunch()ed in previous run? -> ignore */
1134             if (p->str == NULL) continue;
1135
1136             /* Does the current parser handle this header? */
1137             if (strncmpic(p->str, v->str, v->len) == 0)
1138             {
1139                err = v->parser(csp, (char **)&(p->str));
1140             }
1141          }
1142       }
1143    }
1144
1145    return err;
1146 }
1147
1148
1149 /*********************************************************************
1150  *
1151  * Function    :  header_tagger
1152  *
1153  * Description :  Executes all text substitutions from applying
1154  *                tag actions and saves the result as tag.
1155  *
1156  *                XXX: Shares enough code with filter_header() and
1157  *                pcrs_filter_response() to warrant some helper functions.
1158  *
1159  * Parameters  :
1160  *          1  :  csp = Current client state (buffers, headers, etc...)
1161  *          2  :  header = Header that is used as tagger input
1162  *
1163  * Returns     :  JB_ERR_OK on success and always succeeds
1164  *
1165  *********************************************************************/
1166 static jb_err header_tagger(struct client_state *csp, char *header)
1167 {
1168    int wanted_filter_type;
1169    int multi_action_index;
1170    int i;
1171    pcrs_job *job;
1172
1173    struct file_list *fl;
1174    struct re_filterfile_spec *b;
1175    struct list_entry *tag_name;
1176
1177    int found_filters = 0;
1178    const size_t header_length = strlen(header);
1179
1180    if (csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
1181    {
1182       wanted_filter_type = FT_SERVER_HEADER_TAGGER;
1183       multi_action_index = ACTION_MULTI_SERVER_HEADER_TAGGER;
1184    }
1185    else
1186    {
1187       wanted_filter_type = FT_CLIENT_HEADER_TAGGER;
1188       multi_action_index = ACTION_MULTI_CLIENT_HEADER_TAGGER;
1189    }
1190
1191    /* Check if there are any filters */
1192    for (i = 0; i < MAX_AF_FILES; i++)
1193    {
1194       fl = csp->rlist[i];
1195       if (NULL != fl)
1196       {
1197          if (NULL != fl->f)
1198          {
1199            found_filters = 1;
1200            break;
1201          }
1202       }
1203    }
1204
1205    if (0 == found_filters)
1206    {
1207       log_error(LOG_LEVEL_ERROR, "Inconsistent configuration: "
1208          "tagging enabled, but no taggers available.");
1209       return JB_ERR_OK;
1210    }
1211
1212    for (i = 0; i < MAX_AF_FILES; i++)
1213    {
1214       fl = csp->rlist[i];
1215       if ((NULL == fl) || (NULL == fl->f))
1216       {
1217          /*
1218           * Either there are no filter files
1219           * left, or this filter file just
1220           * contains no valid filters.
1221           *
1222           * Continue to be sure we don't miss
1223           * valid filter files that are chained
1224           * after empty or invalid ones.
1225           */
1226          continue;
1227       }
1228
1229       /* For all filters, */
1230       for (b = fl->f; b; b = b->next)
1231       {
1232          if (b->type != wanted_filter_type)
1233          {
1234             /* skip the ones we don't care about, */
1235             continue;
1236          }
1237          /* leaving only taggers that could apply, of which we use the ones, */
1238          for (tag_name = csp->action->multi[multi_action_index]->first;
1239               NULL != tag_name; tag_name = tag_name->next)
1240          {
1241             /* that do apply, and */
1242             if (strcmp(b->name, tag_name->str) == 0)
1243             {
1244                char *modified_tag = NULL;
1245                char *tag = header;
1246                size_t size = header_length;
1247                pcrs_job *joblist = b->joblist;
1248
1249                if (b->dynamic) joblist = compile_dynamic_pcrs_job_list(csp, b);
1250
1251                if (NULL == joblist)
1252                {
1253                   log_error(LOG_LEVEL_RE_FILTER,
1254                      "Tagger %s has empty joblist. Nothing to do.", b->name);
1255                   continue;
1256                }
1257
1258                /* execute their pcrs_joblist on the header. */
1259                for (job = joblist; NULL != job; job = job->next)
1260                {
1261                   const int hits = pcrs_execute(job, tag, size, &modified_tag, &size);
1262
1263                   if (0 < hits)
1264                   {
1265                      /* Success, continue with the modified version. */
1266                      if (tag != header)
1267                      {
1268                         freez(tag);
1269                      }
1270                      tag = modified_tag;
1271                   }
1272                   else
1273                   {
1274                      /* Tagger doesn't match */
1275                      if (0 > hits)
1276                      {
1277                         /* Regex failure, log it but continue anyway. */
1278                         assert(NULL != header);
1279                         log_error(LOG_LEVEL_ERROR,
1280                            "Problems with tagger \'%s\' and header \'%s\': %s",
1281                            b->name, *header, pcrs_strerror(hits));
1282                      }
1283                      freez(modified_tag);
1284                   }
1285                }
1286
1287                if (b->dynamic) pcrs_free_joblist(joblist);
1288
1289                /* If this tagger matched */
1290                if (tag != header)
1291                {
1292                   if (0 == size)
1293                   {
1294                      /*
1295                       * There is to technical limitation which makes
1296                       * it impossible to use empty tags, but I assume
1297                       * no one would do it intentionally.
1298                       */
1299                      freez(tag);
1300                      log_error(LOG_LEVEL_INFO,
1301                         "Tagger \'%s\' created an empty tag. Ignored.",
1302                         b->name);
1303                      continue;
1304                   }
1305  
1306                   if (!list_contains_item(csp->tags, tag))
1307                   {
1308                      if (JB_ERR_OK != enlist(csp->tags, tag))
1309                      {
1310                         log_error(LOG_LEVEL_ERROR,
1311                            "Insufficient memory to add tag \'%s\', "
1312                            "based on tagger \'%s\' and header \'%s\'",
1313                            tag, b->name, *header);
1314                      }
1315                      else
1316                      {
1317                         char *action_message;
1318                         /*
1319                          * update the action bits right away, to make
1320                          * tagging based on tags set by earlier taggers
1321                          * of the same kind possible.
1322                          */
1323                         if (update_action_bits_for_tag(csp, tag))
1324                         {
1325                            action_message = "Action bits updated accordingly.";
1326                         }
1327                         else
1328                         {
1329                            action_message = "No action bits update necessary.";
1330                         }
1331
1332                         log_error(LOG_LEVEL_HEADER,
1333                            "Tagger \'%s\' added tag \'%s\'. %s",
1334                            b->name, tag, action_message);
1335                      }
1336                   }
1337                   else
1338                   {
1339                      /* XXX: Is this log-worthy? */
1340                      log_error(LOG_LEVEL_HEADER,
1341                         "Tagger \'%s\' didn't add tag \'%s\'. "
1342                         "Tag already present", b->name, tag);
1343                   }
1344                   freez(tag);
1345                } /* if the tagger matched */
1346             } /* if the tagger applies */
1347          } /* for every tagger that could apply */
1348       } /* for all filters */
1349    } /* for all filter files */
1350
1351    return JB_ERR_OK;
1352 }
1353
1354 /* here begins the family of parser functions that reformat header lines */
1355
1356 /*********************************************************************
1357  *
1358  * Function    :  filter_header
1359  *
1360  * Description :  Executes all text substitutions from all applying
1361  *                +(server|client)-header-filter actions on the header.
1362  *                Most of the code was copied from pcrs_filter_response,
1363  *                including the rather short variable names
1364  *
1365  * Parameters  :
1366  *          1  :  csp = Current client state (buffers, headers, etc...)
1367  *          2  :  header = On input, pointer to header to modify.
1368  *                On output, pointer to the modified header, or NULL
1369  *                to remove the header.  This function frees the
1370  *                original string if necessary.
1371  *
1372  * Returns     :  JB_ERR_OK on success and always succeeds
1373  *
1374  *********************************************************************/
1375 static jb_err filter_header(struct client_state *csp, char **header)
1376 {
1377    int hits=0;
1378    int matches;
1379    size_t size = strlen(*header);
1380
1381    char *newheader = NULL;
1382    pcrs_job *job;
1383
1384    struct file_list *fl;
1385    struct re_filterfile_spec *b;
1386    struct list_entry *filtername;
1387
1388    int i, found_filters = 0;
1389    int wanted_filter_type;
1390    int multi_action_index;
1391
1392    if (csp->flags & CSP_FLAG_NO_FILTERING)
1393    {
1394       return JB_ERR_OK;
1395    }
1396
1397    if (csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
1398    {
1399       wanted_filter_type = FT_SERVER_HEADER_FILTER;
1400       multi_action_index = ACTION_MULTI_SERVER_HEADER_FILTER;
1401    }
1402    else
1403    {
1404       wanted_filter_type = FT_CLIENT_HEADER_FILTER;
1405       multi_action_index = ACTION_MULTI_CLIENT_HEADER_FILTER;
1406    }
1407
1408    /*
1409     * Need to check the set of re_filterfiles...
1410     */
1411    for (i = 0; i < MAX_AF_FILES; i++)
1412    {
1413       fl = csp->rlist[i];
1414       if (NULL != fl)
1415       {
1416          if (NULL != fl->f)
1417          {
1418            found_filters = 1;
1419            break;
1420          }
1421       }
1422    }
1423
1424    if (0 == found_filters)
1425    {
1426       log_error(LOG_LEVEL_ERROR, "Inconsistent configuration: "
1427          "header filtering enabled, but no matching filters available.");
1428       return JB_ERR_OK;
1429    }
1430
1431    for (i = 0; i < MAX_AF_FILES; i++)
1432    {
1433       fl = csp->rlist[i];
1434       if ((NULL == fl) || (NULL == fl->f))
1435       {
1436          /*
1437           * Either there are no filter files
1438           * left, or this filter file just
1439           * contains no valid filters.
1440           *
1441           * Continue to be sure we don't miss
1442           * valid filter files that are chained
1443           * after empty or invalid ones.
1444           */
1445          continue;
1446       }
1447       /*
1448        * For all applying +filter actions, look if a filter by that
1449        * name exists and if yes, execute its pcrs_joblist on the
1450        * buffer.
1451        */
1452       for (b = fl->f; b; b = b->next)
1453       {
1454          if (b->type != wanted_filter_type)
1455          {
1456             /* Skip other filter types */
1457             continue;
1458          }
1459
1460          for (filtername = csp->action->multi[multi_action_index]->first;
1461               filtername ; filtername = filtername->next)
1462          {
1463             if (strcmp(b->name, filtername->str) == 0)
1464             {
1465                int current_hits = 0;
1466                pcrs_job *joblist = b->joblist;
1467
1468                if (b->dynamic) joblist = compile_dynamic_pcrs_job_list(csp, b);
1469
1470                if (NULL == joblist)
1471                {
1472                   log_error(LOG_LEVEL_RE_FILTER, "Filter %s has empty joblist. Nothing to do.", b->name);
1473                   continue;
1474                }
1475
1476                log_error(LOG_LEVEL_RE_FILTER, "filtering \'%s\' (size %d) with \'%s\' ...",
1477                          *header, size, b->name);
1478
1479                /* Apply all jobs from the joblist */
1480                for (job = joblist; NULL != job; job = job->next)
1481                {
1482                   matches = pcrs_execute(job, *header, size, &newheader, &size);
1483                   if ( 0 < matches )
1484                   {
1485                      current_hits += matches; 
1486                      log_error(LOG_LEVEL_HEADER, "Transforming \"%s\" to \"%s\"", *header, newheader);
1487                      freez(*header);
1488                      *header = newheader;
1489                   }
1490                   else if ( 0 == matches )
1491                   {
1492                      /* Filter doesn't change header */
1493                      freez(newheader);
1494                   }
1495                   else
1496                   {
1497                      /* RegEx failure */
1498                      log_error(LOG_LEVEL_ERROR, "Filtering \'%s\' with \'%s\' didn't work out: %s",
1499                         *header, b->name, pcrs_strerror(matches));
1500                      if (newheader != NULL)
1501                      {
1502                         log_error(LOG_LEVEL_ERROR, "Freeing what's left: %s", newheader);
1503                         freez(newheader);
1504                      }
1505                   }
1506                }
1507
1508                if (b->dynamic) pcrs_free_joblist(joblist);
1509
1510                log_error(LOG_LEVEL_RE_FILTER, "... produced %d hits (new size %d).", current_hits, size);
1511                hits += current_hits;
1512             }
1513          }
1514       }
1515    }
1516
1517    /*
1518     * Additionally checking for hits is important because if
1519     * the continue hack is triggered, server headers can
1520     * arrive empty to separate multiple heads from each other.
1521     */
1522    if ((0 == size) && hits)
1523    {
1524       log_error(LOG_LEVEL_HEADER, "Removing empty header %s", *header);
1525       freez(*header);
1526    }
1527
1528    return JB_ERR_OK;
1529 }
1530
1531
1532 /*********************************************************************
1533  *
1534  * Function    :  server_connection
1535  *
1536  * Description :  Makes sure a proper "Connection:" header is
1537  *                set and signals connection_header_adder to
1538  *                do nothing.
1539  *
1540  * Parameters  :
1541  *          1  :  csp = Current client state (buffers, headers, etc...)
1542  *          2  :  header = On input, pointer to header to modify.
1543  *                On output, pointer to the modified header, or NULL
1544  *                to remove the header.  This function frees the
1545  *                original string if necessary.
1546  *
1547  * Returns     :  JB_ERR_OK on success, or
1548  *                JB_ERR_MEMORY on out-of-memory error.
1549  *
1550  *********************************************************************/
1551 static jb_err server_connection(struct client_state *csp, char **header)
1552 {
1553    if (!strcmpic(*header, "Connection: keep-alive"))
1554    {
1555 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
1556       if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE))
1557       {
1558          csp->flags |= CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE;
1559       }
1560
1561       if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE))
1562       {
1563          log_error(LOG_LEVEL_HEADER,
1564             "Keeping the server header '%s' around.", *header);
1565       }
1566       else
1567 #endif /* FEATURE_CONNECTION_KEEP_ALIVE */
1568       {
1569          char *old_header = *header;
1570
1571          *header = strdup("Connection: close");
1572          if (header == NULL)
1573          {
1574             return JB_ERR_MEMORY;
1575          }
1576          log_error(LOG_LEVEL_HEADER, "Replaced: \'%s\' with \'%s\'", old_header, *header);
1577          freez(old_header);
1578       }
1579    }
1580
1581    /* Signal server_connection_adder() to return early. */
1582    csp->flags |= CSP_FLAG_SERVER_CONNECTION_HEADER_SET;
1583
1584    return JB_ERR_OK;
1585 }
1586
1587
1588 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
1589 /*********************************************************************
1590  *
1591  * Function    :  server_keep_alive
1592  *
1593  * Description :  Stores the servers keep alive timeout.
1594  *
1595  * Parameters  :
1596  *          1  :  csp = Current client state (buffers, headers, etc...)
1597  *          2  :  header = On input, pointer to header to modify.
1598  *                On output, pointer to the modified header, or NULL
1599  *                to remove the header.  This function frees the
1600  *                original string if necessary.
1601  *
1602  * Returns     :  JB_ERR_OK.
1603  *
1604  *********************************************************************/
1605 static jb_err server_keep_alive(struct client_state *csp, char **header)
1606 {
1607    unsigned int keep_alive_timeout;
1608    const char *timeout_position = strstr(*header, "timeout=");
1609
1610    if ((NULL == timeout_position)
1611     || (1 != sscanf(timeout_position, "timeout=%u", &keep_alive_timeout)))
1612    {
1613       log_error(LOG_LEVEL_ERROR, "Couldn't parse: %s", *header);
1614    }
1615    else
1616    {
1617       if (keep_alive_timeout < csp->server_connection.keep_alive_timeout)
1618       {
1619          log_error(LOG_LEVEL_HEADER,
1620             "Reducing keep-alive timeout from %u to %u.",
1621             csp->server_connection.keep_alive_timeout, keep_alive_timeout);
1622          csp->server_connection.keep_alive_timeout = keep_alive_timeout;
1623       }
1624       else
1625       {
1626          /* XXX: Is this log worthy? */
1627          log_error(LOG_LEVEL_HEADER,
1628             "Server keep-alive timeout is %u. Sticking with %u.",
1629             keep_alive_timeout, csp->server_connection.keep_alive_timeout);
1630       }
1631    }
1632
1633    return JB_ERR_OK;
1634 }
1635 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
1636
1637
1638
1639 /*********************************************************************
1640  *
1641  * Function    :  client_connection
1642  *
1643  * Description :  Makes sure a proper "Connection:" header is
1644  *                set and signals connection_header_adder 
1645  *                to do nothing.
1646  *
1647  * Parameters  :
1648  *          1  :  csp = Current client state (buffers, headers, etc...)
1649  *          2  :  header = On input, pointer to header to modify.
1650  *                On output, pointer to the modified header, or NULL
1651  *                to remove the header.  This function frees the
1652  *                original string if necessary.
1653  *
1654  * Returns     :  JB_ERR_OK on success, or
1655  *                JB_ERR_MEMORY on out-of-memory error.
1656  *
1657  *********************************************************************/
1658 static jb_err client_connection(struct client_state *csp, char **header)
1659 {
1660    const char *wanted_header = get_appropiate_connection_header(csp);
1661
1662    if (strcmpic(*header, wanted_header))
1663    {
1664 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
1665       if (!(csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING))
1666       {
1667          log_error(LOG_LEVEL_HEADER,
1668             "Keeping the client header '%s' around. "
1669             "The connection will not be kept alive.",
1670             *header);
1671       }
1672       else
1673 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
1674       {
1675          char *old_header = *header;
1676
1677          *header = strdup(wanted_header);
1678          if (header == NULL)
1679          {
1680             return JB_ERR_MEMORY;
1681          }
1682          log_error(LOG_LEVEL_HEADER,
1683             "Replaced: \'%s\' with \'%s\'", old_header, *header);
1684          freez(old_header);
1685       }
1686    }
1687 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
1688    else
1689    {
1690       log_error(LOG_LEVEL_HEADER,
1691          "Keeping the client header '%s' around. "
1692          "The server connection will be kept alive if possible.",
1693          *header);
1694       csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
1695    }
1696 #endif  /* def FEATURE_CONNECTION_KEEP_ALIVE */
1697
1698    /* Signal client_connection_adder() to return early. */
1699    csp->flags |= CSP_FLAG_CLIENT_CONNECTION_HEADER_SET;
1700
1701    return JB_ERR_OK;
1702 }
1703
1704
1705 /*********************************************************************
1706  *
1707  * Function    :  crumble
1708  *
1709  * Description :  This is called if a header matches a pattern to "crunch"
1710  *
1711  * Parameters  :
1712  *          1  :  csp = Current client state (buffers, headers, etc...)
1713  *          2  :  header = On input, pointer to header to modify.
1714  *                On output, pointer to the modified header, or NULL
1715  *                to remove the header.  This function frees the
1716  *                original string if necessary.
1717  *
1718  * Returns     :  JB_ERR_OK on success, or
1719  *                JB_ERR_MEMORY on out-of-memory error.
1720  *
1721  *********************************************************************/
1722 static jb_err crumble(struct client_state *csp, char **header)
1723 {
1724    (void)csp;
1725    log_error(LOG_LEVEL_HEADER, "crumble crunched: %s!", *header);
1726    freez(*header);
1727    return JB_ERR_OK;
1728 }
1729
1730
1731 /*********************************************************************
1732  *
1733  * Function    :  crunch_server_header
1734  *
1735  * Description :  Crunch server header if it matches a string supplied by the
1736  *                user. Called from `sed'.
1737  *
1738  * Parameters  :
1739  *          1  :  csp = Current client state (buffers, headers, etc...)
1740  *          2  :  header = On input, pointer to header to modify.
1741  *                On output, pointer to the modified header, or NULL
1742  *                to remove the header.  This function frees the
1743  *                original string if necessary.
1744  *
1745  * Returns     :  JB_ERR_OK on success and always succeeds
1746  *
1747  *********************************************************************/
1748 static jb_err crunch_server_header(struct client_state *csp, char **header)
1749 {
1750    const char *crunch_pattern;
1751
1752    /* Do we feel like crunching? */
1753    if ((csp->action->flags & ACTION_CRUNCH_SERVER_HEADER))
1754    {
1755       crunch_pattern = csp->action->string[ACTION_STRING_SERVER_HEADER];
1756
1757       /* Is the current header the lucky one? */
1758       if (strstr(*header, crunch_pattern))
1759       {
1760          log_error(LOG_LEVEL_HEADER, "Crunching server header: %s (contains: %s)", *header, crunch_pattern);  
1761          freez(*header);
1762       }
1763    }
1764
1765    return JB_ERR_OK;
1766 }
1767
1768
1769 /*********************************************************************
1770  *
1771  * Function    :  server_content_type
1772  *
1773  * Description :  Set the content-type for filterable types (text/.*,
1774  *                .*xml.*, javascript and image/gif) unless filtering has been
1775  *                forbidden (CT_TABOO) while parsing earlier headers.
1776  *                NOTE: Since text/plain is commonly used by web servers
1777  *                      for files whose correct type is unknown, we don't
1778  *                      set CT_TEXT for it.
1779  *
1780  * Parameters  :
1781  *          1  :  csp = Current client state (buffers, headers, etc...)
1782  *          2  :  header = On input, pointer to header to modify.
1783  *                On output, pointer to the modified header, or NULL
1784  *                to remove the header.  This function frees the
1785  *                original string if necessary.
1786  *
1787  * Returns     :  JB_ERR_OK on success, or
1788  *                JB_ERR_MEMORY on out-of-memory error.
1789  *
1790  *********************************************************************/
1791 static jb_err server_content_type(struct client_state *csp, char **header)
1792 {
1793    /* Remove header if it isn't the first Content-Type header */
1794    if ((csp->content_type & CT_DECLARED))
1795    {
1796      /*
1797       * Another, slightly slower, way to see if
1798       * we already parsed another Content-Type header.
1799       */
1800       assert(NULL != get_header_value(csp->headers, "Content-Type:"));
1801
1802       log_error(LOG_LEVEL_ERROR,
1803          "Multiple Content-Type headers. Removing and ignoring: \'%s\'",
1804          *header);
1805       freez(*header);
1806
1807       return JB_ERR_OK;
1808    }
1809
1810    /*
1811     * Signal that the Content-Type has been set.
1812     */
1813    csp->content_type |= CT_DECLARED;
1814
1815    if (!(csp->content_type & CT_TABOO))
1816    {
1817       /*
1818        * XXX: The assumption that text/plain is a sign of
1819        * binary data seems to be somewhat unreasonable nowadays
1820        * and should be dropped after 3.0.8 is out.
1821        */
1822       if ((strstr(*header, "text/") && !strstr(*header, "plain"))
1823         || strstr(*header, "xml")
1824         || strstr(*header, "application/x-javascript"))
1825       {
1826          csp->content_type |= CT_TEXT;
1827       }
1828       else if (strstr(*header, "image/gif"))
1829       {
1830          csp->content_type |= CT_GIF;
1831       }
1832    }
1833
1834    /*
1835     * Are we messing with the content type?
1836     */
1837    if (csp->action->flags & ACTION_CONTENT_TYPE_OVERWRITE)
1838    {
1839       /*
1840        * Make sure the user doesn't accidently
1841        * change the content type of binary documents. 
1842        */
1843       if ((csp->content_type & CT_TEXT) || (csp->action->flags & ACTION_FORCE_TEXT_MODE))
1844       {
1845          freez(*header);
1846          *header = strdup("Content-Type: ");
1847          string_append(header, csp->action->string[ACTION_STRING_CONTENT_TYPE]);
1848
1849          if (header == NULL)
1850          {
1851             log_error(LOG_LEVEL_HEADER, "Insufficient memory to replace Content-Type!");
1852             return JB_ERR_MEMORY;
1853          }
1854          log_error(LOG_LEVEL_HEADER, "Modified: %s!", *header);
1855       }
1856       else
1857       {
1858          log_error(LOG_LEVEL_HEADER, "%s not replaced. "
1859             "It doesn't look like a content type that should be filtered. "
1860             "Enable force-text-mode if you know what you're doing.", *header);
1861       }
1862    }
1863
1864    return JB_ERR_OK;
1865 }
1866
1867
1868 /*********************************************************************
1869  *
1870  * Function    :  server_transfer_coding
1871  *
1872  * Description :  - Prohibit filtering (CT_TABOO) if transfer coding compresses
1873  *                - Raise the CSP_FLAG_CHUNKED flag if coding is "chunked"
1874  *                - Remove header if body was chunked but has been
1875  *                  de-chunked for filtering.
1876  *
1877  * Parameters  :
1878  *          1  :  csp = Current client state (buffers, headers, etc...)
1879  *          2  :  header = On input, pointer to header to modify.
1880  *                On output, pointer to the modified header, or NULL
1881  *                to remove the header.  This function frees the
1882  *                original string if necessary.
1883  *
1884  * Returns     :  JB_ERR_OK on success, or
1885  *                JB_ERR_MEMORY on out-of-memory error.
1886  *
1887  *********************************************************************/
1888 static jb_err server_transfer_coding(struct client_state *csp, char **header)
1889 {
1890    /*
1891     * Turn off pcrs and gif filtering if body compressed
1892     */
1893    if (strstr(*header, "gzip") || strstr(*header, "compress") || strstr(*header, "deflate"))
1894    {
1895 #ifdef FEATURE_ZLIB
1896       /*
1897        * XXX: Added to test if we could use CT_GZIP and CT_DEFLATE here.
1898        */
1899       log_error(LOG_LEVEL_INFO, "Marking content type for %s as CT_TABOO because of %s.",
1900          csp->http->cmd, *header);
1901 #endif /* def FEATURE_ZLIB */
1902       csp->content_type = CT_TABOO;
1903    }
1904
1905    /*
1906     * Raise flag if body chunked
1907     */
1908    if (strstr(*header, "chunked"))
1909    {
1910       csp->flags |= CSP_FLAG_CHUNKED;
1911
1912       /*
1913        * If the body was modified, it has been de-chunked first
1914        * and the header must be removed.
1915        *
1916        * FIXME: If there is more than one transfer encoding,
1917        * only the "chunked" part should be removed here.
1918        */
1919       if (csp->flags & CSP_FLAG_MODIFIED)
1920       {
1921          log_error(LOG_LEVEL_HEADER, "Removing: %s", *header);
1922          freez(*header);
1923       }
1924    }
1925
1926    return JB_ERR_OK;
1927 }
1928
1929
1930 /*********************************************************************
1931  *
1932  * Function    :  server_content_encoding
1933  *
1934  * Description :  This function is run twice for each request,
1935  *                unless FEATURE_ZLIB and filtering are disabled.
1936  *
1937  *                The first run is used to check if the content
1938  *                is compressed, if FEATURE_ZLIB is disabled
1939  *                filtering is then disabled as well, if FEATURE_ZLIB
1940  *                is enabled the content is marked for decompression.
1941  *                
1942  *                The second run is used to remove the Content-Encoding
1943  *                header if the decompression was successful.
1944  *
1945  * Parameters  :
1946  *          1  :  csp = Current client state (buffers, headers, etc...)
1947  *          2  :  header = On input, pointer to header to modify.
1948  *                On output, pointer to the modified header, or NULL
1949  *                to remove the header.  This function frees the
1950  *                original string if necessary.
1951  *
1952  * Returns     :  JB_ERR_OK on success, or
1953  *                JB_ERR_MEMORY on out-of-memory error.
1954  *
1955  *********************************************************************/
1956 static jb_err server_content_encoding(struct client_state *csp, char **header)
1957 {
1958 #ifdef FEATURE_ZLIB
1959    if ((csp->flags & CSP_FLAG_MODIFIED)
1960     && (csp->content_type & (CT_GZIP | CT_DEFLATE)))
1961    {
1962       /*
1963        * We successfully decompressed the content,
1964        * and have to clean the header now, so the
1965        * client no longer expects compressed data..
1966        *
1967        * XXX: There is a difference between cleaning
1968        * and removing it completely.
1969        */
1970       log_error(LOG_LEVEL_HEADER, "Crunching: %s", *header);
1971       freez(*header);
1972    }
1973    else if (strstr(*header, "gzip"))
1974    {
1975       /* Mark for gzip decompression */
1976       csp->content_type |= CT_GZIP;
1977    }
1978    else if (strstr(*header, "deflate"))
1979    {
1980       /* Mark for zlib decompression */
1981       csp->content_type |= CT_DEFLATE;
1982    }
1983    else if (strstr(*header, "compress"))
1984    {
1985       /*
1986        * We can't decompress this; therefore we can't filter
1987        * it either.
1988        */
1989       csp->content_type |= CT_TABOO;
1990    }
1991 #else /* !defined(FEATURE_ZLIB) */
1992    if (strstr(*header, "gzip") || strstr(*header, "compress") || strstr(*header, "deflate"))
1993    {
1994       /*
1995        * Body is compressed, turn off pcrs and gif filtering.
1996        */
1997       csp->content_type |= CT_TABOO;
1998
1999       /*
2000        * Log a warning if the user expects the content to be filtered.
2001        */
2002       if ((csp->rlist != NULL) &&
2003          (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER])))
2004       {
2005          log_error(LOG_LEVEL_INFO,
2006             "Compressed content detected, content filtering disabled. "
2007             "Consider recompiling Privoxy with zlib support or "
2008             "enable the prevent-compression action.");
2009       }
2010    }
2011 #endif /* defined(FEATURE_ZLIB) */
2012
2013    return JB_ERR_OK;
2014
2015 }
2016
2017
2018 /*********************************************************************
2019  *
2020  * Function    :  server_adjust_content_length
2021  *
2022  * Description :  Adjust Content-Length header if we modified
2023  *                the body.
2024  *
2025  * Parameters  :
2026  *          1  :  csp = Current client state (buffers, headers, etc...)
2027  *          2  :  header = On input, pointer to header to modify.
2028  *                On output, pointer to the modified header, or NULL
2029  *                to remove the header.  This function frees the
2030  *                original string if necessary.
2031  *
2032  * Returns     :  JB_ERR_OK on success, or
2033  *                JB_ERR_MEMORY on out-of-memory error.
2034  *
2035  *********************************************************************/
2036 static jb_err server_adjust_content_length(struct client_state *csp, char **header)
2037 {
2038    const size_t max_header_length = 80;
2039
2040    /* Regenerate header if the content was modified. */
2041    if (csp->flags & CSP_FLAG_MODIFIED)
2042    {
2043       freez(*header);
2044       *header = (char *) zalloc(max_header_length);
2045       if (*header == NULL)
2046       {
2047          return JB_ERR_MEMORY;
2048       }
2049
2050       snprintf(*header, max_header_length, "Content-Length: %d",
2051          (int)csp->content_length);
2052       log_error(LOG_LEVEL_HEADER, "Adjusted Content-Length to %d",
2053          (int)csp->content_length);
2054    }
2055
2056    return JB_ERR_OK;
2057 }
2058
2059
2060 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
2061 /*********************************************************************
2062  *
2063  * Function    :  server_save_content_length
2064  *
2065  * Description :  Save the Content-Length sent by the server.
2066  *
2067  * Parameters  :
2068  *          1  :  csp = Current client state (buffers, headers, etc...)
2069  *          2  :  header = On input, pointer to header to modify.
2070  *                On output, pointer to the modified header, or NULL
2071  *                to remove the header.  This function frees the
2072  *                original string if necessary.
2073  *
2074  * Returns     :  JB_ERR_OK on success, or
2075  *                JB_ERR_MEMORY on out-of-memory error.
2076  *
2077  *********************************************************************/
2078 static jb_err server_save_content_length(struct client_state *csp, char **header)
2079 {
2080    unsigned long long content_length = 0;
2081
2082    assert(*(*header+14) == ':');
2083
2084    if (1 != sscanf(*header+14, ": %llu", &content_length))
2085    {
2086       log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
2087       freez(*header);
2088    }
2089    else
2090    {
2091       csp->expected_content_length = content_length;
2092       csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
2093    }
2094
2095    return JB_ERR_OK;
2096 }
2097 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
2098
2099
2100 /*********************************************************************
2101  *
2102  * Function    :  server_content_md5
2103  *
2104  * Description :  Crumble any Content-MD5 headers if the document was
2105  *                modified. FIXME: Should we re-compute instead?
2106  *
2107  * Parameters  :
2108  *          1  :  csp = Current client state (buffers, headers, etc...)
2109  *          2  :  header = On input, pointer to header to modify.
2110  *                On output, pointer to the modified header, or NULL
2111  *                to remove the header.  This function frees the
2112  *                original string if necessary.
2113  *
2114  * Returns     :  JB_ERR_OK on success, or
2115  *                JB_ERR_MEMORY on out-of-memory error.
2116  *
2117  *********************************************************************/
2118 static jb_err server_content_md5(struct client_state *csp, char **header)
2119 {
2120    if (csp->flags & CSP_FLAG_MODIFIED)
2121    {
2122       log_error(LOG_LEVEL_HEADER, "Crunching Content-MD5");
2123       freez(*header);
2124    }
2125
2126    return JB_ERR_OK;
2127 }
2128
2129
2130 /*********************************************************************
2131  *
2132  * Function    :  server_content_disposition
2133  *
2134  * Description :  If enabled, blocks or modifies the "Content-Disposition" header.
2135  *                Called from `sed'.
2136  *
2137  * Parameters  :
2138  *          1  :  csp = Current client state (buffers, headers, etc...)
2139  *          2  :  header = On input, pointer to header to modify.
2140  *                On output, pointer to the modified header, or NULL
2141  *                to remove the header.  This function frees the
2142  *                original string if necessary.
2143  *
2144  * Returns     :  JB_ERR_OK on success, or
2145  *                JB_ERR_MEMORY on out-of-memory error.
2146  *
2147  *********************************************************************/
2148 static jb_err server_content_disposition(struct client_state *csp, char **header)
2149 {
2150    const char *newval;
2151
2152    /*
2153     * Are we messing with the Content-Disposition header?
2154     */
2155    if ((csp->action->flags & ACTION_HIDE_CONTENT_DISPOSITION) == 0)
2156    {
2157       /* Me tinks not */
2158       return JB_ERR_OK;
2159    }
2160
2161    newval = csp->action->string[ACTION_STRING_CONTENT_DISPOSITION];
2162
2163    if ((newval == NULL) || (0 == strcmpic(newval, "block")))
2164    {
2165       /*
2166        * Blocking content-disposition header
2167        */
2168       log_error(LOG_LEVEL_HEADER, "Crunching %s!", *header);
2169       freez(*header);
2170       return JB_ERR_OK;
2171    }
2172    else
2173    {  
2174       /*
2175        * Replacing Content-Disposition header
2176        */
2177       freez(*header);
2178       *header = strdup("Content-Disposition: ");
2179       string_append(header, newval);
2180
2181       if (*header != NULL)
2182       {
2183          log_error(LOG_LEVEL_HEADER,
2184             "Content-Disposition header crunched and replaced with: %s", *header);
2185       }
2186    }
2187    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2188 }
2189
2190
2191 /*********************************************************************
2192  *
2193  * Function    :  server_last_modified
2194  *
2195  * Description :  Changes Last-Modified header to the actual date
2196  *                to help hide-if-modified-since.
2197  *                Called from `sed'.
2198  *
2199  * Parameters  :
2200  *          1  :  csp = Current client state (buffers, headers, etc...)
2201  *          2  :  header = On input, pointer to header to modify.
2202  *                On output, pointer to the modified header, or NULL
2203  *                to remove the header.  This function frees the
2204  *                original string if necessary.
2205  *
2206  * Returns     :  JB_ERR_OK on success, or
2207  *                JB_ERR_MEMORY on out-of-memory error.
2208  *
2209  *********************************************************************/
2210 static jb_err server_last_modified(struct client_state *csp, char **header)
2211 {
2212    const char *newval;
2213    char buf[BUFFER_SIZE];
2214
2215    char newheader[50];
2216 #ifdef HAVE_GMTIME_R
2217    struct tm gmt;
2218 #endif
2219    struct tm *timeptr = NULL;
2220    time_t now, last_modified;                  
2221    long int days, hours, minutes, seconds;
2222    
2223    /*
2224     * Are we messing with the Last-Modified header?
2225     */
2226    if ((csp->action->flags & ACTION_OVERWRITE_LAST_MODIFIED) == 0)
2227    {
2228       /*Nope*/
2229       return JB_ERR_OK;
2230    }
2231
2232    newval = csp->action->string[ACTION_STRING_LAST_MODIFIED];
2233
2234    if (0 == strcmpic(newval, "block") )
2235    {
2236       /*
2237        * Blocking Last-Modified header. Useless but why not.
2238        */
2239       log_error(LOG_LEVEL_HEADER, "Crunching %s!", *header);
2240       freez(*header);
2241       return JB_ERR_OK;
2242    }
2243    else if (0 == strcmpic(newval, "reset-to-request-time"))
2244    {  
2245       /*
2246        * Setting Last-Modified Header to now.
2247        */
2248       get_http_time(0, buf, sizeof(buf));
2249       freez(*header);
2250       *header = strdup("Last-Modified: ");
2251       string_append(header, buf);   
2252
2253       if (*header == NULL)
2254       {
2255          log_error(LOG_LEVEL_HEADER, "Insufficient memory. Last-Modified header got lost, boohoo.");  
2256       }
2257       else
2258       {
2259          log_error(LOG_LEVEL_HEADER, "Reset to present time: %s", *header);
2260       }
2261    }
2262    else if (0 == strcmpic(newval, "randomize"))
2263    {
2264       const char *header_time = *header + sizeof("Last-Modified:");
2265
2266       log_error(LOG_LEVEL_HEADER, "Randomizing: %s", *header);
2267       now = time(NULL);
2268 #ifdef HAVE_GMTIME_R
2269       gmtime_r(&now, &gmt);
2270 #elif defined(MUTEX_LOCKS_AVAILABLE)
2271       privoxy_mutex_lock(&gmtime_mutex);
2272       gmtime(&now);
2273       privoxy_mutex_unlock(&gmtime_mutex);
2274 #else
2275       gmtime(&now);
2276 #endif
2277       if (JB_ERR_OK != parse_header_time(header_time, &last_modified))
2278       {
2279          log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s in %s (crunching!)", header_time, *header);
2280          freez(*header);
2281       }
2282       else
2283       {
2284          long int rtime = (long int)difftime(now, last_modified);
2285          if (rtime)
2286          {
2287             const int negative_delta = (rtime < 0);
2288
2289             if (negative_delta)
2290             {
2291                rtime *= -1; 
2292                log_error(LOG_LEVEL_HEADER, "Server time in the future.");
2293             }
2294             rtime = pick_from_range(rtime);
2295             if (negative_delta)
2296             {
2297                rtime *= -1;
2298             }
2299             last_modified += rtime;
2300 #ifdef HAVE_GMTIME_R
2301             timeptr = gmtime_r(&last_modified, &gmt);
2302 #elif defined(MUTEX_LOCKS_AVAILABLE)
2303             privoxy_mutex_lock(&gmtime_mutex);
2304             timeptr = gmtime(&last_modified);
2305             privoxy_mutex_unlock(&gmtime_mutex);
2306 #else
2307             timeptr = gmtime(&last_modified);
2308 #endif
2309             strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr);
2310             freez(*header);
2311             *header = strdup("Last-Modified: ");
2312             string_append(header, newheader);
2313
2314             if (*header == NULL)
2315             {
2316                log_error(LOG_LEVEL_ERROR, "Insufficient memory, header crunched without replacement.");
2317                return JB_ERR_MEMORY;  
2318             }
2319
2320             days    = rtime / (3600 * 24);
2321             hours   = rtime / 3600 % 24;
2322             minutes = rtime / 60 % 60;
2323             seconds = rtime % 60;
2324
2325             log_error(LOG_LEVEL_HEADER,
2326                "Randomized:  %s (added %d da%s %d hou%s %d minut%s %d second%s",
2327                *header, days, (days == 1) ? "y" : "ys", hours, (hours == 1) ? "r" : "rs",
2328                minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)");
2329          }
2330          else
2331          {
2332             log_error(LOG_LEVEL_HEADER, "Randomized ... or not. No time difference to work with.");
2333          }
2334       }
2335    }
2336
2337    return JB_ERR_OK;
2338 }
2339
2340
2341 /*********************************************************************
2342  *
2343  * Function    :  client_accept_encoding
2344  *
2345  * Description :  Rewrite the client's Accept-Encoding header so that
2346  *                if doesn't allow compression, if the action applies.
2347  *                Note: For HTTP/1.0 the absence of the header is enough.
2348  *
2349  * Parameters  :
2350  *          1  :  csp = Current client state (buffers, headers, etc...)
2351  *          2  :  header = On input, pointer to header to modify.
2352  *                On output, pointer to the modified header, or NULL
2353  *                to remove the header.  This function frees the
2354  *                original string if necessary.
2355  *
2356  * Returns     :  JB_ERR_OK on success, or
2357  *                JB_ERR_MEMORY on out-of-memory error.
2358  *
2359  *********************************************************************/
2360 static jb_err client_accept_encoding(struct client_state *csp, char **header)
2361 {
2362    if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
2363    {
2364       log_error(LOG_LEVEL_HEADER, "Suppressed offer to compress content");
2365
2366       freez(*header);
2367
2368       /* Temporarily disable the correct behaviour to
2369        * work around a PHP bug. 
2370        *
2371        * if (!strcmpic(csp->http->ver, "HTTP/1.1"))
2372        * {
2373        *    *header = strdup("Accept-Encoding: identity;q=1.0, *;q=0");
2374        *    if (*header == NULL)
2375        *    {
2376        *       return JB_ERR_MEMORY;
2377        *    }
2378        * }
2379        * 
2380        */
2381    }
2382
2383    return JB_ERR_OK;
2384 }
2385
2386
2387 /*********************************************************************
2388  *
2389  * Function    :  client_te
2390  *
2391  * Description :  Rewrite the client's TE header so that
2392  *                if doesn't allow compression, if the action applies.
2393  *
2394  * Parameters  :
2395  *          1  :  csp = Current client state (buffers, headers, etc...)
2396  *          2  :  header = On input, pointer to header to modify.
2397  *                On output, pointer to the modified header, or NULL
2398  *                to remove the header.  This function frees the
2399  *                original string if necessary.
2400  *
2401  * Returns     :  JB_ERR_OK on success, or
2402  *                JB_ERR_MEMORY on out-of-memory error.
2403  *
2404  *********************************************************************/
2405 static jb_err client_te(struct client_state *csp, char **header)
2406 {
2407    if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
2408    {
2409       freez(*header);
2410       log_error(LOG_LEVEL_HEADER, "Suppressed offer to compress transfer");
2411    }
2412
2413    return JB_ERR_OK;
2414 }
2415
2416
2417 /*********************************************************************
2418  *
2419  * Function    :  client_referrer
2420  *
2421  * Description :  Handle the "referer" config setting properly.
2422  *                Called from `sed'.
2423  *
2424  * Parameters  :
2425  *          1  :  csp = Current client state (buffers, headers, etc...)
2426  *          2  :  header = On input, pointer to header to modify.
2427  *                On output, pointer to the modified header, or NULL
2428  *                to remove the header.  This function frees the
2429  *                original string if necessary.
2430  *
2431  * Returns     :  JB_ERR_OK on success, or
2432  *                JB_ERR_MEMORY on out-of-memory error.
2433  *
2434  *********************************************************************/
2435 static jb_err client_referrer(struct client_state *csp, char **header)
2436 {
2437    const char *parameter;
2438    /* booleans for parameters we have to check multiple times */
2439    int parameter_conditional_block;
2440    int parameter_conditional_forge;
2441  
2442 #ifdef FEATURE_FORCE_LOAD
2443    /*
2444     * Since the referrer can include the prefix even
2445     * if the request itself is non-forced, we must
2446     * clean it unconditionally.
2447     *
2448     * XXX: strclean is too broad
2449     */
2450    strclean(*header, FORCE_PREFIX);
2451 #endif /* def FEATURE_FORCE_LOAD */
2452
2453    if ((csp->action->flags & ACTION_HIDE_REFERER) == 0)
2454    {
2455       /* Nothing left to do */
2456       return JB_ERR_OK;
2457    }
2458
2459    parameter = csp->action->string[ACTION_STRING_REFERER];
2460    assert(parameter != NULL);
2461    parameter_conditional_block = (0 == strcmpic(parameter, "conditional-block"));
2462    parameter_conditional_forge = (0 == strcmpic(parameter, "conditional-forge"));
2463
2464    if (!parameter_conditional_block && !parameter_conditional_forge)
2465    {
2466       /*
2467        * As conditional-block and conditional-forge are the only
2468        * parameters that rely on the original referrer, we can
2469        * remove it now for all the others.
2470        */
2471       freez(*header);
2472    }
2473
2474    if (0 == strcmpic(parameter, "block"))
2475    {
2476       log_error(LOG_LEVEL_HEADER, "Referer crunched!");
2477       return JB_ERR_OK;
2478    }
2479    else if (parameter_conditional_block || parameter_conditional_forge)
2480    {
2481       return handle_conditional_hide_referrer_parameter(header,
2482          csp->http->hostport, parameter_conditional_block);
2483    }
2484    else if (0 == strcmpic(parameter, "forge"))
2485    {
2486       return create_forged_referrer(header, csp->http->hostport);
2487    }
2488    else
2489    {
2490       /* interpret parameter as user-supplied referer to fake */
2491       return create_fake_referrer(header, parameter);
2492    }
2493 }
2494
2495
2496 /*********************************************************************
2497  *
2498  * Function    :  client_accept_language
2499  *
2500  * Description :  Handle the "Accept-Language" config setting properly.
2501  *                Called from `sed'.
2502  *
2503  * Parameters  :
2504  *          1  :  csp = Current client state (buffers, headers, etc...)
2505  *          2  :  header = On input, pointer to header to modify.
2506  *                On output, pointer to the modified header, or NULL
2507  *                to remove the header.  This function frees the
2508  *                original string if necessary.
2509  *
2510  * Returns     :  JB_ERR_OK on success, or
2511  *                JB_ERR_MEMORY on out-of-memory error.
2512  *
2513  *********************************************************************/
2514 static jb_err client_accept_language(struct client_state *csp, char **header)
2515 {
2516    const char *newval;
2517
2518    /*
2519     * Are we messing with the Accept-Language?
2520     */
2521    if ((csp->action->flags & ACTION_HIDE_ACCEPT_LANGUAGE) == 0)
2522    {
2523       /*I don't think so*/
2524       return JB_ERR_OK;
2525    }
2526
2527    newval = csp->action->string[ACTION_STRING_LANGUAGE];
2528
2529    if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
2530    {
2531       /*
2532        * Blocking Accept-Language header
2533        */
2534       log_error(LOG_LEVEL_HEADER, "Crunching Accept-Language!");
2535       freez(*header);
2536       return JB_ERR_OK;
2537    }
2538    else
2539    {  
2540       /*
2541        * Replacing Accept-Language header
2542        */
2543       freez(*header);
2544       *header = strdup("Accept-Language: ");
2545       string_append(header, newval);   
2546
2547       if (*header == NULL)
2548       {
2549          log_error(LOG_LEVEL_ERROR,
2550             "Insufficient memory. Accept-Language header crunched without replacement.");  
2551       }
2552       else
2553       {
2554          log_error(LOG_LEVEL_HEADER,
2555             "Accept-Language header crunched and replaced with: %s", *header);
2556       }
2557    }
2558    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2559 }
2560
2561
2562 /*********************************************************************
2563  *
2564  * Function    :  crunch_client_header
2565  *
2566  * Description :  Crunch client header if it matches a string supplied by the
2567  *                user. Called from `sed'.
2568  *
2569  * Parameters  :
2570  *          1  :  csp = Current client state (buffers, headers, etc...)
2571  *          2  :  header = On input, pointer to header to modify.
2572  *                On output, pointer to the modified header, or NULL
2573  *                to remove the header.  This function frees the
2574  *                original string if necessary.
2575  *
2576  * Returns     :  JB_ERR_OK on success and always succeeds
2577  *
2578  *********************************************************************/
2579 static jb_err crunch_client_header(struct client_state *csp, char **header)
2580 {
2581    const char *crunch_pattern;
2582
2583    /* Do we feel like crunching? */
2584    if ((csp->action->flags & ACTION_CRUNCH_CLIENT_HEADER))
2585    {
2586       crunch_pattern = csp->action->string[ACTION_STRING_CLIENT_HEADER];
2587
2588       /* Is the current header the lucky one? */
2589       if (strstr(*header, crunch_pattern))
2590       {
2591          log_error(LOG_LEVEL_HEADER, "Crunching client header: %s (contains: %s)", *header, crunch_pattern);  
2592          freez(*header);
2593       }
2594    }
2595    return JB_ERR_OK;
2596 }
2597
2598
2599 /*********************************************************************
2600  *
2601  * Function    :  client_uagent
2602  *
2603  * Description :  Handle the "user-agent" config setting properly
2604  *                and remember its original value to enable browser
2605  *                bug workarounds. Called from `sed'.
2606  *
2607  * Parameters  :
2608  *          1  :  csp = Current client state (buffers, headers, etc...)
2609  *          2  :  header = On input, pointer to header to modify.
2610  *                On output, pointer to the modified header, or NULL
2611  *                to remove the header.  This function frees the
2612  *                original string if necessary.
2613  *
2614  * Returns     :  JB_ERR_OK on success, or
2615  *                JB_ERR_MEMORY on out-of-memory error.
2616  *
2617  *********************************************************************/
2618 static jb_err client_uagent(struct client_state *csp, char **header)
2619 {
2620    const char *newval;
2621
2622    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) == 0)
2623    {
2624       return JB_ERR_OK;
2625    }
2626
2627    newval = csp->action->string[ACTION_STRING_USER_AGENT];
2628    if (newval == NULL)
2629    {
2630       return JB_ERR_OK;
2631    }
2632
2633    freez(*header);
2634    *header = strdup("User-Agent: ");
2635    string_append(header, newval);
2636
2637    log_error(LOG_LEVEL_HEADER, "Modified: %s", *header);
2638
2639    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2640 }
2641
2642
2643 /*********************************************************************
2644  *
2645  * Function    :  client_ua
2646  *
2647  * Description :  Handle "ua-" headers properly.  Called from `sed'.
2648  *
2649  * Parameters  :
2650  *          1  :  csp = Current client state (buffers, headers, etc...)
2651  *          2  :  header = On input, pointer to header to modify.
2652  *                On output, pointer to the modified header, or NULL
2653  *                to remove the header.  This function frees the
2654  *                original string if necessary.
2655  *
2656  * Returns     :  JB_ERR_OK on success, or
2657  *                JB_ERR_MEMORY on out-of-memory error.
2658  *
2659  *********************************************************************/
2660 static jb_err client_ua(struct client_state *csp, char **header)
2661 {
2662    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) != 0)
2663    {
2664       log_error(LOG_LEVEL_HEADER, "crunched User-Agent!");
2665       freez(*header);
2666    }
2667
2668    return JB_ERR_OK;
2669 }
2670
2671
2672 /*********************************************************************
2673  *
2674  * Function    :  client_from
2675  *
2676  * Description :  Handle the "from" config setting properly.
2677  *                Called from `sed'.
2678  *
2679  * Parameters  :
2680  *          1  :  csp = Current client state (buffers, headers, etc...)
2681  *          2  :  header = On input, pointer to header to modify.
2682  *                On output, pointer to the modified header, or NULL
2683  *                to remove the header.  This function frees the
2684  *                original string if necessary.
2685  *
2686  * Returns     :  JB_ERR_OK on success, or
2687  *                JB_ERR_MEMORY on out-of-memory error.
2688  *
2689  *********************************************************************/
2690 static jb_err client_from(struct client_state *csp, char **header)
2691 {
2692    const char *newval;
2693
2694    if ((csp->action->flags & ACTION_HIDE_FROM) == 0)
2695    {
2696       return JB_ERR_OK;
2697    }
2698
2699    freez(*header);
2700
2701    newval = csp->action->string[ACTION_STRING_FROM];
2702
2703    /*
2704     * Are we blocking the e-mail address?
2705     */
2706    if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
2707    {
2708       log_error(LOG_LEVEL_HEADER, "crunched From!");
2709       return JB_ERR_OK;
2710    }
2711
2712    log_error(LOG_LEVEL_HEADER, " modified");
2713
2714    *header = strdup("From: ");
2715    string_append(header, newval);
2716
2717    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2718 }
2719
2720
2721 /*********************************************************************
2722  *
2723  * Function    :  client_send_cookie
2724  *
2725  * Description :  Crunches the "cookie" header if necessary.
2726  *                Called from `sed'.
2727  *
2728  *                XXX: Stupid name, doesn't send squat.
2729  *
2730  * Parameters  :
2731  *          1  :  csp = Current client state (buffers, headers, etc...)
2732  *          2  :  header = On input, pointer to header to modify.
2733  *                On output, pointer to the modified header, or NULL
2734  *                to remove the header.  This function frees the
2735  *                original string if necessary.
2736  *
2737  * Returns     :  JB_ERR_OK on success, or
2738  *                JB_ERR_MEMORY on out-of-memory error.
2739  *
2740  *********************************************************************/
2741 static jb_err client_send_cookie(struct client_state *csp, char **header)
2742 {
2743    if (csp->action->flags & ACTION_NO_COOKIE_READ)
2744    {
2745       log_error(LOG_LEVEL_HEADER, "Crunched outgoing cookie: %s", *header);
2746       freez(*header);
2747    }
2748
2749    return JB_ERR_OK;
2750 }
2751
2752
2753 /*********************************************************************
2754  *
2755  * Function    :  client_x_forwarded
2756  *
2757  * Description :  Handle the "x-forwarded-for" config setting properly,
2758  *                also used in the add_client_headers list.  Called from `sed'.
2759  *
2760  * Parameters  :
2761  *          1  :  csp = Current client state (buffers, headers, etc...)
2762  *          2  :  header = On input, pointer to header to modify.
2763  *                On output, pointer to the modified header, or NULL
2764  *                to remove the header.  This function frees the
2765  *                original string if necessary.
2766  *
2767  * Returns     :  JB_ERR_OK on success, or
2768  *                JB_ERR_MEMORY on out-of-memory error.
2769  *
2770  *********************************************************************/
2771 jb_err client_x_forwarded(struct client_state *csp, char **header)
2772 {
2773    if (0 != (csp->action->flags & ACTION_CHANGE_X_FORWARDED_FOR))
2774    {
2775       const char *parameter = csp->action->string[ACTION_STRING_CHANGE_X_FORWARDED_FOR];
2776
2777       if (0 == strcmpic(parameter, "block"))
2778       {
2779          freez(*header);
2780          log_error(LOG_LEVEL_HEADER, "crunched x-forwarded-for!");
2781       }
2782       else if (0 == strcmpic(parameter, "add"))
2783       {
2784          string_append(header, ", ");
2785          string_append(header, csp->ip_addr_str);
2786
2787          if (*header == NULL)
2788          {
2789             return JB_ERR_MEMORY;
2790          }
2791          log_error(LOG_LEVEL_HEADER,
2792             "Appended client IP address to %s", *header);
2793          csp->flags |= CSP_FLAG_X_FORWARDED_FOR_APPENDED;
2794       }
2795       else
2796       {
2797          log_error(LOG_LEVEL_FATAL,
2798             "Invalid change-x-forwarded-for parameter: '%s'", parameter);
2799       }
2800    }
2801
2802    return JB_ERR_OK;
2803 }
2804
2805
2806 /*********************************************************************
2807  *
2808  * Function    :  client_max_forwards
2809  *
2810  * Description :  If the HTTP method is OPTIONS or TRACE, subtract one
2811  *                from the value of the Max-Forwards header field.
2812  *
2813  * Parameters  :
2814  *          1  :  csp = Current client state (buffers, headers, etc...)
2815  *          2  :  header = On input, pointer to header to modify.
2816  *                On output, pointer to the modified header, or NULL
2817  *                to remove the header.  This function frees the
2818  *                original string if necessary.
2819  *
2820  * Returns     :  JB_ERR_OK on success, or
2821  *                JB_ERR_MEMORY on out-of-memory error.
2822  *
2823  *********************************************************************/
2824 static jb_err client_max_forwards(struct client_state *csp, char **header)
2825 {
2826    int max_forwards;
2827
2828    if ((0 == strcmpic(csp->http->gpc, "trace")) ||
2829        (0 == strcmpic(csp->http->gpc, "options")))
2830    {
2831       assert(*(*header+12) == ':');
2832       if (1 == sscanf(*header+12, ": %d", &max_forwards))
2833       {
2834          if (max_forwards > 0)
2835          {
2836             snprintf(*header, strlen(*header)+1, "Max-Forwards: %d", --max_forwards);
2837             log_error(LOG_LEVEL_HEADER,
2838                "Max-Forwards value for %s request reduced to %d.",
2839                csp->http->gpc, max_forwards);
2840          }
2841          else if (max_forwards < 0)
2842          {
2843             log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
2844             freez(*header);
2845          }
2846       }
2847       else
2848       {
2849          log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
2850          freez(*header);
2851       }
2852    }
2853
2854    return JB_ERR_OK;
2855 }
2856
2857
2858 /*********************************************************************
2859  *
2860  * Function    :  client_host
2861  *
2862  * Description :  If the request URI did not contain host and
2863  *                port information, parse and evaluate the Host
2864  *                header field.
2865  *
2866  *                Also, kill ill-formed HOST: headers as sent by
2867  *                Apple's iTunes software when used with a proxy.
2868  *
2869  * Parameters  :
2870  *          1  :  csp = Current client state (buffers, headers, etc...)
2871  *          2  :  header = On input, pointer to header to modify.
2872  *                On output, pointer to the modified header, or NULL
2873  *                to remove the header.  This function frees the
2874  *                original string if necessary.
2875  *
2876  * Returns     :  JB_ERR_OK on success, or
2877  *                JB_ERR_MEMORY on out-of-memory error.
2878  *
2879  *********************************************************************/
2880 static jb_err client_host(struct client_state *csp, char **header)
2881 {
2882    char *p, *q;
2883
2884    /*
2885     * If the header field name is all upper-case, chances are that it's
2886     * an ill-formed one from iTunes. BTW, killing innocent headers here is
2887     * not a problem -- they are regenerated later.
2888     */
2889    if ((*header)[1] == 'O')
2890    {
2891       log_error(LOG_LEVEL_HEADER, "Killed all-caps Host header line: %s", *header);
2892       freez(*header);
2893       return JB_ERR_OK;
2894    }
2895
2896    if (!csp->http->hostport || (*csp->http->hostport == '*') ||  
2897        *csp->http->hostport == ' ' || *csp->http->hostport == '\0')
2898    {
2899       
2900       if (NULL == (p = strdup((*header)+6)))
2901       {
2902          return JB_ERR_MEMORY;
2903       }
2904       chomp(p);
2905       if (NULL == (q = strdup(p)))
2906       {
2907          freez(p);
2908          return JB_ERR_MEMORY;
2909       }
2910
2911       freez(csp->http->hostport);
2912       csp->http->hostport = p;
2913       freez(csp->http->host);
2914       csp->http->host = q;
2915       q = strchr(csp->http->host, ':');
2916       if (q != NULL)
2917       {
2918          /* Terminate hostname and evaluate port string */
2919          *q++ = '\0';
2920          csp->http->port = atoi(q);
2921       }
2922       else
2923       {
2924          csp->http->port = csp->http->ssl ? 443 : 80;
2925       }
2926
2927       log_error(LOG_LEVEL_HEADER, "New host and port from Host field: %s = %s:%d",
2928                 csp->http->hostport, csp->http->host, csp->http->port);
2929    }
2930
2931    /* Signal client_host_adder() to return right away */
2932    csp->flags |= CSP_FLAG_HOST_HEADER_IS_SET;
2933
2934    return JB_ERR_OK;
2935 }
2936
2937
2938 /*********************************************************************
2939  *
2940  * Function    :  client_if_modified_since
2941  *
2942  * Description :  Remove or modify the If-Modified-Since header.
2943  *
2944  * Parameters  :
2945  *          1  :  csp = Current client state (buffers, headers, etc...)
2946  *          2  :  header = On input, pointer to header to modify.
2947  *                On output, pointer to the modified header, or NULL
2948  *                to remove the header.  This function frees the
2949  *                original string if necessary.
2950  *
2951  * Returns     :  JB_ERR_OK on success, or
2952  *                JB_ERR_MEMORY on out-of-memory error.
2953  *
2954  *********************************************************************/
2955 static jb_err client_if_modified_since(struct client_state *csp, char **header)
2956 {
2957    char newheader[50];
2958 #ifdef HAVE_GMTIME_R
2959    struct tm gmt;
2960 #endif
2961    struct tm *timeptr = NULL;
2962    time_t tm = 0;                  
2963    const char *newval;
2964    long int hours, minutes, seconds;
2965    char * endptr;
2966    
2967    if ( 0 == strcmpic(*header, "If-Modified-Since: Wed, 08 Jun 1955 12:00:00 GMT"))
2968    {
2969       /* 
2970        * The client got an error message because of a temporary problem,
2971        * the problem is gone and the client now tries to revalidate our
2972        * error message on the real server. The revalidation would always
2973        * end with the transmission of the whole document and there is
2974        * no need to expose the bogus If-Modified-Since header.
2975        */
2976       log_error(LOG_LEVEL_HEADER, "Crunching useless If-Modified-Since header.");
2977       freez(*header);
2978    }
2979    else if (csp->action->flags & ACTION_HIDE_IF_MODIFIED_SINCE)
2980    {
2981       newval = csp->action->string[ACTION_STRING_IF_MODIFIED_SINCE];
2982
2983       if ((0 == strcmpic(newval, "block")))
2984       {
2985          log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
2986          freez(*header);
2987       }
2988       else /* add random value */
2989       {
2990          const char *header_time = *header + sizeof("If-Modified-Since:");
2991
2992          if (JB_ERR_OK != parse_header_time(header_time, &tm))
2993          {
2994             log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s in %s (crunching!)", header_time, *header);
2995             freez(*header);
2996          }
2997          else
2998          {
2999             long int rtime = strtol(newval, &endptr, 0);
3000             const int negative_range = (rtime < 0);
3001
3002             if (rtime)
3003             {
3004                log_error(LOG_LEVEL_HEADER, "Randomizing: %s (random range: %d minut%s)",
3005                   *header, rtime, (rtime == 1 || rtime == -1) ? "e": "es");
3006                if (negative_range)
3007                {
3008                   rtime *= -1; 
3009                }
3010                rtime *= 60;
3011                rtime = pick_from_range(rtime);
3012             }
3013             else
3014             {
3015                log_error(LOG_LEVEL_ERROR, "Random range is 0. Assuming time transformation test.",
3016                   *header);
3017             }
3018             tm += rtime * (negative_range ? -1 : 1);
3019 #ifdef HAVE_GMTIME_R
3020             timeptr = gmtime_r(&tm, &gmt);
3021 #elif defined(MUTEX_LOCKS_AVAILABLE)
3022             privoxy_mutex_lock(&gmtime_mutex);
3023             timeptr = gmtime(&tm);
3024             privoxy_mutex_unlock(&gmtime_mutex);
3025 #else
3026             timeptr = gmtime(&tm);
3027 #endif
3028             strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr);
3029
3030             freez(*header);
3031             *header = strdup("If-Modified-Since: ");
3032             string_append(header, newheader);
3033
3034             if (*header == NULL)
3035             {
3036                log_error(LOG_LEVEL_HEADER, "Insufficient memory, header crunched without replacement.");
3037                return JB_ERR_MEMORY;  
3038             }
3039
3040             hours   = rtime / 3600;
3041             minutes = rtime / 60 % 60;
3042             seconds = rtime % 60;
3043
3044             log_error(LOG_LEVEL_HEADER,
3045                "Randomized:  %s (%s %d hou%s %d minut%s %d second%s",
3046                *header, (negative_range) ? "subtracted" : "added", hours,
3047                (hours == 1) ? "r" : "rs", minutes, (minutes == 1) ? "e" : "es",
3048                seconds, (seconds == 1) ? ")" : "s)");
3049          }
3050       }
3051    }
3052
3053    return JB_ERR_OK;
3054 }
3055
3056
3057 /*********************************************************************
3058  *
3059  * Function    :  client_if_none_match
3060  *
3061  * Description :  Remove the If-None-Match header.
3062  *
3063  * Parameters  :
3064  *          1  :  csp = Current client state (buffers, headers, etc...)
3065  *          2  :  header = On input, pointer to header to modify.
3066  *                On output, pointer to the modified header, or NULL
3067  *                to remove the header.  This function frees the
3068  *                original string if necessary.
3069  *
3070  * Returns     :  JB_ERR_OK on success, or
3071  *                JB_ERR_MEMORY on out-of-memory error.
3072  *
3073  *********************************************************************/
3074 static jb_err client_if_none_match(struct client_state *csp, char **header)
3075 {
3076    if (csp->action->flags & ACTION_CRUNCH_IF_NONE_MATCH)
3077    {  
3078       log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3079       freez(*header);
3080    }
3081
3082    return JB_ERR_OK;
3083 }
3084
3085
3086 /*********************************************************************
3087  *
3088  * Function    :  client_x_filter
3089  *
3090  * Description :  Disables filtering if the client set "X-Filter: No".
3091  *                Called from `sed'.
3092  *
3093  * Parameters  :
3094  *          1  :  csp = Current client state (buffers, headers, etc...)
3095  *          2  :  header = On input, pointer to header to modify.
3096  *                On output, pointer to the modified header, or NULL
3097  *                to remove the header.  This function frees the
3098  *                original string if necessary.
3099  *
3100  * Returns     :  JB_ERR_OK on success
3101  *
3102  *********************************************************************/
3103 jb_err client_x_filter(struct client_state *csp, char **header)
3104 {
3105    if ( 0 == strcmpic(*header, "X-Filter: No"))
3106    {
3107       if (!(csp->config->feature_flags & RUNTIME_FEATURE_HTTP_TOGGLE))
3108       {
3109          log_error(LOG_LEVEL_INFO, "Ignored the client's request to fetch without filtering.");
3110       }
3111       else
3112       {
3113          if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
3114          {
3115             log_error(LOG_LEVEL_HEADER,
3116                "force-text-mode overruled the client's request to fetch without filtering!");
3117          }
3118          else
3119          {  
3120             csp->content_type = CT_TABOO; /* XXX: This hack shouldn't be necessary */
3121             csp->flags |= CSP_FLAG_NO_FILTERING;
3122             log_error(LOG_LEVEL_HEADER, "Accepted the client's request to fetch without filtering.");
3123          }
3124          log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3125          freez(*header);
3126       }
3127    }
3128    return JB_ERR_OK; 
3129 }
3130
3131
3132 /*********************************************************************
3133  *
3134  * Function    :  client_range
3135  *
3136  * Description :  Removes Range, Request-Range and If-Range headers if
3137  *                content filtering is enabled. If the client's version
3138  *                of the document has been altered by Privoxy, the server
3139  *                could interpret the range differently than the client
3140  *                intended in which case the user could end up with
3141  *                corrupted content.
3142  *
3143  * Parameters  :
3144  *          1  :  csp = Current client state (buffers, headers, etc...)
3145  *          2  :  header = On input, pointer to header to modify.
3146  *                On output, pointer to the modified header, or NULL
3147  *                to remove the header.  This function frees the
3148  *                original string if necessary.
3149  *
3150  * Returns     :  JB_ERR_OK
3151  *
3152  *********************************************************************/
3153 static jb_err client_range(struct client_state *csp, char **header)
3154 {
3155    if (content_filters_enabled(csp->action))
3156    {
3157       log_error(LOG_LEVEL_HEADER, "Content filtering is enabled."
3158          " Crunching: \'%s\' to prevent range-mismatch problems.", *header);
3159       freez(*header);
3160    }
3161
3162    return JB_ERR_OK; 
3163 }
3164
3165 /* the following functions add headers directly to the header list */
3166
3167 /*********************************************************************
3168  *
3169  * Function    :  client_host_adder
3170  *
3171  * Description :  Adds the Host: header field if it is missing.
3172  *                Called from `sed'.
3173  *
3174  * Parameters  :
3175  *          1  :  csp = Current client state (buffers, headers, etc...)
3176  *
3177  * Returns     :  JB_ERR_OK on success, or
3178  *                JB_ERR_MEMORY on out-of-memory error.
3179  *
3180  *********************************************************************/
3181 static jb_err client_host_adder(struct client_state *csp)
3182 {
3183    char *p;
3184    jb_err err;
3185
3186    if (csp->flags & CSP_FLAG_HOST_HEADER_IS_SET)
3187    {
3188       /* Header already set by the client, nothing to do. */
3189       return JB_ERR_OK;
3190    }
3191
3192    if ( !csp->http->hostport || !*(csp->http->hostport))
3193    {
3194       /* XXX: When does this happen and why is it OK? */
3195       log_error(LOG_LEVEL_INFO, "Weirdness in client_host_adder detected and ignored.");
3196       return JB_ERR_OK;
3197    }
3198
3199    /*
3200     * remove 'user:pass@' from 'proto://user:pass@host'
3201     */
3202    if ( (p = strchr( csp->http->hostport, '@')) != NULL )
3203    {
3204       p++;
3205    }
3206    else
3207    {
3208       p = csp->http->hostport;
3209    }
3210
3211    /* XXX: Just add it, we already made sure that it will be unique */
3212    log_error(LOG_LEVEL_HEADER, "addh-unique: Host: %s", p);
3213    err = enlist_unique_header(csp->headers, "Host", p);
3214    return err;
3215
3216 }
3217
3218
3219 #if 0
3220 /*********************************************************************
3221  *
3222  * Function    :  client_accept_encoding_adder
3223  *
3224  * Description :  Add an Accept-Encoding header to the client's request
3225  *                that disables compression if the action applies, and
3226  *                the header is not already there. Called from `sed'.
3227  *                Note: For HTTP/1.0, the absence of the header is enough.
3228  *
3229  * Parameters  :
3230  *          1  :  csp = Current client state (buffers, headers, etc...)
3231  *
3232  * Returns     :  JB_ERR_OK on success, or
3233  *                JB_ERR_MEMORY on out-of-memory error.
3234  *
3235  *********************************************************************/
3236 static jb_err client_accept_encoding_adder(struct client_state *csp)
3237 {
3238    if (   ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
3239        && (!strcmpic(csp->http->ver, "HTTP/1.1")) )
3240    {
3241       return enlist_unique(csp->headers, "Accept-Encoding: identity;q=1.0, *;q=0", 16);
3242    }
3243
3244    return JB_ERR_OK;
3245 }
3246 #endif
3247
3248
3249 /*********************************************************************
3250  *
3251  * Function    :  client_xtra_adder
3252  *
3253  * Description :  Used in the add_client_headers list.  Called from `sed'.
3254  *
3255  * Parameters  :
3256  *          1  :  csp = Current client state (buffers, headers, etc...)
3257  *
3258  * Returns     :  JB_ERR_OK on success, or
3259  *                JB_ERR_MEMORY on out-of-memory error.
3260  *
3261  *********************************************************************/
3262 static jb_err client_xtra_adder(struct client_state *csp)
3263 {
3264    struct list_entry *lst;
3265    jb_err err;
3266
3267    for (lst = csp->action->multi[ACTION_MULTI_ADD_HEADER]->first;
3268         lst ; lst = lst->next)
3269    {
3270       log_error(LOG_LEVEL_HEADER, "addh: %s", lst->str);
3271       err = enlist(csp->headers, lst->str);
3272       if (err)
3273       {
3274          return err;
3275       }
3276
3277    }
3278
3279    return JB_ERR_OK;
3280 }
3281
3282
3283 /*********************************************************************
3284  *
3285  * Function    :  client_x_forwarded_for_adder
3286  *
3287  * Description :  Used in the add_client_headers list.  Called from `sed'.
3288  *
3289  * Parameters  :
3290  *          1  :  csp = Current client state (buffers, headers, etc...)
3291  *
3292  * Returns     :  JB_ERR_OK on success, or
3293  *                JB_ERR_MEMORY on out-of-memory error.
3294  *
3295  *********************************************************************/
3296 static jb_err client_x_forwarded_for_adder(struct client_state *csp)
3297 {
3298    char *header = NULL;
3299    jb_err err;
3300
3301    if (!((csp->action->flags & ACTION_CHANGE_X_FORWARDED_FOR)
3302          && (0 == strcmpic(csp->action->string[ACTION_STRING_CHANGE_X_FORWARDED_FOR], "add")))
3303       || (csp->flags & CSP_FLAG_X_FORWARDED_FOR_APPENDED))
3304    {
3305       /*
3306        * If we aren't adding X-Forwarded-For headers,
3307        * or we already appended an existing X-Forwarded-For
3308        * header, there's nothing left to do here.
3309        */
3310       return JB_ERR_OK;
3311    }
3312
3313    header = strdup("X-Forwarded-For: ");
3314    string_append(&header, csp->ip_addr_str);
3315
3316    if (header == NULL)
3317    {
3318       return JB_ERR_MEMORY;
3319    }
3320
3321    log_error(LOG_LEVEL_HEADER, "addh: %s", header);
3322    err = enlist(csp->headers, header);
3323    freez(header);
3324
3325    return err;
3326 }
3327
3328
3329 /*********************************************************************
3330  *
3331  * Function    :  server_connection_adder
3332  *
3333  * Description :  Adds an appropiate "Connection:" header to csp->headers
3334  *                unless the header was already present. Called from `sed'.
3335  *
3336  * Parameters  :
3337  *          1  :  csp = Current client state (buffers, headers, etc...)
3338  *
3339  * Returns     :  JB_ERR_OK on success, or
3340  *                JB_ERR_MEMORY on out-of-memory error.
3341  *
3342  *********************************************************************/
3343 static jb_err server_connection_adder(struct client_state *csp)
3344 {
3345    const unsigned int flags = csp->flags;
3346    const char *response_status_line = csp->headers->first->str;
3347    const char *wanted_header = get_appropiate_connection_header(csp);
3348
3349    if ((flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
3350     && (flags & CSP_FLAG_SERVER_CONNECTION_HEADER_SET))
3351    {
3352       return JB_ERR_OK;
3353    }
3354
3355    /*
3356     * XXX: if we downgraded the response, this check will fail.
3357     */
3358    if ((csp->config->feature_flags &
3359         RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
3360     && (NULL != response_status_line)
3361     && !strncmpic(response_status_line, "HTTP/1.1", 8))
3362    {
3363       log_error(LOG_LEVEL_HEADER, "A HTTP/1.1 response "
3364          "without Connection header implies keep-alive.");
3365       csp->flags |= CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE;
3366    }
3367
3368    log_error(LOG_LEVEL_HEADER, "Adding: %s", wanted_header);
3369
3370    return enlist(csp->headers, wanted_header);
3371 }
3372
3373
3374 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3375 /*********************************************************************
3376  *
3377  * Function    :  server_proxy_connection_adder
3378  *
3379  * Description :  Adds a "Proxy-Connection: keep-alive" header to
3380  *                csp->headers if the client asked for keep-alive.
3381  *                XXX: We should reuse existant ones.
3382  *
3383  * Parameters  :
3384  *          1  :  csp = Current client state (buffers, headers, etc...)
3385  *
3386  * Returns     :  JB_ERR_OK on success, or
3387  *                JB_ERR_MEMORY on out-of-memory error.
3388  *
3389  *********************************************************************/
3390 static jb_err server_proxy_connection_adder(struct client_state *csp)
3391 {
3392    static const char proxy_connection_header[] = "Proxy-Connection: keep-alive";
3393    jb_err err = JB_ERR_OK;
3394
3395    if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE))
3396    {
3397       log_error(LOG_LEVEL_HEADER, "Adding: %s", proxy_connection_header);
3398       err = enlist(csp->headers, proxy_connection_header);
3399    }
3400
3401    return err;
3402 }
3403 #endif /* FEATURE_CONNECTION_KEEP_ALIVE */
3404
3405
3406 /*********************************************************************
3407  *
3408  * Function    :  client_connection_header_adder
3409  *
3410  * Description :  Adds a proper "Connection:" header to csp->headers
3411  *                unless the header was already present. Called from `sed'.
3412  *
3413  * Parameters  :
3414  *          1  :  csp = Current client state (buffers, headers, etc...)
3415  *
3416  * Returns     :  JB_ERR_OK on success, or
3417  *                JB_ERR_MEMORY on out-of-memory error.
3418  *
3419  *********************************************************************/
3420 static jb_err client_connection_header_adder(struct client_state *csp)
3421 {
3422    const char *wanted_header = get_appropiate_connection_header(csp);
3423
3424    if (!(csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
3425      && (csp->flags & CSP_FLAG_CLIENT_CONNECTION_HEADER_SET))
3426    {
3427       return JB_ERR_OK;
3428    }
3429
3430    if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
3431       && (csp->http->ssl == 0))
3432    {
3433       csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
3434    }
3435
3436    log_error(LOG_LEVEL_HEADER, "Adding: %s", wanted_header);
3437
3438    return enlist(csp->headers, wanted_header);
3439 }
3440
3441
3442 /*********************************************************************
3443  *
3444  * Function    :  server_http
3445  *
3446  * Description :  - Save the HTTP Status into csp->http->status
3447  *                - Set CT_TABOO to prevent filtering if the answer
3448  *                  is a partial range (HTTP status 206)
3449  *                - Rewrite HTTP/1.1 answers to HTTP/1.0 if +downgrade
3450  *                  action applies.
3451  *
3452  * Parameters  :
3453  *          1  :  csp = Current client state (buffers, headers, etc...)
3454  *          2  :  header = On input, pointer to header to modify.
3455  *                On output, pointer to the modified header, or NULL
3456  *                to remove the header.  This function frees the
3457  *                original string if necessary.
3458  *
3459  * Returns     :  JB_ERR_OK on success, or
3460  *                JB_ERR_MEMORY on out-of-memory error.
3461  *
3462  *********************************************************************/
3463 static jb_err server_http(struct client_state *csp, char **header)
3464 {
3465    sscanf(*header, "HTTP/%*d.%*d %d", &(csp->http->status));
3466    if (csp->http->status == 206)
3467    {
3468       csp->content_type = CT_TABOO;
3469    }
3470
3471    if ((csp->action->flags & ACTION_DOWNGRADE) != 0)
3472    {
3473       /* XXX: Should we do a real validity check here? */
3474       if (strlen(*header) > 8)
3475       {
3476          (*header)[7] = '0';
3477          log_error(LOG_LEVEL_HEADER, "Downgraded answer to HTTP/1.0");
3478       }
3479       else
3480       {
3481          /*
3482           * XXX: Should we block the request or
3483           * enlist a valid status code line here?
3484           */
3485          log_error(LOG_LEVEL_INFO, "Malformed server response detected. "
3486             "Downgrading to HTTP/1.0 impossible.");
3487       }
3488    }
3489
3490    return JB_ERR_OK;
3491 }
3492
3493
3494 /*********************************************************************
3495  *
3496  * Function    :  server_set_cookie
3497  *
3498  * Description :  Handle the server "cookie" header properly.
3499  *                Log cookie to the jar file.  Then "crunch",
3500  *                accept or rewrite it to a session cookie.
3501  *                Called from `sed'.
3502  *
3503  *                TODO: Allow the user to specify a new expiration
3504  *                time to cause the cookie to expire even before the
3505  *                browser is closed.
3506  *
3507  * Parameters  :
3508  *          1  :  csp = Current client state (buffers, headers, etc...)
3509  *          2  :  header = On input, pointer to header to modify.
3510  *                On output, pointer to the modified header, or NULL
3511  *                to remove the header.  This function frees the
3512  *                original string if necessary.
3513  *
3514  * Returns     :  JB_ERR_OK on success, or
3515  *                JB_ERR_MEMORY on out-of-memory error.
3516  *
3517  *********************************************************************/
3518 static jb_err server_set_cookie(struct client_state *csp, char **header)
3519 {
3520    time_t now;
3521    time_t cookie_time; 
3522
3523    time(&now);
3524
3525    if ((csp->action->flags & ACTION_NO_COOKIE_SET) != 0)
3526    {
3527       log_error(LOG_LEVEL_HEADER, "Crunching incoming cookie: %s", *header);
3528       freez(*header);
3529    }
3530    else if ((csp->action->flags & ACTION_NO_COOKIE_KEEP) != 0)
3531    {
3532       /* Flag whether or not to log a message */
3533       int changed = 0;
3534
3535       /* A variable to store the tag we're working on */
3536       char *cur_tag;
3537
3538       /* Skip "Set-Cookie:" (11 characters) in header */
3539       cur_tag = *header + 11;
3540
3541       /* skip whitespace between "Set-Cookie:" and value */
3542       while (*cur_tag && ijb_isspace(*cur_tag))
3543       {
3544          cur_tag++;
3545       }
3546
3547       /* Loop through each tag in the cookie */
3548       while (*cur_tag)
3549       {
3550          /* Find next tag */
3551          char *next_tag = strchr(cur_tag, ';');
3552          if (next_tag != NULL)
3553          {
3554             /* Skip the ';' character itself */
3555             next_tag++;
3556
3557             /* skip whitespace ";" and start of tag */
3558             while (*next_tag && ijb_isspace(*next_tag))
3559             {
3560                next_tag++;
3561             }
3562          }
3563          else
3564          {
3565             /* "Next tag" is the end of the string */
3566             next_tag = cur_tag + strlen(cur_tag);
3567          }
3568
3569          /*
3570           * Check the expiration date to see
3571           * if the cookie is still valid, if yes,
3572           * rewrite it to a session cookie.
3573           */
3574          if ((strncmpic(cur_tag, "expires=", 8) == 0) && *(cur_tag + 8))
3575          {
3576             char *expiration_date = cur_tag + 8; /* Skip "[Ee]xpires=" */
3577
3578             /* Did we detect the date properly? */
3579             if (JB_ERR_OK != parse_header_time(expiration_date, &cookie_time))
3580             {
3581                /*
3582                 * Nope, treat it as if it was still valid.
3583                 *
3584                 * XXX: Should we remove the whole cookie instead?
3585                 */
3586                log_error(LOG_LEVEL_ERROR,
3587                   "Can't parse \'%s\', send by %s. Unsupported time format?", cur_tag, csp->http->url);
3588                string_move(cur_tag, next_tag);
3589                changed = 1;
3590             }
3591             else
3592             {
3593                /*
3594                 * Yes. Check if the cookie is still valid.
3595                 *
3596                 * If the cookie is already expired it's probably
3597                 * a delete cookie and even if it isn't, the browser
3598                 * will discard it anyway.
3599                 */
3600
3601                /*
3602                 * XXX: timegm() isn't available on some AmigaOS
3603                 * versions and our replacement doesn't work.
3604                 *
3605                 * Our options are to either:
3606                 *
3607                 * - disable session-cookies-only completely if timegm
3608                 *   is missing,
3609                 *
3610                 * - to simply remove all expired tags, like it has
3611                 *   been done until Privoxy 3.0.6 and to live with
3612                 *    the consequence that it can cause login/logout
3613                 *   problems on servers that don't validate their
3614                 *   input properly, or
3615                 *
3616                 * - to replace it with mktime in which
3617                 *   case there is a slight chance of valid cookies
3618                 *   passing as already expired.
3619                 *
3620                 *   This is the way it's currently done and it's not
3621                 *   as bad as it sounds. If the missing GMT offset is
3622                 *   enough to change the result of the expiration check
3623                 *   the cookie will be only valid for a few hours
3624                 *   anyway, which in many cases will be shorter
3625                 *   than a browser session.
3626                 */
3627                if (cookie_time - now < 0)
3628                {
3629                   log_error(LOG_LEVEL_HEADER,
3630                      "Cookie \'%s\' is already expired and can pass unmodified.", *header);
3631                   /* Just in case some clown sets more then one expiration date */
3632                   cur_tag = next_tag;
3633                }
3634                else
3635                {
3636                   /*
3637                    * Still valid, delete expiration date by copying
3638                    * the rest of the string over it.
3639                    */
3640                   string_move(cur_tag, next_tag);
3641
3642                   /* That changed the header, need to issue a log message */
3643                   changed = 1;
3644
3645                   /*
3646                    * Note that the next tag has now been moved to *cur_tag,
3647                    * so we do not need to update the cur_tag pointer.
3648                    */
3649                }
3650             }
3651
3652          }
3653          else
3654          {
3655             /* Move on to next cookie tag */
3656             cur_tag = next_tag;
3657          }
3658       }
3659
3660       if (changed)
3661       {
3662          assert(NULL != *header);
3663          log_error(LOG_LEVEL_HEADER, "Cookie rewritten to a temporary one: %s",
3664             *header);
3665       }
3666    }
3667
3668    return JB_ERR_OK;
3669 }
3670
3671
3672 #ifdef FEATURE_FORCE_LOAD
3673 /*********************************************************************
3674  *
3675  * Function    :  strclean
3676  *
3677  * Description :  In-Situ-Eliminate all occurances of substring in
3678  *                string
3679  *
3680  * Parameters  :
3681  *          1  :  string = string to clean
3682  *          2  :  substring = substring to eliminate
3683  *
3684  * Returns     :  Number of eliminations
3685  *
3686  *********************************************************************/
3687 int strclean(char *string, const char *substring)
3688 {
3689    int hits = 0;
3690    size_t len;
3691    char *pos, *p;
3692
3693    len = strlen(substring);
3694
3695    while((pos = strstr(string, substring)) != NULL)
3696    {
3697       p = pos + len;
3698       do
3699       {
3700          *(p - len) = *p;
3701       }
3702       while (*p++ != '\0');
3703
3704       hits++;
3705    }
3706
3707    return(hits);
3708 }
3709 #endif /* def FEATURE_FORCE_LOAD */
3710
3711
3712 /*********************************************************************
3713  *
3714  * Function    :  parse_header_time
3715  *
3716  * Description :  Parses time formats used in HTTP header strings
3717  *                to get the numerical respresentation.
3718  *
3719  * Parameters  :
3720  *          1  :  header_time = HTTP header time as string. 
3721  *          2  :  result = storage for header_time in seconds
3722  *
3723  * Returns     :  JB_ERR_OK if the time format was recognized, or
3724  *                JB_ERR_PARSE otherwise.
3725  *
3726  *********************************************************************/
3727 static jb_err parse_header_time(const char *header_time, time_t *result)
3728 {
3729    struct tm gmt;
3730
3731    /*
3732     * Zero out gmt to prevent time zone offsets.
3733     *
3734     * While this is only necessary on some platforms
3735     * (mingw32 for example), I don't know how to
3736     * detect these automatically and doing it everywhere
3737     * shouldn't hurt.
3738     */
3739    memset(&gmt, 0, sizeof(gmt));
3740
3741                             /* Tue, 02 Jun 2037 20:00:00 */
3742    if ((NULL == strptime(header_time, "%a, %d %b %Y %H:%M:%S", &gmt))
3743                             /* Tue, 02-Jun-2037 20:00:00 */
3744     && (NULL == strptime(header_time, "%a, %d-%b-%Y %H:%M:%S", &gmt))
3745                             /* Tue, 02-Jun-37 20:00:00 */
3746     && (NULL == strptime(header_time, "%a, %d-%b-%y %H:%M:%S", &gmt))
3747                         /* Tuesday, 02-Jun-2037 20:00:00 */
3748     && (NULL == strptime(header_time, "%A, %d-%b-%Y %H:%M:%S", &gmt))
3749                         /* Tuesday Jun 02 20:00:00 2037 */
3750     && (NULL == strptime(header_time, "%A %b %d %H:%M:%S %Y", &gmt)))
3751    {
3752       return JB_ERR_PARSE;
3753    }
3754
3755    *result = timegm(&gmt);
3756
3757    return JB_ERR_OK;
3758
3759 }
3760
3761
3762 /*********************************************************************
3763  *
3764  * Function    :  get_destination_from_headers
3765  *
3766  * Description :  Parse the "Host:" header to get the request's destination.
3767  *                Only needed if the client's request was forcefully
3768  *                redirected into Privoxy.
3769  *
3770  *                Code mainly copied from client_host() which is currently
3771  *                run too late for this purpose.
3772  *
3773  * Parameters  :
3774  *          1  :  headers = List of headers (one of them hopefully being
3775  *                the "Host:" header)
3776  *          2  :  http = storage for the result (host, port and hostport). 
3777  *
3778  * Returns     :  JB_ERR_MEMORY in case of memory problems,
3779  *                JB_ERR_PARSE if the host header couldn't be found,
3780  *                JB_ERR_OK otherwise.
3781  *
3782  *********************************************************************/
3783 jb_err get_destination_from_headers(const struct list *headers, struct http_request *http)
3784 {
3785    char *q;
3786    char *p;
3787    char *host;
3788
3789    host = get_header_value(headers, "Host:");
3790
3791    if (NULL == host)
3792    {
3793       log_error(LOG_LEVEL_ERROR, "No \"Host:\" header found.");
3794       return JB_ERR_PARSE;
3795    }
3796
3797    if (NULL == (p = strdup((host))))
3798    {
3799       log_error(LOG_LEVEL_ERROR, "Out of memory while parsing \"Host:\" header");
3800       return JB_ERR_MEMORY;
3801    }
3802    chomp(p);
3803    if (NULL == (q = strdup(p)))
3804    {
3805       freez(p);
3806       log_error(LOG_LEVEL_ERROR, "Out of memory while parsing \"Host:\" header");
3807       return JB_ERR_MEMORY;
3808    }
3809
3810    freez(http->hostport);
3811    http->hostport = p;
3812    freez(http->host);
3813    http->host = q;
3814    q = strchr(http->host, ':');
3815    if (q != NULL)
3816    {
3817       /* Terminate hostname and evaluate port string */
3818       *q++ = '\0';
3819       http->port = atoi(q);
3820    }
3821    else
3822    {
3823       http->port = http->ssl ? 443 : 80;
3824    }
3825
3826    /* Rebuild request URL */
3827    freez(http->url);
3828    http->url = strdup(http->ssl ? "https://" : "http://");
3829    string_append(&http->url, http->hostport);
3830    string_append(&http->url, http->path);
3831    if (http->url == NULL)
3832    {
3833       return JB_ERR_MEMORY;
3834    }
3835
3836    log_error(LOG_LEVEL_HEADER, "Destination extracted from \"Host:\" header. New request URL: %s",
3837       http->url);
3838
3839    return JB_ERR_OK;
3840
3841 }
3842
3843
3844 /*********************************************************************
3845  *
3846  * Function    :  create_forged_referrer
3847  *
3848  * Description :  Helper for client_referrer to forge a referer as
3849  *                'http://[hostname:port/' to fool stupid
3850  *                checks for in-site links 
3851  *
3852  * Parameters  :
3853  *          1  :  header   = Pointer to header pointer
3854  *          2  :  hostport = Host and optionally port as string
3855  *
3856  * Returns     :  JB_ERR_OK in case of success, or
3857  *                JB_ERR_MEMORY in case of memory problems.
3858  *
3859  *********************************************************************/
3860 static jb_err create_forged_referrer(char **header, const char *hostport)
3861 {
3862     assert(NULL == *header);
3863
3864     *header = strdup("Referer: http://");
3865     string_append(header, hostport);
3866     string_append(header, "/");
3867
3868     if (NULL == *header)
3869     {
3870        return JB_ERR_MEMORY;
3871     }
3872
3873     log_error(LOG_LEVEL_HEADER, "Referer forged to: %s", *header);
3874
3875     return JB_ERR_OK;
3876
3877 }
3878
3879
3880 /*********************************************************************
3881  *
3882  * Function    :  create_fake_referrer
3883  *
3884  * Description :  Helper for client_referrer to create a fake referrer
3885  *                based on a string supplied by the user.
3886  *
3887  * Parameters  :
3888  *          1  :  header   = Pointer to header pointer
3889  *          2  :  hosthost = Referrer to fake
3890  *
3891  * Returns     :  JB_ERR_OK in case of success, or
3892  *                JB_ERR_MEMORY in case of memory problems.
3893  *
3894  *********************************************************************/
3895 static jb_err create_fake_referrer(char **header, const char *fake_referrer)
3896 {
3897    assert(NULL == *header);
3898
3899    if ((0 != strncmpic(fake_referrer, "http://", 7)) && (0 != strncmpic(fake_referrer, "https://", 8)))
3900    {
3901       log_error(LOG_LEVEL_HEADER,
3902          "Parameter: +hide-referrer{%s} is a bad idea, but I don't care.", fake_referrer);
3903    }
3904    *header = strdup("Referer: ");
3905    string_append(header, fake_referrer);
3906
3907    if (NULL == *header)
3908    {
3909       return JB_ERR_MEMORY;
3910    }
3911
3912    log_error(LOG_LEVEL_HEADER, "Referer replaced with: %s", *header);
3913
3914    return JB_ERR_OK;
3915
3916 }
3917
3918
3919 /*********************************************************************
3920  *
3921  * Function    :  handle_conditional_hide_referrer_parameter
3922  *
3923  * Description :  Helper for client_referrer to crunch or forge
3924  *                the referrer header if the host has changed.
3925  *
3926  * Parameters  :
3927  *          1  :  header = Pointer to header pointer
3928  *          2  :  host   = The target host (may include the port)
3929  *          3  :  parameter_conditional_block = Boolean to signal
3930  *                if we're in conditional-block mode. If not set,
3931  *                we're in conditional-forge mode.
3932  *
3933  * Returns     :  JB_ERR_OK in case of success, or
3934  *                JB_ERR_MEMORY in case of memory problems.
3935  *
3936  *********************************************************************/
3937 static jb_err handle_conditional_hide_referrer_parameter(char **header,
3938    const char *host, const int parameter_conditional_block)
3939 {
3940    char *referer = strdup(*header);
3941    const size_t hostlenght = strlen(host);
3942    const char *referer_url = NULL;
3943
3944    if (NULL == referer)
3945    {
3946       freez(*header);
3947       return JB_ERR_MEMORY;
3948    }
3949
3950    /* referer begins with 'Referer: http[s]://' */
3951    if ((hostlenght+17) < strlen(referer))
3952    {
3953       /*
3954        * Shorten referer to make sure the referer is blocked
3955        * if www.example.org/www.example.com-shall-see-the-referer/
3956        * links to www.example.com/
3957        */
3958       referer[hostlenght+17] = '\0';
3959    }
3960    referer_url = strstr(referer, "http://");
3961    if ((NULL == referer_url) || (NULL == strstr(referer_url, host)))
3962    {
3963       /* Host has changed, Referer is invalid or a https URL. */
3964       if (parameter_conditional_block)
3965       {
3966          log_error(LOG_LEVEL_HEADER, "New host is: %s. Crunching %s!", host, *header);
3967          freez(*header);
3968       }
3969       else
3970       {
3971          freez(*header);
3972          freez(referer);
3973          return create_forged_referrer(header, host);
3974       }
3975    }
3976    freez(referer);
3977
3978    return JB_ERR_OK;
3979
3980 }
3981
3982
3983 /*********************************************************************
3984  *
3985  * Function    :  get_appropiate_connection_header
3986  *
3987  * Description :  Returns an appropiate Connection header
3988  *                depending on whether or not we try to keep
3989  *                the connection to the server alive.
3990  *
3991  * Parameters  :
3992  *          1  :  csp = Current client state (buffers, headers, etc...)
3993  *
3994  * Returns     :  Pointer to statically allocated header buffer.
3995  *
3996  *********************************************************************/
3997 static const char *get_appropiate_connection_header(const struct client_state *csp)
3998 {
3999    static const char connection_keep_alive[] = "Connection: keep-alive";
4000    static const char connection_close[] = "Connection: close";
4001
4002    if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
4003     && (csp->http->ssl == 0))
4004    {
4005       return connection_keep_alive;
4006    }
4007    return connection_close;
4008 }
4009 /*
4010   Local Variables:
4011   tab-width: 3
4012   end:
4013 */