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