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