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