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