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