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