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