Introduce tags as alternative way to specify which
[privoxy.git] / parsers.c
1 const char parsers_rcs[] = "$Id: parsers.c,v 1.96 2007/04/12 12:53:58 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-2007 the SourceForge
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  * Revisions   :
46  *    $Log: parsers.c,v $
47  *    Revision 1.96  2007/04/12 12:53:58  fabiankeil
48  *    Log a warning if the content is compressed, filtering is
49  *    enabled and Privoxy was compiled without zlib support.
50  *    Closes FR#1673938.
51  *
52  *    Revision 1.95  2007/03/25 14:26:40  fabiankeil
53  *    - Fix warnings when compiled with glibc.
54  *    - Don't use crumble() for cookie crunching.
55  *    - Move cookie time parsing into parse_header_time().
56  *    - Let parse_header_time() return a jb_err code
57  *      instead of a pointer that can only be used to
58  *      check for NULL anyway.
59  *
60  *    Revision 1.94  2007/03/21 12:23:53  fabiankeil
61  *    - Add better protection against malicious gzip headers.
62  *    - Stop logging the first hundred bytes of decompressed content.
63  *      It looks like it's working and there is always debug 16.
64  *    - Log the content size after decompression in decompress_iob()
65  *      instead of pcrs_filter_response().
66  *
67  *    Revision 1.93  2007/03/20 15:21:44  fabiankeil
68  *    - Use dedicated header filter actions instead of abusing "filter".
69  *      Replace "filter-client-headers" and "filter-client-headers"
70  *      with "server-header-filter" and "client-header-filter".
71  *    - Remove filter_client_header() and filter_client_header(),
72  *      filter_header() now checks the shiny new
73  *      CSP_FLAG_CLIENT_HEADER_PARSING_DONE flag instead.
74  *
75  *    Revision 1.92  2007/03/05 13:25:32  fabiankeil
76  *    - Cosmetical changes for LOG_LEVEL_RE_FILTER messages.
77  *    - Handle "Cookie:" and "Connection:" headers a bit smarter
78  *      (don't crunch them just to recreate them later on).
79  *    - Add another non-standard time format for the cookie
80  *      expiration date detection.
81  *    - Fix a valgrind warning.
82  *
83  *    Revision 1.91  2007/02/24 12:27:32  fabiankeil
84  *    Improve cookie expiration date detection.
85  *
86  *    Revision 1.90  2007/02/08 19:12:35  fabiankeil
87  *    Don't run server_content_length() the first time
88  *    sed() parses server headers; only adjust the
89  *    Content-Length header if the page was modified.
90  *
91  *    Revision 1.89  2007/02/07 16:52:11  fabiankeil
92  *    Fix log messages regarding the cookie time format
93  *    (cookie and request URL were mixed up).
94  *
95  *    Revision 1.88  2007/02/07 11:27:12  fabiankeil
96  *    - Let decompress_iob()
97  *      - not corrupt the content if decompression fails
98  *        early. (the first byte(s) were lost).
99  *      - use pointer arithmetics with defined outcome for
100  *        a change.
101  *    - Use a different kludge to remember a failed decompression.
102  *
103  *    Revision 1.87  2007/01/31 16:21:38  fabiankeil
104  *    Search for Max-Forwards headers case-insensitive,
105  *    don't generate the "501 unsupported" message for invalid
106  *    Max-Forwards values and don't increase negative ones.
107  *
108  *    Revision 1.86  2007/01/30 13:05:26  fabiankeil
109  *    - Let server_set_cookie() check the expiration date
110  *      of cookies and don't touch the ones that are already
111  *      expired. Fixes problems with low quality web applications
112  *      as described in BR 932612.
113  *
114  *    - Adjust comment in client_max_forwards to reality;
115  *      remove invalid Max-Forwards headers.
116  *
117  *    Revision 1.85  2007/01/26 15:33:46  fabiankeil
118  *    Stop filter_header() from unintentionally removing
119  *    empty header lines that were enlisted by the continue
120  *    hack.
121  *
122  *    Revision 1.84  2007/01/24 12:56:52  fabiankeil
123  *    - Repeat the request URL before logging any headers.
124  *      Makes reading the log easier in case of simultaneous requests.
125  *    - If there are more than one Content-Type headers in one request,
126  *      use the first one and remove the others.
127  *    - Remove "newval" variable in server_content_type().
128  *      It's only used once.
129  *
130  *    Revision 1.83  2007/01/12 15:03:02  fabiankeil
131  *    Correct a cast, check inflateEnd() exit code
132  *    to see if we have to, replace sprintf calls
133  *    with snprintf.
134  *
135  *    Revision 1.82  2007/01/01 19:36:37  fabiankeil
136  *    Integrate a modified version of Wil Mahan's
137  *    zlib patch (PR #895531).
138  *
139  *    Revision 1.81  2006/12/31 22:21:33  fabiankeil
140  *    Skip empty filter files in filter_header()
141  *    but don't ignore the ones that come afterwards.
142  *    Fixes BR 1619208, this time for real.
143  *
144  *    Revision 1.80  2006/12/29 19:08:22  fabiankeil
145  *    Reverted parts of my last commit
146  *    to keep error handling working.
147  *
148  *    Revision 1.79  2006/12/29 18:04:40  fabiankeil
149  *    Fixed gcc43 conversion warnings.
150  *
151  *    Revision 1.78  2006/12/26 17:19:20  fabiankeil
152  *    Bringing back the "useless" localtime() call
153  *    I removed in revision 1.67. On some platforms
154  *    it's necessary to prevent time zone offsets.
155  *
156  *    Revision 1.77  2006/12/07 18:44:26  fabiankeil
157  *    Rebuild request URL in get_destination_from_headers()
158  *    to make sure redirect{pcrs command} works as expected
159  *    for intercepted requests.
160  *
161  *    Revision 1.76  2006/12/06 19:52:25  fabiankeil
162  *    Added get_destination_from_headers().
163  *
164  *    Revision 1.75  2006/11/13 19:05:51  fabiankeil
165  *    Make pthread mutex locking more generic. Instead of
166  *    checking for OSX and OpenBSD, check for FEATURE_PTHREAD
167  *    and use mutex locking unless there is an _r function
168  *    available. Better safe than sorry.
169  *
170  *    Fixes "./configure --disable-pthread" and should result
171  *    in less threading-related problems on pthread-using platforms,
172  *    but it still doesn't fix BR#1122404.
173  *
174  *    Revision 1.74  2006/10/02 16:59:12  fabiankeil
175  *    The special header "X-Filter: No" now disables
176  *    header filtering as well.
177  *
178  *    Revision 1.73  2006/09/23 13:26:38  roro
179  *    Replace TABs by spaces in source code.
180  *
181  *    Revision 1.72  2006/09/23 12:37:21  fabiankeil
182  *    Don't print a log message every time filter_headers is
183  *    entered or left. It only creates noise without any real
184  *    information.
185  *
186  *    Revision 1.71  2006/09/21 19:55:17  fabiankeil
187  *    Fix +hide-if-modified-since{-n}.
188  *
189  *    Revision 1.70  2006/09/08 12:06:34  fabiankeil
190  *    Have hide-if-modified-since interpret the random
191  *    range value as minutes instead of hours. Allows
192  *    more fine-grained configuration.
193  *
194  *    Revision 1.69  2006/09/06 16:25:51  fabiankeil
195  *    Always have parse_header_time return a pointer
196  *    that actual makes sense, even though we currently
197  *    only need it to detect problems.
198  *
199  *    Revision 1.68  2006/09/06 10:43:32  fabiankeil
200  *    Added config option enable-remote-http-toggle
201  *    to specify if Privoxy should recognize special
202  *    headers (currently only X-Filter) to change its
203  *    behaviour. Disabled by default.
204  *
205  *    Revision 1.67  2006/09/04 11:01:26  fabiankeil
206  *    After filtering de-chunked instances, remove
207  *    "Transfer-Encoding" header entirely instead of changing
208  *    it to "Transfer-Encoding: identity", which is invalid.
209  *    Thanks Michael Shields <shields@msrl.com>. Fixes PR 1318658.
210  *
211  *    Don't use localtime in parse_header_time. An empty time struct
212  *    is good enough, it gets overwritten by strptime anyway.
213  *
214  *    Revision 1.66  2006/09/03 19:38:28  fabiankeil
215  *    Use gmtime_r if available, fallback to gmtime with mutex
216  *    protection for MacOSX and use vanilla gmtime for the rest.
217  *
218  *    Revision 1.65  2006/08/22 10:55:56  fabiankeil
219  *    Changed client_referrer to use the right type (size_t) for
220  *    hostlenght and to shorten the temporary referrer string with
221  *    '\0' instead of adding a useless line break.
222  *
223  *    Revision 1.64  2006/08/17 17:15:10  fabiankeil
224  *    - Back to timegm() using GnuPG's replacement if necessary.
225  *      Using mktime() and localtime() could add a on hour offset if
226  *      the randomize factor was big enough to lead to a summer/wintertime
227  *      switch.
228  *
229  *    - Removed now-useless Privoxy 3.0.3 compatibility glue.
230  *
231  *    - Moved randomization code into pick_from_range().
232  *
233  *    - Changed parse_header_time definition.
234  *      time_t isn't guaranteed to be signed and
235  *      if it isn't, -1 isn't available as error code.
236  *      Changed some variable types in client_if_modified_since()
237  *      because of the same reason.
238  *
239  *    Revision 1.63  2006/08/14 13:18:08  david__schmidt
240  *    OS/2 compilation compatibility fixups
241  *
242  *    Revision 1.62  2006/08/14 08:58:42  fabiankeil
243  *    Changed include from strptime.c to strptime.h
244  *
245  *    Revision 1.61  2006/08/14 08:25:19  fabiankeil
246  *    Split filter-headers{} into filter-client-headers{}
247  *    and filter-server-headers{}.
248  *    Added parse_header_time() to share some code.
249  *    Replaced timegm() with mktime().
250  *
251  *    Revision 1.60  2006/08/12 03:54:37  david__schmidt
252  *    Windows service integration
253  *
254  *    Revision 1.59  2006/08/03 02:46:41  david__schmidt
255  *    Incorporate Fabian Keil's patch work:\rhttp://www.fabiankeil.de/sourcecode/privoxy/
256  *
257  *    Revision 1.58  2006/07/18 14:48:47  david__schmidt
258  *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
259  *    with what was really the latest development (the v_3_0_branch branch)
260  *
261  *    Revision 1.56.2.10  2006/01/21 16:16:08  david__schmidt
262  *    Thanks to  Edward Carrel for his patch to modernize OSX's\rpthreads support.  See bug #1409623.
263  *
264  *    Revision 1.56.2.9  2004/10/03 12:53:45  david__schmidt
265  *    Add the ability to check jpeg images for invalid
266  *    lengths of comment blocks.  Defensive strategy
267  *    against the exploit:
268  *       Microsoft Security Bulletin MS04-028
269  *       Buffer Overrun in JPEG Processing (GDI+) Could
270  *       Allow Code Execution (833987)
271  *    Enabled with +inspect-jpegs in actions files.
272  *
273  *    Revision 1.56.2.8  2003/07/11 13:21:25  oes
274  *    Excluded text/plain objects from filtering. This fixes a
275  *    couple of client-crashing, download corruption and
276  *    Privoxy performance issues, whose root cause lies in
277  *    web servers labelling content of unknown type as text/plain.
278  *
279  *    Revision 1.56.2.7  2003/05/06 12:07:26  oes
280  *    Fixed bug #729900: Suspicious HOST: headers are now killed and regenerated if necessary
281  *
282  *    Revision 1.56.2.6  2003/04/14 21:28:30  oes
283  *    Completing the previous change
284  *
285  *    Revision 1.56.2.5  2003/04/14 12:08:16  oes
286  *    Added temporary workaround for bug in PHP < 4.2.3
287  *
288  *    Revision 1.56.2.4  2003/03/07 03:41:05  david__schmidt
289  *    Wrapping all *_r functions (the non-_r versions of them) with mutex semaphores for OSX.  Hopefully this will take care of all of those pesky crash reports.
290  *
291  *    Revision 1.56.2.3  2002/11/10 04:20:02  hal9
292  *    Fix typo: supressed -> suppressed
293  *
294  *    Revision 1.56.2.2  2002/09/25 14:59:53  oes
295  *    Improved cookie logging
296  *
297  *    Revision 1.56.2.1  2002/09/25 14:52:45  oes
298  *    Added basic support for OPTIONS and TRACE HTTP methods:
299  *     - New parser function client_max_forwards which decrements
300  *       the Max-Forwards HTTP header field of OPTIONS and TRACE
301  *       requests by one before forwarding
302  *     - New parser function client_host which extracts the host
303  *       and port information from the HTTP header field if the
304  *       request URI was not absolute
305  *     - Don't crumble and re-add the Host: header, but only generate
306  *       and append if missing
307  *
308  *    Revision 1.56  2002/05/12 15:34:22  jongfoster
309  *    Fixing typo in a comment
310  *
311  *    Revision 1.55  2002/05/08 16:01:07  oes
312  *    Optimized add_to_iob:
313  *     - Use realloc instead of malloc(), memcpy(), free()
314  *     - Expand to powers of two if possible, to get
315  *       O(log n) reallocs instead of O(n).
316  *     - Moved check for buffer limit here from chat
317  *     - Report failure via returncode
318  *
319  *    Revision 1.54  2002/04/02 15:03:16  oes
320  *    Tiny code cosmetics
321  *
322  *    Revision 1.53  2002/03/26 22:29:55  swa
323  *    we have a new homepage!
324  *
325  *    Revision 1.52  2002/03/24 13:25:43  swa
326  *    name change related issues
327  *
328  *    Revision 1.51  2002/03/13 00:27:05  jongfoster
329  *    Killing warnings
330  *
331  *    Revision 1.50  2002/03/12 01:45:35  oes
332  *    More verbose logging
333  *
334  *    Revision 1.49  2002/03/09 20:03:52  jongfoster
335  *    - Making various functions return int rather than size_t.
336  *      (Undoing a recent change).  Since size_t is unsigned on
337  *      Windows, functions like read_socket that return -1 on
338  *      error cannot return a size_t.
339  *
340  *      THIS WAS A MAJOR BUG - it caused frequent, unpredictable
341  *      crashes, and also frequently caused JB to jump to 100%
342  *      CPU and stay there.  (Because it thought it had just
343  *      read ((unsigned)-1) == 4Gb of data...)
344  *
345  *    - The signature of write_socket has changed, it now simply
346  *      returns success=0/failure=nonzero.
347  *
348  *    - Trying to get rid of a few warnings --with-debug on
349  *      Windows, I've introduced a new type "jb_socket".  This is
350  *      used for the socket file descriptors.  On Windows, this
351  *      is SOCKET (a typedef for unsigned).  Everywhere else, it's
352  *      an int.  The error value can't be -1 any more, so it's
353  *      now JB_INVALID_SOCKET (which is -1 on UNIX, and in
354  *      Windows it maps to the #define INVALID_SOCKET.)
355  *
356  *    - The signature of bind_port has changed.
357  *
358  *    Revision 1.48  2002/03/07 03:46:53  oes
359  *    Fixed compiler warnings etc
360  *
361  *    Revision 1.47  2002/02/20 23:15:13  jongfoster
362  *    Parsing functions now handle out-of-memory gracefully by returning
363  *    an error code.
364  *
365  *    Revision 1.46  2002/01/17 21:03:47  jongfoster
366  *    Moving all our URL and URL pattern parsing code to urlmatch.c.
367  *
368  *    Revision 1.45  2002/01/09 14:33:03  oes
369  *    Added support for localtime_r.
370  *
371  *    Revision 1.44  2001/12/14 01:22:54  steudten
372  *    Remove 'user:pass@' from 'proto://user:pass@host' for the
373  *    new added header 'Host: ..'. (See Req ID 491818)
374  *
375  *    Revision 1.43  2001/11/23 00:26:38  jongfoster
376  *    Fixing two really stupid errors in my previous commit
377  *
378  *    Revision 1.42  2001/11/22 21:59:30  jongfoster
379  *    Adding code to handle +no-cookies-keep
380  *
381  *    Revision 1.41  2001/11/05 23:43:05  steudten
382  *    Add time+date to log files.
383  *
384  *    Revision 1.40  2001/10/26 20:13:09  jongfoster
385  *    ctype.h is needed in Windows, too.
386  *
387  *    Revision 1.39  2001/10/26 17:40:04  oes
388  *    Introduced get_header_value()
389  *    Removed http->user_agent, csp->referrer and csp->accept_types
390  *    Removed client_accept()
391  *
392  *    Revision 1.38  2001/10/25 03:40:48  david__schmidt
393  *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
394  *    threads to call select() simultaneously.  So, it's time to do a real, live,
395  *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
396  *    (native). Both versions will work, but using __OS2__ offers multi-threading.
397  *
398  *    Revision 1.37  2001/10/23 21:36:02  jongfoster
399  *    Documenting sed()'s error behaviou (doc change only)
400  *
401  *    Revision 1.36  2001/10/13 12:51:51  joergs
402  *    Removed client_host, (was only required for the old 2.0.2-11 http://noijb.
403  *    force-load), instead crumble Host: and add it (again) in client_host_adder
404  *    (in case we get a HTTP/1.0 request without Host: header and forward it to
405  *    a HTTP/1.1 server/proxy).
406  *
407  *    Revision 1.35  2001/10/09 22:39:21  jongfoster
408  *    assert.h is also required under Win32, so moving out of #ifndef _WIN32
409  *    block.
410  *
411  *    Revision 1.34  2001/10/07 18:50:55  oes
412  *    Added server_content_encoding, renamed server_transfer_encoding
413  *
414  *    Revision 1.33  2001/10/07 18:04:49  oes
415  *    Changed server_http11 to server_http and its pattern to "HTTP".
416  *      Additional functionality: it now saves the HTTP status into
417  *      csp->http->status and sets CT_TABOO for Status 206 (partial range)
418  *
419  *    Revision 1.32  2001/10/07 15:43:28  oes
420  *    Removed FEATURE_DENY_GZIP and replaced it with client_accept_encoding,
421  *       client_te and client_accept_encoding_adder, triggered by the new
422  *       +no-compression action. For HTTP/1.1 the Accept-Encoding header is
423  *       changed to allow only identity and chunked, and the TE header is
424  *       crunched. For HTTP/1.0, Accept-Encoding is crunched.
425  *
426  *    parse_http_request no longer does anything than parsing. The rewriting
427  *      of http->cmd and version mangling are gone. It now also recognizes
428  *      the put and delete methods and saves the url in http->url. Removed
429  *      unused variable.
430  *
431  *    renamed content_type and content_length to have the server_ prefix
432  *
433  *    server_content_type now only works if csp->content_type != CT_TABOO
434  *
435  *    added server_transfer_encoding, which
436  *      - Sets CT_TABOO to prohibit filtering if encoding compresses
437  *      - Raises the CSP_FLAG_CHUNKED flag if Encoding is "chunked"
438  *      - Change from "chunked" to "identity" if body was chunked
439  *        but has been de-chunked for filtering.
440  *
441  *    added server_content_md5 which crunches any Content-MD5 headers
442  *      if the body was modified.
443  *
444  *    made server_http11 conditional on +downgrade action
445  *
446  *    Replaced 6 boolean members of csp with one bitmap (csp->flags)
447  *
448  *    Revision 1.31  2001/10/05 14:25:02  oes
449  *    Crumble Keep-Alive from Server
450  *
451  *    Revision 1.30  2001/09/29 12:56:03  joergs
452  *    IJB now changes HTTP/1.1 to HTTP/1.0 in requests and answers.
453  *
454  *    Revision 1.29  2001/09/24 21:09:24  jongfoster
455  *    Fixing 2 memory leaks that Guy spotted, where the paramater to
456  *    enlist() was not being free()d.
457  *
458  *    Revision 1.28  2001/09/22 16:32:28  jongfoster
459  *    Removing unused #includes.
460  *
461  *    Revision 1.27  2001/09/20 15:45:25  steudten
462  *
463  *    add casting from size_t to int for printf()
464  *    remove local variable shadow s2
465  *
466  *    Revision 1.26  2001/09/16 17:05:14  jongfoster
467  *    Removing unused #include showarg.h
468  *
469  *    Revision 1.25  2001/09/16 13:21:27  jongfoster
470  *    Changes to use new list functions.
471  *
472  *    Revision 1.24  2001/09/13 23:05:50  jongfoster
473  *    Changing the string paramater to the header parsers a "const".
474  *
475  *    Revision 1.23  2001/09/12 18:08:19  steudten
476  *
477  *    In parse_http_request() header rewriting miss the host value, so
478  *    from http://www.mydomain.com the result was just " / " not
479  *    http://www.mydomain.com/ in case we forward.
480  *
481  *    Revision 1.22  2001/09/10 10:58:53  oes
482  *    Silenced compiler warnings
483  *
484  *    Revision 1.21  2001/07/31 14:46:00  oes
485  *     - Persistant connections now suppressed
486  *     - sed() no longer appends empty header to csp->headers
487  *
488  *    Revision 1.20  2001/07/30 22:08:36  jongfoster
489  *    Tidying up #defines:
490  *    - All feature #defines are now of the form FEATURE_xxx
491  *    - Permanently turned off WIN_GUI_EDIT
492  *    - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
493  *
494  *    Revision 1.19  2001/07/25 17:21:54  oes
495  *    client_uagent now saves copy of User-Agent: header value
496  *
497  *    Revision 1.18  2001/07/13 14:02:46  oes
498  *     - Included fix to repair broken HTTP requests that
499  *       don't contain a path, not even '/'.
500  *     - Removed all #ifdef PCRS
501  *     - content_type now always inspected and classified as
502  *       text, gif or other.
503  *     - formatting / comments
504  *
505  *    Revision 1.17  2001/06/29 21:45:41  oes
506  *    Indentation, CRLF->LF, Tab-> Space
507  *
508  *    Revision 1.16  2001/06/29 13:32:42  oes
509  *    - Fixed a comment
510  *    - Adapted free_http_request
511  *    - Removed logentry from cancelled commit
512  *
513  *    Revision 1.15  2001/06/03 19:12:38  oes
514  *    deleted const struct interceptors
515  *
516  *    Revision 1.14  2001/06/01 18:49:17  jongfoster
517  *    Replaced "list_share" with "list" - the tiny memory gain was not
518  *    worth the extra complexity.
519  *
520  *    Revision 1.13  2001/05/31 21:30:33  jongfoster
521  *    Removed list code - it's now in list.[ch]
522  *    Renamed "permission" to "action", and changed many features
523  *    to use the actions file rather than the global config.
524  *
525  *    Revision 1.12  2001/05/31 17:33:13  oes
526  *
527  *    CRLF -> LF
528  *
529  *    Revision 1.11  2001/05/29 20:11:19  joergs
530  *    '/ * inside comment' warning removed.
531  *
532  *    Revision 1.10  2001/05/29 09:50:24  jongfoster
533  *    Unified blocklist/imagelist/permissionslist.
534  *    File format is still under discussion, but the internal changes
535  *    are (mostly) done.
536  *
537  *    Also modified interceptor behaviour:
538  *    - We now intercept all URLs beginning with one of the following
539  *      prefixes (and *only* these prefixes):
540  *        * http://i.j.b/
541  *        * http://ijbswa.sf.net/config/
542  *        * http://ijbswa.sourceforge.net/config/
543  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
544  *    - Internal changes so that intercepted and fast redirect pages
545  *      are not replaced with an image.
546  *    - Interceptors now have the option to send a binary page direct
547  *      to the client. (i.e. ijb-send-banner uses this)
548  *    - Implemented show-url-info interceptor.  (Which is why I needed
549  *      the above interceptors changes - a typical URL is
550  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
551  *      The previous mechanism would not have intercepted that, and
552  *      if it had been intercepted then it then it would have replaced
553  *      it with an image.)
554  *
555  *    Revision 1.9  2001/05/28 17:26:33  jongfoster
556  *    Fixing segfault if last header was crunched.
557  *    Fixing Windows build (snprintf() is _snprintf() under Win32, but we
558  *    can use the cross-platform sprintf() instead.)
559  *
560  *    Revision 1.8  2001/05/27 22:17:04  oes
561  *
562  *    - re_process_buffer no longer writes the modified buffer
563  *      to the client, which was very ugly. It now returns the
564  *      buffer, which it is then written by chat.
565  *
566  *    - content_length now adjusts the Content-Length: header
567  *      for modified documents rather than crunch()ing it.
568  *      (Length info in csp->content_length, which is 0 for
569  *      unmodified documents)
570  *
571  *    - For this to work, sed() is called twice when filtering.
572  *
573  *    Revision 1.7  2001/05/27 13:19:06  oes
574  *    Patched Joergs solution for the content-length in.
575  *
576  *    Revision 1.6  2001/05/26 13:39:32  jongfoster
577  *    Only crunches Content-Length header if applying RE filtering.
578  *    Without this fix, Microsoft Windows Update wouldn't work.
579  *
580  *    Revision 1.5  2001/05/26 00:28:36  jongfoster
581  *    Automatic reloading of config file.
582  *    Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
583  *    Most of the global variables have been moved to a new
584  *    struct configuration_spec, accessed through csp->config->globalname
585  *    Most of the globals remaining are used by the Win32 GUI.
586  *
587  *    Revision 1.4  2001/05/22 18:46:04  oes
588  *
589  *    - Enabled filtering banners by size rather than URL
590  *      by adding patterns that replace all standard banner
591  *      sizes with the "Junkbuster" gif to the re_filterfile
592  *
593  *    - Enabled filtering WebBugs by providing a pattern
594  *      which kills all 1x1 images
595  *
596  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
597  *      which is selected by the (nonstandard and therefore
598  *      capital) letter 'U' in the option string.
599  *      It causes the quantifiers to be ungreedy by default.
600  *      Appending a ? turns back to greedy (!).
601  *
602  *    - Added a new interceptor ijb-send-banner, which
603  *      sends back the "Junkbuster" gif. Without imagelist or
604  *      MSIE detection support, or if tinygif = 1, or the
605  *      URL isn't recognized as an imageurl, a lame HTML
606  *      explanation is sent instead.
607  *
608  *    - Added new feature, which permits blocking remote
609  *      script redirects and firing back a local redirect
610  *      to the browser.
611  *      The feature is conditionally compiled, i.e. it
612  *      can be disabled with --disable-fast-redirects,
613  *      plus it must be activated by a "fast-redirects"
614  *      line in the config file, has its own log level
615  *      and of course wants to be displayed by show-proxy-args
616  *      Note: Boy, all the #ifdefs in 1001 locations and
617  *      all the fumbling with configure.in and acconfig.h
618  *      were *way* more work than the feature itself :-(
619  *
620  *    - Because a generic redirect template was needed for
621  *      this, tinygif = 3 now uses the same.
622  *
623  *    - Moved GIFs, and other static HTTP response templates
624  *      to project.h
625  *
626  *    - Some minor fixes
627  *
628  *    - Removed some >400 CRs again (Jon, you really worked
629  *      a lot! ;-)
630  *
631  *    Revision 1.3  2001/05/20 01:21:20  jongfoster
632  *    Version 2.9.4 checkin.
633  *    - Merged popupfile and cookiefile, and added control over PCRS
634  *      filtering, in new "permissionsfile".
635  *    - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
636  *      file error you now get a message box (in the Win32 GUI) rather
637  *      than the program exiting with no explanation.
638  *    - Made killpopup use the PCRS MIME-type checking and HTTP-header
639  *      skipping.
640  *    - Removed tabs from "config"
641  *    - Moved duplicated url parsing code in "loaders.c" to a new funcition.
642  *    - Bumped up version number.
643  *
644  *    Revision 1.2  2001/05/17 23:02:36  oes
645  *     - Made referrer option accept 'L' as a substitute for 'ยง'
646  *
647  *    Revision 1.1.1.1  2001/05/15 13:59:01  oes
648  *    Initial import of version 2.9.3 source tree
649  *
650  *
651  *********************************************************************/
652 \f
653
654 #include "config.h"
655
656 #ifndef _WIN32
657 #include <stdio.h>
658 #include <sys/types.h>
659 #endif
660
661 #include <stdlib.h>
662 #include <ctype.h>
663 #include <assert.h>
664 #include <string.h>
665
666 #ifdef __GLIBC__
667 /*
668  * Convince GNU's libc to provide a strptime prototype.
669  */
670 #define __USE_XOPEN
671 #endif /*__GLIBC__ */
672 #include <time.h>
673
674 #ifdef FEATURE_ZLIB
675 #include <zlib.h>
676 #endif
677
678 #if !defined(_WIN32) && !defined(__OS2__)
679 #include <unistd.h>
680 #endif
681
682 #include "project.h"
683
684 #ifdef FEATURE_PTHREAD
685 #include "jcc.h"
686 /* jcc.h is for mutex semapores only */
687 #endif /* def FEATURE_PTHREAD */
688 #include "list.h"
689 #include "parsers.h"
690 #include "encode.h"
691 #include "ssplit.h"
692 #include "errlog.h"
693 #include "jbsockets.h"
694 #include "miscutil.h"
695 #include "list.h"
696 #include "actions.h"
697
698 #ifndef HAVE_STRPTIME
699 #include "strptime.h"
700 #endif
701
702 const char parsers_h_rcs[] = PARSERS_H_VERSION;
703
704 /* Fix a problem with Solaris.  There should be no effect on other
705  * platforms.
706  * Solaris's isspace() is a macro which uses its argument directly
707  * as an array index.  Therefore we need to make sure that high-bit
708  * characters generate +ve values, and ideally we also want to make
709  * the argument match the declared parameter type of "int".
710  *
711  * Why did they write a character function that can't take a simple
712  * "char" argument?  Doh!
713  */
714 #define ijb_isupper(__X) isupper((int)(unsigned char)(__X))
715 #define ijb_tolower(__X) tolower((int)(unsigned char)(__X))
716
717 jb_err header_tagger(struct client_state *csp, char *header);
718 jb_err scan_headers(struct client_state *csp);
719
720 const struct parsers client_patterns[] = {
721    { "referer:",                  8,   client_referrer },
722    { "user-agent:",              11,   client_uagent },
723    { "ua-",                       3,   client_ua },
724    { "from:",                     5,   client_from },
725    { "cookie:",                   7,   client_send_cookie },
726    { "x-forwarded-for:",         16,   client_x_forwarded },
727    { "Accept-Encoding:",         16,   client_accept_encoding },
728    { "TE:",                       3,   client_te },
729    { "Host:",                     5,   client_host },
730    { "if-modified-since:",       18,   client_if_modified_since },
731    { "Keep-Alive:",              11,   crumble },
732    { "connection:",              11,   connection },
733    { "proxy-connection:",        17,   crumble },
734    { "max-forwards:",            13,   client_max_forwards },
735    { "Accept-Language:",         16,   client_accept_language },
736    { "if-none-match:",           14,   client_if_none_match },
737    { "X-Filter:",                 9,   client_x_filter },
738    { "*",                         0,   crunch_client_header },
739    { "*",                         0,   filter_header },
740    { NULL,                        0,   NULL }
741 };
742
743 const struct parsers server_patterns[] = {
744    { "HTTP",                      4, server_http },
745    { "set-cookie:",              11, server_set_cookie },
746    { "connection:",              11, connection },
747    { "Content-Type:",            13, server_content_type },
748    { "Content-MD5:",             12, server_content_md5 },
749    { "Content-Encoding:",        17, server_content_encoding },
750    { "Transfer-Encoding:",       18, server_transfer_coding },
751    { "Keep-Alive:",              11, crumble },
752    { "content-disposition:",     20, server_content_disposition },
753    { "Last-Modified:",           14, server_last_modified },
754    { "*",                         0, crunch_server_header },
755    { "*",                         0, filter_header },
756    { NULL, 0, NULL }
757 };
758
759 const struct parsers server_patterns_light[] = {
760    { "Content-Length:",          15, server_content_length },
761    { "Transfer-Encoding:",       18, server_transfer_coding },
762 #ifdef FEATURE_ZLIB
763    { "Content-Encoding:",        17, server_content_encoding },
764 #endif /* def FEATURE_ZLIB */
765    { NULL, 0, NULL }
766 };
767
768 const add_header_func_ptr add_client_headers[] = {
769    client_host_adder,
770    client_cookie_adder,
771    client_x_forwarded_adder,
772    client_xtra_adder,
773    /* Temporarily disabled:    client_accept_encoding_adder, */
774    connection_close_adder,
775    NULL
776 };
777
778
779 const add_header_func_ptr add_server_headers[] = {
780    connection_close_adder,
781    NULL
782 };
783
784 /*********************************************************************
785  *
786  * Function    :  flush_socket
787  *
788  * Description :  Write any pending "buffered" content.
789  *
790  * Parameters  :
791  *          1  :  fd = file descriptor of the socket to read
792  *          2  :  csp = Current client state (buffers, headers, etc...)
793  *
794  * Returns     :  On success, the number of bytes written are returned (zero
795  *                indicates nothing was written).  On error, -1 is returned,
796  *                and errno is set appropriately.  If count is zero and the
797  *                file descriptor refers to a regular file, 0 will be
798  *                returned without causing any other effect.  For a special
799  *                file, the results are not portable.
800  *
801  *********************************************************************/
802 int flush_socket(jb_socket fd, struct client_state *csp)
803 {
804    struct iob *iob = csp->iob;
805    int len = iob->eod - iob->cur;
806
807    if (len <= 0)
808    {
809       return(0);
810    }
811
812    if (write_socket(fd, iob->cur, (size_t)len))
813    {
814       return(-1);
815    }
816    iob->eod = iob->cur = iob->buf;
817    return(len);
818
819 }
820
821
822 /*********************************************************************
823  *
824  * Function    :  add_to_iob
825  *
826  * Description :  Add content to the buffered page, expanding the
827  *                buffer if necessary.
828  *
829  * Parameters  :
830  *          1  :  csp = Current client state (buffers, headers, etc...)
831  *          2  :  buf = holds the content to be added to the page
832  *          3  :  n = number of bytes to be added
833  *
834  * Returns     :  JB_ERR_OK on success, JB_ERR_MEMORY if out-of-memory
835  *                or buffer limit reached.
836  *
837  *********************************************************************/
838 jb_err add_to_iob(struct client_state *csp, char *buf, int n)
839 {
840    struct iob *iob = csp->iob;
841    size_t used, offset, need, want;
842    char *p;
843
844    if (n <= 0) return JB_ERR_OK;
845
846    used   = (size_t)(iob->eod - iob->buf);
847    offset = (size_t)(iob->cur - iob->buf);
848    need   = used + (size_t)n + 1;
849
850    /*
851     * If the buffer can't hold the new data, extend it first.
852     * Use the next power of two if possible, else use the actual need.
853     */
854    if (need > csp->config->buffer_limit)
855    {
856       log_error(LOG_LEVEL_ERROR, "Buffer limit reached while extending the buffer (iob)");
857       return JB_ERR_MEMORY;
858    }
859
860    if (need > iob->size)
861    {
862       for (want = csp->iob->size ? csp->iob->size : 512; want <= need;) want *= 2;
863       
864       if (want <= csp->config->buffer_limit && NULL != (p = (char *)realloc(iob->buf, want)))
865       {
866          iob->size = want;
867       }
868       else if (NULL != (p = (char *)realloc(iob->buf, need)))
869       {
870          iob->size = need;
871       }
872       else
873       {
874          log_error(LOG_LEVEL_ERROR, "Extending the buffer (iob) failed: %E");
875          return JB_ERR_MEMORY;
876       }
877
878       /* Update the iob pointers */
879       iob->cur = p + offset;
880       iob->eod = p + used;
881       iob->buf = p;
882    }
883
884    /* copy the new data into the iob buffer */
885    memcpy(iob->eod, buf, (size_t)n);
886
887    /* point to the end of the data */
888    iob->eod += n;
889
890    /* null terminate == cheap insurance */
891    *iob->eod = '\0';
892
893    return JB_ERR_OK;
894
895 }
896
897
898 #ifdef FEATURE_ZLIB
899 /*********************************************************************
900  *
901  * Function    :  decompress_iob
902  *
903  * Description :  Decompress buffered page, expanding the
904  *                buffer as necessary.  csp->iob->cur
905  *                should point to the the beginning of the
906  *                compressed data block.
907  *
908  * Parameters  :
909  *          1  :  csp = Current client state (buffers, headers, etc...)
910  *
911  * Returns     :  JB_ERR_OK on success,
912  *                JB_ERR_MEMORY if out-of-memory limit reached, and
913  *                JB_ERR_COMPRESS if error decompressing buffer.
914  *
915  *********************************************************************/
916 jb_err decompress_iob(struct client_state *csp)
917 {
918    char  *buf;       /* new, uncompressed buffer */
919    char  *cur;       /* Current iob position (to keep the original 
920                       * iob->cur unmodified if we return early) */
921    size_t bufsize;   /* allocated size of the new buffer */
922    size_t old_size;  /* Content size before decompression */
923    size_t skip_size; /* Number of bytes at the beginning of the iob
924                         that we should NOT decompress. */
925    int status;       /* return status of the inflate() call */
926    z_stream zstr;    /* used by calls to zlib */
927
928    assert(csp->iob->cur - csp->iob->buf > 0);
929    assert(csp->iob->eod - csp->iob->cur > 0);
930
931    bufsize = csp->iob->size;
932    skip_size = (size_t)(csp->iob->cur - csp->iob->buf);
933    old_size = (size_t)(csp->iob->eod - csp->iob->cur);
934
935    cur = csp->iob->cur;
936
937    if (bufsize < 10)
938    {
939       /*
940        * This is to protect the parsing of gzipped data,
941        * but it should(?) be valid for deflated data also.
942        */
943       log_error (LOG_LEVEL_ERROR, "Buffer too small decompressing iob");
944       return JB_ERR_COMPRESS;
945    }
946
947    if (csp->content_type & CT_GZIP)
948    {
949       /*
950        * Our task is slightly complicated by the facts that data
951        * compressed by gzip does not include a zlib header, and
952        * that there is no easily accessible interface in zlib to
953        * handle a gzip header. We strip off the gzip header by
954        * hand, and later inform zlib not to expect a header.
955        */
956
957       /*
958        * Strip off the gzip header. Please see RFC 1952 for more
959        * explanation of the appropriate fields.
960        */
961       if ((*cur++ != (char)0x1f)
962        || (*cur++ != (char)0x8b)
963        || (*cur++ != Z_DEFLATED))
964       {
965          log_error (LOG_LEVEL_ERROR, "Invalid gzip header when decompressing");
966          return JB_ERR_COMPRESS;
967       }
968       else
969       {
970          int flags = *cur++;
971          /*
972           * XXX: These magic numbers should be replaced
973           * with macros to give a better idea what they do.
974           */
975          if (flags & 0xe0)
976          {
977             /* The gzip header has reserved bits set; bail out. */
978             log_error (LOG_LEVEL_ERROR, "Invalid gzip header flags when decompressing");
979             return JB_ERR_COMPRESS;
980          }
981          cur += 6;
982
983          /* Skip extra fields if necessary. */
984          if (flags & 0x04)
985          {
986             /*
987              * Skip a given number of bytes, specified
988              * as a 16-bit little-endian value.
989              */
990             /*
991              * XXX: This code used to be:
992              * 
993              * csp->iob->cur += *csp->iob->cur++ + (*csp->iob->cur++ << 8);
994              *
995              * which I had to change into:
996              *
997              * cur += *cur++ + (*cur++ << 8);
998              *
999              * at which point gcc43 finally noticed that the value
1000              * of cur is undefined (it depends on which of the
1001              * summands is evaluated first).
1002              *
1003              * I haven't come across a site where this
1004              * code is actually executed yet, but I hope
1005              * it works anyway.
1006              */
1007             int skip_bytes;
1008             skip_bytes = *cur++;
1009             skip_bytes = *cur++ << 8;
1010
1011             assert(skip_bytes == *csp->iob->cur - 2 + ((*csp->iob->cur - 1) << 8));
1012
1013             /*
1014              * The number of bytes to skip should be positive
1015              * and we'd like to stay in the buffer.
1016              */
1017             if((skip_bytes < 0) || (skip_bytes >= (csp->iob->eod - cur)))
1018             {
1019                log_error (LOG_LEVEL_ERROR,
1020                   "Unreasonable amount of bytes to skip (%d). Stopping decompression",
1021                   skip_bytes);
1022                return JB_ERR_COMPRESS;
1023             }
1024             log_error (LOG_LEVEL_INFO,
1025                "Skipping %d bytes for gzip compression. Does this sound right?",
1026                skip_bytes);
1027             cur += skip_bytes;
1028          }
1029
1030          /* Skip the filename if necessary. */
1031          if (flags & 0x08)
1032          {
1033             /* A null-terminated string is supposed to follow. */
1034             while (*cur++ && (cur < csp->iob->eod));
1035
1036          }
1037
1038          /* Skip the comment if necessary. */
1039          if (flags & 0x10)
1040          {
1041             /* A null-terminated string is supposed to follow. */
1042             while (*cur++ && (cur < csp->iob->eod));
1043          }
1044
1045          /* Skip the CRC if necessary. */
1046          if (flags & 0x02)
1047          {
1048             cur += 2;
1049          }
1050
1051          if (cur >= csp->iob->eod)
1052          {
1053             /*
1054              * If the current position pointer reached or passed
1055              * the buffer end, we were obviously tricked to skip
1056              * too much.
1057              */
1058             log_error (LOG_LEVEL_ERROR,
1059                "Malformed gzip header detected. Aborting decompression.");
1060             return JB_ERR_COMPRESS;
1061          }
1062       }
1063    }
1064    else if (csp->content_type & CT_DEFLATE)
1065    {
1066       /*
1067        * XXX: The debug level should be lowered
1068        * before the next stable release.
1069        */
1070       log_error (LOG_LEVEL_INFO, "Decompressing deflated iob: %d", *cur);
1071       /*
1072        * In theory (that is, according to RFC 1950), deflate-compressed
1073        * data should begin with a two-byte zlib header and have an
1074        * adler32 checksum at the end. It seems that in practice only
1075        * the raw compressed data is sent. Note that this means that
1076        * we are not RFC 1950-compliant here, but the advantage is that
1077        * this actually works. :)
1078        *
1079        * We add a dummy null byte to tell zlib where the data ends,
1080        * and later inform it not to expect a header.
1081        *
1082        * Fortunately, add_to_iob() has thoughtfully null-terminated
1083        * the buffer; we can just increment the end pointer to include
1084        * the dummy byte.  
1085        */
1086       csp->iob->eod++;
1087    }
1088    else
1089    {
1090       log_error (LOG_LEVEL_ERROR,
1091          "Unable to determine compression format for decompression");
1092       return JB_ERR_COMPRESS;
1093    }
1094
1095    /* Set up the fields required by zlib. */
1096    zstr.next_in  = (Bytef *)cur;
1097    zstr.avail_in = (unsigned int)(csp->iob->eod - cur);
1098    zstr.zalloc   = Z_NULL;
1099    zstr.zfree    = Z_NULL;
1100    zstr.opaque   = Z_NULL;
1101
1102    /*
1103     * Passing -MAX_WBITS to inflateInit2 tells the library
1104     * that there is no zlib header.
1105     */
1106    if (inflateInit2 (&zstr, -MAX_WBITS) != Z_OK)
1107    {
1108       log_error (LOG_LEVEL_ERROR, "Error initializing decompression");
1109       return JB_ERR_COMPRESS;
1110    }
1111
1112    /*
1113     * Next, we allocate new storage for the inflated data.
1114     * We don't modify the existing iob yet, so in case there
1115     * is error in decompression we can recover gracefully.
1116     */
1117    buf = zalloc (bufsize);
1118    if (NULL == buf)
1119    {
1120       log_error (LOG_LEVEL_ERROR, "Out of memory decompressing iob");
1121       return JB_ERR_MEMORY;
1122    }
1123
1124    assert(bufsize >= skip_size);
1125    memcpy(buf, csp->iob->buf, skip_size);
1126    zstr.avail_out = bufsize - skip_size;
1127    zstr.next_out  = (Bytef *)buf + skip_size;
1128
1129    /* Try to decompress the whole stream in one shot. */
1130    while (Z_BUF_ERROR == (status = inflate(&zstr, Z_FINISH)))
1131    {
1132       /* We need to allocate more memory for the output buffer. */
1133
1134       char *tmpbuf;                /* used for realloc'ing the buffer */
1135       size_t oldbufsize = bufsize; /* keep track of the old bufsize */
1136
1137       /*
1138        * If zlib wants more data then there's a problem, because
1139        * the complete compressed file should have been buffered.
1140        */
1141       if (0 == zstr.avail_in)
1142       {
1143          log_error(LOG_LEVEL_ERROR, "Unexpected end of compressed iob");
1144          return JB_ERR_COMPRESS;
1145       }
1146
1147       /*
1148        * If we tried the limit and still didn't have enough
1149        * memory, just give up.
1150        */
1151       if (bufsize == csp->config->buffer_limit)
1152       {
1153          log_error(LOG_LEVEL_ERROR, "Buffer limit reached while decompressing iob");
1154          return JB_ERR_MEMORY;
1155       }
1156
1157       /* Try doubling the buffer size each time. */
1158       bufsize *= 2;
1159
1160       /* Don't exceed the buffer limit. */
1161       if (bufsize > csp->config->buffer_limit)
1162       {
1163          bufsize = csp->config->buffer_limit;
1164       }
1165     
1166       /* Try to allocate the new buffer. */
1167       tmpbuf = realloc(buf, bufsize);
1168       if (NULL == tmpbuf)
1169       {
1170          log_error(LOG_LEVEL_ERROR, "Out of memory decompressing iob");
1171          freez(buf);
1172          return JB_ERR_MEMORY;
1173       }
1174       else
1175       {
1176          char *oldnext_out = (char *)zstr.next_out;
1177
1178          /*
1179           * Update the fields for inflate() to use the new
1180           * buffer, which may be in a location different from
1181           * the old one.
1182           */
1183          zstr.avail_out += bufsize - oldbufsize;
1184          zstr.next_out   = (Bytef *)tmpbuf + bufsize - zstr.avail_out;
1185
1186          /*
1187           * Compare with an uglier method of calculating these values
1188           * that doesn't require the extra oldbufsize variable.
1189           */
1190          assert(zstr.avail_out == tmpbuf + bufsize - (char *)zstr.next_out);
1191          assert((char *)zstr.next_out == tmpbuf + ((char *)oldnext_out - buf));
1192          assert(zstr.avail_out > 0);
1193
1194          buf = tmpbuf;
1195       }
1196    }
1197
1198    if (Z_STREAM_ERROR == inflateEnd(&zstr))
1199    {
1200       log_error(LOG_LEVEL_ERROR,
1201          "Inconsistent stream state after decompression: %s", zstr.msg);
1202       /*
1203        * XXX: Intentionally no return.
1204        *
1205        * According to zlib.h, Z_STREAM_ERROR is returned
1206        * "if the stream state was inconsistent".
1207        *
1208        * I assume in this case inflate()'s status
1209        * would also be something different than Z_STREAM_END
1210        * so this check should be redundant, but lets see.
1211        */
1212    }
1213
1214    if (status != Z_STREAM_END)
1215    {
1216       /* We failed to decompress the stream. */
1217       log_error(LOG_LEVEL_ERROR,
1218          "Error in decompressing to the buffer (iob): %s", zstr.msg);
1219       return JB_ERR_COMPRESS;
1220    }
1221
1222    /*
1223     * Finally, we can actually update the iob, since the
1224     * decompression was successful. First, free the old
1225     * buffer.
1226     */
1227    freez(csp->iob->buf);
1228
1229    /* Now, update the iob to use the new buffer. */
1230    csp->iob->buf  = buf;
1231    csp->iob->cur  = csp->iob->buf + skip_size;
1232    csp->iob->eod  = (char *)zstr.next_out;
1233    csp->iob->size = bufsize;
1234   
1235    /*
1236     * Make sure the new uncompressed iob obeys some minimal
1237     * consistency conditions.
1238     */
1239    if ((csp->iob->buf <  csp->iob->cur)
1240     && (csp->iob->cur <= csp->iob->eod)
1241     && (csp->iob->eod <= csp->iob->buf + csp->iob->size))
1242    {
1243       const size_t new_size = (size_t)(csp->iob->eod - csp->iob->cur);
1244       if (new_size > 0)
1245       {
1246          log_error(LOG_LEVEL_RE_FILTER,
1247             "Decompression successful. Old size: %d, new size: %d.",
1248             old_size, new_size);
1249       }
1250       else
1251       {
1252          /* zlib thinks this is OK, so lets do the same. */
1253          log_error(LOG_LEVEL_INFO, "Decompression didn't result in any content.");
1254       }
1255    }
1256    else
1257    {
1258       /* It seems that zlib did something weird. */
1259       log_error(LOG_LEVEL_ERROR,
1260          "Unexpected error decompressing the buffer (iob): %d==%d, %d>%d, %d<%d",
1261          csp->iob->cur, csp->iob->buf + skip_size, csp->iob->eod, csp->iob->buf,
1262          csp->iob->eod, csp->iob->buf + csp->iob->size);
1263       return JB_ERR_COMPRESS;
1264    }
1265
1266    return JB_ERR_OK;
1267
1268 }
1269 #endif /* defined(FEATURE_ZLIB) */
1270
1271
1272 /*********************************************************************
1273  *
1274  * Function    :  get_header
1275  *
1276  * Description :  This (odd) routine will parse the csp->iob
1277  *
1278  * Parameters  :
1279  *          1  :  csp = Current client state (buffers, headers, etc...)
1280  *
1281  * Returns     :  Any one of the following:
1282  *
1283  * 1) a pointer to a dynamically allocated string that contains a header line
1284  * 2) NULL  indicating that the end of the header was reached
1285  * 3) ""    indicating that the end of the iob was reached before finding
1286  *          a complete header line.
1287  *
1288  *********************************************************************/
1289 char *get_header(struct client_state *csp)
1290 {
1291    struct iob *iob;
1292    char *p, *q, *ret;
1293    iob = csp->iob;
1294
1295    if ((iob->cur == NULL)
1296       || ((p = strchr(iob->cur, '\n')) == NULL))
1297    {
1298       return(""); /* couldn't find a complete header */
1299    }
1300
1301    *p = '\0';
1302
1303    ret = strdup(iob->cur);
1304    if (ret == NULL)
1305    {
1306       /* FIXME No way to handle error properly */
1307       log_error(LOG_LEVEL_FATAL, "Out of memory in get_header()");
1308    }
1309
1310    iob->cur = p+1;
1311
1312    if ((q = strchr(ret, '\r')) != NULL) *q = '\0';
1313
1314    /* is this a blank line (i.e. the end of the header) ? */
1315    if (*ret == '\0')
1316    {
1317       freez(ret);
1318       return(NULL);
1319    }
1320
1321    return(ret);
1322
1323 }
1324
1325
1326 /*********************************************************************
1327  *
1328  * Function    :  get_header_value
1329  *
1330  * Description :  Get the value of a given header from a chained list
1331  *                of header lines or return NULL if no such header is
1332  *                present in the list.
1333  *
1334  * Parameters  :
1335  *          1  :  header_list = pointer to list
1336  *          2  :  header_name = string with name of header to look for.
1337  *                              Trailing colon required, capitalization
1338  *                              doesn't matter.
1339  *
1340  * Returns     :  NULL if not found, else value of header
1341  *
1342  *********************************************************************/
1343 char *get_header_value(const struct list *header_list, const char *header_name)
1344 {
1345    struct list_entry *cur_entry;
1346    char *ret = NULL;
1347    size_t length = 0;
1348
1349    assert(header_list);
1350    assert(header_name);
1351    length = strlen(header_name);
1352
1353    for (cur_entry = header_list->first; cur_entry ; cur_entry = cur_entry->next)
1354    {
1355       if (cur_entry->str)
1356       {
1357          if (!strncmpic(cur_entry->str, header_name, length))
1358          {
1359             /*
1360              * Found: return pointer to start of value
1361              */
1362             ret = (char *) (cur_entry->str + length);
1363             while (*ret && ijb_isspace(*ret)) ret++;
1364             return(ret);
1365          }
1366       }
1367    }
1368
1369    /* 
1370     * Not found
1371     */
1372    return NULL;
1373
1374 }
1375
1376
1377 /*********************************************************************
1378  *
1379  * Function    :  scan_headers
1380  *
1381  * Description :  Scans headers, applies tags and updates action bits. 
1382  *
1383  * Parameters  :
1384  *          1  :  csp = Current client state (buffers, headers, etc...)
1385  *
1386  * Returns     :  JB_ERR_OK
1387  *
1388  *********************************************************************/
1389 jb_err scan_headers(struct client_state *csp)
1390 {
1391    struct list_entry *h; /* Header */
1392    jb_err err = JB_ERR_OK;
1393
1394    log_error(LOG_LEVEL_HEADER, "scanning headers for: %s", csp->http->url);
1395
1396    for (h = csp->headers->first; (err == JB_ERR_OK) && (h != NULL) ; h = h->next)
1397    {
1398       /* Header crunch()ed in previous run? -> ignore */
1399       if (h->str == NULL) continue;
1400       log_error(LOG_LEVEL_HEADER, "scan: %s", h->str);
1401       err = header_tagger(csp, h->str);
1402    }
1403
1404    update_action_bits(csp);
1405
1406    return err;
1407 }
1408
1409
1410 /*********************************************************************
1411  *
1412  * Function    :  sed
1413  *
1414  * Description :  add, delete or modify lines in the HTTP header streams.
1415  *                On entry, it receives a linked list of headers space
1416  *                that was allocated dynamically (both the list nodes
1417  *                and the header contents).
1418  *
1419  *                As a side effect it frees the space used by the original
1420  *                header lines.
1421  *
1422  * Parameters  :
1423  *          1  :  pats = list of patterns to match against headers
1424  *          2  :  more_headers = list of functions to add more
1425  *                headers (client or server)
1426  *          3  :  csp = Current client state (buffers, headers, etc...)
1427  *
1428  * Returns     :  Single pointer to a fully formed header, or NULL
1429  *                on out-of-memory error.
1430  *
1431  *********************************************************************/
1432 char *sed(const struct parsers pats[],
1433           const add_header_func_ptr more_headers[],
1434           struct client_state *csp)
1435 {
1436    struct list_entry *p;
1437    const struct parsers *v;
1438    const add_header_func_ptr *f;
1439    jb_err err = JB_ERR_OK;
1440    int first_run;
1441
1442    /*
1443     * If filtering is enabled, sed is run twice,
1444     * but most of the work needs to be done only once.
1445     */
1446    first_run = (more_headers != NULL ) ? 1 : 0;
1447
1448    if (first_run) /* Parse and print */
1449    {
1450       scan_headers(csp);
1451
1452       for (v = pats; (err == JB_ERR_OK) && (v->str != NULL) ; v++)
1453       {
1454          for (p = csp->headers->first; (err == JB_ERR_OK) && (p != NULL) ; p = p->next)
1455          {
1456             /* Header crunch()ed in previous run? -> ignore */
1457             if (p->str == NULL) continue;
1458
1459             /* Does the current parser handle this header? */
1460             if ((strncmpic(p->str, v->str, v->len) == 0) || (v->len == CHECK_EVERY_HEADER_REMAINING))
1461             {
1462                err = v->parser(csp, (char **)&(p->str));
1463             }
1464          }
1465       }
1466       /* place any additional headers on the csp->headers list */
1467       for (f = more_headers; (err == JB_ERR_OK) && (*f) ; f++)
1468       {
1469          err = (*f)(csp);
1470       }
1471    }
1472    else /* Parse only */
1473    {
1474       /*
1475        * The second run is only needed if the body was modified
1476        * and the content-lenght has changed.
1477        */
1478       if (strncmpic(csp->http->cmd, "HEAD", 4))
1479       {
1480          /*XXX: Code duplication */
1481          for (v = pats; (err == JB_ERR_OK) && (v->str != NULL) ; v++)
1482          {
1483             for (p = csp->headers->first; (err == JB_ERR_OK) && (p != NULL) ; p = p->next)
1484             {
1485                /* Header crunch()ed in previous run? -> ignore */
1486                if (p->str == NULL) continue;
1487
1488                /* Does the current parser handle this header? */
1489                if (strncmpic(p->str, v->str, v->len) == 0)
1490                {
1491                   err = v->parser(csp, (char **)&(p->str));
1492                }
1493             }
1494          }
1495       }
1496    }
1497
1498    if (err != JB_ERR_OK)
1499    {
1500       return NULL;
1501    }
1502
1503    return list_to_text(csp->headers);
1504 }
1505
1506
1507
1508 /*********************************************************************
1509  *
1510  * Function    :  header_tagger
1511  *
1512  * Description :  Executes all text substitutions from applying
1513  *                tag actions and saves the result as tag.
1514  *
1515  *                XXX: Shares enough code with filter_header() and
1516  *                pcrs_filter_response() to warrant some helper functions.
1517  *
1518  * Parameters  :
1519  *          1  :  csp = Current client state (buffers, headers, etc...)
1520  *          2  :  header = Header that is used as tagger input
1521  *
1522  * Returns     :  JB_ERR_OK on success and always succeeds
1523  *
1524  *********************************************************************/
1525 jb_err header_tagger(struct client_state *csp, char *header)
1526 {
1527    int wanted_filter_type;
1528    int multi_action_index;
1529    int i;
1530    pcrs_job *job;
1531
1532    struct file_list *fl;
1533    struct re_filterfile_spec *b;
1534    struct list_entry *tag_name;
1535
1536    int found_filters = 0;
1537    const size_t header_length = strlen(header);
1538
1539    if (csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
1540    {
1541       wanted_filter_type = FT_SERVER_HEADER_TAGGER;
1542       multi_action_index = ACTION_MULTI_SERVER_HEADER_TAGGER;
1543    }
1544    else
1545    {
1546       wanted_filter_type = FT_CLIENT_HEADER_TAGGER;
1547       multi_action_index = ACTION_MULTI_CLIENT_HEADER_TAGGER;
1548    }
1549
1550    /* Check if there are any filters */
1551    for (i = 0; i < MAX_AF_FILES; i++)
1552    {
1553       fl = csp->rlist[i];
1554       if (NULL != fl)
1555       {
1556          if (NULL != fl->f)
1557          {
1558            found_filters = 1;
1559            break;
1560          }
1561       }
1562    }
1563
1564    if (0 == found_filters)
1565    {
1566       log_error(LOG_LEVEL_ERROR, "Unable to get current state of regex tagging.");
1567       return(JB_ERR_OK);
1568    }
1569
1570    for (i = 0; i < MAX_AF_FILES; i++)
1571    {
1572       fl = csp->rlist[i];
1573       if ((NULL == fl) || (NULL == fl->f))
1574       {
1575          /*
1576           * Either there are no filter files
1577           * left, or this filter file just
1578           * contains no valid filters.
1579           *
1580           * Continue to be sure we don't miss
1581           * valid filter files that are chained
1582           * after empty or invalid ones.
1583           */
1584          continue;
1585       }
1586
1587       /* For all filters, */
1588       for (b = fl->f; b; b = b->next)
1589       {
1590          if (b->type != wanted_filter_type)
1591          {
1592             /* skip the ones we don't care about, */
1593             continue;
1594          }
1595          /* leaving only taggers that could apply, of which we use the ones, */
1596          for (tag_name = csp->action->multi[multi_action_index]->first;
1597               NULL != tag_name; tag_name = tag_name->next)
1598          {
1599             /* that do apply, and */
1600             if (strcmp(b->name, tag_name->str) == 0)
1601             {
1602                char *modified_tag = NULL;
1603                char *tag = header;
1604                size_t size = header_length;
1605
1606                if (NULL == b->joblist)
1607                {
1608                   log_error(LOG_LEVEL_RE_FILTER,
1609                      "Tagger %s has empty joblist. Nothing to do.", b->name);
1610                   continue;
1611                }
1612
1613                /* execute their pcrs_joblist on the header. */
1614                for (job = b->joblist; NULL != job; job = job->next)
1615                {
1616                   const int hits = pcrs_execute(job, tag, size, &modified_tag, &size);
1617
1618                   if (0 < hits)
1619                   {
1620                      /* Success, continue with the modified version. */
1621                      if (tag != header)
1622                      {
1623                         freez(tag);
1624                      }
1625                      tag = modified_tag;
1626                   }
1627                   else
1628                   {
1629                      /* Tagger doesn't match */
1630                      if (0 > hits)
1631                      {
1632                         /* Regex failure, log it but continue anyway. */
1633                         log_error(LOG_LEVEL_ERROR,
1634                            "Problems with tagger \'%s\' and header \'%s\': %s",
1635                            b->name, *header, pcrs_strerror(hits));
1636                      }
1637                      freez(modified_tag);
1638                   }
1639                }
1640
1641                /* If this tagger matched */
1642                if (tag != header)
1643                {
1644                   /* and there is something left to save, */
1645                   if (0 < size)
1646                   {
1647                      /* enlist a unique version of it as tag. */
1648                      if (JB_ERR_OK != enlist_unique(csp->tags, tag, 0))
1649                      {
1650                         log_error(LOG_LEVEL_ERROR,
1651                            "Insufficient memory to add tag \'%s\', "
1652                            "based on tagger \'%s\' and header \'%s\'",
1653                            tag, b->name, *header);
1654                      }
1655                      else
1656                      {
1657                         log_error(LOG_LEVEL_HEADER,
1658                            "Adding tag \'%s\' created by header tagger \'%s\'",
1659                            tag, b->name);
1660                      }
1661                   }
1662                   freez(tag);
1663                }
1664             } /* if the tagger applies */
1665          } /* for every tagger that could apply */
1666       } /* for all filters */
1667    } /* for all filter files */
1668
1669    return JB_ERR_OK;
1670 }
1671
1672 /* here begins the family of parser functions that reformat header lines */
1673
1674 /*********************************************************************
1675  *
1676  * Function    :  filter_header
1677  *
1678  * Description :  Executes all text substitutions from all applying
1679  *                +(server|client)-header-filter actions on the header.
1680  *                Most of the code was copied from pcrs_filter_response,
1681  *                including the rather short variable names
1682  *
1683  * Parameters  :
1684  *          1  :  csp = Current client state (buffers, headers, etc...)
1685  *          2  :  header = On input, pointer to header to modify.
1686  *                On output, pointer to the modified header, or NULL
1687  *                to remove the header.  This function frees the
1688  *                original string if necessary.
1689  *
1690  * Returns     :  JB_ERR_OK on success and always succeeds
1691  *
1692  *********************************************************************/
1693 jb_err filter_header(struct client_state *csp, char **header)
1694 {
1695    int hits=0;
1696    int matches;
1697    size_t size = strlen(*header);
1698
1699    char *newheader = NULL;
1700    pcrs_job *job;
1701
1702    struct file_list *fl;
1703    struct re_filterfile_spec *b;
1704    struct list_entry *filtername;
1705
1706    int i, found_filters = 0;
1707    int wanted_filter_type;
1708    int multi_action_index;
1709
1710    if (csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
1711    {
1712       wanted_filter_type = FT_SERVER_HEADER_FILTER;
1713       multi_action_index = ACTION_MULTI_SERVER_HEADER_FILTER;
1714    }
1715    else
1716    {
1717       wanted_filter_type = FT_CLIENT_HEADER_FILTER;
1718       multi_action_index = ACTION_MULTI_CLIENT_HEADER_FILTER;
1719    }
1720
1721    /*
1722     * Need to check the set of re_filterfiles...
1723     */
1724    for (i = 0; i < MAX_AF_FILES; i++)
1725    {
1726       fl = csp->rlist[i];
1727       if (NULL != fl)
1728       {
1729          if (NULL != fl->f)
1730          {
1731            found_filters = 1;
1732            break;
1733          }
1734       }
1735    }
1736
1737    if (0 == found_filters)
1738    {
1739       log_error(LOG_LEVEL_ERROR, "Unable to get current state of regexp filtering.");
1740       return(JB_ERR_OK);
1741    }
1742
1743    for (i = 0; i < MAX_AF_FILES; i++)
1744    {
1745       fl = csp->rlist[i];
1746       if ((NULL == fl) || (NULL == fl->f))
1747       {
1748          /*
1749           * Either there are no filter files
1750           * left, or this filter file just
1751           * contains no valid filters.
1752           *
1753           * Continue to be sure we don't miss
1754           * valid filter files that are chained
1755           * after empty or invalid ones.
1756           */
1757          continue;
1758       }
1759       /*
1760        * For all applying +filter actions, look if a filter by that
1761        * name exists and if yes, execute its pcrs_joblist on the
1762        * buffer.
1763        */
1764       for (b = fl->f; b; b = b->next)
1765       {
1766          if (b->type != wanted_filter_type)
1767          {
1768             /* Skip other filter types */
1769             continue;
1770          }
1771
1772          for (filtername = csp->action->multi[multi_action_index]->first;
1773               filtername ; filtername = filtername->next)
1774          {
1775             if (strcmp(b->name, filtername->str) == 0)
1776             {
1777                int current_hits = 0;
1778
1779                if ( NULL == b->joblist )
1780                {
1781                   log_error(LOG_LEVEL_RE_FILTER, "Filter %s has empty joblist. Nothing to do.", b->name);
1782                   continue;
1783                }
1784
1785                log_error(LOG_LEVEL_RE_FILTER, "filtering \'%s\' (size %d) with \'%s\' ...",
1786                          *header, size, b->name);
1787
1788                /* Apply all jobs from the joblist */
1789                for (job = b->joblist; NULL != job; job = job->next)
1790                {
1791                   matches = pcrs_execute(job, *header, size, &newheader, &size);
1792                   if ( 0 < matches )
1793                   {
1794                      current_hits += matches; 
1795                      log_error(LOG_LEVEL_HEADER, "Transforming \"%s\" to \"%s\"", *header, newheader);
1796                      freez(*header);
1797                      *header = newheader;
1798                   }
1799                   else if ( 0 == matches )
1800                   {
1801                      /* Filter doesn't change header */
1802                      freez(newheader);
1803                   }
1804                   else
1805                   {
1806                      /* RegEx failure */
1807                      log_error(LOG_LEVEL_ERROR, "Filtering \'%s\' with \'%s\' didn't work out: %s",
1808                         *header, b->name, pcrs_strerror(matches));
1809                      if( newheader != NULL)
1810                      {
1811                         log_error(LOG_LEVEL_ERROR, "Freeing what's left: %s", newheader);
1812                         freez(newheader);
1813                      }
1814                   }
1815                }
1816                log_error(LOG_LEVEL_RE_FILTER, "... produced %d hits (new size %d).", current_hits, size);
1817                hits += current_hits;
1818             }
1819          }
1820       }
1821    }
1822
1823    /*
1824     * Additionally checking for hits is important because if
1825     * the continue hack is triggered, server headers can
1826     * arrive empty to separate multiple heads from each other.
1827     */
1828    if ((0 == size) && hits)
1829    {
1830       log_error(LOG_LEVEL_HEADER, "Removing empty header %s", *header);
1831       freez(*header);
1832    }
1833
1834    return(JB_ERR_OK);
1835 }
1836
1837
1838 /*********************************************************************
1839  *
1840  * Function    :  connection
1841  *
1842  * Description :  Makes sure that the value of the Connection: header
1843  *                is "close" and signals connection_close_adder 
1844  *                to do nothing.
1845  *
1846  * Parameters  :
1847  *          1  :  csp = Current client state (buffers, headers, etc...)
1848  *          2  :  header = On input, pointer to header to modify.
1849  *                On output, pointer to the modified header, or NULL
1850  *                to remove the header.  This function frees the
1851  *                original string if necessary.
1852  *
1853  * Returns     :  JB_ERR_OK on success, or
1854  *                JB_ERR_MEMORY on out-of-memory error.
1855  *
1856  *********************************************************************/
1857 jb_err connection(struct client_state *csp, char **header)
1858 {
1859    char *old_header = *header;
1860
1861    /* Do we have a 'Connection: close' header? */
1862    if (strcmpic(*header, "Connection: close"))
1863    {
1864       /* No, create one */
1865       *header = strdup("Connection: close");
1866       if (header == NULL)
1867       { 
1868          return JB_ERR_MEMORY;
1869       }
1870       log_error(LOG_LEVEL_HEADER, "Replaced: \'%s\' with \'%s\'", old_header, *header);
1871       freez(old_header);
1872    }
1873
1874    /* Signal connection_close_adder() to return early. */
1875    if (csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
1876    {
1877       csp->flags |= CSP_FLAG_SERVER_CONNECTION_CLOSE_SET;
1878    }
1879    else
1880    {
1881       csp->flags |= CSP_FLAG_CLIENT_CONNECTION_CLOSE_SET;
1882    }
1883
1884    return JB_ERR_OK;
1885 }
1886
1887
1888 /*********************************************************************
1889  *
1890  * Function    :  crumble
1891  *
1892  * Description :  This is called if a header matches a pattern to "crunch"
1893  *
1894  * Parameters  :
1895  *          1  :  csp = Current client state (buffers, headers, etc...)
1896  *          2  :  header = On input, pointer to header to modify.
1897  *                On output, pointer to the modified header, or NULL
1898  *                to remove the header.  This function frees the
1899  *                original string if necessary.
1900  *
1901  * Returns     :  JB_ERR_OK on success, or
1902  *                JB_ERR_MEMORY on out-of-memory error.
1903  *
1904  *********************************************************************/
1905 jb_err crumble(struct client_state *csp, char **header)
1906 {
1907    log_error(LOG_LEVEL_HEADER, "crumble crunched: %s!", *header);
1908    freez(*header);
1909    return JB_ERR_OK;
1910 }
1911
1912 /*********************************************************************
1913  *
1914  * Function    :  crunch_server_header
1915  *
1916  * Description :  Crunch server header if it matches a string supplied by the
1917  *                user. Called from `sed'.
1918  *
1919  * Parameters  :
1920  *          1  :  csp = Current client state (buffers, headers, etc...)
1921  *          2  :  header = On input, pointer to header to modify.
1922  *                On output, pointer to the modified header, or NULL
1923  *                to remove the header.  This function frees the
1924  *                original string if necessary.
1925  *
1926  * Returns     :  JB_ERR_OK on success and always succeeds
1927  *
1928  *********************************************************************/
1929 jb_err crunch_server_header(struct client_state *csp, char **header)
1930 {
1931    const char *crunch_pattern;
1932
1933    /* Do we feel like crunching? */
1934    if ((csp->action->flags & ACTION_CRUNCH_SERVER_HEADER))
1935    {
1936       crunch_pattern = csp->action->string[ACTION_STRING_SERVER_HEADER];
1937
1938       /* Is the current header the lucky one? */
1939       if (strstr(*header, crunch_pattern))
1940       {
1941          log_error(LOG_LEVEL_HEADER, "Crunching server header: %s (contains: %s)", *header, crunch_pattern);  
1942          freez(*header);
1943       }
1944    }
1945
1946    return JB_ERR_OK;
1947 }
1948
1949
1950 /*********************************************************************
1951  *
1952  * Function    :  server_content_type
1953  *
1954  * Description :  Set the content-type for filterable types (text/.*,
1955  *                .*xml.*, javascript and image/gif) unless filtering has been
1956  *                forbidden (CT_TABOO) while parsing earlier headers.
1957  *                NOTE: Since text/plain is commonly used by web servers
1958  *                      for files whose correct type is unknown, we don't
1959  *                      set CT_TEXT for it.
1960  *
1961  * Parameters  :
1962  *          1  :  csp = Current client state (buffers, headers, etc...)
1963  *          2  :  header = On input, pointer to header to modify.
1964  *                On output, pointer to the modified header, or NULL
1965  *                to remove the header.  This function frees the
1966  *                original string if necessary.
1967  *
1968  * Returns     :  JB_ERR_OK on success, or
1969  *                JB_ERR_MEMORY on out-of-memory error.
1970  *
1971  *********************************************************************/
1972 jb_err server_content_type(struct client_state *csp, char **header)
1973 {
1974    /* Remove header if it isn't the first Content-Type header */
1975    if(csp->content_type && (csp->content_type != CT_TABOO))
1976    {
1977      /*
1978       * Another, slightly slower, way to see if
1979       * we already parsed another Content-Type header.
1980       */
1981       assert(NULL != get_header_value(csp->headers, "Content-Type:"));
1982
1983       log_error(LOG_LEVEL_ERROR,
1984          "Multiple Content-Type headers. Removing and ignoring: \'%s\'",
1985          *header);
1986       freez(*header);
1987
1988       return JB_ERR_OK;
1989    }
1990
1991    if (!(csp->content_type & CT_TABOO))
1992    {
1993       if ((strstr(*header, " text/") && !strstr(*header, "plain"))
1994         || strstr(*header, "xml")
1995         || strstr(*header, "application/x-javascript"))
1996       {
1997          csp->content_type |= CT_TEXT;
1998       }
1999       else if (strstr(*header, " image/gif"))
2000       {
2001          csp->content_type |= CT_GIF;
2002       }
2003       else if (strstr(*header, " image/jpeg"))
2004       {
2005          csp->content_type |= CT_JPEG;
2006       }
2007       else
2008       {
2009          csp->content_type = 0;
2010       }
2011    }
2012    /*
2013     * Are we enabling text mode by force?
2014     */
2015    if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
2016    {
2017       /*
2018        * Do we really have to?
2019        */
2020       if (csp->content_type & CT_TEXT)
2021       {
2022          log_error(LOG_LEVEL_HEADER, "Text mode is already enabled.");   
2023       }
2024       else
2025       {
2026          csp->content_type |= CT_TEXT;
2027          log_error(LOG_LEVEL_HEADER, "Text mode enabled by force. Take cover!");   
2028       }
2029    }
2030    /*
2031     * Are we messing with the content type?
2032     */ 
2033    if (csp->action->flags & ACTION_CONTENT_TYPE_OVERWRITE)
2034    { 
2035       /*
2036        * Make sure the user doesn't accidently
2037        * change the content type of binary documents. 
2038        */ 
2039       if (csp->content_type & CT_TEXT)
2040       { 
2041          freez(*header);
2042          *header = strdup("Content-Type: ");
2043          string_append(header, csp->action->string[ACTION_STRING_CONTENT_TYPE]);
2044
2045          if (header == NULL)
2046          { 
2047             log_error(LOG_LEVEL_HEADER, "Insufficient memory to replace Content-Type!");
2048             return JB_ERR_MEMORY;
2049          }
2050          log_error(LOG_LEVEL_HEADER, "Modified: %s!", *header);
2051       }
2052       else
2053       {
2054          log_error(LOG_LEVEL_HEADER, "%s not replaced. It doesn't look like text. "
2055             "Enable force-text-mode if you know what you're doing.", *header);   
2056       }
2057    }  
2058    return JB_ERR_OK;
2059 }
2060
2061
2062 /*********************************************************************
2063  *
2064  * Function    :  server_transfer_coding
2065  *
2066  * Description :  - Prohibit filtering (CT_TABOO) if transfer coding compresses
2067  *                - Raise the CSP_FLAG_CHUNKED flag if coding is "chunked"
2068  *                - Remove header if body was chunked but has been
2069  *                  de-chunked for filtering.
2070  *
2071  * Parameters  :
2072  *          1  :  csp = Current client state (buffers, headers, etc...)
2073  *          2  :  header = On input, pointer to header to modify.
2074  *                On output, pointer to the modified header, or NULL
2075  *                to remove the header.  This function frees the
2076  *                original string if necessary.
2077  *
2078  * Returns     :  JB_ERR_OK on success, or
2079  *                JB_ERR_MEMORY on out-of-memory error.
2080  *
2081  *********************************************************************/
2082 jb_err server_transfer_coding(struct client_state *csp, char **header)
2083 {
2084    /*
2085     * Turn off pcrs and gif filtering if body compressed
2086     */
2087    if (strstr(*header, "gzip") || strstr(*header, "compress") || strstr(*header, "deflate"))
2088    {
2089 #ifdef FEATURE_ZLIB
2090       /*
2091        * XXX: Added to test if we could use CT_GZIP and CT_DEFLATE here.
2092        */
2093       log_error(LOG_LEVEL_INFO, "Marking content type for %s as CT_TABOO because of %s.",
2094          csp->http->cmd, *header);
2095 #endif /* def FEATURE_ZLIB */
2096       csp->content_type = CT_TABOO;
2097    }
2098
2099    /*
2100     * Raise flag if body chunked
2101     */
2102    if (strstr(*header, "chunked"))
2103    {
2104       csp->flags |= CSP_FLAG_CHUNKED;
2105
2106       /*
2107        * If the body was modified, it has been de-chunked first
2108        * and the header must be removed.
2109        *
2110        * FIXME: If there is more than one transfer encoding,
2111        * only the "chunked" part should be removed here.
2112        */
2113       if (csp->flags & CSP_FLAG_MODIFIED)
2114       {
2115          log_error(LOG_LEVEL_HEADER, "Removing: %s", *header);
2116          freez(*header);
2117       }
2118    }
2119
2120    return JB_ERR_OK;
2121 }
2122
2123
2124 /*********************************************************************
2125  *
2126  * Function    :  server_content_encoding
2127  *
2128  * Description :  This function is run twice for each request,
2129  *                unless FEATURE_ZLIB and filtering are disabled.
2130  *
2131  *                The first run is used to check if the content
2132  *                is compressed, if FEATURE_ZLIB is disabled
2133  *                filtering is then disabled as well, if FEATURE_ZLIB
2134  *                is enabled the content is marked for decompression.
2135  *                
2136  *                The second run is used to remove the Content-Encoding
2137  *                header if the decompression was successful.
2138  *
2139  * Parameters  :
2140  *          1  :  csp = Current client state (buffers, headers, etc...)
2141  *          2  :  header = On input, pointer to header to modify.
2142  *                On output, pointer to the modified header, or NULL
2143  *                to remove the header.  This function frees the
2144  *                original string if necessary.
2145  *
2146  * Returns     :  JB_ERR_OK on success, or
2147  *                JB_ERR_MEMORY on out-of-memory error.
2148  *
2149  *********************************************************************/
2150 jb_err server_content_encoding(struct client_state *csp, char **header)
2151 {
2152 #ifdef FEATURE_ZLIB
2153    if ((csp->flags & CSP_FLAG_MODIFIED)
2154     && (csp->content_type & (CT_GZIP | CT_DEFLATE)))
2155    {
2156       /*
2157        * We successfully decompressed the content,
2158        * and have to clean the header now, so the
2159        * client no longer expects compressed data..
2160        *
2161        * XXX: There is a difference between cleaning
2162        * and removing it completely.
2163        */
2164       log_error(LOG_LEVEL_HEADER, "Crunching: %s", *header);
2165       freez(*header);
2166    }
2167    else if (strstr(*header, "gzip"))
2168    {
2169       /* Mark for gzip decompression */
2170       csp->content_type |= CT_GZIP;
2171    }
2172    else if (strstr(*header, "deflate"))
2173    {
2174       /* Mark for zlib decompression */
2175       csp->content_type |= CT_DEFLATE;
2176    }
2177    else if (strstr(*header, "compress"))
2178    {
2179       /*
2180        * We can't decompress this; therefore we can't filter
2181        * it either.
2182        */
2183       csp->content_type |= CT_TABOO;
2184    }
2185 #else /* !defined(FEATURE_ZLIB) */
2186    if (strstr(*header, "gzip") || strstr(*header, "compress") || strstr(*header, "deflate"))
2187    {
2188       /*
2189        * Body is compressed, turn off pcrs and gif filtering.
2190        */
2191       csp->content_type |= CT_TABOO;
2192
2193       /*
2194        * Log a warning if the user expects the content to be filtered.
2195        */
2196       if ((csp->rlist != NULL) &&
2197          (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER])))
2198       {
2199          log_error(LOG_LEVEL_INFO,
2200             "Compressed content detected, content filtering disabled. "
2201             "Consider recompiling Privoxy with zlib support or "
2202             "enable the prevent-compression action.");
2203       }
2204    }
2205 #endif /* defined(FEATURE_ZLIB) */
2206
2207    return JB_ERR_OK;
2208
2209 }
2210
2211
2212 /*********************************************************************
2213  *
2214  * Function    :  server_content_length
2215  *
2216  * Description :  Adjust Content-Length header if we modified
2217  *                the body.
2218  *
2219  * Parameters  :
2220  *          1  :  csp = Current client state (buffers, headers, etc...)
2221  *          2  :  header = On input, pointer to header to modify.
2222  *                On output, pointer to the modified header, or NULL
2223  *                to remove the header.  This function frees the
2224  *                original string if necessary.
2225  *
2226  * Returns     :  JB_ERR_OK on success, or
2227  *                JB_ERR_MEMORY on out-of-memory error.
2228  *
2229  *********************************************************************/
2230 jb_err server_content_length(struct client_state *csp, char **header)
2231 {
2232    const size_t max_header_length = 80;
2233
2234    /* Regenerate header if the content was modified. */
2235    if (csp->flags & CSP_FLAG_MODIFIED)
2236    {
2237       freez(*header);
2238       *header = (char *) zalloc(max_header_length);
2239       if (*header == NULL)
2240       {
2241          return JB_ERR_MEMORY;
2242       }
2243
2244       snprintf(*header, max_header_length, "Content-Length: %d",
2245          (int)csp->content_length);
2246       log_error(LOG_LEVEL_HEADER, "Adjusted Content-Length to %d",
2247          (int)csp->content_length);
2248    }
2249
2250    return JB_ERR_OK;
2251 }
2252
2253
2254 /*********************************************************************
2255  *
2256  * Function    :  server_content_md5
2257  *
2258  * Description :  Crumble any Content-MD5 headers if the document was
2259  *                modified. FIXME: Should we re-compute instead?
2260  *
2261  * Parameters  :
2262  *          1  :  csp = Current client state (buffers, headers, etc...)
2263  *          2  :  header = On input, pointer to header to modify.
2264  *                On output, pointer to the modified header, or NULL
2265  *                to remove the header.  This function frees the
2266  *                original string if necessary.
2267  *
2268  * Returns     :  JB_ERR_OK on success, or
2269  *                JB_ERR_MEMORY on out-of-memory error.
2270  *
2271  *********************************************************************/
2272 jb_err server_content_md5(struct client_state *csp, char **header)
2273 {
2274    if (csp->flags & CSP_FLAG_MODIFIED)
2275    {
2276       log_error(LOG_LEVEL_HEADER, "Crunching Content-MD5");
2277       freez(*header);
2278    }
2279
2280    return JB_ERR_OK;
2281 }
2282
2283 /*********************************************************************
2284  *
2285  * Function    :  server_content_disposition
2286  *
2287  * Description :  If enabled, blocks or modifies the "content-disposition" header.
2288  *                Called from `sed'.
2289  *
2290  * Parameters  :
2291  *          1  :  csp = Current client state (buffers, headers, etc...)
2292  *          2  :  header = On input, pointer to header to modify.
2293  *                On output, pointer to the modified header, or NULL
2294  *                to remove the header.  This function frees the
2295  *                original string if necessary.
2296  *
2297  * Returns     :  JB_ERR_OK on success, or
2298  *                JB_ERR_MEMORY on out-of-memory error.
2299  *
2300  *********************************************************************/
2301 jb_err server_content_disposition(struct client_state *csp, char **header)
2302 {
2303    const char *newval;
2304
2305    /*
2306     * Are we messing with the content-disposition header?
2307     */
2308    if ((csp->action->flags & ACTION_HIDE_CONTENT_DISPOSITION) == 0)
2309    {
2310       /*Me tinks not*/
2311       return JB_ERR_OK;
2312    }
2313
2314    newval = csp->action->string[ACTION_STRING_CONTENT_DISPOSITION];
2315
2316    if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
2317    {
2318       /*
2319        * Blocking content-disposition header
2320        */
2321       log_error(LOG_LEVEL_HEADER, "Crunching %s!", *header);
2322       freez(*header);
2323       return JB_ERR_OK;
2324    }
2325    else
2326    {  
2327       /*
2328        * Replacing content-disposition header
2329        */
2330       freez(*header);
2331       *header = strdup("content-disposition: ");
2332       string_append(header, newval);   
2333
2334       if (*header == NULL)
2335       {
2336          log_error(LOG_LEVEL_HEADER, "Insufficent memory. content-disposition header not fully replaced.");  
2337       }
2338       else
2339       {
2340          log_error(LOG_LEVEL_HEADER, "content-disposition header crunched and replaced with: %s", *header);
2341       }
2342    }
2343    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2344 }
2345
2346 /*********************************************************************
2347  *
2348  * Function    :  server_last_modified
2349  *
2350  * Description :  Changes Last-Modified header to the actual date
2351  *                to help hide-if-modified-since.
2352  *                Called from `sed'.
2353  *
2354  * Parameters  :
2355  *          1  :  csp = Current client state (buffers, headers, etc...)
2356  *          2  :  header = On input, pointer to header to modify.
2357  *                On output, pointer to the modified header, or NULL
2358  *                to remove the header.  This function frees the
2359  *                original string if necessary.
2360  *
2361  * Returns     :  JB_ERR_OK on success, or
2362  *                JB_ERR_MEMORY on out-of-memory error.
2363  *
2364  *********************************************************************/
2365 jb_err server_last_modified(struct client_state *csp, char **header)
2366 {
2367    const char *newval;
2368    char buf[BUFFER_SIZE];
2369
2370    char newheader[50];
2371 #ifdef HAVE_GMTIME_R
2372    struct tm gmt;
2373 #endif
2374    struct tm *timeptr = NULL;
2375    time_t now, last_modified;                  
2376    long int rtime;
2377    long int days, hours, minutes, seconds;
2378    
2379    /*
2380     * Are we messing with the Last-Modified header?
2381     */
2382    if ((csp->action->flags & ACTION_OVERWRITE_LAST_MODIFIED) == 0)
2383    {
2384       /*Nope*/
2385       return JB_ERR_OK;
2386    }
2387
2388    newval = csp->action->string[ACTION_STRING_LAST_MODIFIED];
2389
2390    if (0 == strcmpic(newval, "block") )
2391    {
2392       /*
2393        * Blocking Last-Modified header. Useless but why not.
2394        */
2395       log_error(LOG_LEVEL_HEADER, "Crunching %s!", *header);
2396       freez(*header);
2397       return JB_ERR_OK;
2398    }
2399    else if (0 == strcmpic(newval, "reset-to-request-time"))
2400    {  
2401       /*
2402        * Setting Last-Modified Header to now.
2403        */
2404       get_http_time(0, buf);
2405       freez(*header);
2406       *header = strdup("Last-Modified: ");
2407       string_append(header, buf);   
2408
2409       if (*header == NULL)
2410       {
2411          log_error(LOG_LEVEL_HEADER, "Insufficent memory. Last-Modified header got lost, boohoo.");  
2412       }
2413       else
2414       {
2415          log_error(LOG_LEVEL_HEADER, "Reset to present time: %s", *header);
2416       }
2417    }
2418    else if (0 == strcmpic(newval, "randomize"))
2419    {
2420       const char *header_time = *header + sizeof("Last-Modified:");
2421
2422       log_error(LOG_LEVEL_HEADER, "Randomizing: %s", *header);
2423       now = time(NULL);
2424 #ifdef HAVE_GMTIME_R
2425       timeptr = gmtime_r(&now, &gmt);
2426 #elif FEATURE_PTHREAD
2427       pthread_mutex_lock(&gmtime_mutex);
2428       timeptr = gmtime(&now);
2429       pthread_mutex_unlock(&gmtime_mutex);
2430 #else
2431       timeptr = gmtime(&now);
2432 #endif
2433       if (JB_ERR_OK != parse_header_time(header_time, &last_modified))
2434       {
2435          log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s in %s (crunching!)", header_time, *header);
2436          freez(*header);
2437       }
2438       else
2439       {
2440          rtime = (long int)difftime(now, last_modified);
2441          if (rtime)
2442          {
2443             rtime = pick_from_range(rtime);
2444             last_modified += rtime;
2445 #ifdef HAVE_GMTIME_R
2446             timeptr = gmtime_r(&last_modified, &gmt);
2447 #elif FEATURE_PTHREAD
2448             pthread_mutex_lock(&gmtime_mutex);
2449             timeptr = gmtime(&last_modified);
2450             pthread_mutex_unlock(&gmtime_mutex);
2451 #else
2452             timeptr = gmtime(&last_modified);
2453 #endif
2454             strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr);
2455             freez(*header);
2456             *header = strdup("Last-Modified: ");
2457             string_append(header, newheader);
2458
2459             if (*header == NULL)
2460             {
2461                log_error(LOG_LEVEL_ERROR, "Insufficent memory, header crunched without replacement.");
2462                return JB_ERR_MEMORY;  
2463             }
2464
2465             if(LOG_LEVEL_HEADER & debug) /* Save cycles if the user isn't interested. */
2466             {
2467                days    = rtime / (3600 * 24);
2468                hours   = rtime / 3600 % 24;
2469                minutes = rtime / 60 % 60;
2470                seconds = rtime % 60;            
2471
2472                log_error(LOG_LEVEL_HEADER, "Randomized:  %s (added %d da%s %d hou%s %d minut%s %d second%s",
2473                   *header, days, (days == 1) ? "y" : "ys", hours, (hours == 1) ? "r" : "rs",
2474                   minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)");
2475             }
2476          }
2477          else
2478          {
2479             log_error(LOG_LEVEL_HEADER, "Randomized ... or not. No time difference to work with.");
2480          }
2481       }
2482    }
2483
2484    return JB_ERR_OK;
2485 }
2486
2487
2488 /*********************************************************************
2489  *
2490  * Function    :  client_accept_encoding
2491  *
2492  * Description :  Rewrite the client's Accept-Encoding header so that
2493  *                if doesn't allow compression, if the action applies.
2494  *                Note: For HTTP/1.0 the absence of the header is enough.
2495  *
2496  * Parameters  :
2497  *          1  :  csp = Current client state (buffers, headers, etc...)
2498  *          2  :  header = On input, pointer to header to modify.
2499  *                On output, pointer to the modified header, or NULL
2500  *                to remove the header.  This function frees the
2501  *                original string if necessary.
2502  *
2503  * Returns     :  JB_ERR_OK on success, or
2504  *                JB_ERR_MEMORY on out-of-memory error.
2505  *
2506  *********************************************************************/
2507 jb_err client_accept_encoding(struct client_state *csp, char **header)
2508 {
2509    if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
2510    {
2511       log_error(LOG_LEVEL_HEADER, "Suppressed offer to compress content");
2512
2513       freez(*header);
2514
2515       /* Temporarily disable the correct behaviour to
2516        * work around a PHP bug. 
2517        *
2518        * if (!strcmpic(csp->http->ver, "HTTP/1.1"))
2519        * {
2520        *    *header = strdup("Accept-Encoding: identity;q=1.0, *;q=0");
2521        *    if (*header == NULL)
2522        *    {
2523        *       return JB_ERR_MEMORY;
2524        *    }
2525        * }
2526        * 
2527        */
2528    }
2529
2530    return JB_ERR_OK;
2531 }
2532
2533
2534 /*********************************************************************
2535  *
2536  * Function    :  client_te
2537  *
2538  * Description :  Rewrite the client's TE header so that
2539  *                if doesn't allow compression, if the action applies.
2540  *
2541  * Parameters  :
2542  *          1  :  csp = Current client state (buffers, headers, etc...)
2543  *          2  :  header = On input, pointer to header to modify.
2544  *                On output, pointer to the modified header, or NULL
2545  *                to remove the header.  This function frees the
2546  *                original string if necessary.
2547  *
2548  * Returns     :  JB_ERR_OK on success, or
2549  *                JB_ERR_MEMORY on out-of-memory error.
2550  *
2551  *********************************************************************/
2552 jb_err client_te(struct client_state *csp, char **header)
2553 {
2554    if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
2555    {
2556       freez(*header);
2557       log_error(LOG_LEVEL_HEADER, "Suppressed offer to compress transfer");
2558    }
2559
2560    return JB_ERR_OK;
2561 }
2562
2563 /*********************************************************************
2564  *
2565  * Function    :  client_referrer
2566  *
2567  * Description :  Handle the "referer" config setting properly.
2568  *                Called from `sed'.
2569  *
2570  * Parameters  :
2571  *          1  :  csp = Current client state (buffers, headers, etc...)
2572  *          2  :  header = On input, pointer to header to modify.
2573  *                On output, pointer to the modified header, or NULL
2574  *                to remove the header.  This function frees the
2575  *                original string if necessary.
2576  *
2577  * Returns     :  JB_ERR_OK on success, or
2578  *                JB_ERR_MEMORY on out-of-memory error.
2579  *
2580  *********************************************************************/
2581 jb_err client_referrer(struct client_state *csp, char **header)
2582 {
2583    const char *newval;
2584    const char *host;
2585    char *referer;
2586    size_t hostlenght;
2587  
2588 #ifdef FEATURE_FORCE_LOAD
2589    /* Since the referrer can include the prefix even
2590     * if the request itself is non-forced, we must
2591     * clean it unconditionally
2592     */
2593    strclean(*header, FORCE_PREFIX);
2594 #endif /* def FEATURE_FORCE_LOAD */
2595
2596    /*
2597     * Are we sending referer?
2598     */
2599    if ((csp->action->flags & ACTION_HIDE_REFERER) == 0)
2600    {
2601       return JB_ERR_OK;
2602    }
2603
2604    newval = csp->action->string[ACTION_STRING_REFERER];
2605
2606    if ((0 != strcmpic(newval, "conditional-block")))
2607    {  
2608       freez(*header);
2609    }
2610    if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
2611    {
2612       /*
2613        * Blocking referer
2614        */
2615       log_error(LOG_LEVEL_HEADER, "Referer crunched!");
2616       return JB_ERR_OK;
2617    }
2618    else if (0 == strcmpic(newval, "conditional-block"))
2619    {
2620       /*
2621        * Block referer if host has changed.
2622        */
2623
2624       if (NULL == (host = strdup(csp->http->hostport)))
2625       {
2626          freez(*header);
2627          log_error(LOG_LEVEL_HEADER, "Referer crunched! Couldn't allocate memory for temporary host copy.");
2628          return JB_ERR_MEMORY;
2629       }
2630       if (NULL == (referer = strdup(*header)))
2631       {
2632          freez(*header);
2633          freez(host);
2634          log_error(LOG_LEVEL_HEADER, "Referer crunched! Couldn't allocate memory for temporary referer copy.");
2635          return JB_ERR_MEMORY;
2636       }
2637       hostlenght = strlen(host);
2638       if ( hostlenght < (strlen(referer)-17) ) /*referer begins with 'Referer: http[s]://'*/
2639       {
2640          /*Shorten referer to make sure the referer is blocked
2641           *if www.example.org/www.example.com-shall-see-the-referer/
2642           *links to www.example.com/
2643           */
2644          referer[hostlenght+17] = '\0';
2645       }
2646       if ( 0 == strstr(referer, host)) /*Host has changed*/
2647       {
2648          log_error(LOG_LEVEL_HEADER, "New host is: %s. Crunching %s!", host, *header);
2649          freez(*header);
2650       }
2651       else
2652       {
2653          log_error(LOG_LEVEL_HEADER, "%s (not modified, still on %s)", *header, host);
2654       }
2655       freez(referer);
2656       freez(host);
2657       return JB_ERR_OK;    
2658    }
2659    else if (0 != strcmpic(newval, "forge"))
2660    {
2661       /*
2662        * We have a specific (fixed) referer we want to send.
2663        */
2664       if ((0 != strncmpic(newval, "http://", 7)) && (0 != strncmpic(newval, "https://", 8)))
2665       {
2666          log_error(LOG_LEVEL_HEADER, "Parameter: +referrer{%s} is a bad idea, but I don't care.", newval);
2667       }
2668       *header = strdup("Referer: ");
2669       string_append(header, newval);
2670       log_error(LOG_LEVEL_HEADER, "Referer overwritten with: %s", *header);
2671
2672       return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2673    }
2674    else
2675    {
2676       /*
2677        * Forge a referer as http://[hostname:port of REQUEST]/
2678        * to fool stupid checks for in-site links
2679        */
2680
2681       *header = strdup("Referer: http://");
2682       string_append(header, csp->http->hostport);
2683       string_append(header, "/");
2684       log_error(LOG_LEVEL_HEADER, "Referer forged to: %s", *header);
2685       
2686       return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2687    }
2688 }
2689
2690 /*********************************************************************
2691  *
2692  * Function    :  client_accept_language
2693  *
2694  * Description :  Handle the "Accept-Language" config setting properly.
2695  *                Called from `sed'.
2696  *
2697  * Parameters  :
2698  *          1  :  csp = Current client state (buffers, headers, etc...)
2699  *          2  :  header = On input, pointer to header to modify.
2700  *                On output, pointer to the modified header, or NULL
2701  *                to remove the header.  This function frees the
2702  *                original string if necessary.
2703  *
2704  * Returns     :  JB_ERR_OK on success, or
2705  *                JB_ERR_MEMORY on out-of-memory error.
2706  *
2707  *********************************************************************/
2708 jb_err client_accept_language(struct client_state *csp, char **header)
2709 {
2710    const char *newval;
2711
2712    /*
2713     * Are we messing with the Accept-Language?
2714     */
2715    if ((csp->action->flags & ACTION_HIDE_ACCEPT_LANGUAGE) == 0)
2716    {
2717       /*I don't think so*/
2718       return JB_ERR_OK;
2719    }
2720
2721    newval = csp->action->string[ACTION_STRING_LANGUAGE];
2722
2723    if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
2724    {
2725       /*
2726        * Blocking Accept-Language header
2727        */
2728       log_error(LOG_LEVEL_HEADER, "Crunching Accept-Language!");
2729       freez(*header);
2730       return JB_ERR_OK;
2731    }
2732    else
2733    {  
2734       /*
2735        * Replacing Accept-Language header
2736        */
2737       freez(*header);
2738       *header = strdup("Accept-Language: ");
2739       string_append(header, newval);   
2740
2741       if (*header == NULL)
2742       {
2743          log_error(LOG_LEVEL_ERROR,
2744             "Insufficent memory. Accept-Language header crunched without replacement.");  
2745       }
2746       else
2747       {
2748          log_error(LOG_LEVEL_HEADER,
2749             "Accept-Language header crunched and replaced with: %s", *header);
2750       }
2751    }
2752    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2753 }
2754
2755 /*********************************************************************
2756  *
2757  * Function    :  crunch_client_header
2758  *
2759  * Description :  Crunch client header if it matches a string supplied by the
2760  *                user. Called from `sed'.
2761  *
2762  * Parameters  :
2763  *          1  :  csp = Current client state (buffers, headers, etc...)
2764  *          2  :  header = On input, pointer to header to modify.
2765  *                On output, pointer to the modified header, or NULL
2766  *                to remove the header.  This function frees the
2767  *                original string if necessary.
2768  *
2769  * Returns     :  JB_ERR_OK on success and always succeeds
2770  *
2771  *********************************************************************/
2772 jb_err crunch_client_header(struct client_state *csp, char **header)
2773 {
2774    const char *crunch_pattern;
2775
2776    /* Do we feel like crunching? */
2777    if ((csp->action->flags & ACTION_CRUNCH_CLIENT_HEADER))
2778    {
2779       crunch_pattern = csp->action->string[ACTION_STRING_CLIENT_HEADER];
2780
2781       /* Is the current header the lucky one? */
2782       if (strstr(*header, crunch_pattern))
2783       {
2784          log_error(LOG_LEVEL_HEADER, "Crunching client header: %s (contains: %s)", *header, crunch_pattern);  
2785          freez(*header);
2786       }
2787    }
2788    return JB_ERR_OK;
2789 }
2790
2791
2792 /*********************************************************************
2793  *
2794  * Function    :  client_uagent
2795  *
2796  * Description :  Handle the "user-agent" config setting properly
2797  *                and remember its original value to enable browser
2798  *                bug workarounds. Called from `sed'.
2799  *
2800  * Parameters  :
2801  *          1  :  csp = Current client state (buffers, headers, etc...)
2802  *          2  :  header = On input, pointer to header to modify.
2803  *                On output, pointer to the modified header, or NULL
2804  *                to remove the header.  This function frees the
2805  *                original string if necessary.
2806  *
2807  * Returns     :  JB_ERR_OK on success, or
2808  *                JB_ERR_MEMORY on out-of-memory error.
2809  *
2810  *********************************************************************/
2811 jb_err client_uagent(struct client_state *csp, char **header)
2812 {
2813    const char *newval;
2814
2815    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) == 0)
2816    {
2817       return JB_ERR_OK;
2818    }
2819
2820    newval = csp->action->string[ACTION_STRING_USER_AGENT];
2821    if (newval == NULL)
2822    {
2823       return JB_ERR_OK;
2824    }
2825
2826    freez(*header);
2827    *header = strdup("User-Agent: ");
2828    string_append(header, newval);
2829
2830    log_error(LOG_LEVEL_HEADER, "Modified: %s", *header);
2831
2832    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2833 }
2834
2835 /*********************************************************************
2836  *
2837  * Function    :  client_ua
2838  *
2839  * Description :  Handle "ua-" headers properly.  Called from `sed'.
2840  *
2841  * Parameters  :
2842  *          1  :  csp = Current client state (buffers, headers, etc...)
2843  *          2  :  header = On input, pointer to header to modify.
2844  *                On output, pointer to the modified header, or NULL
2845  *                to remove the header.  This function frees the
2846  *                original string if necessary.
2847  *
2848  * Returns     :  JB_ERR_OK on success, or
2849  *                JB_ERR_MEMORY on out-of-memory error.
2850  *
2851  *********************************************************************/
2852 jb_err client_ua(struct client_state *csp, char **header)
2853 {
2854    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) != 0)
2855    {
2856       log_error(LOG_LEVEL_HEADER, "crunched User-Agent!");
2857       freez(*header);
2858    }
2859
2860    return JB_ERR_OK;
2861 }
2862
2863
2864 /*********************************************************************
2865  *
2866  * Function    :  client_from
2867  *
2868  * Description :  Handle the "from" config setting properly.
2869  *                Called from `sed'.
2870  *
2871  * Parameters  :
2872  *          1  :  csp = Current client state (buffers, headers, etc...)
2873  *          2  :  header = On input, pointer to header to modify.
2874  *                On output, pointer to the modified header, or NULL
2875  *                to remove the header.  This function frees the
2876  *                original string if necessary.
2877  *
2878  * Returns     :  JB_ERR_OK on success, or
2879  *                JB_ERR_MEMORY on out-of-memory error.
2880  *
2881  *********************************************************************/
2882 jb_err client_from(struct client_state *csp, char **header)
2883 {
2884    const char *newval;
2885
2886    if ((csp->action->flags & ACTION_HIDE_FROM) == 0)
2887    {
2888       return JB_ERR_OK;
2889    }
2890
2891    freez(*header);
2892
2893    newval = csp->action->string[ACTION_STRING_FROM];
2894
2895    /*
2896     * Are we blocking the e-mail address?
2897     */
2898    if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
2899    {
2900       log_error(LOG_LEVEL_HEADER, "crunched From!");
2901       return JB_ERR_OK;
2902    }
2903
2904    log_error(LOG_LEVEL_HEADER, " modified");
2905
2906    *header = strdup("From: ");
2907    string_append(header, newval);
2908
2909    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2910 }
2911
2912
2913 /*********************************************************************
2914  *
2915  * Function    :  client_send_cookie
2916  *
2917  * Description :  Crunches the "cookie" header if necessary.
2918  *                Called from `sed'.
2919  *
2920  *                XXX: Stupid name, doesn't send squat.
2921  *
2922  * Parameters  :
2923  *          1  :  csp = Current client state (buffers, headers, etc...)
2924  *          2  :  header = On input, pointer to header to modify.
2925  *                On output, pointer to the modified header, or NULL
2926  *                to remove the header.  This function frees the
2927  *                original string if necessary.
2928  *
2929  * Returns     :  JB_ERR_OK on success, or
2930  *                JB_ERR_MEMORY on out-of-memory error.
2931  *
2932  *********************************************************************/
2933 jb_err client_send_cookie(struct client_state *csp, char **header)
2934 {
2935    if (csp->action->flags & ACTION_NO_COOKIE_READ)
2936    {
2937       log_error(LOG_LEVEL_HEADER, "Crunched outgoing cookie: %s", *header);
2938       freez(*header);
2939    }
2940
2941    return JB_ERR_OK;
2942 }
2943
2944
2945 /*********************************************************************
2946  *
2947  * Function    :  client_x_forwarded
2948  *
2949  * Description :  Handle the "x-forwarded-for" config setting properly,
2950  *                also used in the add_client_headers list.  Called from `sed'.
2951  *
2952  * Parameters  :
2953  *          1  :  csp = Current client state (buffers, headers, etc...)
2954  *          2  :  header = On input, pointer to header to modify.
2955  *                On output, pointer to the modified header, or NULL
2956  *                to remove the header.  This function frees the
2957  *                original string if necessary.
2958  *
2959  * Returns     :  JB_ERR_OK on success, or
2960  *                JB_ERR_MEMORY on out-of-memory error.
2961  *
2962  *********************************************************************/
2963 jb_err client_x_forwarded(struct client_state *csp, char **header)
2964 {
2965    if ((csp->action->flags & ACTION_HIDE_FORWARDED) == 0)
2966    {
2967       /* Save it so we can re-add it later */
2968       freez(csp->x_forwarded);
2969       csp->x_forwarded = *header;
2970
2971       /*
2972        * Always set *header = NULL, since this information
2973        * will be sent at the end of the header.
2974        */
2975       *header = NULL;
2976    }
2977    else
2978    {
2979       freez(*header);
2980       log_error(LOG_LEVEL_HEADER, "crunched x-forwarded-for!");
2981    }
2982
2983    return JB_ERR_OK;
2984 }
2985
2986
2987 /*********************************************************************
2988  *
2989  * Function    :  client_max_forwards
2990  *
2991  * Description :  If the HTTP method is OPTIONS or TRACE, subtract one
2992  *                from the value of the Max-Forwards header field.
2993  *
2994  * Parameters  :
2995  *          1  :  csp = Current client state (buffers, headers, etc...)
2996  *          2  :  header = On input, pointer to header to modify.
2997  *                On output, pointer to the modified header, or NULL
2998  *                to remove the header.  This function frees the
2999  *                original string if necessary.
3000  *
3001  * Returns     :  JB_ERR_OK on success, or
3002  *                JB_ERR_MEMORY on out-of-memory error.
3003  *
3004  *********************************************************************/
3005 jb_err client_max_forwards(struct client_state *csp, char **header)
3006 {
3007    int max_forwards;
3008
3009    if ((0 == strcmpic(csp->http->gpc, "trace")) ||
3010        (0 == strcmpic(csp->http->gpc, "options")))
3011    {
3012       assert(*(*header+12) == ':');
3013       if (1 == sscanf(*header+12, ": %u", &max_forwards))
3014       {
3015          if (max_forwards > 0)
3016          {
3017             snprintf(*header, strlen(*header)+1, "Max-Forwards: %u", --max_forwards);
3018             log_error(LOG_LEVEL_HEADER, "Max-Forwards value for %s request reduced to %u.",
3019                csp->http->gpc, max_forwards);
3020          }
3021          else if (max_forwards < 0)
3022          {
3023             log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
3024             freez(*header);
3025          }
3026          else
3027          {
3028             /*
3029              * Not supposed to be reached. direct_response() which
3030              * was already called earlier in chat() should have
3031              * intercepted the request.
3032              */
3033             log_error(LOG_LEVEL_ERROR,
3034                "Non-intercepted %s request with Max-Forwards zero!", csp->http->gpc);
3035             assert(max_forwards != 0);
3036          }
3037       }
3038       else
3039       {
3040          log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
3041          freez(*header);
3042       }
3043    }
3044
3045    return JB_ERR_OK;
3046 }
3047
3048
3049 /*********************************************************************
3050  *
3051  * Function    :  client_host
3052  *
3053  * Description :  If the request URI did not contain host and
3054  *                port information, parse and evaluate the Host
3055  *                header field.
3056  *
3057  *                Also, kill ill-formed HOST: headers as sent by
3058  *                Apple's iTunes software when used with a proxy.
3059  *
3060  * Parameters  :
3061  *          1  :  csp = Current client state (buffers, headers, etc...)
3062  *          2  :  header = On input, pointer to header to modify.
3063  *                On output, pointer to the modified header, or NULL
3064  *                to remove the header.  This function frees the
3065  *                original string if necessary.
3066  *
3067  * Returns     :  JB_ERR_OK on success, or
3068  *                JB_ERR_MEMORY on out-of-memory error.
3069  *
3070  *********************************************************************/
3071 jb_err client_host(struct client_state *csp, char **header)
3072 {
3073    char *p, *q;
3074
3075    /*
3076     * If the header field name is all upper-case, chances are that it's
3077     * an ill-formed one from iTunes. BTW, killing innocent headers here is
3078     * not a problem -- they are regenerated later.
3079     */
3080    if ((*header)[1] == 'O')
3081    {
3082       log_error(LOG_LEVEL_HEADER, "Killed all-caps Host header line: %s", *header);
3083       freez(*header);
3084       return JB_ERR_OK;
3085    }
3086
3087    if (!csp->http->hostport || (*csp->http->hostport == '*') ||  
3088        *csp->http->hostport == ' ' || *csp->http->hostport == '\0')
3089    {
3090       
3091       if (NULL == (p = strdup((*header)+6)))
3092       {
3093          return JB_ERR_MEMORY;
3094       }
3095       chomp(p);
3096       if (NULL == (q = strdup(p)))
3097       {
3098          freez(p);
3099          return JB_ERR_MEMORY;
3100       }
3101
3102       freez(csp->http->hostport);
3103       csp->http->hostport = p;
3104       freez(csp->http->host);
3105       csp->http->host = q;
3106       q = strchr(csp->http->host, ':');
3107       if (q != NULL)
3108       {
3109          /* Terminate hostname and evaluate port string */
3110          *q++ = '\0';
3111          csp->http->port = atoi(q);
3112       }
3113       else
3114       {
3115          csp->http->port = csp->http->ssl ? 443 : 80;
3116       }
3117
3118       log_error(LOG_LEVEL_HEADER, "New host and port from Host field: %s = %s:%d",
3119                 csp->http->hostport, csp->http->host, csp->http->port);
3120    }
3121
3122    /* Signal client_host_adder() to return right away */
3123    csp->flags |= CSP_FLAG_HOST_HEADER_IS_SET;
3124
3125    return JB_ERR_OK;
3126 }
3127
3128 /*********************************************************************
3129  *
3130  * Function    :  client_if_modified_since
3131  *
3132  * Description :  Remove or modify the If-Modified-Since header.
3133  *
3134  * Parameters  :
3135  *          1  :  csp = Current client state (buffers, headers, etc...)
3136  *          2  :  header = On input, pointer to header to modify.
3137  *                On output, pointer to the modified header, or NULL
3138  *                to remove the header.  This function frees the
3139  *                original string if necessary.
3140  *
3141  * Returns     :  JB_ERR_OK on success, or
3142  *                JB_ERR_MEMORY on out-of-memory error.
3143  *
3144  *********************************************************************/
3145 jb_err client_if_modified_since(struct client_state *csp, char **header)
3146 {
3147    char newheader[50];
3148 #ifdef HAVE_GMTIME_R
3149    struct tm gmt;
3150 #endif
3151    struct tm *timeptr = NULL;
3152    time_t tm = 0;                  
3153    const char *newval;
3154    long int rtime;
3155    long int hours, minutes, seconds;
3156    int negative = 0;
3157    char * endptr;
3158    
3159    if ( 0 == strcmpic(*header, "If-Modified-Since: Wed, 08 Jun 1955 12:00:00 GMT"))
3160    {
3161       /* 
3162        * The client got an error message because of a temporary problem,
3163        * the problem is gone and the client now tries to revalidate our
3164        * error message on the real server. The revalidation would always
3165        * end with the transmission of the whole document and there is
3166        * no need to expose the bogus If-Modified-Since header.
3167        */
3168       log_error(LOG_LEVEL_HEADER, "Crunching useless If-Modified-Since header.");
3169       freez(*header);
3170    }
3171    else if (csp->action->flags & ACTION_HIDE_IF_MODIFIED_SINCE)
3172    {
3173       newval = csp->action->string[ACTION_STRING_IF_MODIFIED_SINCE];
3174
3175       if ((0 == strcmpic(newval, "block")))
3176       {
3177          log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3178          freez(*header);
3179       }
3180       else /* add random value */
3181       {
3182          const char *header_time = *header + sizeof("If-Modified-Since:");
3183
3184          if (JB_ERR_OK != parse_header_time(header_time, &tm))
3185          {
3186             log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s in %s (crunching!)", header_time, *header);
3187             freez(*header);
3188          }
3189          else
3190          {
3191             rtime = strtol(newval, &endptr, 0);
3192             if(rtime)
3193             {
3194                log_error(LOG_LEVEL_HEADER, "Randomizing: %s (random range: %d minut%s)",
3195                   *header, rtime, (rtime == 1 || rtime == -1) ? "e": "es");
3196                if(rtime < 0)
3197                {
3198                   rtime *= -1; 
3199                   negative = 1;
3200                }
3201                rtime *= 60;
3202                rtime = pick_from_range(rtime);
3203             }
3204             else
3205             {
3206                log_error(LOG_LEVEL_ERROR, "Random range is 0. Assuming time transformation test.",
3207                   *header);
3208             }
3209             tm += rtime * (negative ? -1 : 1);
3210 #ifdef HAVE_GMTIME_R
3211             timeptr = gmtime_r(&tm, &gmt);
3212 #elif FEATURE_PTHREAD
3213             pthread_mutex_lock(&gmtime_mutex);
3214             timeptr = gmtime(&tm);
3215             pthread_mutex_unlock(&gmtime_mutex);
3216 #else
3217             timeptr = gmtime(&tm);
3218 #endif
3219             strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr);
3220
3221             freez(*header);
3222             *header = strdup("If-Modified-Since: ");
3223             string_append(header, newheader);
3224
3225             if (*header == NULL)
3226             {
3227                log_error(LOG_LEVEL_HEADER, "Insufficent memory, header crunched without replacement.");
3228                return JB_ERR_MEMORY;  
3229             }
3230
3231             if(LOG_LEVEL_HEADER & debug) /* Save cycles if the user isn't interested. */
3232             {
3233                hours   = rtime / 3600;
3234                minutes = rtime / 60 % 60;
3235                seconds = rtime % 60;            
3236
3237                log_error(LOG_LEVEL_HEADER, "Randomized:  %s (%s %d hou%s %d minut%s %d second%s",
3238                   *header, (negative) ? "subtracted" : "added", hours, (hours == 1) ? "r" : "rs",
3239                   minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)");
3240             }
3241          }
3242       }
3243    }
3244
3245    return JB_ERR_OK;
3246 }
3247
3248 /*********************************************************************
3249  *
3250  * Function    :  client_if_none_match
3251  *
3252  * Description :  Remove the If-None-Match header.
3253  *
3254  * Parameters  :
3255  *          1  :  csp = Current client state (buffers, headers, etc...)
3256  *          2  :  header = On input, pointer to header to modify.
3257  *                On output, pointer to the modified header, or NULL
3258  *                to remove the header.  This function frees the
3259  *                original string if necessary.
3260  *
3261  * Returns     :  JB_ERR_OK on success, or
3262  *                JB_ERR_MEMORY on out-of-memory error.
3263  *
3264  *********************************************************************/
3265 jb_err client_if_none_match(struct client_state *csp, char **header)
3266 {
3267    if (csp->action->flags & ACTION_CRUNCH_IF_NONE_MATCH)
3268    {  
3269       log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3270       freez(*header);
3271    }
3272
3273    return JB_ERR_OK;
3274 }
3275
3276 /*********************************************************************
3277  *
3278  * Function    :  client_x_filter
3279  *
3280  * Description :  Disables filtering if the client set "X-Filter: No".
3281  *                Called from `sed'.
3282  *
3283  * Parameters  :
3284  *          1  :  csp = Current client state (buffers, headers, etc...)
3285  *          2  :  header = On input, pointer to header to modify.
3286  *                On output, pointer to the modified header, or NULL
3287  *                to remove the header.  This function frees the
3288  *                original string if necessary.
3289  *
3290  * Returns     :  JB_ERR_OK on success
3291  *
3292  *********************************************************************/
3293 jb_err client_x_filter(struct client_state *csp, char **header)
3294 {
3295    if ( 0 == strcmpic(*header, "X-Filter: No"))
3296    {
3297       if (!(csp->config->feature_flags & RUNTIME_FEATURE_HTTP_TOGGLE))
3298       {
3299          log_error(LOG_LEVEL_INFO, "Ignored the client's request to fetch without filtering.");
3300       }
3301       else
3302       {
3303          if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
3304          {
3305             log_error(LOG_LEVEL_HEADER,
3306                "force-text-mode overruled the client's request to fetch without filtering!");
3307          }
3308          else
3309          {  
3310             csp->content_type = CT_TABOO;
3311             csp->action->flags &= ~ACTION_FILTER_SERVER_HEADERS;
3312             csp->action->flags &= ~ACTION_FILTER_CLIENT_HEADERS;
3313             log_error(LOG_LEVEL_HEADER, "Accepted the client's request to fetch without filtering.");
3314          }
3315          log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3316          freez(*header);
3317       }
3318    }
3319    return JB_ERR_OK; 
3320 }
3321
3322 /* the following functions add headers directly to the header list */
3323
3324 /*********************************************************************
3325  *
3326  * Function    :  client_host_adder
3327  *
3328  * Description :  Adds the Host: header field if it is missing.
3329  *                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 jb_err client_host_adder(struct client_state *csp)
3339 {
3340    char *p;
3341    jb_err err;
3342
3343    if (csp->flags & CSP_FLAG_HOST_HEADER_IS_SET)
3344    {
3345       /* Header already set by the client, nothing to do. */
3346       return JB_ERR_OK;
3347    }
3348
3349    if ( !csp->http->hostport || !*(csp->http->hostport))
3350    {
3351       /* XXX: When does this happen and why is it OK? */
3352       log_error(LOG_LEVEL_INFO, "Weirdness in client_host_adder detected and ignored.");
3353       return JB_ERR_OK;
3354    }
3355
3356    /*
3357     * remove 'user:pass@' from 'proto://user:pass@host'
3358     */
3359    if ( (p = strchr( csp->http->hostport, '@')) != NULL )
3360    {
3361       p++;
3362    }
3363    else
3364    {
3365       p = csp->http->hostport;
3366    }
3367
3368    /* XXX: Just add it, we already made sure that it will be unique */
3369    log_error(LOG_LEVEL_HEADER, "addh-unique: Host: %s", p);
3370    err = enlist_unique_header(csp->headers, "Host", p);
3371    return err;
3372
3373 }
3374
3375
3376 /*********************************************************************
3377  *
3378  * Function    :  client_cookie_adder
3379  *
3380  * Description :  Used in the add_client_headers list.  Called from `sed'.
3381  *
3382  *                XXX: Remove csp->cookie_list which is no longer used.
3383  *
3384  * Parameters  :
3385  *          1  :  csp = Current client state (buffers, headers, etc...)
3386  *
3387  * Returns     :  JB_ERR_OK on success, or
3388  *                JB_ERR_MEMORY on out-of-memory error.
3389  *
3390  *********************************************************************/
3391 jb_err client_cookie_adder(struct client_state *csp)
3392 {
3393    struct list_entry *lst;
3394    char *tmp;
3395    struct list_entry *list1 = csp->cookie_list->first;
3396    struct list_entry *list2 = csp->action->multi[ACTION_MULTI_WAFER]->first;
3397    int first_cookie = 1;
3398    jb_err err;
3399
3400    if ((list1 == NULL) && (list2 == NULL))
3401    {
3402       /* Nothing to do */
3403       return JB_ERR_OK;
3404    }
3405
3406    tmp = strdup("Cookie: ");
3407
3408    for (lst = list1; lst ; lst = lst->next)
3409    {
3410       if (first_cookie)
3411       {
3412          first_cookie = 0;
3413       }
3414       else
3415       {
3416          string_append(&tmp, "; ");
3417       }
3418       string_append(&tmp, lst->str);
3419    }
3420
3421    for (lst = list2;  lst ; lst = lst->next)
3422    {
3423       if (first_cookie)
3424       {
3425          first_cookie = 0;
3426       }
3427       else
3428       {
3429          string_append(&tmp, "; ");
3430       }
3431       string_join(&tmp, cookie_encode(lst->str));
3432    }
3433
3434    if (tmp == NULL)
3435    {
3436       return JB_ERR_MEMORY;
3437    }
3438
3439    log_error(LOG_LEVEL_HEADER, "addh: %s", tmp);
3440    err = enlist(csp->headers, tmp);
3441    free(tmp);
3442    return err;
3443 }
3444
3445
3446 /*********************************************************************
3447  *
3448  * Function    :  client_accept_encoding_adder
3449  *
3450  * Description :  Add an Accept-Encoding header to the client's request
3451  *                that disables compression if the action applies, and
3452  *                the header is not already there. Called from `sed'.
3453  *                Note: For HTTP/1.0, the absence of the header is enough.
3454  *
3455  * Parameters  :
3456  *          1  :  csp = Current client state (buffers, headers, etc...)
3457  *
3458  * Returns     :  JB_ERR_OK on success, or
3459  *                JB_ERR_MEMORY on out-of-memory error.
3460  *
3461  *********************************************************************/
3462 jb_err client_accept_encoding_adder(struct client_state *csp)
3463 {
3464    assert(0); /* Not in use */
3465
3466    if (   ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
3467        && (!strcmpic(csp->http->ver, "HTTP/1.1")) )
3468    {
3469       return enlist_unique(csp->headers, "Accept-Encoding: identity;q=1.0, *;q=0", 16);
3470    }
3471
3472    return JB_ERR_OK;
3473 }
3474
3475
3476 /*********************************************************************
3477  *
3478  * Function    :  client_xtra_adder
3479  *
3480  * Description :  Used in the add_client_headers list.  Called from `sed'.
3481  *
3482  * Parameters  :
3483  *          1  :  csp = Current client state (buffers, headers, etc...)
3484  *
3485  * Returns     :  JB_ERR_OK on success, or
3486  *                JB_ERR_MEMORY on out-of-memory error.
3487  *
3488  *********************************************************************/
3489 jb_err client_xtra_adder(struct client_state *csp)
3490 {
3491    struct list_entry *lst;
3492    jb_err err;
3493
3494    for (lst = csp->action->multi[ACTION_MULTI_ADD_HEADER]->first;
3495         lst ; lst = lst->next)
3496    {
3497       log_error(LOG_LEVEL_HEADER, "addh: %s", lst->str);
3498       err = enlist(csp->headers, lst->str);
3499       if (err)
3500       {
3501          return err;
3502       }
3503
3504    }
3505
3506    return JB_ERR_OK;
3507 }
3508
3509
3510 /*********************************************************************
3511  *
3512  * Function    :  client_x_forwarded_adder
3513  *
3514  * Description :  Used in the add_client_headers list.  Called from `sed'.
3515  *
3516  * Parameters  :
3517  *          1  :  csp = Current client state (buffers, headers, etc...)
3518  *
3519  * Returns     :  JB_ERR_OK on success, or
3520  *                JB_ERR_MEMORY on out-of-memory error.
3521  *
3522  *********************************************************************/
3523 jb_err client_x_forwarded_adder(struct client_state *csp)
3524 {
3525    char *p = NULL;
3526    jb_err err;
3527
3528    if ((csp->action->flags & ACTION_HIDE_FORWARDED) != 0)
3529    {
3530       return JB_ERR_OK;
3531    }
3532
3533    if (csp->x_forwarded)
3534    {
3535       p = strdup(csp->x_forwarded);
3536       string_append(&p, ", ");
3537    }
3538    else
3539    {
3540       p = strdup("X-Forwarded-For: ");
3541    }
3542    string_append(&p, csp->ip_addr_str);
3543
3544    if (p == NULL)
3545    {
3546       return JB_ERR_MEMORY;
3547    }
3548
3549    log_error(LOG_LEVEL_HEADER, "addh: %s", p);
3550    err = enlist(csp->headers, p);
3551    free(p);
3552
3553    return err;
3554 }
3555
3556
3557 /*********************************************************************
3558  *
3559  * Function    :  connection_close_adder
3560  *
3561  * Description :  "Temporary" fix for the needed but missing HTTP/1.1
3562  *                support. Adds a "Connection: close" header to csp->headers
3563  *                unless the header was already present. Called from `sed'.
3564  *
3565  *                FIXME: This whole function shouldn't be neccessary!
3566  *
3567  * Parameters  :
3568  *          1  :  csp = Current client state (buffers, headers, etc...)
3569  *
3570  * Returns     :  JB_ERR_OK on success, or
3571  *                JB_ERR_MEMORY on out-of-memory error.
3572  *
3573  *********************************************************************/
3574 jb_err connection_close_adder(struct client_state *csp)
3575 {
3576    const unsigned int flags = csp->flags;
3577
3578    /*
3579     * Return right away if
3580     *
3581     * - we're parsing server headers and the server header
3582     *   "Connection: close" is already set, or if
3583     *
3584     * - we're parsing client headers and the client header 
3585     *   "Connection: close" is already set.
3586     */
3587    if ((flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE
3588      && flags & CSP_FLAG_SERVER_CONNECTION_CLOSE_SET)
3589    ||(!(flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
3590      && flags & CSP_FLAG_CLIENT_CONNECTION_CLOSE_SET))
3591    {
3592       return JB_ERR_OK;
3593    }
3594
3595    log_error(LOG_LEVEL_HEADER, "Adding: Connection: close");
3596
3597    return enlist(csp->headers, "Connection: close");
3598 }
3599
3600
3601 /*********************************************************************
3602  *
3603  * Function    :  server_http
3604  *
3605  * Description :  - Save the HTTP Status into csp->http->status
3606  *                - Set CT_TABOO to prevent filtering if the answer
3607  *                  is a partial range (HTTP status 206)
3608  *                - Rewrite HTTP/1.1 answers to HTTP/1.0 if +downgrade
3609  *                  action applies.
3610  *
3611  * Parameters  :
3612  *          1  :  csp = Current client state (buffers, headers, etc...)
3613  *          2  :  header = On input, pointer to header to modify.
3614  *                On output, pointer to the modified header, or NULL
3615  *                to remove the header.  This function frees the
3616  *                original string if necessary.
3617  *
3618  * Returns     :  JB_ERR_OK on success, or
3619  *                JB_ERR_MEMORY on out-of-memory error.
3620  *
3621  *********************************************************************/
3622 jb_err server_http(struct client_state *csp, char **header)
3623 {
3624    sscanf(*header, "HTTP/%*d.%*d %d", &(csp->http->status));
3625    if (csp->http->status == 206)
3626    {
3627       csp->content_type = CT_TABOO;
3628    }
3629
3630    if ((csp->action->flags & ACTION_DOWNGRADE) != 0)
3631    {
3632       (*header)[7] = '0';
3633       log_error(LOG_LEVEL_HEADER, "Downgraded answer to HTTP/1.0");
3634    }
3635
3636    return JB_ERR_OK;
3637 }
3638
3639
3640 /*********************************************************************
3641  *
3642  * Function    :  server_set_cookie
3643  *
3644  * Description :  Handle the server "cookie" header properly.
3645  *                Log cookie to the jar file.  Then "crunch",
3646  *                accept or rewrite it to a session cookie.
3647  *                Called from `sed'.
3648  *
3649  *                TODO: Allow the user to specify a new expiration
3650  *                time to cause the cookie to expire even before the
3651  *                browser is closed.
3652  *
3653  * Parameters  :
3654  *          1  :  csp = Current client state (buffers, headers, etc...)
3655  *          2  :  header = On input, pointer to header to modify.
3656  *                On output, pointer to the modified header, or NULL
3657  *                to remove the header.  This function frees the
3658  *                original string if necessary.
3659  *
3660  * Returns     :  JB_ERR_OK on success, or
3661  *                JB_ERR_MEMORY on out-of-memory error.
3662  *
3663  *********************************************************************/
3664 jb_err server_set_cookie(struct client_state *csp, char **header)
3665 {
3666    time_t now;
3667    time_t cookie_time; 
3668    struct tm tm_now; 
3669    time(&now);
3670
3671 #ifdef FEATURE_COOKIE_JAR
3672    if (csp->config->jar)
3673    {
3674       /*
3675        * Write timestamp into outbuf.
3676        *
3677        * Complex because not all OSs have tm_gmtoff or
3678        * the %z field in strftime()
3679        */
3680       char tempbuf[ BUFFER_SIZE ];
3681  
3682 #ifdef HAVE_LOCALTIME_R
3683       tm_now = *localtime_r(&now, &tm_now);
3684 #elif FEATURE_PTHREAD
3685       pthread_mutex_lock(&localtime_mutex);
3686       tm_now = *localtime (&now);
3687       pthread_mutex_unlock(&localtime_mutex);
3688 #else
3689       tm_now = *localtime (&now);
3690 #endif
3691       strftime(tempbuf, BUFFER_SIZE-6, "%b %d %H:%M:%S ", &tm_now); 
3692
3693       /* strlen("set-cookie: ") = 12 */
3694       fprintf(csp->config->jar, "%s %s\t%s\n", tempbuf, csp->http->host, *header + 12);
3695    }
3696 #endif /* def FEATURE_COOKIE_JAR */
3697
3698    if ((csp->action->flags & ACTION_NO_COOKIE_SET) != 0)
3699    {
3700       log_error(LOG_LEVEL_HEADER, "Crunching incoming cookie: %s", *header);
3701       freez(*header);
3702    }
3703    else if ((csp->action->flags & ACTION_NO_COOKIE_KEEP) != 0)
3704    {
3705       /* Flag whether or not to log a message */
3706       int changed = 0;
3707
3708       /* A variable to store the tag we're working on */
3709       char *cur_tag;
3710
3711       /* Skip "Set-Cookie:" (11 characters) in header */
3712       cur_tag = *header + 11;
3713
3714       /* skip whitespace between "Set-Cookie:" and value */
3715       while (*cur_tag && ijb_isspace(*cur_tag))
3716       {
3717          cur_tag++;