e9b6d1c72a95180beb08f38ae578e58a014f5ae1
[privoxy.git] / parsers.c
1 const char parsers_rcs[] = "$Id: parsers.c,v 1.56 2002/05/12 15:34:22 jongfoster Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa//current/Attic/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',
14  *                   and `server_set_cookie'.
15  *
16  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
17  *                Privoxy team. http://www.privoxy.org/
18  *
19  *                Based on the Internet Junkbuster originally written
20  *                by and Copyright (C) 1997 Anonymous Coders and
21  *                Junkbusters Corporation.  http://www.junkbusters.com
22  *
23  *                This program is free software; you can redistribute it
24  *                and/or modify it under the terms of the GNU General
25  *                Public License as published by the Free Software
26  *                Foundation; either version 2 of the License, or (at
27  *                your option) any later version.
28  *
29  *                This program is distributed in the hope that it will
30  *                be useful, but WITHOUT ANY WARRANTY; without even the
31  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
32  *                PARTICULAR PURPOSE.  See the GNU General Public
33  *                License for more details.
34  *
35  *                The GNU General Public License should be included with
36  *                this file.  If not, you can view it at
37  *                http://www.gnu.org/copyleft/gpl.html
38  *                or write to the Free Software Foundation, Inc., 59
39  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
40  *
41  * Revisions   :
42  *    $Log: parsers.c,v $
43  *    Revision 1.56  2002/05/12 15:34:22  jongfoster
44  *    Fixing typo in a comment
45  *
46  *    Revision 1.55  2002/05/08 16:01:07  oes
47  *    Optimized add_to_iob:
48  *     - Use realloc instead of malloc(), memcpy(), free()
49  *     - Expand to powers of two if possible, to get
50  *       O(log n) reallocs instead of O(n).
51  *     - Moved check for buffer limit here from chat
52  *     - Report failure via returncode
53  *
54  *    Revision 1.54  2002/04/02 15:03:16  oes
55  *    Tiny code cosmetics
56  *
57  *    Revision 1.53  2002/03/26 22:29:55  swa
58  *    we have a new homepage!
59  *
60  *    Revision 1.52  2002/03/24 13:25:43  swa
61  *    name change related issues
62  *
63  *    Revision 1.51  2002/03/13 00:27:05  jongfoster
64  *    Killing warnings
65  *
66  *    Revision 1.50  2002/03/12 01:45:35  oes
67  *    More verbose logging
68  *
69  *    Revision 1.49  2002/03/09 20:03:52  jongfoster
70  *    - Making various functions return int rather than size_t.
71  *      (Undoing a recent change).  Since size_t is unsigned on
72  *      Windows, functions like read_socket that return -1 on
73  *      error cannot return a size_t.
74  *
75  *      THIS WAS A MAJOR BUG - it caused frequent, unpredictable
76  *      crashes, and also frequently caused JB to jump to 100%
77  *      CPU and stay there.  (Because it thought it had just
78  *      read ((unsigned)-1) == 4Gb of data...)
79  *
80  *    - The signature of write_socket has changed, it now simply
81  *      returns success=0/failure=nonzero.
82  *
83  *    - Trying to get rid of a few warnings --with-debug on
84  *      Windows, I've introduced a new type "jb_socket".  This is
85  *      used for the socket file descriptors.  On Windows, this
86  *      is SOCKET (a typedef for unsigned).  Everywhere else, it's
87  *      an int.  The error value can't be -1 any more, so it's
88  *      now JB_INVALID_SOCKET (which is -1 on UNIX, and in
89  *      Windows it maps to the #define INVALID_SOCKET.)
90  *
91  *    - The signature of bind_port has changed.
92  *
93  *    Revision 1.48  2002/03/07 03:46:53  oes
94  *    Fixed compiler warnings etc
95  *
96  *    Revision 1.47  2002/02/20 23:15:13  jongfoster
97  *    Parsing functions now handle out-of-memory gracefully by returning
98  *    an error code.
99  *
100  *    Revision 1.46  2002/01/17 21:03:47  jongfoster
101  *    Moving all our URL and URL pattern parsing code to urlmatch.c.
102  *
103  *    Revision 1.45  2002/01/09 14:33:03  oes
104  *    Added support for localtime_r.
105  *
106  *    Revision 1.44  2001/12/14 01:22:54  steudten
107  *    Remove 'user:pass@' from 'proto://user:pass@host' for the
108  *    new added header 'Host: ..'. (See Req ID 491818)
109  *
110  *    Revision 1.43  2001/11/23 00:26:38  jongfoster
111  *    Fixing two really stupid errors in my previous commit
112  *
113  *    Revision 1.42  2001/11/22 21:59:30  jongfoster
114  *    Adding code to handle +no-cookies-keep
115  *
116  *    Revision 1.41  2001/11/05 23:43:05  steudten
117  *    Add time+date to log files.
118  *
119  *    Revision 1.40  2001/10/26 20:13:09  jongfoster
120  *    ctype.h is needed in Windows, too.
121  *
122  *    Revision 1.39  2001/10/26 17:40:04  oes
123  *    Introduced get_header_value()
124  *    Removed http->user_agent, csp->referrer and csp->accept_types
125  *    Removed client_accept()
126  *
127  *    Revision 1.38  2001/10/25 03:40:48  david__schmidt
128  *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
129  *    threads to call select() simultaneously.  So, it's time to do a real, live,
130  *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
131  *    (native). Both versions will work, but using __OS2__ offers multi-threading.
132  *
133  *    Revision 1.37  2001/10/23 21:36:02  jongfoster
134  *    Documenting sed()'s error behaviou (doc change only)
135  *
136  *    Revision 1.36  2001/10/13 12:51:51  joergs
137  *    Removed client_host, (was only required for the old 2.0.2-11 http://noijb.
138  *    force-load), instead crumble Host: and add it (again) in client_host_adder
139  *    (in case we get a HTTP/1.0 request without Host: header and forward it to
140  *    a HTTP/1.1 server/proxy).
141  *
142  *    Revision 1.35  2001/10/09 22:39:21  jongfoster
143  *    assert.h is also required under Win32, so moving out of #ifndef _WIN32
144  *    block.
145  *
146  *    Revision 1.34  2001/10/07 18:50:55  oes
147  *    Added server_content_encoding, renamed server_transfer_encoding
148  *
149  *    Revision 1.33  2001/10/07 18:04:49  oes
150  *    Changed server_http11 to server_http and its pattern to "HTTP".
151  *      Additional functionality: it now saves the HTTP status into
152  *      csp->http->status and sets CT_TABOO for Status 206 (partial range)
153  *
154  *    Revision 1.32  2001/10/07 15:43:28  oes
155  *    Removed FEATURE_DENY_GZIP and replaced it with client_accept_encoding,
156  *       client_te and client_accept_encoding_adder, triggered by the new
157  *       +no-compression action. For HTTP/1.1 the Accept-Encoding header is
158  *       changed to allow only identity and chunked, and the TE header is
159  *       crunched. For HTTP/1.0, Accept-Encoding is crunched.
160  *
161  *    parse_http_request no longer does anything than parsing. The rewriting
162  *      of http->cmd and version mangling are gone. It now also recognizes
163  *      the put and delete methods and saves the url in http->url. Removed
164  *      unused variable.
165  *
166  *    renamed content_type and content_length to have the server_ prefix
167  *
168  *    server_content_type now only works if csp->content_type != CT_TABOO
169  *
170  *    added server_transfer_encoding, which
171  *      - Sets CT_TABOO to prohibit filtering if encoding compresses
172  *      - Raises the CSP_FLAG_CHUNKED flag if Encoding is "chunked"
173  *      - Change from "chunked" to "identity" if body was chunked
174  *        but has been de-chunked for filtering.
175  *
176  *    added server_content_md5 which crunches any Content-MD5 headers
177  *      if the body was modified.
178  *
179  *    made server_http11 conditional on +downgrade action
180  *
181  *    Replaced 6 boolean members of csp with one bitmap (csp->flags)
182  *
183  *    Revision 1.31  2001/10/05 14:25:02  oes
184  *    Crumble Keep-Alive from Server
185  *
186  *    Revision 1.30  2001/09/29 12:56:03  joergs
187  *    IJB now changes HTTP/1.1 to HTTP/1.0 in requests and answers.
188  *
189  *    Revision 1.29  2001/09/24 21:09:24  jongfoster
190  *    Fixing 2 memory leaks that Guy spotted, where the paramater to
191  *    enlist() was not being free()d.
192  *
193  *    Revision 1.28  2001/09/22 16:32:28  jongfoster
194  *    Removing unused #includes.
195  *
196  *    Revision 1.27  2001/09/20 15:45:25  steudten
197  *
198  *    add casting from size_t to int for printf()
199  *    remove local variable shadow s2
200  *
201  *    Revision 1.26  2001/09/16 17:05:14  jongfoster
202  *    Removing unused #include showarg.h
203  *
204  *    Revision 1.25  2001/09/16 13:21:27  jongfoster
205  *    Changes to use new list functions.
206  *
207  *    Revision 1.24  2001/09/13 23:05:50  jongfoster
208  *    Changing the string paramater to the header parsers a "const".
209  *
210  *    Revision 1.23  2001/09/12 18:08:19  steudten
211  *
212  *    In parse_http_request() header rewriting miss the host value, so
213  *    from http://www.mydomain.com the result was just " / " not
214  *    http://www.mydomain.com/ in case we forward.
215  *
216  *    Revision 1.22  2001/09/10 10:58:53  oes
217  *    Silenced compiler warnings
218  *
219  *    Revision 1.21  2001/07/31 14:46:00  oes
220  *     - Persistant connections now suppressed
221  *     - sed() no longer appends empty header to csp->headers
222  *
223  *    Revision 1.20  2001/07/30 22:08:36  jongfoster
224  *    Tidying up #defines:
225  *    - All feature #defines are now of the form FEATURE_xxx
226  *    - Permanently turned off WIN_GUI_EDIT
227  *    - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
228  *
229  *    Revision 1.19  2001/07/25 17:21:54  oes
230  *    client_uagent now saves copy of User-Agent: header value
231  *
232  *    Revision 1.18  2001/07/13 14:02:46  oes
233  *     - Included fix to repair broken HTTP requests that
234  *       don't contain a path, not even '/'.
235  *     - Removed all #ifdef PCRS
236  *     - content_type now always inspected and classified as
237  *       text, gif or other.
238  *     - formatting / comments
239  *
240  *    Revision 1.17  2001/06/29 21:45:41  oes
241  *    Indentation, CRLF->LF, Tab-> Space
242  *
243  *    Revision 1.16  2001/06/29 13:32:42  oes
244  *    - Fixed a comment
245  *    - Adapted free_http_request
246  *    - Removed logentry from cancelled commit
247  *
248  *    Revision 1.15  2001/06/03 19:12:38  oes
249  *    deleted const struct interceptors
250  *
251  *    Revision 1.14  2001/06/01 18:49:17  jongfoster
252  *    Replaced "list_share" with "list" - the tiny memory gain was not
253  *    worth the extra complexity.
254  *
255  *    Revision 1.13  2001/05/31 21:30:33  jongfoster
256  *    Removed list code - it's now in list.[ch]
257  *    Renamed "permission" to "action", and changed many features
258  *    to use the actions file rather than the global config.
259  *
260  *    Revision 1.12  2001/05/31 17:33:13  oes
261  *
262  *    CRLF -> LF
263  *
264  *    Revision 1.11  2001/05/29 20:11:19  joergs
265  *    '/ * inside comment' warning removed.
266  *
267  *    Revision 1.10  2001/05/29 09:50:24  jongfoster
268  *    Unified blocklist/imagelist/permissionslist.
269  *    File format is still under discussion, but the internal changes
270  *    are (mostly) done.
271  *
272  *    Also modified interceptor behaviour:
273  *    - We now intercept all URLs beginning with one of the following
274  *      prefixes (and *only* these prefixes):
275  *        * http://i.j.b/
276  *        * http://ijbswa.sf.net/config/
277  *        * http://ijbswa.sourceforge.net/config/
278  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
279  *    - Internal changes so that intercepted and fast redirect pages
280  *      are not replaced with an image.
281  *    - Interceptors now have the option to send a binary page direct
282  *      to the client. (i.e. ijb-send-banner uses this)
283  *    - Implemented show-url-info interceptor.  (Which is why I needed
284  *      the above interceptors changes - a typical URL is
285  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
286  *      The previous mechanism would not have intercepted that, and
287  *      if it had been intercepted then it then it would have replaced
288  *      it with an image.)
289  *
290  *    Revision 1.9  2001/05/28 17:26:33  jongfoster
291  *    Fixing segfault if last header was crunched.
292  *    Fixing Windows build (snprintf() is _snprintf() under Win32, but we
293  *    can use the cross-platform sprintf() instead.)
294  *
295  *    Revision 1.8  2001/05/27 22:17:04  oes
296  *
297  *    - re_process_buffer no longer writes the modified buffer
298  *      to the client, which was very ugly. It now returns the
299  *      buffer, which it is then written by chat.
300  *
301  *    - content_length now adjusts the Content-Length: header
302  *      for modified documents rather than crunch()ing it.
303  *      (Length info in csp->content_length, which is 0 for
304  *      unmodified documents)
305  *
306  *    - For this to work, sed() is called twice when filtering.
307  *
308  *    Revision 1.7  2001/05/27 13:19:06  oes
309  *    Patched Joergs solution for the content-length in.
310  *
311  *    Revision 1.6  2001/05/26 13:39:32  jongfoster
312  *    Only crunches Content-Length header if applying RE filtering.
313  *    Without this fix, Microsoft Windows Update wouldn't work.
314  *
315  *    Revision 1.5  2001/05/26 00:28:36  jongfoster
316  *    Automatic reloading of config file.
317  *    Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
318  *    Most of the global variables have been moved to a new
319  *    struct configuration_spec, accessed through csp->config->globalname
320  *    Most of the globals remaining are used by the Win32 GUI.
321  *
322  *    Revision 1.4  2001/05/22 18:46:04  oes
323  *
324  *    - Enabled filtering banners by size rather than URL
325  *      by adding patterns that replace all standard banner
326  *      sizes with the "Junkbuster" gif to the re_filterfile
327  *
328  *    - Enabled filtering WebBugs by providing a pattern
329  *      which kills all 1x1 images
330  *
331  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
332  *      which is selected by the (nonstandard and therefore
333  *      capital) letter 'U' in the option string.
334  *      It causes the quantifiers to be ungreedy by default.
335  *      Appending a ? turns back to greedy (!).
336  *
337  *    - Added a new interceptor ijb-send-banner, which
338  *      sends back the "Junkbuster" gif. Without imagelist or
339  *      MSIE detection support, or if tinygif = 1, or the
340  *      URL isn't recognized as an imageurl, a lame HTML
341  *      explanation is sent instead.
342  *
343  *    - Added new feature, which permits blocking remote
344  *      script redirects and firing back a local redirect
345  *      to the browser.
346  *      The feature is conditionally compiled, i.e. it
347  *      can be disabled with --disable-fast-redirects,
348  *      plus it must be activated by a "fast-redirects"
349  *      line in the config file, has its own log level
350  *      and of course wants to be displayed by show-proxy-args
351  *      Note: Boy, all the #ifdefs in 1001 locations and
352  *      all the fumbling with configure.in and acconfig.h
353  *      were *way* more work than the feature itself :-(
354  *
355  *    - Because a generic redirect template was needed for
356  *      this, tinygif = 3 now uses the same.
357  *
358  *    - Moved GIFs, and other static HTTP response templates
359  *      to project.h
360  *
361  *    - Some minor fixes
362  *
363  *    - Removed some >400 CRs again (Jon, you really worked
364  *      a lot! ;-)
365  *
366  *    Revision 1.3  2001/05/20 01:21:20  jongfoster
367  *    Version 2.9.4 checkin.
368  *    - Merged popupfile and cookiefile, and added control over PCRS
369  *      filtering, in new "permissionsfile".
370  *    - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
371  *      file error you now get a message box (in the Win32 GUI) rather
372  *      than the program exiting with no explanation.
373  *    - Made killpopup use the PCRS MIME-type checking and HTTP-header
374  *      skipping.
375  *    - Removed tabs from "config"
376  *    - Moved duplicated url parsing code in "loaders.c" to a new funcition.
377  *    - Bumped up version number.
378  *
379  *    Revision 1.2  2001/05/17 23:02:36  oes
380  *     - Made referrer option accept 'L' as a substitute for '§'
381  *
382  *    Revision 1.1.1.1  2001/05/15 13:59:01  oes
383  *    Initial import of version 2.9.3 source tree
384  *
385  *
386  *********************************************************************/
387 \f
388
389 #include "config.h"
390
391 #ifndef _WIN32
392 #include <stdio.h>
393 #include <sys/types.h>
394 #endif
395
396 #include <stdlib.h>
397 #include <ctype.h>
398 #include <assert.h>
399 #include <string.h>
400
401 #if !defined(_WIN32) && !defined(__OS2__)
402 #include <unistd.h>
403 #endif
404
405 #include "project.h"
406 #include "list.h"
407 #include "parsers.h"
408 #include "encode.h"
409 #include "ssplit.h"
410 #include "errlog.h"
411 #include "jbsockets.h"
412 #include "miscutil.h"
413 #include "list.h"
414
415 const char parsers_h_rcs[] = PARSERS_H_VERSION;
416
417 /* Fix a problem with Solaris.  There should be no effect on other
418  * platforms.
419  * Solaris's isspace() is a macro which uses it's argument directly
420  * as an array index.  Therefore we need to make sure that high-bit
421  * characters generate +ve values, and ideally we also want to make
422  * the argument match the declared parameter type of "int".
423  *
424  * Why did they write a character function that can't take a simple
425  * "char" argument?  Doh!
426  */
427 #define ijb_isupper(__X) isupper((int)(unsigned char)(__X))
428 #define ijb_tolower(__X) tolower((int)(unsigned char)(__X))
429
430
431 const struct parsers client_patterns[] = {
432    { "referer:",                 8,    client_referrer },
433    { "user-agent:",              11,   client_uagent },
434    { "ua-",                      3,    client_ua },
435    { "from:",                    5,    client_from },
436    { "cookie:",                  7,    client_send_cookie },
437    { "x-forwarded-for:",         16,   client_x_forwarded },
438    { "Accept-Encoding:",         16,   client_accept_encoding },
439    { "TE:",                       3,   client_te },
440    { "Host:",                     5,   client_host },
441 /* { "if-modified-since:",       18,   crumble }, */
442    { "Keep-Alive:",              11,   crumble },
443    { "connection:",              11,   crumble },
444    { "proxy-connection:",        17,   crumble },
445    { "max-forwards:",            13,   client_max_forwards },
446    { NULL,                       0,    NULL }
447 };
448
449
450 const struct parsers server_patterns[] = {
451    { "HTTP",                4, server_http },
452    { "set-cookie:",        11, server_set_cookie },
453    { "connection:",        11, crumble },
454    { "Content-Type:",      13, server_content_type },
455    { "Content-Length:",    15, server_content_length },
456    { "Content-MD5:",       12, server_content_md5 },
457    { "Content-Encoding:",  17, server_content_encoding },
458    { "Transfer-Encoding:", 18, server_transfer_coding },
459    { "Keep-Alive:",        11, crumble },
460    { NULL, 0, NULL }
461 };
462
463
464 const add_header_func_ptr add_client_headers[] = {
465    client_host_adder,
466    client_cookie_adder,
467    client_x_forwarded_adder,
468    client_xtra_adder,
469    client_accept_encoding_adder,
470    connection_close_adder,
471    NULL
472 };
473
474
475 const add_header_func_ptr add_server_headers[] = {
476    connection_close_adder,
477    NULL
478 };
479
480
481 /*********************************************************************
482  *
483  * Function    :  flush_socket
484  *
485  * Description :  Write any pending "buffered" content.
486  *
487  * Parameters  :
488  *          1  :  fd = file descriptor of the socket to read
489  *          2  :  csp = Current client state (buffers, headers, etc...)
490  *
491  * Returns     :  On success, the number of bytes written are returned (zero
492  *                indicates nothing was written).  On error, -1 is returned,
493  *                and errno is set appropriately.  If count is zero and the
494  *                file descriptor refers to a regular file, 0 will be
495  *                returned without causing any other effect.  For a special
496  *                file, the results are not portable.
497  *
498  *********************************************************************/
499 int flush_socket(jb_socket fd, struct client_state *csp)
500 {
501    struct iob *iob = csp->iob;
502    int len = iob->eod - iob->cur;
503
504    if (len <= 0)
505    {
506       return(0);
507    }
508
509    if (write_socket(fd, iob->cur, (size_t)len))
510    {
511       return(-1);
512    }
513    iob->eod = iob->cur = iob->buf;
514    return(len);
515
516 }
517
518
519 /*********************************************************************
520  *
521  * Function    :  add_to_iob
522  *
523  * Description :  Add content to the buffered page, expanding the
524  *                buffer if necessary.
525  *
526  * Parameters  :
527  *          1  :  csp = Current client state (buffers, headers, etc...)
528  *          2  :  buf = holds the content to be added to the page
529  *          3  :  n = number of bytes to be added
530  *
531  * Returns     :  JB_ERR_OK on success, JB_ERR_MEMORY if out-of-memory
532  *                or buffer limit reached.
533  *
534  *********************************************************************/
535 jb_err add_to_iob(struct client_state *csp, char *buf, int n)
536 {
537    struct iob *iob = csp->iob;
538    size_t used, offset, need, want;
539    char *p;
540
541    if (n <= 0) return JB_ERR_OK;
542
543    used   = iob->eod - iob->buf;
544    offset = iob->cur - iob->buf;
545    need   = used + n + 1;
546
547    /*
548     * If the buffer can't hold the new data, extend it first.
549     * Use the next power of two if possible, else use the actual need.
550     */
551    if (need > csp->config->buffer_limit)
552    {
553       log_error(LOG_LEVEL_ERROR, "Buffer limit reached while extending the buffer (iob)");
554       return JB_ERR_MEMORY;
555    }
556
557    if (need > iob->size)
558    {
559       for (want = csp->iob->size ? csp->iob->size : 512; want <= need;) want *= 2;
560       
561       if (want <= csp->config->buffer_limit && NULL != (p = (char *)realloc(iob->buf, want)))
562       {
563          iob->size = want;
564       }
565       else if (NULL != (p = (char *)realloc(iob->buf, need)))
566       {
567          iob->size = need;
568       }
569       else
570       {
571          log_error(LOG_LEVEL_ERROR, "Extending the buffer (iob) failed: %E");
572          return JB_ERR_MEMORY;
573       }
574
575       /* Update the iob pointers */
576       iob->cur = p + offset;
577       iob->eod = p + used;
578       iob->buf = p;
579    }
580
581    /* copy the new data into the iob buffer */
582    memcpy(iob->eod, buf, (size_t)n);
583
584    /* point to the end of the data */
585    iob->eod += n;
586
587    /* null terminate == cheap insurance */
588    *iob->eod = '\0';
589
590    return JB_ERR_OK;
591
592 }
593
594
595 /*********************************************************************
596  *
597  * Function    :  get_header
598  *
599  * Description :  This (odd) routine will parse the csp->iob
600  *
601  * Parameters  :
602  *          1  :  csp = Current client state (buffers, headers, etc...)
603  *
604  * Returns     :  Any one of the following:
605  *
606  * 1) a pointer to a dynamically allocated string that contains a header line
607  * 2) NULL  indicating that the end of the header was reached
608  * 3) ""    indicating that the end of the iob was reached before finding
609  *          a complete header line.
610  *
611  *********************************************************************/
612 char *get_header(struct client_state *csp)
613 {
614    struct iob *iob;
615    char *p, *q, *ret;
616    iob = csp->iob;
617
618    if ((iob->cur == NULL)
619       || ((p = strchr(iob->cur, '\n')) == NULL))
620    {
621       return(""); /* couldn't find a complete header */
622    }
623
624    *p = '\0';
625
626    ret = strdup(iob->cur);
627    if (ret == NULL)
628    {
629       /* FIXME No way to handle error properly */
630       log_error(LOG_LEVEL_FATAL, "Out of memory in get_header()");
631    }
632
633    iob->cur = p+1;
634
635    if ((q = strchr(ret, '\r')) != NULL) *q = '\0';
636
637    /* is this a blank line (i.e. the end of the header) ? */
638    if (*ret == '\0')
639    {
640       freez(ret);
641       return(NULL);
642    }
643
644    return(ret);
645
646 }
647
648
649 /*********************************************************************
650  *
651  * Function    :  get_header_value
652  *
653  * Description :  Get the value of a given header from a chained list
654  *                of header lines or return NULL if no such header is
655  *                present in the list.
656  *
657  * Parameters  :
658  *          1  :  header_list = pointer to list
659  *          2  :  header_name = string with name of header to look for.
660  *                              Trailing colon required, capitalization
661  *                              doesn't matter.
662  *
663  * Returns     :  NULL if not found, else value of header
664  *
665  *********************************************************************/
666 char *get_header_value(const struct list *header_list, const char *header_name)
667 {
668    struct list_entry *cur_entry;
669    char *ret = NULL;
670    size_t length = 0;
671
672    assert(header_list);
673    assert(header_name);
674    length = strlen(header_name);
675
676    for (cur_entry = header_list->first; cur_entry ; cur_entry = cur_entry->next)
677    {
678       if (cur_entry->str)
679       {
680          if (!strncmpic(cur_entry->str, header_name, length))
681          {
682             /*
683              * Found: return pointer to start of value
684              */
685             ret = (char *) (cur_entry->str + length);
686             while (*ret && ijb_isspace(*ret)) ret++;
687             return(ret);
688          }
689       }
690    }
691
692    /* 
693     * Not found
694     */
695    return NULL;
696
697 }
698
699 /*********************************************************************
700  *
701  * Function    :  sed
702  *
703  * Description :  add, delete or modify lines in the HTTP header streams.
704  *                On entry, it receives a linked list of headers space
705  *                that was allocated dynamically (both the list nodes
706  *                and the header contents).
707  *
708  *                As a side effect it frees the space used by the original
709  *                header lines.
710  *
711  * Parameters  :
712  *          1  :  pats = list of patterns to match against headers
713  *          2  :  more_headers = list of functions to add more
714  *                headers (client or server)
715  *          3  :  csp = Current client state (buffers, headers, etc...)
716  *
717  * Returns     :  Single pointer to a fully formed header, or NULL
718  *                on out-of-memory error.
719  *
720  *********************************************************************/
721 char *sed(const struct parsers pats[],
722           const add_header_func_ptr more_headers[],
723           struct client_state *csp)
724 {
725    struct list_entry *p;
726    const struct parsers *v;
727    const add_header_func_ptr *f;
728    jb_err err = JB_ERR_OK;
729
730    for (v = pats; (err == JB_ERR_OK) && (v->str != NULL) ; v++)
731    {
732       for (p = csp->headers->first; (err == JB_ERR_OK) && (p != NULL) ; p = p->next)
733       {
734          /* Header crunch()ed in previous run? -> ignore */
735          if (p->str == NULL) continue;
736
737          if (v == pats) log_error(LOG_LEVEL_HEADER, "scan: %s", p->str);
738
739          if (strncmpic(p->str, v->str, v->len) == 0)
740          {
741             err = v->parser(csp, (char **)&(p->str));
742          }
743       }
744    }
745
746    /* place any additional headers on the csp->headers list */
747    for (f = more_headers; (err == JB_ERR_OK) && (*f) ; f++)
748    {
749       err = (*f)(csp);
750    }
751
752    if (err != JB_ERR_OK)
753    {
754       return NULL;
755    }
756
757    return list_to_text(csp->headers);
758 }
759
760
761 /* here begins the family of parser functions that reformat header lines */
762
763
764 /*********************************************************************
765  *
766  * Function    :  crumble
767  *
768  * Description :  This is called if a header matches a pattern to "crunch"
769  *
770  * Parameters  :
771  *          1  :  csp = Current client state (buffers, headers, etc...)
772  *          2  :  header = On input, pointer to header to modify.
773  *                On output, pointer to the modified header, or NULL
774  *                to remove the header.  This function frees the
775  *                original string if necessary.
776  *
777  * Returns     :  JB_ERR_OK on success, or
778  *                JB_ERR_MEMORY on out-of-memory error.
779  *
780  *********************************************************************/
781 jb_err crumble(struct client_state *csp, char **header)
782 {
783    log_error(LOG_LEVEL_HEADER, "crunch!");
784    freez(*header);
785    return JB_ERR_OK;
786 }
787
788
789 /*********************************************************************
790  *
791  * Function    :  server_content_type
792  *
793  * Description :  Set the content-type for filterable types (text/.*,
794  *                javascript and image/gif) unless filtering has been
795  *                forbidden (CT_TABOO) while parsing earlier headers.
796  *
797  * Parameters  :
798  *          1  :  csp = Current client state (buffers, headers, etc...)
799  *          2  :  header = On input, pointer to header to modify.
800  *                On output, pointer to the modified header, or NULL
801  *                to remove the header.  This function frees the
802  *                original string if necessary.
803  *
804  * Returns     :  JB_ERR_OK on success, or
805  *                JB_ERR_MEMORY on out-of-memory error.
806  *
807  *********************************************************************/
808 jb_err server_content_type(struct client_state *csp, char **header)
809 {
810    if (csp->content_type != CT_TABOO)
811    {
812       if (strstr(*header, " text/")
813        || strstr(*header, "application/x-javascript"))
814          csp->content_type = CT_TEXT;
815       else if (strstr(*header, " image/gif"))
816          csp->content_type = CT_GIF;
817       else
818          csp->content_type = 0;
819    }
820
821    return JB_ERR_OK;
822 }
823
824
825 /*********************************************************************
826  *
827  * Function    :  server_transfer_coding
828  *
829  * Description :  - Prohibit filtering (CT_TABOO) if transfer coding compresses
830  *                - Raise the CSP_FLAG_CHUNKED flag if coding is "chunked"
831  *                - Change from "chunked" to "identity" if body was chunked
832  *                  but has been de-chunked for filtering.
833  *
834  * Parameters  :
835  *          1  :  csp = Current client state (buffers, headers, etc...)
836  *          2  :  header = On input, pointer to header to modify.
837  *                On output, pointer to the modified header, or NULL
838  *                to remove the header.  This function frees the
839  *                original string if necessary.
840  *
841  * Returns     :  JB_ERR_OK on success, or
842  *                JB_ERR_MEMORY on out-of-memory error.
843  *
844  *********************************************************************/
845 jb_err server_transfer_coding(struct client_state *csp, char **header)
846 {
847    /*
848     * Turn off pcrs and gif filtering if body compressed
849     */
850    if (strstr(*header, "gzip") || strstr(*header, "compress") || strstr(*header, "deflate"))
851    {
852       csp->content_type = CT_TABOO;
853    }
854
855    /*
856     * Raise flag if body chunked
857     */
858    if (strstr(*header, "chunked"))
859    {
860       csp->flags |= CSP_FLAG_CHUNKED;
861
862       /*
863        * If the body was modified, it has been
864        * de-chunked first, so adjust the header:
865        */
866       if (csp->flags & CSP_FLAG_MODIFIED)
867       {
868          freez(*header);
869          *header = strdup("Transfer-Encoding: identity");
870          return (header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
871       }
872    }
873
874    return JB_ERR_OK;
875 }
876
877
878 /*********************************************************************
879  *
880  * Function    :  server_content_encoding
881  *
882  * Description :  Prohibit filtering (CT_TABOO) if content encoding compresses
883  *
884  * Parameters  :
885  *          1  :  csp = Current client state (buffers, headers, etc...)
886  *          2  :  header = On input, pointer to header to modify.
887  *                On output, pointer to the modified header, or NULL
888  *                to remove the header.  This function frees the
889  *                original string if necessary.
890  *
891  * Returns     :  JB_ERR_OK on success, or
892  *                JB_ERR_MEMORY on out-of-memory error.
893  *
894  *********************************************************************/
895 jb_err server_content_encoding(struct client_state *csp, char **header)
896 {
897    /*
898     * Turn off pcrs and gif filtering if body compressed
899     */
900    if (strstr(*header, "gzip") || strstr(*header, "compress") || strstr(*header, "deflate"))
901    {
902       csp->content_type = CT_TABOO;
903    }
904
905    return JB_ERR_OK;
906
907 }
908
909
910 /*********************************************************************
911  *
912  * Function    :  server_content_length
913  *
914  * Description :  Adjust Content-Length header if we modified
915  *                the body.
916  *
917  * Parameters  :
918  *          1  :  csp = Current client state (buffers, headers, etc...)
919  *          2  :  header = On input, pointer to header to modify.
920  *                On output, pointer to the modified header, or NULL
921  *                to remove the header.  This function frees the
922  *                original string if necessary.
923  *
924  * Returns     :  JB_ERR_OK on success, or
925  *                JB_ERR_MEMORY on out-of-memory error.
926  *
927  *********************************************************************/
928 jb_err server_content_length(struct client_state *csp, char **header)
929 {
930    if (csp->content_length != 0) /* Content length has been modified */
931    {
932       freez(*header);
933       *header = (char *) zalloc(100);
934       if (*header == NULL)
935       {
936          return JB_ERR_MEMORY;
937       }
938
939       sprintf(*header, "Content-Length: %d", (int) csp->content_length);
940
941       log_error(LOG_LEVEL_HEADER, "Adjust Content-Length to %d", (int) csp->content_length);
942    }
943
944    return JB_ERR_OK;
945 }
946
947
948 /*********************************************************************
949  *
950  * Function    :  server_content_md5
951  *
952  * Description :  Crumble any Content-MD5 headers if the document was
953  *                modified. FIXME: Should we re-compute instead?
954  *
955  * Parameters  :
956  *          1  :  csp = Current client state (buffers, headers, etc...)
957  *          2  :  header = On input, pointer to header to modify.
958  *                On output, pointer to the modified header, or NULL
959  *                to remove the header.  This function frees the
960  *                original string if necessary.
961  *
962  * Returns     :  JB_ERR_OK on success, or
963  *                JB_ERR_MEMORY on out-of-memory error.
964  *
965  *********************************************************************/
966 jb_err server_content_md5(struct client_state *csp, char **header)
967 {
968    if (csp->flags & CSP_FLAG_MODIFIED)
969    {
970       log_error(LOG_LEVEL_HEADER, "Crunching Content-MD5");
971       freez(*header);
972    }
973
974    return JB_ERR_OK;
975 }
976
977
978 /*********************************************************************
979  *
980  * Function    :  client_accept_encoding
981  *
982  * Description :  Rewrite the client's Accept-Encoding header so that
983  *                if doesn't allow compression, if the action applies.
984  *                Note: For HTTP/1.0 the absence of the header is enough.
985  *
986  * Parameters  :
987  *          1  :  csp = Current client state (buffers, headers, etc...)
988  *          2  :  header = On input, pointer to header to modify.
989  *                On output, pointer to the modified header, or NULL
990  *                to remove the header.  This function frees the
991  *                original string if necessary.
992  *
993  * Returns     :  JB_ERR_OK on success, or
994  *                JB_ERR_MEMORY on out-of-memory error.
995  *
996  *********************************************************************/
997 jb_err client_accept_encoding(struct client_state *csp, char **header)
998 {
999    if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
1000    {
1001       log_error(LOG_LEVEL_HEADER, "Supressed offer to compress content");
1002
1003       freez(*header);
1004       if (!strcmpic(csp->http->ver, "HTTP/1.1"))
1005       {
1006          *header = strdup("Accept-Encoding: identity;q=1.0, *;q=0");
1007          if (*header == NULL)
1008          {
1009             return JB_ERR_MEMORY;
1010          }
1011       }
1012    }
1013
1014    return JB_ERR_OK;
1015 }
1016
1017
1018 /*********************************************************************
1019  *
1020  * Function    :  client_te
1021  *
1022  * Description :  Rewrite the client's TE header so that
1023  *                if doesn't allow compression, if the action applies.
1024  *
1025  * Parameters  :
1026  *          1  :  csp = Current client state (buffers, headers, etc...)
1027  *          2  :  header = On input, pointer to header to modify.
1028  *                On output, pointer to the modified header, or NULL
1029  *                to remove the header.  This function frees the
1030  *                original string if necessary.
1031  *
1032  * Returns     :  JB_ERR_OK on success, or
1033  *                JB_ERR_MEMORY on out-of-memory error.
1034  *
1035  *********************************************************************/
1036 jb_err client_te(struct client_state *csp, char **header)
1037 {
1038    if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
1039    {
1040       freez(*header);
1041       log_error(LOG_LEVEL_HEADER, "Supressed offer to compress transfer");
1042    }
1043
1044    return JB_ERR_OK;
1045 }
1046
1047 /*********************************************************************
1048  *
1049  * Function    :  client_referrer
1050  *
1051  * Description :  Handle the "referer" config setting properly.
1052  *                Called from `sed'.
1053  *
1054  * Parameters  :
1055  *          1  :  csp = Current client state (buffers, headers, etc...)
1056  *          2  :  header = On input, pointer to header to modify.
1057  *                On output, pointer to the modified header, or NULL
1058  *                to remove the header.  This function frees the
1059  *                original string if necessary.
1060  *
1061  * Returns     :  JB_ERR_OK on success, or
1062  *                JB_ERR_MEMORY on out-of-memory error.
1063  *
1064  *********************************************************************/
1065 jb_err client_referrer(struct client_state *csp, char **header)
1066 {
1067    const char *newval;
1068
1069 #ifdef FEATURE_FORCE_LOAD
1070    /* Since the referrer can include the prefix even
1071     * even if the request itself is non-forced, we must
1072     * clean it unconditionally
1073     */
1074    strclean(*header, FORCE_PREFIX);
1075 #endif /* def FEATURE_FORCE_LOAD */
1076
1077    /*
1078     * Are we sending referer?
1079     */
1080    if ((csp->action->flags & ACTION_HIDE_REFERER) == 0)
1081    {
1082       return JB_ERR_OK;
1083    }
1084
1085    freez(*header);
1086
1087    newval = csp->action->string[ACTION_STRING_REFERER];
1088
1089    if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
1090    {
1091       /*
1092        * Blocking referer
1093        */
1094       log_error(LOG_LEVEL_HEADER, "crunch!");
1095       return JB_ERR_OK;
1096    }
1097    else if (0 == strncmpic(newval, "http://", 7))
1098    {
1099       /*
1100        * We have a specific (fixed) referer we want to send.
1101        */
1102       log_error(LOG_LEVEL_HEADER, "modified");
1103
1104       *header = strdup("Referer: ");
1105       string_append(header, newval);
1106
1107       return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
1108    }
1109    else
1110    {
1111       /*
1112        * Forge a referer as http://[hostname:port of REQUEST]/
1113        * to fool stupid checks for in-site links
1114        */
1115       if (0 != strcmpic(newval, "forge"))
1116       {
1117          /*
1118           * Invalid choice - but forge is probably the best default.
1119           */
1120          log_error(LOG_LEVEL_ERROR, "Bad parameter: +referer{%s}", newval);
1121       }
1122
1123       *header = strdup("Referer: http://");
1124       string_append(header, csp->http->hostport);
1125       string_append(header, "/");
1126       log_error(LOG_LEVEL_HEADER, "crunch+forge to %s", *header);
1127       
1128       return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
1129    }
1130 }
1131
1132
1133 /*********************************************************************
1134  *
1135  * Function    :  client_uagent
1136  *
1137  * Description :  Handle the "user-agent" config setting properly
1138  *                and remember its original value to enable browser
1139  *                bug workarounds. Called from `sed'.
1140  *
1141  * Parameters  :
1142  *          1  :  csp = Current client state (buffers, headers, etc...)
1143  *          2  :  header = On input, pointer to header to modify.
1144  *                On output, pointer to the modified header, or NULL
1145  *                to remove the header.  This function frees the
1146  *                original string if necessary.
1147  *
1148  * Returns     :  JB_ERR_OK on success, or
1149  *                JB_ERR_MEMORY on out-of-memory error.
1150  *
1151  *********************************************************************/
1152 jb_err client_uagent(struct client_state *csp, char **header)
1153 {
1154    const char *newval;
1155
1156    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) == 0)
1157    {
1158       return JB_ERR_OK;
1159    }
1160
1161    newval = csp->action->string[ACTION_STRING_USER_AGENT];
1162    if (newval == NULL)
1163    {
1164       return JB_ERR_OK;
1165    }
1166
1167    log_error(LOG_LEVEL_HEADER, "modified");
1168
1169    freez(*header);
1170    *header = strdup("User-Agent: ");
1171    string_append(header, newval);
1172
1173    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
1174 }
1175
1176
1177 /*********************************************************************
1178  *
1179  * Function    :  client_ua
1180  *
1181  * Description :  Handle "ua-" headers properly.  Called from `sed'.
1182  *
1183  * Parameters  :
1184  *          1  :  csp = Current client state (buffers, headers, etc...)
1185  *          2  :  header = On input, pointer to header to modify.
1186  *                On output, pointer to the modified header, or NULL
1187  *                to remove the header.  This function frees the
1188  *                original string if necessary.
1189  *
1190  * Returns     :  JB_ERR_OK on success, or
1191  *                JB_ERR_MEMORY on out-of-memory error.
1192  *
1193  *********************************************************************/
1194 jb_err client_ua(struct client_state *csp, char **header)
1195 {
1196    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) != 0)
1197    {
1198       log_error(LOG_LEVEL_HEADER, "crunch!");
1199       freez(*header);
1200    }
1201
1202    return JB_ERR_OK;
1203 }
1204
1205
1206 /*********************************************************************
1207  *
1208  * Function    :  client_from
1209  *
1210  * Description :  Handle the "from" config setting properly.
1211  *                Called from `sed'.
1212  *
1213  * Parameters  :
1214  *          1  :  csp = Current client state (buffers, headers, etc...)
1215  *          2  :  header = On input, pointer to header to modify.
1216  *                On output, pointer to the modified header, or NULL
1217  *                to remove the header.  This function frees the
1218  *                original string if necessary.
1219  *
1220  * Returns     :  JB_ERR_OK on success, or
1221  *                JB_ERR_MEMORY on out-of-memory error.
1222  *
1223  *********************************************************************/
1224 jb_err client_from(struct client_state *csp, char **header)
1225 {
1226    const char *newval;
1227
1228    if ((csp->action->flags & ACTION_HIDE_FROM) == 0)
1229    {
1230       return JB_ERR_OK;
1231    }
1232
1233    freez(*header);
1234
1235    newval = csp->action->string[ACTION_STRING_FROM];
1236
1237    /*
1238     * Are we blocking the e-mail address?
1239     */
1240    if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
1241    {
1242       log_error(LOG_LEVEL_HEADER, "crunch!");
1243       return JB_ERR_OK;
1244    }
1245
1246    log_error(LOG_LEVEL_HEADER, " modified");
1247
1248    *header = strdup("From: ");
1249    string_append(header, newval);
1250
1251    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
1252 }
1253
1254
1255 /*********************************************************************
1256  *
1257  * Function    :  client_send_cookie
1258  *
1259  * Description :  Handle the "cookie" header properly.  Called from `sed'.
1260  *                If cookie is accepted, add it to the cookie_list,
1261  *                else we crunch it.  Mmmmmmmmmmm ... cookie ......
1262  *
1263  * Parameters  :
1264  *          1  :  csp = Current client state (buffers, headers, etc...)
1265  *          2  :  header = On input, pointer to header to modify.
1266  *                On output, pointer to the modified header, or NULL
1267  *                to remove the header.  This function frees the
1268  *                original string if necessary.
1269  *
1270  * Returns     :  JB_ERR_OK on success, or
1271  *                JB_ERR_MEMORY on out-of-memory error.
1272  *
1273  *********************************************************************/
1274 jb_err client_send_cookie(struct client_state *csp, char **header)
1275 {
1276    jb_err result = JB_ERR_OK;
1277
1278    if ((csp->action->flags & ACTION_NO_COOKIE_READ) == 0)
1279    {
1280       /* strlen("cookie: ") == 8 */
1281       result = enlist(csp->cookie_list, *header + 8);
1282    }
1283    else
1284    {
1285       log_error(LOG_LEVEL_HEADER, " crunch!");
1286    }
1287
1288    /*
1289     * Always remove the cookie here.  The cookie header
1290     * will be sent at the end of the header.
1291     */
1292    freez(*header);
1293
1294    return result;
1295 }
1296
1297
1298 /*********************************************************************
1299  *
1300  * Function    :  client_x_forwarded
1301  *
1302  * Description :  Handle the "x-forwarded-for" config setting properly,
1303  *                also used in the add_client_headers list.  Called from `sed'.
1304  *
1305  * Parameters  :
1306  *          1  :  csp = Current client state (buffers, headers, etc...)
1307  *          2  :  header = On input, pointer to header to modify.
1308  *                On output, pointer to the modified header, or NULL
1309  *                to remove the header.  This function frees the
1310  *                original string if necessary.
1311  *
1312  * Returns     :  JB_ERR_OK on success, or
1313  *                JB_ERR_MEMORY on out-of-memory error.
1314  *
1315  *********************************************************************/
1316 jb_err client_x_forwarded(struct client_state *csp, char **header)
1317 {
1318    if ((csp->action->flags & ACTION_HIDE_FORWARDED) == 0)
1319    {
1320       /* Save it so we can re-add it later */
1321       freez(csp->x_forwarded);
1322       csp->x_forwarded = *header;
1323
1324       /*
1325        * Always set *header = NULL, since this information
1326        * will be sent at the end of the header.
1327        */
1328       *header = NULL;
1329    }
1330    else
1331    {
1332       freez(*header);
1333       log_error(LOG_LEVEL_HEADER, " crunch!");
1334    }
1335
1336    return JB_ERR_OK;
1337 }
1338
1339
1340 /*********************************************************************
1341  *
1342  * Function    :  client_max_forwards
1343  *
1344  * Description :  If the HTTP method is OPTIONS or TRACE, subtract one
1345  *                from the value of the Max-Forwards header field.
1346  *
1347  * Parameters  :
1348  *          1  :  csp = Current client state (buffers, headers, etc...)
1349  *          2  :  header = On input, pointer to header to modify.
1350  *                On output, pointer to the modified header, or NULL
1351  *                to remove the header.  This function frees the
1352  *                original string if necessary.
1353  *
1354  * Returns     :  JB_ERR_OK on success, or
1355  *                JB_ERR_MEMORY on out-of-memory error.
1356  *
1357  *********************************************************************/
1358 jb_err client_max_forwards(struct client_state *csp, char **header)
1359 {
1360    unsigned int max_forwards;
1361
1362    if ((0 == strcmpic(csp->http->gpc, "trace"))
1363       || (0 == strcmpic(csp->http->gpc, "options")))
1364    {
1365       if (1 == sscanf(*header, "Max-Forwards: %u", &max_forwards))
1366       {
1367          if (max_forwards-- >= 1)
1368          {
1369             sprintf(*header, "Max-Forwards: %u", max_forwards);
1370             log_error(LOG_LEVEL_HEADER, "Max forwards of %s request now %d", csp->http->gpc, max_forwards);
1371          }
1372          else
1373          {
1374             log_error(LOG_LEVEL_ERROR, "Non-intercepted %s request with Max-Forwards zero!", csp->http->gpc);
1375          }
1376       }
1377    }
1378
1379    return JB_ERR_OK;
1380 }
1381
1382
1383 /*********************************************************************
1384  *
1385  * Function    :  client_host
1386  *
1387  * Description :  If the request URI did not contain host and
1388  *                port information, parse and evaluate the Host
1389  *                header field.
1390  *
1391  * Parameters  :
1392  *          1  :  csp = Current client state (buffers, headers, etc...)
1393  *          2  :  header = On input, pointer to header to modify.
1394  *                On output, pointer to the modified header, or NULL
1395  *                to remove the header.  This function frees the
1396  *                original string if necessary.
1397  *
1398  * Returns     :  JB_ERR_OK on success, or
1399  *                JB_ERR_MEMORY on out-of-memory error.
1400  *
1401  *********************************************************************/
1402 jb_err client_host(struct client_state *csp, char **header)
1403 {
1404    char *p, *q;
1405
1406    if (!csp->http->hostport || (*csp->http->hostport == '*') ||  
1407        *csp->http->hostport == ' ' || *csp->http->hostport == '\0')
1408    {
1409       
1410       if (NULL == (p = strdup((*header)+6)))
1411       {
1412          return JB_ERR_MEMORY;
1413       }
1414       chomp(p);
1415       if (NULL == (q = strdup(p)))
1416       {
1417          freez(p);
1418          return JB_ERR_MEMORY;
1419       }
1420
1421       freez(csp->http->hostport);
1422       csp->http->hostport = p;
1423       freez(csp->http->host);
1424       csp->http->host = q;
1425       q = strchr(csp->http->host, ':');
1426       if (q != NULL)
1427       {
1428          /* Terminate hostname and evaluate port string */
1429          *q++ = '\0';
1430          csp->http->port = atoi(q);
1431       }
1432       else
1433       {
1434          csp->http->port = csp->http->ssl ? 443 : 80;
1435       }
1436
1437       log_error(LOG_LEVEL_HEADER, "New host and port from Host field: %s = %s:%d",
1438                 csp->http->hostport, csp->http->host, csp->http->port);
1439    }
1440
1441    return JB_ERR_OK;
1442 }
1443
1444
1445 /* the following functions add headers directly to the header list */
1446
1447 /*********************************************************************
1448  *
1449  * Function    :  client_host_adder
1450  *
1451  * Description :  Adds the Host: header field if it is missing.
1452  *                Called from `sed'.
1453  *
1454  * Parameters  :
1455  *          1  :  csp = Current client state (buffers, headers, etc...)
1456  *
1457  * Returns     :  JB_ERR_OK on success, or
1458  *                JB_ERR_MEMORY on out-of-memory error.
1459  *
1460  *********************************************************************/
1461 jb_err client_host_adder(struct client_state *csp)
1462 {
1463    char *p;
1464    jb_err err;
1465
1466    if ( !csp->http->hostport || !*(csp->http->hostport))
1467    {
1468       return JB_ERR_OK;
1469    }
1470
1471    /*
1472     * remove 'user:pass@' from 'proto://user:pass@host'
1473     */
1474    if ( (p = strchr( csp->http->hostport, '@')) != NULL )
1475    {
1476       p++;
1477    }
1478    else
1479    {
1480       p = csp->http->hostport;
1481    }
1482
1483    log_error(LOG_LEVEL_HEADER, "addh-unique: Host: %s", p);
1484    err = enlist_unique_header(csp->headers, "Host", p);
1485    return err;
1486
1487 }
1488
1489
1490 /*********************************************************************
1491  *
1492  * Function    :  client_cookie_adder
1493  *
1494  * Description :  Used in the add_client_headers list.  Called from `sed'.
1495  *
1496  * Parameters  :
1497  *          1  :  csp = Current client state (buffers, headers, etc...)
1498  *
1499  * Returns     :  JB_ERR_OK on success, or
1500  *                JB_ERR_MEMORY on out-of-memory error.
1501  *
1502  *********************************************************************/
1503 jb_err client_cookie_adder(struct client_state *csp)
1504 {
1505    struct list_entry *lst;
1506    char *tmp;
1507    struct list_entry *list1 = csp->cookie_list->first;
1508    struct list_entry *list2 = csp->action->multi[ACTION_MULTI_WAFER]->first;
1509    int first_cookie = 1;
1510    jb_err err;
1511
1512    if ((list1 == NULL) && (list2 == NULL))
1513    {
1514       /* Nothing to do */
1515       return JB_ERR_OK;
1516    }
1517
1518    tmp = strdup("Cookie: ");
1519
1520    for (lst = list1; lst ; lst = lst->next)
1521    {
1522       if (first_cookie)
1523       {
1524          first_cookie = 0;
1525       }
1526       else
1527       {
1528          string_append(&tmp, "; ");
1529       }
1530       string_append(&tmp, lst->str);
1531    }
1532
1533    for (lst = list2;  lst ; lst = lst->next)
1534    {
1535       if (first_cookie)
1536       {
1537          first_cookie = 0;
1538       }
1539       else
1540       {
1541          string_append(&tmp, "; ");
1542       }
1543       string_join(&tmp, cookie_encode(lst->str));
1544    }
1545
1546    if (tmp == NULL)
1547    {
1548       return JB_ERR_MEMORY;
1549    }
1550
1551    log_error(LOG_LEVEL_HEADER, "addh: %s", tmp);
1552    err = enlist(csp->headers, tmp);
1553    free(tmp);
1554    return err;
1555 }
1556
1557
1558 /*********************************************************************
1559  *
1560  * Function    :  client_accept_encoding_adder
1561  *
1562  * Description :  Add an Accept-Encoding header to the client's request
1563  *                that disables compression if the action applies, and
1564  *                the header is not already there. Called from `sed'.
1565  *                Note: For HTTP/1.0, the absence of the header is enough.
1566  *
1567  * Parameters  :
1568  *          1  :  csp = Current client state (buffers, headers, etc...)
1569  *
1570  * Returns     :  JB_ERR_OK on success, or
1571  *                JB_ERR_MEMORY on out-of-memory error.
1572  *
1573  *********************************************************************/
1574 jb_err client_accept_encoding_adder(struct client_state *csp)
1575 {
1576    if (   ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
1577        && (!strcmpic(csp->http->ver, "HTTP/1.1")) )
1578    {
1579       return enlist_unique(csp->headers, "Accept-Encoding: identity;q=1.0, *;q=0", 16);
1580    }
1581
1582    return JB_ERR_OK;
1583 }
1584
1585
1586 /*********************************************************************
1587  *
1588  * Function    :  client_xtra_adder
1589  *
1590  * Description :  Used in the add_client_headers list.  Called from `sed'.
1591  *
1592  * Parameters  :
1593  *          1  :  csp = Current client state (buffers, headers, etc...)
1594  *
1595  * Returns     :  JB_ERR_OK on success, or
1596  *                JB_ERR_MEMORY on out-of-memory error.
1597  *
1598  *********************************************************************/
1599 jb_err client_xtra_adder(struct client_state *csp)
1600 {
1601    struct list_entry *lst;
1602    jb_err err;
1603
1604    for (lst = csp->action->multi[ACTION_MULTI_ADD_HEADER]->first;
1605         lst ; lst = lst->next)
1606    {
1607       log_error(LOG_LEVEL_HEADER, "addh: %s", lst->str);
1608       err = enlist(csp->headers, lst->str);
1609       if (err)
1610       {
1611          return err;
1612       }
1613
1614    }
1615
1616    return JB_ERR_OK;
1617 }
1618
1619
1620 /*********************************************************************
1621  *
1622  * Function    :  client_x_forwarded_adder
1623  *
1624  * Description :  Used in the add_client_headers list.  Called from `sed'.
1625  *
1626  * Parameters  :
1627  *          1  :  csp = Current client state (buffers, headers, etc...)
1628  *
1629  * Returns     :  JB_ERR_OK on success, or
1630  *                JB_ERR_MEMORY on out-of-memory error.
1631  *
1632  *********************************************************************/
1633 jb_err client_x_forwarded_adder(struct client_state *csp)
1634 {
1635    char *p = NULL;
1636    jb_err err;
1637
1638    if ((csp->action->flags & ACTION_HIDE_FORWARDED) != 0)
1639    {
1640       return JB_ERR_OK;
1641    }
1642
1643    if (csp->x_forwarded)
1644    {
1645       p = strdup(csp->x_forwarded);
1646       string_append(&p, ", ");
1647    }
1648    else
1649    {
1650       p = strdup("X-Forwarded-For: ");
1651    }
1652    string_append(&p, csp->ip_addr_str);
1653
1654    if (p == NULL)
1655    {
1656       return JB_ERR_MEMORY;
1657    }
1658
1659    log_error(LOG_LEVEL_HEADER, "addh: %s", p);
1660    err = enlist(csp->headers, p);
1661    free(p);
1662
1663    return err;
1664 }
1665
1666
1667 /*********************************************************************
1668  *
1669  * Function    :  connection_close_adder
1670  *
1671  * Description :  Adds a "Connection: close" header to csp->headers
1672  *                as a temporary fix for the needed but missing HTTP/1.1
1673  *                support. Called from `sed'.
1674  *                FIXME: This whole function shouldn't be neccessary!
1675  *
1676  * Parameters  :
1677  *          1  :  csp = Current client state (buffers, headers, etc...)
1678  *
1679  * Returns     :  JB_ERR_OK on success, or
1680  *                JB_ERR_MEMORY on out-of-memory error.
1681  *
1682  *********************************************************************/
1683 jb_err connection_close_adder(struct client_state *csp)
1684 {
1685    return enlist(csp->headers, "Connection: close");
1686 }
1687
1688
1689 /*********************************************************************
1690  *
1691  * Function    :  server_http
1692  *
1693  * Description :  - Save the HTTP Status into csp->http->status
1694  *                - Set CT_TABOO to prevent filtering if the answer
1695  *                  is a partial range (HTTP status 206)
1696  *                - Rewrite HTTP/1.1 answers to HTTP/1.0 if +downgrade
1697  *                  action applies.
1698  *
1699  * Parameters  :
1700  *          1  :  csp = Current client state (buffers, headers, etc...)
1701  *          2  :  header = On input, pointer to header to modify.
1702  *                On output, pointer to the modified header, or NULL
1703  *                to remove the header.  This function frees the
1704  *                original string if necessary.
1705  *
1706  * Returns     :  JB_ERR_OK on success, or
1707  *                JB_ERR_MEMORY on out-of-memory error.
1708  *
1709  *********************************************************************/
1710 jb_err server_http(struct client_state *csp, char **header)
1711 {
1712    sscanf(*header, "HTTP/%*d.%*d %d", &(csp->http->status));
1713    if (csp->http->status == 206)
1714    {
1715       csp->content_type = CT_TABOO;
1716    }
1717
1718    if ((csp->action->flags & ACTION_DOWNGRADE) != 0)
1719    {
1720       (*header)[7] = '0';
1721       log_error(LOG_LEVEL_HEADER, "Downgraded answer to HTTP/1.0");
1722    }
1723
1724    return JB_ERR_OK;
1725 }
1726
1727
1728 /*********************************************************************
1729  *
1730  * Function    :  server_set_cookie
1731  *
1732  * Description :  Handle the server "cookie" header properly.
1733  *                Log cookie to the jar file.  Then "crunch" it,
1734  *                or accept it.  Called from `sed'.
1735  *
1736  * Parameters  :
1737  *          1  :  csp = Current client state (buffers, headers, etc...)
1738  *          2  :  header = On input, pointer to header to modify.
1739  *                On output, pointer to the modified header, or NULL
1740  *                to remove the header.  This function frees the
1741  *                original string if necessary.
1742  *
1743  * Returns     :  JB_ERR_OK on success, or
1744  *                JB_ERR_MEMORY on out-of-memory error.
1745  *
1746  *********************************************************************/
1747 jb_err server_set_cookie(struct client_state *csp, char **header)
1748 {
1749 #ifdef FEATURE_COOKIE_JAR
1750    if (csp->config->jar)
1751    {
1752       /*
1753        * Write timestamp into outbuf.
1754        *
1755        * Complex because not all OSs have tm_gmtoff or
1756        * the %z field in strftime()
1757        */
1758       char tempbuf[ BUFFER_SIZE ];
1759       time_t now; 
1760       struct tm tm_now; 
1761       time (&now); 
1762 #ifdef HAVE_LOCALTIME_R
1763       tm_now = *localtime_r(&now, &tm_now);
1764 #else
1765       tm_now = *localtime (&now); 
1766 #endif
1767       strftime(tempbuf, BUFFER_SIZE-6, "%b %d %H:%M:%S ", &tm_now); 
1768
1769       /* strlen("set-cookie: ") = 12 */
1770       fprintf(csp->config->jar, "%s %s\t%s\n", tempbuf, csp->http->host, *header + 12);
1771    }
1772 #endif /* def FEATURE_COOKIE_JAR */
1773
1774    if ((csp->action->flags & ACTION_NO_COOKIE_SET) != 0)
1775    {
1776       return crumble(csp, header);
1777    }
1778    else if ((csp->action->flags & ACTION_NO_COOKIE_KEEP) != 0)
1779    {
1780       /* Flag whether or not to log a message */
1781       int changed = 0;
1782
1783       /* A variable to store the tag we're working on */
1784       char *cur_tag;
1785
1786       /* Skip "Set-Cookie:" (11 characters) in header */
1787       cur_tag = *header + 11;
1788
1789       /* skip whitespace between "Set-Cookie:" and value */
1790       while (*cur_tag && ijb_isspace(*cur_tag))
1791       {
1792          cur_tag++;
1793       }
1794
1795       /* Loop through each tag in the cookie */
1796       while (*cur_tag)
1797       {
1798          /* Find next tag */
1799          char *next_tag = strchr(cur_tag, ';');
1800          if (next_tag != NULL)
1801          {
1802             /* Skip the ';' character itself */
1803             next_tag++;
1804
1805             /* skip whitespace ";" and start of tag */
1806             while (*next_tag && ijb_isspace(*next_tag))
1807             {
1808                next_tag++;
1809             }
1810          }
1811          else
1812          {
1813             /* "Next tag" is the end of the string */
1814             next_tag = cur_tag + strlen(cur_tag);
1815          }
1816
1817          /* Is this the "Expires" tag? */
1818          if (strncmpic(cur_tag, "expires=", 8) == 0)
1819          {
1820             /* Delete the tag by copying the rest of the string over it.
1821              * (Note that we cannot just use "strcpy(cur_tag, next_tag)",
1822              * since the behaviour of strcpy is undefined for overlapping
1823              * strings.)
1824              */
1825             memmove(cur_tag, next_tag, strlen(next_tag) + 1);
1826
1827             /* That changed the header, need to issue a log message */
1828             changed = 1;
1829
1830             /* Note that the next tag has now been moved to *cur_tag,
1831              * so we do not need to update the cur_tag pointer.
1832              */
1833          }
1834          else
1835          {
1836             /* Move on to next cookie tag */
1837             cur_tag = next_tag;
1838          }
1839       }
1840
1841       if (changed)
1842       {
1843          log_error(LOG_LEVEL_HEADER, "Changed cookie to a temporary one.");
1844       }
1845    }
1846
1847    return JB_ERR_OK;
1848 }
1849
1850
1851 #ifdef FEATURE_FORCE_LOAD
1852 /*********************************************************************
1853  *
1854  * Function    :  strclean
1855  *
1856  * Description :  In-Situ-Eliminate all occurances of substring in
1857  *                string
1858  *
1859  * Parameters  :
1860  *          1  :  string = string to clean
1861  *          2  :  substring = substring to eliminate
1862  *
1863  * Returns     :  Number of eliminations
1864  *
1865  *********************************************************************/
1866 int strclean(const char *string, const char *substring)
1867 {
1868    int hits = 0, len = strlen(substring);
1869    char *pos, *p;
1870
1871    while((pos = strstr(string, substring)) != NULL)
1872    {
1873       p = pos + len;
1874       do
1875       {
1876          *(p - len) = *p;
1877       }
1878       while (*p++ != '\0');
1879
1880       hits++;
1881    }
1882
1883    return(hits);
1884 }
1885 #endif /* def FEATURE_FORCE_LOAD */
1886
1887
1888 /*
1889   Local Variables:
1890   tab-width: 3
1891   end:
1892 */