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