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