Added optional left-anchoring to domaincmp
[privoxy.git] / project.h
1 #ifndef _PROJECT_H
2 #define _PROJECT_H
3 #define PROJECT_H_VERSION "$Id: project.h,v 1.9 2001/05/31 17:32:31 oes Exp $"
4 /*********************************************************************
5  *
6  * File        :  $Source: /cvsroot/ijbswa/current/project.h,v $
7  *
8  * Purpose     :  Defines data structures which are widely used in the
9  *                project.  Does not define any variables or functions
10  *                (though it does declare some macros).
11  *
12  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
13  *                IJBSWA team.  http://ijbswa.sourceforge.net
14  *
15  *                Based on the Internet Junkbuster originally written
16  *                by and Copyright (C) 1997 Anonymous Coders and 
17  *                Junkbusters Corporation.  http://www.junkbusters.com
18  *
19  *                This program is free software; you can redistribute it 
20  *                and/or modify it under the terms of the GNU General
21  *                Public License as published by the Free Software
22  *                Foundation; either version 2 of the License, or (at
23  *                your option) any later version.
24  *
25  *                This program is distributed in the hope that it will
26  *                be useful, but WITHOUT ANY WARRANTY; without even the
27  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
28  *                PARTICULAR PURPOSE.  See the GNU General Public
29  *                License for more details.
30  *
31  *                The GNU General Public License should be included with
32  *                this file.  If not, you can view it at
33  *                http://www.gnu.org/copyleft/gpl.html
34  *                or write to the Free Software Foundation, Inc., 59
35  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
36  *
37  * Revisions   :
38  *    $Log: project.h,v $
39  *    Revision 1.9  2001/05/31 17:32:31  oes
40  *
41  *     - Enhanced domain part globbing with infix and prefix asterisk
42  *       matching and optional unanchored operation
43  *
44  *    Revision 1.8  2001/05/29 20:09:15  joergs
45  *    HTTP_REDIRECT_TEMPLATE fixed.
46  *
47  *    Revision 1.7  2001/05/29 09:50:24  jongfoster
48  *    Unified blocklist/imagelist/actionslist.
49  *    File format is still under discussion, but the internal changes
50  *    are (mostly) done.
51  *
52  *    Also modified interceptor behaviour:
53  *    - We now intercept all URLs beginning with one of the following
54  *      prefixes (and *only* these prefixes):
55  *        * http://i.j.b/
56  *        * http://ijbswa.sf.net/config/
57  *        * http://ijbswa.sourceforge.net/config/
58  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
59  *    - Internal changes so that intercepted and fast redirect pages
60  *      are not replaced with an image.
61  *    - Interceptors now have the option to send a binary page direct
62  *      to the client. (i.e. ijb-send-banner uses this)
63  *    - Implemented show-url-info interceptor.  (Which is why I needed
64  *      the above interceptors changes - a typical URL is
65  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
66  *      The previous mechanism would not have intercepted that, and
67  *      if it had been intercepted then it then it would have replaced
68  *      it with an image.)
69  *
70  *    Revision 1.6  2001/05/27 22:17:04  oes
71  *
72  *    - re_process_buffer no longer writes the modified buffer
73  *      to the client, which was very ugly. It now returns the
74  *      buffer, which it is then written by chat.
75  *
76  *    - content_length now adjusts the Content-Length: header
77  *      for modified documents rather than crunch()ing it.
78  *      (Length info in csp->content_length, which is 0 for
79  *      unmodified documents)
80  *
81  *    - For this to work, sed() is called twice when filtering.
82  *
83  *    Revision 1.5  2001/05/26 00:28:36  jongfoster
84  *    Automatic reloading of config file.
85  *    Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
86  *    Most of the global variables have been moved to a new
87  *    struct configuration_spec, accessed through csp->config->globalname
88  *    Most of the globals remaining are used by the Win32 GUI.
89  *
90  *    Revision 1.4  2001/05/22 18:46:04  oes
91  *
92  *    - Enabled filtering banners by size rather than URL
93  *      by adding patterns that replace all standard banner
94  *      sizes with the "Junkbuster" gif to the re_filterfile
95  *
96  *    - Enabled filtering WebBugs by providing a pattern
97  *      which kills all 1x1 images
98  *
99  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
100  *      which is selected by the (nonstandard and therefore
101  *      capital) letter 'U' in the option string.
102  *      It causes the quantifiers to be ungreedy by default.
103  *      Appending a ? turns back to greedy (!).
104  *
105  *    - Added a new interceptor ijb-send-banner, which
106  *      sends back the "Junkbuster" gif. Without imagelist or
107  *      MSIE detection support, or if tinygif = 1, or the
108  *      URL isn't recognized as an imageurl, a lame HTML
109  *      explanation is sent instead.
110  *
111  *    - Added new feature, which permits blocking remote
112  *      script redirects and firing back a local redirect
113  *      to the browser.
114  *      The feature is conditionally compiled, i.e. it
115  *      can be disabled with --disable-fast-redirects,
116  *      plus it must be activated by a "fast-redirects"
117  *      line in the config file, has its own log level
118  *      and of course wants to be displayed by show-proxy-args
119  *      Note: Boy, all the #ifdefs in 1001 locations and
120  *      all the fumbling with configure.in and acconfig.h
121  *      were *way* more work than the feature itself :-(
122  *
123  *    - Because a generic redirect template was needed for
124  *      this, tinygif = 3 now uses the same.
125  *
126  *    - Moved GIFs, and other static HTTP response templates
127  *      to project.h
128  *
129  *    - Some minor fixes
130  *
131  *    - Removed some >400 CRs again (Jon, you really worked
132  *      a lot! ;-)
133  *
134  *    Revision 1.3  2001/05/20 01:21:20  jongfoster
135  *    Version 2.9.4 checkin.
136  *    - Merged popupfile and cookiefile, and added control over PCRS
137  *      filtering, in new "actionsfile".
138  *    - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
139  *      file error you now get a message box (in the Win32 GUI) rather
140  *      than the program exiting with no explanation.
141  *    - Made killpopup use the PCRS MIME-type checking and HTTP-header
142  *      skipping.
143  *    - Removed tabs from "config"
144  *    - Moved duplicated url parsing code in "loaders.c" to a new funcition.
145  *    - Bumped up version number.
146  *
147  *    Revision 1.2  2001/05/17 23:01:01  oes
148  *     - Cleaned CRLF's from the sources and related files
149  *
150  *    Revision 1.1.1.1  2001/05/15 13:59:03  oes
151  *    Initial import of version 2.9.3 source tree
152  *
153  *
154  *********************************************************************/
155 \f
156
157 /* Declare struct FILE for vars and funcs. */
158 #include <stdio.h>
159
160 /* Need time_t for file_list */
161 #include <time.h>
162
163 /*
164  * Include appropriate regular expression libraries.
165  *
166  * PCRS           ==> Include pcre
167  * REGEX && PCRE  ==> Include pcre and pcreposix
168  * REGEX && !PCRE ==> Include gnu_regex
169  *
170  * STATIC  ==> Use  #include "pcre.h"  (compiling at same time)
171  * !STATIC ==> Use  #include <pcre.h>  (System library)
172  *
173  */
174 #if (defined(REGEX) && defined(PCRE)) || defined(PCRS)
175 #  ifdef STATIC
176 #    include "pcre.h"
177 #  else
178 #    include <pcre.h>
179 #  endif
180 #endif /* (defined(REGEX) && defined(PCRE)) || defined(PCRS) */
181
182 #if defined(REGEX) && defined(PCRE)
183 #  ifdef STATIC
184 #    include "pcreposix.h"
185 #  else
186 #    include <pcreposix.h>
187 #  endif
188 #endif /* defined(REGEX) && defined(PCRE) */
189
190 #if defined(REGEX) && !defined(PCRE)
191 #  include "gnu_regex.h"
192 #endif
193
194 #ifdef PCRS
195 #include "pcrs.h"
196 #endif /* def PCRS */
197
198 #ifdef AMIGA 
199 #include "amiga.h" 
200 #endif /* def AMIGA */
201
202 #ifdef __cplusplus
203 extern "C" {
204 #endif
205
206 #define FOREVER 1
207
208 /* Default IP and port to listen on */
209 #define HADDR_DEFAULT   "127.0.0.1"
210 #define HADDR_PORT      8000
211
212
213 /* Need this for struct gateway */
214 struct client_state;
215
216 /* Need this for struct client_state */
217 struct configuration_spec;
218
219
220 struct http_request
221 {
222    char *cmd;
223    char *gpc;
224    char *host;
225    int   port;
226    char *path;
227    char *ver;
228    char *hostport; /* "host[:port]" */
229    int   ssl;
230 };
231
232 struct gateway
233 {
234    /* generic attributes */
235    char *name;
236    int (*conn)(const struct gateway *, struct http_request *, struct client_state *);
237    int   type;
238
239    /* domain specific attributes */
240    char *gateway_host;
241    int   gateway_port;
242
243    char *forward_host;
244    int   forward_port;
245 };
246
247
248 /* Generic linked list of strings */
249 struct list /* FIXME: Why not separate entries and header? */
250 {
251    char *       str;  /* valid in an entry */
252    struct list *last; /* valid in header */
253    struct list *next;
254 };
255
256
257 /* Generic linked list of strings */
258 struct list_share /* FIXME: Why not separate entries and header? */
259 {
260    const char *       str;  /* valid in an entry */
261    struct list_share *last; /* valid in header */
262    struct list_share *next;
263 };
264
265
266 /* A URL pattern */
267 struct url_spec
268 {
269    char  *spec;
270    char  *domain;
271    char  *dbuf;
272    char **dvec;
273    int    dcnt;
274    int    unanchored;
275
276    char *path;
277    int   pathlen;
278    int   port;
279 #ifdef REGEX
280    regex_t *preg;
281 #endif
282 };
283
284
285 /* An I/O buffer */
286 struct iob
287 {
288    char *buf;
289    char *cur;
290    char *eod;
291 };
292
293
294 #define IOB_PEEK(CSP) ((CSP->iob->cur > CSP->iob->eod) ? (CSP->iob->eod - CSP->iob->cur) : 0)
295 #define IOB_RESET(CSP) if(CSP->iob->buf) free(CSP->iob->buf); memset(CSP->iob, '\0', sizeof(CSP->iob));
296
297
298
299 #define ACTION_MASK_ALL        (~0U)
300
301 #define ACTION_MOST_COMPATIBLE 0U
302
303 #define ACTION_BLOCK           0x0001U
304 #define ACTION_FAST_REDIRECTS  0x0002U
305 #define ACTION_FILTER          0x0004U
306 #define ACTION_HIDE_FORWARDED  0x0008U
307 #define ACTION_HIDE_FROM       0x0010U
308 #define ACTION_HIDE_REFERER    0x0020U /* sic - follow HTTP, not English */
309 #define ACTION_HIDE_USER_AGENT 0x0040U
310 #define ACTION_IMAGE           0x0080U
311 #define ACTION_NO_COOKIE_READ  0x0100U
312 #define ACTION_NO_COOKIE_SET   0x0200U
313 #define ACTION_NO_POPUPS       0x0400U
314 #define ACTION_VANILLA_WAFER   0x0800U
315
316 #define ACTION_STRING_FROM       0
317 #define ACTION_STRING_REFERER    1
318 #define ACTION_STRING_USER_AGENT 2
319 #define ACTION_STRING_COUNT      3
320
321 #define ACTION_MULTI_ADD_HEADER  0
322 #define ACTION_MULTI_WAFER       1
323 #define ACTION_MULTI_COUNT       2
324
325
326 struct current_action_spec
327 {
328    unsigned flags;    /* a bit set to "1" = add action    */
329
330    /* For those actions that require parameters: */
331
332    /* each entry is valid if & only if corresponding entry in "add" set. */
333    char * string[ACTION_STRING_COUNT];
334
335    /* Strings to add */
336    struct list_share multi[ACTION_MULTI_COUNT][1];
337 };
338
339 struct action_spec
340 {
341    unsigned mask;   /* a bit set to "0" = remove action */
342    unsigned add;    /* a bit set to "1" = add action    */
343
344    /* For those actions that require parameters: */
345
346    /* each entry is valid if & only if corresponding entry in "add" set. */
347    char * string[ACTION_STRING_COUNT];
348
349    /* Strings to remove. */
350    struct list multi_remove[ACTION_MULTI_COUNT][1];
351
352    /* If nonzero, remove *all* strings. */
353    int         multi_remove_all[ACTION_MULTI_COUNT];
354
355    /* Strings to add */
356    struct list multi_add[ACTION_MULTI_COUNT][1];
357 };
358
359 struct url_actions
360 {
361    struct url_spec url[1];
362
363    struct action_spec action[1];
364
365    struct url_actions * next;
366 };
367
368
369 /* Constants defining bitmask for csp->accept_types */
370
371 #ifdef DETECT_MSIE_IMAGES
372
373 /* MSIE detected by user-agent string */
374 #define ACCEPT_TYPE_IS_MSIE     0x0001
375
376 /*
377  * *If* this is MSIE, it wants an image.  (Or this is a shift-reload, or
378  * it's got an image from this URL before...  yuck!)
379  * Only meaningful if ACCEPT_TYPE_IS_MSIE set 
380  */
381 #define ACCEPT_TYPE_MSIE_IMAGE  0x0002
382
383 /*
384  * *If* this is MSIE, it wants a HTML document.
385  * Only meaningful if ACCEPT_TYPE_IS_MSIE set
386  */
387 #define ACCEPT_TYPE_MSIE_HTML   0x0004
388
389 #endif /* def DETECT_MSIE_IMAGES */
390
391
392 struct client_state
393 {
394    /* The proxy's configuration */
395    struct configuration_spec * config;
396
397
398    /* The actions to perform on the current request */
399    struct current_action_spec  action[1];
400
401
402    /* socket to talk to client (web browser) */
403    int  cfd;
404
405    /* socket to talk to server (web server or proxy) */
406    int  sfd;
407
408
409 #ifdef STATISTICS
410    /* 1 if this URL was rejected, 0 otherwise. Allows actual stats inc to 
411     * occur in main thread only for thread-safety. 
412     */
413    int  rejected;
414 #endif /* def STATISTICS */
415
416 #ifdef FORCE_LOAD
417    int force;
418 #endif /* def FORCE_LOAD */
419
420 #ifdef TOGGLE
421    int   toggled_on;
422 #endif /* def TOGGLE */
423
424    /*
425     * Client PC's IP address, as reported by the accept()_ function.
426     * Both as string and number
427     */
428    char *ip_addr_str;
429    long  ip_addr_long;
430
431 #ifdef TRUST_FILES
432    /* The referer in this request, if one was specified. */
433    char *referrer;
434 #endif /* def TRUST_FILES */
435
436 #if defined(DETECT_MSIE_IMAGES)
437    /* Types the client will accept.
438     * Bitmask - see ACCEPT_TYPE_XXX constants.
439     */
440    int accept_types;
441 #endif /* defined(DETECT_MSIE_IMAGES) */
442
443    /* The URL that was requested */
444    struct http_request http[1];
445
446    /* An I/O buffer used for buffering data read from the client */
447    struct iob iob[1];
448
449    /* List of all headers for this request */
450    struct list headers[1];
451
452    /* List of all cookies for this request */
453    struct list cookie_list[1];
454
455 #if defined(PCRS) || defined(KILLPOPUPS)
456    /* Nonzero if this has a text MIME type */
457    int is_text;
458 #endif /* defined(PCRS) || defined(KILLPOPUPS) */
459
460    /* The "X-Forwarded-For:" header sent by the client */
461    char   *x_forwarded;
462
463    /*
464     * Nonzero if this client is processing data.
465     * Set to zero when the thread associated with this structure dies.
466     */
467    int active;
468
469    /* files associated with this client */
470    struct file_list *flist;   /* forwardfile */
471    struct file_list *actions_list;
472
473
474 #ifdef ACL_FILES
475    struct file_list *alist;   /* aclfile */
476 #endif /* def ACL_FILES */
477
478 #ifdef PCRS
479      struct file_list *rlist;   /* Perl re_filterfile */
480      size_t content_length;     /* Length after processing */ 
481 #endif /* def PCRS */
482
483 #ifdef TRUST_FILES
484    struct file_list *tlist;   /* trustfile */
485 #endif /* def TRUST_FILES */
486
487    struct client_state *next;
488 };
489
490
491 struct parsers
492 {
493    char *str;
494    char  len;
495    char *(*parser)(const struct parsers *, char *, struct client_state *);
496 };
497
498
499 struct interceptors
500 {
501    char *str;
502    char  len;
503    char *(*interceptor)(struct http_request *http, struct client_state *csp);
504 };
505
506
507 struct file_list
508 {
509    /*
510     * this is a pointer to the data structures associated with the file.
511     * Read-only once the structure has been created.
512     */
513    void *f;
514    
515    /* Normally NULL.  When we are finished with file (i.e. when we have
516     * loaded a new one), set to a pointer to an unloader function.
517     * Unloader will be called by sweep() (called from main loop) when
518     * all clients using this file are done.  This prevents threading 
519     * problems.
520     */
521    void (*unloader)(void *);
522
523    /* Used internally by sweep().  Do not access from elsewhere. */
524    int active;
525
526 #ifndef SPLIT_PROXY_ARGS
527    /* String to be displayed as part of show-proxy-args display.
528     * Read-only once the structure has been created.
529     */
530    char *proxy_args;
531 #endif /* ndef SPLIT_PROXY_ARGS */
532
533    /* Following variables allow us to check if file has been changed.
534     * Read-only once the structure has been created.
535     */
536    time_t lastmodified;
537    char * filename;
538
539    /* Pointer to next entry in the linked list of all "file_list"s.
540     * This linked list is so that sweep() can navigate it.
541     * Since sweep() can remove items from the list, we must be careful
542     * to only access this value from main thread (when we know sweep
543     * won't be running).
544     */
545    struct file_list *next;
546 };
547
548
549 #ifdef TRUST_FILES
550 struct block_spec
551 {
552    struct url_spec url[1];
553    int    reject;
554    struct block_spec *next;
555 };
556 #endif /* def TRUST_FILES */
557
558
559 struct forward_spec
560 {
561    struct url_spec url[1];
562    struct gateway gw[1];
563    struct forward_spec *next;
564 };
565
566
567 #ifdef PCRS
568 struct re_filterfile_spec
569 {
570    struct list patterns[1];
571    /* See README.re_filter */
572    pcrs_job *joblist;
573 };
574 #endif /* def PCRS */
575
576
577 #ifdef ACL_FILES
578 #define ACL_PERMIT   1  /* accept connection request */
579 #define ACL_DENY     2  /* reject connection request */
580
581 struct access_control_addr
582 {
583    unsigned long addr;
584    unsigned long mask;
585    unsigned long port;
586 };
587
588 struct access_control_list
589 {
590    struct access_control_addr src[1];
591    struct access_control_addr dst[1];
592
593    short action;
594    struct access_control_list *next;
595 };
596 #endif /* def ACL_FILES */
597
598
599 /* Maximum number of loaders (actions, block, forward, acl...) */
600 #define NLOADERS 8
601
602 /*
603  * Data loaded from the configuration file.
604  *
605  * (Anomaly: toggle is still handled through a global, not this structure)
606  */
607 struct configuration_spec
608 {
609    int debug;
610    int multi_threaded;
611
612 #ifdef IMAGE_BLOCKING
613    int tinygif;              /* FIXME Should be an action */
614    const char *tinygifurl;   /* FIXME Should be an action */
615 #endif /* def IMAGE_BLOCKING */
616
617    const char *logfile;
618
619    const char *actions_file;
620    const char *forwardfile;
621
622 #ifdef ACL_FILES
623    const char *aclfile;
624 #endif /* def ACL_FILES */
625
626 #ifdef PCRS
627    const char *re_filterfile;
628 #endif /* def PCRS */
629
630 #ifdef JAR_FILES
631    const char * jarfile;
632    FILE * jar;
633 #endif /* def JAR_FILES */
634
635    /*
636     * Port and IP to bind to.
637     * Defaults to HADDR_DEFAULT:HADDR_PORT == 127.0.0.1:8000
638     */
639    const char *haddr;
640    int         hport;
641
642 #ifndef SPLIT_PROXY_ARGS
643    const char *suppress_message;
644 #endif /* ndef SPLIT_PROXY_ARGS */
645
646 #ifndef SPLIT_PROXY_ARGS
647    /* suppress listing config files */
648    int suppress_blocklists;
649 #endif /* ndef SPLIT_PROXY_ARGS */
650
651 #ifdef TRUST_FILES
652    const char * trustfile;
653
654    struct list trust_info[1];
655    struct url_spec *trust_list[64];
656 #endif /* def TRUST_FILES */
657
658    /* Various strings for show-proxy-args */
659    char *proxy_args_header;
660    char *proxy_args_invocation;
661    char *proxy_args_gateways;
662    char *proxy_args_trailer;
663
664    /* the configuration file object. */
665    struct file_list *config_file_list;
666
667    /* List of loaders */
668    int (*loaders[NLOADERS])(struct client_state *);
669
670    /* bool, nonzero if we need to bind() to the new port */
671    int need_bind;
672 };
673
674
675 #define SZ(X)  (sizeof(X) / sizeof(*X))
676
677 #define WHITEBG   "<body bgcolor=\"#ffffff\" link=\"#000078\" alink=\"#ff0022\" vlink=\"#787878\">\n"
678 #define BODY      "<body bgcolor=\"#f8f8f0\" link=\"#000078\" alink=\"#ff0022\" vlink=\"#787878\">\n"
679 #define BANNER    "<strong>Internet J<small>UNK<i><font color=\"red\">BUSTER</font></i></small></strong>"
680
681 #ifdef FORCE_LOAD
682 #define FORCE_PREFIX "/IJB-FORCE-LOAD"
683 #endif /* def FORCE_LOAD */
684
685 #define HOME_PAGE_URL  "http://ijbswa.sourceforge.net/"
686 #define REDIRECT_URL HOME_PAGE_URL "redirect.php?v=" VERSION "&to="
687
688 static const char CFAIL[] =
689    "HTTP/1.0 503 Connect failed\n"
690    "Content-Type: text/html\n\n"
691    "<html>\n"
692    "<head>\n"
693    "<title>Internet Junkbuster: Connect failed</title>\n"
694    "</head>\n"
695    BODY
696    "<h1><center>"
697    BANNER
698    "</center></h1>"
699    "TCP connection to '%s' failed: %s.\n<br>"
700    "</body>\n"
701    "</html>\n";
702
703 static const char CNXDOM[] =
704    "HTTP/1.0 404 Non-existent domain\n"
705    "Content-Type: text/html\n\n"
706    "<html>\n"
707    "<head>\n"
708    "<title>Internet Junkbuster: Non-existent domain</title>\n"
709    "</head>\n"
710    BODY
711    "<h1><center>"
712    BANNER
713    "</center></h1>"
714    "No such domain: %s\n"
715    "</body>\n"
716    "</html>\n";
717
718 static const char CNOBANNER[] =
719    "HTTP/1.0 200 No Banner\n"
720    "Content-Type: text/html\n\n"
721    "<html>\n"
722    "<head>\n"
723    "<title>Internet Junkbuster: No Banner</title>\n"
724    "</head>\n"
725    BODY
726    "<h1><center>"
727    BANNER
728    "</h1>"
729    "You asked for a banner that this proxy can't produce because either configuration does not permit.\n<br>"
730    "or the URL didn't end with .gif\n"
731    "</center></body>\n"
732    "</html>\n";
733
734 static const char CSUCCEED[] =
735    "HTTP/1.0 200 Connection established\n"
736    "Proxy-Agent: IJ/" VERSION "\n\n";
737
738 static const char CHEADER[] =
739    "HTTP/1.0 400 Invalid header received from browser\n\n";
740
741 static const char SHEADER[] =
742    "HTTP/1.0 502 Invalid header received from server\n\n";
743
744 #ifdef IMAGE_BLOCKING
745
746 /*
747  * Hint: You can encode your own GIFs like that:
748  * perl -e 'while (read STDIN, $c, 1) { printf("\\%.3o,", unpack("C", $c)); }'
749  */
750
751 static const char BLANKGIF[] =
752    "HTTP/1.0 200 OK\r\n"
753    "Pragma: no-cache\r\n"
754    "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMT\r\n"
755    "Expires:       Thu Jul 31, 1997 07:42:22 pm GMT\r\n"
756    "Content-type: image/gif\r\n\r\n"
757    "GIF89a\001\000\001\000\200\000\000\377\377\377\000\000"
758    "\000!\371\004\001\000\000\000\000,\000\000\000\000\001"
759    "\000\001\000\000\002\002D\001\000;";
760
761 static const char JBGIF[] =
762    "HTTP/1.0 200 OK\r\n"
763    "Pragma: no-cache\r\n"
764    "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMT\r\n"
765    "Expires:       Thu Jul 31, 1997 07:42:22 pm GMT\r\n"
766    "Content-type: image/gif\r\n\r\n"
767    "GIF89aD\000\013\000\360\000\000\000\000\000\377\377\377!"
768    "\371\004\001\000\000\001\000,\000\000\000\000D\000\013\000"
769    "\000\002a\214\217\251\313\355\277\000\200G&K\025\316hC\037"
770    "\200\234\230Y\2309\235S\230\266\206\372J\253<\3131\253\271"
771    "\270\215\342\254\013\203\371\202\264\334P\207\332\020o\266"
772    "N\215I\332=\211\312\3513\266:\026AK)\364\370\365aobr\305"
773    "\372\003S\275\274k2\354\254z\347?\335\274x\306^9\374\276"
774    "\037Q\000\000;";
775
776 #endif /* def IMAGE_BLOCKING */
777
778 #if defined(FAST_REDIRECTS) || defined(IMAGE_BLOCKING)
779
780 static const char HTTP_REDIRECT_TEMPLATE[] =
781       "HTTP/1.0 302 Local Redirect from Junkbuster\r\n" 
782       "Pragma: no-cache\r\n"
783       "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMT\r\n"
784       "Expires:       Thu Jul 31, 1997 07:42:22 pm GMT\r\n"
785       "Location: %s\r\n\r\n";
786
787 #endif /*  defined(FAST_REDIRECTS) || defined(IMAGE_BLOCKING) */
788
789 #ifdef __cplusplus
790 } /* extern "C" */
791 #endif
792
793 #endif /* ndef _PROJECT_H */
794
795 /*
796   Local Variables:
797   tab-width: 3
798   end:
799 */