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