--- /dev/null
+# Note: Makefile is built automatically from Makefile.in
+#
+# $Id: Makefile.in,v 1.2 2001/05/13 22:04:51 administrator Exp $
+#
+# Written by and Copyright (C) 2001 the SourceForge
+# IJBSWA team. http://ijbswa.sourceforge.net
+#
+# Based on the Internet Junkbuster originally written
+# by and Copyright (C) 1997 Anonymous Coders and
+# Junkbusters Corporation. http://www.junkbusters.com
+#
+# This program is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will
+# be useful, but WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# The GNU General Public License should be included with
+# this file. If not, you can view it at
+# http://www.gnu.org/copyleft/gpl.html
+# or write to the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Log: Makefile.in,v $
+#
+
+
+# define version (will be wired into the rpm.)
+VERSION_MAJOR = @VERSION_MAJOR@
+VERSION_MINOR = @VERSION_MINOR@
+VERSION_POINT = @VERSION_POINT@
+VERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_POINT)
+RPM_VERSION = $(VERSION)
+
+# The version is currently specified in config.h, which is
+# written by "configure".
+#
+#VERSION_CFLAGS = -DVERSION_MAJOR=$(VERSION_MAJOR) \
+# -DVERSION_MINOR=$(VERSION_MINOR) \
+# -DVERSION_POINT=$(VERSION_POINT) \
+# -DVERSION="$(VERSION)"
+
+# Directories for "make install"
+DEST = /etc/junkbuster
+SBIN_DEST = @sbindir@
+MAN_DEST = @mandir@
+
+# The flag "-mno-win32" can be used by Cygwin to emulate a un?x type install.
+# The flag "-mwindows -mno-cygwin" will cause Cygwin to use MingW32 for Win32 install.
+CYGWIN_FLAGS = @CYGWIN_FLAGS@
+
+# Need to define this in order to link PCRE statically under Win32
+# Also define under UNIX to use system PCRE headers.
+PCRE_WIN_FLAGS = @STATIC_PCRE_ONLY@-DSTATIC
+
+# Either/Or of these next two lines
+#DEBUG_CFLAGS = -g
+DEBUG_CFLAGS = -O3
+
+# Solaris needs a special define:
+# FIXME: This is always commented out
+SOLARIS_FLAGS = @SOLARIS_ONLY@-D__EXTENSIONS__=1
+
+# -DSTDC_HEADERS Now in config.h
+# Do we need -DHAVE_STRING ???
+CFLAGS = @CFLAGS@ @CPPFLAGS@ \
+ -D__MT__=1 -D__STDC__=1 $(SOLARIS_FLAGS) -DHAVE_STRING $(DEBUG_CFLAGS) \
+ -Ipcre $(CYGWIN_FLAGS) $(PCRE_WIN_FLAGS)
+
+PROGRAM = junkbuster@EXEEXT@
+CC = gcc
+ECHO = echo
+GZIP = gzip
+INSTALL = cp -f
+LD = gcc
+OBJEXT = @OBJEXT@
+RM = rm -f
+STRIP = strip
+
+C_SRC = encode.c errlog.c filters.c gateway.c jbsockets.c jcc.c \
+ killpopup.c loadcfg.c loaders.c miscutil.c parsers.c \
+ showargs.c ssplit.c
+
+C_OBJS = $(C_SRC:.c=.$(OBJEXT))
+C_HDRS = $(C_SRC:.c=.h) project.h
+
+W32_SRC = @WIN_ONLY@w32log.c w32rulesdlg.c w32taskbar.c win32.c
+W32_FILES = @WIN_ONLY@w32.res
+W32_OBJS = @WIN_ONLY@$(W32_SRC:.c=.$(OBJEXT)) $(W32_FILES)
+W32_HDRS = @WIN_ONLY@w32log.h w32res.h w32rulesdlg.h w32taskbar.h
+W32_LIB = @WIN_ONLY@-lwsock32 -lcomctl32
+W32_INIS = @WIN_ONLY@junkbstr.txt saclfile.txt sblock.txt scookie.txt \
+ @WIN_ONLY@sforward.txt simage.txt spopup.txt strust.txt sregexp.txt
+
+PCRS_SRC = @PCRS_ONLY@pcrs.c
+PCRS_OBJS = $(PCRS_SRC:.c=.$(OBJEXT))
+PCRS_HDRS = $(PCRS_SRC:.c=.h)
+
+PCRE_SRC = @STATIC_PCRE_ONLY@pcre/get.c pcre/maketables.c pcre/study.c pcre/pcre.c
+PCRE_OBJS = @STATIC_PCRE_ONLY@$(PCRE_SRC:.c=.$(OBJEXT))
+PCRE_HDRS = @STATIC_PCRE_ONLY@pcre/config.h pcre/chartables.c pcre/internal.h pcre/pcre.h
+PCRE_LIB = @LIBRARY_PCRE_ONLY@-lpcre
+
+# No REGEX:
+@NO_REGEX_ONLY@REGEX_SRC =
+# Without PCRE:
+@GNU_REGEX_ONLY@REGEX_SRC = gnu_regex.c
+# With PCRE:
+@PCRE_REGEX_ONLY@REGEX_SRC = @STATIC_PCRE_ONLY@pcre/pcreposix.c
+
+REGEX_OBJS = $(REGEX_SRC:.c=.$(OBJEXT))
+REGEX_HDRS = $(REGEX_SRC:.c=.h)
+
+# Dependencies introduced by #include "project.h".
+PROJECT_H_DEPS = project.h $(REGEX_HDRS) $(PCRS_HDRS) @STATIC_PCRE_ONLY@pcre/pcre.h
+
+# Only need this on Solaris
+# FIXME: This is always commented out
+SOCKET_LIB = @SOLARIS_ONLY@-lsocket -lnsl
+
+LIBS = $(PCRE_LIB) $(W32_LIB) $(SOCKET_LIB)
+
+SRCS = $(C_SRC) $(W32_SRC) $(PCRS_SRC) $(PCRE_SRC) $(REGEX_SRC)
+OBJS = $(C_OBJS) $(W32_OBJS) $(PCRS_OBJS) $(PCRE_OBJS) $(REGEX_OBJS)
+HDRS = $(C_HDRS) $(W32_HDRS) $(PCRS_HDRS) $(PCRE_OBJS) $(REGEX_HDRS)
+
+
+# -------------------------------------------------------------------------
+# Do not change anything below this line
+# And there should NOT be any targets above this line.
+# -------------------------------------------------------------------------
+LDFLAGS = $(DEBUG_CFLAGS) $(CYGWIN_FLAGS)
+
+
+all: $(PROGRAM)
+
+
+SUFFIX = .txt:o
+.SUFFIXES : .txt
+
+%.txt:
+ sed -e 's/$$//' < $< > $@
+
+inifiles: $(W32_INIS)
+
+junkbstr.txt: config
+ sed -e 's!\(/etc/junkbuster\|.\)/blocklist!sblock.txt!' \
+ -e 's!\(/etc/junkbuster\|.\)/popup!spopup.txt!' \
+ -e 's!\(/etc/junkbuster\|.\)/cookiefile!scookie.txt!' \
+ -e 's!\(/etc/junkbuster\|.\)/forward!sforward.txt!' \
+ -e 's!\(/etc/junkbuster\|.\)/trust!strust.txt!' \
+ -e 's!\(/etc/junkbuster\|.\)/aclfile!sacl.txt!' \
+ -e 's!\(/var/log/junkbuster\|.\)/jarfile!jar.log!' \
+ -e 's!\(/var/log/junkbuster\|.\)/junkbuster\.log!junkbstr.log!' \
+ -e 's!\(/etc/junkbuster\|.\)/imagelist!simage.txt!' \
+ -e 's!\(/etc/junkbuster\|.\)/re_filterfile!sregexp.txt!' \
+ -e 's!$$!!' \
+ < $< > $@
+
+saclfile.txt: aclfile
+sblock.txt: blocklist
+scookie.txt: cookiefile
+sforward.txt: forward
+simage.txt: imagelist
+spopup.txt: popup
+strust.txt: trust
+sregexp.txt: re_filterfile
+
+
+# -------------------------------------------------------------------------
+#
+# -------------------------------------------------------------------------
+rpm-dist:
+ @make clean
+# verify that i'm root needs to be done
+ cd .. && tar --exclude "ijb/CVS" -cvzf ijb.tar.gz ijb/
+# verify all version strings, FLAGS, etc. in the spec file
+ cat ../../SPECS/junkbuster.spec | sed 's/^Version:.*/Version: $(RPM_VERSION)/g' | sed 's/^Release:.*/Release: $(VERSION_POINT)/g' > /tmp/abc && cp -f /tmp/abc ../../SPECS/junkbuster.spec
+ cd ../../ && rpm -ba SPECS/junkbuster.spec
+ chmod -R a+r ../../RPMS
+ chmod -R a+r ../../SRPMS
+
+# -------------------------------------------------------------------------
+#
+# -------------------------------------------------------------------------
+win-dist:
+ $(ECHO) Not implemented.
+
+# -------------------------------------------------------------------------
+#
+# -------------------------------------------------------------------------
+tarball-dist:
+ @make clean
+ make $(PROGRAM)
+# remove all objects and create the tarball with the binary
+ cd .. && $(RM) ijb/a.out ijb/core ijb/*.$(OBJEXT) && tar --exclude "ijb/CVS" -cvzf ../ijb-distribution-$(VERSION).tar.gz ijb/
+ chmod a+r ../../ijb-distribution-$(VERSION).tar.gz
+ @$(ECHO) Tarball with binary created.
+
+# -------------------------------------------------------------------------
+#
+# -------------------------------------------------------------------------
+
+encode.@OBJEXT@: encode.c encode.h config.h
+errlog.@OBJEXT@: errlog.c errlog.h config.h $(PROJECT_H_DEPS) @WIN_ONLY@w32log.h
+filters.@OBJEXT@: filters.c filters.h config.h $(PROJECT_H_DEPS) errlog.h encode.h gateway.h jbsockets.h jcc.h loadcfg.h parsers.h showargs.h ssplit.h @WIN_ONLY@win32.h
+gateway.@OBJEXT@: gateway.c gateway.h config.h $(PROJECT_H_DEPS) errlog.h jbsockets.h jcc.h loadcfg.h
+jbsockets.@OBJEXT@: jbsockets.c jbsockets.h config.h $(PROJECT_H_DEPS) filters.h
+jcc.@OBJEXT@: jcc.c jcc.h config.h $(PROJECT_H_DEPS) errlog.h filters.h gateway.h jbsockets.h killpopup.h loadcfg.h loaders.h miscutil.h parsers.h showargs.h @WIN_ONLY@w32log.h win32.h
+killpopup.@OBJEXT@: killpopup.c killpopup.h config.h $(PROJECT_H_DEPS) jcc.h loadcfg.h
+loadcfg.@OBJEXT@: loadcfg.c loadcfg.h config.h $(PROJECT_H_DEPS) errlog.h filters.h gateway.h jbsockets.h jcc.h killpopup.h loaders.h miscutil.h parsers.h showargs.h @WIN_ONLY@w32log.h win32.h
+loaders.@OBJEXT@: loaders.c loaders.h config.h $(PROJECT_H_DEPS) errlog.h encode.h filters.h gateway.h jcc.h loadcfg.h miscutil.h parsers.h ssplit.h
+miscutil.@OBJEXT@: miscutil.c miscutil.h config.h
+parsers.@OBJEXT@: parsers.c parsers.h config.h $(PROJECT_H_DEPS) errlog.h encode.h filters.h jbsockets.h jcc.h loadcfg.h loaders.h miscutil.h showargs.h ssplit.h
+showargs.@OBJEXT@: showargs.c showargs.h config.h $(PROJECT_H_DEPS) errlog.h encode.h gateway.h jcc.h loadcfg.h miscutil.h parsers.h
+ssplit.@OBJEXT@: ssplit.c ssplit.h config.h miscutil.h
+
+# GNU regex
+gnu_regex.@OBJEXT@: gnu_regex.c gnu_regex.h config.h
+
+# PCRS
+pcrs.@OBJEXT@: pcrs.c pcre/pcre.h pcrs.h
+
+# PCRE
+pcre/get.@OBJEXT@: pcre/get.c pcre/config.h pcre/internal.h pcre/pcre.h
+pcre/maketables.@OBJEXT@: pcre/maketables.c pcre/config.h pcre/internal.h pcre/pcre.h
+pcre/pcre.@OBJEXT@: pcre/pcre.c pcre/config.h pcre/internal.h pcre/pcre.h pcre/chartables.c
+pcre/pcreposix.@OBJEXT@: pcre/pcreposix.c pcre/config.h pcre/internal.h pcre/pcre.h pcre/pcreposix.h
+pcre/study.@OBJEXT@: pcre/study.c pcre/config.h pcre/internal.h pcre/pcre.h
+
+# An auxiliary program makes the PCRE default character table source
+
+pcre/chartables.c: pcre/dftables
+ pcre/dftables >pcre/chartables.c
+
+pcre/dftables: pcre/dftables.c pcre/maketables.c pcre/pcre.h pcre/internal.h pcre/config.h
+ $(CC) -o pcre/dftables $(CFLAGS) pcre/dftables.c
+
+# Win32
+w32log.@OBJEXT@: w32log.c errlog.h config.h jcc.h loadcfg.h miscutil.h pcre/pcre.h pcre/pcreposix.h pcrs.h project.h w32log.h w32rulesdlg.h w32taskbar.h win32.h
+w32rulesdlg.@OBJEXT@: w32rulesdlg.c config.h w32rulesdlg.h win32.h
+w32taskbar.@OBJEXT@: w32taskbar.c config.h w32log.h w32taskbar.h
+win32.@OBJEXT@: win32.c config.h jcc.h loadcfg.h pcre/pcre.h pcre/pcreposix.h pcrs.h project.h w32log.h win32.h
+
+w32.res: w32.rc w32res.h icons/denyrule.ico icons/ico00001.ico icons/ico00002.ico icons/ico00003.ico icons/ico00004.ico icons/ico00005.ico icons/ico00006.ico icons/ico00007.ico icons/ico00008.ico icons/icon1.ico icons/idle.ico icons/junkbust.ico config.h
+ windres -D__MINGW32__=0.2 -O coff -i $< -o $@
+
+
+$(PROGRAM): $(OBJS) $(W32_FILES)
+ $(LD) $(LDFLAGS) -o $(PROGRAM) $(OBJS) $(LIBS)
+
+clean:
+ $(RM) a.out core $(OBJS) $(W32_FILES) $(W32_INIS)
+
+clobber: clean
+ $(RM) $(PROGRAM) *.pdb *.lib *.exp TAGS junkbuster.log
+
+tags: $(SRCS) $(HDRS)
+ etags $(SRCS) $(HDRS)
+
+install: all
+ $(STRIP) $(PROGRAM)
+ $(INSTALL) $(PROGRAM) $(SBIN_DEST)
+ $(INSTALL) README README.TOO README.WIN README.re_filter README.cygwin $(DEST)
+ $(INSTALL) aclfile blocklist config cookiefile forward imagelist \
+ popup re_filterfile trust $(DEST)
+ # FIXME: On SuSE, these are not found. Where do they go?
+ $(ECHO) junkbuster.logrotate junkbuster.monthly junkbuster.weekly
+ $(GZIP) -c junkbuster.1 > $(MAN_DEST)/junkbuster.1.gz
+ $(INSTALL) junkbuster.init /sbin/init.d/junkbuster
+
+
+## Local Variables:
+## tab-width: 3
+## end:
--- /dev/null
+#ifndef _CONFIG_H
+#define _CONFIG_H
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/acconfig.h,v $
+ *
+ * Purpose : This file should be the first thing included in every
+ * .c file. (Before even system headers). It contains
+ * #define statements for various features. It was
+ * introduced because the compile command line started
+ * getting ludicrously long with feature defines.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: acconfig.h,v $
+ *
+ *********************************************************************/
+\f
+@TOP@
+
+/*
+ * Version number - Major (X._._)
+ */
+#undef VERSION_MAJOR
+
+/*
+ * Version number - Minor (_.X._)
+ */
+#undef VERSION_MINOR
+
+/*
+ * Version number - Point (_._.X)
+ */
+#undef VERSION_POINT
+
+/*
+ * Version number, as a string
+ */
+#undef VERSION
+
+/*
+ * Regular expression matching for URLs. (Highly recommended). If this is
+ * not defined then you can ony use prefix matching.
+ */
+#undef REGEX
+
+/*
+ * Allow JunkBuster to be "disabled" so it is just a normal non-blocking
+ * non-anonymizing proxy. This is useful if you're trying to access a
+ * blocked or broken site - just change the setting in the config file
+ * and send a SIGHUP (UN*X), or use the handy "Disable" menu option (Windows
+ * GUI).
+ */
+#undef TOGGLE
+
+/*
+ * Enables arbitrary content modification regexps
+ */
+#undef PCRS
+
+/*
+ * If a stream is compressed via gzip (Netscape specific I think), then
+ * it cannot be modified with Perl regexps. This forces it to be
+ * uncompressed.
+ */
+#undef DENY_GZIP
+
+/*
+ * Enables statistics function.
+ */
+#undef STATISTICS
+
+/*
+ * Bypass filtering for 1 page only
+ */
+#undef FORCE_LOAD
+
+/*
+ * Split the show-proxy-args page into a page for each config file.
+ */
+#undef SPLIT_PROXY_ARGS
+
+/*
+ * Kills JavaScript popups - window.open, onunload, etc.
+ */
+#undef KILLPOPUPS
+
+/*
+ * Support for webDAV - e.g. so Microsoft Outlook can access HotMail e-mail
+ */
+#undef WEBDAV
+
+/*
+ * Detect image requests automatically for MSIE. Will fall back to
+ * other image-detection methods (i.e. USE_IMAGE_LIST) for other
+ * browsers.
+ *
+ * It detects the following header pair as an image request:
+ *
+ * User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
+ * Accept: * / *
+ *
+ * And the following as a HTML request:
+ *
+ * User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
+ * Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, * / *
+ *
+ * And no, I haven't got that backwards - IE is being wierd.
+ *
+ * Known limitations:
+ * 1) If you press shift-reload on a blocked HTML page, you get
+ * the image "blocked" page, not the HTML "blocked" page.
+ * 2) Once an image "blocked" page has been sent, viewing it
+ * in it's own browser window *should* bring up the HTML
+ * "blocked" page, but it doesn't. You need to clear the
+ * browser cache to get the HTML version again.
+ *
+ * These limitations are due to IE making inconsistent choices
+ * about which "Accept:" header to send.
+ */
+#undef DETECT_MSIE_IMAGES
+
+/*
+ * Use image list to detect images.
+ * If you do not define this then everything is treated as HTML.
+ *
+ * Whatever the setting of this value, DETECT_MSIE_IMAGES will
+ * override it for people using Internet Explorer.
+ */
+#undef USE_IMAGE_LIST
+
+/*
+ * Allows the use of ACL files to control access to the proxy by IP address.
+ */
+#undef ACL_FILES
+
+/*
+ * Allows the use of trust files.
+ */
+#undef TRUST_FILES
+
+/*
+ * Allows the use of jar files to capture cookies.
+ */
+#undef JAR_FILES
+
+/*
+ * Use PCRE rather than GNU Regex
+ */
+#undef PCRE
+
+@BOTTOM@
+
+#endif /* _CONFIG_H */
--- /dev/null
+# Access Control List for the Internet Junkbuster 2.0
+#
+# Copyright 1997-8 Junkbusters Corp. For distribution, modification and use
+# under the GNU General Public License. These files come with NO WARRANTY.
+# See http://www.junkbusters.com/ht/en/gpl.html or README file for details.
+#
+# Access controls are included at the request of some ISPs and systems
+# administrators, and are not usually needed by individual users.
+# Please note the warnings in the FAQ that this proxy is not
+# intended to be a substitute for a firewall or to encourage anyone
+# to defer addressing basic security weaknesses.
+# For details see http://www.junkbusters.com/ht/en/ijbman.html#aclfile
+
+# For this file to have any effect, the line beginning "aclfile"
+# must be commented in, with the name of this file following the word "aclfile"
+
+# If no access file is specified, the proxy talks to anyone that connects.
+# If an access file is specified, the proxy talks only to IP addresses
+# permitted somewhere in this file and not denied later in this file.
+#
+# Summary -- if using an ACL:
+#
+# Client must have permission to receive service
+# LAST match in ACL file wins
+# Default behavior is to deny service
+#
+# Syntax for an entry in an Access Control List is:
+#
+# ACTION SRC_ADDR[/SRC_MASKLEN] [ DST_ADDR[/DST_MASKLEN] ]
+#
+# where the fields are
+#
+# ACTION = "permit" | "deny"
+#
+# SRC_ADDR = client hostname or dotted IP address
+# SRC_MASKLEN = number of bits in the subnet mask for the source
+#
+# DST_ADDR = server or forwarder hostname or dotted IP address
+# DST_MASKLEN = number of bits in the subnet mask for the target
+#
+# field separator (FS) is whitespace (space or tab)
+#
+# IMPORTANT NOTE
+# ==============
+# If the junkbuster is using a forwarder or a gateway for a particular
+# destination URL, the DST_ADDRR that is examined is the address of
+# the forwarder or the gateway and NOT the address of the ultimate target.
+# This is necessary because it may be impossible for the local
+# junkbuster to determine the address of the ultimate target
+# (that's often what gateways are used for).
+#
+# Here are a few examples to show how the ACL works:
+
+# localhost is OK -- no DST_ADDR implies that ALL destination addresses are OK
+# permit localhost
+
+# a silly example to illustrate:
+#
+# permit any host on the class-C subnet with junkbusters to go anywhere
+#
+# permit www.junkbusters.com/24
+#
+# except deny one particular IP address from using it at all
+#
+# deny ident.junkbusters.com
+
+# another example
+#
+# You can specify an explicit network address and subnet mask.
+# Explicit addresses do not have to be resolved to be used.
+#
+# permit 207.153.200.0/24
+
+# a subnet mask of 0 matches anything, so the next line permits everyone.
+#
+# permit 0.0.0.0/0
+
+# Note: you cannot say
+#
+# permit .org
+#
+# to allow all .org domains; every IP-address listed must resolve fully.
+
+# An ISP may want to provide a junkbuster that is accessible by "the world"
+# and yet restrict use of some of their private content to hosts on its
+# internal network (i.e. its own subscribers). Say, for instance the
+# ISP owns the Class-B IP address block 123.124.0.0 (a 16 bit netmask).
+# This is how they could do it:
+
+# permit 0.0.0.0/0 0.0.0.0/0 # other clients can go anywhere
+# with the following exceptions:
+#
+# deny 0.0.0.0/0 123.124.0.0/16 # block all external requests for
+# sites on the ISP's network
+#
+# permit 0.0.0.0/0 www.my_isp.com # except for the ISP's main web site
+#
+# permit 123.124.0.0/16 0.0.0.0/0 # the ISP's clients can go anywhere
+
+# Note that some hostnames may be listed with multiple IP addresses;
+# the primary value returned by gethostbyname() is used.
+#
--- /dev/null
+const char amiga_rcs[] = "$Id: amiga.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/jcc.c,v $
+ *
+ * Purpose : Amiga-specific declarations.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: jcc.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#ifdef AMIGA
+
+#include <stdio.h>
+#include <signal.h>
+
+#include "amiga.h"
+
+chonst char amiga_h_rcs[] = AMIGA_H_VERSION;
+
+unsigned long __stack = 20*1024;
+/* static char ver[] = "$VER: junkbuster " __AMIGAVERSION__ " (" __AMIGADATE__ ")"; */
+struct Task *main_task = NULL;
+int childs = 0;
+
+void serve(struct client_state *csp);
+
+__saveds ULONG server_thread(void)
+{
+ struct client_state *local_csp;
+ struct UserData UserData;
+ struct Task *me=FindTask(NULL);
+
+ Wait(SIGF_SINGLE);
+ local_csp=(struct client_state *)(me->tc_UserData);
+ me->tc_UserData=&UserData;
+ SocketBase=(APTR)OpenLibrary("bsdsocket.library",3);
+ if(SocketBase)
+ {
+ SetErrnoPtr(&(UserData.eno),sizeof(int));
+ local_csp->cfd=ObtainSocket(local_csp->cfd, AF_INET, SOCK_STREAM, 0);
+ if(-1!=local_csp->cfd)
+ {
+ Signal(main_task,SIGF_SINGLE);
+ serve((struct client_state *) local_csp);
+ } else {
+ local_csp->active = 0;
+ Signal(main_task,SIGF_SINGLE);
+ }
+ CloseLibrary(SocketBase);
+ } else {
+ local_csp->active = 0;
+ Signal(main_task,SIGF_SINGLE);
+ }
+ childs--;
+ return 0;
+}
+
+void amiga_exit(void)
+{
+ if(SocketBase)
+ {
+ CloseLibrary(SocketBase);
+ }
+}
+
+static struct SignalSemaphore memsem;
+static struct SignalSemaphore *memsemptr = NULL;
+static struct UserData GlobalUserData;
+
+void InitAmiga(void)
+{
+ main_task = FindTask(NULL);
+ main_task->tc_UserData = &GlobalUserData;
+
+ if (((struct Library *)SysBase)->lib_Version < 39)
+ {
+ exit(RETURN_FAIL);
+ }
+
+ signal(SIGINT,SIG_IGN);
+ SocketBase = (APTR)OpenLibrary("bsdsocket.library",3);
+ if (!SocketBase)
+ {
+ fprintf(stderr, "Can't open bsdsocket.library V3+\n");
+ exit(RETURN_ERROR);
+ }
+ SetErrnoPtr(&(GlobalUserData.eno),sizeof(int));
+ InitSemaphore(&memsem);
+ memsemptr = &memsem;
+
+ atexit(amiga_exit);
+}
+
+#ifdef __GNUC__
+#ifdef libnix
+/* multitaskingsafe libnix replacements */
+static void *memPool=NULL;
+
+void *malloc (size_t s)
+{
+ ULONG *mem;
+ LONG size = s;
+
+ if (size<=0)
+ {
+ return NULL;
+ }
+ if (!memPool)
+ {
+ if (!(memPool=CreatePool(MEMF_ANY,32*1024,8*1024)))
+ {
+ return NULL;
+ }
+ }
+ size += sizeof(ULONG) + MEM_BLOCKMASK;
+ size &= ~MEM_BLOCKMASK;
+ if (memsemptr)
+ {
+ ObtainSemaphore(memsemptr);
+ }
+ if ((mem=AllocPooled(memPool,size)))
+ {
+ *mem++=size;
+ }
+ if (memsemptr)
+ {
+ ReleaseSemaphore(memsemptr);
+ }
+ return mem;
+}
+
+void free (void *m)
+{
+ ULONG *mem = m;
+
+ if(mem && memPool)
+ {
+ ULONG size=*--mem;
+
+ if (memsemptr)
+ {
+ ObtainSemaphore(memsemptr);
+ }
+ FreePooled(memPool,mem,size);
+ if (memsemptr)
+ {
+ ReleaseSemaphore(memsemptr);
+ }
+ }
+}
+
+void *realloc (void *old, size_t ns)
+{
+ void *new;
+ LONG osize, *o = old;
+ LONG nsize = ns;
+
+ if (!old)
+ {
+ return malloc(nsize);
+ }
+ osize = (*(o-1)) - sizeof(ULONG);
+ if (nsize <= osize)
+ {
+ return old;
+ }
+ if ((new = malloc(nsize)))
+ {
+ ULONG *n = new;
+
+ osize >>= 2;
+ while(osize--)
+ {
+ *n++ = *o++;
+ }
+ free(old);
+ }
+ return new;
+}
+
+void __memCleanUp (void)
+{
+ if (memsemptr)
+ {
+ ObtainSemaphore(memsemptr);
+ }
+ if (memPool)
+ {
+ DeletePool(memPool);
+ }
+ if (memsemptr)
+ {
+ ReleaseSemaphore(memsemptr);
+ }
+}
+
+#define ADD2LIST(a,b,c) asm(".stabs \"_" #b "\"," #c ",0,0,_" #a )
+#define ADD2EXIT(a,pri) ADD2LIST(a,__EXIT_LIST__,22); \
+ asm(".stabs \"___EXIT_LIST__\",20,0,0," #pri "+128")
+ADD2EXIT(__memCleanUp,-50);
+#elif !defined(ixemul)
+#error No libnix and no ixemul!?
+#endif /* libnix */
+#else
+#error Only GCC is supported, multitasking safe malloc/free required.
+#endif /* __GNUC__ */
+
+#endif /* def AMIGA */
--- /dev/null
+#ifdef AMIGA
+#ifndef _AMIGA_H
+#define _AMIGA_H
+#define AMIGA_H_VERSION "$Id: amiga.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/amiga.h,v $
+ *
+ * Purpose : Amiga-specific declarations.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: jcc.h,v $
+ *
+ *********************************************************************/
+\f
+
+#define _KERNEL
+#include <sys/socket.h>
+#undef _KERNEL
+
+#define __NOLIBBASE__
+#include <proto/socket.h>
+#undef __NOLIBBASE__
+
+#include <proto/exec.h>
+#include <exec/tasks.h>
+#include <proto/dos.h>
+#include <dos/dostags.h>
+
+struct UserData
+{
+ struct Library *sb;
+ int eno;
+};
+
+#define SocketBase ((struct Library *)(((struct UserData *)(FindTask(NULL)->tc_UserData))->sb))
+#define errno (((struct UserData *)(FindTask(NULL)->tc_UserData))->eno)
+#define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,NULL)
+#define inet_ntoa(x) Inet_NtoA(x.s_addr)
+
+extern int childs;
+extern struct Task *main_task;
+
+void InitAmiga(void);
+void amiga_exit(void);
+void __memCleanUp(void);
+__saveds ULONG server_thread(void);
+
+#define exit(x)\
+{\
+ if(main_task)\
+ {\
+ if(main_task == FindTask(NULL))\
+ {\
+ while(childs) Delay(10*TICKS_PER_SECOND); exit(x);\
+ } else {\
+ CloseLibrary(SocketBase);\
+ childs--;\
+ RemTask(NULL);\
+ }\
+ }\
+}
+
+#define EINTR 0
+
+#endif /* ndef _AMIGA_H */
+#endif /* def AMIGA */
--- /dev/null
+#
+# This is /etc/junkbuster/blocklist which was put here by a junkbuster rpm
+#
+# $Id: blocklist,v 1.3 2000/09/17 07:29:18 swa Exp $
+#
+# Last modified on Mon Sep 25 20:41:50 2000 (CEST)
+#
+# --------------------------------------------------------------------------
+#
+# Newest version is always available from
+#
+# http://www.waldherr.org/blocklist
+#
+# Read http://www.waldherr.org/junkbuster/update.shtml on how to keep
+# this file up-to-date.
+#
+# This list is Copyright (c) Stefan Waldherr <stefan@waldherr.org>.
+#
+# No distribution of this list without acknowledgement of the author(s).
+# No selling of thist list without prior written agreement.
+#
+# --------------------------------------------------------------------------
+#
+# Contributors are listed in the Hall Of Fame at
+#
+# http://www.waldherr.org/junkbuster/hof.shtml
+#
+# PS: I know that there are a ton of redundant regexps in this
+# file, but I haven't had time to fix them. Any help
+# appreciated.
+#
+# --------------------------------------------------------------------------
+#
+# For more detail, see http://www.junkbusters.com/ht/en/ijbfaq.html#blocking
+#
+# --------------------------------------------------------------------------
+#
+# Empty lines and lines beginning with a `#' are ignored.
+# The following line should be included to block use of telnet (port 23)
+:23
+
+# --------------------------------------------------------------------------
+#
+# generic paths
+#
+# --------------------------------------------------------------------------
+
+/*.*/(.*[-_.])?ads?[0-9]?(/|[-_.].*|\.(gif|jpe?g))
+/*.*/(.*[-_.])?count(er)?(\.cgi|\.dll|\.exe|[?/])
+/*.*/(ng)?adclient\.cgi
+/*.*/(plain|live|rotate)[-_.]?ads?/
+
+/*.*/(sponsor)s?[0-9]?/
+###/*.*/(sponsor|banner)s?[0-9]?/
+###/*.*/.*banner([-_]?[a-z0-9]+)?\.(gif|jpg)
+
+/*.*/_?(plain|live)?ads?(-banners)?/
+/*.*/abanners/
+/*.*/ad(sdna_image|gifs?)/
+/*.*/ad(server|stream|juggler)\.(cgi|pl|dll|exe)
+/*.*/adbanners/
+/*.*/adserver
+/*.*/adstream\.cgi
+/*.*/adv((er)?ts?|ertis(ing|ements?))?/
+/*.*/anzei(gen)?/?
+/*.*/ban[-_]cgi/
+/*.*/banner_?ads/
+/*.*/banner_?anzeigen
+/*.*/bannerimage/
+/*.*/banners?/
+/*.*/banners?\.cgi/
+/*.*/cgi-bin/centralad/getimage
+/*.*/images/addver\.gif
+/*.*/images/advert\.gif
+/*.*/images/marketing/.*\.(gif|jpe?g)
+/*.*/place-ads
+/*.*/popupads/
+/*.*/promobar.*
+/*.*/publicite/
+/*.*/randomads/.*\.(gif|jpe?g)
+/*.*/reklama/.*\.(gif|jpe?g)
+/*.*/reklame/.*\.(gif|jpe?g)
+/*.*/reklaam/.*\.(gif|jpe?g)
+/*.*/siteads/
+/*.*/sponsor.*\.gif
+/*.*/sponsors?[0-9]?/
+/*.*/ucbandeimg/
+/*.*/werb\..*
+/*.*/werbebanner/
+/*.*/werbung/.*\.(gif|jpe?g)
+/.*/adv\. # www.telegraaf.nl
+/.*/advert[0-9]+\.jpg
+/.*bann\.gif
+/Media/Images/Adds/
+/_banner/
+/ad_images/
+/adgenius/
+/adimages/
+/*.*/ads/
+/*.*/ads\\
+/viewad/
+/adserve/
+/adverts/
+/annonser?/
+/bando/
+/bannerad/
+/bannerfarm/
+/bin/getimage.cgi/...\?AD
+/bin/nph-oma.count/ct/default.shtml
+/bin/nph-oma.count/ix/default.html
+/cgi-bin/getimage.cgi/....\?GROUP=
+/cgi-bin/nph-load
+/cgi-bin/webad.dll/ad
+/cwmail/acc\.gif
+/cwmail/amzn-bm1\.gif
+/db_area/banrgifs/
+/gif/teasere/
+/grafikk/annonse/
+/graphics/defaultAd/
+/grf/annonif
+/htmlad/
+/image\.ng/AdType
+/image\.ng/transactionID
+/images/.*/.*_anim\.gif # alvin brattli
+/ip_img/.*\.(gif|jpe?g)
+/marketpl*/
+/minibanners/
+/netscapeworld/nw-ad/
+/promotions/houseads/
+/rotads/
+/rotateads/
+/rotations/
+/torget/jobline/.*\.gif
+/viewad/
+/werbung/
+/worldnet/ad\.cgi
+/zhp/auktion/img/
+/cgi-bin/nph-adclick.exe/
+/*.*/Image/BannerAdvertising/
+/*.*/ad-bin/
+/*.*/adlib/server\.cgi
+/*.*/gsa_bs/gsa_bs.cmdl
+/autoads/
+/anz/pics/
+
+# for our finnish friends, by Kai Puolamaki <Kai.Puolamaki@iki.fi>
+/*.*/mainos/*.*/.*\.gif
+/*.*/mainos/*.*/.*\.jpe?g
+
+# more from a finnish friend Petri Haapio <pha@iki.fi>
+cgi.tietovalta.fi
+keltaisetsivut.fi/web/img/\.*gif
+haku.net/pics/pana\.*gif
+www.fi/guvat/\.*gif
+/*.*/(.*[-_.].*)?maino(kset|nta|s).*(/|\.(gif|html?|jpe?g|png))
+/*.*/(ilm(oitus)?|kampanja)(hallinta|kuvat?)(/|\.(gif|html?|jpe?g|png))
+
+# and even more from a finnish friend Hannu Napari <Hannu.Napari@hut.fi>
+194.251.243.50/cgi-bin/banner
+
+www.dime.net/ad
+www.iltalehti.fi/ad
+www.iltalehti.fi/ilmkuvat
+www.mtv3.fi/mainoskuvat
+
+# <jwz@jwz.org>
+/*.*/adfinity
+/*.*/[?]adserv
+/*.*/bizgrphx/
+/*.*/smallad2\.gif
+/*.*/ana2ad\.gif
+/*.*/adimg/
+/*.*/.*counter\.pl
+/*.*/spin_html/
+/*.*/images/topics/topicgimp\.gif
+discovery.com/.*banner_id
+/*.*/.*bannr\.gif
+cruel.com/images/
+idrink.com/frm_bottom.htm
+/*.*/.*pb_ihtml\.gif
+/*.*/ph-ad.*\.focalink\.com
+/cgi-bin/adjuggler
+
+/we_ba/ # hausfrauenseite.de *bwhahahaaaaa*
+
+# ms sucks !
+/.*(ms)?backoff(ice)?.*\.(gif|jpe?g)
+/.*(/ie4|/ie3|msie|sqlbans|powrbybo|activex|backoffice|explorer|netnow|getpoint|ntbutton|hmlink).*\.(gif|jpe?g)
+/.*activex.*(gif|jpe?g)
+/.*explorer?.(gif|jpe?g)
+/.*freeie\.(gif|jpe?g)
+/.*/ie_?(buttonlogo|static?|anim.*)?\.(gif|jpe?g)
+/.*ie_sm\.(gif|jpe?g)
+/.*msie(30)?\.(gif|jpe?g)
+/.*msnlogo\.(gif|jpe?g)
+/.*office97_ad1\.(gif|jpe?g)
+/.*pbbobansm\.(gif|jpe?g)
+/.*powrbybo\.(gif|jpe?g)
+/.*sqlbans\.(gif|jpe?g)
+/.*exc_ms\.gif
+/.*ie4get_animated\.gif
+/.*ie4_animated\.gif
+/.*n_iemap\.gif
+/.*ieget\.gif
+/.*logo_msnhm_*
+/.*mcsp2\.gif
+/.*msn2\.gif
+/.*add_active\.gif
+/.*n_msnmap\.gif
+/.*Ad00\.gif
+/.*s_msn\.gif
+/.*addchannel\.gif
+/.*adddesktop\.gif
+/.*/ns4\.gif
+/.*/v3sban\.gif
+/.*/?FPCreated\.gif
+/.*/opera35\.gif
+/.*/opera13\.gif
+/.*/opera_b\.gif
+/.*/ie_horiz\.gif
+/.*/ie_logo\.gif
+
+# ... and even more!
+/.*/favicon\.ico
+
+# generally useless information and promo stuff (commented out)
+#/*.*/(counter|getpcbutton|BuiltByNOF|netscape|hotmail|vcr(rated)?|rsaci(rated)?|freeloader|cache_now(_anim)?|apache_pb|now_(anim_)?button|ie_?(buttonlogo|static?|.*ani.*)?)\.(gif|jpe?g)
+
+/*.*/images/na/us/brand/
+/*.*/advantage\.(gif|jpg)
+/*.*/advanbar\.(gif|jpg)
+/*.*/advanbtn\.(gif|jpg)
+/*.*/biznetsmall\.(gif|jpg)
+/*.*/utopiad\.(gif|jpg)
+/*.*/epipo\.(gif|jpg)
+/*.*/amazon([a-zA-Z0-9]+)\.(gif|jpg)
+/*.*/bnlogo.(gif|jpg)
+/*.*/buynow([a-zA-Z0-9]+)\.(gif|jpg)
+
+/p/d/publicid
+
+
+# for the dutch folks by a dutch friend gertjan@west.nl
+/*.*/Advertenties/
+/.*./Adverteerders/
+netdirect.nl/nd_servlet/___
+
+# --------------------------------------------------------------------------
+#
+# specific servers
+#
+# --------------------------------------------------------------------------
+
+# the next two lines work
+12.16.1.10/web_GIF
+12.16.1.10/~web_ani
+193.158.37.3/cgi-bin/impact
+193.210.156.114
+193.98.1.160/img
+194.221.183.222/mailsentlu
+194.221.183.223
+194.221.183.224
+194.221.183.225
+194.221.183.226
+194.221.183.227
+194.231.79.38
+195.124.124.56
+195.27.70.69
+195.30.94.21
+195.63.104.222//inbox
+195.63.104.222//log # www.weltbild.de
+195.63.104.222//meld
+195.63.104.222//menu
+195.63.104.222/folderlu
+195.63.104.222/folderru
+195.63.104.222/inbox
+195.63.104.222/loginlu
+195.63.104.222/loginmu
+195.63.104.222/loginru
+195.63.104.222/logoutlu
+195.63.104.222/logoutmu
+195.63.104.222/logoutru
+195.63.104.61//inbox
+195.63.104.61//log # www.weltbild.de
+195.63.104.61//meld
+195.63.104.61//menu
+195.63.104.61/inbox
+195.63.104.61/loginlu
+195.63.104.61/loginmu
+195.63.104.61/loginru
+195.63.104.61/logoutlu
+195.63.104.61/logoutmu
+195.63.104.61/logoutru
+199.78.52.10
+1st-fuss.com
+204.253.46.71:1977
+204.94.67.40/wc/
+205.153.208.93
+205.216.163.62
+205.217.103.58:1977
+206.165.5.162/images/gcanim\.gif
+206.221.254.181:80
+206.50.219.33
+207.137.96.35
+207.159.129.131/abacus
+207.159.135.72
+207.82.250.9
+207.87.15.234
+207.87.27.10/tool/includes/gifs/
+208.156.39.142
+208.156.39.144
+208.156.60.230
+208.156.60.234
+208.156.60.235
+209.1.112.252/adgraph/
+209.1.135.142:1971
+209.1.135.144:1971
+209.132.97.164/IMG/
+209.185.222.45
+209.185.222.60
+209.185.253.199
+209.207.224.220/servfu.pl
+209.207.224.222/servfu.pl
+209.239.37.214/cgi-pilotfaq/getimage\.cgi
+209.297.224.220
+209.75.21.6
+209.85.89.183/cgi-bin/cycle\?host
+212.63.155.122/(banner|concret|softwareclub)
+216.15.157.34
+216.27.61.150
+216.49.10.236/web1000/
+247media.com
+62.144.115.12/dk/
+ICDirect.com/cgi-bin
+Shannon.Austria.Eu.net/\.cgi/
+WebSiteSponsor.de
+207.181.220.145
+213.165.64.42
+
+#
+# generic hosts (probably most effective)
+#
+ad*.*.*
+ad*.*.*.*
+*.ads.*.*
+banner*.*.*
+banner*.*.*.*
+
+*.admaximize.com
+*.imgis.com
+/*.*/*preferences.com*
+1ad.prolinks.de
+adwisdom.com
+akamaitech.net/.*/Banners/
+altavista.telia.com/av/pix/sponsors/
+amazon.com/g/associates/logos/
+annonce.insite.dk
+asinglesplace.com/asplink\.gif
+athand.com/rotation
+automatiseringgids.nl/gfx/advertenties/
+#avenuea.com/Banners/
+avenuea.com/view/
+badservant.guj.de
+befriends.net/personals/matchmaking\.jpg
+bizad.nikkeibp.co.jp
+bs.gsanet.com/gsa_bs/
+cash-for-clicks.de
+cda.at/customer/
+cgicounter.puretec.de/cgi-bin/
+ciec.org/images/countdown\.gif
+classic.adlink.de/cgi-bin/accipiter/adserver.exe
+click..wisewire.com
+clickhere.egroups.com/img/
+imagine-inc.com
+commonwealth.riddler.com/Commonwealth/bin/statdeploy\?[0-9]+
+customad.cnn.com
+dagbladet.no/ann-gif
+deja.com/jump/
+digits.com/wc/
+dino.mainz.ibm.de
+dn.adzerver.com/image.ad
+ds.austriaonline.at
+emap.admedia.net
+etrade.com/promo/
+eur.yimg.com/a/
+eur.a1.yimg.com/eur.yimg.com/a/
+us.a1.yimg.com/us.yimg.com/a/
+eurosponsor.de
+fastcounter.linkexchange.com
+flycast.com
+focalink.com/SmartBanner
+freepage.de/cgi-bin/feets/freepage_ext/.*/rw_banner
+freespace.virgin.net/andy.drake
+futurecard.com/images/
+gaia.occ.com/click.*
+globaltrack.com
+globaltrak.net
+go.com/cimages\?SEEK_
+gp.dejanews.com/gtplacer
+gtp.dejanews.com/gtplacer
+deja.com/gifs/onsale/
+hitbox.com
+home.miningco.com/event.ng/.*AdID
+hurra.de
+hyperbanner.net
+icount.com/.*count
+image*.narrative.com/news/.*\.(gif|jpe?g)
+image.click2net.com
+image.linkexchange.com
+images.nytimes.com
+images.yahoo.com/adv/
+images.yahoo.com/promotions/
+imageserv.adtech.de
+img.web.de
+impartner.de/cgi-bin
+informer2.comdirect.de:6004/cd/banner2
+infoseek.go.com/cimages
+ins.at/asp/images/
+kaufwas.com/cgi-bin/zentralbanner\.cgi
+leader.linkexchange.com
+link4ads.com
+link4link.com
+linktrader.com/cgi-bin/
+logiclink.nl/cgi-bin/
+lucky.theonion.com/cgi-bin/oniondirectin\.cgi
+lucky.theonion.com/cgi-bin/onionimp\.cgi
+lucky.theonion.com/cgi-bin/onionimpin\.cgi
+m.doubleclick.net
+mailorderbrides.com/mlbrd2\.gif
+media.priceline.com
+mediaplex.com
+members.sexroulette.com
+messenger.netscape.com
+miningco.com/zadz/
+# movielink became moviefone
+moviefone.com/.*banner
+moviefone.com/.*newbutton
+moviefone.com/.*ad\.gif
+moviefone.com/.*mmail
+moviefone.com/.*poster\.gif
+moviefone.com/.*btyb
+moviefone.com/.*h_guy
+moviefone.com/.*h_showtick
+moviefone.com/.*h_aML
+moviefone.com/.*/m_
+moviefone.com/.*/icon_
+moviefone.com/.*/NF_.*back
+moviefone.com/.*/h_.*gif
+moviefone.com/media/imagelinks
+moviefone.com/media/imagelinks/MF.(ad|sponsor)
+moviefone.com/media/art
+mqgraphics.mapquest.com/graphics/Advertisements/
+netgravity.*
+newads.cmpnet.com
+news.com/cgi-bin/acc_clickthru
+ngadcenter.net
+ngserve.pcworld.com/adgifs/
+nol.at:81
+nrsite.com
+nytsyn.com/gifs
+offers.egroups.com
+pagecount.com
+ph-ad.*\.focalink.com
+preferences.com
+promotions.yahoo.com/
+pub.nomade.fr
+qsound.com/tracker/tracker.exe
+resource-marketing.com/tb/
+revenue.infi.net
+rtl.de/homepage/wb/images/
+schnellsuche.de/images/*
+shout-ads.com/cgibin/shout.php3
+sjmercury.com/advert/
+smartclicks.com/.*/smart(img|banner|host|bar|site)
+smh.com.au/adproof/
+spinbox1.filez.com
+static.wired.com/advertising/
+swiftad.com
+sysdoc.pair.com/cgi-sys/cgiwrap/sysdoc/sponsor\.gif
+t-online.de/home/040255162-001/*
+taz.de/taz/anz/
+tcsads.tcs.co.at
+teleauskunft.de/commercial/
+thecounter.com/id
+tm.intervu.net
+tvguide.com/rbitmaps/
+ubl.com/graphics/
+ubl.com/images/
+ultra.multimania.com
+ultra1.socomm.net
+uproar.com
+us.yimg.com/a/
+us.yimg.com/promotions/
+valueclick.com
+valueclick.net
+victory.cnn.com
+videoserver.kpix.com
+washingtonpost.com/wp-adv/
+webconnect.net/cgi-bin/webconnect.dll
+webcounter.goweb.de
+webserv.vnunet.com/ip_img/.*ban
+werbung.pro-sieben.de/cgi-bin
+whatis.com/cgi-bin/getimage.exe/
+www..bigyellow.com/......mat.*
+www.adclub.net
+www.addme.com/link8\.gif
+www.aftonbladet.se/annons
+www.americanpassage.com/
+www.angelfire.com/in/twistriot/images/wish4\.gif
+www.bizlink.ru/cgi-bin/irads\.cgi
+www.blacklightmedia.com/adlemur
+www.bluesnews.com/flameq\.gif
+www.bluesnews.com/images/ad[0-9]+\.gif
+www.bluesnews.com/images/gcanim3\.gif
+www.bluesnews.com/images/throbber2\.gif
+www.bluesnews.com/miscimages/fragbutton\.gif
+www.businessweek.com/sponsors/
+www.canoe.ca/AdsCanoe/
+www.cdnow.com/MN/client.banners
+www.clickagents.com
+www.clickthrough.ca
+www.clicmoi.com/cgi-bin/pub\.exe
+www.dailycal.org/graphics/adbanner-ab\.gif
+www.detelefoongids.com/pic/[0-9]*
+www.dhd.de/CGI/werbepic
+www.dsf.de/cgi-bin/site_newiac.adpos
+www.firsttarget.com/cgi-bin/klicklog.cgi
+www.forbes.com/forbes/gifs/ads
+www.forbes.com/tool/includes/gifs/
+www.fxweb.holowww.com/.*\.cgi
+www.geocities.com/TimesSquare/Zone/5267/
+www.goto.com/images-promoters/
+www.handelsblatt.de/hbad
+www.hotlinks.de/cgi-bin/barimage\.cgi
+www.infoseek.com/cimages
+www.infoworld.com/pageone/gif
+www.isys.net/customer/images
+www.javaworld.com/javaworld/jw-ad
+www.kron.com/place-ads/
+www.leo.org/leoclick/
+www.linkexchange.ru/cgi-bin/erle\.cgi
+www.linkstation.de/cgi-bin/zeige
+www.linux.org/graphic/miniature/
+www.linux.org/graphic/square/
+www.linux.org/graphic/standard/
+www.luncha.se/annonsering
+www.mediashower.com
+www.ml.org/gfx/spon/icom/
+www.ml.org/gfx/spon/wmv
+www.musicblvd.com/mb2/graphics/netgravity/
+nedstat.nl/cgi-bin/
+www.news.com/Midas/Images/
+www.newscientist.com/houseads
+www.nextcard.com/affiliates/
+www.nikkeibp.asiabiztech.com/image/NAIS4\.gif
+www.nordlys.no/imaker/.*/.*/.*/.....\.gif # alvin brattli
+www.nordlys.no/imaker/.*/.*/.*/..003 # alvin brattli
+www.oanda.com/server/banner
+omdispatch.co.uk
+www.oneandonlynetwork.com
+www.page2page.de/cgi-bin/
+www.prnet.de/.*/bannerschnippel/.*\.(gif|jpe?g)
+www.promptsoftware.com/marketing/
+#www.reklama.ru/cgi-bin/banners/
+www.riddler.com/sponsors/
+www.rle.ru/cgi-bin/erle\.cgi
+www.rock.com/images/affiliates/search_black\.gif
+www.rtl.de/search/.*kunde
+#www.search.com/Banners
+www.sfgate.com/place-ads/
+www.shareware.com/midas/images/borders-btn\.gif
+#www.sjmercury.com/products/marcom/banners/
+www.smartclicks.com:81
+www.sol.dk/graphics/portalmenu
+www.sponsornetz.de/jump/show.exe
+www.sponsorpool.net
+www.sunworld.com/sunworldonline/icons/adinfo.sm\.gif
+www.swwwap.com/cgi-bin/
+www.taz.de/~taz/anz/
+www.telecom.at/icons/.*film\.(gif|jpe?g)
+www.theonion.com/bin/
+www.topsponsor.de/cgi-bin/show.exe
+www.ugo.net
+www.ugu.com/images/EJ\.gif
+www.warzone.com/pics/banner/
+www.warzone.com/wzfb/ads.cgi
+www.webpeep.com
+www.websitepromote.com/partner/img/
+www.winjey.com/onlinewerbung/*\.gif
+www.wishing.com/webaudit
+www.www-pool.de/cgi-bin/banner-pool
+www2.blol.com/agrJRU\.gif
+www3.exn.net:80
+yahoo.com/CategoryID=0
+yahoo.de/adv/images
+~cpan.valueclick.com
+~www.hitbox.com
+
+#swa
+www.bannerland.de/click.exe
+*.cyberclick.net
+*.eu-adcenter.net/
+www.web-stat.com
+www.slate.com/snav/
+www.slate.com/redirect/
+www.slate.com/articleimages/
+usads.imdb.com
+www.forbes.com/tool/images/frontend/
+www.zserver.com
+www.spinbox.com
+pathfinder.com/shopping/marketplace/images/
+/*.*/adbanner*
+/*.*/adgraphic*
+static.wired.com/images
+perso.estat.com/cgi-bin/perso/
+dinoadserver1.roka.net
+fooladclient*.fool.com
+affiliate.aol.com/static/
+cybereps.com:8000
+iadnet.com
+orientserve.com
+wvolante.com
+findcommerce.com
+smartage.com
+
+# www.sunday-times.co.uk
+www.sunday-times.co.uk/standing/newsint/ticker
+
+# Für Germany.Net-User: Germany.Net (fast) banner- u. grafikfrei!
+germany.net/gebu-frei\.gif
+germany.net/bilder/menue/leiste\.gif
+germany.net/bilder/gn_logos/*
+germany.net/bilder/90x90/*
+germany.net/banner-homepage/*
+germany.net/downloadshop/*
+germany.net/bilder/action/promopoly/germanynet/basisdienste/hilfe/*
+
+# Block as much of GeoCities as possible
+# All geocities-owned images
+www.geocities.com/images
+www.geocities.com/MemberBanners/live/
+pic.geocities.com/images
+# And the popup (it still pops up, but does not eat up precious bandwidth)
+#www.geocities.com/ad_container/pop.html # already fixed by other regexp
+
+# from corion@informatik.uni-frankfurt.de
+sam.songline.com/@
+img.getstats.com/
+#ads.xmonitor.net/xadengine.cgi # fixed by above regexp
+# Also block the japanese geocities popups
+www.geocities.co.jp/images
+# Also block the come.to, surf.to etc. popups
+v3.come.to/pop.asp
+
+# Also block the xoom stuff.
+xb.xoom.com
+home.talkcity.com/homepopup.html.*
+
+# Max Maischein <max.maischein@econsult.de> again ...
+# Halflife.net uses WON banners
+# Banners from Freeserve
+#banner.freeservers.com/cgi-bin/fs_adbar # fixed by above regexp
+# And those nasty va-popups !
+/.*/?va_banner.html
+# And an all-around hit against advert*.jpg
+/.*/advert[0-9]+\.jpg
+# And yet another Internet Explorer gif ...
+/.*/ie_horiz\.gif
+# Some uninteresting buttons I think...
+mircx.com/images/buttons/
+services.mircx.com/.*\.gif
+# Ooops - UserFriendly (Iambe) has a banner that gets eaten ...
+~www.userfriendly.org/images/banners/banner_dp_heart\.gif
+# Easyspace - yet another "free disk space" provider with <yuck> banner popups
+www.easyspace.com/(fpub)?banner.html
+www.easyspace.com/100\.gif
+# Some russian banner exchanges
+banner.ricor.ru/cgi-bin/banner.pl
+#www.bizlink.ru/cgi-bin/irads.cgi # already fixed by other regexp
+stx9.sextracker.com/stx/send/
+# And even more of geocities :
+www.geocities.com/pictures/
+# Gaah - www.angelfire.com - another webspace provider with popups
+angelfire.com/sys/download.html
+# Gamasutra.com uses this ad provider
+sally.songline.com/@
+
+# Eule.de (search engine)
+# maybe images.eule.de as a whole...
+www.eule.de/cgi-bin/
+images.eule.de/comdirect\.gif
+images.eule.de/wp\.gif
+aladin.de/125_1\.gif
+images.eule.de/neu/books\.gif
+
+# --------------------------------------------------------------------------
+#
+# some images
+#
+# --------------------------------------------------------------------------
+
+# some images on cnn's website just suck!
+/.*cnnstore\.gif
+/.*book.search\.gif
+/.*cnnpostopinionhome.\.gif
+/.*custom_feature\.gif
+/.*explore.anim.*gif
+/.*infoseek\.gif
+/.*pathnet.warner\.gif
+/.*images/cnnfn_infoseek\.gif
+/.*images/pathfinder_btn2\.gif
+/.*img/gen/fosz_front_em_abc\.gif
+/.*img/promos/bnsearch\.gif
+/.*navbars/nav_partner_logos\.gif
+/BarnesandNoble/images/bn.recommend.box.*
+/digitaljam/images/digital_ban\.gif
+/hotstories/companies/images/companies_banner\.gif
+/markets/images/markets_banner\.gif
+/ows-img/bnoble\.gif
+/ows-img/nb_Infoseek\.gif
+cnn.com/images/custom/totale\.gif
+cnn.com/images/lotd/custom.wheels\.gif
+cnn.com/images/.*/by/main.12\.gif
+cnn.com/images/.*/find115\.gif
+cnn.com/.*/free.email.120\.gif
+cnnfn.com/images/left_banner\.gif
+focus.de/A/AF/AFL/
+www.cnn.com/images/.*/bn/books\.gif
+www.cnn.com/images/.*/pointcast\.gif
+www.cnn.com/images/.*/fusa\.gif
+cnn.com/images/.*/start120\.gif
+images.cnn.com/SHOP/
+/.*by/main\.gif
+/.*gutter117\.gif
+/.*barnes_logo\.gif
+# the / indicates the beginning of the path (and no longer the FQDN)
+/.*nbclogo\.gif
+/.*microdell\.gif
+/.*secureit\.gif
+
+g.deja.com/gifs/(q|us)west_120x120\.gif
+
+#
+/gif/buttons/banner_.*
+/gif/buttons/cd_shop_.*
+/gif/cd_shop/cd_shop_ani_.*
+
+#altavista
+/av/gifs/av_map\.gif
+/av/gifs/av_logo\.gif
+/av/gifs/new/ns\.gif
+altavista.com/i/valsdc3\.gif
+jump.altavista.com/gn_sf
+
+# tucows
+tucows.*.*/images/locallogo\.gif
+#tucows.dsuper.net/images/locallogo\.gif
+
+#
+mt_freshmeat\.jpg
+
+# simpliemu.hypermart.net/frames.html
+go2net.com/mgic/adpopup
+go2net.com/metaspy/images/exposed\.gif
+go2net.com/metaspy/images/ms_un\.gif
+
+#
+www.cebu-usa.com/cwbanim1\.gif
+www.cebu-usa.com/Connection\.jpg
+www.cebu-usa.com/phonead\.gif
+www.cebu-usa.com/ban3\.jpg
+www.cebu-usa.com/tlban\.gif
+www.cebu-usa.com/apwlogo1\.gif
+www.cebu-usa.com/rose\.gif
+
+# fnet
+www.fnet.de/img/geldboerselogo\.jpg
+
+# hirsch@mathcs.emory.edu
+/images/getareal2\.gif
+
+www.assalom.com/aziza/logos/cniaffil\.gif
+www.assalom.com/aziza/logos/4starrl1\.gif
+www.phantomstar.com/images/media/m1\.gif
+
+#
+wahlstreet.de/MediaW\$/tsponline\.gif
+wahlstreet.de/MediaW\$/dzii156x60\.gif
+wahlstreet.de/MediaW\$/etban156x60_2_opt2\.gif
+
+# linuxtoday.com
+/pics/gotlx1\.gif
+/pics/getareal1\.gif
+/pics/amzn-b5\.gif
+/ltbs/cgi-bin/click.cgi
+linuxtoday.com/ltbs/pics/
+
+# Geocities popups
+/ad[-_]container/
+/include/watermark/v2/
+
+# Reinier Bikker <R.P.Bikker@phys.uu.nl>
+# Banner.xxLINK.nl/
+
+# Mark Lutz <luma@nikocity.de>
+/.*/*werb.*\.(gif|jpe?g) # hope that's not to restrictive
+
+#Free Yellow thing at bottom of pages (HereticPC)
+www.freeyellow.com/images/powerlink5a\.gif
+www.freeyellow.com/images/powerlink5b\.gif
+www.freeyellow.com/images/powerlink5c\.gif
+www.freeyellow.com/images/powerlink5d\.gif
+www.freeyellow.com/images/powerlink5e\.gif
+
+#HereticPC
+www.eads.com/images/refbutton\.gif
+www.fortunecity.com/console2/newnav/*
+www.goldetc.net/search\.gif
+www.cris.com/~Lzrdking/carpix/cars3-le\.gif
+www.justfreestuff.com/scott\.gif
+www.cyberthrill.com/entrance\.gif
+secure.pec.net/images/pec69ani\.gif
+www.new-direction.com/avviva\.gif
+internetmarketingcenter\.gif
+www.new-direction.com/wp-linkexchange-loop\.gif
+www.new-direction.com/windough\.gif
+www.digitalwork.com/universal_images/affiliate/dw_le_3\.gif
+service.bfast.com/bfast/click/*
+www.new-direction.com/magiclearning\.gif
+www.new-direction.com/mailloop\.gif
+
+www.free-banners.com/images/hitslogo\.gif
+rob.simplenet.com/dyndns/fortune5\.gif
+nasdaq-amex.com/images/bn_ticker\.gif
+
+#
+# navilor@hotmail.com
+#
+#
+# wayne@staff.msen.com
+#
+a*.*.*.yimg.com/([0-9]*|\/)*us.yimg.com/*
+ad.doubleclick.net
+www.dnps.com/ads
+www.realtop50.com/cgi-bin/ad
+~a*.*.*.yimg.com/([0-9]|\/)*us.yimg.com/i/*
+
+#
+www.yacht.de/images/(my_ani|eissingani|chartertrans|fum|schnupper|fysshop|garmin)\.gif
+www.sponsorweb.de/web-sponsor/nt-bin/show.exe
+
+#
+# Club-internet pops up a complain if you refuse cookie (still pops up...)
+perso.club-internet.fr/html/Popup/popup_frame_nocookie.html
+perso.club-internet.fr/pagesperso/popup_nocookie.html
+
+gmx.net/images/newsbanner/
+cash4banner.de
+
+quicken.lexware.de/images/us7-468x60.gif
+/img/special/chatpromo\.gif
+www.travelocity.com/images/promos/
+
+# wonder that that does...
+p01.com/1x1.dyn
+
+/*.*/phpAds/viewbanner.php
+/*.*/phpAds/phpads.php
+
+www.linux-magazin.de/banner
+comtrack.comclick.com
+click-fr.com
+iac-online.de/filler
+
+media.interadnet.com
+stat.www.fi/cgi-bin
+/cgi/banners.cgi
+ads-digi.sol.no
+fp.buy.com
+disneystoreaffiliates.com
+
+powerwork.mobile.de/cgi-bin/getimage\.cgi
+
+
+
+####################################################
+# Jon's addition:
+#
+# Register ads
+#www.theregister.co.uk/media/155\.gif
+www.theregister.dealtime.co.uk/BannerIn/
+#www.theregister.co.uk/media/SearchDomainRed\.gif
+#www.theregister.co.uk/media/ByDomainbusterRed\.gif
+#www.theregister.co.uk/media/454\.gif
+#www.theregister.co.uk/media/461\.gif
+#www.theregister.co.uk/media/dealtime-lh\.gif
+# Ad target:
+www.domainbuster.com/cgi-bin/domainbuster/dpro\.pl
+
+#www.theregister.co.uk/media/.*\.swf
+#www.theregister.co.uk/media/.*\.js
+
+# get agressive:
+www.theregister.co.uk/media/
+
+# Dilbert:
+www.dilbert.com/comics/dilbert/images/.*_140x800.*\.gif
+
+# stattrack.com
+# Uses URL: http://www.stattrack.com/cgi-bin/stats/image.cgi
+/cgi-bin/stats/
+# And loads JavaScript from http://www.stattrack.com/stats/code
+www.stattrack.com/stats/
+
+#GeoCities crap
+##geo.yahoo.com/serv
+##visit.geocities.com/visit.gif
+*.*.*.yimg.com/*/www.geocities.com/js_source
+#http://us.toto.geo.yahoo.com/toto?s=76001086
+##*.toto.geo.yahoo.com
+
+# Nuke GeoCities rubbish
+*.*.geo.yahoo.com
+*.geo.yahoo.com
+geo.yahoo.com
+visit.geocities.com
+*.*.*.yimg.com/.*/www.geocities.com/
+
+#http://counter16.bravenet.com/counter.php
+counter*.*.*
+
+#http://stat.cybermonitor.com/7emezone_p?1707_USdvd
+stat*.*.*
+
+#http://members.tripod.com/adm/popup/.....
+members.tripod.com/adm/popup/
+
+#This is the worst ad idea ever! Bye bye!
+#count.exitexchange.com/exit/1100661
+#count.exitexchange.com/clients/navbar.html
+#(used in http://skyhivisuals.tripod.com/malfunctions_.htm)
+exitexchange.com
+
+#SourceForge ads.
+sfads.osdn.com
+
+#Crap trapping sites
+webhideout.com
+
+####################################################
+
+
+
+#
+# some regexps are simply too aggressive ...
+#
+# equalizer to /*.*(.*[-_.])?ads?[0-9]?(/|[-_.].*|.(gif|jpe?g))
+# or other regexps
+#
+#
+~adamwhone.co.uk
+~adsl.tin.it
+~stsci.edu
+~tgs.com
+~sun.com
+~povray.org
+~admin.*.*
+~admin.*.*.*
+~ad.siemens.de # SIEMENS Automation & Drives
+~add-url.altavista.com
+~adis.on.ca
+~address*.*.*
+~address*.*.*.*
+~add*.*.*
+~add*.*.*.*
+~adu*.*.*
+~adu*.*.*.*
+~advice.*.*
+~advice.*.*.*
+
+# univ. don't advertise, do they :-)
+~*.*.edu
+~*.*.*.edu
+~www.ugu.com/sui/ugu/adv
+~adfa.edu.au
+~adsl*.*.*
+
+~clubs.yahoo.com/clubs
+~edit.my.yahoo.com/config/show_identity
+~www.ix.de/newsticker/data/ad
+~www.heise.de/newsticker/data/ad
+~www.careernet.de/anzeige
+~www.careernet.de/bewerber/stellenanzeigen
+~www.baumgartner.de/stellenmarkt/anzeigen
+~www.dspartner.de/Anzeigen
+~www.aws-jobs.de/Anzeigen
+~www.jobware.de/.*/anzeigen/
+~www.jobworld.de/bilder/
+~www.cnn.com/TECH/computing/.*/internet.ads/
+~www.financial.de/shop/
+~gnn.de/.*\.html
+~www.auktionen.de
+
+~194.221.152.2/phptelefontmp
+~harvard.edu/images/banner/
+
+~adswww.harvard.edu
+~www.dhd.de/CGI/anzeigen/
+
+~ads.web.de/web/
+~img.web.de/web/img/
+
+~www.segel.de/menu/bilder/anzeigen\.gif
+~www.corel.com/graphics/banners/
+~www.software.ibm.com/ad/
+~www.omg.org/docs/ad/
+
+~sperrmuell.de/scripts/anzeigen
+www.freenet.de/index.html
+www.01019freenet.de/index.html
+~www.freenet.de/freenet/
+~www.01019freenet.de/freenet/
+~webfactory.de/anzeigen.php
+~www.cdmag.com
+~www.internatif.org/bortzmeyer/debian/sponsor/
+~hp.com
+
+~www.software.hosting.ibm.com/ad/
+~www.ibm.com/software/ad/
+~brickshelf.com
+
+~www.debian.org/Pics/banner-blue\.gif
+~www.linux.de/pics/Nachrichten_banner\.gif
+~www.werbekurier.de
+
+~finder.shopping.yahoo.com/shop/
+~national.com/pf
+~mozilla.org
+~eidos.de
+~e-sheep.com
+~punkassgear.com
+~mozilla.org
+~mozillazine.org
+~adbusters.org
+~annoy.com
+~consumer-direct.com
+~www.iez-auktion.de
+~ibm.com
+~sgi.com
+
+# my banking stuff => no ads. last regexp for fast access :-)
+~comdirekt.de
+~comdirect.de
+~teledata.de
+
+
+~msdn.microsoft.com
+
+# do not forget newline at the end of this file!!!
+
--- /dev/null
+# Sample Configuration file for the Internet Junkbuster 2.0
+
+#
+# $Id: config,v 1.2 2001/04/30 03:05:11 rodney Exp $
+#
+
+#
+#
+# Copyright 1997-8 Junkbusters Corp. For distribution, modification and use
+# under the GNU General Public License. These files come with NO WARRANTY.
+# See http://www.junkbusters.com/ht/en/gpl.html or README file for details.
+#
+# When starting the proxy, give the name of this file as an argument.
+# Any changes made to this file are *not* automatically loaded; you have
+# to stop and restart the proxy.
+
+# For information see http://www.junkbusters.com/ht/en/ijbman.html
+# or the documentation that came with the release
+
+# Lines beginning with a # character are comments; they are ignored.
+# Many example lines are provided here commented out
+
+# the blockfile contains patterns to be blocked by the proxy
+blockfile ./blocklist # comments are OK here, too
+
+# the imagefile contains patterns to detect blocked images
+imagefile ./imagelist
+
+# the popfile contains patterns of servers where javascript popups are disabled
+#
+# if the next line is not commented out, all javascript popups from the sites
+# that match the patterns in popup will be blocked
+# popupfile ./popup
+
+# File containing content modification rules
+#re_filterfile ./re_filterfile
+
+# Uncomment to filter *all* traffic. Default is to
+# filter only if we wouldn't send a cookie either.
+#
+#re_filter_all
+
+
+# the cookiefile contains patterns to specify the cookie management policy
+#
+cookiefile ./cookiefile
+
+# the logfile is where all logging and error messages are written
+#
+logfile ./junkbuster.log
+
+# the jarfile is where cookies can be stored
+#
+#jarfile ./jarfile
+
+# the forwardfile defines domain-specific routing
+#
+#forwardfile ./forward
+
+# file which lists and into which trusted domains are written
+#
+#trustfile ./trust
+# files specify locations of "for information about trusted referers, see.."
+# multiple trust_info_url lines are OK
+#
+# trust_info_url http://internet.junkbuster.com/
+# trust_info_url http://www.yoursite.com/our_trust_policy.html
+#
+
+# The access control list file can be used to restrict IP addresses
+# that are permitted to use the proxy (see warnings in the FAQ).
+#
+#aclfile ./aclfile
+
+# add an "X-Forwarded-For:" specification to each request header
+#
+#add-forwarded-header
+
+# if logging cookies into a jarfile, and no other wafers were
+# explicity set, then by default a vanilla wafer is sent with
+# each request.
+#
+# setting 'suppress-vanilla-wafer' stops this vanilla wafer from
+# being sent.
+#
+suppress-vanilla-wafer
+
+# add these wafers to each request header
+# multiple wafer lines are OK
+#
+#wafer NOTE=Like most people, I want my browsing to be anonymous.
+#wafer WARNING=Please do not attempt to track me.
+
+# Anything can be added to the request headers. Please don't litter.
+# multiple add-header lines are OK
+#
+#add-header Forwarded: by http://stay-out-of-my-backyard.net
+#add-header Forwarded: by http://pro-privacy-isp.net
+#add-header Proxy-Connection: Keep-Alive
+
+# listen-address specifies where the Junkbuster will listen for connections
+# Specifying a port is optional; if unspecified the defaults is 8000.
+# Before Version 2.0.2 the default was to bind to all IP addresses (INADDR_ANY)
+# This has been restricted to localhost to avoid unintended security breaches.
+# To open the proxy to all, uncomment the following line:
+#listen-address :8000
+# other example usage:
+#listen-address 124.207.250.245:8080
+# to explicitly state what is now the default:
+#listen-address localhost
+# or equivalently:
+listen-address 127.0.0.1:8000
+
+# user-agent specifies treatment of the "User-Agent:" (and "UA-*:") header(s)
+# default: Forge the "User-Agent:"
+# 'text' : Always send <text> as the "User-Agent:"
+# . : Pass the "User-Agent:" unchanged
+# @ : Pass the "User-Agent:" if the server is in the cookie file,
+# forge the "User-Agent:" otherwise
+#user-agent @
+
+# note: Russian browsers may be confused if user agent misidentifies
+# the operating system (Mac vs Windows); see FAQ
+user-agent .
+
+# referer specifies treatment of the "Referer:" header
+# New option by "Andreas S. Oesterhelt" <oes@paradis.rhein.de>
+#
+# default: Kill the referrer-header from the client
+# 'text' : Always send <text> as the referrer
+# . : Pass the referrer unchanged
+# @ : Pass the referrer if the server is in the cookie file,
+# kill the referrer otherwise
+# § : Pass the referrer if the server is in the cookie file,
+# send a forged referrer that points to the root-diretory URL
+# of the current request otherwise
+referer §
+
+# from specifies value to be subsituted if browser provides a "From:" header
+#
+#from spam-me-senseless@sittingduck.net
+
+# tinygif allows you to change the appearance of blocked images
+#
+# tinygif 0 # Show a "broken icon"
+# tinygif 1 # Show a GIF of one transparent pixel
+# tinygif 2 # Show a GIF with the word "JUNKBUSTER"
+tinygif 2
+# tinygif 3 http://localhost/1x1.gif # Temporary redirect to this URL
+
+# Andrew <anw@tirana.freewire.co.uk> added
+# The following can be used to suppress display of the block lists when the
+# page http://x.x/show-proxy-args is displayed. With a long block list this
+# accelerates loading of the configuration page and also hides the contents of
+# the block lists (for whatever reason). Maintainers of junkbuster proxies for
+# multiple use can specify a message for any use who wants to know what is in
+# these files.
+#
+#suppress-blocklists Contact sysadmin@example.com for details.
+# suppress-blocklists
+
+# debug sets the level of debugging information to log in the logfile
+#
+# debug 1 # GPC = show each GET/POST/CONNECT request
+# debug 2 # CONN = show each connection status
+# debug 4 # IO = show I/O status
+# debug 8 # HDR = show header parsing
+# debug 16 # LOG = log all data into the logfile
+# debug 32 # FRC = debug force feature
+# debug 64 # REF = debug regular expression filter
+#
+# multiple "debug" directives, are OK - they're logical-OR'd together
+#
+#debug 15 # same as setting the first 4 listed above
+debug 1
+#debug 255
+
+# single-threaded operation (i.e. disallows multiple threads or processes)
+# This is most often used for debugging because it keeps the
+# debugging output "in order" for easy reading.
+#
+#single-threaded
+
+# Toggle flag. 0 => disabled, anything else (ie. 1) => enabled
+toggle 1
+
+
+# Win32 GUI specific options. Moved here from ijbw32.ini
+# in hopes of keep all of our config settings together.
+
+activity-animation 1
+log-messages 1
+log-highlight-messages 1
+log-buffer-size 1
+log-max-lines 200
+log-font-name Comic Sans MS
+log-font-size 8
+show-on-task-bar 0
+close-button-minimizes 1
+
+# hide-console is used only on Win32 console mode. It instructs
+# the Internet Junkbuster to disconnect from and hide the
+# command console.
+#
+#hide-console
+
+
--- /dev/null
+/* config.h. Generated automatically by configure. */
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+#ifndef _CONFIG_H
+#define _CONFIG_H
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/acconfig.h,v $
+ *
+ * Purpose : This file should be the first thing included in every
+ * .c file. (Before even system headers). It contains
+ * #define statements for various features. It was
+ * introduced because the compile command line started
+ * getting ludicrously long with feature defines.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: acconfig.h,v $
+ *
+ *********************************************************************/
+\f
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/*
+ * Version number - Major (X._._)
+ */
+#define VERSION_MAJOR 2
+
+/*
+ * Version number - Minor (_.X._)
+ */
+#define VERSION_MINOR 9
+
+/*
+ * Version number - Point (_._.X)
+ */
+#define VERSION_POINT 3
+
+/*
+ * Version number, as a string
+ */
+#define VERSION "2.9.3"
+
+/*
+ * Regular expression matching for URLs. (Highly recommended). If this is
+ * not defined then you can ony use prefix matching.
+ */
+#define REGEX 1
+
+/*
+ * Allow JunkBuster to be "disabled" so it is just a normal non-blocking
+ * non-anonymizing proxy. This is useful if you're trying to access a
+ * blocked or broken site - just change the setting in the config file
+ * and send a SIGHUP (UN*X), or use the handy "Disable" menu option (Windows
+ * GUI).
+ */
+#define TOGGLE 1
+
+/*
+ * Enables arbitrary content modification regexps
+ */
+#define PCRS 1
+
+/*
+ * If a stream is compressed via gzip (Netscape specific I think), then
+ * it cannot be modified with Perl regexps. This forces it to be
+ * uncompressed.
+ */
+#define DENY_GZIP 1
+
+/*
+ * Enables statistics function.
+ */
+#define STATISTICS 1
+
+/*
+ * Bypass filtering for 1 page only
+ */
+#define FORCE_LOAD 1
+
+/*
+ * Split the show-proxy-args page into a page for each config file.
+ */
+#define SPLIT_PROXY_ARGS 1
+
+/*
+ * Kills JavaScript popups - window.open, onunload, etc.
+ */
+#define KILLPOPUPS 1
+
+/*
+ * Support for webDAV - e.g. so Microsoft Outlook can access HotMail e-mail
+ */
+#define WEBDAV 1
+
+/*
+ * Detect image requests automatically for MSIE. Will fall back to
+ * other image-detection methods (i.e. USE_IMAGE_LIST) for other
+ * browsers.
+ *
+ * It detects the following header pair as an image request:
+ *
+ * User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
+ * Accept: * / *
+ *
+ * And the following as a HTML request:
+ *
+ * User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
+ * Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, * / *
+ *
+ * And no, I haven't got that backwards - IE is being wierd.
+ *
+ * Known limitations:
+ * 1) If you press shift-reload on a blocked HTML page, you get
+ * the image "blocked" page, not the HTML "blocked" page.
+ * 2) Once an image "blocked" page has been sent, viewing it
+ * in it's own browser window *should* bring up the HTML
+ * "blocked" page, but it doesn't. You need to clear the
+ * browser cache to get the HTML version again.
+ *
+ * These limitations are due to IE making inconsistent choices
+ * about which "Accept:" header to send.
+ */
+#define DETECT_MSIE_IMAGES 1
+
+/*
+ * Use image list to detect images.
+ * If you do not define this then everything is treated as HTML.
+ *
+ * Whatever the setting of this value, DETECT_MSIE_IMAGES will
+ * override it for people using Internet Explorer.
+ */
+#define USE_IMAGE_LIST 1
+
+/*
+ * Allows the use of ACL files to control access to the proxy by IP address.
+ */
+#define ACL_FILES 1
+
+/*
+ * Allows the use of trust files.
+ */
+#define TRUST_FILES 1
+
+/*
+ * Allows the use of jar files to capture cookies.
+ */
+#define JAR_FILES 1
+
+/*
+ * Use PCRE rather than GNU Regex
+ */
+#define PCRE 1
+
+/* Define if you have the bcopy function. */
+#define HAVE_BCOPY 1
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+#endif /* _CONFIG_H */
--- /dev/null
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+#ifndef _CONFIG_H
+#define _CONFIG_H
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/acconfig.h,v $
+ *
+ * Purpose : This file should be the first thing included in every
+ * .c file. (Before even system headers). It contains
+ * #define statements for various features. It was
+ * introduced because the compile command line started
+ * getting ludicrously long with feature defines.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: acconfig.h,v $
+ *
+ *********************************************************************/
+\f
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef size_t
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/*
+ * Version number - Major (X._._)
+ */
+#undef VERSION_MAJOR
+
+/*
+ * Version number - Minor (_.X._)
+ */
+#undef VERSION_MINOR
+
+/*
+ * Version number - Point (_._.X)
+ */
+#undef VERSION_POINT
+
+/*
+ * Version number, as a string
+ */
+#undef VERSION
+
+/*
+ * Regular expression matching for URLs. (Highly recommended). If this is
+ * not defined then you can ony use prefix matching.
+ */
+#undef REGEX
+
+/*
+ * Allow JunkBuster to be "disabled" so it is just a normal non-blocking
+ * non-anonymizing proxy. This is useful if you're trying to access a
+ * blocked or broken site - just change the setting in the config file
+ * and send a SIGHUP (UN*X), or use the handy "Disable" menu option (Windows
+ * GUI).
+ */
+#undef TOGGLE
+
+/*
+ * Enables arbitrary content modification regexps
+ */
+#undef PCRS
+
+/*
+ * If a stream is compressed via gzip (Netscape specific I think), then
+ * it cannot be modified with Perl regexps. This forces it to be
+ * uncompressed.
+ */
+#undef DENY_GZIP
+
+/*
+ * Enables statistics function.
+ */
+#undef STATISTICS
+
+/*
+ * Bypass filtering for 1 page only
+ */
+#undef FORCE_LOAD
+
+/*
+ * Split the show-proxy-args page into a page for each config file.
+ */
+#undef SPLIT_PROXY_ARGS
+
+/*
+ * Kills JavaScript popups - window.open, onunload, etc.
+ */
+#undef KILLPOPUPS
+
+/*
+ * Support for webDAV - e.g. so Microsoft Outlook can access HotMail e-mail
+ */
+#undef WEBDAV
+
+/*
+ * Detect image requests automatically for MSIE. Will fall back to
+ * other image-detection methods (i.e. USE_IMAGE_LIST) for other
+ * browsers.
+ *
+ * It detects the following header pair as an image request:
+ *
+ * User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
+ * Accept: * / *
+ *
+ * And the following as a HTML request:
+ *
+ * User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
+ * Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, * / *
+ *
+ * And no, I haven't got that backwards - IE is being wierd.
+ *
+ * Known limitations:
+ * 1) If you press shift-reload on a blocked HTML page, you get
+ * the image "blocked" page, not the HTML "blocked" page.
+ * 2) Once an image "blocked" page has been sent, viewing it
+ * in it's own browser window *should* bring up the HTML
+ * "blocked" page, but it doesn't. You need to clear the
+ * browser cache to get the HTML version again.
+ *
+ * These limitations are due to IE making inconsistent choices
+ * about which "Accept:" header to send.
+ */
+#undef DETECT_MSIE_IMAGES
+
+/*
+ * Use image list to detect images.
+ * If you do not define this then everything is treated as HTML.
+ *
+ * Whatever the setting of this value, DETECT_MSIE_IMAGES will
+ * override it for people using Internet Explorer.
+ */
+#undef USE_IMAGE_LIST
+
+/*
+ * Allows the use of ACL files to control access to the proxy by IP address.
+ */
+#undef ACL_FILES
+
+/*
+ * Allows the use of trust files.
+ */
+#undef TRUST_FILES
+
+/*
+ * Allows the use of jar files to capture cookies.
+ */
+#undef JAR_FILES
+
+/*
+ * Use PCRE rather than GNU Regex
+ */
+#undef PCRE
+
+/* Define if you have the bcopy function. */
+#undef HAVE_BCOPY
+
+/* Define if you have the memmove function. */
+#undef HAVE_MEMMOVE
+
+/* Define if you have the strerror function. */
+#undef HAVE_STRERROR
+
+#endif /* _CONFIG_H */
--- /dev/null
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-mingw32 Use mingw32 for a Windows GUI"
+ac_help="$ac_help
+ --disable-regex Don't allow regular expressions in the blockfile"
+ac_help="$ac_help
+ --disable-pcre-regex Use old, slow GNU Regex instead of PCRE."
+ac_help="$ac_help
+ --disable-toggle Don't support temporary disable"
+ac_help="$ac_help
+ --disable-pcrs Don't support arbitrary content modification"
+ac_help="$ac_help
+ --disable-force Don't allow blockfle to be bypassed"
+ac_help="$ac_help
+ --disable-killpopup Never block popups"
+ac_help="$ac_help
+ --disable-stats Don't keep statistics"
+ac_help="$ac_help
+ --disable-split-proxy-args One big show-proxy-args page, not one per file."
+ac_help="$ac_help
+ --disable-webdav Don't support WebDAV. This option stops MS Outlook
+ Express from accessing HotMail e-mail."
+ac_help="$ac_help
+ --disable-ie-images Don't auto-detect whether a request from MS Internet
+ Explorer is for an image or HTML."
+ac_help="$ac_help
+ --disable-image-list Don't try to figure out whether a request is for an
+ image or HTML using the imagelist - assume HTML."
+ac_help="$ac_help
+ --disable-acl-files Prevents the use of ACL files to control access to
+ the proxy by IP address."
+ac_help="$ac_help
+ --disable-trust-files Prevents the use of trust files."
+ac_help="$ac_help
+ --disable-jar-files Prevents the use of jar files to capture cookies."
+ac_help="$ac_help
+ --disable-static-pcre Link dynamically with the pcre and pcreposix
+ libraries. You must build the libraries seperately."
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=jcc.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+VERSION_MAJOR=2
+VERSION_MINOR=9
+VERSION_POINT=3
+
+
+
+
+
+cat >> confdefs.h <<EOF
+#define VERSION_MAJOR ${VERSION_MAJOR}
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION_MINOR ${VERSION_MINOR}
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION_POINT ${VERSION_POINT}
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_POINT}"
+EOF
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:592: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:622: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:673: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:705: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 716 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:721: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:747: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:752: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:761: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:780: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:812: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 827 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:833: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 844 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:850: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 861 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:867: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+
+echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
+echo "configure:893: checking for mingw32 environment" >&5
+if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 898 "configure"
+#include "confdefs.h"
+
+int main() {
+return __MINGW32__;
+; return 0; }
+EOF
+if { (eval echo configure:905: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_mingw32=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_mingw32=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_mingw32" 1>&6
+MINGW32=
+test "$ac_cv_mingw32" = yes && MINGW32=yes
+echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+echo "configure:922: checking for Cygwin environment" >&5
+if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 927 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#ifndef __CYGWIN__
+#define __CYGWIN__ __CYGWIN32__
+#endif
+return __CYGWIN__;
+; return 0; }
+EOF
+if { (eval echo configure:938: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_cygwin=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_cygwin=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_cygwin" 1>&6
+CYGWIN=
+test "$ac_cv_cygwin" = yes && CYGWIN=yes
+
+
+echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+echo "configure:957: checking for executable suffix" >&5
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+ ac_cv_exeext=.exe
+else
+ rm -f conftest*
+ echo 'int main () { return 0; }' > conftest.$ac_ext
+ ac_cv_exeext=
+ if { (eval echo configure:967: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ for file in conftest.*; do
+ case $file in
+ *.c | *.o | *.obj) ;;
+ *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
+ esac
+ done
+ else
+ { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
+ fi
+ rm -f conftest*
+ test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
+fi
+fi
+
+EXEEXT=""
+test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
+echo "$ac_t""${ac_cv_exeext}" 1>&6
+ac_exeext=$EXEEXT
+
+echo $ac_n "checking for object suffix""... $ac_c" 1>&6
+echo "configure:988: checking for object suffix" >&5
+if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ rm -f conftest*
+echo 'int i = 1;' > conftest.$ac_ext
+if { (eval echo configure:994: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ for ac_file in conftest.*; do
+ case $ac_file in
+ *.c) ;;
+ *) ac_cv_objext=`echo $ac_file | sed -e s/conftest.//` ;;
+ esac
+ done
+else
+ { echo "configure: error: installation or configuration problem; compiler does not work" 1>&2; exit 1; }
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_objext" 1>&6
+OBJEXT=$ac_cv_objext
+ac_objext=$ac_cv_objext
+
+
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1014: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1019 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1027: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1044 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1062 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1083 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1094: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:1119: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1124 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:1173: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:1194: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1199 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_size_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+ cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+
+for ac_func in strerror bcopy memmove
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1230: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1235 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1258: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+
+# Check whether --enable-mingw32 or --disable-mingw32 was given.
+if test "${enable_mingw32+set}" = set; then
+ enableval="$enable_mingw32"
+ if test $enableval = yes; then
+ WIN_ONLY=
+ CYGWIN_FLAGS="-mwindows -mno-cygwin"
+ echo "Using mingw32 (Win32 GUI)"
+ else
+ WIN_ONLY=#
+ if test "$CYGWIN" = "yes"; then
+ CYGWIN_FLAGS="-mno-win32"
+ echo "Using Cygnus (Win32 command line)"
+ else
+ CYGWIN_FLAGS=
+ fi
+ fi
+else
+ if test "$MINGW32" = "yes"; then
+ WIN_ONLY=
+ CYGWIN_FLAGS="-mwindows -mno-cygwin"
+ echo "Using mingw32 (Win32 GUI)"
+ else
+ WIN_ONLY=#
+ if test "$CYGWIN" = "yes"; then
+ CYGWIN_FLAGS="-mno-win32"
+ echo "Using Cygnus (Win32 command line)"
+ else
+ CYGWIN_FLAGS=
+ fi
+ fi
+fi
+
+
+
+
+
+SOLARIS_ONLY=#
+
+
+
+
+GNU_REGEX_ONLY=
+PCRE_REGEX_ONLY=
+NO_REGEX_ONLY=#
+
+# Check whether --enable-regex or --disable-regex was given.
+if test "${enable_regex+set}" = set; then
+ enableval="$enable_regex"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define REGEX 1
+EOF
+
+else
+ NO_REGEX_ONLY=
+ GNU_REGEX_ONLY=#
+ PCRE_REGEX_ONLY=#
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define REGEX 1
+EOF
+
+fi
+
+
+# Check whether --enable-pcre-regex or --disable-pcre-regex was given.
+if test "${enable_pcre_regex+set}" = set; then
+ enableval="$enable_pcre_regex"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define PCRE 1
+EOF
+
+ GNU_REGEX_ONLY=#
+else
+ PCRE_REGEX_ONLY=#
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define PCRE 1
+EOF
+
+ GNU_REGEX_ONLY=#
+
+fi
+
+
+
+
+
+
+
+
+# Check whether --enable-toggle or --disable-toggle was given.
+if test "${enable_toggle+set}" = set; then
+ enableval="$enable_toggle"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define TOGGLE 1
+EOF
+
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define TOGGLE 1
+EOF
+
+fi
+
+
+PCRS_ONLY=
+# Check whether --enable-pcrs or --disable-pcrs was given.
+if test "${enable_pcrs+set}" = set; then
+ enableval="$enable_pcrs"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define PCRS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define DENY_GZIP 1
+EOF
+
+else
+ PCRS_ONLY=#
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define PCRS 1
+EOF
+ cat >> confdefs.h <<\EOF
+#define DENY_GZIP 1
+EOF
+
+fi
+
+
+
+# Check whether --enable-force or --disable-force was given.
+if test "${enable_force+set}" = set; then
+ enableval="$enable_force"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define FORCE_LOAD 1
+EOF
+
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define FORCE_LOAD 1
+EOF
+
+fi
+
+
+# Check whether --enable-killpopup or --disable-killpopup was given.
+if test "${enable_killpopup+set}" = set; then
+ enableval="$enable_killpopup"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define KILLPOPUPS 1
+EOF
+
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define KILLPOPUPS 1
+EOF
+
+fi
+
+
+# Check whether --enable-stats or --disable-stats was given.
+if test "${enable_stats+set}" = set; then
+ enableval="$enable_stats"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define STATISTICS 1
+EOF
+
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define STATISTICS 1
+EOF
+
+fi
+
+
+# Check whether --enable-split-proxy-args or --disable-split-proxy-args was given.
+if test "${enable_split_proxy_args+set}" = set; then
+ enableval="$enable_split_proxy_args"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define SPLIT_PROXY_ARGS 1
+EOF
+
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define SPLIT_PROXY_ARGS 1
+EOF
+
+fi
+
+
+# Check whether --enable-webdav or --disable-webdav was given.
+if test "${enable_webdav+set}" = set; then
+ enableval="$enable_webdav"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define WEBDAV 1
+EOF
+
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define WEBDAV 1
+EOF
+
+fi
+
+
+# Check whether --enable-ie-images or --disable-ie-images was given.
+if test "${enable_ie_images+set}" = set; then
+ enableval="$enable_ie_images"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define DETECT_MSIE_IMAGES 1
+EOF
+
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define DETECT_MSIE_IMAGES 1
+EOF
+
+fi
+
+
+# Check whether --enable-image-list or --disable-image-list was given.
+if test "${enable_image_list+set}" = set; then
+ enableval="$enable_image_list"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define USE_IMAGE_LIST 1
+EOF
+
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define USE_IMAGE_LIST 1
+EOF
+
+fi
+
+
+# Check whether --enable-acl-files or --disable-acl-files was given.
+if test "${enable_acl_files+set}" = set; then
+ enableval="$enable_acl_files"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define ACL_FILES 1
+EOF
+
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define ACL_FILES 1
+EOF
+
+fi
+
+
+# Check whether --enable-trust-files or --disable-trust-files was given.
+if test "${enable_trust_files+set}" = set; then
+ enableval="$enable_trust_files"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define TRUST_FILES 1
+EOF
+
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define TRUST_FILES 1
+EOF
+
+fi
+
+
+# Check whether --enable-jar-files or --disable-jar-files was given.
+if test "${enable_jar_files+set}" = set; then
+ enableval="$enable_jar_files"
+ if test $enableval = yes; then
+ cat >> confdefs.h <<\EOF
+#define JAR_FILES 1
+EOF
+
+fi
+else
+ cat >> confdefs.h <<\EOF
+#define JAR_FILES 1
+EOF
+
+fi
+
+
+LIBRARY_PCRE_ONLY=#
+STATIC_PCRE_ONLY=
+# Check whether --enable-static-pcre or --disable-static-pcre was given.
+if test "${enable_static_pcre+set}" = set; then
+ enableval="$enable_static_pcre"
+ if test $enableval = no; then
+ LIBRARY_PCRE_ONLY=
+ STATIC_PCRE_ONLY=#
+fi
+fi
+
+
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@VERSION_MAJOR@%$VERSION_MAJOR%g
+s%@VERSION_MINOR@%$VERSION_MINOR%g
+s%@VERSION_POINT@%$VERSION_POINT%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@EXEEXT@%$EXEEXT%g
+s%@OBJEXT@%$OBJEXT%g
+s%@WIN_ONLY@%$WIN_ONLY%g
+s%@CYGWIN_FLAGS@%$CYGWIN_FLAGS%g
+s%@SOLARIS_ONLY@%$SOLARIS_ONLY%g
+s%@GNU_REGEX_ONLY@%$GNU_REGEX_ONLY%g
+s%@PCRE_REGEX_ONLY@%$PCRE_REGEX_ONLY%g
+s%@NO_REGEX_ONLY@%$NO_REGEX_ONLY%g
+s%@PCRS_ONLY@%$PCRS_ONLY%g
+s%@LIBRARY_PCRE_ONLY@%$LIBRARY_PCRE_ONLY%g
+s%@STATIC_PCRE_ONLY@%$STATIC_PCRE_ONLY%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+
--- /dev/null
+dnl Process this file with autoconf to produce a configure script.
+dnl
+dnl $Id: configure.in,v 1.2 2001/05/13 22:04:51 administrator Exp $
+dnl
+dnl Written by and Copyright (C) 2001 the SourceForge
+dnl IJBSWA team. http://ijbswa.sourceforge.net
+dnl
+dnl Based on the Internet Junkbuster originally written
+dnl by and Copyright (C) 1997 Anonymous Coders and
+dnl Junkbusters Corporation. http://www.junkbusters.com
+dnl
+dnl This program is free software; you can redistribute it
+dnl and/or modify it under the terms of the GNU General
+dnl Public License as published by the Free Software
+dnl Foundation; either version 2 of the License, or (at
+dnl your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will
+dnl be useful, but WITHOUT ANY WARRANTY; without even the
+dnl implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE. See the GNU General Public
+dnl License for more details.
+dnl
+dnl The GNU General Public License should be included with
+dnl this file. If not, you can view it at
+dnl http://www.gnu.org/copyleft/gpl.html
+dnl or write to the Free Software Foundation, Inc., 59
+dnl Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+dnl
+dnl $Log: configure.in,v $
+dnl
+AC_INIT(jcc.c)
+AC_CONFIG_HEADER(config.h)
+
+VERSION_MAJOR=2
+VERSION_MINOR=9
+VERSION_POINT=3
+
+AC_SUBST(VERSION_MAJOR)
+AC_SUBST(VERSION_MINOR)
+AC_SUBST(VERSION_POINT)
+
+AC_DEFINE_UNQUOTED(VERSION_MAJOR,${VERSION_MAJOR})
+AC_DEFINE_UNQUOTED(VERSION_MINOR,${VERSION_MINOR})
+AC_DEFINE_UNQUOTED(VERSION_POINT,${VERSION_POINT})
+AC_DEFINE_UNQUOTED(VERSION,"${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_POINT}")
+
+dnl Checks for programs.
+dnl AC_PROG_CXX
+AC_PROG_CC
+AC_PROG_CPP
+dnl AC_PROG_INSTALL
+dnl AC_PROG_LN_S
+dnl AC_PROG_MAKE_SET
+dnl RANLIB is for PCRE:
+dnl AC_PROG_RANLIB
+
+AC_MINGW32
+AC_CYGWIN
+AC_EXEEXT
+AC_OBJEXT
+
+dnl Checks for libraries.
+dnl AC_CHECK_LIB(pcre, pcre_compile)
+dnl AC_CHECK_LIB(pcreposix, regcomp, pcre)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+dnl AC_HEADER_SYS_WAIT
+dnl AC_CHECK_HEADERS(fcntl.h limits.h malloc.h sys/time.h unistd.h)
+dnl limits.h is for PCRE:
+dnl AC_CHECK_HEADERS(limits.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_SIZE_T
+
+dnl Checks for library functions.
+dnl AC_TYPE_SIGNAL
+dnl AC_CHECK_FUNC(strstr)
+dnl bcopy and memmove are for PCRE
+AC_CHECK_FUNCS(strerror bcopy memmove)
+
+dnl Build type
+
+AC_ARG_ENABLE(mingw32,
+[ --enable-mingw32 Use mingw32 for a Windows GUI],
+[if test $enableval = yes; then
+ WIN_ONLY=
+ CYGWIN_FLAGS="-mwindows -mno-cygwin"
+ echo "Using mingw32 (Win32 GUI)"
+ else
+ WIN_ONLY=#
+ if test "$CYGWIN" = "yes"; then
+ CYGWIN_FLAGS="-mno-win32"
+ echo "Using Cygnus (Win32 command line)"
+ else
+ CYGWIN_FLAGS=
+ fi
+ fi],
+[if test "$MINGW32" = "yes"; then
+ WIN_ONLY=
+ CYGWIN_FLAGS="-mwindows -mno-cygwin"
+ echo "Using mingw32 (Win32 GUI)"
+ else
+ WIN_ONLY=#
+ if test "$CYGWIN" = "yes"; then
+ CYGWIN_FLAGS="-mno-win32"
+ echo "Using Cygnus (Win32 command line)"
+ else
+ CYGWIN_FLAGS=
+ fi
+ fi])
+
+AC_SUBST(WIN_ONLY)
+AC_SUBST(CYGWIN_FLAGS)
+
+SOLARIS_ONLY=#
+AC_SUBST(SOLARIS_ONLY)
+
+dnl Features
+
+dnl Regex engine:
+
+GNU_REGEX_ONLY=
+PCRE_REGEX_ONLY=
+NO_REGEX_ONLY=#
+
+AC_ARG_ENABLE(regex,
+[ --disable-regex Don't allow regular expressions in the blockfile],
+[if test $enableval = yes; then
+ AC_DEFINE(REGEX)
+else
+ NO_REGEX_ONLY=
+ GNU_REGEX_ONLY=#
+ PCRE_REGEX_ONLY=#
+fi],AC_DEFINE(REGEX))
+
+AC_ARG_ENABLE(pcre-regex,
+[ --disable-pcre-regex Use old, slow GNU Regex instead of PCRE.],
+[if test $enableval = yes; then
+ AC_DEFINE(PCRE)
+ GNU_REGEX_ONLY=#
+else
+ PCRE_REGEX_ONLY=#
+fi],[AC_DEFINE(PCRE)
+ GNU_REGEX_ONLY=#
+])
+
+AC_SUBST(GNU_REGEX_ONLY)
+AC_SUBST(PCRE_REGEX_ONLY)
+AC_SUBST(NO_REGEX_ONLY)
+
+
+dnl Other features:
+
+AC_ARG_ENABLE(toggle,
+[ --disable-toggle Don't support temporary disable],
+[if test $enableval = yes; then
+ AC_DEFINE(TOGGLE)
+fi],AC_DEFINE(TOGGLE))
+
+PCRS_ONLY=
+AC_ARG_ENABLE(pcrs,
+[ --disable-pcrs Don't support arbitrary content modification],
+[if test $enableval = yes; then
+ AC_DEFINE(PCRS)
+ AC_DEFINE(DENY_GZIP)
+else
+ PCRS_ONLY=#
+fi],[AC_DEFINE(PCRS) AC_DEFINE(DENY_GZIP)])
+AC_SUBST(PCRS_ONLY)
+
+AC_ARG_ENABLE(force,
+[ --disable-force Don't allow blockfle to be bypassed],
+[if test $enableval = yes; then
+ AC_DEFINE(FORCE_LOAD)
+fi],AC_DEFINE(FORCE_LOAD))
+
+AC_ARG_ENABLE(killpopup,
+[ --disable-killpopup Never block popups],
+[if test $enableval = yes; then
+ AC_DEFINE(KILLPOPUPS)
+fi],AC_DEFINE(KILLPOPUPS))
+
+AC_ARG_ENABLE(stats,
+[ --disable-stats Don't keep statistics],
+[if test $enableval = yes; then
+ AC_DEFINE(STATISTICS)
+fi],AC_DEFINE(STATISTICS))
+
+AC_ARG_ENABLE(split-proxy-args,
+[ --disable-split-proxy-args One big show-proxy-args page, not one per file.],
+[if test $enableval = yes; then
+ AC_DEFINE(SPLIT_PROXY_ARGS)
+fi],AC_DEFINE(SPLIT_PROXY_ARGS))
+
+AC_ARG_ENABLE(webdav,
+[ --disable-webdav Don't support WebDAV. This option stops MS Outlook
+ Express from accessing HotMail e-mail.],
+[if test $enableval = yes; then
+ AC_DEFINE(WEBDAV)
+fi],
+AC_DEFINE(WEBDAV))
+
+AC_ARG_ENABLE(ie-images,
+[ --disable-ie-images Don't auto-detect whether a request from MS Internet
+ Explorer is for an image or HTML.],
+[if test $enableval = yes; then
+ AC_DEFINE(DETECT_MSIE_IMAGES)
+fi],
+AC_DEFINE(DETECT_MSIE_IMAGES))
+
+AC_ARG_ENABLE(image-list,
+[ --disable-image-list Don't try to figure out whether a request is for an
+ image or HTML using the imagelist - assume HTML.],
+[if test $enableval = yes; then
+ AC_DEFINE(USE_IMAGE_LIST)
+fi],
+AC_DEFINE(USE_IMAGE_LIST))
+
+AC_ARG_ENABLE(acl-files,
+[ --disable-acl-files Prevents the use of ACL files to control access to
+ the proxy by IP address.],
+[if test $enableval = yes; then
+ AC_DEFINE(ACL_FILES)
+fi],
+AC_DEFINE(ACL_FILES))
+
+AC_ARG_ENABLE(trust-files,
+[ --disable-trust-files Prevents the use of trust files.],
+[if test $enableval = yes; then
+ AC_DEFINE(TRUST_FILES)
+fi],
+AC_DEFINE(TRUST_FILES))
+
+AC_ARG_ENABLE(jar-files,
+[ --disable-jar-files Prevents the use of jar files to capture cookies.],
+[if test $enableval = yes; then
+ AC_DEFINE(JAR_FILES)
+fi],
+AC_DEFINE(JAR_FILES))
+
+LIBRARY_PCRE_ONLY=#
+STATIC_PCRE_ONLY=
+AC_ARG_ENABLE(static-pcre,
+[ --disable-static-pcre Link dynamically with the pcre and pcreposix
+ libraries. You must build the libraries seperately.],
+[if test $enableval = no; then
+ LIBRARY_PCRE_ONLY=
+ STATIC_PCRE_ONLY=#
+fi])
+AC_SUBST(LIBRARY_PCRE_ONLY)
+AC_SUBST(STATIC_PCRE_ONLY)
+
+AC_OUTPUT(Makefile)
+
--- /dev/null
+#
+# This is /etc/junkbuster/cookefile which was put here by a junkbuster rpm
+#
+# Last modified on Sun Jan 31 22:36:03 1999 (CEST)
+#
+# --------------------------------------------------------------------------
+#
+# Newest version is always available from
+#
+# http://www.waldherr.org/cookiefile
+#
+# Read http://www.waldherr.org/junkbuster/update.shtml on how to keep
+# this file up-to-date.
+#
+# For more detail, see http://www.junkbusters.com/ht/en/ijbfaq.html#cookies
+#
+# Empty lines and lines beginning with a # are ignored.
+# To permit an entire site to set cookies, simply include its domain name:
+# really-trustyworthy-people.org
+#
+# You can allow cookies out, but stop them coming in:
+# >send-user-cookies.com
+#
+#>egroups.com
+#>tvguide.com
+#>wired.com/news/
+#americanexpress.com
+#cnn.com
+#www.nytimes.com
+#yahoo.com
+#amazon.de
+#amazon.co.uk
+#slashdot.org
+#www.palmgear.com
+#onelist.com
+#freshmeat.net
+
+# Sites that need cookies
+javasoft.com
+sun.com
+msdn.microsoft.com
+sourceforge.net
+yahoo.com
+anonymizer.com
+
+# Experimenting
+ashleycars.co.uk
+
+# Shopping
+dabs.com
+overclockers.co.uk
+worldpay.com # for quietpc.com
+jungle.com
+scan.co.uk
+
+#Shopping: Micro Warehouse's site
+#inmac.co.uk
+#technomatic.co.uk
+
+# This is stupid. Without these two entries, the link from McAfee's website
+# to their online UK shop gives a 500 server error.
+#mcafee.com
+#mcafeestoreuk.beyond.com
+
+
+
+
--- /dev/null
+#ifndef _CYGWIN_H
+#define _CYGWIN_H
+#define CYGWIN_H_VERSION "$Id: cygwin.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/cygwin.h,v $
+ *
+ * Purpose : The windows.h file seems to be a *tad* different, so I
+ * will bridge the gaps here. Perhaps I should convert the
+ * latest SDK too? Shudder, I think not.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: cygwin.h,v $
+ *
+ *********************************************************************/
+
+/* Conditionally include this whole file. */
+#ifdef __MINGW32__
+
+/* Hmmm, seems to be overlooked. */
+#define _RICHEDIT_VER 0x0300
+
+/*
+ * Named slightly different ... but not in Cygwin v1.3.1 ...
+ *
+ * #define LVITEM LV_ITEM
+ * #define LVCOLUMN LV_COLUMN
+ */
+
+#endif /* def __MINGW32__ */
+#endif /* ndef _CYGWIN_H */
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+This file contains details of the changes made to JunkBuster, in
+chronological order. Scroll down to the bottom for the newest
+additions!
+
+
+*****************************************************************************
+* Copied from old README *
+*****************************************************************************
+
+README for the Internet Junkbuster Proxy (TM) Copyright 1997-8 Junkbusters Corp.
+
+ Id: README,v 1.1 2001/04/16 21:10:38 rodney Exp
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+The version of the code with this makefile is Version 2.0.2.
+No CHANGES file is included here; for a history of previous versions see
+ http://www.junkbusters.com/ht/en/ijbdist.html#previous
+This version tightens security over 2.0.1; some multi-user sites will need
+to change the listen-address in the configuration file (see previous URL).
+
+For installation on Windows see http://www.junkbusters.com/ht/en/ijbwin.html
+An executable is provided so you don't need nmake or a C compiler.
+
+For UNIX and other systems see the FAQ. If you just want to test it with its
+defaults of simply stopping cookies and private info, all you need to do now
+on most Unix systems is type make, run junkbuster & and configure your browser.
+
+This directory should contain the following files. The .html files are also
+in http://www.junkbusters.com/ht/en/ and http://internet.junkbuster.com
+You are welcome to publish copies of the .html files on your local web server,
+according to the GNU General Public License.
+
+gpl.html GNU General Public Licence
+junkbstr.exe Executable (binary) for Windows 95/NT
+Makefile A very bland Makefile; Most versions of Unix except HP & Suns
+ compile without change. Windows requires the changes indicated.
+ijbman.html Manual for the Internet Junkbuster, HTML format
+junkbuster.1 Manual for the Internet Junkbuster, man macro format:
+ man ./junkbuster.1 # or nroff -man junkbuster.1 | more
+ijbfaq.html FAQ: Frequently Asked Questions on the Internet Junkbuster
+ Includes installation instructions
+junkbstr.ini Sample configuration file with almost all options commented out
+sblock.ini Sample blockfile (which doesn't really block much, see FAQ)
+scookie.ini Sample cookiefile (permits little; you decide who to trust)
+saclfile.ini Sample access control file (block access to everyone)
+sforward.ini Sample forwardfile (does no fowarding, no gateways, so SOCKS)
+strust.ini Sample trustfile (has no trusted sites and blocks nothing)
+conn.c, bind.c, encode.c, loaders.c, parsers.c, ssplit.c Various utilities
+socks4.c Code for SOCKS4 and SOCKS4A gateways
+jcc.c The main program
+jcc.h #included declarations etc
+gnu_regex.c, gnu_regex.h: Regular expression code from the FSF, not us.
+win32.c A few lines of code specific to the Windows version (95 & NT)
+acl.c Access controls (new in version 2.0) - doesn't replace firewalls
+filters.c Strings for the presentation of messages to user
+
+If you find that the Internet Junkbuster improves the quality of your life
+online, we hope you'll visit http://www.junkbusters.com to see how our free
+services can help you bust other kinds of junk out of your life:
+junk mail, spam, telemarketing, and invasions of your private data.
+And please tell your friends about this free product, and help them set it up.
+
+If your company finds this software useful in protecting its confidential
+information and making its people happier and more productive, please consider
+purchasing one of our our commercial support packages:
+ http://www.junkbusters.com/ht/en/ijbfaq.html#commercial
+
+We don't advertise, so please tell others in your community about us.
+
+Junkbusters Corp. http://www.junkbusters.com
+
+
+*****************************************************************************
+* Copied from old README.too *
+*****************************************************************************
+
+Id: README.TOO,v 1.1 2001/04/16 21:10:38 rodney Exp
+
+This is the README.TOO file for Stefan's version of the Internet
+Junkbuster (from http://www.waldherr.org/junkbuster/).
+
+
+
+Installation:
+-------------
+Install the RPM with the usual command `rpm -Uvh foobar.rpm'. Since we
+run the Junkbuster as user `nobody', cd to a directory where `nobody'
+has read access (in particular NOT /root) and issue (as root)
+
+ /etc/rc.d/init.d/junkbuster start
+
+This will be done automagically for you any time you boot your machine.
+
+
+
+Configuration:
+--------------
+To let Junkbuster take `care' of the ads, you have to setup your
+browser to use the Junkbuster.
+
+ Short instructions for the advanced user:
+
+ Configure Netscape to use 127.0.0.1 on port 8000 as
+ a proxy server.
+
+ Detailed instructions for the beginner:
+
+ Remove Internet Explorer and install Netscape. No `real'
+ user would ever use MSIE. Though the Junkbuster works
+ with IE as well. Read
+ http://www.junkbusters.com/ht/en/ijbfaq.html#browser
+
+Check to see if the Junkbuster works correctly by surfing to
+
+ http://127.0.0.1/show-proxy-args
+
+or any other place and add the text `/show-proxy-args' to the URL.
+Ok? Then enjoy your ad-free surfing.
+
+
+
+Mailinglists:
+-------------
+In case you are interested in the Junkbuster, there are two
+mailinglists (junkbuster-users and junkbuster-announce). Instructions
+on how to subscribe and unsubscribe are at
+
+ http://www.waldherr.org/junkbuster/
+
+Bugs:
+-----
+Please fill out
+
+ http://sourceforge.net/bugs/?func=addbug&group_id=11118
+
+Patches:
+--------
+Please fill out
+
+ http://sourceforge.net/patch/?func=addpatch&group_id=11118
+
+Need Help?
+----------
+Please fill out
+
+ http://sourceforge.net/support/?func=addsupport&group_id=11118
+
+
+Comments:
+---------
+I would greatly appreciate feedback for this program. Send comments to
+Stefan Waldherr <stefan@waldherr.org> (in either German or English). I
+prefer plain text. If you happen to see an ad which got thru the filter
+PLEASE use the `contribute' form at http://www.waldherr.org/junkbuster/.
+
+Have fun,
+Stefan.
+
+
+*****************************************************************************
+* Copied from old README.win *
+*****************************************************************************
+
+$Id: README.WIN,v 1.1 2001/04/16 21:10:38 rodney Exp $
+
+This is the README.WIN file for the Windows version of the Internet
+Junkbuster (from http://www.waldherr.org/junkbuster/).
+
+Installation:
+-------------
+Congrats, since you are reading this file, you have already unzipped
+the archive correctly.
+
+Start the Junkbuster with `junkbstr' (i.e., click on the icon in the
+ijb subdirectory). If you want to start Junkbuster automatically,
+make a link to the program in the `Autostart' folder.
+
+
+
+Configuration:
+--------------
+To let Junkbuster take `care' of the ads, you have to setup your
+browser to use the Junkbuster.
+
+ Short instructions for the advanced user:
+
+ Configure Netscape to use 127.0.0.1 on port 8000 as
+ a proxy server.
+
+ Detailed instructions for the beginner:
+
+ Remove Internet Explorer and install Netscape. No `real'
+ user would ever use MSIE. Though the Junkbuster works
+ with IE as well. Read
+ http://www.junkbusters.com/ht/en/ijbfaq.html#browser
+
+Check to see if the Junkbuster works correctly by surfing to
+
+ http://127.0.0.1/show-proxy-args
+
+or any other place and add the text `/show-proxy-args' to the URL.
+Ok? Then enjoy your ad-free surfing.
+
+
+
+Mailinglists:
+-------------
+In case you are interested in the Junkbuster, there are two
+mailinglists (junkbuster-users and junkbuster-announce). Instructions
+on how to subscribe and unsubscribe are at
+
+ http://www.waldherr.org/junkbuster/
+
+Bugs:
+-----
+Please fill out
+
+ http://sourceforge.net/bugs/?func=addbug&group_id=11118
+
+Patches:
+--------
+Please fill out
+
+ http://sourceforge.net/patch/?func=addpatch&group_id=11118
+
+Need Help?
+----------
+Please fill out
+
+ http://sourceforge.net/support/?func=addsupport&group_id=11118
+
+Comments:
+---------
+I would greatly appreciate feedback for this program. Send comments to
+Stefan Waldherr <stefan@waldherr.org> (in either German or English). I
+prefer plain text. If you happen to see an ad which got thru the filter
+PLEASE use the `contribute' form at http://www.waldherr.org/junkbuster/.
+
+Have fun,
+Stefan.
+
+
+*****************************************************************************
+* Copied from old README.re_filter *
+*****************************************************************************
+
+DISCLAIMER:
+ This is pre-alpha code. Using it in any other way
+ than just reading it is a high risk activity and
+ the author disclaims all liability for any damage.
+
+ See the GNU General Public License at
+ http://www.gnu.org/copyleft/gpl.html for details.
+
+
+Dear alpha-Tester,
+
+Thank you for trying out the experimental re_filter feature of
+Junkbuster. As this is still a very early pre-release version,
+and I'm neither much of an autoconf or make wizard, building
+the patched junkbuster involves some manual work, that is
+described below. Please also see the Request for Thoughts section,
+as the whole point of this pre-release ist to collect ideas for
+improvement and bug reports.
+
+
+INSTALLATION:
+
+ - Get and install pcre from
+ ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/
+ Version 3.1 or any later one will do. I recommend 3.4.
+ It *should* install on Win32 as well, but I haven't tried
+ that. Don't forget to run ldconfig afterwards.
+
+ - Now you have two options:
+
+ A) Install pcrs as a shared library:
+ pcrs.c and pcrs.h are included in the (patched) ijb subdirectory.
+ 1.) patch Makefile < Makefile.re_shared.diff
+ 2.) gcc -Wall -fPIC -c pcrs.c
+ 3.) gcc -shared -Wl,-soname,libpcrs.so.1 -o libpcrs.so.1.0.1 pcrs.o -lc -lpcre
+ If this worked OK,
+ 4.) copy libpcrs.so.1.0.1 to /usr/local/lib
+ 5.) ln -s /usr/local/lib/libpcrs.1.0.1 /usr/local/lib/libpcrs.so
+ 6.) ldconfig (Or whatever the equivalent on your platform might be)
+ 7.) cp pcrs.h /usr/local/include
+
+ OR
+
+ B) Incorporate pcrs into the junkbuster (much easier):
+ Smile and relax. You're done.
+
+ - Edit the provided re_filterfile to suit your needs and place it
+ with the rest of junkbusters configfiles.
+
+ - Now junkbuster should build with a simple 'make'.
+ Note: Setting debug = REF in jcc.c will enable debugging
+ for the re_filter.
+
+ - Include a line "re_filterfile <wherever>" in your junkbuster
+ config file, pointing at the re_filterfile
+
+ - (Optional:) Include a line "re_filter_all" in the config
+ file. This will set the Policy to filter content from all sites.
+ Default is to filter only from sites that you wouldn't send a
+ cookie either.
+
+ - Fire up junkbuster.
+
+HOW IT WORKS:
+
+ Nah, not tonight anymore ;-)
+
+REQUEST FOR THOUGHTS:
+
+ - The main decision is whether to filter on-the-fly or to buffer
+ up the whole document and then run the filter on it. I've built
+ both versions and currently prefer buffering.
+
+ The advantage of on-the-fly-filtering is obviously that the
+ document begins to display before it's fully loaded. The big
+ disadvantage is that with arbitraty content altering in place,
+ you don't know the size that the document will have after
+ altering when the Content-Length Header is to be sent. Only
+ option is to chew it altogether.
+
+ Apart from preserving the ability to generate a valid Content-Length
+ header (which the patch currently does not yet do), buffering up
+ the document has some advantages from the filtering point of view:
+
+ - Reliability. Patterns in the document cannot be ripped apart
+ and are reliably found. (If you look at the document fragment-wise
+ while it's being transmitted, you miss any pattern that spans
+ a fragment border) This is especially bad for patterns that do
+ serious HTML reformatting, as fragments are typically in the order
+ of 1500 bytes each.
+
+ - Flexibility: The re_filter gives you the choice whether you want
+ to replace only the pattern's first occurance or replace it globally.
+ This becomes meningless with fragments. (Solution possible, though.)
+
+ As the filter only processes objects of MIME type text/*, which are typically
+ rather small compared to binary multimedia (sic) type data, I don't think
+ that the disadvantage of delayed display of the first bytes is really grave.
+
+ What do you think?
+
+ - Is the choice between a radical (filter all) and semi-smart (filter only when
+ also crunching cookies) flexible enough? Should I really introduce yet another
+ configfile for specifying the domains to filter content from? Would anyone use
+ that?
+
+ - Should I use pcre as a shared library and work out a nice installation
+ automagic, or should the relevant functions be incorporated in re_filter.c?
+
+ - Even if yes, do we really want an extension that relies on an external library
+ like pcre?
+
+ - Any bugs, stupid parts in the code ?
+
+ - Cool suggestions for the re_filterfile? (PLEASE!)
+
+ - Should character set translation along the lines of Perl's 'tr' operator
+ be included?
+
+ - Is the whole feature just pathetic?
+
+FEEDBACK:
+
+ A whole lot of work has gone into this feature (the pcrs code was also
+ just written for this) and I'd really like to know if and how you like
+ it. Since I'm more of a perl than C programmer (and after doing so much
+ string manipulation in C I'm once again glad abaout that!), I'm sure there
+ is much to improve. Please send any suggestions/observations/hellos to
+ oes@paradis.rhein.de. I would also be very glad about any assistance for
+ a autoconf/make procedure for prcs.
+
+Well, have fun!
+--Andreas
+
+
+*****************************************************************************
+* Copied from old README.cygwin *
+*****************************************************************************
+
+Id: README.cygwin,v 1.2 2001/04/29 23:16:29 rodney Exp
+
+
+What I did: I saw too many "personalities" in IJB; so I
+ran the code through a couple of regexp's and then let XEmacs
+reformat the whole shebang! The results is a uniform
+looking code base; aka. as if 1 person created the whole
+project.
+
+Why I did it: (1) it is easier to maintain (2) easier for
+a new person to make changes/additions (3) it *looks* more
+professional (4) IMHO, it is easier to read (this is very
+much a personal preference).
+
+What I propose: A IJB standards list be included in the
+distro and all source/patch checkins be checked for
+compliance. We don't need to be an arse on this point, but
+submitters should make a valiant attempt to support the
+standards.
+
+Note: do not even try to diff my code with another code
+base, you will be overwhelmed. After all, the regexps did a
+good bit of changing and XEmacs reformatter did a great deal
+more.
+
+One more note: these changes include conditional compilation for
+un?x (namely Linux), cygwin (un?x like compile for WIN32), and
+mingw32 (WIN32 like compilation w/o VC++). Right now, all seems
+fully functional except cygwin. The cygwin compile will work,
+but includes code to make it single threaded. I need to debug
+the fork issues, but that will have to come later.
+
+
+Specific changes to expect:
+
+
+1: I've majorly reworked the Makefiles. The existing Makefile was
+too *spaghetti* for me! For one, I eliminated the "-I." from the
+include path (ugly). Use #include "" for local directory files
+and #include <> for path found files (that's basic even to c).
+
+
+2: In accordance with #1, I changed #include "windows.h" to
+#include <windows.h> and #include <gnu_regex.h> to #include
+"gnu_regex.h".
+
+
+3: As part of my standards suggestions (to come later in this
+file), I added a standard comment block to every function. There
+were too many functions with *no* comment and about 20 different
+styles to those that did. This is an example of the block I used:
+/*********************************************************************
+ *
+ * Function : block_acl
+ *
+ * Description : Block this request?
+ * Decide yes or no based on ACL file.
+ *
+ * Parameters :
+ * 1 : src = Address the browser/user agent is requesting.
+ * 2 : dst = The proxy or gateway address this is going to.
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 = FALSE (don't block) and 1 = TRUE (do block)
+ *
+ *********************************************************************/
+
+
+4: Some files prototyped like this:
+ void
+ func(param1)
+ int param1;
+ {
+ }
+and other like this:
+ void func(int param1)
+ {
+ }
+I made all look like the second.
+
+
+5: Made:
+ if( to be if (
+ while( to be while (
+ switch( to be switch (
+ etc ...
+The former looks too much like a function call.
+
+
+6: Put braces on their own line and aligned under the
+reserved word:
+ if () {
+ } else {
+ }
+to be:
+ if ()
+ {
+ }
+ else
+ {
+ }
+The same for while, do, etc...
+
+
+7: Casted malloc in several places, e.g.:
+ p = malloc(n);
+to be:
+ p = (char *)malloc(n);
+This eliminates compiler warnings.
+
+
+8: Applied the Perl regexp patch and made it fully conditionally
+compiled (-DPCRS=TRUE).
+
+
+9: It *appears* that if MINGW32 sees a "main" function, it will
+try to link it and start with main (ala console mode). Since I
+need MINGW32 to find WinMain instead, I conditionally changed
+"main" to "_main" (for MINGW32 only!).
+
+
+10: Changed popup.c to be killpopup.c. This was necessary to
+clean up the Makefile. Since there was an ini type file called
+"popup" and "popup.c", make got confused on target names. No
+other ini file has a .c file with the same name, so I hope this
+isn't a big deal. Plus, it fits its config variable
+(kill_all_popups) much better.
+
+
+11: Added:
+ /*
+ Local Variables:
+ tab-width: 3
+ end:
+ */
+to all .c and .h files. I use 3 character tabs and this will make
+the files display correctly in Emacs editors. This is just my
+default setting. Perhaps I will filter all files via "expand
+-t3", so not to pi$$ everyone off. Vi is capable of using 3
+character tabs, as I am sure VC++ would be.
+
+
+12: Several places included regexp code with out "#ifdef REGEX"
+which broke the ability to compile w/o regexp's. I fixed the code
+and can compile w/o regexp (which I don't normally do, but now I
+*can*).
+
+
+13: In WinMain, changed:
+ pszLastTok = strchr(pszLastTok, ' ');
+to be:
+ pszLastTok = strchr(pszLastTok+1, ' ');
+The former causes an infinite loop with 2 or more parameters.
+
+
+14: Added my own strdup for Cygwin, see jcc.c for why.
+
+
+15: Added defines in the Makefile and this to jcc.h:
+ #define VERSION VERSION_MAJOR "." VERSION_MINOR "." VERSION_POINT
+This makes "update the numbers also in jcc.h manually" unnecessary
+(see your Makefile for this quote).
+
+
+16: Split the "inifiles" target in Makefile into separate targets,
+this way each file can be regenerated individually according to
+the same implicit rule.
+
+
+17: With the Makefile restructure, I can only provide for
+Cygwin/gcc. Hopefully this is a bit cleaner and others can add
+their compilers w/o re-spaghetting the file. I have provided
+several makefiles as examples only, I do not intend for the
+project to start maintaining multiple Makefiles. Perhaps some of
+the platform specific Makefile code could be split out into
+separate files and we could use the "include" directive to read in
+the correct one.
+
+Better than this, let's get a configure.in guru on the project and
+dynamically create the Makefiles!
+
+
+18: In an effort to get this to market (you knew this was coming
+eh?), I am going to put the standards suggestions in another file
+and ship this one as is. But then, you can probably guess most of
+the standards by the changes you see.
+
+
+19: Added a really quick and dirty "install" target to the
+Makefile. This needs to be cleaned up and proper directories put
+in for each platform.
+
+
+-- release 1 (obsoleted) --
+
+
+20: Incorporated the TOGGLE and webDAV support patches into my
+Cygwin patch. I added conditional compilation to both features.
+I changed "extern BOOL g_bToggleIJB;" to be of type "int". This
+makes jcc.h independent of "windows.h". The inclusion of such
+should not (and is not) necessary for compilation on all
+platforms. Besides, BOOL is really only a char or an int anyway!
+
+
+21: Added a new ini! I modified the usual un?x type config file
+to M$ type ini file for a Perl regexp compile. This was necessary
+to call EditFile on the Perl regexp config file. The new ini
+filename is "sregexp.ini" (naturally). I then added menu items to
+edit the popup.ini and sregexp.ini files.
+
+
+22: I made "dot h" files for all the "dot c" files. I used this
+command to do the *dirty* work:
+ grep -e "^[A-z]" *.c | sed -e "/=/d" -e "/^[^(]*$/d" \
+ -e "/^extern/d" -e "/^static/d" -e "/;$/d"
+
+And I made each "dot h" file be immune to multiple inclusion via
+conditional compilation. Ie. the "jcc.h" file will only include
+itself if _JCC_H is undefined.
+
+After this was done, I compiled the project source by source and
+let the compiler tell me what each file was dependent on. Once I
+got all the objects to compile, I included the new dependencies in
+the Makefiles.
+
+BTW, I intend to get the Makefile to be generated by a configure
+script. Whether this is a GNU "configure.in" type file or a shell
+script, I do not know. All I do know is that this is a must for a
+"Go/No go" type decision. We cannot proceed with the philosophy
+"leave it up to the user to get it to work".
+
+
+23: I broke out the code to load the config file from main. I put
+this code into a function called load_config. I made this routine
+be called from a signal "HUP". This means we can restart
+junkbusters from the command line or from the daemon script via
+"restart" without actually killing it and restarting it. This is
+common behavior to un?x daemons (see inetd for example). I fixed
+the junkbusters.init script to take advantage of this. I intend
+to make a M$ menu complement to this as soon as I can.
+
+
+24: BTW, if you have not already noticed by my postings and/or
+code, I have added patches and made them all conditionally
+compiled. Ie. #ifdef TOGGLE, #ifdef WEBDAV, #ifdef PCRS, etc...
+I think that all extensions to IJB should be submitted in this
+way. Not only can you compile IJB to be as "tight" as you want,
+it also gives the user a "smorgasbord" of options to
+choose from. This is quite common in the free software world (you
+need look no farther than emacs to see this) and provides maximum
+flexibility.
+
+
+25: As promised, I obsoleted the "ijbw32.ini" file. I was a bit
+confused by the "close-behaviour=1" entry. It seems to me that it
+duplicated the "close-button-minimizes=1" entry. And (by looking
+at the code) it was unused. Anyway, I eliminated the "ijbw32.ini"
+file and assimilated the settings into the config file. Bye Bye
+"ijbw32.ini", hello "config" (aka. don't unnecessarily duplicate
+files and/or data types).
+
+
+26: Eliminated re_filter.c. This only defined
+(un)load_re_filterfile and re_process_buffer. I moved
+(un)load_re_filterfile to loaders.c and re_process_buffer to
+filters.c. I also modified the Makefiles to reflect this. In the
+doing, I modified the loader and unloader to use the "files"
+variable and moved joblist to "re_filterfile_spec" struct. I
+added "plist" to the client_state so that all Perl regexp code
+could find the latest parsing of the re_filterfile ini.
+
+This is in keeping with the IJB data structures philosophies.
+
+
+27: Eliminated acl.c. This (as pcre) only defined
+(un)load_aclfile and block_acl. I moved (un)load_aclfile to
+loaders.c and block_acl to filters.c. I also modified the
+Makefiles to reflect this.
+
+
+28: Since I created "dot h" files for all the "dot c" files, I
+eliminated all the "extern ...variable;" and all the "extern
+...function;" statements that I could find in the "dot c" files.
+Instead, I included the proper "dot h" files to do this for us.
+
+
+29: Corrected the "install" Makefile target for un?x. I will do
+the same for WIN32 targets.
+
+
+30: Note on the "TOGGLE" patch: since I made IJB fully restartable
+via a NOHUP signal; I thought the TOGGLE patch should apply to
+both un?x and WIN32. Thus, I eliminated the WIN32 dependencies in
+that patch and added "toggle" to the config file. Now everything
+works fine for either platform. Still to come is a restart menu
+command in WIN32 (See: note 23).
+
+
+31: Just a possible programmer note, we REALLY need a generic
+linked list module. Since text lists, client states, filter
+files, etc... implement list creation and destruction over and
+over; I suggest a generic list that can handle *any* type of list
+(ala template classes in C++). If this module included an
+iterator (of sorts), we could eliminate the myriad of "for ( top=x;
+NULL != x->next; x=x->next )" type statements that are all over
+IJB.
+
+After all, this was taught in the basic "Intro to Data Types"
+class (for all you CS majors).
+
+
+32: Renamed all of the .INI files to be .TXT files. I did this
+because the .INI files were NOT *really* ini files; which
+potentially be confusing. I used the .TXT extension to make sure
+that EditFile still worked.
+
+
+33: Removed the "initialed comments", such as "/* swa */". This
+leads to less readable code (because it becomes fragmented) and
+retains the "multiple personality" syndrome. Comments such as
+this can always be figured out from the versioning system. Also,
+these comments really should be pooled in one place : the README
+files.
+
+
+34: Perhaps we should break with the current versioning tactic of
+a "tail version" and start fresh. Perhaps a new major version
+release is in order? Version = 3.0.0?
+
+
+35: Added a "Accept-Encoding: gzip" cruncher. If a stream is
+compressed via gzip (Netscape specific I think), then it cannot
+be modified with Perl regexps. So I added this as an option in
+the Makefiles.
+
+
+36: As promised in one of my postings, I have make a
+configure-esk script to generate the Makefiles. I would still
+like to have a full blown configure.in compatible system, but this
+will do in the meantime. Note: this configure script covers
+linux, cygwin, and mingw32. At this point I do not have VC++ to
+test any of my changes. But the configure script should be
+flexible enough to handle this platform.
+
+
+--
+
+Please give any feedback to the ijb egroups and, if you feel you
+need quicker contact, CC me at IwantToKeepAnon@yahoo.com
+
+Let me say once more, this has a *lot* of changes and may (aka
+WILL) break a lot of existing patches. But I hope the "idea" will
+catch on. Perhaps this could be made the baseline code base and
+other patches added and standardized later.
+
+*****************************************************************************
+* Date: 7 May 2001 *
+* Version: ?? *
+* Description: Changes for MS Visual C++ *
+* Author: Jon Foster <jon@jon-foster.co.uk> *
+*****************************************************************************
+(Based on Stromlund's version 0.20)
+
+I have made several changes to make this compile under VC++ 97, and add new
+features.
+
+Code changes:
+
+1) If you disable IJB (using the TOGGLE patch) it now turns PCRS off.
+2) "Missing function prototype" warnings have been corrected by adding
+ appropriate #include statements
+3) The _DIST_URL define removed and hardcoded. There are hardcoded URLs all
+ over the place that need fixing - one more doesn't matter. We do really
+ need to come up with a long-term solution though. (Suggestion: Host a
+ redirector on the SourceForge web space. e.g
+ "http://ijbswa.sourceforge.net/redirect.php?ver=2.0.2-10&target=faq",
+ "http://ijbswa.sourceforge.net/redirect.php?ver=2.0.2-10&target=download",
+ etc. This allows us to move the pages around easily, and the SourceForge
+ space can be maintained by anyone who's interested, it's not tied to a
+ particular individual. This is similar to the approach taken by
+ Microsoft and Netscape in their browsers.)
+4) New file ijbconfig.h is #included everywhere. This provides me with a
+ place to define VERSION, PCRS, etc. You can still define VERSION_xxx
+ on the command line, but the other defines are in the header file.
+ There were just too many #defines - so many that the VC++ 97 IDE
+ broke when I tried to define them on the command line. We probably
+ should fix the configure script so that it modifies this file.
+5) Deleted empty file afxres.h - we needed to use the VC++ system header
+ file of that name. However, it's easier to just delete it and put
+ the relevent #defines in w32res.h.
+6) New #define: NO_PROGRAM_NAME_DISPLAY uses "IJB" as the program name in
+ the log file instead of "H:\Documents and Settings\Administrator\My
+ Documents\Prog\VC\ijb2\Release\junkbuter.exe" or similar. The reason
+ for this should be obvious!
+7) New #define: STATISTICS enables the statistics feature
+8) Statistics is thread-safe, I think. However, loading up the
+ statistics page now counts as a blocked request.
+9) New, shorter message if a setting in the config file is recognised
+ but unsupported by the current build. It doesn't have "WARNING:" in
+ front of it either. We may want to actually take this message out
+ and have it just silently ignore these entries.
+10) New feature: #define SPLIT_PROXY_ARGS and the show-proxy-settings
+ page will split each file out to a seperate page. This is
+ because the files are quite big, and having to do 1 extra click to
+ get to them is no problem. This #define also disables the
+ suppress_blocklists feature (because I believe the original intent
+ of suppress_blocklists was similar?). It also saves memory by
+ reading the config files to generate the HTML on the fly, rather
+ than storing prepared HTML constantly in memory.
+11) Marked global constants with "const" attribute. This has a
+ knock-on effect on pointers in function prototypes, so these have
+ also been marked const where needed.
+12) Rewrote encode.c to have tables pre-initialized, so it can be
+ marked constant. Also split into 3 distinct functions so that
+ the tables (which are realy an implementation detail) are not
+ visible outside that file.
+13) Changes to how files are reloaded when you reload the config
+ file. Previous method didn't free memory (or if you uncommented
+ the free() calls, it was not thread-safe.) It is now handled
+ automatically - files are reloaded whenever the filename to
+ read changes, or the file's timestamp changes. The code in
+ loaders.c which handles this test has been moved to a single
+ utility function.
+14) killpopup changes:
+ * Only compiled if you #define KILLPOPUPS
+ * Call to filter_popups() moved from read_socket() to chat().
+ * Writing 1 past end of buffer bug fixed.
+ * It was scanning the whole buffer even if only partially filled.
+ * Moved load/unload to loaders.c and changed file handling to
+ follow standard.
+15) Auto-detect whether we want an image or HTML implemented for
+ Microsoft IE. :-)
+ There doesn't seem to be a way to tell with the latest build
+ of Mozilla. :-(
+16) Image file code conditionally compiled.
+17) Provided option (SPLIT_PROXY_ARGS) to split the show-proxy-args
+ page into a main page, and then a page for each config file.
+ This option will also save memory by loading the files when
+ required for display, rather than saving them in memory when
+ they are initially loaded.
+18) Force page loading ("noijb.") patch applied. #define FORCE_LOAD
+
+
+Packaging changes:
+
+1) PCRE 3.4 (less it's test and demo programs) is now included in the
+ pcre directory. It will be statically linked with Junkbuster. (On
+ win32, DLLs cause a lot of hassle - with a library this small it isn't
+ worth it. I don't know if it would be better to dynamically link under
+ UNIX?)
+2) junkbustr.dsp and junkbustr.dsw VC++97 project and workspace files are
+ included.
+3) win32build/junkbustr.exe Win32 binary is included. It should not require
+ any DLLs. It was compiled with all features supported.
+4) All README.xyz files put together in this file.
+5) Unused files (acl.c, pthread.c, ...) deleted.
+6) My block & cookie files used (based on the Waldherr ones).
+
+Known bug: The Adobe Acrobat 4 plug-in fails when I try to view PDF files in
+MSIE. Workaround: disable "web browser integration" in the Adobe Acrobat
+settings.
+
+*****************************************************************************
+* Date: 14 May 2001 (early morning) *
+* Version: Reported as 2.9.0 *
+* Description: Various updates *
+* Author: Jon Foster <jon@jon-foster.co.uk> *
+*****************************************************************************
+
+1) Now use PCRE, not GNU REGEX. I have not yet had chance to check the
+ syntax of the block/image/cookie file to ensure that they match what
+ is expected - however they seem to work.
+2) Replaced "configure" script with one generated by "autoconf". Also
+ use a header "config.h" (was ijbconfig.h in my previous release) for
+ the #defines. "config.h" is now generated with "autoheader" from
+ "acconfig.h" and "configure.in". (Note that to install you do not
+ need autoconf or autoheader - just run "./configure".)
+ To see command-line options, run "./configure --help".
+ This is my first ever autoconf script, so it has some rough edges
+ (how PCRE is handled is the roughest).
+3) Error logging code replaced with new module errlog.c, based on the
+ one from JunkBusterMT (but with the threading code removed).
+4) Most of Rodney's 0.21 and 0.21A patches applied. (Marked *). I did not
+ apply all of these, since I had already independently done conditional
+ popup file, conditional image file, and integration of popup code.
+5*) ACL, Jar and trust files conditionally compiled.
+6*) New source file headers.
+7*) Various cosmetic changes. (But I have not consistently ordered the
+ config files - I think that's worthwhile, but it's 1am and I want to
+ get this released!)
+8*) RCS tags on .h files.
+9) RCS tags are const char[] rather than const char *. (Saves 4 bytes
+ per tag ;-)
+10) VC++ project files renamed to vc_junkbuster.*.
+11) show-proxy-args now shows status of all conditionals, not just REGEX
+12) Various functions moved around. Most notably all the system-specific
+ sockets code which was spread between jcc.c, bind.c, and connect.c,
+ has been moved to "jbsockets.c". The non-system-specific code from
+ connect.c and socks4.c has been movet to "gateway.c". Also, the
+ config file loader and the global variables it writes to have been
+ moved to "loadcfg.c". (Maybe this should go into loaders.c?)
+ And candidate for the "worst filename ever" award is "miscutil.c",
+ which contains, well, miscellaneous utility functions like zalloc.
+ (Suggestions for a better name for this file are welcome!)
+13) Loaders now use a common function to read a line and skip comments,
+ and this function also stores the proxy_args.
+14) Added ./junkbuster --help (Not for Win32 GUI)
+15) Added ./junkbuster --version (Not for Win32 GUI)
+16) Win32 resources are now all marked as "U.S. English", rather than
+ being a mix of "U.S. English", "U.K. English" and "Irish English".
+17) Version number changes to 2.9.0
+
+Known bugs:
+- See (1) above about blockfiles.
+- Sending SIGHUP (under Red Hat Linux 7.1) causes a crash. v0.21A hangs
+ after a SIGHUP. This needs investigating, but pthreads support will
+ almost certainly help here, so it may not be worth investigating
+ immediately.
+- Compiling with shared system pcre and pcreposix libraries is supported
+ via a switch to configure, but completely untested.
+
+Please note that there are now 2^14 == 16384 combinations of conditional
+defines, and 4 major compilers (VC, Linux, mingw32, cygwin) for a total
+of 65536 different builds. We cannot possibly test all of them! My
+standard build is "everything on", and I've tested that on each compiler,
+along with a few variants. You may uncover new bugs (probably compiler
+errors) if you use an exotic combination of switches.
+
+*****************************************************************************
+* Date: 14 May 2001 *
+* Version: 2.9.1 *
+* Description: Various updates *
+* Author: Andreas S. Oesterhelt <oes@oesterhelt.org> *
+*****************************************************************************
+(From his e-mail:)
+
+ - in parsers.c, fixed two #ifdef FORCE to #ifdef FORCE_LOAD
+ (BTW: I think FORCE is precise enough, since loading remote
+ data is the whole purpose of a proxy..)
+ - Set the FORCE_PREFIX (back) to 'IJB-FORCE-LOAD-'. While 'noijb.'
+ is more elegant and looks like a hostname in the URL, it doesn't
+ make clear to the inexperienced user that the proxy is bypassed. It
+ also has a higher name collision risk.
+ - Filled in the function header templates for my functions in
+ parsers.c (again). They obviously got lost in our current
+ patch war ;-)
+ - Cut the credit for the §-referrer-option from the config file,
+ that Stefan had placed there.
+ - Improved the re_filterfile
+
+*****************************************************************************
+* Date: 14 May 2001 *
+* Version: 2.9.2 *
+* Description: FORCE patch (again!) *
+* Author: Andreas S. Oesterhelt <oes@oesterhelt.org> *
+*****************************************************************************
+(These notes written by Jon)
+
+- Andreas applied the latest version of the FORCE patch.
+
+*****************************************************************************
+* Date: 14 May 2001 (late afternoon) *
+* Version: 2.9.3 *
+* Description: Various updates *
+* Author: Jon Foster <jon@jon-foster.co.uk> *
+*****************************************************************************
+
+1) Incorporated updates from current CVS tree, including:
+ - Amiga support (completely untested by me - I don't have an Amiga)
+ - "tinygif 3" support (redirects blocked images to a specified URL, so
+ the browser doesn't have to load and cache many copies of the same
+ image).
+ - one case where there were both local and global "referrer" variables
+ (yuck!) clarified by renaming the local one to "refer".
+ - Fixed some places where close() was used instead of close_socket().
+ Thanks to Jörg Strohmayer (joergs at users.sourceforge.net) for these.
+2) Temporary hack to get FORCE_LOAD to work with IE. I just lowercased the
+ FORCE_LOAD_PREFIX. Needs fixing properly.
+3) Most URLs hardcoded into JunkBuster were changed to go through a script
+ e.g. http://ijbswa.sourceforge.net/redirect.php?v=2.9.3&to=faq
+ The only other URLs left are the GNU GPL:
+ http://www.fsf.org/copyleft/gpl.html
+ and the home page:
+ http://ijbswa.sourceforge.net/
+ ... and various URLs which will be intercepted by JunkBuster anyway.
+ TODO: Still need to do something with the URLs in JunkBuster Corp's
+ copyright/trademark notice on the bottom of the show-proxy-args page.
+4) PCRE or GNU Regex is now a #define option.
+
+*****************************************************************************
+* End of file *
+*****************************************************************************
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">\r
+<html>\r
+<head>\r
+<!-- Copyright 1996-8 Junkbusters Corporation -->\r
+<!-- This work comes with NO WARRANTY -->\r
+<!-- It may be redistributed and modified under the GNU GPL-->\r
+<!-- See the body of http://www.junkbusters.com/ht/en/gpl.html for details-->\r
+<!-- Junkbusters is a registered trade mark of Junkbusters Corporation -->\r
+<!-- Generated 1998/10/31 03:58:25 UTC -->\r
+<meta name="Generator" content="Junkbusters Ebira $Revision: 1.1 $ $Date: 2001/04/16 21:10:38 $">\r
+<!-- Document ID: $Revision: 1.1 $ $Date: 2001/04/16 21:10:38 $ -->\r
+<title>\r
+The GNU General Public License\r
+</title>\r
+<base href="http://www.junkbusters.com/ht/en/gpl.html">\r
+<meta name="description" content="We did not write the GPL: the Free Software Foundation did | The GPL allows copying and changing of copyrighted documents | Version 2, June 1991 | Preamble | GNU General Public License: Terms and Conditions for Copying, Distribution and Modification | Appendix: How to Apply These Terms to Your New Programs">\r
+<meta name="keywords" content="stop, junk, busters, junkbusters, junkbuster, mail, email, e-mail, direct, spam, spamoff, declare, telemarketing, telemarketers, privacy, sharing, names, renting, direct, marketing, database, databases, junk mail, lists, environment, conservation, recycling, catalogs, consumer, sending, opt out ">\r
+<link rel="next" href="precre.html">\r
+<link rel="previous" href="precre.html">\r
+<link rel="contents" href="toc.html">\r
+</head>\r
+<body bgcolor="#f8f8f0" link="#000078" alink="#ff0022" vlink="#787878">\r
+<p align="center">\r
+<a name="top_of_page" href="legal.html#marks">\r
+<img border=0 width=160 height=34 src="/images/trans_tn.gif" alt="Junkbusters"></a>\r
+</p>\r
+\r
+<center>\r
+<h1>The GNU General Public License\r
+</h1>\r
+</center>\r
+<!-- Translators: no -->\r
+<center>\r
+<h2><a name="notus"><font face="arial, helvetica">\r
+We did not write the GPL: the Free Software Foundation did\r
+</font></a>\r
+</h2>\r
+</center>\r
+\r
+<h3><a name="allows" href="/cgi-bin/gp?pg=gpl&pr=allows"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+The GPL allows copying and changing of copyrighted documents\r
+</h3>\r
+<p>\r
+<a name="fsf">The Free Software Foundation</a>\r
+<a href="http://www.fsf.org/fsf/fsf.html">(FSF)</a>\r
+is a non-profit institution\r
+that designed the GNU General Public License (GPL) to promote the\r
+publication of free software.\r
+The GPL is used by thousands of programmers\r
+who want to give others the right to copy and modify\r
+the source code of their programs. Millions of people benefit from this.\r
+<p>\r
+<a name="junkbuster">We use the GPL</a>\r
+to allow everyone to use, copy and modify the\r
+<a href="ijb.html">Internet Junkbuster</a>\r
+as they wish.\r
+<a name="separate">Companies can use it for commercial purposes,</a>\r
+but they are not permitted to use it in products that they claim\r
+as their property\r
+without negotiating a separate agreement with us beforehand.\r
+<p>\r
+<a name="text">The GPL</a>\r
+<a href="http://dsl.org/copyleft/">can also be used</a>\r
+on documents written in human languages.\r
+We give everyone permission to use everything on our web site under the GPL.\r
+This means that you do not have to break copyright laws in order\r
+to print a page or email a screen of the text to someone, for example.\r
+Many sites do not permit you to do these things.\r
+<p>\r
+<a name="best">If you have a home page,</a>\r
+we recommend that you consider using the GPL to\r
+allow others the right to copy and use all the documents you create for it.\r
+If you just mark a page as copyright, they won't even\r
+legally be able to print it.\r
+If you don't state you are its copyright owner,\r
+they could change it slightly and claim it as their own property. \r
+By marking it with both copyright and GPL notices\r
+you allow them to copy it but not to claim\r
+anything derived from it as their own.\r
+<p>\r
+<a name="protect">The GPL protects your</a>\r
+<a href="declare.html">J<small>UNK<i>BUSTERS</i></small> D<small>ECLARATION</small></a>,\r
+<a href="spamoff.html">Spam Offer</a>,\r
+and all documents from us that you publish on your home page\r
+or distribute to direct marketers by any other means.\r
+By making your\r
+D<small>ECLARATION</small>\r
+available to them under the GPL, you are\r
+<a href="precre.html#gpl">permitting them use to it, but never to claim it as their property,</a>\r
+even if they transform it.\r
+<p>\r
+<a name="rest">The</a>\r
+remainder of this page is the text of the GPL.\r
+As legal documents go it's relatively clear,\r
+but unfortunately it's fairly long because it has to cover\r
+a lot of details specific to computer programs\r
+that may not be relevant to\r
+D<small>ECLARATION</small>s.\r
+The hypertext links are ours, and should not be misinterpreted\r
+as an indication of emphasis by the FSF.\r
+</p>\r
+<p align="center"><a href="#top_of_page"><img border=0 width=250 height=15 src="/images/top.gif" alt="--- Back to Top of Page ---"></a></p>\r
+<center>\r
+<h2><a name="v2"><font face="arial, helvetica">\r
+Version 2, June 1991\r
+</font></a>\r
+</h2>\r
+</center>\r
+<blockquote>\r
+<a name="crn">Copyright 1989, 1991</a>\r
+<br>\r
+<a name="address">Free Software Foundation, Inc.</a>\r
+<br>\r
+675 Mass Ave.\r
+<br>\r
+Cambridge, MA 02139\r
+<br>\r
+USA\r
+</blockquote>\r
+<a name="changing">Everyone</a>\r
+is permitted to copy and distribute verbatim copies\r
+of this license document, but changing it is not allowed.\r
+\r
+<h3><a name="pream" href="/cgi-bin/gp?pg=gpl&pr=pream"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Preamble\r
+</h3>\r
+<p>\r
+The licenses for most software are designed to take away your\r
+freedom to share and change it. By contrast, the GNU General Public\r
+License is intended to guarantee your freedom to share and change free\r
+software--to make sure the software is free for all its users. This\r
+General Public License applies to most of the Free Software\r
+Foundation's software and to any other program whose authors commit to\r
+using it. (Some other Free Software Foundation software is covered by\r
+the GNU Library General Public License instead.) You can apply it to\r
+your programs, too.\r
+<p>\r
+<a name="freedom">When we speak of free software,</a>\r
+we are referring to freedom, not\r
+price. Our General Public Licenses are designed to make sure that you\r
+have the freedom to distribute copies of free software (and charge for\r
+this service if you wish), that you receive source code or can get it\r
+if you want it, that you can change the software or use pieces of it\r
+in new free programs; and that you know you can do these things.\r
+<p>\r
+<a name="forbid">To protect your rights,</a>\r
+we need to make restrictions that forbid\r
+anyone to deny you these rights or to ask you to surrender the rights.\r
+These restrictions translate to certain responsibilities for you if you\r
+distribute copies of the software, or if you modify it.\r
+<p>\r
+<a name="allrights">For example,</a>\r
+if you distribute copies of such a program, whether\r
+gratis or for a fee, you must give the recipients all the rights that\r
+you have. You must make sure that they, too, receive or can get the\r
+source code. And you must show them these terms so they know their\r
+rights.\r
+<p>\r
+<a name="steps">We protect your rights with two steps:</a>\r
+(1) copyright the software, and\r
+(2) offer you this license which gives you legal permission to copy,\r
+distribute and/or modify the software.\r
+<p>\r
+<a name="protection">Also,</a>\r
+for each author's protection and ours, we want to make certain\r
+that everyone understands that there is no warranty for this free\r
+software. If the software is modified by someone else and passed on, we\r
+want its recipients to know that what they have is not the original, so\r
+that any problems introduced by others will not reflect on the original\r
+authors' reputations.\r
+<p>\r
+<a name="threat">Finally,</a>\r
+any free program is threatened constantly by software\r
+patents. We wish to avoid the danger that redistributors of a free\r
+program will individually obtain patent licenses, in effect making the\r
+program proprietary. To prevent this, we have made it clear that any\r
+patent must be licensed for everyone's free use or not licensed at all.\r
+<p>\r
+<a name="terms">The precise terms and conditions</a>\r
+for copying, distribution and\r
+modification follow.\r
+</p>\r
+\r
+<h3><a name="tnc" href="/cgi-bin/gp?pg=gpl&pr=tnc"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+GNU General Public License: Terms and Conditions for Copying, Distribution and Modification\r
+</h3>\r
+<p>\r
+<a name="applies">O.</a>\r
+This License applies to any program or other work which contains\r
+a notice placed by the copyright holder saying it may be distributed\r
+under the terms of this General Public License. The "Program", below,\r
+refers to any such program or work, and a "work based on the Program"\r
+means either the Program or any derivative work under copyright law:\r
+that is to say, a work containing the Program or a portion of it,\r
+either verbatim or with modifications and/or translated into another\r
+language. (Hereinafter,\r
+<a href="bus-ops.html#trans">translation</a>\r
+is included without limitation in\r
+the term "modification".) Each licensee is addressed as "you".\r
+<p>\r
+<a name="scope">Activities</a>\r
+<a href="faqs.html#copying">other than copying, distribution and modification are not covered by this License;</a>\r
+they are outside its scope. The act of\r
+running the Program is not restricted, and the output from the Program\r
+is covered only if its contents constitute a work based on the\r
+Program (independent of having been made by running the Program).\r
+<p>\r
+<a name="depends">Whether that is true depends on what the Program does.</a>\r
+<br><ol type="1">\r
+<li>\r
+<a name="verbatim">You may copy</a>\r
+and distribute verbatim copies of the Program's\r
+source code as you receive it, in any medium, provided that you\r
+conspicuously and appropriately publish on each copy an appropriate\r
+copyright notice and disclaimer of warranty; keep intact all the\r
+notices that refer to this License and to the absence of any warranty;\r
+and give any other recipients of the Program a copy of this License\r
+along with the Program.\r
+<p>\r
+<a name="fee">You may charge a fee</a>\r
+for the physical act of transferring a copy, and\r
+you may at your option offer warranty protection in exchange for a fee.\r
+<li>\r
+<a name="modify">You may modify</a>\r
+your copy or copies of the Program or any portion\r
+of it, thus forming a work based on the Program, and copy and\r
+distribute such modifications or work under the terms of Section 1\r
+above, provided that you also meet all of these conditions:\r
+<br><ol type="a">\r
+<li>\r
+<a name="notices">You must cause</a>\r
+the modified files to carry prominent notices\r
+stating that you changed the files and the date of any change.\r
+<li>\r
+<a name="nocharge">You must</a>\r
+cause any work that you distribute or publish, that in\r
+whole or in part contains or is derived from the Program or any\r
+part thereof, to be licensed as a whole at no charge to all third\r
+parties under the terms of this License.\r
+<li>\r
+<a name="interactive">If the modified program</a>\r
+normally reads commands interactively\r
+when run, you must cause it, when started running for such\r
+interactive use in the most ordinary way, to print or display an\r
+announcement including an appropriate copyright notice and a\r
+notice that there is no warranty (or else, saying that you provide\r
+a warranty) and that users may redistribute the program under\r
+these conditions, and telling the user how to view a copy of this\r
+License. (Exception: if the Program itself is interactive but\r
+does not normally print such an announcement, your work based on\r
+the Program is not required to print an announcement.)\r
+</ol>\r
+<p>\r
+<a name="sections">These requirements</a>\r
+apply to the modified work as a whole. If\r
+identifiable sections of that work are not derived from the Program,\r
+and can be reasonably considered independent and separate works in\r
+themselves, then this License, and its terms, do not apply to those\r
+sections when you distribute them as separate works. But when you\r
+distribute the same sections as part of a whole which is a work based\r
+on the Program, the distribution of the whole must be on the terms of\r
+this License, whose permissions for other licensees extend to the\r
+entire whole, and thus to each and every part regardless of who wrote it.\r
+<p>\r
+<a name="intent">Thus,</a>\r
+it is not the intent of this section to claim rights or contest\r
+your rights to work written entirely by you; rather, the intent is to\r
+exercise the right to control the distribution of derivative or\r
+collective works based on the Program.\r
+<p>\r
+<a name="aggregation">In addition,</a>\r
+mere aggregation of another work not based on the Program\r
+with the Program (or with a work based on the Program) on a volume of\r
+a storage or distribution medium does not bring the other work under\r
+the scope of this License.\r
+<li>\r
+<a name="exeutable">You may copy</a>\r
+and distribute the Program (or a work based on it,\r
+under Section 2) in object code or executable form under the terms of\r
+Sections 1 and 2 above provided that you also do one of the following:\r
+<br><ol type="a">\r
+<li>\r
+<a name="medium">Accompany it</a>\r
+with the complete corresponding machine-readable\r
+source code, which must be distributed under the terms of Sections\r
+1 and 2 above on a medium customarily used for software interchange; or,\r
+<li>\r
+<a name="written">Accompany it with a written offer,</a>\r
+valid for at least three\r
+years, to give any third party, for a charge no more than your\r
+cost of physically performing source distribution, a complete\r
+machine-readable copy of the corresponding source code, to be\r
+distributed under the terms of Sections 1 and 2 above on a medium\r
+customarily used for software interchange; or,\r
+<li>\r
+<a name="distrib">Accompany it</a>\r
+with the information you received as to the offer\r
+to distribute corresponding source code. (This alternative is\r
+allowed only for noncommercial distribution and only if you\r
+received the program in object code or executable form with such\r
+an offer, in accord with Subsection b above.)\r
+</ol>\r
+<p>\r
+<a name="preferred">The source code</a>\r
+for a work means the preferred form of the work for\r
+making modifications to it. For an executable work, complete source\r
+code means all the source code for all modules it contains, plus any\r
+associated interface definition files, plus the scripts used to\r
+control compilation and installation of the executable. However, as a\r
+special exception, the source code distributed need not include\r
+anything that is normally distributed (in either source or binary\r
+form) with the major components (compiler, kernel, and so on) of the\r
+operating system on which the executable runs, unless that component\r
+itself accompanies the executable.\r
+<p>\r
+<a name="access">If distribution of executable or object code is made</a>\r
+by offering\r
+access to copy from a designated place, then offering equivalent\r
+access to copy the source code from the same place counts as\r
+distribution of the source code, even though third parties are not\r
+compelled to copy the source along with the object code.\r
+<li>\r
+<a name="otherwise">You may not copy,</a>\r
+modify, sublicense, or distribute the Program\r
+except as expressly provided under this License. Any attempt\r
+otherwise to copy, modify, sublicense or distribute the Program is\r
+void, and will automatically terminate your rights under this License.\r
+However, parties who have received copies, or rights, from you under\r
+this License will not have their licenses terminated so long as such\r
+parties remain in full compliance.\r
+<li>\r
+<a name="voluntary">You are not required</a>\r
+to accept this License, since you have not\r
+signed it. However, nothing else grants you permission to modify or\r
+distribute the Program or its derivative works. These actions are\r
+prohibited by law if you do not accept this License. Therefore, by\r
+modifying or distributing the Program (or any work based on the\r
+Program), you indicate your acceptance of this License to do so, and\r
+all its terms and conditions for copying, distributing or modifying\r
+the Program or works based on it.\r
+<li>\r
+<a name="redistrib">Each time you redistribute</a>\r
+the Program (or any work based on the\r
+Program), the recipient automatically receives a license from the\r
+original licensor to copy, distribute or modify the Program subject to\r
+these terms and conditions. You may not impose any further\r
+restrictions on the recipients' exercise of the rights granted herein.\r
+You are not responsible for enforcing compliance by third parties to\r
+this License.\r
+<li>\r
+<a name="patent">If, as a consequence of a court judgment</a>\r
+or allegation of patent\r
+infringement or for any other reason (not limited to patent issues),\r
+conditions are imposed on you (whether by court order, agreement or\r
+otherwise) that contradict the conditions of this License, they do not\r
+excuse you from the conditions of this License. If you cannot\r
+distribute so as to satisfy simultaneously your obligations under this\r
+License and any other pertinent obligations, then as a consequence you\r
+may not distribute the Program at all. For example, if a patent\r
+license would not permit royalty-free redistribution of the Program by\r
+all those who receive copies directly or indirectly through you, then\r
+the only way you could satisfy both it and this License would be to\r
+refrain entirely from distribution of the Program.\r
+<p>\r
+<a name="invalid">If any portion</a>\r
+of this section is held invalid or unenforceable under\r
+any particular circumstance, the balance of the section is intended to\r
+apply and the section as a whole is intended to apply in other\r
+circumstances.\r
+<p>\r
+<a name="induce">It is not the purpose</a>\r
+of this section to induce you to infringe any\r
+patents or other property right claims or to contest validity of any\r
+such claims; this section has the sole purpose of protecting the\r
+integrity of the free software distribution system, which is\r
+implemented by public license practices. Many people have made\r
+generous contributions to the wide range of software distributed\r
+through that system in reliance on consistent application of that\r
+system; it is up to the author/donor to decide if he or she is willing\r
+to distribute software through any other system and a licensee cannot\r
+impose that choice.\r
+<p>\r
+<a name="clarify">This section</a>\r
+is intended to make thoroughly clear what is believed to\r
+be a consequence of the rest of this License.\r
+<li>\r
+<a name="geog">If the distribution</a>\r
+and/or use of the Program is restricted in\r
+certain countries either by patents or by copyrighted interfaces, the\r
+original copyright holder who places the Program under this License\r
+may add an explicit geographical distribution limitation excluding\r
+those countries, so that distribution is permitted only in or among\r
+countries not thus excluded. In such case, this License incorporates\r
+the limitation as if written in the body of this License.\r
+<li>\r
+<a name="revise">The Free Software Foundation</a>\r
+may publish revised and/or new versions \r
+of the General Public License from time to time. Such new versions will\r
+be similar in spirit to the present version, but may differ in detail to\r
+address new problems or concerns.\r
+Each version is given a distinguishing version number. If the Program\r
+specifies a version number of this License which applies to it and "any\r
+later version", you have the option of following the terms and conditions\r
+either of that version or of any later version published by the Free\r
+Software Foundation. If the Program does not specify a version number of\r
+this License, you may choose any version ever published by the Free Software\r
+Foundation.\r
+<li>\r
+<a name="permission">If you wish to incorporate parts</a>\r
+of the Program into other free\r
+programs whose distribution conditions are different, write to the author\r
+to ask for permission. For software which is copyrighted by the Free\r
+Software Foundation, write to the Free Software Foundation; we sometimes\r
+make exceptions for this. Our decision will be guided by the two goals\r
+of preserving the free status of all derivatives of our free software and\r
+of promoting the sharing and reuse of software generally.\r
+<p>\r
+<a name="nowarr">NO WARRANTY</a>\r
+<li>\r
+<a name="foc">BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE,</a>\r
+THERE IS NO WARRANTY\r
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\r
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\r
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\r
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\r
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\r
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\r
+REPAIR OR CORRECTION.\r
+<li>\r
+<a name="liable">IN NO EVENT UNLESS REQUIRED</a>\r
+BY APPLICABLE LAW OR AGREED TO IN WRITING\r
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\r
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\r
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\r
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\r
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\r
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\r
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\r
+POSSIBILITY OF SUCH DAMAGES.\r
+</ol>\r
+END OF TERMS AND CONDITIONS\r
+</p>\r
+\r
+<h3><a name="append" href="/cgi-bin/gp?pg=gpl&pr=append"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Appendix: How to Apply These Terms to Your New Programs\r
+</h3>\r
+<p>\r
+If you develop a new program, and you want it to be of the greatest\r
+possible use to the public, the best way to achieve this is to make it\r
+free software which everyone can redistribute and change under these terms.\r
+<p>\r
+<a name="attach">To do so,</a>\r
+attach the following notices to the program. It is safest\r
+to attach them to the start of each source file to most effectively\r
+convey the exclusion of warranty; and each file should have at least\r
+the "copyright" line and a pointer to where the full notice is found.\r
+<blockquote>\r
+<one line\r
+to give the program's name and a brief idea of what it\r
+does.>\r
+Copyright (C) 19yy\r
+<name of\r
+author>\r
+<p>\r
+<a name="free">This program is free software;</a>\r
+you can redistribute it and/or modify\r
+it under the terms of the GNU General Public License as published by\r
+the Free Software Foundation; either version 2 of the License, or\r
+(at your option) any later version.\r
+<p>\r
+<a name="merchant">This program</a>\r
+is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+GNU General Public License for more details.\r
+<p>\r
+<a name="ifnot">You should</a>\r
+have received a copy of the GNU General Public License\r
+along with this program; if not, write to the Free Software\r
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+</blockquote>\r
+<p>\r
+<a name="contact">Also add</a>\r
+information on how to contact you by electronic and paper mail.\r
+<p>\r
+<a name="short">If the program is interactive,</a>\r
+make it output a short notice like this\r
+when it starts in an interactive mode:\r
+<blockquote>\r
+Gnomovision version 69, Copyright (C) 19yy name of author\r
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\r
+This is free software, and you are welcome to redistribute it\r
+under certain conditions; type `show c' for details.\r
+</blockquote>\r
+<p>\r
+<a name="hypo">The hypothetical</a>\r
+commands `show w' and `show c' should show the appropriate\r
+parts of the General Public License. Of course, the commands you use may\r
+be called something other than `show w' and `show c'; they could even be\r
+mouse-clicks or menu items--whatever suits your program.\r
+<p>\r
+<a name="disclaimer">You should also get your employer</a>\r
+(if you work as a programmer) or your\r
+school, if any, to sign a "copyright disclaimer" for the program, if\r
+necessary. Here is a sample; alter the names:\r
+<blockquote>\r
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program\r
+`Gnomovision' (which makes passes at compilers) written by James Hacker.\r
+\r
+<signature\r
+of\r
+Ty Coon>,\r
+1 April 1989\r
+<br>\r
+Ty Coon, President of Vice\r
+</blockquote>\r
+<p>\r
+<a name="library">This General Public License</a>\r
+does not permit incorporating your program into\r
+proprietary programs. If your program is a subroutine library, you may\r
+consider it more useful to permit linking proprietary applications with the\r
+library. If this is what you want to do, use the GNU Library General\r
+Public License instead of this License.\r
+</p>\r
+<p align="center"><a href="#top_of_page"><img border=0 width=250 height=15 src="/images/top.gif" alt="--- Back to Top of Page ---"></a></p>\r
+<font face="arial, helvetica">\r
+<a rel="begin" href="index.html">Home</a> <font color="#ff0000">\r
+<b> · </b></font>\r
+<a rel="next" href="precre.html">Next</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="lopt.html">Site Map</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="legal.html">Legal</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="junkdata.html">Privacy</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="cookies.html">Cookies</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="ijb.html">Banner Ads</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="telemarketing.html">Telemarketing</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="junkmail.html">Mail</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="junkemail.html">Spam</a>\r
+\r
+</font><form action="/cgi-bin/search" method="GET">\r
+<input type="text" name="q" size=60 maxlength=120 value="">\r
+<input type="submit" value="Search"></form>\r
+<small>\r
+<small>\r
+<p>\r
+<a href="legal.html#copy">Copyright</a> © 1996-8 Junkbusters\r
+<a href="legal.html#marks">®</a> Corporation.\r
+Copying and distribution permitted under\r
+the <a href="gpl.html"><small>GNU</small></a>\r
+General Public License.\r
+</small>\r
+<tt>\r
+1998/10/31\r
+http://www.junkbusters.com/ht/en/gpl.html\r
+</tt>\r
+<address><kbd>webmaster@junkbusters.com</kbd></address>\r
+</small>\r
+</body>\r
+</html>\r
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">\r
+<html>\r
+<head>\r
+<!-- Copyright 1996-8 Junkbusters Corporation -->\r
+<!-- This work comes with NO WARRANTY -->\r
+<!-- It may be redistributed and modified under the GNU GPL-->\r
+<!-- See the body of http://www.junkbusters.com/ht/en/gpl.html for details-->\r
+<!-- Junkbusters is a registered trade mark of Junkbusters Corporation -->\r
+<!-- Generated 1998/10/31 03:58:25 UTC -->\r
+<meta name="Generator" content="Junkbusters Ebira $Revision: 1.1 $ $Date: 2001/04/16 21:10:38 $">\r
+<!-- Document ID: $Revision: 1.1 $ $Date: 2001/04/16 21:10:38 $ -->\r
+<title>\r
+Internet Junkbuster Frequently Asked Questions\r
+</title>\r
+<base href="http://www.junkbusters.com/ht/en/ijbfaq.html">\r
+<meta name="description" content="An extensive FAQ on the Internet Junkbuster, free software to removes banner ads, cookies, and other stuff you don't want from your web browser.">\r
+<meta name="keywords" content="stop, junk, busters, junkbusters, junkbuster, mail, email, e-mail, direct, spam, spamoff, declare, telemarketing, telemarketers, privacy, sharing, names, renting, direct, marketing, database, databases, junk mail, lists, environment, conservation, recycling, catalogs, consumer, sending, opt out , privacy, advertising, direct, marketing, targeting, through, click, trails, http_referer, cookie, cutter, iff, internet fast forward, Cookie Management Tool">\r
+<link rel="next" href="ijbman.html">\r
+<link rel="previous" href="ijb.html">\r
+<link rel="contents" href="toc.html">\r
+</head>\r
+<body bgcolor="#f8f8f0" link="#000078" alink="#ff0022" vlink="#787878">\r
+<center>\r
+<h1><a name="top_of_page">Internet J<small>UNK<i><font color=red>BUSTER</font></i></small> Frequently Asked Questions\r
+</a></h1>\r
+</center>\r
+<font face="arial, helvetica">\r
+<p align="center">\r
+<a href="#u">Download for UNIX</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="ijbwin.html#zip">(Download for Windows 95/NT)</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="ijbdist.html#top_of_page">(Other OS)</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="#browser">Configuring Browsers</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="#local">Installation</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="#companies">For Companies</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="#blocking">Blocking</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="#cookies">Cookies</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="#anonymity">Anonymity</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="#security">Security</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="ijbman.html#top_of_page">(Technical Manual)</a>\r
+</p>\r
+</font><br>\r
+<center>\r
+<h2><a name="top"><font face="arial, helvetica">\r
+The Top Ten Questions\r
+</font></a>\r
+</h2>\r
+</center>\r
+<br>For a list of the questions on this page (without the answers),\r
+see our\r
+<a href="toc.html#ijbfaq">Table of Contents.</a>\r
+It also contains detailed pointers into our pages\r
+on\r
+<a href="cookies.html">cookies</a>\r
+and on busting \r
+<a href="junkemail.html">junk e-mail,</a>\r
+<a href="junkmail.html">junk mail</a>\r
+and\r
+<a href="telemarketing.html">telemarketing calls.</a>\r
+\r
+<h3><a name="what" href="/cgi-bin/gp?pg=ijbfaq&pr=what"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+What is the Internet Junkbuster Proxy and what does it do for me?\r
+</h3>\r
+<p>\r
+The\r
+Internet Junkbuster\r
+Proxy\r
+<a href="legal.html#marks"><small><sup>TM</sup></small></a>\r
+is\r
+<a href="ijbfaq.html#free">free</a>\r
+privacy-enhancing software that can be run on your PC or by your\r
+<small>ISP</small>\r
+or company.\r
+It blocks requests for\r
+<small>URL</small>s\r
+(typically banner ads)\r
+that match its\r
+<a href="ijbfaq.html#blocking">blockfile.</a>\r
+It also deletes unauthorized\r
+<a href="ijbfaq.html#cookies">cookies</a>\r
+and other\r
+unwanted identifying\r
+<a href="ijbfaq.html#anonymity">header information</a>\r
+that is exchanged between web servers and browsers.\r
+These headers are not normally accessible to users\r
+(even though they may contain information that's important to your privacy),\r
+but with the\r
+Internet Junkbuster\r
+you can see almost\r
+<a href="ijbman.html#o_d">anything you want</a>\r
+and control everything you're likely to need.\r
+<b>You</b>\r
+<a href="over.html#you_def">decide what's junk.</a>\r
+<a href="legal.html#marks"><small><sup>SM</sup></small></a>\r
+Many people\r
+<a href="ijbfaq.html#readymade">publish</a>\r
+their blockfiles to help others get started.\r
+</p>\r
+\r
+<h3><a name="free" href="/cgi-bin/gp?pg=ijbfaq&pr=free"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Is there a license fee / warranty / registration form / expiration?\r
+</h3>\r
+<p>\r
+No, none of these.\r
+It's completely free of charge.\r
+Junkbusters\r
+offers you the software to copy, use, modify and distribute\r
+as you wish, forever, at\r
+<a href="over.html#nobucks">no charge</a>\r
+under the\r
+<a href="gpl.html">GNU General Public License.</a>\r
+<p>\r
+<a name="warranty">It comes with</a>\r
+<a href="gpl.html#nowarr">no warranty of any kind.</a>\r
+<p>\r
+<a name="register">You don't have to register,</a>\r
+in fact we don't even provide a way to do so:\r
+the practice of registering software is\r
+usually just an\r
+excuse\r
+to send you solicitations and\r
+<a href="self.html#warranty">sell your name</a>\r
+and information about your behavior.\r
+You are welcome to obtain and use our software as anonymously you wish.\r
+(Your\r
+<small>IP</small>\r
+address will naturally be\r
+<a href="http://www.junkbusters.com/cgi-bin/privacy">disclosed</a>\r
+when you download it,\r
+so if you work for a web ad company\r
+you might want to use a service such as the\r
+<a href="ijbfaq.html#anonymizing">lpwa.com</a>\r
+when you get it.\r
+We\r
+<a href="over.html#nopriv">never</a>\r
+want to be given any information that you consider private or confidential.)\r
+<p>\r
+<a name="why">We are often asked why we give away a product that many</a>\r
+would happily pay for.\r
+The answer is that we are determined to carry out our\r
+<a href="over.html">mission:</a>\r
+to free the world from junk communications.\r
+</p>\r
+\r
+<h3><a name="windows" href="/cgi-bin/gp?pg=ijbfaq&pr=windows"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Does it run on Windows? On a Mac? On the AOL browser?\r
+</h3>\r
+<p>\r
+For the latest information on availability, see the\r
+<a href="ijbdist.html">Distribution Information</a>\r
+page.\r
+We\r
+<a href="ijbdist.html#win3.1">don't</a>\r
+think it will ever run on\r
+Windows 3.1.\r
+But you don't need to have it running on your computer\r
+if you get your\r
+<small>ISP</small>\r
+or Systems Administrator at\r
+<a href="ijbfaq.html#companies">work</a>\r
+to run it.\r
+</p>\r
+\r
+<h3><a name="isp" href="/cgi-bin/gp?pg=ijbfaq&pr=isp"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How can I get my ISP to run the Internet Junkbuster?\r
+</h3>\r
+<p>\r
+Try their sales or support department\r
+(depending on whether you are already a customer).\r
+<a name="unaware">You might send them email including the following</a>\r
+<small>URL</small>:\r
+<br>\r
+   <big><kbd>http://www.junkbusters.com/ht/en/ijbfaq.html#isps</kbd></big>\r
+<br>\r
+<a name="switch">You could mention that many</a>\r
+<a href="ijbfaq.html#does">other</a>\r
+<small>ISP</small>s\r
+provide it,\r
+and that you regard it as an important part of your decision on\r
+where to buy Internet service.\r
+</p>\r
+\r
+<h3><a name="who" href="/cgi-bin/gp?pg=ijbfaq&pr=who"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Who chooses the options that control what is blocked?\r
+</h3>\r
+<p>\r
+Whoever starts the\r
+Internet Junkbuster\r
+chooses the options and the blockfile.\r
+If your \r
+<small>ISP</small>\r
+runs it for you, they have to make these decision\r
+(though\r
+<a href="http://www.lunatech.com/proxy/">some</a>\r
+may give you a choice of proxies,\r
+and a way to suggest new\r
+<small>URL</small>s\r
+to block).\r
+If you run it on your computer,\r
+<b>You</b>\r
+<a href="over.html#you_def">decide what's junk.</a>\r
+<a href="legal.html#marks"><small><sup>SM</sup></small></a>\r
+</p>\r
+\r
+<h3><a name="self" href="/cgi-bin/gp?pg=ijbfaq&pr=self"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How do I download and run the program on my computer?\r
+</h3>\r
+<p>\r
+It depends on your platform.\r
+If you are using Windows 95 or NT,\r
+see our separate page on\r
+<a href="ijbwin.html">installing under Windows.</a>\r
+If you have a C compiler and are using almost any flavor of\r
+<small>UNIX <a href="legal.html#not_our_trademark">®</a></small>\r
+you\r
+<a href="ijbfaq.html#local">download it, compile it, start it running,</a>\r
+and then\r
+<a href="ijbfaq.html#browser">configure your browser.</a>\r
+Several precompiled packages are also available through links in our\r
+<a href="ijbdist.html">distribution page</a>,\r
+which lists all available platforms.\r
+<p>\r
+<a name="port">If you are using a platform for which we have no current</a>\r
+availability,\r
+you are welcome to port the code.\r
+If you do this and you would like us to consider publishing your ported version,\r
+please\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=port">tell us.</a>\r
+</p>\r
+\r
+<h3><a name="show" href="/cgi-bin/gp?pg=ijbfaq&pr=show"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How can I tell which blockfile and options are being used?\r
+</h3>\r
+<p>\r
+Just point your browser to\r
+<a href="http://internet.junkbuster.com/cgi-bin/show-proxy-args">http://internet.junkbuster.com/cgi-bin/show-proxy-args</a>\r
+or to any\r
+<small>URL</small>\r
+ending in\r
+<big><kbd>show-proxy-args</kbd></big>\r
+(even if it doesn't exist).\r
+It needn't exist because the\r
+Internet Junkbuster 2.0\r
+intercepts the request, blocks it,\r
+and returns in its place\r
+information about itself.\r
+Using the\r
+<small>URL</small>\r
+above is useful for checking that your browser really is\r
+going through an\r
+Internet Junkbuster,\r
+because the\r
+<big><kbd>junkbuster.com</kbd></big>\r
+server returns a warning if the request actually gets to it.\r
+Some people set the home page of their browser to such a\r
+<small>URL</small>\r
+to be sure that it is configured to use the proxy.\r
+<p>\r
+<a name="headers">If you wish to check the header information</a>\r
+your proxy is actually sending,\r
+a visit to\r
+<a href="http://internet.junkbuster.com/cgi-bin/show-http-headers">http://internet.junkbuster.com/cgi-bin/show-http-headers</a>\r
+will give you the more relevant ones first.\r
+You might also like to turn the proxy\r
+<a href="ijbfaq.html#discontinue">off</a>\r
+and compare the difference. (Don't forget to turn it back on again.)\r
+</p>\r
+\r
+<h3><a name="responding" href="/cgi-bin/gp?pg=ijbfaq&pr=responding"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+My browser started giving me ``server not responding'' messages\r
+</h3>\r
+<p>\r
+Once your browser is told to use a proxy such as the\r
+Internet Junkbuster,\r
+it thinks of it as its server for everything,\r
+so this message means it can't talk to the proxy.\r
+The\r
+Internet Junkbuster\r
+may not be running,\r
+or you may have specified its proxy\r
+<a href="ijbfaq.html#address">address</a>\r
+incorrectly.\r
+Check that the details you entered are correct.\r
+If you have\r
+<big><kbd>telnet</kbd></big>\r
+you can try connecting to the appropriate port to see if the\r
+Internet Junkbuster\r
+is running.\r
+If your\r
+<small>ISP</small>\r
+is running the\r
+Internet Junkbuster,\r
+you may want to check with them.\r
+If you are running it yourself under\r
+<small>UNIX <a href="legal.html#not_our_trademark">®</a></small>,\r
+try looking at a\r
+<big><kbd>ps ax</kbd></big>\r
+to see if it is running.\r
+The\r
+<a href="ijbman.html#o_h">port</a>\r
+specified in its options should be the same one as your\r
+browser has configured.\r
+</p>\r
+\r
+<h3><a name="idea" href="/cgi-bin/gp?pg=ijbfaq&pr=idea"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+I've got this great idea for a new feature. Who do I tell?\r
+</h3>\r
+<p>\r
+We'd be very interested to hear it, but please bear a few things in mind.\r
+<br><ul type="1">\r
+<li>\r
+<a name="considered">Please check this FAQ to see if we've already considered</a>\r
+the idea,\r
+such as\r
+<a href="ijbfaq.html#size">automatic detection</a>\r
+of banner ads\r
+and\r
+<a href="ijbfaq.html#broken">replacing ads</a>\r
+with something else such as a\r
+transparent\r
+<small>GIF</small>.\r
+<li>\r
+<a name="confidential">Don't tell us anything you want to keep confidential</a>\r
+or retain some right over.\r
+<li>\r
+<a name="wish">We currently have a</a>\r
+long wish list of things that we may or may not do\r
+in the near future, including\r
+a version for your favorite computer and a plug-in version.\r
+<li>\r
+<a name="go4it">If you don't want to wait</a>\r
+you're welcome to improve on our code, publish your version on the Web,\r
+and\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=idea">tell us</a>\r
+where to find it.\r
+Projects that are especially welcome\r
+include\r
+a port to the Mac\r
+and extensions for\r
+<small>HTTP</small>\r
+1.1.\r
+</ul>\r
+</p>\r
+\r
+<h3><a name="other" href="/cgi-bin/gp?pg=ijbfaq&pr=other"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+My question isn't listed here. Who do I ask for support?\r
+</h3>\r
+<p>\r
+<a name="harder">If you find using our free product</a>\r
+harder than you're used to for consumer software,\r
+there are many\r
+<a href="links.html#WebWiper">commercial alternatives</a>\r
+that you could consider.\r
+<p>\r
+<a name="RTM">The answer to detailed technical questions may be answered in</a>\r
+<a href="ijbman.html">manual page</a>,\r
+or in the source code.\r
+Also double-check this page for an answer:\r
+using the ``find'' feature on your browser for likely keywords may help.\r
+Our site also has a\r
+<a href="search.html">search</a>\r
+feature.\r
+<p>\r
+<a name="Use">Many people post requests for help and responses on</a>\r
+<a href="http://search.dejanews.com/dnquery.xp?query=junkbuster&site=excite">Usenet.</a>\r
+<p>\r
+<a name="them">If your</a>\r
+<small>ISP</small>\r
+is providing\r
+the\r
+Internet Junkbuster\r
+for you,\r
+and your question is about how to use it,\r
+check their web page before asking them.\r
+<p>\r
+<a name="us">Even though we don't offer the kind of</a>\r
+support you might expect if you paid a lot of money for a software product,\r
+you can still ask us.\r
+But before you do, please consider whether\r
+you could ask someone closer to you.\r
+And please be patient if we're slow to reply: we\r
+<a href="over.html#nobucks">never charge consumers </a>\r
+for our services,\r
+so we have to subsidize consumers with revenue from companies,\r
+and our resources are limited.\r
+<p>\r
+<a name="quote">If your company or organization</a>\r
+would be interested in a maintenance contract\r
+with phone and email support,\r
+hard copy documentation and source code and pre-compiled binaries on tape\r
+or disk,\r
+please\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=quote">ask us</a>\r
+for a quote.\r
+</p>\r
+<p align="center"><a href="#top_of_page"><img border=0 width=250 height=15 src="/images/top.gif" alt="--- Back to Top of Page ---"></a></p>\r
+<br>\r
+<center>\r
+<h2><a name="browser"><font face="arial, helvetica">\r
+Configuring your browser to talk to the Internet Junkbuster\r
+</font></a>\r
+</h2>\r
+</center>\r
+<br>\r
+<h3><a name="address" href="/cgi-bin/gp?pg=ijbfaq&pr=address"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+What is the proxy address of the Internet Junkbuster?\r
+</h3>\r
+<p>\r
+<a name="localhost">If you set up</a>\r
+the\r
+Internet Junkbuster\r
+to run on the computer you browse from\r
+(rather than your\r
+<small>ISP</small>'s server\r
+or some networked computer at work),\r
+the proxy will be on\r
+<big><kbd>localhost</kbd></big>\r
+(which is the special name used by every computer on the Internet to\r
+refer to itself)\r
+and\r
+the port will be\r
+<big><kbd>8000</kbd></big>\r
+(unless you have told the\r
+Internet Junkbuster\r
+to\r
+run on a different port with the\r
+<a href="ijbman.html#listen-address">listen-address</a>\r
+option).\r
+So you when\r
+<a href="ijbfaq.html#set">configuring your browser's proxy settings</a>\r
+you typically enter the word\r
+<big><kbd>localhost</kbd></big>\r
+in the two boxes next to\r
+<b><font face="arial, helvetica">\r
+HTTP</font></b>\r
+and\r
+<b><font face="arial, helvetica">\r
+Secure</font></b>,\r
+and the number\r
+<big><kbd>8000</kbd></big>\r
+in the two boxes labelled\r
+to the right of those boxes.\r
+<p>\r
+<a name="remote">If your</a>\r
+<small>ISP</small>\r
+or company is running \r
+the\r
+Internet Junkbuster\r
+for you,\r
+they will tell you the address to use.\r
+It will be the name of the computer it's running on\r
+(or possibly its numeric IP address),\r
+plus a port number.\r
+Port 8000 is the default, so assume this number if it is not specified.\r
+Sometimes a colon is used to glue them together,\r
+as in\r
+<big><kbd>junkbuster.fictitous-pro-privacy-isp.net:8000</kbd></big>\r
+but\r
+with most browsers\r
+you do not type the colon,\r
+you enter the address and port number in separate boxes.\r
+</p>\r
+\r
+<h3><a name="set" href="/cgi-bin/gp?pg=ijbfaq&pr=set"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How do I tell the browser where to find the Internet Junkbuster?\r
+</h3>\r
+<p>\r
+All current browsers can be told the address of a proxy to use.\r
+You enter the same information in two fields in your browser's proxy\r
+configuration screen (see list below): one for\r
+<small>HTTP</small>,\r
+and one for the Secure Protocol (assuming your browser supports\r
+<small>SSL</small>).\r
+If you find some information already entered for your proxy,\r
+see the\r
+<a href="ijbfaq.html#already">next question.</a>\r
+Here are the menus you go through to get to the proxy configuration settings.\r
+(We also recommend that you\r
+<a href="links.html#java">disable Java</a>,\r
+which is a separate operation.)\r
+<strong>Make notes on the changes you make so you know how to undo them!</strong>\r
+You will need to know what you did\r
+in case you wish to\r
+<a href="ijbfaq.html#discontinue">discontinue</a>\r
+using the proxy.\r
+<br><ul type="1">\r
+<li>\r
+<a name="netscape">For</a>\r
+<a href="http://www.netscape.com/comprod/products/navigator/version_3.0/index.html">Netscape</a>\r
+2.01, 2.02 and 3.0\r
+<a href="/images/pcn30.gif">[Graphic Illustration]:</a>\r
+<b><font face="arial, helvetica">\r
+Options</font></b>;\r
+<b><font face="arial, helvetica">\r
+Network Preferences</font></b>;\r
+<b><font face="arial, helvetica">\r
+Proxies</font></b>;\r
+<b><font face="arial, helvetica">\r
+Manual Proxy Configuration View ;</font></b>\r
+enter\r
+<a href="ijbfaq.html#address">proxy address details</a>\r
+under\r
+<b><font face="arial, helvetica">\r
+HTTP</font></b>\r
+and\r
+<b><font face="arial, helvetica">\r
+Security Proxy</font></b>;\r
+click on\r
+<b><font face="arial, helvetica">\r
+OK</font></b>;\r
+click on the next\r
+<b><font face="arial, helvetica">\r
+OK</font></b>.\r
+<br>\r
+With Netscape 2.0,\r
+follow with\r
+<b><font face="arial, helvetica">\r
+Options</font></b>,\r
+<b><font face="arial, helvetica">\r
+Save Options</font></b>.\r
+<br>\r
+<a name="Netscape4.02">With Netscape 4.X series, you first have to go through</a>\r
+<b><font face="arial, helvetica">\r
+Edit/Preferences</font></b>.\r
+<a href="/images/pcn405.gif">[Graphic Illustration]</a>\r
+Then in the frame on the left,\r
+click on triangle pointing to the right towards the word\r
+<b><font face="arial, helvetica">\r
+Advanced</font></b>;\r
+it will switch to a triangle pointing down;\r
+and the words\r
+<b><font face="arial, helvetica">\r
+Cache</font></b>,\r
+<b><font face="arial, helvetica">\r
+Proxies</font></b>\r
+and\r
+<b><font face="arial, helvetica">\r
+Disk Space</font></b>\r
+appear.\r
+Click on\r
+<b><font face="arial, helvetica">\r
+Proxies</font></b>\r
+and the frame on the right will\r
+display a banner saying\r
+<b><font face="arial, helvetica">\r
+Proxies Configure proxies to access the Internet</font></b>.\r
+Click the radio button labeled\r
+<b><font face="arial, helvetica">\r
+Manual proxy configuration</font></b>\r
+then click the button labeled\r
+<b><font face="arial, helvetica">\r
+View</font></b>;\r
+enter\r
+<a href="ijbfaq.html#address">proxy address details</a>\r
+under\r
+<b><font face="arial, helvetica">\r
+HTTP</font></b>\r
+and\r
+<b><font face="arial, helvetica">\r
+Security Proxy</font></b>;\r
+click on\r
+<b><font face="arial, helvetica">\r
+OK</font></b>;\r
+click on the next\r
+<b><font face="arial, helvetica">\r
+OK</font></b>.\r
+<li>\r
+<a name="explorer3">For</a>\r
+<a href="http://www.microsoft.com/ie/support/docs/tech30/">Internet Explorer 3.0:</a>\r
+<b><font face="arial, helvetica">\r
+View</font></b>;\r
+<b><font face="arial, helvetica">\r
+Options</font></b>;\r
+<b><font face="arial, helvetica">\r
+Connections</font></b>;\r
+tick\r
+<b><font face="arial, helvetica">\r
+Connect through proxy server</font></b>\r
+box;\r
+<b><font face="arial, helvetica">\r
+Settings</font></b>;\r
+enter\r
+<a href="ijbfaq.html#address">proxy address details</a>\r
+<b><font face="arial, helvetica">\r
+HTTP</font></b>\r
+Box, with port number in the second box;\r
+same with\r
+<b><font face="arial, helvetica">\r
+Secure</font></b>;\r
+click on\r
+<b><font face="arial, helvetica">\r
+OK</font></b>.\r
+<li>\r
+<a name="explorer2">For Internet Explorer 2.0: </a>\r
+<b><font face="arial, helvetica">\r
+View</font></b>;\r
+<b><font face="arial, helvetica">\r
+Options</font></b>;\r
+<b><font face="arial, helvetica">\r
+Proxy</font></b>;\r
+enter\r
+<a href="ijbfaq.html#address">proxy address details</a>\r
+click on\r
+<b><font face="arial, helvetica">\r
+OK</font></b>.\r
+<li>\r
+<a name="nt">On NT for MS-IE:</a>\r
+<b><font face="arial, helvetica">\r
+Control Panel</font></b>;\r
+<b><font face="arial, helvetica">\r
+Internet</font></b>;\r
+<b><font face="arial, helvetica">\r
+Advanced</font></b>;\r
+<b><font face="arial, helvetica">\r
+Proxy</font></b>.\r
+<li>\r
+<a name="if">For MS-IE 4.0: seems to be almost the same as for</a>\r
+<a href="ijbfaq.html#explorer3">3.0</a>,\r
+<b><font face="arial, helvetica">\r
+View</font></b>;\r
+<b><font face="arial, helvetica">\r
+Internet Options</font></b>;\r
+<b><font face="arial, helvetica">\r
+Connections</font></b>;\r
+tick\r
+<b><font face="arial, helvetica">\r
+Connect through proxy server</font></b>\r
+box;\r
+<b><font face="arial, helvetica">\r
+Settings</font></b>;\r
+enter\r
+<a href="ijbfaq.html#address">proxy address details</a>\r
+<b><font face="arial, helvetica">\r
+HTTP</font></b>\r
+Box, with port number in the second box;\r
+same with\r
+<b><font face="arial, helvetica">\r
+Secure</font></b>;\r
+click on\r
+<b><font face="arial, helvetica">\r
+OK</font></b>.\r
+Note that 4.0 has\r
+<b><font face="arial, helvetica">\r
+Advanced</font></b>\r
+settings to allow\r
+<small>HTTP</small>\r
+1.1 through proxies;\r
+these must be disabled because the proxy does not currently understand\r
+<small>HTTP</small>\r
+1.1.\r
+Please\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=set">tell us</a>\r
+if you see any other differences.\r
+<li>\r
+<a name="mosaic">For NCSA Mosaic for Windows:</a>\r
+<b><font face="arial, helvetica">\r
+Options</font></b>,\r
+<b><font face="arial, helvetica">\r
+Preferences</font></b>,\r
+<b><font face="arial, helvetica">\r
+Proxy</font></b>;\r
+enter\r
+<a href="ijbfaq.html#address">proxy address details</a>\r
+under\r
+<b><font face="arial, helvetica">\r
+HTTP</font></b>.\r
+<li>\r
+<a name="Opera">For</a>\r
+Opera:\r
+<b><font face="arial, helvetica">\r
+Preferences</font></b>,\r
+<b><font face="arial, helvetica">\r
+Proxy servers</font></b>;\r
+check the box next to HTTP;\r
+enter the server and port number in the box on the other side;\r
+click on\r
+<b><font face="arial, helvetica">\r
+OK</font></b>.\r
+<li>\r
+<a name="lynx">For</a>\r
+<a href="http://www.yahoo.com/Computers_and_Internet/Software/Internet/World_Wide_Web/Browsers/Lynx">Lynx,</a>\r
+<a href="http://www.yahoo.com/Computers_and_Internet/Software/Internet/World_Wide_Web/Browsers/Mosaic/">Mosaic/X,</a>\r
+<a name ="grail" href="http://monty.cnri.reston.va.us/grail-0.3/">Grail,</a>\r
+and\r
+W3O\r
+<a href="http://www.w3.org/pub/WWW/Arena/">Arena,</a>\r
+you can specify the proxy via environment variables\r
+before starting the application.\r
+This will probably be done with something like either\r
+<br>\r
+   <big><kbd>setenv http_proxy http://localhost:8000/</kbd></big>\r
+<br>\r
+or\r
+<br>\r
+   <big><kbd>http_proxy=http://junkbuster.fictitous-pro-privacy-isp.net:8000/ export http_proxy</kbd></big>\r
+<br>\r
+depending on your shell and where the\r
+Internet Junkbuster\r
+lives.\r
+</ul>\r
+If your browser is not listed here,\r
+or if you notice an error, please\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=set">tell us</a>\r
+the correct procedure.\r
+</p>\r
+\r
+<h3><a name="already" href="/cgi-bin/gp?pg=ijbfaq&pr=already"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+What should I do if I find another proxy is already configured?\r
+</h3>\r
+<p>\r
+Some\r
+<small>ISP</small>s\r
+and companies require all Web traffic to go through their proxy.\r
+In this case you would find your proxy configuration with values already set,\r
+possibly under\r
+<a name="Automatic">Automatic Proxy Configuration</a>\r
+(in the case of \r
+<a href="http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/proxy-live.html">Netscape</a>\r
+and\r
+<a href="http://ieak.microsoft.com/">MS-IE 3.0</a>\r
+and above).\r
+It's probably a firewall proxy between your company and the outside world,\r
+<a name="cache">or a</a>\r
+<a href="http://vancouver-webpages.com/CacheNow/">caching proxy</a>\r
+if you're using an \r
+<small>ISP</small>.\r
+<p>\r
+<a name="f">What needs to be done in this case is to</a>\r
+use the\r
+<a href="ijbman.html#forwardfile">forwardfile</a>\r
+option\r
+to tell the\r
+Internet Junkbuster\r
+the address of the other proxy.\r
+Specify a different (unused) port number\r
+with the\r
+<a href="ijbman.html#listen-address">listen-address</a>\r
+option,\r
+and configure your browser to\r
+<a href="ijbfaq.html#chain">use that port.</a>\r
+If you haven't done this kind of thing before,\r
+it's probably best to consult your systems administrator or \r
+<small>ISP</small>\r
+about it;\r
+check their web page first.\r
+</p>\r
+\r
+<h3><a name="discontinue" href="/cgi-bin/gp?pg=ijbfaq&pr=discontinue"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+What if I want to stop using the Internet Junkbuster?\r
+</h3>\r
+<p>\r
+Just go through the same procedure you used to start your\r
+browser using the\r
+Internet Junkbuster,\r
+but remove the details you put in\r
+(or if there was something there before, restore it).\r
+You may need to use\r
+<b><font face="arial, helvetica">\r
+Save Options</font></b>\r
+to make this change permanent.\r
+On Netscape 3.0 you can go through\r
+<b><font face="arial, helvetica">\r
+Options</font></b>;\r
+<b><font face="arial, helvetica">\r
+Network Preferences</font></b>;\r
+<b><font face="arial, helvetica">\r
+Proxies</font></b>\r
+and click on\r
+<b><font face="arial, helvetica">\r
+No Proxy</font></b>\r
+to turn it off, and later click on\r
+<b><font face="arial, helvetica">\r
+Manual Proxy Configuration</font></b>\r
+if you want to start using it again.\r
+(No need to enter the again details under\r
+<b><font face="arial, helvetica">\r
+View</font></b>\r
+as you did the\r
+<a href="ijbfaq.html#netscape">first time;</a>\r
+they should remain there unchanged.)\r
+<p>\r
+<a name="shut">This stops your browser talking to the proxy;</a>\r
+<a href="ijbfaq.html#shutdown">shutting down the proxy</a>\r
+is a different matter.\r
+</p>\r
+\r
+<h3><a name="dial" href="/cgi-bin/gp?pg=ijbfaq&pr=dial"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Automatic dialing isn't working any more. How do I fix it?\r
+</h3>\r
+<p>\r
+Some browsers (such as MSIE-4) can be configured to dial your\r
+<small>ISP</small>\r
+automatically when you click on a link,\r
+but this feature gets disabled if you specify a proxy running on your\r
+own computer\r
+(with address\r
+<big><kbd>localhost</kbd></big>\r
+or\r
+<big><kbd>127.0.0.1</kbd></big>)\r
+because these addresses don't require dialing.\r
+The\r
+Internet Junkbuster\r
+knows nothing about dialing, so it doesn't work.\r
+To make automatic dialing work,\r
+make up a name such as\r
+<big><kbd>junkbuster.ijb</kbd></big>\r
+and use that name in the proxy settings\r
+instead of\r
+<big><kbd>localhost</kbd></big>,\r
+and then add the line\r
+<big><kbd>127.0.0.1 junkbuster.ijb</kbd></big>\r
+to the file\r
+<big><kbd>c:\windows\hosts</kbd></big>\r
+(if there already is a line beginning with\r
+<big><kbd>127.0.0.1</kbd></big>\r
+just add\r
+<big><kbd>junkbuster.ijb</kbd></big>\r
+at the end of it.)\r
+<p>\r
+<a name="also">This should also work Netscape Communicator 4 on</a>\r
+machines where IE-4 has been installed.\r
+</p>\r
+<p align="center"><a href="#top_of_page"><img border=0 width=250 height=15 src="/images/top.gif" alt="--- Back to Top of Page ---"></a></p>\r
+<br>\r
+<center>\r
+<h2><a name="local"><font face="arial, helvetica">\r
+Setting up the Internet Junkbuster on your local computer\r
+</font></a>\r
+</h2>\r
+</center>\r
+<br>The next two sections assume you wish to compile the code\r
+with your own C compiler.\r
+<a name="install">If you just want to use the</a>\r
+<big><kbd>.exe</kbd></big>\r
+file provided for Windows,\r
+see the\r
+<a href="ijbwin.html">Windows Installation page.</a>\r
+\r
+<h3><a name="u" href="/cgi-bin/gp?pg=ijbfaq&pr=u"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How do I compile the code under Unix?\r
+</h3>\r
+<p>\r
+If you are running Redhat\r
+<a href="aboutus.html#linux">Linux</a>\r
+you may prefer to use the\r
+<a href="ijbdist.html#red">rpm</a>\r
+instead of the following procedure.\r
+<br><ol type="1">\r
+<li>\r
+<a name="download">First</a>\r
+<a href="ijb20.tar.Z">download the tar file</a>\r
+(~286k)\r
+<a name="tar">and</a>\r
+uncompress and extract the files from it with this command\r
+<br>\r
+   <big><kbd>uncompress -c ijb20.tar.Z | tar xf -</kbd></big>\r
+<p>\r
+<li>\r
+<a name="sun">If your operating system is from</a>\r
+<a href="legal.html#not_our_trademark">Sun</a>\r
+or\r
+<a href="legal.html#not_our_trademark">HP</a>\r
+examine the\r
+<big><kbd>Makefile</kbd></big>\r
+and make any changes indicated inside.\r
+<li>\r
+<a name="make">Run</a>\r
+<br>\r
+<br>\r
+   <big><kbd>make</kbd></big>\r
+<p>\r
+<li>\r
+<a name="defaults">Copy the sample configuration file</a>\r
+(<big><kbd>junkbstr.ini</kbd></big>,\r
+previously called\r
+<big><kbd>sconfig.txt</kbd></big>\r
+and other names in earlier releases)\r
+to some convenient place such as\r
+<big><kbd>/usr/local/lib/junkbuster/configfile</kbd></big>\r
+or whatever you choose.\r
+The sample file has all the options commented out.\r
+You can remove the\r
+<big><kbd>#</kbd></big>\r
+character on any that you want, but it may be better to\r
+leave this until to later.\r
+Run it asynchronously:\r
+<br>\r
+<br>\r
+   <big><kbd>junkbuster configfile &</kbd></big>\r
+<p>\r
+If you are running a version earlier than 2.0 you can start it with\r
+<big><kbd>junkbuster &</kbd></big>\r
+<p>\r
+<li>\r
+<a name="config">Configure your browser (described</a>\r
+<a href="ijbfaq.html#browser">above).</a>\r
+<li>\r
+<a name="test">Verify that the</a>\r
+Internet Junkbuster\r
+is working (described\r
+<a href="ijbfaq.html#show">above).</a>\r
+<li>\r
+<a name="restart">Decide on the options you really want,</a>\r
+<big><kbd>kill</kbd></big>\r
+the\r
+<a href="ijbfaq.html#pid">process</a>\r
+and start it again. The most popular option is\r
+<a href="ijbman.html#blockfile">blockfile</a>\r
+to block ads.\r
+<a name="comprehensive">A sample blockfile is provided as an illustration,</a>\r
+but it doesn't really stop many ads.\r
+More comprehensive ones are available\r
+<a href="ijbfaq.html#readymade">elsewhere</a>.\r
+<li>\r
+<a name="rc">You'll probably want to add an entry to</a>\r
+<big><kbd>/etc/rc.d/rc.local</kbd></big>\r
+or equivalent to start it at boot time.\r
+(Any output you specify should be redirected to a file.\r
+And don't forget the\r
+&\r
+at the end to run it asynchronously or your system will seize\r
+up after the next reboot.)\r
+</ol>\r
+</p>\r
+\r
+<h3><a name="win" href="/cgi-bin/gp?pg=ijbfaq&pr=win"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How do I compile the code under Windows?\r
+</h3>\r
+<p>\r
+A binary is currently being supplied with the source code,\r
+but if you prefer to compile it yourself here is the likely procedure.\r
+Most of these steps are repeated in our checklist for\r
+<a href="ijbwin.html">installation under Windows.</a>\r
+<br><ol type="1">\r
+<li>\r
+<a name="zip">First</a>\r
+<a href="ijb20.zip">click here to download the zip file</a>\r
+called\r
+<big><kbd>ijb20.zip</kbd></big>\r
+(~208k),\r
+then uncompress and unpack the zip archive using a tool like\r
+<a href="http://www.winzip.com/">WinZip</a>.\r
+<li>\r
+<a name="change">Now the distribution (source and sample files)</a>\r
+will be in a folder\r
+called\r
+<big><kbd>ijb20</kbd></big>.\r
+Go into that folder and then edit the Makefile for\r
+your system,\r
+removing the comment character\r
+(<big><kbd>#</kbd></big>)\r
+in the lines related to Win32.\r
+Then type:\r
+<br>\r
+   <big><kbd>nmake</kbd></big>\r
+<br>\r
+This should create an executable called\r
+<big><kbd>junkbstr.exe</kbd></big>.\r
+<a name="compilers">For information on issues with various compilers, see the</a>\r
+<a href="ijbdist.html#compilers">Distribution Information</a>\r
+page.\r
+<li>\r
+<a name="attempt">Run the executable with the command:</a>\r
+<br>\r
+   <big><kbd>junkbstr</kbd></big>\r
+<br>\r
+The program will produce a message\r
+indicating that it has started and is ready to serve.\r
+<p>\r
+<a name="ini">(Version 2.0.1 and above uses</a>\r
+the file\r
+<big><kbd>junkbstr.ini</kbd></big>\r
+as the config file\r
+if it exists and no argument was given. If you have an earlier\r
+version or if you want it to use a different config file,\r
+simply specify that file as the argument.)\r
+<li>\r
+<a name="configures">Configure your browser (described</a>\r
+<a href="ijbfaq.html#browser">above).</a>\r
+<li>\r
+<a name="work">Check the proxy is working (described</a>\r
+<a href="ijbfaq.html#check">below</a>).\r
+<li>\r
+<a name="shortcut">To have the proxy start itself automatically</a>\r
+when you login to Win95,\r
+drop the ``shortcut'' to the\r
+<big><kbd>junkbstr</kbd></big>\r
+executable into the StartUp folder:\r
+<br>\r
+   <big><kbd>C:\Windows\Start Menu\Programs\StartUp</kbd></big>\r
+<br>\r
+You might want to change the shortcut's\r
+<big><kbd>Properties->Shortcut</kbd></big>\r
+to\r
+<big><kbd>Run: Minimized</kbd></big>.\r
+If you specify the\r
+<a href="ijbman.html#hide-console">hide-console</a>\r
+option then the\r
+<small>DOS</small>\r
+window will vanish after it starts.\r
+<p>\r
+<a name="NT">WinNT users can put it into their own</a>\r
+StartUp folders or the Administrator\r
+can put it into the system's global StartUp folder.\r
+For details on how to make this a service under NT\r
+see our\r
+<a href="ijbwin.html#service">Windows page</a>.\r
+</ol>\r
+</p>\r
+\r
+<h3><a name="check" href="/cgi-bin/gp?pg=ijbfaq&pr=check"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How do I check that the proxy is working?\r
+</h3>\r
+<p>\r
+Pick a page from somewhere (such as your bookmarks, or just one\r
+that your browser was pointing to)\r
+and\r
+<b><font face="arial, helvetica">\r
+Reload</font></b>\r
+it.\r
+If you get a message along the lines of ``server not responding,\r
+using cached copy instead,'' see the advice\r
+<a href="ijbfaq.html#responding">above.</a>\r
+If the page reloads OK, check that your browser is actually\r
+talking to the proxy by going to\r
+<a href="http://internet.junkbuster.com/cgi-bin/show-proxy-args">http://internet.junkbuster.com/cgi-bin/show-proxy-args</a>\r
+or any\r
+<small>URL</small>\r
+ending in\r
+<big><kbd>show-proxy-args</kbd></big>\r
+(as described\r
+<a href="ijbfaq.html#show">below</a>,\r
+the proxy should intercept the request.)\r
+When you see ``Internet Junkbuster Proxy Status,''\r
+you'll know it's working.\r
+</p>\r
+\r
+<h3><a name="chain" href="/cgi-bin/gp?pg=ijbfaq&pr=chain"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How and why would I have this proxy chained with other proxies?\r
+</h3>\r
+<p>\r
+You may need the \r
+<a href="ijbman.html#forwardfile">forwarding</a>\r
+feature to ``daisy chain'' the\r
+Internet Junkbuster\r
+to another proxy, perhaps an\r
+<a href="ijbfaq.html#anonymizing">anonymizing</a>\r
+proxy to\r
+<a href="ijbfaq.html#conceal">conceal</a>\r
+your\r
+<small>IP</small>\r
+address,\r
+or a\r
+<a href="ijbfaq.html#cache">caching proxy</a>\r
+from your\r
+<small>ISP</small>,\r
+or a\r
+<a href="ijbfaq.html#firewall">firewall</a>\r
+proxy between your company and the outside world.\r
+Version 2.0\r
+can be even configured to forward\r
+<a href="ijbman.html#forwardfile">selectively</a>\r
+according to the\r
+<small>URL</small>\r
+requested:\r
+for example, connecting directly to trusted hosts,\r
+but going through an anonymizing or firewall proxy for all other hosts.\r
+<p>\r
+<a name="administrator">Network administrators might use it to provide</a>\r
+transparent access to multiple networks without\r
+modifying browser configurations.\r
+<a name="direct">Most browsers also provide a way of</a>\r
+specifying hosts that the browser\r
+connects to directly, bypassing the proxy. Some provide a method for\r
+<a href="ijbfaq.html#Automatic">Automatic Proxy Configuration.</a>\r
+A well written\r
+Internet Junkbuster\r
+configuration can be much more flexible and powerful.\r
+<p>\r
+<a name="example">An</a>\r
+<small>ISP</small>'s\r
+caching proxy\r
+would typically be called something like\r
+<big><kbd>cache.your-isp.net:8080</kbd></big>\r
+(as described on you\r
+<small>ISP</small>'s\r
+web page);\r
+you would put this information in your\r
+<a href="ijbman.html#forwardfile">forwardfile</a>\r
+as described in our manual.\r
+Your browser would be configured to\r
+the\r
+Internet Junkbuster\r
+for\r
+<small>HTTP</small>\r
+and Security Proxies as before,\r
+but you probably want to tell it to use the caching proxy\r
+for\r
+<small>FTP</small>\r
+and other protocols.\r
+<a name="nonlocal">If your</a>\r
+<small>ISP</small>\r
+is running\r
+the\r
+Internet Junkbuster\r
+for you,\r
+they have probably already decided whether to chain with a caching proxy.\r
+</p>\r
+\r
+<h3><a name="socks" href="/cgi-bin/gp?pg=ijbfaq&pr=socks"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How does the Internet Junkbuster work with SOCKS gateways?\r
+</h3>\r
+<p>\r
+There is support for some\r
+<a href="http://www.leverage.com/users/tlod/ssockd/ssockd.html">gateways</a>\r
+in\r
+Version <a href="ijbdist.html#c4">1.4</a>\r
+and above.\r
+The gateway protocol used to be specified on the command line;\r
+it is\r
+now specified\r
+in the same file as\r
+<a href="ijbman.html#forwardfile">forwarding.</a>\r
+Note that the browser's proxy configuration must\r
+<em>not</em>\r
+specify a\r
+<big><kbd>SOCKS</kbd></big>\r
+host;\r
+it should specify the proxy as described\r
+<a href="ijbfaq.html#set">above.</a>\r
+</p>\r
+\r
+<h3><a name="plain" href="/cgi-bin/gp?pg=ijbfaq&pr=plain"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How do I configure it to be just a plain old proxy?\r
+</h3>\r
+<p>\r
+To get the proxy to do as little as possible (which means not deleting any\r
+sensitive headers), place in your\r
+configuration file the following three lines (each ending in a space\r
+then a period) to stop it changing sensitive headers:\r
+<br>\r
+   <big><kbd>referer .</kbd></big>\r
+<br>\r
+   <big><kbd>from .</kbd></big>\r
+<br>\r
+   <big><kbd>user-agent .</kbd></big>\r
+<br>\r
+   <big><kbd>cookiefile mycookiefile</kbd></big>\r
+<br>\r
+The fourth line is also needed to specify a\r
+<a href="ijbman.html#o_c">cookiefile</a>\r
+that might be called\r
+<big><kbd>mycookiefile</kbd></big>\r
+containing a single line with a\r
+<big><kbd>*</kbd></big>\r
+character, to allow all cookies through.\r
+</p>\r
+\r
+<h3><a name="shutdown" href="/cgi-bin/gp?pg=ijbfaq&pr=shutdown"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How do I shut down the proxy (to restart it)?\r
+</h3>\r
+<p>\r
+It depends on your platform. Under Windows, use\r
+<b><font face="arial, helvetica">\r
+Ctrl-Break</font></b>\r
+in the \r
+<small>DOS</small>\r
+window or\r
+the old three-fingered salute of\r
+<b><font face="arial, helvetica">\r
+Ctrl-Alt-Delete</font></b>\r
+and select\r
+<b><font face="arial, helvetica">\r
+End Task</font></b>.\r
+Under\r
+<small>UNIX <a href="legal.html#not_our_trademark">®</a></small>\r
+you'll need to\r
+<big><kbd>kill</kbd></big>\r
+the\r
+<b><kbd>junkbuster</kbd></b>\r
+process.\r
+<a name="pid">If you don't know the process number to give to</a>\r
+<big><kbd>kill</kbd></big>, try this:\r
+<big><kbd>ps ax | grep junkbuster</kbd></big>\r
+<br>\r
+</p>\r
+<p align="center"><a href="#top_of_page"><img border=0 width=250 height=15 src="/images/top.gif" alt="--- Back to Top of Page ---"></a></p>\r
+<br>\r
+<center>\r
+<h2><a name="companies"><font face="arial, helvetica">\r
+Information for companies\r
+</font></a>\r
+</h2>\r
+</center>\r
+<br>\r
+<h3><a name="think" href="/cgi-bin/gp?pg=ijbfaq&pr=think"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+What do advertising companies think of this kind of technology?\r
+</h3>\r
+<p>\r
+We've seen only a few public comments from the advertising industry on this,\r
+other than\r
+<a href="links.html#adverse">SEC filings.</a>\r
+First, the president of the Internet Advertising Bureau told\r
+<a href="new.html#Rich">CNET</a>\r
+that he wasn't worried by banner blockers.\r
+Second, after the Federal Trade Commission's\r
+<a href="ftc.html">workshop</a>\r
+where we gave a live demonstration of our proxy before\r
+many eminent representatives of the industry,\r
+the\r
+<a href="self.html#dma">Direct Marketing Association</a>\r
+made the following\r
+statement in the closing paragraphs\r
+of their\r
+<a href="http://www.ftc.gov/bcp/privacy/wkshp97/comments2/dma027a.htm">summary comments</a>\r
+to the Commission.\r
+<blockquote>\r
+Clever shareware developers have come up with products that\r
+can obliterate cookies and advertisements for those consumers\r
+who have these concerns.\r
+The Internet is a market that is so democratic and flexible\r
+that it is easy for companies and software\r
+developers to respond to a perceived market need. \r
+</blockquote>\r
+Their attitude seems to be that they would prefer that\r
+people use technical solutions\r
+to protect their privacy than have protections\r
+imposed by legislation or government regulations.\r
+So, do you perceive a market need?\r
+Then here are some ways to flex your democratic muscles.\r
+</p>\r
+\r
+<h3><a name="nobrainer" href="/cgi-bin/gp?pg=ijbfaq&pr=nobrainer"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Should we provide the Internet Junkbuster for our employees?\r
+</h3>\r
+<p>\r
+That depends. Try this quick three-point test.\r
+<br><ol type="1">\r
+<li>\r
+<a name="waste">Do you want to spend your communications budget</a>\r
+on bandwidth that wastes your employees' time by forcing them to wait\r
+for a lot of annoying distractions while they're trying to\r
+do their jobs?\r
+<li>\r
+<a name="surveillance">Do you want current and potential vendors</a>\r
+to know quantitative details about the\r
+<a href="ijbfaq.html#agent">software and hardware platforms</a>\r
+that you have?\r
+<li>\r
+<a name="intelligence">Do you want your competitors to be able to</a>\r
+<a href="cookies.html">track</a>\r
+exactly which of your\r
+employees are checking out their web sites?\r
+</ol>\r
+If the answer to all three questions is yes,\r
+then you probably don't have any need for this kind of product.\r
+</p>\r
+\r
+<h3><a name="commercial" href="/cgi-bin/gp?pg=ijbfaq&pr=commercial"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Can our company get commercial support for the software?\r
+</h3>\r
+<p>\r
+Yes,\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=commercial">ask us</a>\r
+for a quote on a maintenance contract with your choice of\r
+phone and email support,\r
+hard copy documentation,\r
+source code and pre-compiled binaries on tape or disk,\r
+and email alerting of upgrades and issues.\r
+We also offer consulting services to help set up ``stealth browsing''\r
+capabilities to help reduce the footprints left while doing competitive\r
+analysis and other Web work where confidentiality is critical.\r
+</p>\r
+\r
+<h3><a name="isps" href="/cgi-bin/gp?pg=ijbfaq&pr=isps"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+I run an ISP. What issues should I consider before offering it?\r
+</h3>\r
+<p>\r
+Many\r
+<small>ISP</small>s\r
+who offer the proxy to their customers have told us that\r
+most of their customers are \r
+delighted with it\r
+(although one reported that a customer complaint that without banner ads,\r
+surfing was like reading a novel: we recommend making it optional).\r
+Many\r
+<small>ISP</small>s\r
+like it because it reduces bandwidth requirements.\r
+To help get you started,\r
+here's a checklist we've developed from working with a few\r
+<small>ISP</small>s.\r
+You may think of more,\r
+and we'd be interested if you're willing to\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=isps">share them</a>\r
+with us.\r
+<br><ol type="1">\r
+<li>\r
+<a name="pending">If you get more than one request for</a>\r
+the\r
+Internet Junkbuster\r
+you may want to tell your customers on your News page that you\r
+<a href="ijbfaq.html#isp">already</a>\r
+know about it and are assessing it.\r
+<li>\r
+<a name="try">Try the software and</a>\r
+<a href="ijbfaq.html#install">verify</a>\r
+that it performs satisfactorily.\r
+<li>\r
+<a name="value">Determine whether your customers perceive the service as</a>\r
+<a href="ijbfaq.html#switch">valuable</a>\r
+(and therefore worth the time to set up).\r
+We've had reports of many delighted customers.\r
+<li>\r
+<a name="secure">Assess the</a>\r
+level of\r
+<a href="ijbfaq.html#others">security</a>\r
+associated with the software.\r
+If access is to be\r
+<a href="ijbfaq.html#restrict">restricted</a>\r
+(to just dial-in ports, for example)\r
+how is this to be done?\r
+<li>\r
+<a name="costs">Consider</a>\r
+whether to expect any additional load on computing resources required,\r
+and any change in use of bandwidth due to the blocking of large\r
+<small>GIF</small>s.\r
+<li>\r
+<a name="opt">Choose the</a>\r
+<a href="ijbman.html">options</a>\r
+you wish to provide.\r
+<li>\r
+<a name="multiple">Decide whether you want</a>\r
+to offer a choice of configurations, such some of these four.\r
+<br><ol type="A">\r
+<li>\r
+<a name="banner">Banners</a>\r
+<a href="ijbfaq.html#blocking">Blocked,</a>\r
+Wafer with\r
+<a href="ijbfaq.html#notice">No-Cookie-Copyright</a>\r
+notice\r
+<li>\r
+<a name="low">Cookies</a>\r
+not stopped\r
+(<a href="ijbman.html#cookiefile">cookiefile</a>\r
+with just a\r
+<big><kbd>*</kbd></big>\r
+in it),\r
+<a href="ijbfaq.html#header">User Agent</a>\r
+specified as\r
+<a href="ijbfaq.html#lynx">Lynx</a>\r
+<li>\r
+<a name="oneway">Cookies from browser</a>\r
+<a href="ijbfaq.html#one">allowed</a>,\r
+permitting\r
+<a href="ijbfaq.html#registration">registered services</a>\r
+<li>\r
+<a name="kid">A proxy for</a>\r
+<a href="ijbfaq.html#children">kids.</a>\r
+</ol>\r
+<a name="caching">If you run a</a>\r
+<a href="ijbfaq.html#chain">caching proxy,</a>\r
+decide whether the \r
+Internet Junkbuster\r
+will chain with it by default,\r
+and whether to offer an alternate with no caching.\r
+(Some\r
+<small>ISP</small>s\r
+don't, because they want to give customers an incentive to use caching\r
+and save bandwidth.)\r
+<li>\r
+<a name="naming">Decide on a naming scheme for your</a>\r
+proxies.\r
+If you're running only one\r
+proxy on one machine,\r
+the simplest way is to just use port 8000 on your main machine,\r
+such as\r
+<big><kbd>our-isp.net.</kbd></big>\r
+But it would probably be safer to put an entry in your name server\r
+and call it something like\r
+<big><kbd>junkbuster.our-isp.net.</kbd></big>\r
+If running several proxies, you could either use different ports\r
+on the same machine, or if you have\r
+the opportunity to distribute the load over\r
+a few machines \r
+you could\r
+use different hostname aliases such as\r
+<big><kbd>banner.junkbuster.our-isp.net</kbd></big>,\r
+<big><kbd>lynx.junkbuster.our-isp.net</kbd></big>\r
+and\r
+<big><kbd>oneway.junkbuster.our-isp.net</kbd></big>\r
+(corresponding to the examples in the previous point).\r
+You may want to set up\r
+<a href="ijbfaq.html#Automatic">Automatic Proxy Configuration.</a>\r
+<li>\r
+<a name="document">Prepare a page</a>\r
+explaining the\r
+Internet Junkbuster\r
+to your customers.\r
+<a name="does">Here's are some examples from</a>\r
+<a href="http://www.cia.com.au/us/help/faq-proxy.html">Australia</a>,\r
+<a href="http://www.rhein-ruhr.de/info/junkbuster.html">Germany</a>,\r
+<a href="http://www.packet.net/ijb/">Florida</a>,\r
+<a href="http://www.eclipse.net/adfilter/index.html">New York/New Jersey/Pennsylvania,</a>\r
+<a href="http://a-o.com/proxy/proxy.html">North Carolina</a>,\r
+<a href="http://www.trip.net/junkbuster/">Texas</a>,\r
+and\r
+<a href="http://www.inconnect.com/proxy.html">Utah</a>.\r
+<a name="reuse">You are welcome to copy and modify</a>\r
+material\r
+from\r
+Junkbusters\r
+according to the\r
+<a href="gpl.html">GPL</a>.\r
+You might want to set up a process to check this page periodically\r
+and update it when it changes.\r
+(A few links can probably serve as well as lot of copying however.)\r
+A typical page would probably specify the following.\r
+<br><ul type="1">\r
+<li>\r
+<a name="abstract">A brief explanation stating what</a>\r
+the\r
+Internet Junkbuster\r
+does, with a link to this page.\r
+<li>\r
+<a name="addresses">The addresses of the proxy or proxies,</a>\r
+with their port number(s).\r
+<li>\r
+<a name="options">The options used,</a>\r
+and how to view the contents of the blockfile (which you can place on\r
+your web pages,\r
+preferably in a file called\r
+<big><kbd>blocklist.html</kbd></big>\r
+or\r
+<big><kbd>blocklist.txt</kbd></big>).\r
+<li>\r
+<a name="additions">An indication</a>\r
+of whether suggestions for the blocklist are considered,\r
+and if so, how to submit them: to a particular email address,\r
+via web-based form, etc.\r
+<li>\r
+<a name="configuration">Instructions</a>\r
+on how to\r
+configure a browser.\r
+You may want to include details for only the two major browsers\r
+and leave the others to a link.\r
+<li>\r
+<a name="service">Procedures on how to report problems, give feedback etc.</a>\r
+</ul>\r
+<li>\r
+<a name="beta">Invite a small number of technologically sophisticated</a>\r
+customers to beta-test the service.\r
+<li>\r
+<a name="announce">Announce general availability on your ``News'' page.</a>\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=isps">Tell us</a>\r
+if you would like to be included on a list of\r
+<small>ISP</small>s\r
+offering the\r
+Internet Junkbuster.\r
+</ol>\r
+</p>\r
+\r
+<h3><a name="ps2" href="/cgi-bin/gp?pg=ijbfaq&pr=ps2"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+What's a Proxy Server Server and how can I make money as one?\r
+</h3>\r
+<p>\r
+Other organizations with web presence and some bandwidth to spare\r
+can set up as\r
+<i><dfn>Proxy Server Servers</dfn></i>\r
+<!-- Aside: All this, and... -->\r
+(<small>PS<sup>2</sup></small>s).\r
+The idea here is to allow users to choose their proxy configuration,\r
+and provide it to them on a semi-permanent basis.\r
+Users would fill in a form specifying what options they want in\r
+their proxy,\r
+possibly even at a very high level, such as\r
+``no ads''\r
+or ``no nudity.''\r
+This information is sent to a\r
+<small>CGI</small>\r
+script that\r
+configures a proxy, starts it running, and returns its address and port number\r
+(possibly along with configuration instructions for the browser\r
+that the user specified.)\r
+<p>\r
+<a name="revenue">Users</a>\r
+could be charged\r
+a subscription fee,\r
+or the service could be thrown in free in the hope of\r
+improving customer retention for some existing business\r
+(which is what\r
+<small>ISP</small>s\r
+are doing).\r
+It might be possible to make money by\r
+inserting new ads in the holes left where others were blocked,\r
+but the original owners might object.\r
+<small>PS<sup>2</sup></small>s\r
+could differentiate themselves\r
+by providing frequently updated and comprehensive\r
+blocking of ads, or of offensive material based on their own grading system.\r
+Some content providers might do it for the chance to be the\r
+only company that the consumer permits to set cookies.\r
+(Identification could even be done via cookies,\r
+but this might not be popular with the kind of user who wants a proxy.)\r
+<small>PS<sup>2</sup></small>s\r
+might sell specific or aggregate information about their\r
+users' browsing habits,\r
+so the agreement with users on whether they are permitted to do this\r
+would be important to both sides.\r
+<p>\r
+<a name="publicize">If your organization</a>\r
+establishes a \r
+Proxy Server Service\r
+you would like publicized,\r
+please\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=publicize">notify us.</a>\r
+</p>\r
+<p align="center"><a href="#top_of_page"><img border=0 width=250 height=15 src="/images/top.gif" alt="--- Back to Top of Page ---"></a></p>\r
+<br>\r
+<center>\r
+<h2><a name="blocking"><font face="arial, helvetica">\r
+Blocking\r
+</font></a>\r
+</h2>\r
+</center>\r
+<br>\r
+<h3><a name="readymade" href="/cgi-bin/gp?pg=ijbfaq&pr=readymade"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Where can I get an example blockfile that stops most ads?\r
+</h3>\r
+<p>\r
+The sample blockfile we provide blocks almost nothing,\r
+and we do not publish blockfiles that stop almost all banner ads.\r
+But others have; you can find them by\r
+<a href="http://www.altavista.com/cgi-bin/query?pg=q&what=web&fmt=.&q=%2Bjunkbuster+%2Burl%3Ablocklist">asking Altavista.</a>\r
+You can add any part of the new file to your old one\r
+(probably called\r
+<big><kbd>sblock.ini</kbd></big>\r
+if you haven't changed the default name in the latest version)\r
+or your just replace it completely.\r
+You\r
+<a href="ijbfaq.html#cover">probably</a>\r
+don't need to restart the proxy.\r
+<p>\r
+<a name="pub">If you develop an interesting blocklist and publish it on the Web,</a>\r
+you might want to include the word ``junkbuster'' in it\r
+and use the word ``blocklist'' in the file name given in the\r
+<small>URL</small>\r
+so that others can find it with the query given in the previous sentence.\r
+</p>\r
+\r
+<h3><a name="zap" href="/cgi-bin/gp?pg=ijbfaq&pr=zap"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+If I see an ad I wish I hadn't, how do I stop it?\r
+</h3>\r
+<p>\r
+If your\r
+<small>ISP</small>\r
+is running the\r
+Internet Junkbuster,\r
+they should have a policy on whether they accept suggestions from\r
+their customers on what to block. Consult their web page.\r
+<p>\r
+<a name="cover">If you are running</a>\r
+the\r
+Internet Junkbuster\r
+yourself, you have complete control over what gets through.\r
+Just add a pattern to cover the offending \r
+<small>URL</small>\r
+to your blockfile.\r
+Version 1.3 and later automatically rereads the blockfile when it changes,\r
+but if you're running an earlier version you'll\r
+have to\r
+<a href="ijbfaq.html#shutdown">stop it</a>\r
+and restart it.\r
+<p>\r
+<a name="target">To choose a pattern you'll first need to find the</a>\r
+<small>URL</small>\r
+of the ad you want cover.\r
+<p>\r
+<a name="pinpoint">Some people use the</a>\r
+<a href="ijbman.html#debug">debug</a>\r
+<big><kbd>1</kbd></big>\r
+option to display each \r
+<small>URL</small>\r
+in a window as the request is sent to the server.\r
+It's then usually an easy task to pick the offending \r
+<small>URL</small>\r
+from the list of recent candidates.\r
+<p>\r
+<a name="source">Alternatively,</a>\r
+you can use\r
+<b><font face="arial, helvetica">\r
+View Document Info</font></b>\r
+(or\r
+<b><font face="arial, helvetica">\r
+View Document Source</font></b>\r
+if your browser doesn't have that).\r
+The\r
+<b><font face="arial, helvetica">\r
+Info</font></b>\r
+feature has the advantage of showing you the full\r
+<small>URL</small>\r
+including the host name,\r
+which may not be specified in the source:\r
+there you might see something like\r
+<big><kbd>SRC="/ads/click_here_or_die.gif"</kbd></big>\r
+indicating only the\r
+<i><dfn>path</dfn></i>.\r
+(The host name is assumed to be the same as the one the page came from.)\r
+<p>\r
+<a name="offsite">But ads often</a>\r
+come from a different site, in which case you\r
+might see something like\r
+<big><kbd>SRC="grabem.n.trackem.com/Ad/Infinitum/SpaceID=1666"</kbd></big>\r
+or longer.\r
+<a name="warehouse">If the company looks like a pure ad warehouse</a>\r
+(as in the last case),\r
+you may want to place just its domain name in the blockfile,\r
+which blocks all \r
+<small>URL</small>s\r
+from that site.\r
+<p>\r
+<a name="wanted">If the ad comes from a server</a>\r
+that you really want some content from,\r
+you can include enough of the path\r
+to avoid zapping stuff you might want.\r
+In the first example above,\r
+<big><kbd>/ads/</kbd></big>\r
+would seem to be enough.\r
+If you don't include the domain name,\r
+the pattern applies to all sites,\r
+so you don't want such patterns\r
+to be too general:\r
+for example\r
+<big><kbd>/ad</kbd></big>\r
+would block\r
+<big><kbd>/admin/salaries/</kbd></big>\r
+on your company's internal site.\r
+<p>\r
+<a name="image">To speed the blocking of images, some</a>\r
+<small>UNIX <a href="legal.html#not_our_trademark">®</a></small>\r
+users create a\r
+shell script called\r
+<big><kbd>Image:</kbd></big>\r
+containing a line such as\r
+<big><kbd>echo $1 | sed s/http:..// >> $HOME/lib/blockfile</kbd></big>\r
+that adds its argument to the user's blockfile.\r
+Once an offending image has been be found using\r
+<b><font face="arial, helvetica">\r
+View Document Info</font></b>\r
+it's easy to cut-and-paste the line (or part of it) into a shell window.\r
+The same script can be linked to a file called\r
+<big><kbd>Frame:</kbd></big>\r
+to dealing with framed documents,\r
+and\r
+<big><kbd>junkbuster:</kbd></big>\r
+to accept the output of the\r
+<a href="ijbman.html#debug">debug</a>\r
+option.\r
+<p>\r
+<a name="partial">When compiled without the</a>\r
+<i><dfn>regular expressions</dfn></i>\r
+option, the\r
+Internet Junkbuster\r
+uses only very simple (and fast) matching methods.\r
+The pattern\r
+<big><kbd>/banners</kbd></big>\r
+will not stop\r
+<big><kbd>/images/banners/huge.gif</kbd></big>\r
+getting through: you would have to include the pattern\r
+<big><kbd>/images/banners</kbd></big>\r
+or something that matches in full from the left.\r
+<a name="regex">So you can get what you want here,</a>\r
+the matcher understands\r
+<small>POSIX</small>\r
+regular expressions:\r
+you can use\r
+<big><kbd>/*.*/banners</kbd></big>\r
+to block\r
+and any\r
+<small>URL</small>\r
+containing\r
+<big><kbd>/banners</kbd></big>\r
+(even in the middle of the path).\r
+<a name="posix">(In Versions 1.1 through 1.4</a>\r
+they were an option at compile time;\r
+from Version 2.0 they have become the default.)\r
+Regular expressions give you\r
+<a href="http://theory.uwinnipeg.ca/localfiles/infofiles/gcc/rx_toc.html">many more features</a>\r
+than this,\r
+but if you're not already familiar with them you probably won't \r
+need to know anything beyond the\r
+<big><kbd>/*.*/</kbd></big>\r
+idiom.\r
+If you do, a\r
+<big><kbd>man egrep</kbd></big>\r
+is probably a good starting point).\r
+<p>\r
+<a name="slash">Don't forget the</a>\r
+<big><kbd>/</kbd></big>\r
+(slash)\r
+at the beginning of the path.\r
+If you leave it out the line will be interpreted as a domain name,\r
+so\r
+<big><kbd>ad</kbd></big>\r
+would block all sites from Andorra\r
+(since\r
+<big><kbd>.ad</kbd></big>\r
+is the two-letter\r
+<a href="reference.html#country">country code</a>\r
+for that principality).\r
+<p>\r
+<a name="detail">For a detailed technical description</a>\r
+of how pattern matching is done,\r
+see the\r
+<a href="ijbman.html#o_b">manual.</a>\r
+</p>\r
+\r
+<h3><a name="despite" href="/cgi-bin/gp?pg=ijbfaq&pr=despite"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How come this ad is still getting through anyway?\r
+</h3>\r
+<p>\r
+If the ad had been displayed before you included its\r
+<small>URL</small>\r
+in the blockfile,\r
+it will probably be held in cache for some time,\r
+so it will be displayed without the need for any request to the server.\r
+Using the\r
+<a href="ijbman.html#debug">debug</a>\r
+<big><kbd>1</kbd></big>\r
+option to show each\r
+<small>URL</small>\r
+as it is fetched is a good way to see exactly what is happening.\r
+<p>\r
+<a name="otherwise">If new items seem to be getting through,</a>\r
+check that you are\r
+<a href="ijbfaq.html#show">really running</a>\r
+the proxy with the right blockfile in the options.\r
+Check the blockfile for\r
+<a href="ijbfaq.html#exceptions">exceptions.</a>\r
+<p>\r
+<a name="java">Some sites may have different ways of inserting ads,</a>\r
+such as via\r
+<a href="cookies.html#java">Java.</a>\r
+If you have ideas on how to block new kinds\r
+of junk not currently covered, please\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=java">tell us.</a>\r
+</p>\r
+\r
+<h3><a name="exceptions" href="/cgi-bin/gp?pg=ijbfaq&pr=exceptions"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How do I stop it blocking a URL that I actually want?\r
+</h3>\r
+<p>\r
+You can change the patterns so they don't cover it,\r
+or use a simple feature in Version 1.1 and later: a line beginning with a\r
+<big><kbd>~</kbd></big>\r
+character means that a\r
+<small>URL</small>\r
+blocked by previous patterns that matches the rest of\r
+the line is let through.\r
+For example,\r
+the pattern\r
+<big><kbd>/ad</kbd></big>\r
+would block\r
+<big><kbd>/addasite.html</kbd></big>\r
+but not if followed by\r
+<big><kbd>~/addasite</kbd></big>\r
+in the blockfile.\r
+Or suppose you want to see everything that comes from\r
+a site you like, even if it looks like an ad: simply put\r
+<big><kbd>~aSiteYouLike.com</kbd></big>\r
+at the\r
+<em>end</em>\r
+of the blockfile.\r
+(Order is important, because the last matching line wins.)\r
+<p>\r
+<a name="agreed">As well as unblocking</a>\r
+pages that were unintentionally blocked,\r
+this feature is useful for unblocking ads from a specific source.\r
+This might be because you are interested in those particular ones,\r
+or if you have an explicit agreement to accept certain ads,\r
+such as those from a free web-based email provider.\r
+</p>\r
+\r
+<h3><a name="children" href="/cgi-bin/gp?pg=ijbfaq&pr=children"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Can I block sites I don't want my children to see?\r
+</h3>\r
+<p>\r
+Yes, but remember that\r
+<a name="savvy">children who are technically sophisticated enough</a>\r
+to use the browsers' proxy configuration options\r
+could of course bypass any proxy.\r
+This kind of technology can be used as a gentle barrier to remind\r
+or guide the child,\r
+but nobody should expect it to replace the parent's role\r
+in setting and enforcing standards of online behavior for their children.\r
+<p>\r
+<a name="recommend">Some</a>\r
+<small>ISP</small>s\r
+are starting to provide specialized proxies to protect children.\r
+There are two basic approaches: the ``black list'' and the ``white list''\r
+approach.\r
+<a name="negative">The black list approach allows the child</a>\r
+to go anywhere not explicitly prohibited; the white list permits visits\r
+only to sites explicitly designated as acceptable.\r
+<p>\r
+<a name="positive">It's very easy for</a>\r
+anyone to\r
+compile a white list from a page of ``recommended\r
+kids sites'' and to configure an\r
+Internet Junkbuster\r
+to allow access to those sites only.\r
+If you compile with the\r
+<a href="ijbfaq.html#regex">regex</a>\r
+option,\r
+you can place a\r
+<big><kbd>*</kbd></big>\r
+(asterisk) as the first line of the blockfile (which blocks everything),\r
+and then list\r
+<a href="ijbfaq.html#exceptions">exceptions</a>\r
+after that.\r
+Be careful to make the exception sufficiently broad:\r
+for example, using\r
+<big><kbd>~www.uexpress.com/ups/comics/ch/</kbd></big>\r
+as the exception for\r
+<a href="http://www.uexpress.com/ups/comics/ch/"><cite>Calvin and Hobbes</cite></a>\r
+would block some of the graphic elements on the page;\r
+you would probably want a wider exception such as\r
+<big><kbd>~www.uexpress.com/ups/</kbd></big>\r
+to permit them.\r
+<p>\r
+<a name="trust">Version 2.0 has an experimental feature</a>\r
+to permit only sites mentioned in a nominated\r
+<a href="ijbman.html#trustfile">trusted site.</a>\r
+This allows organizations to build lists of sites for kids to browse,\r
+and the software automatically restricts access to those on the list.\r
+<p>\r
+<a name="scan">Many filtering</a>\r
+<a href="links.html#blocking">products</a>\r
+actually scan for keywords in\r
+the text of pages they retrieve\r
+before presenting it,\r
+but\r
+the\r
+Internet Junkbuster\r
+does not do this.\r
+Building a perfectly reliable black list system is hard,\r
+because it's very difficult to state\r
+in advance\r
+exactly\r
+what is obscene or unsuitable.\r
+For more info see our\r
+<a href="links.html#parents">links</a>\r
+page.\r
+</p>\r
+\r
+<h3><a name="message" href="/cgi-bin/gp?pg=ijbfaq&pr=message"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+What do I see when a page or graphic is blocked by the proxy?\r
+</h3>\r
+<p>\r
+You usually see a broken image icon,\r
+but it depends on several factors beyond the proxy's control.\r
+If asked for a\r
+<small>URL</small>\r
+matching its blockfile, the proxy returns an\r
+<small>HTML</small>\r
+page containing a message identifying itself\r
+(currently the two words ``Internet Junkbuster'')\r
+with a status 202 (Accepted) instead of the usual 200 (OK).\r
+(Versions 1.X returned an error 404: Forbidden, which caused\r
+strange behavior in some cases.)\r
+Status 202 is described in the\r
+<small>HTTP</small>\r
+<a href="http://www.ics.uci.edu/pub/ietf/http/rfc1945.html#Code202">RFC</a>\r
+as indicating that the request has been accepted but not completed,\r
+and that it might complete successfully in the future\r
+(in our case, if the blockfile were changed).\r
+<p>\r
+<a name="depends">The broken image icon is most common</a>\r
+because the browser is usually expecting a graphic.\r
+But if it was expecting text, or if the page happens to be using certain\r
+<small>HTML</small>\r
+extensions\r
+such as\r
+<big><kbd>layer</kbd></big>\r
+and your browser is a late model from Microsoft,\r
+you may see the words ``Internet Junkbuster'' displayed as a hot link.\r
+<p>\r
+<a name="click">Clicking on the link takes you to an explanation of</a>\r
+the pattern in the blockfile that caused the block,\r
+so that you can edit the blockfile and go back and reload if you really\r
+want to see what was blocked. The explanatory link is generated by\r
+the proxy and is automatically intercepted based on its ending in\r
+<big><kbd>ij-blocked-url</kbd></big>;\r
+even though the site is specified as\r
+<big><kbd>http://internet.junkbuster.com</kbd></big>\r
+no request should actually made to that site.\r
+If one is, it means that the proxy was been removed after it\r
+generated the link.\r
+<p>\r
+<a name="layer">To summarize:</a>\r
+the identifying link to the blocking explanation\r
+is usually turned into a broken image icon,\r
+but it may be displayed on a page alone,\r
+or they may may be restricted to the particular frame, layer or graphic area\r
+specified in the page containing them.\r
+The proxy has no way of knowing the context in which a\r
+<small>URL</small>\r
+will be used and cannot control how the blocking message will be rendered.\r
+</p>\r
+\r
+<h3><a name="broken" href="/cgi-bin/gp?pg=ijbfaq&pr=broken"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Why not replace blocked banners with something invisible?\r
+</h3>\r
+<p>\r
+<a name="infringe">Many users have suggested to us</a>\r
+that blocked banners should be replaced by a something like a\r
+1x1 transparent\r
+<small>GIF</small>\r
+to make the page would look as if there was nothing ever there.\r
+Apart from making it harder to catch unintended blocking,\r
+this might also displease the owners of the page,\r
+who could argue that such a change constitutes a copyright infringement.\r
+We think that merely failing to allow an included graphic to be accessed\r
+would probably not be considered an infringement:\r
+after all this is what happens when a browser\r
+is configured not to load images automatically.\r
+However, we are\r
+<a href="over.html#notlaw">not</a>\r
+lawyers,\r
+so anyone in doubt should take appropriate advice.\r
+<p>\r
+<a name="done">In a context where the copyright issue is resolved</a>\r
+satisfactorily,\r
+a proxy could simply return a status 301 or 302 and\r
+specify a replacement\r
+<small>URL</small>\r
+in a\r
+<big><kbd>Location</kbd></big>\r
+and/or\r
+<big><kbd>URI</kbd></big>\r
+header.\r
+An alternative would be to use inline code to return a\r
+1 x 1 clear\r
+<small>GIF</small>.\r
+We do not publish sample code for this,\r
+and we have no way of stopping\r
+<a href="ijbdist.html#others">others</a>\r
+who have.\r
+</p>\r
+\r
+<h3><a name="size" href="/cgi-bin/gp?pg=ijbfaq&pr=size"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Why not block banners based on the dimensions of the image?\r
+</h3>\r
+<p>\r
+Many users have pointed out that most banner ads come in standard sizes,\r
+so why not block all\r
+<small>GIF</small>s\r
+of those sizes?\r
+This would theoretically be without fetching the object \r
+because the dimensions are usually given in the\r
+<big><kbd>IMG</kbd></big>\r
+tag,\r
+but it would require substantial changes in the code,\r
+and we doubt whether it would be much more effective than a good block list.\r
+</p>\r
+\r
+<h3><a name="embedded" href="/cgi-bin/gp?pg=ijbfaq&pr=embedded"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+What about non-graphic advertising within the pages I want?\r
+</h3>\r
+<p>\r
+The\r
+Internet Junkbuster\r
+deliberately\r
+does not provide a way of automatically editing the contents of a page,\r
+to remove textual advertising or\r
+to repair the holes left by blocked banners.\r
+Other packages such as\r
+<a href="links.html#webfilter">WebFilter</a>\r
+do.\r
+<p>\r
+<a name="base">For the same reason,</a>\r
+it has no way of stopping a new browser\r
+window being created, because this is done through the\r
+<big><kbd>target</kbd></big>\r
+attribute in the\r
+<big><kbd><a></kbd></big>\r
+and\r
+<big><kbd><base></kbd></big>\r
+elements,\r
+not through headers.\r
+Nor do we plan to add a feature to\r
+<a href="http://simmons.starkville.ms.us/tips/081097/">paralyze animated</a>\r
+<small>GIF</small>s.\r
+</p>\r
+\r
+<h3><a name="push" href="/cgi-bin/gp?pg=ijbfaq&pr=push"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Does it block ads on the broadcasting ``push'' systems? How about pop-up ads?\r
+</h3>\r
+<p>\r
+We haven't tried it but we expect it would probably\r
+work on image ads on push channels.\r
+See also\r
+<a href="links.html#adchoice">adchoice</a>.\r
+<p>\r
+<a name="pop">Disabling</a>\r
+<a href="cookies.html#java">Javascript</a>\r
+stops some pop-up ads.\r
+One problem is that some advertisers throw open a new\r
+browser window to frame the ad. The ad is easily blocked,\r
+but the empty window remains. You can kill it easily, but this is a chore.\r
+We don't see how to stop them other than editing the\r
+<small>HTML</small>\r
+from the parent window, which we\r
+<a href="ijbfaq.html#broken">don't</a>\r
+like to do.\r
+<p>\r
+<a name="TBTD">The</a>\r
+<a href="http://www.tbtf.com/archive/10-06-97.html">TBTF</a>\r
+newsletter warned subscribers to push information that\r
+<a name="LOGTARGET">in IE4,</a>\r
+<a href="http://www.microsoft.com/standards/cdf.htm#Logging">LOGTARGET</a>\r
+allows\r
+servers to determine the\r
+<small>URL</small>s\r
+viewed at their site even if accessed from cache or through a proxy.\r
+If you use this browser see our instructions on\r
+<a href="cookies.html#counting">how to disable</a>\r
+this.\r
+<p>\r
+<a name="pushy">If you find you have experience using the proxy with push,</a>\r
+or have any other advice about it, please\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=pushy">tell us.</a>\r
+</p>\r
+<p align="center"><a href="#top_of_page"><img border=0 width=250 height=15 src="/images/top.gif" alt="--- Back to Top of Page ---"></a></p>\r
+<br>\r
+<center>\r
+<h2><a name="cookies"><font face="arial, helvetica">\r
+Cookies\r
+</font></a>\r
+</h2>\r
+</center>\r
+<br>For background information on cookies see our\r
+<a href="cookies.html">page describing their dangers.</a>\r
+\r
+<h3><a name="breakthrough" href="/cgi-bin/gp?pg=ijbfaq&pr=breakthrough"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Might some cookies still get through? How can I stop them?\r
+</h3>\r
+<p>\r
+Yes, you should expect the occasional cookie to make it through to your browser.\r
+We know of at least three ways this can happen;\r
+please\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=breakthrough">tell us</a>\r
+if you find any others.\r
+One way is in secure documents, which are explained\r
+<a href="ijbfaq.html#secure">below.</a>\r
+<p>\r
+<a name="EQUIV">A</a>\r
+<a href="links.html#JavaScript">few</a>\r
+sites set cookies using a line such as\r
+<big><kbd><META HTTP-EQUIV="Set-Cookie" CONTENT="flavor=chocolate"></kbd></big>\r
+in the\r
+<big><kbd>HEAD</kbd></big>\r
+section of an\r
+<small>HTML</small>\r
+document.\r
+<a name="javascript">Cookies can also be</a>\r
+<!-- IEM: http://cgi.netscape.com/eng/mozilla/Gold/handbook/javascript/ref_a-c.html#cookie_property -->\r
+set and read\r
+in\r
+JavaScript.\r
+To see if this is happening in a document,\r
+view its source, look in the\r
+<big><kbd>head</kbd></big>\r
+for a section tagged\r
+<big><kbd>script language="JavaScript"</kbd></big>.\r
+If it contains a reference to\r
+<big><kbd>document.cookie</kbd></big>,\r
+the page can manipulate your cookie file without sending any cookie headers.\r
+The\r
+Internet Junkbuster\r
+does not tamper with these methods.\r
+Fortunately they are rarely used at the moment.\r
+If a cookie gets set, it should be stopped\r
+by the proxy on its way back to the server when a page is requested,\r
+but it can still be read in Javascript.\r
+bu\r
+<p>\r
+<a name="alert">To prevent cookies breaking through,</a>\r
+<strong>always</strong>\r
+keep\r
+<a href="cookies.html#disable">cookie alerts</a>\r
+turned on in your browser,\r
+and\r
+<a href="cookies.html#java">disable</a>\r
+Java and Javascript.\r
+Making the files\r
+<a href="cookies.html#only">hard to write</a>\r
+may also help.\r
+</p>\r
+\r
+<h3><a name="method" href="/cgi-bin/gp?pg=ijbfaq&pr=method"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Exactly how do cookies get created and stored anyway?\r
+</h3>\r
+<p>\r
+When a web site's server sends you a page it also sends\r
+certain ``header information'' which your browser records but does not display.\r
+One of these is a\r
+<big><kbd>Set-Cookie</kbd></big>\r
+header, which specifies the cookie information that the server wants your browser to record.\r
+Similarly, when your browser requests a page it also sends headers, specifying\r
+information such as the graphics formats it understands.\r
+If a cookie has previously been set by a site that matches the\r
+<small>URL</small>\r
+it is about to request,\r
+your browser adds a\r
+<big><kbd>Cookie</kbd></big>\r
+header quoting the previous information.\r
+<p>\r
+<a name="privacy">For more background information on how cookies</a>\r
+can damage your privacy, see our\r
+<a href="cookies.html">page on cookies.</a>\r
+For highly detailed technical information see the\r
+<a href="links.html#kristol">RFC.</a>\r
+The\r
+Internet Junkbuster\r
+will show you all headers you use the\r
+<a href="ijbman.html#debug">debug</a>\r
+<big><kbd>8</kbd></big>\r
+option,\r
+or you can get a sample from our\r
+<a href="ijbfaq.html#headers">demonstration page.</a>\r
+</p>\r
+\r
+<h3><a name="break" href="/cgi-bin/gp?pg=ijbfaq&pr=break"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+If cookies can't get through, will some things stop working for me?\r
+</h3>\r
+<p>\r
+Possibly.\r
+Some personalized services including certain\r
+<!-- IEM: http://my.yahoo.com -->\r
+chat\r
+rooms\r
+require cookies.\r
+<a name="registration">Newspapers that require</a>\r
+<!-- IEM: http://www.nytimes.com/subscribe/sub-bin/new_sub.cgi#agree -->\r
+registration\r
+or\r
+<!-- IEM: http://interactive5.wsj.com/regUser.html -->\r
+subscription\r
+will not automatically recognize you if you don't send them the cookie they\r
+assigned you. And there are a very small number of sites that do\r
+strange things with cookies; they don't work for anyone that blocks\r
+cookies by any means.\r
+Some sites such as\r
+<a href="links.html#withhold">Microsoft</a>\r
+explain that their content is so wonderfully compelling that\r
+they will withhold it from you unless you submit to their\r
+inserting cookies.\r
+<p>\r
+<a name="want">If you want such sites to be given your cookies,</a>\r
+you can use the\r
+<a href="ijbman.html#cookiefile">cookiefile</a>\r
+option provided you are running\r
+<a href="ijbfaq.html#crumble">Version 1.2 or later</a>\r
+yourself.\r
+Simply include the domain name of those sites in the\r
+<i>cookiefile</i>\r
+specified by this option.\r
+If it still doesn't work,\r
+the problem may be in\r
+<a href="ijbfaq.html#breakage">other headers.</a>\r
+<p>\r
+<a name="one">It's possible to let cookies out but not in,</a>\r
+which is enough to keep some sites happy, but not all of them:\r
+one newspaper site seems to go into an endless frenzy\r
+if deprived of fresh cookies.\r
+A cookiefile containing\r
+a single line consisting of the two characters\r
+<big><kbd>>*</kbd></big>\r
+(greater-than and star) permits server-bound cookies only.\r
+The\r
+<big><kbd>*</kbd></big>\r
+is a\r
+<a href="ijbman.html#wildcard">wildcard</a>\r
+that matches all domains.\r
+<p>\r
+<a name="else">If someone else is running the</a>\r
+Internet Junkbuster\r
+for you and has a version\r
+that\r
+<!-- IAM: ijbfaq.html#registration -->\r
+passes server-bound cookies through,\r
+you can try editing your browser's cookie\r
+file to contain just the ones you want,\r
+and restart your browser.\r
+<a name="window">To subscribe to a new service like this</a>\r
+after you have started using the\r
+Internet Junkbuster,\r
+you can try the following:\r
+tell your browser to\r
+<a href="ijbfaq.html#discontinue">stop using</a>\r
+the\r
+Internet Junkbuster,\r
+fill out and submit your subscription details\r
+(allowing that web site to set a cookie),\r
+then\r
+reconfigure your browser to use the\r
+Internet Junkbuster\r
+again\r
+(and stop more cookies being sent).\r
+This also requires the\r
+<a href="ijbman.html#cookiefile">cookiefile</a>\r
+option,\r
+and its success depends on the Web site\r
+not wanting to change your cookies at every session.\r
+For this reason it does not work at some major newspaper sites, for example.\r
+<a name="buyers">But you may prefer to</a>\r
+look at whether other sites provide the same\r
+or better services without demanding the opportunity\r
+to track your behavior.\r
+The web is a buyer's market where most prices are zero:\r
+very few people pay\r
+for content with money, so why should you pay with your privacy?\r
+</p>\r
+\r
+<h3><a name="crumble" href="/cgi-bin/gp?pg=ijbfaq&pr=crumble"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Can I control cookies on a per-site basis?\r
+</h3>\r
+<p>\r
+<a name="discard">Yes, since version 1.2 the</a>\r
+Internet Junkbuster\r
+has included advanced cookie management facilities.\r
+Unless you specify otherwise,\r
+cookies are discarded (``crumbled'') by the\r
+Internet Junkbuster\r
+whether they came from the server or the browser.\r
+In Version 1.2 and later you can\r
+use the\r
+<a href="ijbman.html#cookiefile">cookiefile</a>\r
+option\r
+to specify when cookies are to be passed through intact.\r
+It uses the same syntax and\r
+<a href="ijbman.html#o_b">matching</a>\r
+algorithm as the blockfile.\r
+<p>\r
+<a name="cook">If the</a>\r
+<small>URL</small>\r
+matches a pattern in the\r
+<i><dfn>cookiefile</dfn></i>\r
+then cookies are let through in both the browser's request for the\r
+<small>URL</small>\r
+and in the server's response.\r
+<a name="directional">One-way permissions can be</a>\r
+specified by starting the line with the\r
+<big><kbd>></kbd></big>\r
+or\r
+<big><kbd><</kbd></big>\r
+character.\r
+For example, a cookiefile consisting of the four lines\r
+<br>\r
+   <big><kbd>org</kbd></big>\r
+<br>\r
+   <big><kbd>>send-user-cookies.org</kbd></big>\r
+<br>\r
+   <big><kbd><accept-server-cookies.org</kbd></big>\r
+<br>\r
+   <big><kbd>~block-all-cookies.org</kbd></big>\r
+<br>\r
+allows cookies to and from\r
+<big><kbd>.org</kbd></big>\r
+domains only, with the following exceptions:\r
+<br><ol type="1">\r
+<li>\r
+<a name="fed">Cookies sent from servers in the domain</a>\r
+<big><kbd>send-user-cookies.org</kbd></big>\r
+are blocked on their way to the client,\r
+but cookies sent by the browser to that domain are still be fed to them.\r
+<li>\r
+<a name="take">The cookies of</a>\r
+<big><kbd>accept-server-cookies.org</kbd></big>\r
+check in to the proxy and are passed through to the browser,\r
+but when they come back to the proxy they never check out.\r
+<li>\r
+<a name="deny">All cookies to and from</a>\r
+<big><kbd>block-all-cookies.org</kbd></big>\r
+are blocked.\r
+</ol>\r
+<p>\r
+<a name="paths">If</a>\r
+the\r
+<b><kbd>junkbuster</kbd></b>\r
+was compiled with the regular expressions option\r
+they may be used in paths.\r
+Any logging to a\r
+<a href="ijbfaq.html#jar">``cookie jar''</a>\r
+is separate and not affected.\r
+<p>\r
+<a name="breadth">It's important to give hosts you want to be able</a>\r
+to set cookies sufficient breadth. For example,\r
+instead of\r
+<big><kbd>www.yahoo.com</kbd></big>\r
+use\r
+<big><kbd>yahoo.com</kbd></big>\r
+because the company uses many different hosts ending in that domain.\r
+</p>\r
+\r
+<h3><a name="wafers" href="/cgi-bin/gp?pg=ijbfaq&pr=wafers"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Can I make up my own fake cookies (wafers) to feed to servers?\r
+</h3>\r
+<p>\r
+Yes,\r
+using the\r
+<a href="ijbman.html#wafer">wafer</a>\r
+option.\r
+We coined the term\r
+<i><dfn>wafer</dfn></i>\r
+to describe cookies chosen by a user,\r
+not the Web server.\r
+Servers may not find wafers as tasty as the cookies\r
+they make themselves.\r
+But users may enjoy controlling servers' diets for various reasons,\r
+such as the following.\r
+<br><ul type="1">\r
+<li>\r
+<a name="retaliate">Users who consider cookies to</a>\r
+be an unwelcome intrusion and a waste\r
+of their disk space can respond in kind.\r
+By writing ``signature wafers'' they can\r
+express their feelings about cookies,\r
+in a place that the people\r
+in charge of them are most likely to notice.\r
+<li>\r
+<a name="notice">Sites running a proxy</a>\r
+that logs cookies to a file\r
+(such as the\r
+Internet Junkbuster\r
+does with the\r
+<a href="ijbman.html#jarfile">jarfile</a>\r
+option on)\r
+may want to notify\r
+servers that their cookies are being intercepted,\r
+deleted or copied.\r
+One possible reason for doing this is the uncertain copyright status\r
+of cookie strings.\r
+<a href="over.html#notlaw">Nothing</a>\r
+here should be taken as legal advice: we are simply raising a question\r
+for any interested parties to consider,\r
+and make no representation that such measures are necessary or sufficient.\r
+Concerned proxy sites might decide to send a wafer\r
+(named ``NOTICE'' for example)\r
+containing text along the lines of the following.\r
+<blockquote>\r
+<p>\r
+<a name="licenses_on_cookies_refused">TO WHOM IT MAY CONCERN</a>\r
+<i>\r
+<br>\r
+<br>\r
+Do not send me any copyrighted information other than the\r
+document that I am requesting or any of its necessary components.\r
+<br>\r
+<br>\r
+In particular do not send me any cookies that\r
+are subject to a claim of copyright by anybody.\r
+Take notice that I refuse to be bound by any license condition\r
+(copyright or otherwise) applying to any cookie.\r
+</i>\r
+</blockquote>\r
+Any company that tries to argue in court that the proxy site\r
+was breaching their copyright in the cookies would\r
+be met with the defense that the proxy site gave that company\r
+the opportunity to protect its copyright by simply\r
+not sending cookies after receiving the notice. \r
+<p>\r
+<a name="pointer">Cookies can be as long as four thousand characters,</a>\r
+so there's plenty of space for lawyerly verbosity,\r
+but white space, commas, and semi-colons are\r
+<a href="ijbman.html#o_w">prohibited.</a>\r
+Spaces can be turned into underscores.\r
+Alternatively,\r
+a\r
+<small>URL</small>\r
+could be sent as the cookie value,\r
+pointing to a document containing a notice,\r
+perhaps with a suggestive value such as\r
+<br>\r
+<big><kbd>http://www.junkbusters.com/ht/en/ijbfaq.html#licenses_on_cookies_refused</kbd></big>\r
+<br>\r
+But including the notice directly would probably be preferable\r
+because the addressee does not have to look it up.\r
+<p>\r
+<a name="vanilla">The</a>\r
+Internet Junkbuster 2.0\r
+currently sends a full notice as a\r
+``vanilla wafer''\r
+if cookies are being logged to a cookie jar\r
+and no other wafers have been specified.\r
+It can be suppressed with the\r
+<a href="ijbman.html#suppress-vanilla-wafer">suppress-vanilla-wafer</a>\r
+option,\r
+which might be used in situations where there is an established understanding\r
+between the proxy and all who serve it.\r
+</ul>\r
+<p>\r
+<a name="gimme">Junkbusters provides a</a>\r
+<small>CGI</small>\r
+script that lets you\r
+<a href="ijbfaq.html#headers">see</a>\r
+your wafers as they appear to servers.\r
+<p>\r
+<a name="malfunction">Wafers confuse a few fragile servers.</a>\r
+If this troubles you, don't use this option.\r
+<p>\r
+<a name="regardless">Any wafers specified are sent to</a>\r
+all sites regardless of the cookiefile.\r
+<a name="compliant">They are appended after any genuine cookies,</a>\r
+to maintain compliance with\r
+<a href="links.html#kristol">RFC 2109</a>\r
+in the event that a path was specified for a cookie.\r
+The\r
+<small>RFC</small>'s provisions regarding the\r
+<big><kbd>$</kbd></big>\r
+character\r
+(such as the\r
+<big><kbd>Version</kbd></big>\r
+attribute)\r
+are transparent\r
+to the proxy; it simply quotes what was recited by the browser.\r
+<p>\r
+<a name="personalize">If you want to send wafers only to specific sites,</a>\r
+you could try putting them your browser's cookie file in a format\r
+conforming to the Netscape\r
+<a href="links.html#netscape">specification</a>,\r
+and then specify in the proxy's cookiefile that cookies are to be\r
+<a href="ijbfaq.html#directional">sent to</a>\r
+but not accepted from those sites, so they can't overwrite the file.\r
+This may work with Netscape but not all other browsers.\r
+</p>\r
+\r
+<h3><a name="jar" href="/cgi-bin/gp?pg=ijbfaq&pr=jar"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Why would anyone want to save their cookies in a ``cookie jar?''\r
+</h3>\r
+<p>\r
+We provided this capability just in case anyone wants it.\r
+There are a few possible reasons.\r
+<br><ul type="1">\r
+<li>\r
+<a name="pay">It's conceivable that</a>\r
+marketing companies might one day\r
+<a href="new.html#hagel">buy</a>\r
+history files and cookie jars from consumers\r
+in the same way that they currently pay them to fill out survey forms.\r
+With this information they could\r
+gather psychographic information,\r
+see which competitors' sites the consumer has visited,\r
+and discover what advertising is being targeted at them.\r
+<li>\r
+<a name="choose">Some consumers might</a>\r
+employ semi-automated means of sorting through\r
+their cookie jars, selecting which ones to place in their cookies\r
+file for use by their browsers.\r
+Their decisions could be based on payments offered,\r
+privacy rating systems such as\r
+<a href="links.html#truste">TRUSTe</a>\r
+proposes,\r
+or their own opinion of the company.\r
+It could be done manually or with software.\r
+<li>\r
+<a name="share">Users may even start ``sharing'' cookies among themselves,</a>\r
+sending back cookies that servers generated for other visitors.\r
+Servers that aren't expecting this possibility\r
+will be misled about their visitors' identities.\r
+Cookies could be shared among users on a single machine,\r
+or across continents via\r
+<small>FTP</small>\r
+and anonymous remailers.\r
+<a name="disinformation">Privacy activists may promote</a>\r
+cookie disinformation campaigns\r
+as a way to defend the public against abuse.\r
+If a significant percentage of people send disinformative cookies,\r
+user tracking via cookies may become less reliable and less used.\r
+</ul>\r
+</p>\r
+<p align="center"><a href="#top_of_page"><img border=0 width=250 height=15 src="/images/top.gif" alt="--- Back to Top of Page ---"></a></p>\r
+<br>\r
+<center>\r
+<h2><a name="anonymity"><font face="arial, helvetica">\r
+Anonymity\r
+</font></a>\r
+</h2>\r
+</center>\r
+<br>For details\r
+on how your identity can be revealed while you surf,\r
+see our page on\r
+<a href="http://www.junkbusters.com/cgi-bin/privacy">privacy.</a>\r
+Once you start using\r
+the\r
+Internet Junkbuster\r
+you should find that much of the information\r
+previously indicated on that page will no longer be provided.\r
+If the\r
+<big><kbd>REMOTE HOST</kbd></big>\r
+indicating your IP address is too close for comfort,\r
+see our suggestions\r
+<a href="ijbfaq.html#conceal">below</a>\r
+on how to\r
+conceal\r
+your IP address.\r
+We also recommend that you\r
+<a href="cookies.html">disable JavaScript</a>\r
+and\r
+<a href="links.html#java">Java.</a>\r
+\r
+<h3><a name="disclose" href="/cgi-bin/gp?pg=ijbfaq&pr=disclose"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+If I use the Internet Junkbuster, will my anonymity be guaranteed?\r
+</h3>\r
+<p>\r
+No. Your chances of remaining anonymous are improved,\r
+but unless you are an expert on Internet security\r
+it would be safest to assume that everything you do on the Web\r
+can be attributed to you personally.\r
+<p>\r
+<a name="happen">The</a>\r
+Internet Junkbuster\r
+removes various information about you,\r
+but it's still possible that web sites can find out who you are.\r
+Here's one way this can happen.\r
+<p>\r
+<a name="ftp">A few browsers</a>\r
+<a href="http://www.junkbusters.com/cgi-bin/privacy">disclose the user's email address</a>\r
+in certain situations, such as when transferring a file by\r
+<small>FTP</small>.\r
+The\r
+Internet Junkbuster 2.0\r
+does not filter the\r
+<small>FTP</small>\r
+stream.\r
+If you need this feature, or are concerned about the mail handler\r
+of your browser disclosing your email address,\r
+you might consider\r
+products such as\r
+<a href="links.html#nsclean">NSClean</a>.\r
+<p>\r
+<a name="binaries">Browsers downloaded as binaries</a>\r
+could use non-standard headers to give out any information\r
+they can have access to: see the manufacturer's license agreement.\r
+It's impossible to anticipate and prevent every breach of privacy that\r
+might occur.\r
+The professionally paranoid prefer browsers available as source code,\r
+because anticipating their behavior is easier.\r
+</p>\r
+\r
+<h3><a name="should" href="/cgi-bin/gp?pg=ijbfaq&pr=should"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Why should I trust my ISP or Junkbusters with my browsing data?\r
+</h3>\r
+<p>\r
+You shouldn't have to trust us, and you certainly don't have to.\r
+We do not run the proxy as a service,\r
+where we could observe your online behavior.\r
+We provide source code so that everyone can see that the proxy isn't\r
+doing anything sneaky.\r
+<p>\r
+<a name="awful">You are already trusting your</a>\r
+<small>ISP</small>\r
+not to look at an awful lot of information on what you do.\r
+They probably post a\r
+<a href="links.html#policy">privacy policy</a>\r
+on their site to reassure you.\r
+If they run a proxy for you, using it could actually\r
+make it slightly easier for them to monitor you,\r
+but we doubt that any sane\r
+<small>ISP</small>\r
+would try this,\r
+because if it were discovered customers would desert them.\r
+</p>\r
+\r
+<h3><a name="header" href="/cgi-bin/gp?pg=ijbfaq&pr=header"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+What private information from server-bound headers is removed?\r
+</h3>\r
+<p>\r
+The\r
+Internet Junkbuster\r
+pounces on the following\r
+<small>HTTP</small>\r
+headers in requests to servers,\r
+unless instructed otherwise in the options.\r
+<br><ul type="1">\r
+<li>\r
+<a name="from">The</a>\r
+<big><kbd>FROM</kbd></big>\r
+header,\r
+which a few browsers use to tell your email address to servers,\r
+is dropped\r
+unless the\r
+<a href="ijbman.html#from">from</a>\r
+option is set.\r
+<li>\r
+<a name="agent">The</a>\r
+<big><kbd>USER_AGENT</kbd></big>\r
+<a name="infer">header</a>\r
+is changed to indicate that the browser is\r
+currently Mozilla (Netscape) 3.01 Gold\r
+with an unremarkable Macintosh configuration.\r
+Misidentification helps resist certain\r
+<a href="ijbfaq.html#misidentify">attacks.</a>\r
+If your browser and hardware happen to be accurately identified,\r
+you might want to change the default.\r
+(Earlier versions of the\r
+Internet Junkbuster\r
+indicated different details;\r
+by altering them periodically we aim to hinder anyone trying to\r
+<a href="ijbfaq.html#detect">infer</a>\r
+whether our proxy is present.)\r
+<a name="lying">If you don't like the idea</a>\r
+of incorrectly identifying your computer as a Mac,\r
+set it accordingly.\r
+<!-- Aside: or read Kundera's Unbearable Lightness of Being, 5:5, ``It is a tragicomic fact..'' (p187?) -->\r
+<li>\r
+<a name="referer">The</a>\r
+<big><kbd>REFERER</kbd></big>\r
+header\r
+(which indicates where the\r
+<small>URL</small>\r
+currently being requested was found)\r
+is dropped.\r
+A single static referer to replace all\r
+real referers may be specified using the \r
+<a href="ijbman.html#referer">referer</a>\r
+option.\r
+Where no referer is provided by the browser, none is added;\r
+the\r
+<a href="ijbman.html#add-header">add-header</a>\r
+option with arguments such as\r
+<big><kbd>-x 'Referer: http://me.me.me'</kbd></big>\r
+can be used to send a bogus referer with every request.\r
+</ul>\r
+In \r
+Version <a href="ijbdist.html#c4">1.4</a>\r
+and later you can use the\r
+<a href="ijbman.html#o_r">-r @</a>\r
+option to selectively disclose\r
+<big><kbd>REFERER</kbd></big>\r
+and\r
+<big><kbd>USER_AGENT</kbd></big>\r
+to only those sites you nominate.\r
+<p>\r
+<a name="UA">Some browsers</a>\r
+send Referer and User-Agent information under different non-standard headers.\r
+The\r
+Internet Junkbuster 2.0\r
+stops\r
+<big><kbd>UA</kbd></big>\r
+headers,\r
+but others may get through.\r
+This information is also available via JavaScript,\r
+so\r
+<a href="cookies.html">disable disable</a>\r
+it.\r
+<a name="indexers">Some search engines</a>\r
+<a href="cookies.html#queries">encode the query you typed</a>\r
+in the\r
+<small>URL</small>\r
+that goes to advertisers to target a banner ad at you,\r
+so you will need to block the ad as well as the referer header,\r
+unless you want them (and anyone they might\r
+<a href="cookies.html#set">buy data</a>\r
+from)\r
+to know\r
+<a href="links.html#search">everything you ever search for.</a>\r
+<p>\r
+<a name="JavaScript">If you have JavaScript enabled (the default on</a>\r
+most browsers) servers can use it to obtain Referer and User Agent,\r
+as well as your plug-ins.\r
+We recommend\r
+<a href="cookies.html#java">disabling</a>\r
+JavaScript and Java.\r
+<p>\r
+<a name="response">Currently no</a>\r
+<small>HTTP</small>\r
+response headers (browser bound)\r
+are removed,\r
+not even the\r
+<big><kbd>Forwarded:</kbd></big>\r
+or\r
+<big><kbd>X-Forwarded-For:</kbd></big>\r
+headers.\r
+Nor are any added,\r
+<a href="ijbman.html#o_y">unless requested.</a>\r
+We are considering a more flexible header management system for\r
+a future version.\r
+</p>\r
+\r
+<h3><a name="breakage" href="/cgi-bin/gp?pg=ijbfaq&pr=breakage"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Might some things break because header information is changed?\r
+</h3>\r
+<p>\r
+Possibly. If used with a browser less advanced than Netscape 3.0 or IE-3,\r
+indicating an advanced browser\r
+may encourage pages containing extensions that confuse your browser.\r
+If this becomes a problem\r
+upgrade your browser or\r
+use the\r
+<a href="ijbman.html#user-agent">user-agent</a>\r
+option to indicate an\r
+<a href="ijbfaq.html#low">older browser.</a>\r
+In \r
+Version <a href="ijbdist.html#c4">1.4</a>\r
+and later you can selectively reveal your real browser\r
+to only those sites you nominate.\r
+<p>\r
+<a name="Russian">Because different browsers</a>\r
+use different encodings of Russian characters,\r
+certain web servers convert pages on-the-fly according to the User Agent\r
+header. Giving a User Agent with the wrong operating system or\r
+browser manufacturer causes some Russian sites to be garbled;\r
+Russian surfers should\r
+<a href="ijbman.html#o_r">change it</a>\r
+to something closer.\r
+<p>\r
+<a name="counters">Some</a>\r
+<a href="http://www.yahoo.com/Computers_and_Internet/Internet/World_Wide_Web/Programming/Access_Counts/">page access counters</a>\r
+work by looking at the referer;\r
+they may fail or break when deprived.\r
+<p>\r
+<a name="wired">Some sites depend on getting a referer header,</a>\r
+such as\r
+<big><kbd>uclick.com</kbd></big>,\r
+which serves comic strips\r
+for many newspaper sites,\r
+including\r
+<a href="http://www.uclick.com/?feature=db"><cite>Doonsbury</cite></a>\r
+for the\r
+<a href="http://www.washingtonpost.com/wp-srv/style/longterm/comics/comics.htm"><cite>Washington Post.</cite></a>\r
+(If you click on that last link, you can then get to a page containing\r
+the strip via the\r
+same\r
+<small>URL</small>\r
+we've linked to under\r
+<cite>Doonsbury</cite>,\r
+but if you click on the\r
+<cite>Doonsbury</cite>\r
+link directly, it gives you an error message suggesting that you\r
+use a browser that supports referers.)\r
+In \r
+Version <a href="ijbdist.html#c4">1.4</a>\r
+and later you can use the\r
+<a href="ijbman.html#o_r">-r @</a>\r
+option\r
+and place a line like\r
+<big><kbd>>uclick.com</kbd></big>\r
+in your cookiefile.\r
+<a href="http://www.wired.com/news/">Wired News</a>\r
+used to use referer to decide whether to add a navigation column to\r
+the page, but they have changed that.\r
+<p>\r
+<a name="Intellicast">The weather maps of</a>\r
+<a href="links.html#Intellicast">Intellicast</a>\r
+have been blocked by their server when no referer or cookie is provided.\r
+You can use the same countermeasure with a line such as\r
+<big><kbd>>208.194.150.32</kbd></big>\r
+(or simply get your weather information\r
+<a href="ijbfaq.html#buyers">elsewhere</a>).\r
+<p>\r
+<a name="decide">Some software vendors, including</a>\r
+<a href="http://www.intuit.com/quicken_store/">Intuit</a>\r
+use\r
+<big><kbd>USER_AGENT</kbd></big>\r
+to decide which versions of their products to display to you.\r
+With the\r
+<a href="ijbfaq.html#agent">default</a>\r
+you get Mac versions.\r
+<p>\r
+<a name="resort">As a last resort if a site you need doesn't seem to be working,</a>\r
+the\r
+<a href="ijbfaq.html#set">proxy configuration</a>\r
+of many browsers allow you to specify\r
+<b><font face="arial, helvetica">\r
+No Proxy For</font></b>\r
+any hostname you want.\r
+<p>\r
+<a name="What">We had reports that on some versions of Netscape the</a>\r
+<a href="http://home.netscape.com/home/whats-new.html">What's New</a>\r
+feature did not work with the proxy,\r
+but we think we fixed this in Version 2.0.1.\r
+</p>\r
+\r
+<h3><a name="misidentify" href="/cgi-bin/gp?pg=ijbfaq&pr=misidentify"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How is misidentifying my browser good for security and privacy?\r
+</h3>\r
+<p>\r
+Almost\r
+<a href="new.html#Browser">every</a>\r
+major release of both leading browsers has contained\r
+bugs that allow malicious servers to compromise your privacy and security.\r
+Known bugs are quickly fixed, but millions of copies of the affected\r
+software remain out there, and yours is probably one of them.\r
+The\r
+<a href="ijbfaq.html#agent">header</a>\r
+that normally identifies your browser tells such servers exactly which attacks\r
+to use against you.\r
+By misidentifying your browser you reduce the likelihood that they\r
+will be able to mount a successful attack.\r
+</p>\r
+\r
+<h3><a name="conceal" href="/cgi-bin/gp?pg=ijbfaq&pr=conceal"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Does the Internet Junkbuster conceal my IP address?\r
+</h3>\r
+<p>\r
+Web sites get the IP address of any proxy or browser they serve pages to.\r
+If you run the proxy on your own computer the IP address disclosed\r
+is the same as your browser would, unless you use the\r
+<a href="ijbman.html#forwardfile">forwardfile</a>\r
+option is used to chain to another proxy,\r
+in which case servers only get the last IP address in the chain.\r
+Chaining slightly slows browsing of course, but it improves anonymity.\r
+<p>\r
+<a name="anonymizing">One public proxy that you can</a>\r
+forward to is\r
+<a href="new.html#LPWA">lpwa.com</a>\r
+port 8000.\r
+Read about its privacy-enhancing\r
+features and the authentication procedures first,\r
+and note that it blocks\r
+<a href="ijbfaq.html#wired">referer</a>\r
+in almost all cases,\r
+as well as some\r
+<a href="http://lpwa.com:8000/system.html#principles:header">other headers.</a>\r
+</p>\r
+\r
+<h3><a name="authorize" href="/cgi-bin/gp?pg=ijbfaq&pr=authorize"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+How can I set the proxy to remember my LPWA password?\r
+</h3>\r
+<p>\r
+After you log in to\r
+<a href="http://lpwa.com">LPWA</a>\r
+it tells your browser to send a\r
+<big><kbd>Proxy-authorization</kbd></big>\r
+header with each request.\r
+Whenever you shut down the browser and start again with a new browser,\r
+you need to log in again.\r
+If you are the only person using the\r
+Internet Junkbuster\r
+proxy, you can avoid repeated logins to\r
+<a href="http://lpwa.com">LPWA</a>\r
+by telling the\r
+Internet Junkbuster\r
+to send the information by placing a line such as\r
+<br>\r
+   <big><kbd>add-header Proxy-authorization: Basic ZHVtbXk=.</kbd></big>\r
+<br>\r
+in the configuration file.\r
+The exact example above\r
+<em>does not work</em>\r
+because the code\r
+<big><kbd>ZHVtbXk=.</kbd></big>\r
+is a bogus one that\r
+<a href="http://lpwa.com">LPWA</a>\r
+would never generate;\r
+follow the procedure below to generate a valid one.\r
+<br><ol type="1">\r
+<li>\r
+<a name="eight">Restart your</a>\r
+Internet Junkbuster\r
+with\r
+<big><kbd>debug 8</kbd></big>\r
+so you can see the\r
+<a href="ijbman.html#o_d">headers.</a>\r
+<li>\r
+<a name="login">Log in to</a>\r
+<a href="http://lpwa.com">LPWA</a>\r
+and go to any other site.\r
+<li>\r
+<a name="observe">Find the</a>\r
+<big><kbd>Proxy-authorization</kbd></big>\r
+header from the debug output and paste it\r
+after the word\r
+<a href="ijbman.html#add-header">add-header</a>\r
+into the config file.\r
+Also change the debug value back again.\r
+<li>\r
+<a name="return">Shut down your browser, start it up again, and</a>\r
+restart the proxy. Test that it works.\r
+</ol>\r
+This trick is convenient for sole users, but is not suitable when\r
+more than one person uses the proxy, because they will all get the\r
+same\r
+<a href="http://lpwa.com">LPWA</a>\r
+identity.\r
+</p>\r
+\r
+<h3><a name="ident" href="/cgi-bin/gp?pg=ijbfaq&pr=ident"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Does the Internet Junkbuster thwart identification by identd?\r
+</h3>\r
+<p>\r
+We think so,\r
+provided you are not the user running the\r
+proxy.\r
+If your computer (or your\r
+<small>ISP</small>'s)\r
+is running the\r
+<a href="links.html#identd"><kbd>identd</kbd></a>\r
+demon,\r
+servers can ask it for the identity of the\r
+user making the request at time you request a page from them.\r
+But if you're going through a proxy,\r
+they will identify the user name associated with the proxy, not you.\r
+A visit to\r
+<a href="http://ident.junkbusters.com">http://ident.junkbusters.com</a>\r
+lets you see what's happening.\r
+This test is (quite rightly) blocked by many\r
+<a href="ijbfaq.html#firewall">firewalls;</a>\r
+just interrupt the transfer if you get an abnormal wait after clicking.\r
+Running other applications\r
+may also expose you via\r
+<a href="links.html#identd"><kbd>identd</kbd></a>;\r
+the proxy of course doesn't help then.\r
+</p>\r
+\r
+<h3><a name="detect" href="/cgi-bin/gp?pg=ijbfaq&pr=detect"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Can web sites tell that I'm using the Internet Junkbuster?\r
+</h3>\r
+<p>\r
+With the default options the proxy doesn't announce itself.\r
+Obvious indications such as\r
+<a href="links.html#alive">Keep-Alive</a>\r
+headers are\r
+<a href="ijbman.html#o_x">deleted,</a>\r
+but sites might notice that you can cancel cookies faster than\r
+any human could possibly click on a mouse.\r
+(If you want to provide a\r
+plausible explanation for this,\r
+change the User Agent header to a\r
+<a href="ijbfaq.html#lynx">cookie-free</a>\r
+or\r
+<a href="cookies.html#communicator">cookie-crunching</a>\r
+browser).\r
+<p>\r
+<a name="figure">But when certain options</a>\r
+are used they could figure out something's going on,\r
+even if they're not pushing cookies.\r
+If you use blocking\r
+they can tell from their logs that the graphics in their pages\r
+are not being requested selectively.\r
+The\r
+<a href="ijbman.html#add-forwarded-header">add-forwarded-header</a>\r
+option explicitly announces to the server that a proxy is present,\r
+and\r
+sending them\r
+<a href="ijbfaq.html#wafers">wafers</a>\r
+is of course a dead giveaway.\r
+</p>\r
+<p align="center"><a href="#top_of_page"><img border=0 width=250 height=15 src="/images/top.gif" alt="--- Back to Top of Page ---"></a></p>\r
+<br>\r
+<center>\r
+<h2><a name="security"><font face="arial, helvetica">\r
+Security\r
+</font></a>\r
+</h2>\r
+</center>\r
+<br>\r
+<h3><a name="encrypt" href="/cgi-bin/gp?pg=ijbfaq&pr=encrypt"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+What happens with Secure Documents (SSL, https:)?\r
+</h3>\r
+<p>\r
+If you enter a\r
+``Secure Document Area,''\r
+cookies and other header information\r
+such as User Agent and Referer\r
+are sent encrypted,\r
+so they cannot be filtered.\r
+We recommend getting your browser to alert you when this happens.\r
+(On Netscape:\r
+<b><font face="arial, helvetica">\r
+Options</font></b>;\r
+<b><font face="arial, helvetica">\r
+Security</font></b>;\r
+<b><font face="arial, helvetica">\r
+General</font></b>;\r
+<b><font face="arial, helvetica">\r
+Show an alert before entering a secure document space</font></b>.) \r
+We also recommend adding the line\r
+<big><kbd>:443</kbd></big>\r
+to the blockfile to stop all but sites specified in an exception\r
+after that line from using SSL.\r
+<p>\r
+<a name="passage">It may be possible to filter encrypted cookies</a>\r
+by combining the blocking proxy with a cryptographic proxy along\r
+the lines of\r
+<a href="http://stronghold.ukweb.com/safepassage/">SafePassage</a>,\r
+but we have not tried this.\r
+</p>\r
+\r
+<h3><a name="ssl" href="/cgi-bin/gp?pg=ijbfaq&pr=ssl"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Will using this as my Security Proxy compromise security?\r
+</h3>\r
+<p>\r
+We're not security experts, but we don't think so.\r
+The whole point of\r
+<small>SSL</small>\r
+is that the\r
+contents of messages are\r
+<!-- IEM: http://addy.com/dc/html/what_is_ssl_.html -->\r
+encrypted\r
+by the time\r
+they leave the browser and the server.\r
+Eavesdroppers (including proxies) can see where your messages are going\r
+whether you are running a proxy or not,\r
+but they only get to see the contents after they have been encrypted.\r
+</p>\r
+\r
+<h3><a name="restrict" href="/cgi-bin/gp?pg=ijbfaq&pr=restrict"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Can I restrict use of the proxy to a set of nominated IP addresses?\r
+</h3>\r
+<p>\r
+Yes, we added an\r
+<a href="ijbman.html#aclfile">access control</a>\r
+file in Version 2.0.\r
+But before you use it please consider why you want to do it.\r
+If the reason is security,\r
+it probably means you need a firewall.\r
+<p>\r
+<a name="selective">The</a>\r
+<a href="ijbman.html#listen-address">listen-address</a>\r
+option provides a way of binding the proxy to a single IP address/port.\r
+The right way to do this is to choose a port inside your firewall, and\r
+deny access to it to those outside the firewall.\r
+The\r
+Internet Junkbuster\r
+is not a firewall proxy;\r
+it should not be expected to solve security problems.\r
+<p>\r
+<a name="firewall">For background information on firewalls,</a>\r
+see\r
+<a href="http://www.yahoo.com/Computers_and_Internet/Security_and_Encryption/Firewalls/">Yahoo</a>\r
+or a\r
+<a href="http://www.netscapeworld.com/ned-02-1998/ned-02-firewall.html">magazine article</a>\r
+or these well-known books:\r
+<a href="http://www.amazon.com/exec/obidos/ISBN=0201633574/junkbusterscomA/"><cite>Firewalls and Internet Security: Repelling the Wily Hacker</cite></a>\r
+by\r
+<person>William R. Cheswick</person>\r
+and\r
+<person>Steven M. Bellovin</person>\r
+or\r
+<a href="http://www.amazon.com/exec/obidos/ISBN=1565921240/junkbusterscomA/"><cite>Building Internet Firewalls</cite></a>\r
+by\r
+<person>D. Brent Chapman</person>\r
+and\r
+<person>Elizabeth D. Zwicky</person>.\r
+There's\r
+<!-- IEM: http://www.wmd.de/wmd/staff/pauck/misc/fwtk_on_linux.html -->\r
+free Linux software\r
+available,\r
+and a large number of\r
+<a href="http://www.yahoo.com/Business_and_Economy/Companies/Computers/Software/System_Utilities/Security/Firewalls/">commercial</a>\r
+products and services.\r
+For an excellent security overview, primer, and compendium reference, see\r
+<a href="http://www.amazon.com/exec/obidos/ISBN=1565921488/junkbusterscomA/"><cite>Practical Unix and Internet Security</cite></a>\r
+by\r
+<person>Simson Garfinkel</person>\r
+and\r
+<person>Gene Spafford</person>.\r
+</p>\r
+\r
+<h3><a name="others" href="/cgi-bin/gp?pg=ijbfaq&pr=others"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Are there any security risks for ISPs or others who offer the proxy?\r
+</h3>\r
+<p>\r
+Yes.\r
+As with any service offered over the Internet,\r
+hackers can try to misuse it.\r
+A well-run\r
+<small>ISP</small>\r
+will have professionals who are experienced at assessing and containing\r
+these risks.\r
+<p>\r
+<a name="outside">It's possible to set up your machine so</a>\r
+that other people can have access to your proxy,\r
+but if you lack expertise in computer security\r
+you probably shouldn't have your computer configured to offer\r
+this or any other service to the outside world.\r
+<p>\r
+<a name="attack">Hackers can attempt to gain access</a>\r
+to the machine by various attacks,\r
+which we have tried to guard against but don't guarantee to thwart.\r
+They can also use the ``anonymizing'' quality of proxies\r
+to try to cover their tracks while hacking other computers.\r
+For this reason we recommend preventing it being used\r
+as an anonymous\r
+<big><kbd>telnet</kbd></big>\r
+by putting the pattern\r
+<big><kbd>:23</kbd></big>\r
+in the blockfile (it's included as standard equipment).\r
+(Actually the current implementation incidentally blocks telnet due to the\r
+way headers are handled, but it's best not to rely on this.)\r
+If you wish to block all ports except the default\r
+<small>HTTP</small>\r
+port 80,\r
+you can put the lines\r
+<br>\r
+   <big><kbd>:</kbd></big>\r
+<br>\r
+   <big><kbd>~:80</kbd></big>\r
+<br>\r
+at the beginning of the blockfile, but be aware that some servers\r
+run on non-default ports (e.g. 8080). You might also want to add the line\r
+<big><kbd>~:443</kbd></big>\r
+to allow\r
+<small>SSL</small>.\r
+<p>\r
+<a name="root">On</a>\r
+<small>UNIX <a href="legal.html#not_our_trademark">®</a></small>\r
+systems it is neither necessary nor desirable for the proxy to run as root.\r
+<p>\r
+<a name="patched">Versions 2.0.1 and below may be vulnerable to remote</a>\r
+exploitation of a memory buffer bug; for security reasons all users\r
+are encouraged to\r
+<a href="ijbdist.html#upgrade">upgrade.</a>\r
+<p>\r
+<a name="holes">If you find any security holes in the code</a>\r
+please\r
+<a href="/cgi-bin/gp?pg=ijbfaq&pr=holes">tell us,</a>\r
+along with any suggestions you may have for fixing it.\r
+However, we do not claim that we will be able to do so.\r
+<p>\r
+<a name="useful">We distribute this code in the hope that people</a>\r
+will find it useful, but we provide\r
+<a href="ijbfaq.html#free">no warranty</a>\r
+for it,\r
+and we are not responsible for anyone's use or misuse of it.\r
+<p>\r
+<a name="updates">You may also want to check back periodically for updated versions of the code.</a>\r
+We do not\r
+maintain a mailing list.\r
+To get quick updates, bookmark our\r
+<a href="ijbdist.html#versions">Distribution Information</a>\r
+page.\r
+</p>\r
+<p align="center"><a href="#top_of_page"><img border=0 width=250 height=15 src="/images/top.gif" alt="--- Back to Top of Page ---"></a></p>\r
+<font face="arial, helvetica">\r
+<a rel="begin" href="index.html">Home</a> <font color="#ff0000">\r
+<b> · </b></font>\r
+<a rel="next" href="ijbman.html">Next</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="lopt.html">Site Map</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="legal.html">Legal</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="junkdata.html">Privacy</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="cookies.html">Cookies</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="ijb.html">Banner Ads</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="telemarketing.html">Telemarketing</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="junkmail.html">Mail</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="junkemail.html">Spam</a>\r
+\r
+</font><form action="/cgi-bin/search" method="GET">\r
+<input type="text" name="q" size=60 maxlength=120 value="">\r
+<input type="submit" value="Search"></form>\r
+<small>\r
+<small>\r
+<p>\r
+<a href="legal.html#copy">Copyright</a> © 1996-8 Junkbusters\r
+<a href="legal.html#marks">®</a> Corporation.\r
+Copying and distribution permitted under\r
+the <a href="gpl.html"><small>GNU</small></a>\r
+General Public License.\r
+</small>\r
+<tt>\r
+1998/10/31\r
+http://www.junkbusters.com/ht/en/ijbfaq.html\r
+</tt>\r
+<address><kbd>webmaster@junkbusters.com</kbd></address>\r
+</small>\r
+</body>\r
+</html>\r
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">\r
+<html>\r
+<head>\r
+<!-- Copyright 1996-8 Junkbusters Corporation -->\r
+<!-- This work comes with NO WARRANTY -->\r
+<!-- It may be redistributed and modified under the GNU GPL-->\r
+<!-- See the body of http://www.junkbusters.com/ht/en/gpl.html for details-->\r
+<!-- Junkbusters is a registered trade mark of Junkbusters Corporation -->\r
+<!-- Generated 1998/10/31 03:58:25 UTC -->\r
+<meta name="Generator" content="Junkbusters Ebira $Revision: 1.1 $ $Date: 2001/04/16 21:10:38 $">\r
+<!-- Document ID: $Revision: 1.1 $ $Date: 2001/04/16 21:10:38 $ -->\r
+<title>\r
+Internet Junkbuster Technical Information\r
+</title>\r
+<base href="http://www.junkbusters.com/ht/en/ijbman.html">\r
+<meta name="description" content="The manual page for the Internet Junkbuster, free software to removes banner ads, cookies, and other stuff you don't want from your web browser.">\r
+<meta name="keywords" content="stop, junk, busters, junkbusters, junkbuster, mail, email, e-mail, direct, spam, spamoff, declare, telemarketing, telemarketers, privacy, sharing, names, renting, direct, marketing, database, databases, junk mail, lists, environment, conservation, recycling, catalogs, consumer, sending, opt out ">\r
+<link rel="next" href="cookies.html">\r
+<link rel="previous" href="ijbfaq.html">\r
+<link rel="contents" href="toc.html">\r
+</head>\r
+<body bgcolor="#f8f8f0" link="#000078" alink="#ff0022" vlink="#787878">\r
+<center>\r
+<h1><a name="top_of_page">Internet J<small>UNK<i><font color=red>BUSTER</font></i></small> Technical Information\r
+</a></h1>\r
+</center>\r
+<font face="arial, helvetica">\r
+<p align="center">\r
+<a href="#description">Options</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="#show">Checking Options</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="#install">Installation</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="#copyright">Copyright</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="ijbfaq.html#top_of_page">(FAQ)</a>\r
+</p>\r
+</font><br>\r
+<center>\r
+<h2><a name="man"><font face="arial, helvetica">\r
+Manual Page\r
+</font></a>\r
+</h2>\r
+</center>\r
+<br>A copy of this page\r
+in standard\r
+<big><kbd>man</kbd></big>\r
+macro format\r
+is included in the\r
+<a href="ijbfaq.html#tar">tar archive</a>.\r
+\r
+<h3><a name="name" href="/cgi-bin/gp?pg=ijbman&pr=name"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Name\r
+</h3>\r
+<p>\r
+<b><kbd>junkbuster</kbd></b>\r
+- The\r
+Internet Junkbuster\r
+Proxy\r
+<a href="legal.html#marks"><small><sup>TM</sup></small></a>\r
+</p>\r
+\r
+<h3><a name="synopsis" href="/cgi-bin/gp?pg=ijbman&pr=synopsis"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Synopsis\r
+</h3>\r
+<p>\r
+<b><kbd>junkbuster</kbd></b>\r
+<i>configfile</i>\r
+(Version 2.0 onwards)\r
+<br>\r
+<b><kbd>junkbstr.exe</kbd></b>\r
+<i>configfile</i>\r
+(Windows)\r
+<br>\r
+<b><kbd>junkbuster</kbd></b>\r
+<a href="#o_a">[-a]</a>\r
+<a href="#o_y">[-y]</a>\r
+<a href="#o_s">[-s]</a>\r
+<a href="#o_c">[-c]</a>\r
+<a href="#o_v">[-v]</a>\r
+<br>\r
+<a href="#o_u">[-u user_agent]</a>\r
+<a href="#o_r">[-r referer]</a>\r
+<a href="#o_t">[-t from]</a>\r
+<br>\r
+<a href="#o_b">[-b blockfile]</a>\r
+<a href="#o_j">[-j jarfile]</a>\r
+<a href="#o_l">[-l logfile]</a>\r
+<br>\r
+<a href="#o_w">[-w NAME=VALUE]</a>\r
+<a href="#o_x">[-x Header_text]</a>\r
+<br>\r
+<a href="#o_h">[-h [bind_host_address][:bind_port]]</a>\r
+<br>\r
+<a href="#o_f">[-f forward_host[:port]]</a>\r
+<a href="#o_d">[-d N]</a>\r
+<br>\r
+<a href="#o_g">[-g gw_protocol[:[gw_host][:gw_port]]]</a>\r
+<br>\r
+(Version 1.4 and earlier)\r
+</p>\r
+\r
+<h3><a name="description" href="/cgi-bin/gp?pg=ijbman&pr=description"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Description\r
+</h3>\r
+<p>\r
+<b><kbd>junkbuster</kbd></b>\r
+is an instrumentable proxy that filters the \r
+<small>HTTP</small>\r
+stream between\r
+web servers and browsers.\r
+Its main purpose is to enhance privacy.\r
+<p>\r
+<a name="dual">Versions before 2.0 used command-line options;</a>\r
+Versions from 2.0 onward use a configuration file.\r
+The following descriptions of the options first give the older\r
+command-line usage, then the new configfile line.\r
+<p>\r
+<a name="won">In Versions 2.0.1 upwards on Windows,</a>\r
+a start-up message is printed and the configuration is read from the file\r
+<big><kbd>junkbstr.ini</kbd></big>\r
+if it exists and no argument was given.\r
+<p>\r
+<a name="reread">All files except the configfile</a>\r
+are checked for changes before each page is fetched,\r
+so they may edited without restarting the proxy.\r
+<h4>Options\r
+</h4>\r
+<dl><p><dt><i><a name="o_b">-b blockfile</a></i><br><a name="blockfile"><tt>blockfile</tt>  <i>blockfile</i></a><dd>\r
+<a href="ijbfaq.html#blocking">Block</a>\r
+requests to\r
+<small>URL</small>s\r
+matching any pattern given in the lines of the\r
+<i>blockfile</i>.\r
+The\r
+<b><kbd>junkbuster</kbd></b>\r
+instead returns status 202, indicating that the request has been accepted\r
+(though not completed),\r
+and a\r
+<a href="ijbfaq.html#show">message identifying itself</a>\r
+(though the browser may\r
+display only a broken image icon).\r
+(Versions before 2.0 returned an error 403 (Forbidden).)\r
+The syntax of a pattern is\r
+<big><kbd>[domain][:port][/path]</kbd></big>\r
+(the\r
+<big><kbd>http://</kbd></big>\r
+or\r
+<big><kbd>https://</kbd></big>\r
+protocol part is omitted).\r
+To decide if a pattern matches a target, the domains are compared first,\r
+then the paths. \r
+<p>\r
+<a name="compare">To compare the domains,</a>\r
+the pattern domain and the target\r
+domain specified in the\r
+<small>URL</small>\r
+are each broken into their components.\r
+(Components are separated by the\r
+<big><kbd>.</kbd></big>\r
+(period) character.)\r
+Next each of the target components\r
+is compared with the corresponding pattern component: last with last,\r
+next-to-last with next-to-last, and so on.\r
+(This is called\r
+<i><dfn>right-anchored</dfn></i>\r
+matching.)\r
+If all of the pattern components find their match in the target,\r
+then the domains are considered a match.\r
+Case is irrelevant when comparing domain components.\r
+<p>\r
+<a name="substring">A successfully</a>\r
+matching pattern can be an anchored substring of a target, but\r
+not vice versa.\r
+Thus if a pattern doesn't specify a domain,\r
+it matches all domains.\r
+<a name="wildcard">Furthermore, when comparing two components,</a>\r
+the components must either match in their entirety or up to a wildcard\r
+<big><kbd>* </kbd></big>\r
+(star character) in the pattern. The wildcard feature\r
+implements only a "prefix" match capability ("abc*" vs. "abcdefg"),\r
+not suffix matching ("*efg" vs. "abcdefg") or\r
+infix matching ("abc*efg" vs. "abcdefg").\r
+The feature is restricted to the domain component;\r
+it is unrelated to the optional\r
+regular expression\r
+feature in the path\r
+<a href="ijbman.html#regex">(described below).</a>\r
+<p>\r
+<a name="numeric">If a numeric port</a>\r
+is specified in the pattern domain, then the target port must\r
+match as well. The default port in a target is port 80.\r
+<p>\r
+<a name="onward">If the domain and port match,</a>\r
+then the target\r
+<small>URL</small>\r
+path is checked for\r
+a match against the path in the pattern.\r
+Paths are compared with a simple case-sensitive\r
+left-anchored substring comparison.\r
+Once again, the pattern can be an\r
+anchored substring of the target, but not vice versa.\r
+A path of\r
+<big><kbd>/</kbd></big>\r
+(slash) would match all paths. Wildcards are not considered in\r
+path comparisons.\r
+<p>\r
+<a name="example">For example, the target</a>\r
+<small>URL</small>\r
+<br>\r
+   <big><kbd>the.yellow-brick-road.com/TinMan/has_no_brain</kbd></big>\r
+<br>\r
+would be matched (and blocked) by the following patterns\r
+<br>\r
+   <big><kbd>yellow-brick-road.com</kbd></big>\r
+<br>\r
+and\r
+<br>\r
+   <big><kbd>Yellow*.COM</kbd></big>\r
+<br>\r
+and\r
+<br>\r
+   <big><kbd>/TinM</kbd></big>\r
+<br>\r
+but not\r
+<br>\r
+   <big><kbd>follow.the.yellow-brick-road.com</kbd></big>\r
+<br>\r
+or\r
+<br>\r
+   <big><kbd>/tinman</kbd></big>\r
+<br>\r
+<p>\r
+<a name="comments">Comments in a blockfile start with a</a>\r
+<big><kbd>#</kbd></big>\r
+(hash) character and end at a new line.\r
+Blank lines are also ignored.\r
+<p>\r
+<a name="except">Lines beginning with a</a>\r
+<big><kbd>~</kbd></big>\r
+(tilde) character are taken to be\r
+<a href="ijbfaq.html#exceptions">exceptions:</a>\r
+a\r
+<small>URL</small>\r
+blocked by previous patterns that matches the rest of\r
+the line is let through. (The last match wins.)\r
+<p>\r
+<a name="regex">Patterns</a>\r
+may contain\r
+<small>POSIX</small>\r
+<a href="ijbfaq.html#regex">regular expressions</a>\r
+provided the\r
+<b><kbd>junkbuster</kbd></b>\r
+was compiled with this option\r
+(the default in Version 2.0 on).\r
+The idiom\r
+<big><kbd>/*.*/ad</kbd></big>\r
+can then be used\r
+to match any\r
+<small>URL</small>\r
+containing\r
+<big><kbd>/ad</kbd></big>\r
+(such as\r
+<big><kbd>http://nomatterwhere.com/images/advert/g3487.gif</kbd></big>\r
+for example).\r
+These expressions\r
+<a href="ijbman.html#substring">don't work</a>\r
+in the domain part.\r
+<p>\r
+<a name="rereads">In version 1.3 and later</a>\r
+the blockfile and cookiefile are checked for changes before each request.\r
+<p><dt><i><a name="o_w">-w NAME=VALUE</a></i><br><a name="wafer"><tt>wafer</tt>  <i>NAME=VALUE</i></a><dd>\r
+Specifies a pair to be sent as a cookie with every request\r
+<a href="ijbfaq.html#wafers">to the server.</a>\r
+(Such boring cookies are called\r
+<i>wafers</i>.)\r
+This option may be called more than once to generate multiple wafers.\r
+The original\r
+Netscape specification\r
+prohibited\r
+semi-colons, commas and white space;\r
+these characters will be\r
+<small>URL</small>-encoded\r
+if used in wafers.\r
+<!-- Aside: genuine cookies are not encoded -->\r
+<!-- Aside: we could use quoted string as specified in the new RFC -->\r
+The Path and Domain attributes are not currently supported.\r
+<p><dt><i><a name="o_c">-c cookiefile</a></i><br><a name="cookiefile"><tt>cookiefile</tt>  <i>cookiefile</i></a><dd>\r
+Enforce the cookie management policy specified in the\r
+<i>cookiefile.</i>\r
+<a name="java">If this option is not used all cookies are silently crunched,</a>\r
+so that users who never want cookies aren't bothered by browsers\r
+asking whether each cookie should be accepted.\r
+However, cookies can\r
+<a href="ijbfaq.html#breakthrough">still get through</a>\r
+via\r
+<a href="links.html#javascript">JavaScript</a>\r
+and\r
+<small>SSL</small>,\r
+so alerts should be left on.\r
+<p>\r
+<a name="dropping">In Version 1.2 and later</a>\r
+this option must be followed by a\r
+<a href="ijbfaq.html#crumble">filename</a>\r
+containing instructions on which sites are allowed to\r
+receive and set cookies.\r
+<a name="drop">By default cookies are dropped in both the browser's request</a>\r
+and the server's response, unless the\r
+<small>URL</small>\r
+requested matches an entry in the\r
+<i>cookiefile</i>.\r
+The matching algorithm is the same as for the blockfile.\r
+A leading\r
+<big><kbd>></kbd></big>\r
+character allows\r
+<a href="ijbfaq.html#directional">server-bound</a>\r
+cookies only;\r
+a\r
+<big><kbd><</kbd></big>\r
+allows only browser-bound cookies;\r
+a\r
+<big><kbd>~</kbd></big>\r
+character stops cookies in\r
+<a href="ijbfaq.html#crumble">both directions.</a>\r
+Thus a cookiefile containing a single line with the two characters\r
+<big><kbd>>*</kbd></big>\r
+will pass on all cookies to servers but not give any new ones to the browser.\r
+<p><dt><i><a name="o_j">-j jarfile</a></i><br><a name="jarfile"><tt>jarfile</tt>  <i>jarfile</i></a><dd>\r
+All Set-cookie attempts by the server are\r
+<a href="ijbfaq.html#jar">logged</a>\r
+to\r
+<i>jarfile</i>.\r
+If no wafer is specified,\r
+one containing a\r
+<a href="ijbfaq.html#notice">canned notice</a>\r
+(the \r
+<i>vanilla wafer</i>)\r
+is added as an alert to the server\r
+unless the\r
+<a href="ijbman.html#suppress-vanilla-wafer">suppress-vanilla-wafer</a>\r
+<!-- Aside: (no vanilla~wafer) -->\r
+option is invoked.\r
+<p><dt><i><a name="o_v">-v</a></i><br><a name="suppress-vanilla-wafer"><tt>suppress-vanilla-wafer</tt></a><dd>\r
+Suppress the vanilla wafer.\r
+<p><dt><i><a name="o_t">-t from</a></i><br><a name="from"><tt>from</tt>  <i>from</i></a><dd>\r
+If the browser\r
+<a href="ijbfaq.html#from">discloses an email address</a>\r
+in the\r
+<big><kbd>FROM</kbd></big>\r
+header (most don't),\r
+replace it with\r
+<i>from.</i>\r
+If\r
+<i>from</i>\r
+is set to\r
+<b>.</b>\r
+(the period character)\r
+the\r
+<big><kbd>FROM</kbd></big>\r
+is passed to the server unchanged.\r
+The default is to delete the\r
+<big><kbd>FROM</kbd></big>\r
+header.\r
+<p><dt><i><a name="o_r">-r referer</a></i><br><a name="referer"><tt>referer</tt>  <i>referer</i></a><dd>\r
+Whenever the browser discloses the\r
+<small>URL</small>\r
+that\r
+<a href="ijbfaq.html#referer">led to</a>\r
+the current request,\r
+replace it with\r
+<i>referer.</i>\r
+If\r
+<i>referer</i>\r
+is set to\r
+<b>.</b>\r
+(period)\r
+the \r
+<small>URL</small>\r
+is passed to the server unchanged.\r
+In \r
+Version <a href="ijbdist.html#c4">1.4</a>\r
+and later, if referer is set to \r
+<b>@</b>\r
+(at) the\r
+<small>URL</small>\r
+is sent in cases where the cookiefile\r
+specifies that a cookie would be sent.\r
+(No way to send bogus referers selectively is provided.)\r
+The default is to delete Referer.\r
+<p>\r
+<a name="referrer">Version 2.0 also accepts the spelling</a>\r
+<big><kbd>referrer</kbd></big>,\r
+which most dictionaries consider correct.\r
+<p><dt><i><a name="o_u">-u user-agent</a></i><br><a name="user-agent"><tt>user-agent</tt>  <i>user-agent</i></a><dd>\r
+Information disclosed by the browser\r
+<a href="ijbfaq.html#agent">about itself</a>\r
+is replaced with the value\r
+<i>user-agent.</i>\r
+If\r
+<i>user-agent</i>\r
+is set to\r
+<b>.</b>\r
+(period)\r
+the\r
+<big><kbd>User-Agent</kbd></big>\r
+header is passed to the server unchanged,\r
+along with any\r
+<big><kbd>UA</kbd></big>\r
+headers produced by\r
+<small>MS-IE</small>\r
+(which would otherwise be deleted).\r
+In \r
+Version <a href="ijbdist.html#c4">1.4</a>\r
+and later, if\r
+<i>user-agent</i>\r
+is set to\r
+<b>@</b>\r
+(at) these headers are sent unchanged in cases where the cookiefile\r
+specifies that a cookie would be sent,\r
+otherwise only default\r
+<big><kbd>User-Agent</kbd></big>\r
+header is sent.\r
+That default\r
+is Mozilla/3.0 (Netscape)\r
+with an unremarkable\r
+<a href="ijbfaq.html#infer">Macintosh</a>\r
+configuration.\r
+If used with a browser less advanced than Mozilla/3.0 or IE-3, the default\r
+may encourage pages containing extensions that confuse the browser.\r
+<!-- Aside: Some servers use extensions to everyone anyway. But in that case it's probably ignoring cookies anyway. Some servers attempt to send cookies only to browsers identifying themselves as Mozilla. -->\r
+<p><dt><i><a name="o_h">-h [host][:port]</a></i><br><a name="listen-address"><tt>listen-address</tt>  <i>[host][:port]</i></a><dd>\r
+If\r
+<i>host</i>\r
+is specified,\r
+bind the\r
+<b><kbd>junkbuster</kbd></b>\r
+to that\r
+<small>IP</small>\r
+address.\r
+If a\r
+<i>port</i>\r
+is specified, use it.\r
+The default\r
+port\r
+is 8000;\r
+the default host is\r
+<big><kbd>localhost</kbd></big>.\r
+Before Version 2.0.2,\r
+the default was to bind to all \r
+<small>IP</small>\r
+addresses\r
+(<big><kbd>INADDR_ANY</kbd></big>);\r
+but this has been restricted to\r
+<big><kbd>localhost</kbd></big>\r
+to avoid unintended security breaches.\r
+(To open the proxy to all, use the line\r
+<br>\r
+   <big><kbd>listen-address :8000</kbd></big>\r
+<br>\r
+in the configuration file.)\r
+<p><dt><i><a name="o_f">-f forward_host[:port]</a></i><br><a name="forwardfile"><tt>forwardfile</tt>  <i>forwardfile</i></a><dd>\r
+Version 1.X required all\r
+<small>HTTP</small>\r
+requests from the client to be forwarded to the same destination.\r
+Version 2.0 takes its routing specification from a\r
+<i>forwardfile</i>,\r
+allowing selection of the proxy (a.k.a. forwarding host) and gateway\r
+according to the\r
+<small>URL</small>.\r
+Here is a typical line.\r
+<br>\r
+<pre>\r
+* lpwa.com:8000 . .\r
+</pre>\r
+<p>\r
+<a name="lines">Each line contains four fields:</a>\r
+<big><kbd>target</kbd></big>,\r
+<big><kbd>forward_to</kbd></big>,\r
+<big><kbd>via_gateway_type</kbd></big>\r
+and\r
+<big><kbd>gateway</kbd></big>.\r
+As usual, the\r
+<a href="ijbman.html#compare">last</a>\r
+<big><kbd>target</kbd></big>\r
+domain that matches the requested\r
+<small>URL</small>\r
+wins,\r
+and the\r
+<big><kbd>*</kbd></big>\r
+character alone matches any domain.\r
+The target domain need not be a fully qualified\r
+hostname; it can be a general domain such as\r
+<big><kbd>com</kbd></big>\r
+or\r
+<big><kbd>co.uk</kbd></big>\r
+or even just a port number.\r
+<a name="nose">For example, because</a>\r
+<a href="http://lpwa.com">LPWA</a>\r
+does not handle\r
+<a href="ijbfaq.html#encrypt">SSL</a>,\r
+the line above will typically be followed by a line such as\r
+<br>\r
+<pre>\r
+:443 . . .\r
+</pre>\r
+to allow SSL transactions to proceed directly.\r
+The cautious would also\r
+add an entry in their blockfile to stop transactions\r
+to port 443 for all but specified trusted sites.\r
+<p>\r
+<a name="forward">If the winning</a>\r
+<big><kbd>forward_to</kbd></big>\r
+field is\r
+<big><kbd>.</kbd></big>\r
+(the dot character) the proxy connects \r
+directly to the server given in the\r
+<small>URL</small>,\r
+otherwise it forwards to the host and port number specified.\r
+The default port is 8000.\r
+The\r
+<big><kbd>via_gateway_type</kbd></big>\r
+and\r
+<big><kbd>gateway</kbd></big>\r
+fields also use a dot to indicate no gateway protocol.\r
+The gateway protocols are explained\r
+<a href="ijbman.html#o_g">below</a>.\r
+<p>\r
+<a name="old">The example line above in a forwardfile alone</a>\r
+would send everything through port 8000 at\r
+<big><kbd>lpwa.com</kbd></big>\r
+with no gateway protocol,\r
+and is equivalent to the old\r
+<big><kbd>-f lpwa.com:8000</kbd></big>\r
+with no\r
+<big><kbd>-g</kbd></big>\r
+option.\r
+For more information see the example file provided with the distribution.\r
+<p>\r
+<a name="loop">Configure with care: no loop detection is performed.</a>\r
+When setting up chains of proxies that might loop back, try adding\r
+<a href="ijbman.html#squid">Squid.</a>\r
+<p><dt><i><a name="o_g">-g gw_protocol[:[gw_host][:gw_port]]</a></i><dd>\r
+Use\r
+<i>gw_protocol</i>\r
+as the gateway protocol.\r
+This option was introduced in Version 1.4,\r
+but was folded into the\r
+<a href="ijbman.html#forwardfile">forwardfile</a>\r
+option in Version 2.0.\r
+The default is to use no gateway protocol;\r
+this may be explicitly specified as\r
+<big><kbd>direct</kbd></big>\r
+on the command line\r
+or the dot character in the forwardfile.\r
+The\r
+<big><kbd>SOCKS4</kbd></big>\r
+protocol may be specified as\r
+<big><kbd>socks</kbd></big>\r
+or\r
+<big><kbd>socks4</kbd></big>.\r
+The\r
+<big><kbd>SOCKS4A</kbd></big>\r
+protocol is specified as\r
+<big><kbd>socks4a</kbd></big>.\r
+The\r
+<big><kbd>SOCKS5</kbd></big>\r
+protocol is not currently supported.\r
+The default\r
+<small>SOCKS</small>\r
+<i>gw_port</i>\r
+is 1080.\r
+<p>\r
+<a name="configure">The user's browser should</a>\r
+<em>not</em>\r
+be\r
+<a href="ijbfaq.html#socks">configured</a>\r
+to use\r
+<big><kbd>SOCKS</kbd></big>;\r
+the proxy conducts the negotiations, not the browser.\r
+<p>\r
+<a name="identify">The user identification capabilities of</a>\r
+<big><kbd>SOCKS4</kbd></big>\r
+are deliberately not used;\r
+the user is always identified to the\r
+<big><kbd>SOCKS</kbd></big>\r
+server as\r
+<big><kbd>userid=anonymous</kbd></big>.\r
+If the server's policy is to reject requests from\r
+<big><kbd>anonymous</kbd></big>,\r
+the proxy will not work.\r
+Use a\r
+<a href="ijbman.html#o_d">debug</a>\r
+value of 3\r
+to see the status returned by the server.\r
+<p><dt><i><a name="o_d">-d N</a></i><br><a name="debug"><tt>debug</tt>  <i>N</i></a><dd>\r
+Set debug mode.\r
+The most common value is 1,\r
+to\r
+<a href="ijbfaq.html#pinpoint">pinpoint</a>\r
+offensive\r
+<small>URL</small>s,\r
+so they can be added to the blockfile.\r
+The value of\r
+<b>N</b>\r
+is a bitwise\r
+logical-<small>OR</small>\r
+of the following values:\r
+<br>\r
+1 = URLs (show each URL requested by the browser);<br>\r
+2 = Connections (show each connection to or from the proxy);<br>\r
+4 = I/O (log I/O errors);<br>\r
+8 = Headers (as each header is scanned, show the header and what is done to it);<br>\r
+16 = Log everything (including debugging traces and the contents of the pages).<br>\r
+<a name="or">Multiple</a>\r
+<big><kbd>debug</kbd></big>\r
+lines are permitted; they are logical OR-ed together.\r
+<p>\r
+<a name="single">Because most browsers send several requests in parallel</a>\r
+the debugging output may appear intermingled, so the\r
+<a href="ijbman.html#single-threaded">single-threaded</a>\r
+option is recommended when using\r
+<a href="ijbman.html#debug">debug</a>\r
+with\r
+<b>N</b>\r
+greater than 1.\r
+<!-- Aside: Yes, it's clumsy, but it's easy to parse. -->\r
+<p><dt><i><a name="o_y">-y</a></i><br><a name="add-forwarded-header"><tt>add-forwarded-header</tt></a><dd>\r
+Add \r
+<big><kbd>X-Forwarded-For</kbd></big>\r
+headers to the server-bound \r
+<small>HTTP</small>\r
+stream\r
+indicating the client \r
+<small>IP</small>\r
+address\r
+<a href="ijbfaq.html#detect">to the server,</a>\r
+in the new style of\r
+<a href="ijbman.html#squid">Squid 1.1.4.</a>\r
+If you want the traditional\r
+<big><kbd>HTTP_FORWARDED</kbd></big>\r
+response header, add it manually with the\r
+<a href="ijbman.html#o_x">-x</a>\r
+option.\r
+<!-- Aside: Not a default, since the end-client usually doesn't wish to be identified, but may be helpful in debugging chains. -->\r
+<p><dt><i><a name="o_x">-x HeaderText</a></i><br><a name="add-header"><tt>add-header</tt>  <i>HeaderText</i></a><dd>\r
+Add the\r
+<i>HeaderText</i>\r
+verbatim to requests to the server.\r
+Typical uses include\r
+adding old-style forwarding notices such as\r
+<big><kbd>Forwarded: by http://pro-privacy-isp.net</kbd></big>\r
+and reinstating the\r
+<big><kbd>Proxy-Connection: Keep-Alive</kbd></big>\r
+header\r
+(which the\r
+<b><kbd>junkbuster</kbd></b>\r
+deletes so as\r
+<a href="ijbfaq.html#detect">not</a>\r
+to reveal its existence).\r
+No checking is done for correctness or plausibility,\r
+so it can be used to throw any old trash into the server-bound \r
+<small>HTTP</small>\r
+stream.\r
+Please don't litter.\r
+<!-- Aside: this represents "more than enough rope" -->\r
+<p><dt><i><a name="o_s">-s</a></i><br><a name="single-threaded"><tt>single-threaded</tt></a><dd>\r
+Doesn't\r
+<big><kbd>fork()</kbd></big>\r
+a separate process\r
+(or create a separate thread)\r
+to handle each connection.\r
+Useful when debugging to keep the process single threaded.\r
+<p><dt><i><a name="o_l">-l logfile</a></i><br><a name="logfile"><tt>logfile</tt>  <i>logfile</i></a><dd>\r
+Write all debugging data into\r
+<i>logfile.</i>\r
+The default\r
+<i>logfile</i>\r
+is the standard output.\r
+<p><dt><br><a name="aclfile"><tt>aclfile</tt>  <i>aclfile</i></a><dd>\r
+Unless this option is used, the proxy talks to anyone who can connect to it,\r
+and everyone who can has equal permissions on where they can go.\r
+An access file allows restrictions to be placed on these two policies,\r
+by distinguishing some\r
+<i><dfn>source</dfn></i>\r
+<small>IP</small>\r
+addresses and/or\r
+some\r
+<i><dfn>destination</dfn></i>\r
+addresses.\r
+(If a\r
+<a href="ijbman.html#forwardfile">forwarder or a gateway</a>\r
+is being used, its address is considered the destination address,\r
+not the ultimate\r
+<small>IP</small>\r
+address of the\r
+<small>URL</small>\r
+requested.)\r
+<p>\r
+<a name="permit">Each line of the access file begins with</a>\r
+either the word\r
+<big><kbd>permit</kbd></big>\r
+or\r
+<big><kbd>deny</kbd></big>\r
+followed by source and (optionally) destination addresses \r
+to be matched against those of the\r
+<small>HTTP</small>\r
+request.\r
+The last matching line specifies the result: if it was a\r
+<big><kbd>deny</kbd></big>\r
+line or if no line matched,\r
+the request will be refused.\r
+<p>\r
+<a name="various">A source or destination</a>\r
+can be specified as a single numeric\r
+<small>IP</small>\r
+address,\r
+or with a hostname, provided that the host's name\r
+can be resolved to a numeric address: this cannot be used to block all\r
+<big><kbd>.mil </kbd></big>\r
+domains for example,\r
+because there is no single address associated with that domain name.\r
+Either form may be followed by a slash and an integer\r
+<big><kbd>N</kbd></big>,\r
+specifying a subnet mask of\r
+<big><kbd>N</kbd></big>\r
+bits.\r
+For example,\r
+<big><kbd>permit 207.153.200.72/24</kbd></big>\r
+matches the entire Class-C subnet from\r
+207.153.200.0\r
+through 207.153.200.255.\r
+(A netmask of 255.255.255.0 corresponds to 24 bits of\r
+ones in the netmask, as with\r
+<big><kbd>*_MASKLEN=24</kbd></big>.)\r
+A value of 16 would be used for a Class-B subnet.\r
+A value of zero for\r
+<big><kbd>N</kbd></big>\r
+in the subnet mask length will cause any address to match;\r
+this can be used to express a default rule.\r
+For more information see the example file provided with the distribution.\r
+<p>\r
+<a name="false">If you like these access controls</a>\r
+you should probably have\r
+<a href="ijbfaq.html#firewall">firewall</a>;\r
+they are not intended to replace one.\r
+<p><dt><br><a name="trustfile"><tt>trustfile</tt>  <i>trustfile</i></a><dd>\r
+This feature is experimental, has not been fully documented and is\r
+very subject to change.\r
+The goal is for parents to be able to choose a page or site whose\r
+links they regard suitable for their\r
+<a href="ijbfaq.html#children">young children</a>\r
+and for the proxy to allow access only to sites mentioned there.\r
+To do this the proxy examines the\r
+<a href="ijbman.html#o_r">referer</a>\r
+variable on each page request to check they resulted from\r
+a click on the ``trusted referer'' site: if so the referred site\r
+is added to a list of trusted sites, so that the child can\r
+then move around that site.\r
+There are several uncertainties in this scheme that experience may be\r
+able to iron out; check back in the months ahead.\r
+<p><dt><br><a name="trust_info_url"><tt>trust_info_url</tt>  <i>trust_info_url</i></a><dd>\r
+When access is denied due to lack of a trusted referer, this\r
+<small>URL</small>\r
+is displayed with a message pointing the user to it for further information.\r
+<p><dt><br><a name="hide-console"><tt>hide-console</tt></a><dd>\r
+In the Windows version only, instructs the program\r
+to disconnect from and hide the command console after starting.\r
+<p><dt><i><a name="o_a">-a</a></i><dd>\r
+(Obsolete) Accept the server's\r
+<big><kbd>Set-cookie</kbd></big>\r
+headers, passing them through to the browser.\r
+<a name="obsolete">This option was removed in Version 1.2</a>\r
+and replaced by an improvement to the\r
+<a href="ijbman.html#o_c">-c</a>\r
+option.\r
+</dl>\r
+</p>\r
+\r
+<h3><a name="install" href="/cgi-bin/gp?pg=ijbman&pr=install"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Installation and Use\r
+</h3>\r
+<p>\r
+Browsers must be told where to find the\r
+<b><kbd>junkbuster</kbd></b>\r
+(e.g.\r
+<big><kbd>localhost</kbd></big>\r
+port 8000).\r
+To set the \r
+<small>HTTP</small>\r
+proxy in Netscape 3.0,\r
+go through:\r
+<b><font face="arial, helvetica">\r
+Options</font></b>;\r
+<b><font face="arial, helvetica">\r
+Network Preferences</font></b>;\r
+<b><font face="arial, helvetica">\r
+Proxies</font></b>;\r
+<b><font face="arial, helvetica">\r
+Manual Proxy Configuration</font></b>;\r
+<b><font face="arial, helvetica">\r
+View</font></b>.\r
+See the\r
+<a href="ijbfaq.html"><small>FAQ</small></a>\r
+for other browsers.\r
+The\r
+<a href="ijbfaq.html#security">Security Proxy</a>\r
+should also be set to the same values,\r
+otherwise\r
+<big><kbd>shttp:</kbd></big>\r
+<small>URL</small>s\r
+won't work.\r
+<p>\r
+<a name="limitations">Note the limitations</a>\r
+explained in the\r
+<a href="ijbfaq.html"><small>FAQ</small></a>.\r
+</p>\r
+\r
+<h3><a name="show" href="/cgi-bin/gp?pg=ijbman&pr=show"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Checking Options\r
+</h3>\r
+<p>\r
+To allow users to\r
+<a href="ijbfaq.html#show">check</a>\r
+that a\r
+<b><kbd>junkbuster</kbd></b>\r
+is running and how it is configured,\r
+it intercepts requests for any\r
+<small>URL</small>\r
+ending in\r
+<big><kbd>/show-proxy-args</kbd></big>\r
+and blocks it,\r
+returning instead returns information on its\r
+version number and\r
+current configuration\r
+including the contents of its blockfile.\r
+To get an explicit warning that no\r
+<b><kbd>junkbuster</kbd></b>\r
+intervened if the proxy was not configured,\r
+it's best to point it to a\r
+<small>URL</small>\r
+that does this, such as\r
+<a href="http://internet.junkbuster.com/cgi-bin/show-proxy-args">http://internet.junkbuster.com/cgi-bin/show-proxy-args</a>\r
+on Junkbusters's website.\r
+</p>\r
+\r
+<h3><a name="also" href="/cgi-bin/gp?pg=ijbman&pr=also"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+See Also\r
+</h3>\r
+<p>\r
+<a href="ijbfaq.html">http://www.junkbusters.com/ht/en/ijbfaq.html</a>\r
+<br>\r
+<a href="cookies.html">http://www.junkbusters.com/ht/en/cookies.html</a>\r
+<br>\r
+<a href="http://internet.junkbuster.com/cgi-bin/show-proxy-args">http://internet.junkbuster.com/cgi-bin/show-proxy-args</a>\r
+<br>\r
+<a name ="kristol" href="http://www.cis.ohio-state.edu/htbin/rfc/rfc2109.html">http://www.cis.ohio-state.edu/htbin/rfc/rfc2109.html</a>\r
+<br>\r
+<a name ="squid" href="http://squid.nlanr.net/Squid/">http://squid.nlanr.net/Squid/</a>\r
+<br>\r
+<a href="http://www-math.uni-paderborn.de/~axel/">http://www-math.uni-paderborn.de/~axel/</a>\r
+</p>\r
+\r
+<h3><a name="copyright" href="/cgi-bin/gp?pg=ijbman&pr=copyright"><img border=0 width=14 height=14 src="/images/fb.gif" alt="<Feedback>"></a> \r
+Copyright and GPL\r
+</h3>\r
+<p>\r
+Written and copyright by the Anonymous Coders and Junkbusters Corporation\r
+and made available under the\r
+<a href="gpl.html">GNU General Public License (GPL).</a>\r
+This software comes with\r
+<a href="gpl.html#nowarr">NO WARRANTY.</a>\r
+Internet Junkbuster\r
+Proxy\r
+is a\r
+<a href="legal.html#marks">trademark</a>\r
+of Junkbusters Corporation.\r
+</p>\r
+<p align="center"><a href="#top_of_page"><img border=0 width=250 height=15 src="/images/top.gif" alt="--- Back to Top of Page ---"></a></p>\r
+<font face="arial, helvetica">\r
+<a rel="begin" href="index.html">Home</a> <font color="#ff0000">\r
+<b> · </b></font>\r
+<a rel="next" href="cookies.html">Next</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="lopt.html">Site Map</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="legal.html">Legal</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="junkdata.html">Privacy</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="cookies.html">Cookies</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="ijb.html">Banner Ads</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="telemarketing.html">Telemarketing</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="junkmail.html">Mail</a>\r
+<font color="#ff0000">\r
+<b> · </b></font><a href="junkemail.html">Spam</a>\r
+\r
+</font><form action="/cgi-bin/search" method="GET">\r
+<input type="text" name="q" size=60 maxlength=120 value="">\r
+<input type="submit" value="Search"></form>\r
+<small>\r
+<small>\r
+<p>\r
+<a href="legal.html#copy">Copyright</a> © 1996-8 Junkbusters\r
+<a href="legal.html#marks">®</a> Corporation.\r
+Copying and distribution permitted under\r
+the <a href="gpl.html"><small>GNU</small></a>\r
+General Public License.\r
+</small>\r
+<tt>\r
+1998/10/31\r
+http://www.junkbusters.com/ht/en/ijbman.html\r
+</tt>\r
+<address><kbd>webmaster@junkbusters.com</kbd></address>\r
+</small>\r
+</body>\r
+</html>\r
--- /dev/null
+const char encode_rcs[] = "$Id: encode.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/encode.c,v $
+ *
+ * Purpose : Functions to encode and decode URLs, and also to
+ * encode cookies and HTML text.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: encode.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+\r
+#include "encode.h"
+
+const char encode_h_rcs[] = ENCODE_H_VERSION;
+
+/* Maps special characters in a URL to their equivalent % codes. */
+static const char * const url_code_map[256] = {
+ NULL, "%01", "%02", "%03", "%04", "%05", "%06", "%07", "%08", "%09",
+ "%0A", "%0B", "%0C", "%0D", "%0E", "%0F", "%10", "%11", "%12", "%13",
+ "%14", "%15", "%16", "%17", "%18", "%19", "%1A", "%1B", "%1C", "%1D",
+ "%1E", "%1F", "+", "%21", "%22", "%23", "%24", "%25", "%26", "%27",
+ "%28", "%29", NULL, "%2B", "%2C", NULL, NULL, "%2F", NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "%3A", "%3B",
+ "%3C", "%3D", "%3E", "%3F", NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, "%5B", "%5C", "%5D", "%5E", NULL, "%60", NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, "%7B", "%7C", "%7D", "%7E", "%7F", "%80", "%81",
+ "%82", "%83", "%84", "%85", "%86", "%87", "%88", "%89", "%8A", "%8B",
+ "%8C", "%8D", "%8E", "%8F", "%90", "%91", "%92", "%93", "%94", "%95",
+ "%96", "%97", "%98", "%99", "%9A", "%9B", "%9C", "%9D", "%9E", "%9F",
+ "%A0", "%A1", "%A2", "%A3", "%A4", "%A5", "%A6", "%A7", "%A8", "%A9",
+ "%AA", "%AB", "%AC", "%AD", "%AE", "%AF", "%B0", "%B1", "%B2", "%B3",
+ "%B4", "%B5", "%B6", "%B7", "%B8", "%B9", "%BA", "%BB", "%BC", "%BD",
+ "%BE", "%BF", "%C0", "%C1", "%C2", "%C3", "%C4", "%C5", "%C6", "%C7",
+ "%C8", "%C9", "%CA", "%CB", "%CC", "%CD", "%CE", "%CF", "%D0", "%D1",
+ "%D2", "%D3", "%D4", "%D5", "%D6", "%D7", "%D8", "%D9", "%DA", "%DB",
+ "%DC", "%DD", "%DE", "%DF", "%E0", "%E1", "%E2", "%E3", "%E4", "%E5",
+ "%E6", "%E7", "%E8", "%E9", "%EA", "%EB", "%EC", "%ED", "%EE", "%EF",
+ "%F0", "%F1", "%F2", "%F3", "%F4", "%F5", "%F6", "%F7", "%F8", "%F9",
+ "%FA", "%FB", "%FC", "%FD", "%FE", "%FF"
+};
+
+/* Maps special characters in HTML to their equivalent entites. */
+static const char * const html_code_map[256] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,""",NULL,NULL,NULL,"&",NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "<",NULL,">",NULL,NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+/* Maps special characters in a cookie to their equivalent % codes. */
+static const char * const cookie_code_map[256] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, "+", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, "%2C",NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "%3B",
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+
+/*********************************************************************
+ *
+ * Function : html_encode
+ *
+ * Description : Encodes a string so it's not interpreted as
+ * containing HTML tags or entities.
+ * Replaces <, >, &, and " with the appropriate HTML
+ * entities.
+ *
+ * Parameters :
+ * 1 : s = String to encode. Null-terminated.
+ *
+ * Returns : Encoded string, newly allocated on the heap.
+ * Caller is responsible for freeing it with free().
+ *
+ *********************************************************************/
+char * html_encode(const char *s)
+{
+ /* each input char can expand to at most 6 chars */
+ char * buf = (char *) malloc((strlen(s) * 6) + 1);
+
+ if (buf)
+ {
+ char c;
+ char * p = buf;
+ while ( (c = *s++) != '\0')
+ {
+ const char * replace_with = html_code_map[(unsigned char) c];
+ if(replace_with != NULL)
+ {
+ strcpy(p, replace_with);
+ p += strlen(replace_with);
+ }
+ else
+ {
+ *p++ = c;
+ }
+ }
+
+ *p = '\0';
+ }
+
+ return(buf);
+}
+
+/*********************************************************************
+ *
+ * Function : cookie_encode
+ *
+ * Description : Encodes a string so it can be used in a cookie.
+ * Replaces " ", ",", and ";" with the appropriate
+ * codes.
+ *
+ * Parameters :
+ * 1 : s = String to encode. Null-terminated.
+ *
+ * Returns : Encoded string, newly allocated on the heap.
+ * Caller is responsible for freeing it with free().
+ *
+ *********************************************************************/
+char * cookie_encode(const char *s)
+{
+ /* each input char can expand to at most 3 chars */
+ char * buf = (char *) malloc((strlen(s) * 3) + 1);
+
+ if (buf)
+ {
+ char c;
+ char * p = buf;
+ while ( (c = *s++) != '\0')
+ {
+ const char * replace_with = cookie_code_map[(unsigned char) c];
+ if (replace_with != NULL)
+ {
+ strcpy(p, replace_with);
+ p += strlen(replace_with);
+ }
+ else
+ {
+ *p++ = c;
+ }
+ }
+
+ *p = '\0';
+ }
+
+ return(buf);
+}
+
+/*********************************************************************
+ *
+ * Function : url_encode
+ *
+ * Description : Encodes a string so it can be used in a URL
+ * query string. Replaces special characters with\r
+ * the appropriate %xx codes.
+ *
+ * Parameters :
+ * 1 : s = String to encode. Null-terminated.
+ *
+ * Returns : Encoded string, newly allocated on the heap.
+ * Caller is responsible for freeing it with free().
+ *
+ *********************************************************************/
+char * url_encode(const char *s)
+{\r
+ /* each input char can expand to at most 3 chars */\r
+ char * buf = (char *) malloc((strlen(s) * 3) + 1);
+\r
+ if (buf)
+ {\r
+ char c;
+ char * p = buf;
+ while( (c = *s++) != '\0')
+ {
+ const char * replace_with = url_code_map[(unsigned char) c];
+ if (replace_with != NULL)
+ {
+ strcpy(p, replace_with);
+ p += strlen(replace_with);
+ }
+ else
+ {
+ *p++ = c;
+ }
+ }
+
+ *p = '\0';
+\r
+ }
+\r
+ return(buf);
+}
+
+
+/*********************************************************************
+ *
+ * Function : xdtoi
+ *
+ * Description : Converts a single hex digit to an integer.
+ *
+ * Parameters :
+ * 1 : d = in the range of ['0'..'9', 'A'..'F', 'a'..'f']
+ *
+ * Returns : The integer value, or -1 for non-hex characters.
+ *
+ *********************************************************************/
+static int xdtoi(char d)
+{
+ if ((d >= '0') && (d <= '9'))
+ {
+ return(d - '0');
+ }
+ else if ((d >= 'a') && (d <= 'f'))
+ {
+ return(d - 'a' + 10);
+ }
+ else if ((d >= 'A') && (d <= 'F'))
+ {
+ return(d - 'A' + 10);
+ }
+ else
+ {
+ return(-1);
+ }
+}
+
+
+/*********************************************************************
+ *
+ * Function : xtoi
+ *
+ * Description : Hex string to integer conversion.
+ *
+ * Parameters :
+ * 1 : s = a 2 digit hex string (e.g. "1f"). Only the
+ * first two characters will be looked at.
+ *
+ * Returns : The integer value, or 0 for non-hex strings.
+ *
+ *********************************************************************/
+static int xtoi(const char *s)
+{
+ int d1, d2;
+
+ d1 = xdtoi(*s++);
+ if(d1 >= 0)
+ {
+ d2 = xdtoi(*s);
+ if(d2 >= 0)
+ {
+ return (d1 << 4) + d2;
+ }
+ }
+
+ return 0;
+}
+
+
+/*********************************************************************
+ *
+ * Function : url_decode
+ *
+ * Description : Decodes a URL query string, replacing %xx codes
+ * with their decoded form.
+ *
+ * Parameters :
+ * 1 : s = String to decode. Null-terminated.
+ *
+ * Returns : Decoded string, newly allocated on the heap.
+ * Caller is responsible for freeing it with free().
+ *
+ *********************************************************************/
+char *url_decode(const char * s)
+{
+ char *buf = malloc(strlen(s) + 1);
+ char *q = buf;
+\r
+ if (buf)\r
+ {\r
+ while (*s)
+ {
+ switch (*s)
+ {
+ case '+':
+ s++;
+ *q++ = ' ';
+ break;
+
+ case '%':
+ if ((*q = xtoi(s + 1)))
+ {
+ s += 3;
+ q++;
+ }
+ else
+ {
+ /* malformed, just use it */
+ *q++ = *s++;
+ }
+ break;
+
+ default:
+ *q++ = *s++;
+ break;
+ }
+ }
+ *q = '\0';\r
+ }
+\r
+ return(buf);
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _ENCODE_H
+#define _ENCODE_H
+#define ENCODE_H_VERSION "$Id: encode.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/encode.h,v $
+ *
+ * Purpose : Functions to encode and decode URLs, and also to
+ * encode cookies and HTML text.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: encode.h,v $
+ *
+ *********************************************************************/
+\f
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char * html_encode(const char *s);
+extern char * cookie_encode(const char *s);
+extern char * url_encode(const char *s);
+extern char * url_decode(const char *str);
+
+/* Revision control strings from this header and associated .c file */
+extern const char encode_rcs[];
+extern const char encode_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _ENCODE_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+const char errlog_rcs[] = "$Id: errlog.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/errlog.c,v $
+ *
+ * Purpose : Log errors to a designated destination in an elegant,
+ * printf-like fashion.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: errlog.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif /* ndef _WIN32 */
+
+#include <errno.h>
+/* #include <pthread.h> */
+
+#ifdef _WIN32
+#include <windows.h>
+#include "w32log.h"
+#endif /* def _WIN32 */
+
+#include "errlog.h"
+#include "project.h"
+
+const char errlog_h_rcs[] = ERRLOG_H_VERSION;
+
+/* LOG_LEVEL_ERROR and LOG_LEVEL_INFO cannot be turned off */
+#define LOG_LEVEL_MINIMUM (LOG_LEVEL_ERROR | LOG_LEVEL_INFO)
+
+/* where to log (default: stderr) */
+static FILE *logfp = NULL;
+
+/* where to log (NULL == stderr) */
+static char * logfilename = NULL;
+
+/* logging detail level. */
+static int debug = LOG_LEVEL_MINIMUM;
+
+
+/*********************************************************************
+ *
+ * Function : init_errlog
+ *
+ * Description : Initializes the logging module. Must call before
+ * calling log_error.
+ *
+ * Parameters :
+ * 1 : prog_name = The program name.
+ * 2 : logfname = The logfile name, or NULL for stderr.
+ * 3 : debuglevel = The debugging level.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void init_error_log(const char *prog_name, const char *logfname, int debuglevel)
+{
+ FILE *fp;
+
+ /* FIXME RACE HAZARD: should start critical section error_log_use here */
+
+ /* set the logging detail level */
+ debug = debuglevel | LOG_LEVEL_MINIMUM;
+
+ if ((logfp != NULL) && (logfp != stderr))
+ {
+ fclose(logfp);
+ }
+ logfp = stderr;
+
+ /* set the designated log file */
+ if( logfname )
+ {
+ if( !(fp = fopen(logfname, "a")) )
+ {
+ log_error(LOG_LEVEL_ERROR, "init_errlog(): can't open logfile: %s", logfname);
+#if defined(_WIN32) && ! defined (_WIN_CONSOLE)
+ MessageBox(NULL, "init_errlog(): can't open logfile", "Internet JunkBuster Error",
+ MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST);
+#endif /* defined(_WIN32) && ! defined (_WIN_CONSOLE) */
+ exit(1);
+ }
+
+ /* set logging to be completely unbuffered */
+ setbuf(fp, NULL);
+
+ logfp = fp;
+ }
+
+ log_error(LOG_LEVEL_INFO, "Internet JunkBuster version " VERSION);
+ if (prog_name != NULL)
+ {
+ log_error(LOG_LEVEL_INFO, "Program name: %s", prog_name);
+ }
+
+ /* FIXME RACE HAZARD: should end critical section error_log_use here */
+
+} /* init_error_log */
+
+
+/*********************************************************************
+ *
+ * Function : log_error
+ *
+ * Description : This is the error-reporting and logging function.
+ *
+ * Parameters :
+ * 1 : loglevel = the type of message to be logged
+ * 2 : fmt = the main string we want logged, printf-like
+ * 3 : ... = arguments to be inserted in fmt (printf-like).
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void log_error(int loglevel, char *fmt, ...)
+{
+ va_list ap;
+ char outbuf[BUFSIZ];
+ char * src = fmt;
+ int outc = 0;
+ long this_thread = 1; /* was: pthread_t this_thread;*/
+
+ /* verify if loglevel applies to current settings and bail out if negative */
+ if(!(loglevel & debug))
+ {
+ return;
+ }
+
+ /* FIXME get current thread id */
+ /* this_thread = (long)pthread_self(); */
+
+ switch (loglevel)
+ {
+ case LOG_LEVEL_ERROR:
+ outc = sprintf(outbuf, "IJB(%d) Error: ", this_thread);
+ break;
+ case LOG_LEVEL_GPC:
+ outc = sprintf(outbuf, "IJB(%d) Request: ", this_thread);
+ break;
+ case LOG_LEVEL_CONNECT:
+ outc = sprintf(outbuf, "IJB(%d) Connect: ", this_thread);
+ break;
+ case LOG_LEVEL_HEADER:
+ outc = sprintf(outbuf, "IJB(%d) Header: ", this_thread);
+ break;
+ case LOG_LEVEL_INFO:
+ outc = sprintf(outbuf, "IJB(%d) Info: ", this_thread);
+ break;
+ default:
+ outc = sprintf(outbuf, "IJB(%d) UNKNOWN LOG TYPE(%d): ", this_thread, loglevel);
+ break;
+ }
+
+ /* get ready to scan var. args. */
+ va_start( ap, fmt );
+
+ /* build formatted message from fmt and var-args */
+ while ((*src) && (outc < BUFSIZ-2))
+ {
+ char tempbuf[BUFSIZ];
+ char *sval;
+ int ival;
+ unsigned uval;
+ long lval;
+ unsigned long ulval;
+ int oldoutc;
+ char ch;
+
+ ch = *src++;
+ if( ch != '%' )
+ {
+ outbuf[outc++] = ch;
+ continue;
+ }
+
+ ch = *src++;
+ switch (ch) {
+ case '%':
+ outbuf[outc++] = '%';
+ break;
+ case 'd':
+ ival = va_arg( ap, int );
+ oldoutc = outc;
+ outc += sprintf(tempbuf, "%d", ival);
+ if (outc < BUFSIZ-1)
+ {
+ strcpy(outbuf + oldoutc, tempbuf);
+ }
+ else
+ {
+ outbuf[oldoutc] = '\0';
+ }
+ break;
+ case 'u':
+ uval = va_arg( ap, unsigned );
+ oldoutc = outc;
+ outc += sprintf(tempbuf, "%u", uval);
+ if (outc < BUFSIZ-1)
+ {
+ strcpy(outbuf + oldoutc, tempbuf);
+ }
+ else
+ {
+ outbuf[oldoutc] = '\0';
+ }
+ break;
+ case 'l':
+ /* this is a modifier that must be followed by u or d */
+ ch = *src++;
+ if (ch == 'd')
+ {
+ lval = va_arg( ap, long );
+ oldoutc = outc;
+ outc += sprintf(tempbuf, "%ld", lval);
+ }
+ else if (ch == 'u')
+ {
+ ulval = va_arg( ap, unsigned long );
+ oldoutc = outc;
+ outc += sprintf(tempbuf, "%lu", ulval);
+ }
+ else
+ {
+ /* Error */
+ sprintf(outbuf, "IJB(%d) Error: log_error(): Bad format string:\n"
+ "Format = \"%s\"\n"
+ "Exiting.", this_thread, fmt);
+ /* FIXME RACE HAZARD: should start critical section error_log_use here */
+ if( !logfp )
+ {
+ logfp = stderr;
+ }
+ fputs(outbuf, logfp);
+ /* FIXME RACE HAZARD: should end critical section error_log_use here */
+#if defined(_WIN32) && ! defined (_WIN_CONSOLE)
+ MessageBox(NULL, outbuf, "Internet JunkBuster Error",
+ MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST);
+#endif /* defined(_WIN32) && ! defined (_WIN_CONSOLE) */
+ exit(1);
+ break;
+ }
+ if (outc < BUFSIZ-1)
+ {
+ strcpy(outbuf + oldoutc, tempbuf);
+ }
+ else
+ {
+ outbuf[oldoutc] = '\0';
+ }
+ break;
+ case 'c':
+ /*
+ * Note that char paramaters are converted to int, so we need to
+ * pass "int" to va_arg. (See K&R, 2nd ed, section A7.3.2, page 202)
+ */
+ outbuf[outc++] = (char) va_arg( ap, int );
+ break;
+ case 's':
+ sval = va_arg( ap, char * );
+ oldoutc = outc;
+ outc += strlen(sval);
+ if (outc < BUFSIZ-1)
+ {
+ strcpy(outbuf + oldoutc, sval);
+ }
+ else
+ {
+ outbuf[oldoutc] = '\0';
+ }
+ break;
+ case 'E':
+ /* Non-standard: Print error code from errno */
+ ival = errno;
+#ifndef NOSTRERROR
+ sval = strerror(ival);
+#else /* def NOSTRERROR */
+ sval = NULL
+#endif /* def NOSTRERROR */
+ if (sval == NULL)
+ {
+ sprintf(tempbuf, "(errno = %d)", ival);
+ sval = tempbuf;
+ }
+ oldoutc = outc;
+ outc += strlen(sval);
+ if (outc < BUFSIZ-1)
+ {
+ strcpy(outbuf + oldoutc, sval);
+ }
+ else
+ {
+ outbuf[oldoutc] = '\0';
+ }
+ break;
+ default:
+ sprintf(outbuf, "IJB(%d) Error: log_error(): Bad format string:\n"
+ "Format = \"%s\"\n"
+ "Exiting.", this_thread, fmt);
+ /* FIXME RACE HAZARD: should start critical section error_log_use here */
+ if( !logfp )
+ {
+ logfp = stderr;
+ }
+ fputs(outbuf, logfp);
+ /* FIXME RACE HAZARD: should end critical section error_log_use here */
+#if defined(_WIN32) && ! defined (_WIN_CONSOLE)
+ MessageBox(NULL, outbuf, "Internet JunkBuster Error",
+ MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST);
+#endif /* defined(_WIN32) && ! defined (_WIN_CONSOLE) */
+ exit(1);
+ break;
+
+ } /* switch( p ) */
+
+ } /* for( p ... ) */
+
+ /* done with var. args */
+ va_end( ap );
+
+ if (outc >= BUFSIZ-2)
+ {
+ /* insufficient room for newline and trailing null. */
+
+ static const char warning[] = "... [too long, truncated]\n";
+
+ if (outc < BUFSIZ)
+ {
+ /* Need to add terminating null in this case. */
+ outbuf[outc] = '\0';
+ }
+
+ /* Truncate output */
+ outbuf[BUFSIZ - sizeof(warning)] = '\0';
+
+ /* Append warning */
+ strcat(outbuf, warning);
+ }
+ else
+ {
+ /* Add terminating newline and null */
+ outbuf[outc++] = '\n';
+ outbuf[outc] = '\0';
+ }
+
+ /* FIXME RACE HAZARD: should start critical section error_log_use here */
+
+ /* deal with glibc stupidity - it won't let you initialize logfp */
+ if( !logfp )
+ {
+ logfp = stderr;
+ }
+
+ fputs(outbuf, logfp);
+
+ /* FIXME RACE HAZARD: should end critical section error_log_use here */
+
+#if defined(_WIN32) && !defined(_WIN_CONSOLE)
+ /* Write to display */
+ LogPutString(outbuf);
+ LogShowActivity();
+#endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
+
--- /dev/null
+#ifndef _ERRLOG_H
+#define _ERRLOG_H
+#define ERRLOG_H_VERSION "$Id: errlog.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/errlog.h,v $
+ *
+ * Purpose : Log errors to a designated destination in an elegant,
+ * printf-like fashion.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: errlog.h,v $
+ *
+ *********************************************************************/
+\f
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Debug level for errors */
+
+#define LOG_LEVEL_GPC 0x0001
+#define LOG_LEVEL_CONNECT 0x0002
+#define LOG_LEVEL_IO 0x0004
+#define LOG_LEVEL_HEADER 0x0008
+#define LOG_LEVEL_LOG 0x0010
+#ifdef PCRS
+#define LOG_LEVEL_FRC 0x0020
+#define LOG_LEVEL_REF 0x0040
+#endif /* def PCRS */
+
+/* Following are always on: */
+#define LOG_LEVEL_ERROR 0x1000
+#define LOG_LEVEL_INFO 0x2000
+
+extern void init_error_log(const char *prog_name, const char *logfname, int debuglevel);
+extern void log_error(int loglevel, char *fmt, ...);
+
+/* Revision control strings from this header and associated .c file */
+extern const char errlog_rcs[];
+extern const char errlog_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _ERRLOG_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
+
--- /dev/null
+const char filters_rcs[] = "$Id: filters.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/filters.c,v $
+ *
+ * Purpose : Declares functions to parse/crunch headers and pages.
+ * Functions declared include:
+ * `acl_addr', `add_stats', `block_acl', `block_imageurl',
+ * `block_url', `cookie_url', `domaincmp', `dsplit',
+ * `filter_popups', `forward_url',
+ * `ij_untrusted_url', `intercept_url', `re_process_buffer',
+ * `show_proxy_args', and `trust_url'
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: filters.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#include <netinet/in.h>
+#else
+#include <winsock2.h>
+#endif
+
+#include "project.h"
+#include "filters.h"
+#include "encode.h"
+#include "jcc.h"
+#include "showargs.h"
+#include "parsers.h"
+#include "ssplit.h"
+#include "gateway.h"
+#include "jbsockets.h"
+#include "errlog.h"
+#include "jbsockets.h"
+
+#ifdef _WIN32
+#include "win32.h"
+#endif
+
+const char filters_h_rcs[] = FILTERS_H_VERSION;
+
+/* Fix a problem with Solaris. There should be no effect on other
+ * platforms.
+ * Solaris's isspace() is a macro which uses it's argument directly
+ * as an array index. Therefore we need to make sure that high-bit
+ * characters generate +ve values, and ideally we also want to make
+ * the argument match the declared parameter type of "int".
+ */
+#define ijb_isdigit(__X) isdigit((int)(unsigned char)(__X))
+
+
+static const char CBLOCK[] =
+#ifdef AMIGA
+ "HTTP/1.0 403 Request for blocked URL\n"
+#else /* ifndef AMIGA */
+ "HTTP/1.0 202 Request for blocked URL\n"
+#endif /* ndef AMIGA */
+ "Pragma: no-cache\n"
+ "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMT\n"
+ "Expires: Thu Jul 31, 1997 07:42:22 pm GMT\n"
+ "Content-Type: text/html\n\n"
+ "<html>\n"
+ "<head>\n"
+ "<title>Internet Junkbuster: Request for blocked URL</title>\n"
+ "</head>\n"
+ WHITEBG
+ "<center><h1>"
+ BANNER
+ "</h1></center>\n"
+ "<p align=center>Your request for <b>%s%s</b><br>\n"
+ "was blocked because it matches the following pattern "
+ "in the blockfile: <b>%s</b>\n</p>"
+#ifdef FORCE_LOAD
+ "<p align=center><a href=\"http://" FORCE_PREFIX
+ "%s%s\">Go there anyway.</a></p>"
+#endif /* def FORCE_LOAD */
+ "</body>\n"
+ "</html>\n";
+
+#ifdef TRUST_FILES
+static const char CTRUST[] =
+#ifdef AMIGA
+ "HTTP/1.0 403 Request for untrusted URL\n"
+#else /* ifndef AMIGA */
+ "HTTP/1.0 202 Request for untrusted URL\n"
+#endif /* ndef AMIGA */
+ "Pragma: no-cache\n"
+ "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMT\n"
+ "Expires: Thu Jul 31, 1997 07:42:22 pm GMT\n"
+ "Content-Type: text/html\n\n"
+ "<html>\n"
+ "<head>\n"
+ "<title>Internet Junkbuster: Request for untrusted URL</title>\n"
+ "</head>\n"
+ WHITEBG
+ "<center>"
+ "<a href=http://internet.junkbuster.com/ij-untrusted-url?%s+%s+%s>"
+ BANNER
+ "</a>"
+ "</center>"
+ "</body>\n"
+ "</html>\n";
+#endif /* def TRUST_FILES */
+
+
+#ifdef ACL_FILES
+/*********************************************************************
+ *
+ * Function : block_acl
+ *
+ * Description : Block this request?
+ * Decide yes or no based on ACL file.
+ *
+ * Parameters :
+ * 1 : src = Address the browser/user agent is requesting.
+ * 2 : dst = The proxy or gateway address this is going to.
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 = FALSE (don't block) and 1 = TRUE (do block)
+ *
+ *********************************************************************/
+int block_acl(struct access_control_addr *src, struct access_control_addr *dst, struct client_state *csp)
+{
+ struct file_list *fl;
+ struct access_control_list *a, *acl;
+ struct access_control_addr s[1], d[1];
+
+ /* if not using an access control list, then permit the connection */
+ if (((fl = csp->alist) == NULL) || ((acl = fl->f) == NULL))
+ {
+ return(0);
+ }
+
+ /* search the list */
+ for (a = acl->next ; a ; a = a->next)
+ {
+ *s = *src;
+ *d = *dst;
+
+ s->addr &= a->src->mask;
+ d->addr &= a->dst->mask;
+
+ if ((s->addr == a->src->addr)
+ && (d->addr == a->dst->addr)
+ && ((s->port == a->src->port)
+ || (s->port == 0)
+ || (a->src->port == 0))
+ && ((d->port == a->dst->port)
+ || (d->port == 0)
+ || (a->dst->port == 0)))
+ {
+ if (a->action == ACL_PERMIT)
+ {
+ return(0);
+ }
+ else
+ {
+ return(1);
+ }
+ }
+ }
+
+ return(1);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : acl_addr
+ *
+ * Description : Called from `load_aclfile'. FIXME: I can't say more.
+ *
+ * Parameters :
+ * 1 : aspec = (what?)
+ * 2 : aca = (what?)
+ *
+ * Returns : 0 => Ok, everything else is an error.
+ *
+ *********************************************************************/
+int acl_addr(char *aspec, struct access_control_addr *aca)
+{
+ int i, masklength, port;
+ char *p;
+
+ masklength = 32;
+ port = 0;
+
+ if ((p = strchr(aspec, '/')))
+ {
+ *p++ = '\0';
+
+ if (ijb_isdigit(*p) == 0)
+ {
+ return(-1);
+ }
+ masklength = atoi(p);
+ }
+
+ if ((masklength < 0) || (masklength > 32))
+ {
+ return(-1);
+ }
+
+ if ((p = strchr(aspec, ':')))
+ {
+ *p++ = '\0';
+
+ if (ijb_isdigit(*p) == 0)
+ {
+ return(-1);
+ }
+ port = atoi(p);
+ }
+
+ aca->port = port;
+
+ aca->addr = ntohl(resolve_hostname_to_ip(aspec));
+
+ if (aca->addr == -1)
+ {
+ log_error(LOG_LEVEL_ERROR, "can't resolve address for %s", aspec);
+ return(-1);
+ }
+
+ /* build the netmask */
+ aca->mask = 0;
+ for (i=1; i <= masklength ; i++)
+ {
+ aca->mask |= (1 << (32 - i));
+ }
+
+ /* now mask off the host portion of the ip address
+ * (i.e. save on the network portion of the address).
+ */
+ aca->addr = aca->addr & aca->mask;
+
+ return(0);
+
+}
+#endif /* def ACL_FILES */
+
+
+/*********************************************************************
+ *
+ * Function : block_url
+ *
+ * Description : Called from `chat'. Check to see if we need to block this.
+ *
+ * Parameters :
+ * 1 : http = http_request request to "check" for blocked
+ * 2 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : NULL => unblocked, else string to HTML block description.
+ *
+ *********************************************************************/
+char *block_url(struct http_request *http, struct client_state *csp)
+{
+ struct file_list *fl;
+ struct block_spec *b;
+ struct url_spec url[1];
+ char *p;
+ int n;
+
+ if (((fl = csp->blist) == NULL) || ((b = fl->f) == NULL))
+ {
+ return(NULL);
+ }
+
+ *url = dsplit(http->host);
+
+ /* if splitting the domain fails, punt */
+ if (url->dbuf == NULL) return(NULL);
+
+ for (b = b->next; b ; b = b->next)
+ {
+ if ((b->url->port == 0) || (b->url->port == http->port))
+ {
+ if ((b->url->domain[0] == '\0') || (domaincmp(b->url, url) == 0))
+ {
+ if ((b->url->path == NULL) ||
+#ifdef REGEX
+ (regexec(b->url->preg, http->path, 0, NULL, 0) == 0)
+#else
+ (strncmp(b->url->path, http->path, b->url->pathlen) == 0)
+#endif
+ )
+ {
+ freez(url->dbuf);
+ freez(url->dvec);
+
+ if (b->reject == 0) return(NULL);
+
+ n = strlen(CBLOCK);
+ n += strlen(http->hostport);
+ n += strlen(http->path);
+ n += strlen(b->url->spec);
+#ifdef FORCE_LOAD
+ n += strlen(http->hostport);
+ n += strlen(http->path);
+#endif /* def FORCE_LOAD */
+
+ p = (char *)malloc(n);
+
+#ifdef FORCE_LOAD
+ sprintf(p, CBLOCK, http->hostport, http->path, b->url->spec, http->hostport, http->path);
+#else
+ sprintf(p, CBLOCK, http->hostport, http->path, b->url->spec);
+#endif /* def FORCE_LOAD */
+
+ return(p);
+ }
+ }
+ }
+ }
+ freez(url->dbuf);
+ freez(url->dvec);
+ return(NULL);
+
+}
+
+
+#if defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST)
+/*********************************************************************
+ *
+ * Function : block_imageurl
+ *
+ * Description : Given a URL which is blocked, decide whether to
+ * send the "blocked" image or HTML.
+ *
+ * Parameters :
+ * 1 : http = URL to check.
+ * 2 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : True (nonzero) if URL is in image list, false (0)
+ * otherwise
+ *
+ *********************************************************************/
+int block_imageurl(struct http_request *http, struct client_state *csp)
+{
+#ifdef DETECT_MSIE_IMAGES
+ if ((csp->accept_types
+ & (ACCEPT_TYPE_IS_MSIE|ACCEPT_TYPE_MSIE_IMAGE|ACCEPT_TYPE_MSIE_HTML))
+ == (ACCEPT_TYPE_IS_MSIE|ACCEPT_TYPE_MSIE_IMAGE))
+ {
+ return 1;
+ }
+ else if ((csp->accept_types
+ & (ACCEPT_TYPE_IS_MSIE|ACCEPT_TYPE_MSIE_IMAGE|ACCEPT_TYPE_MSIE_HTML))
+ == (ACCEPT_TYPE_IS_MSIE|ACCEPT_TYPE_MSIE_HTML))
+ {
+ return 0;
+ }
+#endif
+
+#if defined(USE_IMAGE_LIST)
+ return block_imageurl_using_imagelist(http, csp);
+#else
+ /* Don't know - assume HTML */
+ return 0;
+#endif
+}
+#endif /* defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST) */
+
+
+#ifdef USE_IMAGE_LIST
+/*********************************************************************
+ *
+ * Function : block_imageurl
+ *
+ * Description : Test if a URL is in the imagelist.
+ *
+ * Parameters :
+ * 1 : http = URL to check.
+ * 2 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : True (nonzero) if URL is in image list, false (0)
+ * otherwise
+ *
+ *********************************************************************/
+int block_imageurl_using_imagelist(struct http_request *http, struct client_state *csp)
+{
+ struct file_list *fl;
+ struct block_spec *b;
+ struct url_spec url[1];
+
+ if (((fl = csp->ilist) == NULL) || ((b = fl->f) == NULL))
+ {
+ return(0);
+ }
+
+ *url = dsplit(http->host);
+
+ /* if splitting the domain fails, punt */
+ if (url->dbuf == NULL) return(0);
+
+ for (b = b->next; b ; b = b->next)
+ {
+
+ if ((b->url->port == 0) || (b->url->port == http->port))
+ {
+ /* port matches, check domain */
+ if ((b->url->domain[0] == '\0') || (domaincmp(b->url, url) == 0))
+ {
+ /* domain matches, check path */
+ if ((b->url->path == NULL) ||
+#ifdef REGEX
+ (regexec(b->url->preg, http->path, 0, NULL, 0) == 0)
+#else
+ (strncmp(b->url->path, http->path, b->url->pathlen) == 0)
+#endif
+ )
+ {
+ /* Matches */
+ freez(url->dbuf);
+ freez(url->dvec);
+
+ if (b->reject == 0) return(0);
+
+ return(1);
+ }
+ }
+ }
+ }
+ freez(url->dbuf);
+ freez(url->dvec);
+ return(0);
+
+}
+#endif /* def USE_IMAGE_LIST */
+
+
+#ifdef PCRS
+/*********************************************************************
+ *
+ * Function : re_process_buffer
+ *
+ * Description : Apply all jobs from the joblist (aka. Perl regexp's) to
+ * the text buffer that's been accumulated in csp->iob->buf.
+ * Then, write the modified buffer out to the client
+ * (Maybe this should happen from jcc.c via flush_socket
+ * for better readability).
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void re_process_buffer(struct client_state *csp)
+{
+ int hits=0;
+ int size = csp->iob->eod - csp->iob->cur;
+ char *old=csp->iob->cur, *new = NULL;
+ pcrs_job *job, *joblist;
+
+ struct file_list *fl;
+ struct re_filterfile_spec *b;
+
+ /* Sanity first ;-) */
+ if (size <= 0) return;
+
+ if ( ( NULL == (fl = csp->rlist) ) || ( NULL == (b = fl->f) ) )
+ {
+ log_error(LOG_LEVEL_ERROR, "Unable to get current state of regexp filtering.");
+ return;
+ }
+
+ joblist = b->joblist;
+
+
+ log_error(LOG_LEVEL_REF, "re_filtering %s%s (size %d) ...",
+ csp->http->hostport, csp->http->path, size);
+
+ /* Apply all jobs from the joblist */
+ for (job = joblist; NULL != job; job = job->next)
+ {
+ hits += pcrs_exec_substitution(job, old, size, &new, &size);
+ if (old != csp->iob->cur) free(old);
+ old=new;
+ }
+
+ log_error(LOG_LEVEL_REF, " produced %d hits (new size %d).", hits, size);
+
+ if (write_socket(csp->cfd, old, size) != size)
+ {
+ log_error(LOG_LEVEL_ERROR, "write to client failed.");
+ }
+
+ /* fwiw, reset the iob */
+ IOB_RESET(csp);
+ freez(new);
+ return;
+
+}
+#endif /* def PCRS */
+
+
+#ifdef TRUST_FILES
+/*********************************************************************
+ *
+ * Function : trust_url
+ *
+ * Description : Should we "trust" this URL? See "trustfile" line in config.
+ *
+ * Parameters :
+ * 1 : http = http_request request for requested URL
+ * 2 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : NULL => trusted, else string to HTML "untrusted" description.
+ *
+ *********************************************************************/
+char *trust_url(struct http_request *http, struct client_state *csp)
+{
+ struct file_list *fl;
+ struct block_spec *b;
+ struct url_spec url[1], **tl, *t;
+ char *p, *h;
+ char *hostport, *path, *refer;
+ struct http_request rhttp[1];
+ int n;
+
+ if (((fl = csp->tlist) == NULL) || ((b = fl->f) == NULL))
+ {
+ return(NULL);
+ }
+
+ *url = dsplit(http->host);
+
+ /* if splitting the domain fails, punt */
+ if (url->dbuf == NULL) return(NULL);
+
+ memset(rhttp, '\0', sizeof(*rhttp));
+
+ for (b = b->next; b ; b = b->next)
+ {
+ if ((b->url->port == 0) || (b->url->port == http->port))
+ {
+ if ((b->url->domain[0] == '\0') || (domaincmp(b->url, url) == 0))
+ {
+ if ((b->url->path == NULL) ||
+#ifdef REGEX
+ (regexec(b->url->preg, http->path, 0, NULL, 0) == 0)
+#else
+ (strncmp(b->url->path, http->path, b->url->pathlen) == 0)
+#endif
+ )
+ {
+ freez(url->dbuf);
+ freez(url->dvec);
+
+ if (b->reject == 0) return(NULL);
+
+ hostport = url_encode(http->hostport);
+ path = url_encode(http->path);
+
+ if (csp->referrer)
+ {
+ refer = url_encode(csp->referrer);
+ }
+ else
+ {
+ refer = url_encode("undefined");
+ }
+
+ n = strlen(CTRUST);
+ n += strlen(hostport);
+ n += strlen(path);
+ n += strlen(refer);
+
+ p = (char *)malloc(n);
+
+ sprintf(p, CTRUST, hostport, path, refer);
+
+ freez(hostport);
+ freez(path);
+ freez(refer);
+
+ return(p);
+ }
+ }
+ }
+ }
+
+ freez(url->dbuf);
+ freez(url->dvec);
+
+ if ((csp->referrer == NULL)|| (strlen(csp->referrer) <= 9))
+ {
+ /* no referrer was supplied */
+ goto trust_url_not_trusted;
+ }
+
+ /* forge a URL from the referrer so we can use
+ * convert_url() to parse it into its components.
+ */
+
+ p = NULL;
+ p = strsav(p, "GET ");
+ p = strsav(p, csp->referrer + 9); /* skip over "Referer: " */
+ p = strsav(p, " HTTP/1.0");
+
+ parse_http_request(p, rhttp, csp);
+
+ if (rhttp->cmd == NULL)
+ {
+ freez(p);
+ goto trust_url_not_trusted;
+ }
+
+ freez(p);
+
+ *url = dsplit(rhttp->host);
+
+ /* if splitting the domain fails, punt */
+ if (url->dbuf == NULL) goto trust_url_not_trusted;
+
+ for (tl = trust_list; (t = *tl) ; tl++)
+ {
+ if ((t->port == 0) || (t->port == rhttp->port))
+ {
+ if ((t->domain[0] == '\0') || domaincmp(t, url) == 0)
+ {
+ if ((t->path == NULL) ||
+#ifdef REGEX
+ (regexec(t->preg, rhttp->path, 0, NULL, 0) == 0)
+#else
+ (strncmp(t->path, rhttp->path, t->pathlen) == 0)
+#endif
+ )
+ {
+ /* if the URL's referrer is from a trusted referrer, then
+ * add the target spec to the trustfile as an unblocked
+ * domain and return NULL (which means it's OK).
+ */
+
+ FILE *fp;
+
+ freez(url->dbuf);
+ freez(url->dvec);
+
+ if ((fp = fopen(trustfile, "a")))
+ {
+ h = NULL;
+
+ h = strsav(h, "~");
+ h = strsav(h, http->hostport);
+
+ p = http->path;
+ if ((*p++ == '/')
+ && (*p++ == '~'))
+ {
+ /* since this path points into a user's home space
+ * be sure to include this spec in the trustfile.
+ */
+ if ((p = strchr(p, '/')))
+ {
+ *p = '\0';
+ h = strsav(h, http->path);
+ h = strsav(h, "/");
+ }
+ }
+
+ free_http_request(rhttp);
+
+ fprintf(fp, "%s\n", h);
+ freez(h);
+ fclose(fp);
+ }
+ return(NULL);
+ }
+ }
+ }
+ }
+
+trust_url_not_trusted:
+ free_http_request(rhttp);
+
+ hostport = url_encode(http->hostport);
+ path = url_encode(http->path);
+
+ if (csp->referrer)
+ {
+ refer = url_encode(csp->referrer);
+ }
+ else
+ {
+ refer = url_encode("undefined");
+ }
+
+ n = strlen(CTRUST);
+ n += strlen(hostport);
+ n += strlen(path);
+ n += strlen(refer);
+
+ p = (char *)malloc(n);
+ sprintf(p, CTRUST, hostport, path, refer);
+
+ freez(hostport);
+ freez(path);
+ freez(refer);
+
+ return(p);
+
+}
+#endif /* def TRUST_FILES */
+
+
+/*********************************************************************
+ *
+ * Function : intercept_url
+ *
+ * Description : checks the URL `basename' against a list of URLs to
+ * snarf. If it matches, it calls the associated function
+ * which returns an HTML page to send back to the client.
+ * Right now, we snarf:
+ * "show-proxy-args", and
+ * "ij-untrusted-url" (optional w/TRUST_FILES)
+ *
+ * Parameters :
+ * 1 : http = http_request request, check `basename's of blocklist
+ * 2 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : NULL for no recognized URLs, or an HTML description page.
+ *
+ *********************************************************************/
+char *intercept_url(struct http_request *http, struct client_state *csp)
+{
+ char *basename;
+ const struct interceptors *v;
+
+ basename = strrchr(http->path, '/');
+
+ if (basename == NULL) return(NULL);
+
+ basename ++; /* first char past the last slash */
+
+ if (*basename)
+ {
+ for (v = intercept_patterns; v->str; v++)
+ {
+ if (strncmp(basename, v->str, v->len) == 0)
+ {
+ return((v->interceptor)(http, csp));
+ }
+ }
+ }
+
+ return(NULL);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : cookie_url
+ *
+ * Description : Accept this cookie, or no? See "cookiefile" setting.
+ *
+ * Parameters :
+ * 1 : http = http_request request for blocked URLs
+ * 2 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : NULL => accept, cookie_spec pointer to crunch.
+ *
+ *********************************************************************/
+struct cookie_spec *cookie_url(struct http_request *http, struct client_state *csp)
+{
+ struct file_list *fl;
+ struct cookie_spec *b;
+ struct url_spec url[1];
+
+ if (((fl = csp->clist) == NULL) || ((b = fl->f) == NULL))
+ {
+ return(NULL);
+ }
+
+ *url = dsplit(http->host);
+
+ /* if splitting the domain fails, punt */
+ if (url->dbuf == NULL) return(NULL);
+
+ for (b = b->next; NULL != b; b = b->next)
+ {
+ if ((b->url->port == 0) || (b->url->port == http->port))
+ {
+ if ((b->url->domain[0] == '\0') || (domaincmp(b->url, url) == 0))
+ {
+ if ((b->url->path == NULL) ||
+#ifdef REGEX
+ (regexec(b->url->preg, http->path, 0, NULL, 0) == 0)
+#else
+ (strncmp(b->url->path, http->path, b->url->pathlen) == 0)
+#endif
+ )
+ {
+ freez(url->dbuf);
+ freez(url->dvec);
+ return(b);
+ }
+ }
+ }
+ }
+
+ freez(url->dbuf);
+ freez(url->dvec);
+ return(NULL);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : forward_url
+ *
+ * Description : Should we forward this to another proxy?
+ *
+ * Parameters :
+ * 1 : http = http_request request for current URL
+ * 2 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : Return gw_default for no forward match,
+ * else a gateway pointer to a specific forwarding proxy.
+ *
+ *********************************************************************/
+const struct gateway *forward_url(struct http_request *http, struct client_state *csp)
+{
+ struct file_list *fl;
+ struct forward_spec *b;
+ struct url_spec url[1];
+
+ if (((fl = csp->flist) == NULL) || ((b = fl->f) == NULL))
+ {
+ return(gw_default);
+ }
+
+ *url = dsplit(http->host);
+
+ /* if splitting the domain fails, punt */
+ if (url->dbuf == NULL) return(gw_default);
+
+ for (b = b->next; b ; b = b->next)
+ {
+ if ((b->url->port == 0) || (b->url->port == http->port))
+ {
+ if ((b->url->domain[0] == '\0') || (domaincmp(b->url, url) == 0))
+ {
+ if ((b->url->path == NULL) ||
+#ifdef REGEX
+ (regexec(b->url->preg, http->path, 0, NULL, 0) == 0)
+#else
+ (strncmp(b->url->path, http->path, b->url->pathlen) == 0)
+#endif
+ )
+ {
+ freez(url->dbuf);
+ freez(url->dvec);
+ return(b->gw);
+ }
+ }
+ }
+ }
+
+ freez(url->dbuf);
+ freez(url->dvec);
+ return(gw_default);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : dsplit
+ *
+ * Description : Takes a domain and returns a pointer to a url_spec
+ * structure populated with dbuf, dcnt and dvec. The
+ * other fields in the structure that is returned are zero.
+ *
+ * Parameters :
+ * 1 : domain = a URL address
+ *
+ * Returns : url_spec structure populated with dbuf, dcnt and dvec.
+ *
+ *********************************************************************/
+struct url_spec dsplit(char *domain)
+{
+ struct url_spec ret[1];
+ char *v[BUFSIZ];
+ int size;
+ char *p;
+
+ memset(ret, '\0', sizeof(*ret));
+
+ if ((p = strrchr(domain, '.')))
+ {
+ if (*(++p) == '\0')
+ {
+ ret->toplevel = 1;
+ }
+ }
+
+ ret->dbuf = strdup(domain);
+
+ /* map to lower case */
+ for (p = ret->dbuf; *p ; p++) *p = tolower(*p);
+
+ /* split the domain name into components */
+ ret->dcnt = ssplit(ret->dbuf, ".", v, SZ(v), 1, 1);
+
+ if (ret->dcnt <= 0)
+ {
+ memset(ret, '\0', sizeof(ret));
+ return(*ret);
+ }
+
+ /* save a copy of the pointers in dvec */
+ size = ret->dcnt * sizeof(*ret->dvec);
+
+ if ((ret->dvec = (char **)malloc(size)))
+ {
+ memcpy(ret->dvec, v, size);
+ }
+
+ return(*ret);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : domaincmp
+ *
+ * Description : Compare domain names.
+ * domaincmp("a.b.c" , "a.b.c") => 0 (MATCH)
+ * domaincmp("a*.b.c", "a.b.c") => 0 (MATCH)
+ * domaincmp("b.c" , "a.b.c") => 0 (MATCH)
+ * domaincmp("" , "a.b.c") => 0 (MATCH)
+ *
+ * Parameters :
+ * 1 : pattern = a domain that may contain a '*' as a wildcard.
+ * 2 : fqdn = domain name against which the patterns are compared.
+ *
+ * Returns : 0 => domains are equivalent, else no match.
+ *
+ *********************************************************************/
+int domaincmp(struct url_spec *pattern, struct url_spec *fqdn)
+{
+ char **pv, **fv; /* vectors */
+ int pn, fn; /* counters */
+ char *p, *f; /* chars */
+
+ pv = pattern->dvec;
+ pn = pattern->dcnt;
+
+ fv = fqdn->dvec;
+ fn = fqdn->dcnt;
+
+ while ((pn > 0) && (fn > 0))
+ {
+ p = pv[--pn];
+ f = fv[--fn];
+
+ while (*p && *f && (*p == tolower(*f)))
+ {
+ p++, f++;
+ }
+
+ if ((*p != tolower(*f)) && (*p != '*')) return(1);
+ }
+
+ if (pn > 0) return(1);
+
+ return(0);
+
+}
+
+
+/* intercept functions */
+
+/*********************************************************************
+ *
+ * Function : show_proxy_args
+ *
+ * Description : This "crunch"es "http:/any.thing/show-proxy-args" and
+ * returns a web page describing the current status of IJB.
+ *
+ * Parameters :
+ * 1 : http = ignored
+ * 2 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : A string that contains the current status of IJB.
+ *
+ *********************************************************************/
+char *show_proxy_args(struct http_request *http, struct client_state *csp)
+{
+ char *s = NULL;
+
+#ifdef SPLIT_PROXY_ARGS
+ FILE * fp;
+ char buf[BUFSIZ];
+ char * p;
+ const char * filename = NULL;
+ const char * file_description = NULL;
+ char * query_string = strrchr(http->path, '?');
+ char which_file = '\0';
+
+
+ if (query_string != NULL)
+ {
+ /* first char past the last '?' (maybe '\0')*/
+ which_file = query_string[1];
+ }
+ switch (which_file)
+ {
+ case 'b':
+ if (csp->blist)
+ {
+ filename = csp->blist->filename;
+ file_description = "Block List";
+ }
+ break;
+ case 'c':
+ if (csp->clist)
+ {
+ filename = csp->clist->filename;
+ file_description = "Cookie List";
+ }
+ break;
+ case 'f':
+ if (csp->flist)
+ {
+ filename = csp->flist->filename;
+ file_description = "Forward List";
+ }
+ break;
+
+#ifdef ACL_FILES
+ case 'a':
+ if (csp->alist)
+ {
+ filename = csp->alist->filename;
+ file_description = "Access Control List";
+ }
+ break;
+#endif /* def ACL_FILES */
+
+#ifdef USE_IMAGE_LIST
+ case 'i':
+ if (csp->ilist)
+ {
+ filename = csp->ilist->filename;
+ file_description = "Image List";
+ }
+ break;
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef KILLPOPUPS
+ case 'p':
+ if (csp->plist)
+ {
+ filename = csp->plist->filename;
+ file_description = "Popup list";
+ }
+ break;
+#endif /* def KILLPOPUPS */
+
+#ifdef PCRS
+ case 'r':
+ if (csp->rlist)
+ {
+ filename = csp->rlist->filename;
+ file_description = "RE Filter List";
+ }
+ break;
+#endif /* def PCRS */
+
+#ifdef TRUST_FILES
+ case 't':
+ if (csp->tlist)
+ {
+ filename = csp->tlist->filename;
+ file_description = "Trust List";
+ }
+ break;
+#endif /* def TRUST_FILES */
+ }
+
+ if (filename)
+ {
+ /* Display specified file */
+ /* FIXME: Add HTTP headers so this isn't cached */
+ s = strsav(s,
+ "HTTP/1.0 200 OK\n"
+ "Server: IJ/" VERSION "\n"
+ "Content-type: text/html\n"
+ "Pragma: no-cache\n"
+ "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMT\n"
+ "Expires: Thu Jul 31, 1997 07:42:22 pm GMT\n"
+ "\n"
+
+ "<html>"
+ "<head>"
+ "<title>Internet Junkbuster Proxy Status - ");
+ s = strsav(s, file_description);
+ s = strsav(s,
+ "</title>"
+ "</head>\n"
+ "<body bgcolor=\"#f8f8f0\" link=\"#000078\" alink=\"#ff0022\" vlink=\"#787878\">\n"
+ "<center>\n"
+ "<h1>" BANNER "\n");
+ s = strsav(s, file_description);
+ s = strsav(s,
+ "</h1></center>\n"
+ "<p><a href=\"show-proxy-args\">Back to proxy status</a></p>\n"
+ "<h2>");
+ s = strsav(s, file_description);
+ s = strsav(s,
+ "</h2>\n"
+ "Contents of file "<code>");
+ p = html_encode(filename);
+ s = strsav(s, p);
+ freez(p);
+ s = strsav(s,
+ "</code>":<br>\n"
+ "</p>\n"
+ "<pre>");
+
+ if ((fp = fopen(filename, "r")) == NULL)
+ {
+ s = strsav(s, "</pre><h1>ERROR OPENING FILE!</h1><pre>");
+ }
+ else
+ {
+ while (fgets(buf, sizeof(buf), fp))
+ {
+ p = html_encode(buf);
+ if (p)
+ {
+ s = strsav(s, p);
+ freez(p);
+ s = strsav(s, "<br>");
+ }
+ }
+ fclose(fp);
+ }
+
+ s = strsav(s,
+ "</pre>\n"
+ "<br>\n"
+ "<p><a href=\"show-proxy-args\">Back to proxy status</a></p>\n"
+ "<br>\n"
+ "<small><small><p>\n"
+ "Code and documentation of the " BANNER " Proxy"
+ "<sup><small>TM</small></sup>\n"
+ "<a href=\"http://www.junkbusters.com/ht/en/legal.html#copy\">\n" "Copyright</a>© 1997 Junkbusters Corporation\n"
+ "<a href=\"http://www.junkbusters.com/ht/en/legal.html#marks\"><sup><small>TM</small></sup></a><br>\n"
+ "Copying and distribution permitted under the"
+ "<a href=\"http://www.gnu.org/copyleft/gpl.html\">\n"
+ "<small>GNU</small></a> "
+ "General Public License.\n"
+ "</small>"
+ "<address><kbd>webmaster@junkbusters.com</kbd></address>"
+ "</small>"
+ "</body></html>\n");
+ return(s);
+ }
+#endif /* def SPLIT_PROXY_ARGS */
+
+ s = strsav(s, proxy_args->header);
+ s = strsav(s, proxy_args->invocation);
+#ifdef STATISTICS
+ s = add_stats(s);
+#endif /* def STATISTICS */
+ s = strsav(s, proxy_args->gateways);
+
+#ifdef SPLIT_PROXY_ARGS
+ s = strsav(s,
+ "<h2>The following files are in use:</h2>\n"
+ "<p>(Click a filename to view it)</p>\n"
+ "<ul>\n");
+
+ if (csp->blist)
+ {
+ s = strsav(s, "<li>Block List: <a href=\"show-proxy-args?block\"><code>");
+ s = strsav(s, csp->blist->filename);
+ s = strsav(s, "</code></a></li>\n");
+ }
+
+ if (csp->clist)
+ {
+ s = strsav(s, "<li>Cookie List: <a href=\"show-proxy-args?cookie\"><code>");
+ s = strsav(s, csp->clist->filename);
+ s = strsav(s, "</code></a></li>\n");
+ }
+
+ if (csp->flist)
+ {
+ s = strsav(s, "<li>Forward List: <a href=\"show-proxy-args?forward\"><code>");
+ s = strsav(s, csp->flist->filename);
+ s = strsav(s, "</code></a></li>\n");
+ }
+
+#ifdef ACL_FILES
+ if (csp->alist)
+ {
+ s = strsav(s, "<li>Access Control List: <a href=\"show-proxy-args?acl\"><code>");
+ s = strsav(s, csp->alist->filename);
+ s = strsav(s, "</code></a></li>\n");
+ }
+#endif /* def ACL_FILES */
+
+#ifdef USE_IMAGE_LIST
+ if (csp->ilist)
+ {
+ s = strsav(s, "<li>Image List: <a href=\"show-proxy-args?image\"><code>");
+ s = strsav(s, csp->ilist->filename);
+ s = strsav(s, "</code></a></li>\n");
+ }
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef KILLPOPUPS
+ if (csp->plist)
+ {
+ s = strsav(s, "<li>Popup List: <a href=\"show-proxy-args?popup\"><code>");
+ s = strsav(s, csp->plist->filename);
+ s = strsav(s, "</code></a></li>\n");
+ }
+#endif /* def KILLPOPUPS */
+
+#ifdef PCRS
+ if (csp->rlist)
+ {
+ s = strsav(s, "<li>RE Filter List: <a href=\"show-proxy-args?re\"><code>");
+ s = strsav(s, csp->rlist->filename);
+ s = strsav(s, "</code></a></li>\n");
+ }
+#endif /* def PCRS */
+
+#ifdef TRUST_FILES
+ if (csp->tlist)
+ {
+ s = strsav(s, "<li>Trust List: <a href=\"show-proxy-args?trust\"><code>");
+ s = strsav(s, csp->tlist->filename);
+ s = strsav(s, "</code></a></li>\n");
+ }
+#endif /* def TRUST_FILES */
+
+ s = strsav(s, "</ul>");
+
+#else /* ifndef SPLIT_PROXY_ARGS */
+ if (csp->blist)
+ {
+ s = strsav(s, csp->blist->proxy_args);
+ }
+
+ if (csp->clist)
+ {
+ s = strsav(s, csp->clist->proxy_args);
+ }
+
+ if (csp->flist)
+ {
+ s = strsav(s, csp->flist->proxy_args);
+ }
+
+#ifdef ACL_FILES
+ if (csp->alist)
+ {
+ s = strsav(s, csp->alist->proxy_args);
+ }
+#endif /* def ACL_FILES */
+
+#ifdef USE_IMAGE_LIST
+ if (csp->ilist)
+ {
+ s = strsav(s, csp->ilist->proxy_args);
+ }
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef KILLPOPUPS
+ if (csp->plist)
+ {
+ s = strsav(s, csp->plist->proxy_args);
+ }
+#endif /* def KILLPOPUPS */
+
+#ifdef PCRS
+ if (csp->rlist)
+ {
+ s = strsav(s, csp->rlist->proxy_args);
+ }
+#endif /* def PCRS */
+
+#ifdef TRUST_FILES
+ if (csp->tlist)
+ {
+ s = strsav(s, csp->tlist->proxy_args);
+ }
+#endif /* def TRUST_FILES */
+
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ s = strsav(s, proxy_args->trailer);
+
+ return(s);
+
+}
+
+
+#ifdef TRUST_FILES
+/*********************************************************************
+ *
+ * Function : ij_untrusted_url
+ *
+ * Description : This "crunch"es "http:/any.thing/ij-untrusted-url" and
+ * returns a web page describing why it was untrusted.
+ *
+ * Parameters :
+ * 1 : http = http_request request for crunched URL
+ * 2 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : A string that contains why this was untrusted.
+ *
+ *********************************************************************/
+char *ij_untrusted_url(struct http_request *http, struct client_state *csp)
+{
+ int n;
+ char *hostport, *path, *refer, *p, *v[9];
+ char buf[BUFSIZ];
+ struct url_spec **tl, *t;
+
+
+ static const char format[] =
+ "HTTP/1.0 200 OK\r\n"
+ "Pragma: no-cache\n"
+ "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMT\n"
+ "Expires: Thu Jul 31, 1997 07:42:22 pm GMT\n"
+ "Content-Type: text/html\n\n"
+ "<html>\n"
+ "<head>\n"
+ "<title>Internet Junkbuster: Request for untrusted URL</title>\n"
+ "</head>\n"
+ BODY
+ "<center><h1>"
+ BANNER
+ "</h1></center>"
+ "The " BANNER " Proxy "
+ "<A href=\"" HOME_PAGE_URL "\">"
+ "(" HOME_PAGE_URL ") </A>"
+ "intercepted the request for %s%s\n"
+ "because the URL is not trusted.\n"
+ "<br><br>\n";
+
+ if ((n = ssplit(http->path, "?+", v, SZ(v), 0, 0)) == 4)
+ {
+ hostport = url_decode(v[1]);
+ path = url_decode(v[2]);
+ refer = url_decode(v[3]);
+ }
+ else
+ {
+ hostport = strdup("undefined_host");
+ path = strdup("/undefined_path");
+ refer = strdup("undefined");
+ }
+
+ n = sizeof(format);
+ n += strlen(hostport);
+ n += strlen(path );
+
+ if ((p = (char *)malloc(n)))
+ {
+ sprintf(p, format, hostport, path);
+ }
+
+ strsav(p, "The referrer in this request was <strong>");
+ strsav(p, refer);
+ strsav(p, "</strong><br>\n");
+
+ freez(hostport);
+ freez(path );
+ freez(refer );
+
+ p = strsav(p, "<h3>The following referrers are trusted</h3>\n");
+
+ for (tl = trust_list; (t = *tl) ; tl++)
+ {
+ sprintf(buf, "%s<br>\n", t->spec);
+ p = strsav(p, buf);
+ }
+
+ if (trust_info->next)
+ {
+ struct list *l;
+
+ strcpy(buf,
+ "<p>"
+ "You can learn more about what this means "
+ "and what you may be able to do about it by "
+ "reading the following documents:<br>\n"
+ "<ol>\n"
+ );
+
+ p = strsav(p, buf);
+
+ for (l = trust_info->next; l ; l = l->next)
+ {
+ sprintf(buf,
+ "<li> <a href=%s>%s</a><br>\n",
+ l->str, l->str);
+ p = strsav(p, buf);
+ }
+
+ p = strsav(p, "</ol>\n");
+ }
+
+ p = strsav(p, "</body>\n" "</html>\n");
+
+ return(p);
+
+}
+#endif /* def TRUST_FILES */
+
+
+#ifdef STATISTICS
+/*********************************************************************
+ *
+ * Function : add_stats
+ *
+ * Description : Statistics function of JB. Called by `show_proxy_args'.
+ *
+ * Parameters :
+ * 1 : s = string that holds the proxy args description page
+ *
+ * Returns : A pointer to the descriptive status web page.
+ *
+ *********************************************************************/
+char *add_stats(char *s)
+{
+ /*
+ * Output details of the number of requests rejected and
+ * accepted. This is switchable in the junkbuster config.
+ * Does nothing if this option is not enabled.
+ */
+
+ float perc_rej; /* Percentage of http requests rejected */
+ char out_str[81];
+ int local_urls_read = urls_read;
+ int local_urls_rejected = urls_rejected;
+
+ /*
+ * Need to alter the stats not to include the fetch of this
+ * page.
+ *
+ * Can't do following thread safely! doh!
+ *
+ * urls_read--;
+ * urls_rejected--; * This will be incremented subsequently *
+ */
+
+ s = strsav(s,"<h2>Statistics for this " BANNER ":</h2>\n");
+
+ if (local_urls_read == 0)
+ {
+
+ s = strsav(s,"No activity so far!\n");
+
+ }
+ else
+ {
+
+ perc_rej = (float)local_urls_rejected * 100.0F /
+ (float)local_urls_read;
+
+ sprintf(out_str,
+ "%d requests received, %d filtered "
+ "(%6.2f %%).",
+ local_urls_read,
+ local_urls_rejected, perc_rej);
+
+ s = strsav(s,out_str);
+ }
+
+ return(s);
+}
+#endif /* def STATISTICS */
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _FILTERS_H
+#define _FILTERS_H
+#define FILTERS_H_VERSION "$Id: filters.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/filters.h,v $
+ *
+ * Purpose : Declares functions to parse/crunch headers and pages.
+ * Functions declared include:
+ * `acl_addr', `add_stats', `block_acl', `block_imageurl',
+ * `block_url', `cookie_url', `domaincmp', `dsplit',
+ * `filter_popups', `forward_url'
+ * `ij_untrusted_url', `intercept_url', `re_process_buffer',
+ * `show_proxy_args', and `trust_url'
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: filters.h,v $
+ *
+ *********************************************************************/
+\f\r
+
+#include "project.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef ACL_FILES
+extern int block_acl(struct access_control_addr *src, struct access_control_addr *dst, struct client_state *csp);
+extern int acl_addr(char *aspec, struct access_control_addr *aca);
+#endif /* def ACL_FILES */
+
+extern char *block_url(struct http_request *http, struct client_state *csp);
+#ifdef TRUST_FILES
+extern char *trust_url(struct http_request *http, struct client_state *csp);
+#endif /* def TRUST_FILES */
+extern char *intercept_url(struct http_request *http, struct client_state *csp);
+
+#if defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST)
+extern int block_imageurl(struct http_request *http, struct client_state *csp);
+#endif /* defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST) */
+
+#ifdef USE_IMAGE_LIST
+extern int block_imageurl_using_imagelist(struct http_request *http, struct client_state *csp);
+#endif /* def USE_IMAGE_LIST */
+
+extern struct cookie_spec *cookie_url(struct http_request *http, struct client_state *csp);
+extern const struct gateway *forward_url(struct http_request *http, struct client_state *csp);
+
+extern struct url_spec dsplit(char *domain);
+extern int domaincmp(struct url_spec *pattern, struct url_spec *fqdn);
+
+extern char *show_proxy_args(struct http_request *http, struct client_state *csp);
+
+#ifdef TRUST_FILES
+extern char *ij_untrusted_url(struct http_request *http, struct client_state *csp);
+#endif /* def TRUST_FILES */
+
+#ifdef STATISTICS
+extern char *add_stats(char *s);
+#endif /* def STATISTICS */
+
+#ifdef PCRS
+extern void re_process_buffer(struct client_state *csp);
+#endif /* def PCRS */
+
+/* Revision control strings from this header and associated .c file */
+extern const char filters_rcs[];
+extern const char filters_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _FILTERS_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+# Forwarding specification for Internet Junkbuster 2.0
+#
+# Copyright 1997-8 Junkbusters Corp. For distribution, modification and use
+# under the GNU General Public License. These files come with NO WARRANTY.
+# See http://www.junkbusters.com/ht/en/gpl.html or README file for details.
+
+# For this file to have any effect, the line beginning "forwardfile" must
+# be commented in, with the name of this file following the word "forwardfile"
+
+#
+# This feature allows routing of HTTP requests via multiple proxies.
+# It can be used to better protect privacy and confidentiality when
+# accessing specific domains by routing requests to those domains
+# to a special purpose filtering proxy such as lpwa.com
+#
+# It can also be used in an environment with multiple networks to route
+# requests via multiple gateways allowing transparent access to multiple
+# networks without having to modify browser configurations.
+#
+# Also specified here are special gateway protocols such as SOCKS.
+
+# The syntax of each line is
+#
+# target_domain[:port][/path] forwarding_domain[:port] gateway_type gateway_domain[:port]
+#
+
+# A '.' in the forwarding domain/port means that requests made to the
+# target domain are not forwarded but are made directly by the proxy
+# (though the proxy may still use a gateway to contact the server)
+#
+# Lines are checked in turn, and the last match wins.
+#
+# There is an implicit line equivalent to the following, which specifies that
+# anything not finding a match on the list is to go out without forwarding
+# or gateway protocol; like so:
+#
+# * . . . # implicit
+
+# In the following common configuration, everything goes to Lucent's LPWA,
+# except SSL on port 443 (which it doesn't handle)
+# * lpwa.com:8000 . .
+# :443 . . .
+
+# See the FAQ for instructions on how to automate the login procedure for LPWA.
+# Some users have reported difficulties related to LPWA's use of . as the
+# last element of the domain, and have said that this can be fixed with this:
+# lpwa. lpwa.com:8000 . .
+
+# In this fictitious example, everything goes via an ISP's caching proxy,
+# except requests to that ISP:
+#
+# * caching.myisp.net:8000 . .
+# myisp.net . . .
+
+# For the @home network, we're told the forwarding configuration is this:
+# * proxy:8080 . .
+# Also, we're told they insist on getting cookies and Javascript, so you need
+# to add home.com to the cookie file. We consider Javascript a security risk;
+# see our page on cookies. Java need not be enabled.
+
+# In this example direct connections are made to all "internal" domains,
+# but everything else goes through Lucent's LPWA by way of the company's
+# SOCKS gateway to the Internet.
+#
+# * lpwa.com:8000 socks argyle.my_company.com:1080
+# my_company.com . . .
+
+# This is how you could set up a site that always uses SOCKS but no forwarders
+#
+# * . socks knee.my_company.com:1080
+
+# An advanced example for network administrators.
+#
+# If you have links to multiple ISPs that provide various special
+#content to their subscribers, you can configure forwarding to pass
+# requests to the specific host that's connected to that ISP
+# so that everybody can see
+# all of the content on all of the ISPs.
+#
+# This is tricky, but here's a sample:
+#
+# host-a has a PPP connection to isp-a.com
+# host-b has a PPP connection to isp-b.com
+
+# host-a can run an Internet Junkbuster proxy with forwarding like this:
+#
+# / . . .
+# isp-b.com host-b:8000 . .
+#
+# host-b can run an Internet Junkbuster proxy with forwarding like this:
+# / . . .
+# isp-a.com host-a:8000 . .
+#
+# Now, *anyone* on the Internet (including users on host-a and host-b)
+# can set their browser's proxy to *either* host-a or host-b and
+# be able to browse the content on isp-a or isp-b.
+
--- /dev/null
+const char gateway_rcs[] = "$Id: gateway.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/gateway.c,v $
+ *
+ * Purpose : Contains functions to connect to a server, possibly
+ * using a "gateway" (i.e. HTTP proxy and/or SOCKS4
+ * proxy). Also contains the list of gateway types.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: gateway.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#endif /* def _WIN32 */
+
+#include "jcc.h"
+#include "errlog.h"
+#include "jbsockets.h"
+#include "gateway.h"
+
+const char gateway_h_rcs[] = GATEWAY_H_VERSION;
+
+#define SOCKS_4 40 /* original SOCKS 4 protocol */
+#define SOCKS_4A 41 /* as modified for hosts w/o external DNS */
+
+const struct gateway gateways[] = {
+ /* type function gw type/host/port, fw host/port */
+ { "direct", direct_connect, 0, NULL, 0, NULL, 0 },
+ { ".", direct_connect, 0, NULL, 0, NULL, 0 },
+ { "socks", socks4_connect, SOCKS_4, NULL, 1080, NULL, 0 },
+ { "socks4", socks4_connect, SOCKS_4, NULL, 1080, NULL, 0 },
+ { "socks4a", socks4_connect, SOCKS_4A, NULL, 1080, NULL, 0 },
+ { NULL, NULL, 0, NULL, 0, NULL, 0 }
+};
+
+const struct gateway *gw_default = gateways; /* direct */
+
+
+#define SOCKS_REQUEST_GRANTED 90
+#define SOCKS_REQUEST_REJECT 91
+#define SOCKS_REQUEST_IDENT_FAILED 92
+#define SOCKS_REQUEST_IDENT_CONFLICT 93
+
+/* structure of a socks client operation */
+struct socks_op {
+ unsigned char vn; /* socks version number */
+ unsigned char cd; /* command code */
+ unsigned char dstport[2]; /* destination port */
+ unsigned char dstip[4]; /* destination address */
+ unsigned char userid; /* first byte of userid */
+ /* more bytes of the userid follow, terminated by a NULL */
+};
+
+/* structure of a socks server reply */
+struct socks_reply {
+ unsigned char vn; /* socks version number */
+ unsigned char cd; /* command code */
+ unsigned char dstport[2]; /* destination port */
+ unsigned char dstip[4]; /* destination address */
+};
+
+static const char socks_userid[] = "anonymous";
+
+
+/*********************************************************************
+ *
+ * Function : direct_connect
+ *
+ * Description : Direct how we connect to the web. This can be:
+ * directly : no forwarding, or
+ * indirectly : through another proxy such as squid.
+ *
+ * Parameters :
+ * 1 : gw = pointer to a gateway structure (such as gw_default)
+ * 2 : http = the http request and apropos headers
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : -1 => failure, else it is the socket file descriptor.
+ *
+ *********************************************************************/
+int direct_connect(const struct gateway *gw, struct http_request *http, struct client_state *csp)
+{
+ if (gw->forward_host)
+ {
+ return(connect_to(gw->forward_host, gw->forward_port, csp));
+ }
+ else
+ {
+ return(connect_to(http->host, http->port, csp));
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : socks4_connect
+ *
+ * Description : Connect to the SOCKS server, and connect through
+ * it to the web server or web proxy. This handles
+ * all the SOCKS negotiation, and returns a file
+ * descriptor for a socket which can be treated as a
+ * normal (non-SOCKS) socket.
+ *
+ * Parameters :
+ * 1 : gw = pointer to a gateway structure (such as gw_default)
+ * 2 : http = the http request and apropos headers
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : -1 => failure, else a socket file descriptor.
+ *
+ *********************************************************************/
+int socks4_connect(const struct gateway *gw, struct http_request *http, struct client_state *csp)
+{
+ int web_server_addr;
+ unsigned char cbuf[BUFSIZ];
+ unsigned char sbuf[BUFSIZ];
+ struct socks_op *c = (struct socks_op *)cbuf;
+ struct socks_reply *s = (struct socks_reply *)sbuf;
+ int n, csiz, sfd, target_port;
+ int err = 0;
+ char *errstr, *target_host;
+
+ if ((gw->gateway_host == NULL) || (*gw->gateway_host == '\0'))
+ {
+ log_error(LOG_LEVEL_CONNECT, "socks4_connect: NULL gateway host specified");
+ err = 1;
+ }
+
+ if (gw->gateway_port <= 0)
+ {
+ log_error(LOG_LEVEL_CONNECT, "socks4_connect: invalid gateway port specified");
+ err = 1;
+ }
+
+ if (err)
+ {
+ errno = EINVAL;
+ return(-1);
+ }
+
+ if (gw->forward_host)
+ {
+ target_host = gw->forward_host;
+ target_port = gw->forward_port;
+ }
+ else
+ {
+ target_host = http->host;
+ target_port = http->port;
+ }
+
+ /* build a socks request for connection to the web server */
+
+ strcpy((char *)&(c->userid), socks_userid);
+
+ csiz = sizeof(*c) + sizeof(socks_userid) - 1;
+
+ switch (gw->type)
+ {
+ case SOCKS_4:
+ web_server_addr = htonl(resolve_hostname_to_ip(target_host));
+ break;
+ case SOCKS_4A:
+ web_server_addr = 0x00000001;
+ n = csiz + strlen(target_host) + 1;
+ if (n > sizeof(cbuf))
+ {
+ errno = EINVAL;
+ return(-1);
+ }
+ strcpy(((char *)cbuf) + csiz, http->host);
+ csiz = n;
+ break;
+ default:
+ /* Should never get here */
+ log_error(LOG_LEVEL_ERROR, "SOCKS4 impossible internal error - bad SOCKS type.");
+ errno = EINVAL;
+ return(-1);
+ }
+
+ c->vn = 4;
+ c->cd = 1;
+ c->dstport[0] = (target_port >> 8 ) & 0xff;
+ c->dstport[1] = (target_port ) & 0xff;
+ c->dstip[0] = (web_server_addr >> 24 ) & 0xff;
+ c->dstip[1] = (web_server_addr >> 16 ) & 0xff;
+ c->dstip[2] = (web_server_addr >> 8 ) & 0xff;
+ c->dstip[3] = (web_server_addr ) & 0xff;
+
+ /* pass the request to the socks server */
+ sfd = connect_to(gw->gateway_host, gw->gateway_port, csp);
+
+ if (sfd < 0)
+ {
+ return(-1);
+ }
+
+ if ((n = write_socket(sfd, (char *)c, csiz)) != csiz)
+ {
+ log_error(LOG_LEVEL_CONNECT, "SOCKS4 negotiation write failed...");
+ close_socket(sfd);
+ return(-1);
+ }
+
+ if ((n = read_socket(sfd, sbuf, sizeof(sbuf))) != sizeof(*s))
+ {
+ log_error(LOG_LEVEL_CONNECT, "SOCKS4 negotiation read failed...");
+ close_socket(sfd);
+ return(-1);
+ }
+
+ switch (s->cd)
+ {
+ case SOCKS_REQUEST_GRANTED:
+ return(sfd);
+ break;
+ case SOCKS_REQUEST_REJECT:
+ errstr = "SOCKS request rejected or failed";
+ errno = EINVAL;
+ break;
+ case SOCKS_REQUEST_IDENT_FAILED:
+ errstr = "SOCKS request rejected because "
+ "SOCKS server cannot connect to identd on the client";
+ errno = EACCES;
+ break;
+ case SOCKS_REQUEST_IDENT_CONFLICT:
+ errstr = "SOCKS request rejected because "
+ "the client program and identd report "
+ "different user-ids";
+ errno = EACCES;
+ break;
+ default:
+ errstr = (char *) cbuf;
+ errno = ENOENT;
+ sprintf(errstr,
+ "SOCKS request rejected for reason code %d\n", s->cd);
+ }
+
+ log_error(LOG_LEVEL_CONNECT, "socks4_connect: %s ...", errstr);
+
+ close_socket(sfd);
+ return(-1);
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _GATEWAY_H
+#define _GATEWAY_H
+#define GATEWAY_H_VERSION "$Id: gateway.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/gateway.h,v $
+ *
+ * Purpose : Contains functions to connect to a server, possibly
+ * using a "gateway" (i.e. HTTP proxy and/or SOCKS4
+ * proxy). Also contains the list of gateway types.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: gateway.h,v $
+ *
+ *********************************************************************/
+\f
+
+#include "project.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const struct gateway gateways[];
+extern const struct gateway *gw_default;
+
+extern int socks4_connect(const struct gateway *gw, struct http_request *http, struct client_state *csp);
+extern int direct_connect(const struct gateway *gw, struct http_request *http, struct client_state *csp);
+
+/* Revision control strings from this header and associated .c file */
+extern const char gateway_rcs[];
+extern const char gateway_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _GATEWAY_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#
+# This is /etc/junkbuster/imagelist which was put here by a junkbuster rpm
+#
+# Last modified on Fri Oct 1 22:42:21 1999 (CEST)
+#
+# --------------------------------------------------------------------------
+#
+# Newest version is always available from
+#
+# http://www.waldherr.org/imagelist
+#
+# Read http://www.waldherr.org/junkbuster/update.shtml on how to keep
+# this file up-to-date.
+#
+# Comments: Stefan Waldherr <stefan@waldherr.org>
+#
+# Note that the regexp is split into domain and path, hence the `/' as the
+# beginning of a path.
+#
+
+# generic, most powerful regepxs, path contains `.gif', `.jpeg' or `.jpg'
+/.*\.gif
+/.*\.jpe?g
+
+adforce.imgis.com
+ad.preferences.com/image.*
+ads.web.aol.com
+focalink.com
+ad-adex3.flycast.com
+ad.doubleclick.net
+connect.247media.ads.link4ads.com
+ln.doubleclick.net
+mojofarm.mediaplex.com/ad/
+www.carbuyer.com/cgi-carbuyer/getimage.cgi
--- /dev/null
+const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/jbsockets.c,v $
+ *
+ * Purpose : Contains wrappers for system-specific sockets code,
+ * so that the rest of JunkBuster can be more
+ * OS-independent. Contains #ifdefs to make this work
+ * on many platforms.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: jbsockets.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#ifdef _WIN32
+
+#include <windows.h>
+#include <sys/timeb.h>
+#include <io.h>
+
+#else
+
+#include <unistd.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <netdb.h>
+#include <sys/socket.h>
+
+#ifndef __BEOS__
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#else
+#include <socket.h>
+#endif
+
+#endif
+
+#include "project.h"
+#include "jbsockets.h"
+#include "filters.h"
+
+const char jbsockets_h_rcs[] = JBSOCKETS_H_VERSION;
+
+
+/*********************************************************************
+ *
+ * Function : connect_to
+ *
+ * Description : Open a socket and connect to it. Will check
+ * that this is allowed according to ACL.
+ *
+ * Parameters :
+ * 1 : host = hostname to connect to
+ * 2 : portnum = port to connent on
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ * Not modified, only used for source IP and ACL.
+ *
+ * Returns : -1 => failure, else it is the socket file descriptor.
+ *
+ *********************************************************************/
+int connect_to(char *host, int portnum, struct client_state *csp)
+{
+ struct sockaddr_in inaddr;
+ int fd, addr;
+ fd_set wfds;
+ struct timeval tv[1];
+#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)
+ int flags;
+#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
+
+#ifdef ACL_FILES
+ struct access_control_addr src[1], dst[1];
+#endif /* def ACL_FILES */
+
+ memset((char *)&inaddr, 0, sizeof inaddr);
+
+ if ((addr = resolve_hostname_to_ip(host)) == -1)
+ {
+ return(-1);
+ }
+
+#ifdef ACL_FILES
+ src->addr = csp->ip_addr_long;
+ src->port = 0;
+
+ dst->addr = ntohl(addr);
+ dst->port = portnum;
+
+ if (block_acl(src, dst, csp))
+ {
+ errno = EPERM;
+ return(-1);
+ }
+#endif /* def ACL_FILES */
+
+ inaddr.sin_addr.s_addr = addr;
+ inaddr.sin_family = AF_INET;
+
+ if (sizeof(inaddr.sin_port) == sizeof(short))
+ {
+ inaddr.sin_port = htons((short)portnum);
+ }
+ else
+ {
+ inaddr.sin_port = htonl(portnum);
+ }
+
+ if ((fd = socket(inaddr.sin_family, SOCK_STREAM, 0)) < 0)
+ {
+ return(-1);
+ }
+
+#ifdef TCP_NODELAY
+ { /* turn off TCP coalescence */
+ int mi = 1;
+ setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char *) &mi, sizeof (int));
+ }
+#endif /* def TCP_NODELAY */
+
+#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)\r
+ if ((flags = fcntl(fd, F_GETFL, 0)) != -1)
+ {
+ flags |= O_NDELAY;
+ fcntl(fd, F_SETFL, flags);
+ }
+#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
+
+ while (connect(fd, (struct sockaddr *) & inaddr, sizeof inaddr) == -1)
+ {
+#ifdef _WIN32
+ if (errno == WSAEINPROGRESS)
+#else /* ifndef _WIN32 */
+ if (errno == EINPROGRESS)
+#endif /* ndef _WIN32 */
+ {
+ break;
+ }
+
+ if (errno != EINTR)
+ {
+ close_socket(fd);
+ return(-1);
+ }
+ }
+
+#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)
+ if (flags != -1)
+ {
+ flags &= ~O_NDELAY;
+ fcntl(fd, F_SETFL, flags);
+ }
+#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
+
+ /* wait for connection to complete */
+ FD_ZERO(&wfds);
+ FD_SET(fd, &wfds);
+
+ tv->tv_sec = 30;
+ tv->tv_usec = 0;
+
+ if (select(fd + 1, NULL, &wfds, NULL, tv) <= 0)
+ {
+ close_socket(fd);
+ return(-1);
+ }
+ return(fd);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : write_socket
+ *
+ * Description : Write the contents of buf (for n bytes) to socket fd.
+ *
+ * Parameters :
+ * 1 : fd = file descriptor (aka. handle) of socket to write to.
+ * 2 : buf = pointer to data to be written.
+ * 3 : len = length of data to be written to the socket "fd".
+ *
+ * Returns : Win32: If no error occurs, returns the total number of
+ * bytes sent, which can be less than the number
+ * indicated by len. Otherwise, returns (-1).
+ * Unix: ??? (Please fill me in!)
+ *
+ *********************************************************************/
+int write_socket(int fd, const char *buf, int len)
+{
+ if (len <= 0) return(0);
+
+ /* if (DEBUG(LOG)) fwrite(buf, n, 1, logfp); */
+
+#if defined(_WIN32) || defined(__BEOS__) || defined(AMIGA)
+ return( send(fd, buf, len, 0));
+#else
+ return( write(fd, buf, len));
+#endif
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : read_socket
+ *
+ * Description : Read from a TCP/IP socket in a platform independent way.
+ *
+ * Parameters :
+ * 1 : fd = file descriptor of the socket to read
+ * 2 : buf = pointer to buffer where data will be written
+ * Must be >= len bytes long.
+ * 3 : len = maximum number of bytes to read
+ *
+ * Returns : On success, the number of bytes read is returned (zero
+ * indicates end of file), and the file position is advanced
+ * by this number. It is not an error if this number is
+ * smaller than the number of bytes requested; this may hap-
+ * pen for example because fewer bytes are actually available
+ * right now (maybe because we were close to end-of-file, or
+ * because we are reading from a pipe, or from a terminal),
+ * or because read() was interrupted by a signal. On error,
+ * -1 is returned, and errno is set appropriately. In this
+ * case it is left unspecified whether the file position (if
+ * any) changes.
+ *
+ *********************************************************************/
+int read_socket(int fd, char *buf, int len)
+{
+ if (len <= 0)
+ {
+ return(0);
+ }
+
+#if defined(_WIN32) || defined(__BEOS__) || defined(AMIGA)
+ return( recv(fd, buf, len, 0));
+#else
+ return( read(fd, buf, len));
+#endif
+}
+
+
+/*********************************************************************
+ *
+ * Function : close_socket
+ *
+ * Description : Closes a TCP/IP socket
+ *
+ * Parameters :
+ * 1 : fd = file descriptor of socket to be closed
+ *
+ * Returns : void
+ *
+ *********************************************************************/
+void close_socket(int fd)
+{
+#if defined(_WIN32) || defined(__BEOS__)
+ closesocket(fd);
+#elif defined(AMIGA)\r
+ CloseSocket(fd); \r
+#else
+ close(fd);
+#endif
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : bind_port
+ *
+ * Description : Call socket, set socket options, and listen.
+ * Called by listen_loop to "boot up" our proxy address.
+ *
+ * Parameters :
+ * 1 : hostnam = TCP/IP address to bind/listen to
+ * 2 : portnum = port to listen on
+ *
+ * Returns : if success, return file descriptor
+ * if failure, returns -2 if address is in use, otherwise -1
+ *
+ *********************************************************************/
+int bind_port(const char *hostnam, int portnum)
+{
+ struct sockaddr_in inaddr;
+ int fd;
+ int one = 1;
+
+ memset((char *)&inaddr, '\0', sizeof inaddr);
+
+ inaddr.sin_family = AF_INET;
+ inaddr.sin_addr.s_addr = resolve_hostname_to_ip(hostnam);
+
+ if (sizeof(inaddr.sin_port) == sizeof(short))
+ {
+ inaddr.sin_port = htons((short)portnum);
+ }
+ else
+ {
+ inaddr.sin_port = htonl(portnum);
+ }
+
+ fd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (fd < 0)
+ {
+ return(-1);
+ }
+
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
+
+ if (bind (fd, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0)
+ {
+ close_socket (fd);
+#ifdef _WIN32
+ if (errno == WSAEADDRINUSE)
+#else
+ if (errno == EADDRINUSE)
+#endif
+ {
+ return(-2);
+ }
+ else
+ {
+ return(-1);
+ }
+ }
+
+ while (listen(fd, 5) == -1)
+ {
+ if (errno != EINTR)
+ {
+ return(-1);
+ }
+ }
+
+ return fd;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : accept_connection
+ *
+ * Description : Accepts a connection on a socket. Socket must have
+ * been created using bind_port().
+ *
+ * Parameters :
+ * 1 : csp = Client state, cfd, ip_addr_str, and
+ * ip_addr_long will be set by this routine.
+ * 2 : fd = file descriptor returned from bind_port
+ *
+ * Returns : when a connection is accepted, it returns 1 (TRUE).
+ * On an error it returns 0 (FALSE).
+ *
+ *********************************************************************/
+int accept_connection(struct client_state * csp, int fd)
+{
+ struct sockaddr raddr;
+ struct sockaddr_in *rap = (struct sockaddr_in *) &raddr;
+ int afd, raddrlen;
+
+ raddrlen = sizeof raddr;
+ do
+ {
+ afd = accept (fd, &raddr, &raddrlen);
+ } while (afd < 1 && errno == EINTR);
+
+ if (afd < 0)
+ {
+ return 0;
+ }
+
+ csp->cfd = afd;
+ csp->ip_addr_str = strdup(inet_ntoa(rap->sin_addr));
+ csp->ip_addr_long = ntohl(rap->sin_addr.s_addr);
+
+ return 1;
+}
+
+
+/*********************************************************************
+ *
+ * Function : resolve_hostname_to_ip
+ *
+ * Description : Resolve a hostname to an internet tcp/ip address.
+ * NULL or an empty string resolve to INADDR_ANY.
+ *
+ * Parameters :
+ * 1 : host = hostname to resolve
+ *
+ * Returns : -1 => failure, INADDR_ANY or tcp/ip address if succesful.
+ *
+ *********************************************************************/
+int resolve_hostname_to_ip(const char *host)
+{
+ struct sockaddr_in inaddr;
+ struct hostent *hostp;
+
+ if ((host == NULL) || (*host == '\0'))
+ {
+ return(INADDR_ANY);
+ }
+
+ memset((char *) &inaddr, 0, sizeof inaddr);
+
+ if ((inaddr.sin_addr.s_addr = inet_addr(host)) == -1)
+ {
+ if ((hostp = gethostbyname(host)) == NULL)
+ {
+ errno = EINVAL;
+ return(-1);
+ }
+ if (hostp->h_addrtype != AF_INET)
+ {
+#ifdef _WIN32
+ errno = WSAEPROTOTYPE;
+#else
+ errno = EPROTOTYPE;
+#endif
+ return(-1);
+ }
+ memcpy(
+ (char *) &inaddr.sin_addr,
+ (char *) hostp->h_addr,
+ sizeof(inaddr.sin_addr)
+ );
+ }
+ return(inaddr.sin_addr.s_addr);
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _JBSOCKETS_H
+#define _JBSOCKETS_H
+#define JBSOCKETS_H_VERSION "$Id: jbsockets.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/jbsockets.h,v $
+ *
+ * Purpose : Contains wrappers for system-specific sockets code,
+ * so that the rest of JunkBuster can be more
+ * OS-independent. Contains #ifdefs to make this work
+ * on many platforms.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: jbsockets.h,v $
+ *
+ *********************************************************************/
+\f
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int connect_to(char *host, int portnum, struct client_state *csp);
+extern int write_socket(int fd, const char *buf, int n);
+extern int read_socket(int fd, char *buf, int n);
+extern void close_socket(int fd);
+
+extern int bind_port(const char *hostnam, int portnum);
+extern int accept_connection(struct client_state * csp, int fd);
+
+extern int resolve_hostname_to_ip(const char *host);
+
+/* Revision control strings from this header and associated .c file */
+extern const char jbsockets_rcs[];
+extern const char jbsockets_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _JBSOCKETS_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+const char jcc_rcs[] = "$Id: jcc.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/jcc.c,v $
+ *
+ * Purpose : Main file. Contains main() method, main loop, and
+ * the main connection-handling function.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: jcc.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#ifdef _WIN32
+
+# include <sys/timeb.h>
+# include <windows.h>
+# include <io.h>
+# include <process.h>
+# ifdef TOGGLE
+# include <time.h>
+# endif /* def TOGGLE */
+
+# include "win32.h"
+# ifndef _WIN_CONSOLE
+# include "w32log.h"
+# endif /* ndef _WIN_CONSOLE */
+
+#else /* ifndef _WIN32 */
+
+# include <unistd.h>
+# include <sys/time.h>
+# include <sys/wait.h>
+# include <sys/stat.h>
+# include <signal.h>
+
+# ifdef __BEOS__
+# include <socket.h> /* BeOS has select() for sockets only. */
+# include <OS.h> /* declarations for threads and stuff. */
+# endif
+
+# ifndef FD_ZERO
+# include <select.h>
+# endif
+
+#endif
+
+#include "project.h"
+#include "jcc.h"
+#include "filters.h"
+#include "loaders.h"
+#include "showargs.h"
+#include "parsers.h"
+#include "killpopup.h"
+#include "miscutil.h"
+#include "errlog.h"
+#include "jbsockets.h"
+#include "gateway.h"
+
+const char jcc_h_rcs[] = JCC_H_VERSION;
+const char project_h_rcs[] = PROJECT_H_VERSION;
+
+const char DEFAULT_USER_AGENT[] ="User-Agent: Mozilla (X11; I; Linux 2.0.32 i586)";
+
+struct client_state clients[1];
+struct file_list files[1];
+
+#ifdef STATISTICS
+int urls_read = 0; /* total nr of urls read inc rejected */
+int urls_rejected = 0; /* total nr of urls rejected */
+#endif /* def STATISTICS */
+
+
+static void listen_loop(void);
+static void chat(struct client_state *csp);
+static void serve(struct client_state *csp);
+#ifdef __BEOS__
+static int32 server_thread(void *data);
+#endif /* def __BEOS__ */
+
+
+#define BODY "<body bgcolor=\"#f8f8f0\" link=\"#000078\" alink=\"#ff0022\" vlink=\"#787878\">\n"
+
+static const char CFAIL[] =
+ "HTTP/1.0 503 Connect failed\n"
+ "Content-Type: text/html\n\n"
+ "<html>\n"
+ "<head>\n"
+ "<title>Internet Junkbuster: Connect failed</title>\n"
+ "</head>\n"
+ BODY
+ "<h1><center>"
+ BANNER
+ "</center></h1>"
+ "TCP connection to '%s' failed: %s.\n<br>"
+ "</body>\n"
+ "</html>\n";
+
+static const char CNXDOM[] =
+ "HTTP/1.0 404 Non-existent domain\n"
+ "Content-Type: text/html\n\n"
+ "<html>\n"
+ "<head>\n"
+ "<title>Internet Junkbuster: Non-existent domain</title>\n"
+ "</head>\n"
+ BODY
+ "<h1><center>"
+ BANNER
+ "</center></h1>"
+ "No such domain: %s\n"
+ "</body>\n"
+ "</html>\n";
+
+static const char CSUCCEED[] =
+ "HTTP/1.0 200 Connection established\n"
+ "Proxy-Agent: IJ/" VERSION "\n\n";
+
+static const char CHEADER[] =
+ "HTTP/1.0 400 Invalid header received from browser\n\n";
+
+static const char SHEADER[] =
+ "HTTP/1.0 502 Invalid header received from server\n\n";
+
+#if defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST)
+static const char BLANKGIF[] =
+ "HTTP/1.0 200 OK\r\n"
+ "Pragma: no-cache\r\n"
+ "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMT\r\n"\r
+ "Expires: Thu Jul 31, 1997 07:42:22 pm GMT\r\n"\r
+ "Content-type: image/gif\r\n\r\n"
+ "GIF89a\001\000\001\000\200\000\000\377\377\377\000\000"
+ "\000!\371\004\001\000\000\000\000,\000\000\000\000\001"
+ "\000\001\000\000\002\002D\001\000;";
+
+static const char JBGIF[] =
+ "HTTP/1.0 200 OK\r\n"
+ "Pragma: no-cache\r\n"
+ "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMT\r\n"\r
+ "Expires: Thu Jul 31, 1997 07:42:22 pm GMT\r\n"\r
+ "Content-type: image/gif\r\n\r\n"
+ "GIF89aD\000\013\000\360\000\000\000\000\000\377\377\377!"
+ "\371\004\001\000\000\001\000,\000\000\000\000D\000\013\000"
+ "\000\002a\214\217\251\313\355\277\000\200G&K\025\316hC\037"
+ "\200\234\230Y\2309\235S\230\266\206\372J\253<\3131\253\271"
+ "\270\215\342\254\013\203\371\202\264\334P\207\332\020o\266"
+ "N\215I\332=\211\312\3513\266:\026AK)\364\370\365aobr\305"
+ "\372\003S\275\274k2\354\254z\347?\335\274x\306^9\374\276"
+ "\037Q\000\000;";
+\r
+static const char FWGIF[] =\r
+ "HTTP/1.0 302 Blocked Advert\r\n" \r
+ "Pragma: no-cache\r\n"\r
+ "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMT\r\n"\r
+ "Expires: Thu Jul 31, 1997 07:42:22 pm GMT\r\n"\r
+ "Location: ";\r
+\r
+#endif /* defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST) */
+
+#ifdef _WIN32
+#define sleep(N) Sleep(((N) * 1000))
+#endif
+
+
+/*********************************************************************
+ *
+ * Function : chat
+ *
+ * Description : Once a connection to the client has been accepted,
+ * this function is called (via serve()) to handle the
+ * main business of the communication. When this
+ * function returns, the caller must close the client
+ * socket handle.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : On success, the number of bytes written are returned (zero
+ * indicates nothing was written). On error, -1 is returned,
+ * and errno is set appropriately. If count is zero and the
+ * file descriptor refers to a regular file, 0 will be
+ * returned without causing any other effect. For a special
+ * file, the results are not portable.
+ *
+ *********************************************************************/
+static void chat(struct client_state *csp)
+{
+ char buf[BUFSIZ], *hdr, *p, *req;
+ char *err = NULL;
+ char *eno;
+ fd_set rfds;
+ int n, maxfd, server_body, ms_iis5_hack = 0;
+ struct cookie_spec *cs;
+ const struct gateway *gw;
+ struct http_request *http;
+#ifdef PCRS
+ int filtering = 0;
+#endif /* def PCRS */
+
+ http = csp->http;
+
+ /*
+ * Read the client's request. Note that since we're not using select() we
+ * could get blocked here if a client connected, then didn't say anything!
+ */
+
+ while (FOREVER)
+ {
+ n = read_socket(csp->cfd, buf, sizeof(buf));
+
+ if (n <= 0) break; /* error! */
+
+ add_to_iob(csp, buf, n);
+
+ req = get_header(csp);
+
+ if (req == NULL)\r
+ {\r
+ break; /* no HTTP request! */\r
+ }
+
+ if (*req == '\0')\r
+ {\r
+ continue; /* more to come! */\r
+ }
+
+#ifdef FORCE_LOAD
+ /* If this request contains the FORCE_PREFIX,
+ * better get rid of it now and set the force flag --oes
+ */
+
+ if(strstr(req, FORCE_PREFIX))
+ {
+ strclean(req, FORCE_PREFIX);
+ /* if DEBUG(FRC) fprintf(logfp, "%s: Enforcing request \"%s\".\n", prog, req); */
+ csp->force = 1;
+ }
+ else
+ {
+ csp->force = 0;
+ }
+#endif /* def FORCE_LOAD */
+
+ parse_http_request(req, http, csp);
+ freez(req);
+ break;
+ }
+
+ if (http->cmd == NULL)
+ {
+ strcpy(buf, CHEADER);
+ write_socket(csp->cfd, buf, strlen(buf));
+ return;
+ }
+
+ /* decide how to route the HTTP request */
+
+ if ((gw = forward_url(http, csp)) == NULL)
+ {
+ log_error(LOG_LEVEL_ERROR, "gateway spec is NULL!?!? This can't happen!");
+ abort();
+ }
+
+ /* build the http request to send to the server
+ * we have to do one of the following:
+ *
+ * create = use the original HTTP request to create a new
+ * HTTP request that has only the path component
+ * without the http://domainspec
+ * pass = pass the original HTTP request unchanged
+ *
+ * drop = drop the HTTP request
+ *
+ * here's the matrix:
+ * SSL
+ * 0 1
+ * +--------+--------+
+ * | | |
+ * 0 | create | drop |
+ * | | |
+ * Forwarding +--------+--------+
+ * | | |
+ * 1 | pass | pass |
+ * | | |
+ * +--------+--------+
+ *
+ */
+
+ if (gw->forward_host)
+ {
+ /* if forwarding, just pass the request as is */
+ enlist(csp->headers, http->cmd);
+ }
+ else
+ {
+ if (http->ssl == 0)
+ {
+ /* otherwise elide the host information from the url */
+ p = NULL;
+ p = strsav(p, http->gpc);
+ p = strsav(p, " ");
+ p = strsav(p, http->path);
+ p = strsav(p, " ");
+ p = strsav(p, http->ver);
+ enlist(csp->headers, p);
+ freez(p);
+ }
+ }
+
+ /* decide what we're to do with cookies */
+
+#if defined(TOGGLE)
+ /*
+ * by haroon - most of credit to srt19170
+ * if toggled_on flag is false IJB is disabled, pass cookies thru
+ */
+ if (!csp->toggled_on)
+ {
+ csp->accept_server_cookie = 1;
+ csp->send_user_cookie = 1;
+ }
+ else
+#endif
+
+ if ((cs = cookie_url(http, csp)))
+ {
+ csp->accept_server_cookie = cs->accept_server_cookie;
+ csp->send_user_cookie = cs->send_user_cookie;
+ }
+ else
+ {
+ csp->accept_server_cookie = 0;
+ csp->send_user_cookie = 0;
+ }
+
+ /* grab the rest of the client's headers */
+
+ while (FOREVER)
+ {
+ if ( ( p = get_header(csp) ) && ( *p == '\0' ) )
+ {
+ n = read_socket(csp->cfd, buf, sizeof(buf));
+ if (n <= 0)
+ {
+ log_error(LOG_LEVEL_ERROR, "read from client failed: %E");
+ return;
+ }
+ add_to_iob(csp, buf, n);
+ continue;
+ }
+
+ if (p == NULL) break;
+
+ enlist(csp->headers, p);
+ freez(p);
+ }
+
+ /* filter it as required */
+
+ hdr = sed(client_patterns, add_client_headers, csp);
+
+ destroy_list(csp->headers);
+
+#ifdef TOGGLE
+ /*
+ * by haroon - most of credit to srt19170
+ * if toggled_on flag is true then IJB is enabled, do the usual
+ * otherwise avoid crunching
+ */
+
+/* This next line is a little ugly, but it simplifies the if statement below. */
+/* Basically if TOGGLE, then we want the if to test "csp->toggled_on", else we don't */
+#define IS_TOGGLED_ON csp->toggled_on &&
+
+#else /* ifndef TOGGLE */
+
+/* We don't have TOGGLE, so we don't care about toggling. */
+#define IS_TOGGLED_ON
+
+#endif /* ndef TOGGLE */
+
+
+#ifdef TRUST_FILES
+/* This next line is a little ugly, but it simplifies the if statement below. */
+/* Basically if TRUST_FILES, then we want the if to call "trust_url", else we don't */
+#define IS_TRUSTED_URL (p = trust_url(http, csp)) ||
+
+#else /* ifndef TRUST_FILES */
+
+/* We don't have TRUST_FILES, so we don't care about trusted URL's. */
+#define IS_TRUSTED_URL
+
+#endif /* ndef TRUST_FILES */
+
+
+ /* Check the request against all rules, unless
+ * we're disabled or in force mode.
+ */
+
+ if (IS_TOGGLED_ON
+#ifdef FORCE_LOAD
+ (!csp->force) &&
+#endif /* def FORCE_LOAD */
+ ( (p = intercept_url(http, csp)) ||
+ IS_TRUSTED_URL
+ (p = block_url(http, csp)) ))
+ {
+#ifdef STATISTICS
+ csp->rejected = 1;
+#endif /* def STATISTICS */
+
+ log_error(LOG_LEVEL_GPC, "%s%s crunch!", http->hostport, http->path);
+
+#if defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST)
+ /* now use block_imageurl */
+ if ( (tinygif > 0) && block_imageurl(http, csp) )
+ {
+ /* Send "blocked" image */
+ log_error(LOG_LEVEL_GPC, "%s%s image crunch!",
+ http->hostport, http->path);
+
+ if (tinygif == 1)
+ {
+ write_socket(csp->cfd, BLANKGIF, sizeof(BLANKGIF)-1);
+ }
+ else if ((tinygif == 3) && (tinygifurl))\r
+ {\r
+ write_socket(csp->cfd, FWGIF, sizeof(FWGIF)-1);\r
+ write_socket(csp->cfd, tinygifurl, strlen(tinygifurl));\r
+ }\r
+ else
+ {
+ write_socket(csp->cfd, JBGIF, sizeof(JBGIF)-1);
+ }
+ }
+ else
+#endif /* defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST) */
+ {
+ /* Send HTML "blocked" message */
+ write_socket(csp->cfd, p, strlen(p));
+ }
+
+ log_error(LOG_LEVEL_LOG, "%s", p);
+
+ freez(p);
+ freez(hdr);
+ return;
+ }
+
+ log_error(LOG_LEVEL_GPC, "%s%s", http->hostport, http->path);
+
+ if (gw->forward_host)
+ {
+ log_error(LOG_LEVEL_CONNECT, "via %s:%d to: %s",
+ gw->forward_host, gw->forward_port, http->hostport);
+ }
+ else
+ {
+ log_error(LOG_LEVEL_CONNECT, "to %s", http->hostport);
+ }
+
+ /* here we connect to the server, gateway, or the forwarder */
+
+ csp->sfd = (gw->conn)(gw, http, csp);
+
+ if (csp->sfd < 0)
+ {
+ log_error(LOG_LEVEL_CONNECT, "connect to: %s failed: %E",
+ http->hostport);
+
+ if (errno == EINVAL)
+ {
+ err = zalloc(strlen(CNXDOM) + strlen(http->host));
+ sprintf(err, CNXDOM, http->host);
+ }
+ else
+ {
+ eno = safe_strerror(errno);
+ err = zalloc(strlen(CFAIL) + strlen(http->hostport) + strlen(eno));
+ sprintf(err, CFAIL, http->hostport, eno);
+ }
+
+ write_socket(csp->cfd, err, strlen(err));
+
+ log_error(LOG_LEVEL_LOG, err);
+
+ freez(err);
+ freez(hdr);
+ return;
+ }
+
+ log_error(LOG_LEVEL_CONNECT, "OK");
+
+ if (gw->forward_host || (http->ssl == 0))
+ {
+ /* write the client's (modified) header to the server
+ * (along with anything else that may be in the buffer)
+ */
+
+ n = strlen(hdr);
+
+ if ((write_socket(csp->sfd, hdr, n) != n)
+ || (flush_socket(csp->sfd, csp ) < 0))
+ {
+ log_error(LOG_LEVEL_CONNECT, "write header to: %s failed: %E",
+ http->hostport);
+
+ eno = safe_strerror(errno);
+ err = zalloc(strlen(CFAIL) + strlen(http->hostport) + strlen(eno));
+ sprintf(err, CFAIL, http->hostport, eno);
+ write_socket(csp->cfd, err, strlen(err));
+
+ freez(err);
+ freez(hdr);
+ return;
+ }
+ }
+ else
+ {
+ /*
+ * We're running an SSL tunnel and we're not forwarding,
+ * so just send the "connect succeeded" message to the
+ * client, flush the rest, and get out of the way.
+ */
+ if (write_socket(csp->cfd, CSUCCEED, sizeof(CSUCCEED)-1) < 0)
+ {
+ freez(hdr);
+ return;
+ }
+ IOB_RESET(csp);
+ }
+
+ /* we're finished with the client's header */
+ freez(hdr);
+
+ maxfd = ( csp->cfd > csp->sfd ) ? csp->cfd : csp->sfd;
+
+ /* pass data between the client and server
+ * until one or the other shuts down the connection.
+ */
+
+ server_body = 0;
+
+ while (FOREVER)
+ {
+ FD_ZERO(&rfds);
+
+ FD_SET(csp->cfd, &rfds);
+ FD_SET(csp->sfd, &rfds);
+
+ n = select(maxfd+1, &rfds, NULL, NULL, NULL);
+
+ if (n < 0)
+ {
+ log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
+ return;
+ }
+
+ /* this is the body of the browser's request
+ * just read it and write it.
+ */
+
+ if (FD_ISSET(csp->cfd, &rfds))
+ {
+ n = read_socket(csp->cfd, buf, sizeof(buf));
+
+ if (n <= 0) break; /* "game over, man" */
+
+ if (write_socket(csp->sfd, buf, n) != n)
+ {
+ log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
+ return;
+ }
+ continue;
+ }
+
+ /*
+ * The server wants to talk. It could be the header or the body.
+ * If `hdr' is null, then it's the header otherwise it's the body.
+ * FIXME: Does `hdr' really mean `host'?
+ */
+
+
+ if (FD_ISSET(csp->sfd, &rfds))
+ {
+ fflush( 0 );
+ n = read_socket(csp->sfd, buf, sizeof(buf) - 1);
+
+ if (n < 0)
+ {
+ log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host);
+
+ eno = safe_strerror(errno);
+ sprintf(buf, CFAIL, http->hostport, eno);
+ freez(eno);
+ write_socket(csp->cfd, buf, strlen(buf));
+ return;
+ }
+
+ /* Add a trailing zero. This lets filter_popups
+ * use string operations.
+ */
+ buf[n] = '\0';
+
+#ifdef KILLPOPUPS
+ /* Filter the popups on this read. */
+ if ( IS_TOGGLED_ON
+ ( kill_all_popups ||
+ ( ( http->host != NULL ) && ( popupfile != NULL ) ) ) )
+ {
+ filter_popups(csp, http->host, buf, n);
+ }
+#endif /* def KILLPOPUPS */
+
+ /* Normally, this would indicate that we've read
+ * as much as the server has sent us and we can
+ * close the client connection. However, Microsoft
+ * in its wisdom has released IIS/5 with a bug that
+ * prevents it from sending the trailing \r\n in
+ * a 302 redirect header (and possibly other headers).
+ * To work around this if we've haven't parsed
+ * a full header we'll append a trailing \r\n
+ * and see if this now generates a valid one.
+ *
+ * This hack shouldn't have any impacts. If we've
+ * already transmitted the header or if this is a
+ * SSL connection, then we won't bother with this
+ * hack. So we only work on partially received
+ * headers. If we append a \r\n and this still
+ * doesn't generate a valid header, then we won't
+ * transmit anything to the client.
+ */
+ if (n == 0)
+ {
+ /* This hack must only be enforced for headers. */
+ if (server_body || http->ssl)
+ {
+#ifdef PCRS
+ if (filtering)
+ {
+ re_process_buffer(csp);
+ }
+#endif /* def PCRS */
+ break; /* "game over, man" */
+ }
+
+ /* Let's pretend the server just sent us a blank line. */
+ n = sprintf(buf, "\r\n");
+
+ /*
+ * Now, let the normal header parsing algorithm below do its
+ * job. If it fails, we'll exit instead of continuing.
+ */
+
+ ms_iis5_hack = 1;
+ }
+
+ /*
+ * If this is an SSL connection or we're in the body
+ * of the server document, just write it to the client.
+ */
+
+ if (server_body || http->ssl)
+ {
+#ifdef PCRS
+ if (filtering)
+ {
+ add_to_iob(csp, buf, n); /* Buffer the body for filtering */
+ }
+ else
+#endif /* def PCRS */
+ {
+ /* just write */
+ if (write_socket(csp->cfd, buf, n) != n)
+ {
+ log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
+ return;
+ }
+ }
+ continue;
+ }
+ else
+ {
+ /* we're still looking for the end of the
+ * server's header ... (does that make header
+ * parsing an "out of body experience" ?
+ */
+
+ /* buffer up the data we just read */
+ add_to_iob(csp, buf, n);
+
+ /* get header lines from the iob */
+
+ while ((p = get_header(csp)))
+ {
+ if (*p == '\0')
+ {
+ /* see following note */
+ break;
+ }
+ enlist(csp->headers, p);
+ freez(p);
+ }
+
+ /* NOTE: there are no "empty" headers so
+ * if the pointer `p' is not NULL we must
+ * assume that we reached the end of the
+ * buffer before we hit the end of the header.
+ */
+
+ if (p)
+ {
+ if (ms_iis5_hack)
+ {
+ /* Well, we tried our MS IIS/5
+ * hack and it didn't work.
+ * The header is incomplete
+ * and there isn't anything
+ * we can do about it.
+ */
+ break;
+ }
+ else
+ {
+ /* Since we have to wait for
+ * more from the server before
+ * we can parse the headers
+ * we just continue here.
+ */
+ continue;
+ }
+ }
+
+ /* we have now received the entire header.
+ * filter it and send the result to the client
+ */
+
+ hdr = sed(server_patterns, add_server_headers, csp);
+ n = strlen(hdr);
+
+ /* write the server's (modified) header to
+ * the client (along with anything else that
+ * may be in the buffer)
+ */
+
+#ifdef PCRS
+ /* Decide if we want to re_filter this. */
+
+ if (IS_TOGGLED_ON /* Only filter if toggle is "on" */
+ csp->is_text && /* It's a text / * MIME-Type */
+ re_filterfile && /* There are expressions to be used */
+ !http->ssl && /* We talk plaintext */
+ (re_filter_all || !csp->send_user_cookie)) /* Policy allows */
+ {
+ filtering = 1;
+ }
+
+/* This next line is a little ugly, but it simplifies the if statement below. */
+/* Basically if using PCRS, we want the OR condition to require "!filtering" */
+#define NOT_FILTERING_AND !filtering &&
+
+#else /* not def PCRS */
+
+#define NOT_FILTERING_AND
+
+#endif /* def PCRS */
+
+
+ if ((write_socket(csp->cfd, hdr, n) != n)
+ || (NOT_FILTERING_AND (flush_socket(csp->cfd, csp) < 0)))
+ {
+ log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E");
+
+ /* the write failed, so don't bother
+ * mentioning it to the client...
+ * it probably can't hear us anyway.
+ */
+ freez(hdr);
+ return;
+ }
+
+ /* we're finished with the server's header */
+
+ freez(hdr);
+ server_body = 1;
+
+ /* If this was a MS IIS/5 hack then it means
+ * the server has already closed the
+ * connection. Nothing more to read. Time
+ * to bail.
+ */
+ if (ms_iis5_hack)
+ {
+ break;
+ }
+ }
+ continue;
+ }
+
+ return; /* huh? we should never get here */
+ }
+
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : serve
+ *
+ * Description : This is little more than chat. We only "serve" to
+ * to close any socket that chat may have opened.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void serve(struct client_state *csp)
+{
+ chat(csp);
+ close_socket(csp->cfd);
+
+ if (csp->sfd >= 0)
+ {
+ close_socket(csp->sfd);
+ }
+
+ csp->active = 0;
+
+}
+
+
+#ifdef __BEOS__
+
+/*********************************************************************
+ *
+ * Function : server_thread
+ *
+ * Description : We only exist to call `serve' in a threaded environment.
+ *
+ * Parameters :
+ * 1 : data = Current client state (buffers, headers, etc...)
+ *
+ * Returns : Always 0.
+ *
+ *********************************************************************/
+static int32 server_thread(void *data)
+{
+ serve((struct client_state *) data);
+ return 0;
+
+}
+
+#endif
+
+
+/*********************************************************************
+ *
+ * Function : main
+ *
+ * Description : Load the config file and start the listen loop.
+ * This function is a lot more *sane* with the `load_config'
+ * and `listen_loop' functions; although it stills does
+ * a *little* too much for my taste.
+ *
+ * Parameters :
+ * 1 : argc = Number of parameters (including $0).
+ * 2 : argv = Array of (char *)'s to the parameters.
+ *
+ * Returns : 1 if : can't open config file, unrecognized directive,
+ * stats requested in multi-thread mode, can't open the
+ * log file, can't open the jar file, listen port is invalid,
+ * any load fails, and can't bind port.
+ *
+ * Else main never returns, the process must be signaled
+ * to terminate execution. Or, on Windows, use the
+ * "File", "Exit" menu option.
+ *
+ *********************************************************************/
+#ifdef __MINGW32__
+int _main(int argc, const char *argv[])
+#else
+int main(int argc, const char *argv[])
+#endif
+{
+ configfile =
+#ifndef _WIN32
+ "config"
+#else
+ "junkbstr.txt"
+#endif
+ ;
+
+#if !defined(_WIN32) || defined(_WIN_CONSOLE)
+ if ((argc >= 2) && (strcmp(argv[1], "--help")==0))
+ {
+ printf("JunkBuster proxy version " VERSION ".\n\n"
+ "Usage: %s [configfile]\n\n"
+ "See " HOME_PAGE_URL " for details.\n"
+ "This program is distributed under the GNU GPL, version 2 or later.\n",
+ argv[0]);
+ exit(2);
+ }
+ if ((argc >= 2) && (strcmp(argv[1], "--version")==0))
+ {
+ printf(VERSION "\n");
+ exit(2);
+ }
+#endif /* !defined(_WIN32) || defined(_WIN_CONSOLE) */
+
+ Argc = argc;
+ Argv = argv;
+
+ if (argc > 1)
+ {
+ configfile = argv[1];
+ }
+
+ remove_all_loaders();
+ memset( proxy_args, 0, sizeof( proxy_args ) );
+ files->next = NULL;
+
+ load_config( 0 );
+
+ /*
+ * Since load_config acts as a signal handler too, it returns
+ * its status in configret. Check it for an error in loading.
+ */
+ if ( 0 != configret )
+ {
+ /* load config failed! Exit with error. */
+ return( 1 );
+ }
+
+#ifdef _WIN32
+ InitWin32();
+#endif
+
+
+#ifndef _WIN32
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGCHLD, SIG_IGN);
+ signal(SIGHUP, load_config);
+
+#else /* ifdef _WIN32 */
+# ifdef _WIN_CONSOLE
+ /*
+ * We *are* in a windows console app.
+ * Print a verbose messages about FAQ's and such
+ */
+ printf(win32_blurb);
+# endif /* def _WIN_CONSOLE */
+#endif /* def _WIN32 */
+
+
+ listen_loop();
+
+ /* NOTREACHED */
+ return(-1);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : listen_loop
+ *
+ * Description : bind the listen port and enter a "FOREVER" listening loop.
+ *
+ * Parameters : N/A
+ *
+ * Returns : Never.
+ *
+ *********************************************************************/
+static void listen_loop(void)
+{
+ struct client_state *csp = NULL;
+ int bfd;
+
+ log_error(LOG_LEVEL_CONNECT, "bind (%s, %d)",
+ haddr ? haddr : "INADDR_ANY", hport);
+
+ bfd = bind_port(haddr, hport);
+ config_changed = 0;
+
+ if (bfd < 0)
+ {
+ log_error(LOG_LEVEL_ERROR, "can't bind %s:%d: %E "
+ "- There may be another junkbuster or some other "
+ "proxy running on port %d",
+ (NULL != haddr) ? haddr : "INADDR_ANY", hport, hport
+ );
+ return;
+ }
+
+
+ while (FOREVER)
+ {
+#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)
+ while (waitpid(-1, NULL, WNOHANG) > 0)
+ {
+ /* zombie children */
+ }
+#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
+ sweep();
+
+ if ( NULL == (csp = (struct client_state *) malloc(sizeof(*csp))) )
+ {
+ log_error(LOG_LEVEL_ERROR, "malloc(%d) for csp failed: %E", sizeof(*csp));
+ continue;
+ }
+
+ memset(csp, '\0', sizeof(*csp));
+
+ csp->active = 1;
+ csp->sfd = -1;
+
+ if ( config_changed )
+ {
+ /*
+ * Since we were listening to the "old port", we will not see
+ * a "listen" param change until the next IJB request. So, at
+ * least 1 more request must be made for us to find the new
+ * setting. I am simply closing the old socket and binding the
+ * new one.
+ *
+ * Which-ever is correct, we will serve 1 more page via the
+ * old settings. This should probably be a "show-proxy-args"
+ * request. This should not be a so common of an operation
+ * that this will hurt people's feelings.
+ */
+ close_socket(bfd);
+
+ log_error(LOG_LEVEL_CONNECT, "bind (%s, %d)",
+ haddr ? haddr : "INADDR_ANY", hport);
+ bfd = bind_port(haddr, hport);
+
+ config_changed = 0;
+ }
+
+ log_error(LOG_LEVEL_CONNECT, "accept connection ... ");
+
+ if (!accept_connection(csp, bfd))
+ {
+ log_error(LOG_LEVEL_CONNECT, "accept failed: %E");
+\r
+#ifdef AMIGA\r
+ if(!childs)\r
+ {\r
+ exit(1); \r
+ }\r
+#endif\r
+ continue;
+ }
+ else
+ {
+ log_error(LOG_LEVEL_CONNECT, "OK");
+ }
+
+#if defined(TOGGLE)
+ /* by haroon - most of credit to srt19170 */
+ csp->toggled_on = g_bToggleIJB;
+#endif
+
+ /* add it to the list of clients */
+ csp->next = clients->next;
+ clients->next = csp;
+
+ if (run_loader(csp))
+ {
+ log_error(LOG_LEVEL_ERROR, "a loader failed - must exit");
+ return;
+ }
+
+ if (multi_threaded)
+ {
+ int child_id;
+
+/* this is a switch () statment in the C preprocessor - ugh */
+#undef SELECTED_ONE_OPTION
+
+#if defined(_WIN32) && !defined(_CYGWIN) && !defined(SELECTED_ONE_OPTION)
+#define SELECTED_ONE_OPTION
+ child_id = _beginthread(
+ (void*)serve,
+ 64 * 1024,
+ csp);
+#endif
+
+#if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
+#define SELECTED_ONE_OPTION
+ {
+ thread_id tid = spawn_thread
+ (server_thread, "server", B_NORMAL_PRIORITY, csp);
+
+ if ((tid >= 0) && (resume_thread(tid) == B_OK))
+ {
+ child_id = (int) tid;
+ }
+ else
+ {
+ child_id = -1;
+ }
+ }
+#endif
+
+#if defined(AMIGA) && !defined(SELECTED_ONE_OPTION)\r
+#define SELECTED_ONE_OPTION\r
+ csp->cfd = ReleaseSocket(csp->cfd, -1);\r
+ if((child_id = (int)CreateNewProcTags(\r
+ NP_Entry, (ULONG)server_thread,\r
+ NP_Output, Output(),\r
+ NP_CloseOutput, FALSE,\r
+ NP_Name, (ULONG)"junkbuster child",\r
+ NP_StackSize, 20*1024,\r
+ TAG_DONE)))\r
+ {\r
+ childs++;\r
+ ((struct Task *)child_id)->tc_UserData = csp;\r
+ Signal((struct Task *)child_id, SIGF_SINGLE);\r
+ Wait(SIGF_SINGLE);\r
+ }\r
+#endif\r
+\r
+#if !defined(SELECTED_ONE_OPTION)
+ child_id = fork();
+#endif
+
+#undef SELECTED_ONE_OPTION
+/* end of cpp switch () */
+
+ if (child_id < 0) /* failed */
+ {
+ char buf[BUFSIZ];
+
+ log_error(LOG_LEVEL_ERROR, "can't fork: %E");
+
+ sprintf(buf , "JunkBuster: can't fork: errno = %d", errno);
+
+ write_socket(csp->cfd, buf, strlen(buf));
+ close_socket(csp->cfd);
+ csp->active = 0;
+ sleep(5);
+ continue;
+ }
+
+#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)
+ /* This block is only needed when using fork().
+ * When using threads, the server thread was
+ * created and run by the call to _beginthread().
+ */
+ if (child_id == 0) /* child */
+ {
+ serve(csp);
+ _exit(0);
+
+ }
+ else /* parent */
+ {
+ /* in a fork()'d environment, the parent's
+ * copy of the client socket and the CSP
+ * are not used.
+ */
+
+#if !defined(_WIN32) && defined(__CYGWIN__)
+ wait( NULL );
+#endif /* !defined(_WIN32) && defined(__CYGWIN__) */
+ close_socket(csp->cfd);
+ csp->active = 0;
+ }
+#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
+ }
+ else
+ {
+ serve(csp);
+ }
+ }
+ /* NOTREACHED */
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _JCC_H
+#define _JCC_H
+#define JCC_H_VERSION "$Id: jcc.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/jcc.h,v $
+ *
+ * Purpose : Main file. Contains main() method, main loop, and
+ * the main connection-handling function.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: jcc.h,v $
+ *
+ *********************************************************************/
+\f
+
+/* Declare struct FILE for vars and funcs. */
+#include <stdio.h>
+
+/* All of our project's data types. */
+#include "project.h"
+
+#include "loadcfg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define freez(X) if(X) free(X); X = NULL
+
+
+/* Global variables */
+
+
+#ifdef STATISTICS
+extern int urls_read;
+extern int urls_rejected;
+#endif /*def STATISTICS*/
+
+extern struct client_state clients[];
+
+extern struct file_list files[];
+
+/* Global constants */
+
+extern const char DEFAULT_USER_AGENT[];
+
+
+/* Functions */
+
+#ifdef __MINGW32__
+int _main(int argc, const char *argv[]);
+#else
+int main(int argc, const char *argv[]);
+#endif
+
+/* Revision control strings from this header and associated .c file */
+extern const char jcc_rcs[];
+extern const char jcc_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _JCC_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+# Sample Configuration file for the Internet Junkbuster 2.0
+
+#
+# $Id: config,v 1.2 2001/04/30 03:05:11 rodney Exp $
+#
+
+#
+#
+# Copyright 1997-8 Junkbusters Corp. For distribution, modification and use
+# under the GNU General Public License. These files come with NO WARRANTY.
+# See http://www.junkbusters.com/ht/en/gpl.html or README file for details.
+#
+# When starting the proxy, give the name of this file as an argument.
+# Any changes made to this file are *not* automatically loaded; you have
+# to stop and restart the proxy.
+
+# For information see http://www.junkbusters.com/ht/en/ijbman.html
+# or the documentation that came with the release
+
+# Lines beginning with a # character are comments; they are ignored.
+# Many example lines are provided here commented out
+
+# the blockfile contains patterns to be blocked by the proxy
+blockfile ./blocklist # comments are OK here, too
+
+# the imagefile contains patterns to detect blocked images
+imagefile ./imagelist
+
+# the popfile contains patterns of servers where javascript popups are disabled
+#
+# if the next line is not commented out, all javascript popups from the sites
+# that match the patterns in popup will be blocked
+# popupfile ./popup
+
+# File containing content modification rules
+#re_filterfile ./re_filterfile
+
+# Uncomment to filter *all* traffic. Default is to
+# filter only if we wouldn't send a cookie either.
+#
+#re_filter_all
+
+
+# the cookiefile contains patterns to specify the cookie management policy
+#
+cookiefile ./cookiefile
+
+# the logfile is where all logging and error messages are written
+#
+logfile ./junkbuster.log
+
+# the jarfile is where cookies can be stored
+#
+#jarfile ./jarfile
+
+# the forwardfile defines domain-specific routing
+#
+forwardfile ./forward
+
+# file which lists and into which trusted domains are written
+#
+#trustfile ./trust
+# files specify locations of "for information about trusted referers, see.."
+# multiple trust_info_url lines are OK
+#
+# trust_info_url http://internet.junkbuster.com/
+# trust_info_url http://www.yoursite.com/our_trust_policy.html
+#
+
+# The access control list file can be used to restrict IP addresses
+# that are permitted to use the proxy (see warnings in the FAQ).
+#
+#aclfile ./aclfile
+
+# add an "X-Forwarded-For:" specification to each request header
+#
+#add-forwarded-header
+
+# if logging cookies into a jarfile, and no other wafers were
+# explicity set, then by default a vanilla wafer is sent with
+# each request.
+#
+# setting 'suppress-vanilla-wafer' stops this vanilla wafer from
+# being sent.
+#
+suppress-vanilla-wafer
+
+# add these wafers to each request header
+# multiple wafer lines are OK
+#
+#wafer NOTE=Like most people, I want my browsing to be anonymous.
+#wafer WARNING=Please do not attempt to track me.
+
+# Anything can be added to the request headers. Please don't litter.
+# multiple add-header lines are OK
+#
+#add-header Forwarded: by http://stay-out-of-my-backyard.net
+#add-header Forwarded: by http://pro-privacy-isp.net
+#add-header Proxy-Connection: Keep-Alive
+
+# listen-address specifies where the Junkbuster will listen for connections
+# Specifying a port is optional; if unspecified the defaults is 8000.
+# Before Version 2.0.2 the default was to bind to all IP addresses (INADDR_ANY)
+# This has been restricted to localhost to avoid unintended security breaches.
+# To open the proxy to all, uncomment the following line:
+#listen-address :8000
+# other example usage:
+#listen-address 124.207.250.245:8080
+# to explicitly state what is now the default:
+#listen-address localhost
+# or equivalently:
+listen-address 127.0.0.1:8000
+
+# user-agent specifies treatment of the "User-Agent:" (and "UA-*:") header(s)
+# default: Forge the "User-Agent:"
+# 'text' : Always send <text> as the "User-Agent:"
+# . : Pass the "User-Agent:" unchanged
+# @ : Pass the "User-Agent:" if the server is in the cookie file,
+# forge the "User-Agent:" otherwise
+#user-agent @
+
+# note: Russian browsers may be confused if user agent misidentifies
+# the operating system (Mac vs Windows); see FAQ
+user-agent .
+
+# referer specifies treatment of the "Referer:" header
+# New option by "Andreas S. Oesterhelt" <oes@paradis.rhein.de>
+#
+# default: Kill the referrer-header from the client
+# 'text' : Always send <text> as the referrer
+# . : Pass the referrer unchanged
+# @ : Pass the referrer if the server is in the cookie file,
+# kill the referrer otherwise
+# § : Pass the referrer if the server is in the cookie file,
+# send a forged referrer that points to the root-diretory URL
+# of the current request otherwise
+referer §
+
+# from specifies value to be subsituted if browser provides a "From:" header
+#
+#from spam-me-senseless@sittingduck.net
+
+# tinygif allows you to change the appearance of blocked images
+#
+# tinygif 0 # Show a "broken icon"
+# tinygif 1 # Show a GIF of one transparent pixel
+tinygif 2 # Show a GIF with the word "JUNKBUSTER"
+# tinygif 3 http://localhost/1x1.gif # Temporary redirect to this URL
+
+# Andrew <anw@tirana.freewire.co.uk> added
+# The following can be used to suppress display of the block lists when the
+# page http://x.x/show-proxy-args is displayed. With a long block list this
+# accelerates loading of the configuration page and also hides the contents of
+# the block lists (for whatever reason). Maintainers of junkbuster proxies for
+# multiple use can specify a message for any use who wants to know what is in
+# these files.
+#
+#suppress-blocklists Contact sysadmin@example.com for details.
+# suppress-blocklists
+
+# debug sets the level of debugging information to log in the logfile
+#
+# debug 1 # GPC = show each GET/POST/CONNECT request
+# debug 2 # CONN = show each connection status
+# debug 4 # IO = show I/O status
+# debug 8 # HDR = show header parsing
+# debug 16 # LOG = log all data into the logfile
+# debug 32 # FRC = debug force feature
+# debug 64 # REF = debug regular expression filter
+#
+# multiple "debug" directives, are OK - they're logical-OR'd together
+#
+#debug 15 # same as setting the first 4 listed above
+debug 1
+# debug 255 # Log *everything*
+
+# single-threaded operation (i.e. disallows multiple threads or processes)
+# This is most often used for debugging because it keeps the
+# debugging output "in order" for easy reading.
+#
+#single-threaded
+
+# Toggle flag. 0 => disabled, anything else (ie. 1) => enabled
+toggle 1
+
+
+# Win32 GUI specific options. Moved here from ijbw32.ini
+# in hopes of keep all of our config settings together.
+
+activity-animation 1
+log-messages 1
+log-highlight-messages 1
+log-buffer-size 1
+log-max-lines 200
+log-font-name Comic Sans MS
+log-font-size 8
+show-on-task-bar 0
+close-button-minimizes 1
+
+# hide-console is used only on Win32 console mode. It instructs
+# the Internet Junkbuster to disconnect from and hide the
+# command console.
+#
+#hide-console
+
+
--- /dev/null
+.TH JUNKBUSTER 1 "http://www.junkbusters.com/ht/en/ijb2.0man.html"\r
+.SH NAME\r
+\fBjunkbuster\fP\r
+- The\r
+Internet Junkbuster\r
+Proxy\r
+\s-2(TM)\s+2\r
+.SH SYNOPSIS\r
+\fBjunkbuster\fP\r
+\fI\&configfile\fP\r
+(Version 2.0 onwards)\r
+.br\r
+\fBjunkbstr.exe\fP\r
+\fI\&configfile\fP\r
+(Windows)\r
+.br\r
+\fBjunkbuster\fP\r
+[-a]\r
+[-y]\r
+[-s]\r
+[-c]\r
+[-v]\r
+.br\r
+[-u user_agent]\r
+[-r referer]\r
+[-t from]\r
+.br\r
+[-b blockfile]\r
+[-j jarfile]\r
+[-l logfile]\r
+.br\r
+[-w NAME=VALUE]\r
+[-x Header_text]\r
+.br\r
+[-h [bind_host_address][:bind_port]]\r
+.br\r
+[-f forward_host[:port]]\r
+[-d N]\r
+.br\r
+[-g gw_protocol[:[gw_host][:gw_port]]]\r
+.br\r
+(Version 1.4 and earlier)\r
+.SH DESCRIPTION\r
+\fBjunkbuster\fP\r
+is an instrumentable proxy that filters the \r
+\s-2HTTP\s0\r
+stream between\r
+web servers and browsers.\r
+Its main purpose is to enhance privacy.\r
+.P\r
+Versions before 2.0 used command-line options;\r
+Versions from 2.0 onward use a configuration file.\r
+The following descriptions of the options first give the older\r
+command-line usage, then the new configfile line.\r
+.P\r
+In Versions 2.0.1 upwards on Windows,\r
+a start-up message is printed and the configuration is read from the file\r
+\fC\&junkbstr.ini\fP\r
+if it exists and no argument was given.\r
+.P\r
+All files except the configfile\r
+are checked for changes before each page is fetched,\r
+so they may edited without restarting the proxy.\r
+.SS OPTIONS\r
+.TP\r
+.\" anchor: o_b blockfile\r
+\fI-b blockfile\fP (Old) blockfile \fIblockfile\fP (New)\r
+Block\" ijbfaq.html#blocking\r
+requests to\r
+\s-2URL\s0s\r
+matching any pattern given in the lines of the\r
+\fI\&blockfile\fP.\r
+The\r
+\fBjunkbuster\fP\r
+instead returns status 202, indicating that the request has been accepted\r
+(though not completed),\r
+and a\r
+message identifying itself\" ijbfaq.html#show\r
+(though the browser may\r
+display only a broken image icon).\r
+(Versions before 2.0 returned an error 403 (Forbidden).)\r
+The syntax of a pattern is\r
+\fB\&[domain][:port][/path]\fP\r
+(the\r
+\fB\&http://\fP\r
+or\r
+\fB\&https://\fP\r
+protocol part is omitted).\r
+To decide if a pattern matches a target, the domains are compared first,\r
+then the paths. \r
+.P\r
+To compare the domains,\r
+the pattern domain and the target\r
+domain specified in the\r
+\s-2URL\s0\r
+are each broken into their components.\r
+(Components are separated by the\r
+\fC\&.\fP\r
+(period) character.)\r
+Next each of the target components\r
+is compared with the corresponding pattern component: last with last,\r
+next-to-last with next-to-last, and so on.\r
+(This is called\r
+\fIright-anchored\fP\r
+matching.)\r
+If all of the pattern components find their match in the target,\r
+then the domains are considered a match.\r
+Case is irrelevant when comparing domain components.\r
+.P\r
+A successfully\r
+matching pattern can be an anchored substring of a target, but\r
+not vice versa.\r
+Thus if a pattern doesn't specify a domain,\r
+it matches all domains.\r
+.\" anchor: wildcard\r
+Furthermore, when comparing two components,\r
+the components must either match in their entirety or up to a wildcard\r
+\fC\&* \fP\r
+(star character) in the pattern. The wildcard feature\r
+implements only a "prefix" match capability ("abc*" vs. "abcdefg"),\r
+not suffix matching ("*efg" vs. "abcdefg") or\r
+infix matching ("abc*efg" vs. "abcdefg").\r
+The feature is restricted to the domain component;\r
+it is unrelated to the optional\r
+regular expression\r
+feature in the path\r
+(described below).\" ijbman.html#regex\r
+.P\r
+If a numeric port\r
+is specified in the pattern domain, then the target port must\r
+match as well. The default port in a target is port 80.\r
+.P\r
+If the domain and port match,\r
+then the target\r
+\s-2URL\s0\r
+path is checked for\r
+a match against the path in the pattern.\r
+Paths are compared with a simple case-sensitive\r
+left-anchored substring comparison.\r
+Once again, the pattern can be an\r
+anchored substring of the target, but not vice versa.\r
+A path of\r
+\fC\&/\fP\r
+(slash) would match all paths. Wildcards are not considered in\r
+path comparisons.\r
+.P\r
+For example, the target\r
+\s-2URL\s0\r
+.br\r
+.ti +0.25i\r
+\fB\&the.yellow-brick-road.com/TinMan/has_no_brain\fP\r
+.br\r
+would be matched (and blocked) by the following patterns\r
+.br\r
+.ti +0.25i\r
+\fB\&yellow-brick-road.com\fP\r
+.br\r
+and\r
+.br\r
+.ti +0.25i\r
+\fB\&Yellow*.COM\fP\r
+.br\r
+and\r
+.br\r
+.ti +0.25i\r
+\fB\&/TinM\fP\r
+.br\r
+but not\r
+.br\r
+.ti +0.25i\r
+\fB\&follow.the.yellow-brick-road.com\fP\r
+.br\r
+or\r
+.br\r
+.ti +0.25i\r
+\fB\&/tinman\fP\r
+.br\r
+.P\r
+Comments in a blockfile start with a\r
+\fB\&#\fP\r
+(hash) character and end at a new line.\r
+Blank lines are also ignored.\r
+.P\r
+Lines beginning with a\r
+\fC\&~\fP\r
+(tilde) character are taken to be\r
+exceptions:\" ijbfaq.html#exceptions\r
+a\r
+\s-2URL\s0\r
+blocked by previous patterns that matches the rest of\r
+the line is let through. (The last match wins.)\r
+.P\r
+Patterns\r
+may contain\r
+\s-2POSIX\s0\r
+regular expressions\" ijbfaq.html#regex\r
+provided the\r
+\fBjunkbuster\fP\r
+was compiled with this option\r
+(the default in Version 2.0 on).\r
+The idiom\r
+\fC\&/*.*/ad\fP\r
+can then be used\r
+to match any\r
+\s-2URL\s0\r
+containing\r
+\fC\&/ad\fP\r
+(such as\r
+\fC\&http://nomatterwhere.com/images/advert/g3487.gif\fP\r
+for example).\r
+These expressions\r
+don't work\" ijbman.html#substring\r
+in the domain part.\r
+.P\r
+In version 1.3 and later\r
+the blockfile and cookiefile are checked for changes before each request.\r
+.TP\r
+tinygif \fIN\fP\r
+Set appearance of blocked GIFs. You can select one of the following\r
+values:\r
+.br\r
+.br\r
+\h'-\w"0 = "u'0 = Show a ``broken icon'' in the browser\r
+.br\r
+\h'-\w"1 = "u'1 = Show a one pixel transparent GIF\r
+.br\r
+\h'-\w"2 = "u'2 = Show a GIF with the word ``JUNKBUSTER''\r
+.TP\r
+popupfile \fI\&popup\fP\r
+Sets the name of the popupfile. If uncommented, the popupfile\r
+controls on which sites Javascript popup windows are disabled.\r
+.TP\r
+.\" anchor: o_w wafer\r
+\fI-w NAME=VALUE\fP (Old) wafer \fINAME=VALUE\fP (New)\r
+Specifies a pair to be sent as a cookie with every request\r
+to the server.\" ijbfaq.html#wafers\r
+(Such boring cookies are called\r
+\fI\&wafers\fP.)\r
+This option may be called more than once to generate multiple wafers.\r
+The original\r
+Netscape specification\r
+prohibited\r
+semi-colons, commas and white space;\r
+these characters will be\r
+\s-2URL\s0-encoded\r
+if used in wafers.\r
+The Path and Domain attributes are not currently supported.\r
+.TP\r
+.\" anchor: o_c cookiefile\r
+\fI-c cookiefile\fP (Old) cookiefile \fIcookiefile\fP (New)\r
+Enforce the cookie management policy specified in the\r
+\fI\&cookiefile.\fP\r
+.\" anchor: java\r
+If this option is not used all cookies are silently crunched,\r
+so that users who never want cookies aren't bothered by browsers\r
+asking whether each cookie should be accepted.\r
+However, cookies can\r
+still get through\" ijbfaq.html#breakthrough\r
+via\r
+JavaScript\" links.html#javascript\r
+and\r
+\s-2SSL\s0,\r
+so alerts should be left on.\r
+.P\r
+In Version 1.2 and later\r
+this option must be followed by a\r
+filename\" ijbfaq.html#crumble\r
+containing instructions on which sites are allowed to\r
+receive and set cookies.\r
+.\" anchor: drop\r
+By default cookies are dropped in both the browser's request\r
+and the server's response, unless the\r
+\s-2URL\s0\r
+requested matches an entry in the\r
+\fI\&cookiefile\fP.\r
+The matching algorithm is the same as for the blockfile.\r
+A leading\r
+\fC\&>\fP\r
+character allows\r
+server-bound\" ijbfaq.html#directional\r
+cookies only;\r
+a\r
+\fC\&<\fP\r
+allows only browser-bound cookies;\r
+a\r
+\fC\&~\fP\r
+character stops cookies in\r
+both directions.\" ijbfaq.html#crumble\r
+Thus a cookiefile containing a single line with the two characters\r
+\fC\&>*\fP\r
+will pass on all cookies to servers but not give any new ones to the browser.\r
+.TP\r
+.\" anchor: o_j jarfile\r
+\fI-j jarfile\fP (Old) jarfile \fIjarfile\fP (New)\r
+All Set-cookie attempts by the server are\r
+logged\" ijbfaq.html#jar\r
+to\r
+\fI\&jarfile\fP.\r
+If no wafer is specified,\r
+one containing a\r
+canned notice\" ijbfaq.html#notice\r
+(the \r
+\fI\&vanilla wafer\fP)\r
+is added as an alert to the server\r
+unless the\r
+suppress-vanilla-wafer\" ijbman.html#suppress-vanilla-wafer\r
+option is invoked.\r
+.TP\r
+.\" anchor: o_v suppress-vanilla-wafer\r
+\fI-v\fP (Old) suppress-vanilla-wafer \fI\fP (New)\r
+Suppress the vanilla wafer.\r
+.TP\r
+.\" anchor: o_t from\r
+\fI-t from\fP (Old) from \fIfrom\fP (New)\r
+If the browser\r
+discloses an email address\" ijbfaq.html#from\r
+in the\r
+\fB\&FROM\fP\r
+header (most don't),\r
+replace it with\r
+\fI\&from.\fP\r
+If\r
+\fI\&from\fP\r
+is set to\r
+\fB\&.\fP\r
+(the period character)\r
+the\r
+\fB\&FROM\fP\r
+is passed to the server unchanged.\r
+The default is to delete the\r
+\fB\&FROM\fP\r
+header.\r
+.TP\r
+.\" anchor: o_r referer\r
+\fI-r referer\fP (Old) referer \fIreferer\fP (New)\r
+Whenever the browser discloses the\r
+\s-2URL\s0\r
+that\r
+led to\" ijbfaq.html#referer\r
+the current request,\r
+replace it with\r
+\fI\&referer.\fP\r
+If\r
+\fI\&referer\fP\r
+is set to\r
+\fB\&.\fP\r
+(period)\r
+the \r
+\s-2URL\s0\r
+is passed to the server unchanged.\r
+In \r
+Version 1.4\r
+and later, if referer is set to \r
+\fB\&@\fP\r
+(at) the\r
+\s-2URL\s0\r
+is sent in cases where the cookiefile\r
+specifies that a cookie would be sent.\r
+(No way to send bogus referers selectively is provided.)\r
+The default is to delete Referer.\r
+.P\r
+Version 2.0 also accepts the spelling\r
+\fC\&referrer\fP,\r
+which most dictionaries consider correct.\r
+.TP\r
+.\" anchor: o_u user-agent\r
+\fI-u user-agent\fP (Old) user-agent \fIuser-agent\fP (New)\r
+Information disclosed by the browser\r
+about itself\" ijbfaq.html#agent\r
+is replaced with the value\r
+\fI\&user-agent.\fP\r
+If\r
+\fI\&user-agent\fP\r
+is set to\r
+\fB\&.\fP\r
+(period)\r
+the\r
+\fB\&User-Agent\fP\r
+header is passed to the server unchanged,\r
+along with any\r
+\fB\&UA\fP\r
+headers produced by\r
+\s-2MS-IE\s0\r
+(which would otherwise be deleted).\r
+In \r
+Version 1.4\r
+and later, if\r
+\fI\&user-agent\fP\r
+is set to\r
+\fB\&@\fP\r
+(at) these headers are sent unchanged in cases where the cookiefile\r
+specifies that a cookie would be sent,\r
+otherwise only default\r
+\fB\&User-Agent\fP\r
+header is sent.\r
+That default\r
+is Mozilla/3.0 (Netscape)\r
+with an unremarkable\r
+Macintosh\" ijbfaq.html#infer\r
+configuration.\r
+If used with a browser less advanced than Mozilla/3.0 or IE-3, the default\r
+may encourage pages containing extensions that confuse the browser.\r
+.TP\r
+.\" anchor: o_h listen-address\r
+\fI-h [host][:port]\fP (Old) listen-address \fI[host][:port]\fP (New)\r
+If\r
+\fI\&host\fP\r
+is specified,\r
+bind the\r
+\fBjunkbuster\fP\r
+to that\r
+\s-2IP\s0\r
+address.\r
+If a\r
+\fI\&port\fP\r
+is specified, use it.\r
+The default\r
+port\r
+is 8000;\r
+the default host is\r
+\fC\&localhost\fP.\r
+Before Version 2.0.2,\r
+the default was to bind to all \r
+\s-2IP\s0\r
+addresses\r
+(\fB\&INADDR_ANY\fP);\r
+but this has been restricted to\r
+\fB\&localhost\fP\r
+to avoid unintended security breaches.\r
+(To open the proxy to all, use the line\r
+.br\r
+.ti +0.25i\r
+\fB\&listen-address :8000\fP\r
+.br\r
+in the configuration file.)\r
+.TP\r
+.\" anchor: o_f forwardfile\r
+\fI-f forward_host[:port]\fP (Old) forwardfile \fIforwardfile\fP (New)\r
+Version 1.X required all\r
+\s-2HTTP\s0\r
+requests from the client to be forwarded to the same destination.\r
+Version 2.0 takes its routing specification from a\r
+\fI\&forwardfile\fP,\r
+allowing selection of the proxy (a.k.a. forwarding host) and gateway\r
+according to the\r
+\s-2URL\s0.\r
+Here is a typical line.\r
+.br\r
+.ft CW\r
+.S 8\r
+.nf\r
+.sp\r
+* lpwa.com:8000 . .\r
+.S\r
+.ft\r
+.fi\r
+.sp\r
+\r
+.P\r
+Each line contains four fields:\r
+\fB\&target\fP,\r
+\fB\&forward_to\fP,\r
+\fB\&via_gateway_type\fP\r
+and\r
+\fB\&gateway\fP.\r
+As usual, the\r
+last\" ijbman.html#compare\r
+\fB\&target\fP\r
+domain that matches the requested\r
+\s-2URL\s0\r
+wins,\r
+and the\r
+\fC\&*\fP\r
+character alone matches any domain.\r
+The target domain need not be a fully qualified\r
+hostname; it can be a general domain such as\r
+\fC\&com\fP\r
+or\r
+\fC\&co.uk\fP\r
+or even just a port number.\r
+.\" anchor: nose\r
+For example, because\r
+<a href="http://lpwa.com">LPWA</a>\r
+does not handle\r
+SSL,\" ijbfaq.html#encrypt\r
+the line above will typically be followed by a line such as\r
+.br\r
+.ft CW\r
+.S 8\r
+.nf\r
+.sp\r
+:443 . . .\r
+.S\r
+.ft\r
+.fi\r
+.sp\r
+\r
+to allow SSL transactions to proceed directly.\r
+The cautious would also\r
+add an entry in their blockfile to stop transactions\r
+to port 443 for all but specified trusted sites.\r
+.P\r
+If the winning\r
+\fB\&forward_to\fP\r
+field is\r
+\fC\&.\fP\r
+(the dot character) the proxy connects \r
+directly to the server given in the\r
+\s-2URL\s0,\r
+otherwise it forwards to the host and port number specified.\r
+The default port is 8000.\r
+The\r
+\fC\&via_gateway_type\fP\r
+and\r
+\fC\&gateway\fP\r
+fields also use a dot to indicate no gateway protocol.\r
+The gateway protocols are explained\r
+below.\" ijbman.html#o_g\r
+.P\r
+The example line above in a forwardfile alone\r
+would send everything through port 8000 at\r
+\fC\&lpwa.com\fP\r
+with no gateway protocol,\r
+and is equivalent to the old\r
+\fC\&-f lpwa.com:8000\fP\r
+with no\r
+\fC\&-g\fP\r
+option.\r
+For more information see the example file provided with the distribution.\r
+.P\r
+Configure with care: no loop detection is performed.\r
+When setting up chains of proxies that might loop back, try adding\r
+Squid.\" ijbman.html#squid\r
+.TP\r
+.\" anchor: o_g \r
+\fI-g gw_protocol[:[gw_host][:gw_port]]\fP (Old) \r
+Use\r
+\fI\&gw_protocol\fP\r
+as the gateway protocol.\r
+This option was introduced in Version 1.4,\r
+but was folded into the\r
+forwardfile\" ijbman.html#forwardfile\r
+option in Version 2.0.\r
+The default is to use no gateway protocol;\r
+this may be explicitly specified as\r
+\fB\&direct\fP\r
+on the command line\r
+or the dot character in the forwardfile.\r
+The\r
+\fC\&SOCKS4\fP\r
+protocol may be specified as\r
+\fB\&socks\fP\r
+or\r
+\fB\&socks4\fP.\r
+The\r
+\fC\&SOCKS4A\fP\r
+protocol is specified as\r
+\fB\&socks4a\fP.\r
+The\r
+\fC\&SOCKS5\fP\r
+protocol is not currently supported.\r
+The default\r
+\s-2SOCKS\s0\r
+\fI\&gw_port\fP\r
+is 1080.\r
+.P\r
+The user's browser should\r
+\fInot\fP\r
+be\r
+configured\" ijbfaq.html#socks\r
+to use\r
+\fC\&SOCKS\fP;\r
+the proxy conducts the negotiations, not the browser.\r
+.P\r
+The user identification capabilities of\r
+\fC\&SOCKS4\fP\r
+are deliberately not used;\r
+the user is always identified to the\r
+\fC\&SOCKS\fP\r
+server as\r
+\fC\&userid=anonymous\fP.\r
+If the server's policy is to reject requests from\r
+\fC\&anonymous\fP,\r
+the proxy will not work.\r
+Use a\r
+debug\" ijbman.html#o_d\r
+value of 3\r
+to see the status returned by the server.\r
+.TP\r
+.\" anchor: o_d debug\r
+\fI-d N\fP (Old) debug \fIN\fP (New)\r
+Set debug mode.\r
+The most common value is 1,\r
+to\r
+pinpoint\" ijbfaq.html#pinpoint\r
+offensive\r
+\s-2URL\s0s,\r
+so they can be added to the blockfile.\r
+The value of\r
+\fB\&N\fP\r
+is a bitwise\r
+logical-\s-2OR\s0\r
+of the following values:\r
+.br\r
+.br\r
+\h'-\w"1 = "u'1 = URLs (show each URL requested by the browser);\r
+.br\r
+\h'-\w"2 = "u'2 = Connections (show each connection to or from the proxy);\r
+.br\r
+\h'-\w"4 = "u'4 = I/O (log I/O errors);\r
+.br\r
+\h'-\w"8 = "u'8 = Headers (as each header is scanned, show the header and what is done to it);\r
+.br\r
+\h'-\w"16 = "u'16 = Log everything (including debugging traces and the contents of the pages).\r
+.\" anchor: or\r
+Multiple\r
+\fB\&debug\fP\r
+lines are permitted; they are logical OR-ed together.\r
+.P\r
+Because most browsers send several requests in parallel\r
+the debugging output may appear intermingled, so the\r
+single-threaded\" ijbman.html#single-threaded\r
+option is recommended when using\r
+debug\" ijbman.html#debug\r
+with\r
+\fB\&N\fP\r
+greater than 1.\r
+.TP\r
+.\" anchor: o_y add-forwarded-header\r
+\fI-y\fP (Old) add-forwarded-header \fI\fP (New)\r
+Add \r
+\fB\&X-Forwarded-For\fP\r
+headers to the server-bound \r
+\s-2HTTP\s0\r
+stream\r
+indicating the client \r
+\s-2IP\s0\r
+address\r
+to the server,\" ijbfaq.html#detect\r
+in the new style of\r
+Squid 1.1.4.\" ijbman.html#squid\r
+If you want the traditional\r
+\fC\&HTTP_FORWARDED\fP\r
+response header, add it manually with the\r
+-x\" ijbman.html#o_x\r
+option.\r
+.TP\r
+.\" anchor: o_x add-header\r
+\fI-x HeaderText\fP (Old) add-header \fIHeaderText\fP (New)\r
+Add the\r
+\fI\&HeaderText\fP\r
+verbatim to requests to the server.\r
+Typical uses include\r
+adding old-style forwarding notices such as\r
+\fB\&Forwarded: by http://pro-privacy-isp.net\fP\r
+and reinstating the\r
+\fB\&Proxy-Connection: Keep-Alive\fP\r
+header\r
+(which the\r
+\fBjunkbuster\fP\r
+deletes so as\r
+not\" ijbfaq.html#detect\r
+to reveal its existence).\r
+No checking is done for correctness or plausibility,\r
+so it can be used to throw any old trash into the server-bound \r
+\s-2HTTP\s0\r
+stream.\r
+Please don't litter.\r
+.TP\r
+.\" anchor: o_s single-threaded\r
+\fI-s\fP (Old) single-threaded \fI\fP (New)\r
+Doesn't\r
+\fB\&fork()\fP\r
+a separate process\r
+(or create a separate thread)\r
+to handle each connection.\r
+Useful when debugging to keep the process single threaded.\r
+.TP\r
+.\" anchor: o_l logfile\r
+\fI-l logfile\fP (Old) logfile \fIlogfile\fP (New)\r
+Write all debugging data into\r
+\fI\&logfile.\fP\r
+The default\r
+\fI\&logfile\fP\r
+is the standard output.\r
+.TP\r
+.\" anchor: o_acl aclfile\r
+aclfile \fIaclfile\fP (New)\r
+Unless this option is used, the proxy talks to anyone who can connect to it,\r
+and everyone who can has equal permissions on where they can go.\r
+An access file allows restrictions to be placed on these two policies,\r
+by distinguishing some\r
+\fIsource\fP\r
+\s-2IP\s0\r
+addresses and/or\r
+some\r
+\fIdestination\fP\r
+addresses.\r
+(If a\r
+forwarder or a gateway\" ijbman.html#forwardfile\r
+is being used, its address is considered the destination address,\r
+not the ultimate\r
+\s-2IP\s0\r
+address of the\r
+\s-2URL\s0\r
+requested.)\r
+.P\r
+Each line of the access file begins with\r
+either the word\r
+\fB\&permit\fP\r
+or\r
+\fB\&deny\fP\r
+followed by source and (optionally) destination addresses \r
+to be matched against those of the\r
+\s-2HTTP\s0\r
+request.\r
+The last matching line specifies the result: if it was a\r
+\fB\&deny\fP\r
+line or if no line matched,\r
+the request will be refused.\r
+.P\r
+A source or destination\r
+can be specified as a single numeric\r
+\s-2IP\s0\r
+address,\r
+or with a hostname, provided that the host's name\r
+can be resolved to a numeric address: this cannot be used to block all\r
+\fB\&.mil \fP\r
+domains for example,\r
+because there is no single address associated with that domain name.\r
+Either form may be followed by a slash and an integer\r
+\fB\&N\fP,\r
+specifying a subnet mask of\r
+\fB\&N\fP\r
+bits.\r
+For example,\r
+\fB\&permit 207.153.200.72/24\fP\r
+matches the entire Class-C subnet from\r
+207.153.200.0\r
+through 207.153.200.255.\r
+(A netmask of 255.255.255.0 corresponds to 24 bits of\r
+ones in the netmask, as with\r
+\fC\&*_MASKLEN=24\fP.)\r
+A value of 16 would be used for a Class-B subnet.\r
+A value of zero for\r
+\fB\&N\fP\r
+in the subnet mask length will cause any address to match;\r
+this can be used to express a default rule.\r
+For more information see the example file provided with the distribution.\r
+.P\r
+If you like these access controls\r
+you should probably have\r
+firewall;\" ijbfaq.html#firewall\r
+they are not intended to replace one.\r
+.TP\r
+.\" anchor: o_tf trustfile\r
+trustfile \fItrustfile\fP (New)\r
+This feature is experimental, has not been fully documented and is\r
+very subject to change.\r
+The goal is for parents to be able to choose a page or site whose\r
+links they regard suitable for their\r
+young children\" ijbfaq.html#children\r
+and for the proxy to allow access only to sites mentioned there.\r
+To do this the proxy examines the\r
+referer\" ijbman.html#o_r\r
+variable on each page request to check they resulted from\r
+a click on the ``trusted referer'' site: if so the referred site\r
+is added to a list of trusted sites, so that the child can\r
+then move around that site.\r
+There are several uncertainties in this scheme that experience may be\r
+able to iron out; check back in the months ahead.\r
+.TP\r
+.\" anchor: o_ti trust_info_url\r
+trust_info_url \fItrust_info_url\fP (New)\r
+When access is denied due to lack of a trusted referer, this\r
+\s-2URL\s0\r
+is displayed with a message pointing the user to it for further information.\r
+.TP\r
+.\" anchor: o_hc hide-console\r
+hide-console \fI\fP (New)\r
+In the Windows version only, instructs the program\r
+to disconnect from and hide the command console after starting.\r
+.TP\r
+.\" anchor: o_a \r
+\fI-a\fP (Old) \r
+(Obsolete) Accept the server's\r
+\fB\&Set-cookie\fP\r
+headers, passing them through to the browser.\r
+.\" anchor: obsolete\r
+This option was removed in Version 1.2\r
+and replaced by an improvement to the\r
+-c\" ijbman.html#o_c\r
+option.\r
+.LE\r
+.SH INSTALLATION AND USE\r
+Browsers must be told where to find the\r
+\fBjunkbuster\fP\r
+(e.g.\r
+\fB\&localhost\fP\r
+port 8000).\r
+To set the \r
+\s-2HTTP\s0\r
+proxy in Netscape 3.0,\r
+go through:\r
+\fB\&Options\fP;\r
+\fB\&Network Preferences\fP;\r
+\fB\&Proxies\fP;\r
+\fB\&Manual Proxy Configuration\fP;\r
+\fB\&View\fP.\r
+See the\r
+\s-2FAQ\s0\r
+for other browsers.\r
+The\r
+Security Proxy\" ijbfaq.html#security\r
+should also be set to the same values,\r
+otherwise\r
+\fB\&shttp:\fP\r
+\s-2URL\s0s\r
+won't work.\r
+.P\r
+Note the limitations\r
+explained in the\r
+\s-2FAQ\s0.\r
+.SH CHECKING OPTIONS\r
+To allow users to\r
+check\" ijbfaq.html#show\r
+that a\r
+\fBjunkbuster\fP\r
+is running and how it is configured,\r
+it intercepts requests for any\r
+\s-2URL\s0\r
+ending in\r
+\fB\&/show-proxy-args\fP\r
+and blocks it,\r
+returning instead returns information on its\r
+version number and\r
+current configuration\r
+including the contents of its blockfile.\r
+To get an explicit warning that no\r
+\fBjunkbuster\fP\r
+intervened if the proxy was not configured,\r
+it's best to point it to a\r
+\s-2URL\s0\r
+that does this, such as\r
+http://internet.junkbuster.com/cgi-bin/show-proxy-args\r
+on Junkbusters's website.\r
+.SH SEE ALSO\r
+http://www.waldherr.org/junkbuster/\" waldherr.org#\r
+.br\r
+http://www.junkbusters.com/ht/en/ijbfaq.html\" ijbfaq.html#\r
+.br\r
+http://www.junkbusters.com/ht/en/cookies.html\" cookies.html#\r
+.br\r
+http://internet.junkbuster.com/cgi-bin/show-proxy-args\r
+.br\r
+http://www.cis.ohio-state.edu/htbin/rfc/rfc2109.html\r
+.br\r
+http://squid.nlanr.net/Squid/\r
+.br\r
+http://www-math.uni-paderborn.de/~axel/\r
+.SH COPYRIGHT AND GPL\r
+Written and copyright by the Anonymous Coders and Junkbusters Corporation\r
+and made available under the\r
+GNU General Public License (GPL).\" gpl.html#\r
+This software comes with\r
+NO WARRANTY.\" gpl.html#nowarr\r
+Internet Junkbuster\r
+Proxy\r
+is a\r
+trademark\" legal.html#marks\r
+of Junkbusters Corporation.\r
--- /dev/null
+#!/bin/sh\r
+#\r
+# $Id: junkbuster.init,v 1.2 2001/04/30 02:36:54 rodney Exp $\r
+#\r
+# This is file is either \r
+#\r
+# /etc/rc.d/init.d/junkbuster \r
+#\r
+# or\r
+#\r
+# /sbin/init.d/junkbuster\r
+#\r
+# and was put here by the junkbuster rpm\r
+#\r
+# junkbuster This shell script takes care of starting and stopping\r
+# junkbuster.\r
+#\r
+# This works only correctly if the user `nobody' is allowed\r
+# to be in the directory where this file is called \r
+# (for example: /root is NOT ok)\r
+# ---------------------------------------------------------------------------\r
+# Force /bin/sh as shell (padraic@renaghan.com).\r
+# Augmented with help by Sterling <wolffe@sempai.org>\r
+# Hints from mjohnson11@uswest.net\r
+# Hints from rochedav@primenet.com\r
+# ---------------------------------------------------------------------------\r
+# These lines are needed so Redhat's config tools will "see" this script:\r
+# chkconfig: 35 84 09\r
+# description: Blocks annoying ads from the internet, along with cookies \\r
+# and a few other privacy features. \r
+# processname: junkbuster\r
+# config: /etc/junkbuster/config\r
+\r
+\r
+# ---------------------------------------------------------------------------\r
+#\r
+# SuSE only\r
+#\r
+# ---------------------------------------------------------------------------\r
+if [ -f /etc/rc.config ]; then\r
+\r
+# Author: Daniel Bischof <daniel@suse.de>, 1999\r
+# Adjustment: Axel Braun <doc.b@gmx.de>, 17.08.2000 \r
+. /etc/rc.config\r
+#base=${0##*/}\r
+#link=${base#*[SK][0-9][0-9]}\r
+#test $link = $base && START_IJB=yes\r
+#test "$START_IJB" = "yes" || exit 0\r
+return=$rc_done\r
+case "$1" in\r
+ start)\r
+ echo -n "Starting The Internet Junkbuster"\r
+ su - nobody -c 'nohup /usr/sbin/junkbuster /etc/junkbuster/config < /dev/null > /dev/null &' \r
+ sleep 1\r
+ echo -e "$return"\r
+ ;;\r
+ stop)\r
+ echo -n "Shutting down The Internet Junkbuster"\r
+ killproc -TERM /usr/sbin/junkbuster || return=$rc_failed\r
+ echo -e "$return"\r
+ ;;\r
+ restart|reload)\r
+ echo -n "Reload The Internet Junkbuster"\r
+ killproc -HUP /usr/sbin/junkbuster || return=$rc_failed\r
+ echo -e "$return"\r
+ ;;\r
+ status)\r
+ checkproc /usr/sbin/junkbuster && echo OK || echo No process\r
+ ;;\r
+ *)\r
+ echo "Usage: $0 {start|restart|status|stop}"\r
+ exit 1\r
+esac\r
+test "$return" = "$rc_done" || exit 1\r
+exit 0\r
+\r
+else\r
+# ---------------------------------------------------------------------------\r
+#\r
+# RedHat only\r
+#\r
+# ---------------------------------------------------------------------------\r
+\r
+# Source function library.\r
+if [ -f /etc/rc.d/init.d/functions ]; then\r
+. /etc/rc.d/init.d/functions\r
+fi\r
+\r
+if [ -f /etc/sysconfig/network ]; then\r
+. /etc/sysconfig/network\r
+fi\r
+\r
+# Check that networking is up.\r
+[ ${NETWORKING} = "no" ] && exit 0\r
+\r
+[ -f /etc/junkbuster/config ] || exit 0\r
+\r
+[ -f /usr/sbin/junkbuster ] || exit 0\r
+\r
+RETVAL=0\r
+\r
+# See how we were called.\r
+case "$1" in\r
+\r
+ start)\r
+ # abort if already started\r
+ pid=`pidofproc junkbuster`\r
+ [ -n "$pid" ] && ps h $pid >/dev/null 2>&1 && \\r
+ echo -n "Already started: " && status junkbuster && \\r
+ exit 0\r
+\r
+ # Start daemon.\r
+ echo -n "Starting junkbuster:" && RETVAL=1\r
+ ulimit -c 0\r
+ su - nobody -s /bin/sh -c '/usr/sbin/junkbuster /etc/junkbuster/config' &\r
+ sleep 1\r
+ pid=`pidofproc junkbuster`\r
+ [ -n "$pid" ] && ps h $pid >/dev/null 2>&1 && RETVAL=0 && echo_success && touch /var/lock/subsys/junkbuster\r
+ [ $RETVAL -eq 1 ] && echo_failure\r
+ echo\r
+ ;;\r
+\r
+ stop)\r
+ # Stop daemon.\r
+ echo -n "Shutting down junkbuster:"\r
+ killproc junkbuster\r
+ RETVAL=$?\r
+ [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/junkbuster\r
+ echo\r
+ ;;\r
+\r
+ status)\r
+ status junkbuster\r
+ RETVAL=$?\r
+ ;;\r
+\r
+ restart|reload)\r
+ $0 stop && $0 start\r
+ ;;\r
+\r
+ *)\r
+ echo "Usage: junkbuster {start|stop|status|restart|reload}"\r
+ exit 1\r
+esac\r
+\r
+exit $RETVAL\r
+\r
+fi\r
+\r
--- /dev/null
+#
+# Logrotate file for Junkbuster RPM
+#
+# $Id: junkbuster.logrotate,v 1.1 2001/04/30 03:17:00 rodney Exp $
+
+# Fixed problems of
+# filename.1 -> filename.1.2 -> filename.1.3
+# filename.1.2.2, filename.1.2.3, filename.1.3.2, filename.1.3.3
+# filename.1.2.2.2, filename.1.2.2.3 ...
+# by explicitly listing each logfile in the directory instead of `*'.
+#
+
+/var/log/junkbuster/junkbuster {
+ compress
+ weekly
+}
+
+
+#/var/log/junkbuster/jarfile {
+# compress
+# weekly
+#}
--- /dev/null
+#!/bin/sh\r
+\r
+# $Id: junkbuster.monthly,v 1.1 2001/04/16 21:10:38 rodney Exp $\r
+#\r
+# bug fixed, which downloaded all three files to the file blocklist\r
+#\r
+# Revised: Mon Dec 06 10:46:08 PST 1999 by Jon Hamkins\r
+# Hints by Ulrik Haugen <qha@lysator.liu.se>\r
+# Hints by mirjamv@theochem.kun.nl\r
+#\r
+set -e\r
+\r
+# blocklist\r
+wget -q --output-document=/etc/junkbuster/blocklist.new \\r
+ http://www.waldherr.org/blocklist\r
+\r
+mv -f /etc/junkbuster/blocklist.new /etc/junkbuster/blocklist\r
+\r
+if [ -f /etc/junkbuster/blocklist.local ] ; then\r
+ cat /etc/junkbuster/blocklist.local >> /etc/junkbuster/blocklist\r
+fi\r
+chmod 644 /etc/junkbuster/blocklist\r
+\r
+# cookiefile\r
+wget -q --output-document=/etc/junkbuster/cookiefile.new \\r
+ http://www.waldherr.org/cookiefile\r
+\r
+mv -f /etc/junkbuster/cookiefile.new /etc/junkbuster/cookiefile\r
+\r
+if [ -f /etc/junkbuster/cookiefile.local ] ; then\r
+ cat /etc/junkbuster/cookiefile.local >> /etc/junkbuster/cookiefile\r
+fi\r
+chmod 644 /etc/junkbuster/cookiefile\r
+\r
+# imagelist\r
+wget -q --output-document=/etc/junkbuster/imagelist.new \\r
+ http://www.waldherr.org/imagelist\r
+\r
+mv -f /etc/junkbuster/imagelist.new /etc/junkbuster/imagelist\r
+\r
+if [ -f /etc/junkbuster/imagelist.local ] ; then\r
+ cat /etc/junkbuster/imagelist.local >> /etc/junkbuster/imagelist\r
+fi\r
+chmod 644 /etc/junkbuster/imagelist\r
--- /dev/null
+#!/bin/sh\r
+\r
+# $Id: junkbuster.weekly,v 1.1 2001/04/16 21:10:38 rodney Exp $\r
+\r
+# Revised: Mon Dec 06 10:46:08 PST 1999 by Jon Hamkins\r
+# Hints by Ulrik Haugen <qha@lysator.liu.se>\r
+# Hints by mirjamv@theochem.kun.nl\r
+\r
+set -e\r
+\r
+# blocklist\r
+wget -q --output-document=/etc/junkbuster/blocklist.new \\r
+ http://www.waldherr.org/blocklist\r
+\r
+mv -f /etc/junkbuster/blocklist.new /etc/junkbuster/blocklist\r
+\r
+if [ -f /etc/junkbuster/blocklist.local ] ; then\r
+ cat /etc/junkbuster/blocklist.local >> /etc/junkbuster/blocklist\r
+fi\r
+\r
+chmod 644 /etc/junkbuster/blocklist\r
--- /dev/null
+const char killpopup_rcs[] = "$Id: killpopup.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/killpopup.c,v $
+ *
+ * Purpose : Handles the filtering of popups.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: killpopup.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <malloc.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include "project.h"
+#include "killpopup.h"
+#include "jcc.h"
+
+const char killpopup_h_rcs[] = KILLPOPUP_H_VERSION;
+
+#ifdef KILLPOPUPS
+
+/* Change these for debug output. *lots*. */
+/*#define POPUP_VERBOSE 1*/
+/* CHANGED - added the below and shifted the more spammy stuff into it ;-) */
+#undef POPUP_VERY_VERBOSE
+#undef POPUP_VERBOSE
+
+
+/*********************************************************************
+ *
+ * Function : filter_popups
+ *
+ * Description : Filter the block of data that's been read from the server.
+ * IF NECESSARY.
+ *
+ * Parameters :
+ * 1 : csp = Client state
+ * 2 : host_name = hostname of originating web page to
+ * look up on blocklist
+ * 3 : buff = Buffer to scan and modify. Null terminated.
+ * 4 : size = Buffer size, excluding null terminator.
+ *
+ * Returns : void
+ *
+ *********************************************************************/
+void filter_popups(struct client_state *csp, char *host_name, char *buff, int size)
+{
+ struct popup_settings * data;
+ struct popup_blocklist * cur;
+ int i;
+ int found = 0;
+ char *popup = NULL;
+ char *close = NULL;
+ char *p = NULL;
+ char *q = NULL; /* by BREITENB NEW! */
+
+ if ( (!csp->plist) || ((data = csp->plist->f) == NULL) )
+ {
+ /* Disabled. */
+ return;
+ }
+
+ /* If the hostname is on our list for blocking then mark it
+ * as a host to block from. (This may be later changed if the
+ * host is also on the list-to-allow list).
+ */
+
+ for (i=0; (i < 50) && (i < size); i++) /* avoid scanning binary data! */
+ {
+ if ((unsigned int)(buff[i])>127)
+ {
+#ifdef POPUP_VERBOSE
+ fprintf(logfp, "I'm not scanning binary stuff! (%i)\n",buff[i]);
+#endif
+ return;
+ }
+ }
+
+
+ for (cur = data->blocked ; cur ; cur = cur->next)
+ {
+ if ( host_name != 0 )
+ {
+ if ( strcmp( cur->host_name, host_name ) == 0 )
+ {
+#ifdef POPUP_VERBOSE
+ fprintf(logfp, "Blocking %s\n", host_name );
+#endif
+ found = 1;
+ }
+ }
+ }
+
+ /* Force match if we're supposed to nuke _all_ popups, globally. */
+ if ( kill_all_popups != 0 )
+ {
+#ifdef POPUP_VERBOSE
+ fprintf(logfp, "Indescriminatly nuking popups..\n" );
+#endif
+ found = 1;
+ }
+ /* an exception-from blocking should still be an exception! by BREITENB NEW! */
+
+
+ /* Now, if its allowed adjust the filtering, so it _doesn't_ happen. */
+ for (cur = data->allowed ; cur ; cur = cur->next)
+ {
+ if ( host_name != 0 )
+ {
+ if ( strcmp( cur->host_name, host_name ) == 0 )
+ {
+#ifdef POPUP_VERBOSE
+ fprintf(logfp, "Reversing block decision for %s\n", host_name );
+#endif
+ found = 0;
+ }
+ }
+ }
+
+ if ( found == 0)
+ {
+#ifdef POPUP_VERBOSE
+ fprintf(logfp, "Allowing %s\n", host_name );
+#endif
+ return;
+ }
+
+ while ((popup = strstr( buff, "window.open(" )) != NULL)
+ /* if ( popup ) by BREITENB filter ALL popups! NEW! */
+ {
+#ifdef POPUP_VERBOSE
+ fprintf(logfp, "Found start of window open" );
+#endif
+ close = strstr( popup+1, ");" );
+ if ( close )
+ {
+#ifdef POPUP_VERBOSE
+ fprintf(logfp, "Found end of window open" );
+#endif
+ for ( p = popup; p != (close+1); p++ )
+ {
+ *p = ' ';
+ }
+#ifdef POPUP_VERBOSE
+ fprintf(logfp, "Blocked %s\n", host_name );
+#endif
+ }
+ else
+ {
+#ifdef POPUP_VERBOSE
+ fprintf(logfp, "Couldn't find end, turned into comment. Read boundary?\n" );
+#endif
+ *popup = '/';
+ popup++;
+ *popup = '/';
+ }
+
+
+ q=popup; /* by BREITENB NEW! */
+ while (q>=buff)
+ {
+ if (*q==' ' || *q=='\t')
+ q--;
+ else break;
+ }
+ if (q>=buff)
+ {
+ if (*q=='=') *++q='1';
+ /* result of popup is assigned to a variable! ensure success. hehehe. */
+ }
+ }
+
+ /* Filter all other crap like onUnload onExit etc. (by BREITENB) NEW!*/
+ popup=strstr( buff, "<body");
+ if (!popup) popup=strstr( buff, "<BODY");
+ if (!popup) popup=strstr( buff, "<Body");
+ if (!popup) popup=strstr( buff, "<BOdy");
+ if (popup)
+ {
+ q=strchr(popup,'>');
+ if (q)
+ {
+ /* we are now between <body and the ending > */
+ p=strstr(popup, "onUnload");
+ if (p)
+ {
+ strncpy(p,"_nU_",4);
+ }
+ p=strstr(popup, "onExit");
+ if (p)
+ {
+ strncpy(p,"_nE_",4);
+ }
+ }
+ }
+
+}
+
+#endif /* def KILLPOPUPS */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _KILLPOPUP_H
+#define _KILLPOPUP_H
+#define KILLPOPUP_H_VERSION "$Id: killpopup.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/killpopup.h,v $
+ *
+ * Purpose : Handles the filtering of popups.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: killpopup.h,v $
+ *
+ *********************************************************************/
+\f
+
+#include "project.h"
+
+#ifdef KILLPOPUPS
+
+extern void filter_popups(struct client_state *csp, char *host_name, char *buff, int size);
+
+#endif /* def KILLPOPUPS */
+
+/* Revision control strings from this header and associated .c file */
+extern const char killpopup_rcs[];
+extern const char killpopup_h_rcs[];
+
+#endif /* ndef _KILLPOPUP_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/loadcfg.c,v $
+ *
+ * Purpose : Loads settings from the configuration file into
+ * global variables. This file contains both the
+ * routine to load the configuration and the global
+ * variables it writes to.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: loadcfg.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+
+#ifdef _WIN32
+
+# include <sys/timeb.h>
+# include <windows.h>
+# include <io.h>
+# include <process.h>
+# ifdef TOGGLE
+# include <time.h>
+# endif /* def TOGGLE */
+
+# include "win32.h"
+# ifndef _WIN_CONSOLE
+# include "w32log.h"
+# endif /* ndef _WIN_CONSOLE */
+
+#else /* ifndef _WIN32 */
+
+# include <unistd.h>
+# include <sys/time.h>
+# include <sys/wait.h>
+# include <sys/stat.h>
+# include <signal.h>
+
+#endif
+
+#include "loadcfg.h"
+#include "jcc.h"
+#include "filters.h"
+#include "loaders.h"
+#include "showargs.h"
+#include "parsers.h"
+#include "killpopup.h"
+#include "miscutil.h"
+#include "errlog.h"
+#include "jbsockets.h"
+#include "gateway.h"
+
+const char loadcfg_h_rcs[] = LOADCFG_H_VERSION;
+
+/*
+ * Fix a problem with Solaris. There should be no effect on other
+ * platforms.
+ * Solaris's isspace() is a macro which uses it's argument directly
+ * as an array index. Therefore we need to make sure that high-bit
+ * characters generate +ve values, and ideally we also want to make
+ * the argument match the declared parameter type of "int".
+ */
+#define ijb_isupper(__X) isupper((int)(unsigned char)(__X))
+#define ijb_tolower(__X) tolower((int)(unsigned char)(__X))
+
+static const char VANILLA_WAFER[] =
+ "NOTICE=TO_WHOM_IT_MAY_CONCERN_"
+ "Do_not_send_me_any_copyrighted_information_other_than_the_"
+ "document_that_I_am_requesting_or_any_of_its_necessary_components._"
+ "In_particular_do_not_send_me_any_cookies_that_"
+ "are_subject_to_a_claim_of_copyright_by_anybody._"
+ "Take_notice_that_I_refuse_to_be_bound_by_any_license_condition_"
+ "(copyright_or_otherwise)_applying_to_any_cookie._";
+
+#ifdef TOGGLE
+/* by haroon - indicates if ijb is enabled */
+int g_bToggleIJB = 1; /* JunkBusters is enabled by default. */
+#endif
+
+int debug = 0;
+int multi_threaded = 1;
+
+#if defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST)
+int tinygif = 0;
+const char *tinygifurl = NULL;\r
+#endif /* defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST) */
+
+const char *logfile = NULL;
+
+const char *configfile = NULL;
+
+const char *blockfile = NULL;
+const char *cookiefile = NULL;
+const char *forwardfile = NULL;
+
+#ifdef ACL_FILES
+const char *aclfile = NULL;
+#endif /* def ACL_FILES */
+
+#ifdef USE_IMAGE_LIST
+const char *imagefile = NULL;
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef KILLPOPUPS
+const char *popupfile = NULL;
+int kill_all_popups = 0; /* Not recommended really ... */
+#endif /* def KILLPOPUPS */
+
+#ifdef PCRS
+const char *re_filterfile = NULL;
+int re_filter_all = 0;
+#endif /* def PCRS */
+
+#ifdef TRUST_FILES
+const char *trustfile = NULL;
+#endif /* def TRUST_FILES */
+
+#ifdef JAR_FILES
+const char *jarfile = NULL;
+FILE *jar = NULL;
+#endif /* def JAR_FILES */
+
+const char *referrer = NULL;
+const char *uagent = NULL;
+const char *from = NULL;
+
+#ifndef SPLIT_PROXY_ARGS
+const char *suppress_message = NULL;
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+int suppress_vanilla_wafer = 0;
+int add_forwarded = 0;
+
+struct list wafer_list[1];
+struct list xtra_list[1];
+
+#ifdef TRUST_FILES
+struct list trust_info[1];
+struct url_spec *trust_list[64];
+#endif /* def TRUST_FILES */
+
+/*
+ * Port and IP to bind to.
+ * Defaults to HADDR_DEFAULT:HADDR_PORT == 127.0.0.1:8000
+ */
+const char *haddr = NULL;
+int hport = 0;
+
+#ifndef SPLIT_PROXY_ARGS
+int suppress_blocklists = 0; /* suppress listing sblock and simage */
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+struct proxy_args proxy_args[1];
+
+int configret = 0;
+int config_changed = 0;
+
+
+/*
+ * The load_config function is now going to call `init_proxy_args',
+ * so it will need argc and argv. Since load_config will also be
+ * a signal handler, we need to have these globally available.
+ */
+int Argc = 0;
+const char **Argv = NULL;
+
+
+/*
+ * This takes the "cryptic" hash of each keyword and aliases them to
+ * something a little more readable. This also makes changing the
+ * hash values easier if they should change or the hash algorthm changes.
+ * Use the included "hash" program to find out what the hash will be
+ * for any string supplied on the command line.
+ */
+
+#define hash_trustfile 56494766ul
+#define hash_trust_info_url 449869467ul
+#define hash_debug 78263ul
+#define hash_tinygif 2227702ul
+#define hash_add_forwarded_header 3191044770ul
+#define hash_single_threaded 4250084780ul
+#define hash_suppress_vanilla_wafer 3121233547ul
+#define hash_wafer 89669ul
+#define hash_add_header 237434619ul
+#define hash_cookiefile 247469766ul
+#define hash_logfile 2114766ul
+#define hash_blockfile 48845391ul
+#define hash_imagefile 51447891ul
+#define hash_jarfile 2046641ul
+#define hash_listen_address 1255650842ul
+#define hash_forwardfile 1268669141ul
+#define hash_aclfile 1908516ul
+#define hash_popupfile 54623516ul
+#define hash_kill_all_popups 2311539906ul
+#define hash_re_filterfile 3877522444ul
+#define hash_re_filter_all 3877521376ul
+#define hash_user_agent 283326691ul
+#define hash_referrer 10883969ul
+#define hash_referer 2176719ul
+#define hash_from 16264ul
+#define hash_hide_console 2048809870ul
+#define hash_include_stats 2174146548ul
+#define hash_suppress_blocklists 1948693308ul
+#define hash_toggle 447966ul
+
+#define hash_activity_animation 1817904738ul
+#define hash_log_messages 2291744899ul
+#define hash_log_highlight_messages 4032101240ul
+#define hash_log_buffer_size 2918070425ul
+#define hash_log_max_lines 2868344173ul
+#define hash_log_font_name 2866730124ul
+#define hash_log_font_size 2866731014ul
+#define hash_show_on_task_bar 215410365ul
+#define hash_close_button_minimizes 3651284693ul
+
+
+/*********************************************************************
+ *
+ * Function : load_config
+ *
+ * Description : Load the config file and all parameters.
+ *
+ * Parameters :
+ * 1 : signum : this can be the signal SIGHUP or 0 (if from main).
+ * In any case, we just ignore this and reload the config file.
+ *
+ * Returns : configret : 0 => Ok, everything else is an error.
+ * Note: we use configret since a signal handler cannot
+ * return a value, and this function does double duty.
+ * Ie. Is is called from main and from signal( SIGHUP );
+ *
+ *********************************************************************/
+void load_config( int signum )
+{
+ char buf[BUFSIZ];
+ char *p, *q;
+ FILE *configfp = NULL;
+
+ configret = 0;
+ config_changed = 1;
+
+ log_error(LOG_LEVEL_INFO, "loading configuration file '%s':", configfile);
+
+ init_proxy_args(Argc, Argv);
+
+
+ /* (Waste of memory [not quite a "leak"] here. The
+ * last blockfile/popupfile/... etc will not be
+ * unloaded until we load a new one. If the
+ * block/popup/... feature has been disabled in
+ * the new config file, then we're wasting some
+ * memory we could otherwise reclaim.
+ */
+
+ /* Disable all loaders. */
+ remove_all_loaders();
+
+ /*
+ * Reset to as close to startup state as we can.
+ * But leave changing the logfile until after we're done loading.
+ */
+
+ #ifdef JAR_FILES
+ if ( NULL != jar )
+ {
+ fclose( jar );
+ jar = NULL;
+ }
+ #endif /* def JAR_FILES */
+
+ debug = 0;
+ multi_threaded = 1;
+
+#if defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST)
+ tinygif = 0;\r
+ freez((char *)tinygifurl);
+#endif /* defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST) */
+
+ suppress_vanilla_wafer = 0;
+ add_forwarded = 0;
+ hport = HADDR_PORT;
+
+#ifdef _WIN_CONSOLE
+ hideConsole = 0;
+#endif /*def _WIN_CONSOLE*/
+
+#ifdef PCRS
+ re_filter_all = 0;
+#endif /* def PCRS */
+
+#ifdef KILLPOPUPS
+ kill_all_popups = 0;
+#endif /* def KILLPOPUPS */
+
+#ifdef TOGGLE
+ g_bToggleIJB = 1;
+#endif
+
+#ifdef STATISTICS
+ urls_read = 0;
+ urls_rejected = 0;
+#endif /* def STATISTICS */
+
+#ifndef SPLIT_PROXY_ARGS
+ suppress_blocklists = 0;
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ freez((char *)from);
+ freez((char *)haddr);
+ freez((char *)uagent);
+ freez((char *)referrer);
+ freez((char *)logfile);
+
+
+ freez((char *)blockfile);
+ freez((char *)cookiefile);
+ freez((char *)forwardfile);
+
+#ifdef ACL_FILES
+ freez((char *)aclfile);
+#endif /* def ACL_FILES */
+
+#ifdef USE_IMAGE_LIST
+ freez((char *)imagefile);
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef JAR_FILES
+ freez((char *)jarfile);
+#endif /* def JAR_FILES */
+
+#ifdef KILLPOPUPS
+ freez((char *)popupfile);
+#endif /* def KILLPOPUPS */
+
+#ifndef SPLIT_PROXY_ARGS
+ freez((char *)suppress_message);
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+#ifdef TRUST_FILES
+ freez((char *)trustfile);
+#endif /* def TRUST_FILES */
+
+#ifdef PCRS
+ freez((char *)re_filterfile);
+#endif /* def PCRS */
+
+ if (NULL != configfile)
+ {
+ if ((configfp = fopen(configfile, "r")) == NULL)
+ {
+ log_error(LOG_LEVEL_ERROR, "can't open configuration file '%s': %E",
+ configfile);
+ configret = 1;
+ return;
+ }
+ }
+
+ if (NULL != configfp)
+ {
+ memset (buf, 'j', sizeof(buf));
+ while (read_config_line(buf, sizeof(buf), configfp, NULL) != NULL)
+ {
+ char cmd[BUFSIZ];
+ char arg[BUFSIZ];
+ char tmp[BUFSIZ];
+
+ strcpy(tmp, buf);
+
+ /* Copy command (i.e. up to space or tab) into cmd */
+ p = buf;
+ q = cmd;
+ while (*p && (*p != ' ') && (*p != '\t'))
+ {
+ *q++ = *p++;
+ }
+ *q = '\0';
+
+ /* Skip over the whitespace in buf */
+ while (*p && ((*p == ' ') || (*p == '\t')))
+ {
+ p++;
+ }
+
+ /* Copy the argument into arg */
+ strcpy(arg, p);
+
+ /* Should never happen, but check this anyway */
+ if (*cmd == '\0')
+ {
+ continue;
+ }
+
+ /* Make sure the command field is lower case */
+ for (p=cmd; *p; p++)
+ {
+ if (ijb_isupper(*p))
+ {
+ *p = ijb_tolower(*p);
+ }
+ }
+
+ /* Save the argument for show-proxy-args */
+ savearg(cmd, arg);
+
+
+ switch( hash_string( cmd ) )
+ {
+#ifdef TRUST_FILES
+ case hash_trustfile :\r
+ freez((char *)trustfile);
+ trustfile = strdup(arg);
+ continue;
+
+ case hash_trust_info_url :
+ enlist(trust_info, arg);
+ continue;
+#endif /* def TRUST_FILES */
+
+ case hash_debug :
+ debug |= atoi(arg);
+ continue;
+
+#if defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST)
+ case hash_tinygif :\r
+ freez((char *)tinygifurl);
+ tinygif = atoi(arg);
+ if(3 == tinygif)\r
+ {\r
+ p = arg;\r
+ while((*p >= '0') && (*p <= '9'))\r
+ {\r
+ p++;\r
+ }\r
+ while((*p == ' ') || (*p == '\t'))\r
+ {\r
+ p++;\r
+ }\r
+ if (*p)\r
+ {\r
+ q = malloc(strlen(p) + 5);\r
+ if (q)\r
+ {\r
+ strcpy(q, p);\r
+ strcat(q, "\r\n\r\n");\r
+ tinygifurl = q;\r
+ }\r
+ }\r
+ }\r
+ if ((tinygif != 1) && \r
+ (tinygif != 2) && \r
+ ((tinygif != 3) || (tinygifurl==NULL)) )\r
+ {\r
+ log_error(LOG_LEVEL_ERROR, "tinygif setting invalid.");\r
+ }\r
+ continue;
+#endif /* defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST) */
+
+ case hash_add_forwarded_header :
+ add_forwarded = 1;
+ continue;
+
+ case hash_single_threaded :
+ multi_threaded = 0;
+ continue;
+
+ case hash_suppress_vanilla_wafer :
+ suppress_vanilla_wafer = 1;
+ continue;
+
+ case hash_wafer :
+ enlist(wafer_list, arg);
+ continue;
+
+ case hash_add_header :
+ enlist(xtra_list, arg);
+ continue;
+
+ case hash_cookiefile :\r
+ freez((char *)cookiefile);
+ cookiefile = strdup(arg);
+ continue;
+
+ case hash_logfile :\r
+ freez((char *)logfile);
+ logfile = strdup(arg);
+ continue;
+
+ case hash_blockfile :\r
+ freez((char *)blockfile);
+ blockfile = strdup(arg);
+ continue;
+
+#ifdef USE_IMAGE_LIST
+ case hash_imagefile :\r
+ freez((char *)imagefile);
+ imagefile = strdup(arg);
+ continue;
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef JAR_FILES
+ case hash_jarfile :\r
+ freez((char *)jarfile);
+ jarfile = strdup(arg);
+ continue;
+#endif /* def JAR_FILES */
+
+ case hash_listen_address :\r
+ freez((char *)haddr);
+ haddr = strdup(arg);
+ continue;
+
+ case hash_forwardfile :\r
+ freez((char *)forwardfile);
+ forwardfile = strdup(arg);
+ continue;
+
+#ifdef ACL_FILES
+ case hash_aclfile :\r
+ freez((char *)aclfile);
+ aclfile = strdup(arg);
+ continue;
+#endif /* def ACL_FILES */
+
+#ifdef KILLPOPUPS
+ case hash_popupfile :\r
+ freez((char *)popupfile);
+ popupfile = strdup(arg);
+ continue;
+
+ case hash_kill_all_popups :
+ kill_all_popups = 1;
+ continue;
+#endif /* def KILLPOPUPS */
+
+#ifdef PCRS
+ case hash_re_filterfile :\r
+ freez((char *)re_filterfile);
+ re_filterfile = strdup(arg);
+ continue;
+
+ case hash_re_filter_all :
+ re_filter_all = 1;
+ log_error(LOG_LEVEL_REF, "re_filter policy is %s.",
+ re_filter_all ? "RADICAL" : "SEMI-SMART");
+ continue;
+#endif /* def PCRS */
+
+ case hash_user_agent :\r
+ freez((char *)uagent);
+ uagent = strdup(arg);
+ continue;
+
+ /*
+ * Offer choice of correct spelling according to dictionary,
+ * or the misspelling used in the HTTP spec.
+ */
+ case hash_referrer :
+ case hash_referer :\r
+ freez((char *)referrer);
+ referrer = strdup(arg);
+ continue;
+
+ case hash_from :\r
+ freez((char *)from);
+ from = strdup(arg);
+ continue;
+
+#ifdef _WIN_CONSOLE
+ case hash_hide_console :
+ hideConsole = 1;
+ continue;
+#endif /*def _WIN_CONSOLE*/
+
+#ifndef SPLIT_PROXY_ARGS
+ case hash_suppress_blocklists :
+ if (arg[0] != '\0')
+ {
+ suppress_message = strdup(arg);
+ }
+ else
+ {
+ /* There will be NO reference in proxy-args. */
+ suppress_message = NULL;
+ }
+
+ suppress_blocklists = 1;
+ continue;
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+#ifdef TOGGLE
+ case hash_toggle :
+ g_bToggleIJB = atoi(arg);
+ continue;
+#endif /* def TOGGLE */
+
+#if defined(_WIN32) && ! defined(_WIN_CONSOLE)
+ case hash_activity_animation :
+ g_bShowActivityAnimation = atoi(arg);
+ continue;
+
+ case hash_log_messages :
+ g_bLogMessages = atoi(arg);
+ continue;
+
+ case hash_log_highlight_messages :
+ g_bHighlightMessages = atoi(arg);
+ continue;
+
+ case hash_log_buffer_size :
+ g_bLimitBufferSize = atoi(arg);
+ continue;
+
+ case hash_log_max_lines :
+ g_nMaxBufferLines = atoi(arg);
+ continue;
+
+ case hash_log_font_name :
+ strcpy( g_szFontFaceName, arg );
+ continue;
+
+ case hash_log_font_size :
+ g_nFontSize = atoi(arg);
+ continue;
+
+ case hash_show_on_task_bar :
+ g_bShowOnTaskBar = atoi(arg);
+ continue;
+
+ case hash_close_button_minimizes :
+ g_bCloseHidesWindow = atoi(arg);
+ continue;
+#endif /* defined(_WIN32) && ! defined(_WIN_CONSOLE) */
+
+ /* Warnings about unsupported features */
+
+#ifndef TRUST_FILES
+ case hash_trustfile :
+ case hash_trust_info_url :
+#endif /* ndef TRUST_FILES */
+#ifndef USE_IMAGE_LIST
+ case hash_imagefile :
+#endif /* ndef USE_IMAGE_LIST */
+#ifndef PCRS
+ case hash_re_filterfile :
+ case hash_re_filter_all :
+#endif /* ndef PCRS */
+#ifndef TOGGLE
+ case hash_toggle :
+#endif /* ndef TOGGLE */
+#if defined(_WIN_CONSOLE) || ! defined(_WIN32)
+ case hash_activity_animation :
+ case hash_log_messages :
+ case hash_log_highlight_messages :
+ case hash_log_buffer_size :
+ case hash_log_max_lines :
+ case hash_log_font_name :
+ case hash_log_font_size :
+ case hash_show_on_task_bar :
+ case hash_close_button_minimizes :
+#endif /* defined(_WIN_CONSOLE) || ! defined(_WIN32) */
+#ifndef _WIN_CONSOLE
+ case hash_hide_console :
+#endif /* ndef _WIN_CONSOLE */
+#if !defined(DETECT_MSIE_IMAGES) && !defined(USE_IMAGE_LIST)
+ case hash_tinygif :
+#endif /* !defined(DETECT_MSIE_IMAGES) && !defined(USE_IMAGE_LIST) */
+#ifndef KILLPOPUPS
+ case hash_popupfile :
+ case hash_kill_all_popups :
+#endif /* ndef KILLPOPUPS */
+#ifndef JAR_FILES
+ case hash_jarfile :
+#endif /* ndef JAR_FILES */
+#ifndef ACL_FILES
+ case hash_aclfile :
+#endif /* ndef ACL_FILES */
+
+#ifdef SPLIT_PROXY_ARGS
+ case hash_suppress_blocklists :
+#endif /* def SPLIT_PROXY_ARGS */
+ log_error(LOG_LEVEL_INFO, "Unsupported directive \"%s\" ignored.", cmd);
+ continue;
+
+ default :
+ log_error(LOG_LEVEL_ERROR, "Unrecognized directive (%lulu) in "
+ "configuration file: \"%s\"", hash_string( cmd ), buf);
+ p = malloc( BUFSIZ );
+ if (p != NULL)
+ {
+ sprintf( p, "<br>\nWARNING: unrecognized directive : %s<br><br>\n", buf );
+ proxy_args->invocation = strsav( proxy_args->invocation, p );
+ freez( p );
+ }
+ /*
+ * I decided that I liked this better as a warning than an
+ * error.
+ */
+
+ /*
+ * configret = 1;
+ * return;
+ */
+ continue;
+ }
+ }
+ fclose(configfp);
+ }
+
+ init_error_log(Argv[0], logfile, debug);
+
+ if (cookiefile)
+ {
+ add_loader(load_cookiefile);
+ }
+
+ if (blockfile)
+ {
+ add_loader(load_blockfile);
+ }
+
+#ifdef USE_IMAGE_LIST
+ if (imagefile)
+ {
+ add_loader(load_imagefile);
+ }
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef TRUST_FILES
+ if (trustfile)
+ {
+ add_loader(load_trustfile);
+ }
+#endif /* def TRUST_FILES */
+
+ if (forwardfile)
+ {
+ add_loader(load_forwardfile);
+ }
+
+#ifdef ACL_FILES
+ if (aclfile)
+ {
+ add_loader(load_aclfile);
+ }
+#endif /* def ACL_FILES */
+
+#ifdef KILLPOPUPS
+ if (popupfile)
+ {
+ add_loader(load_popupfile);
+ }
+#endif /* def KILLPOPUPS */
+
+#ifdef PCRS
+ if (re_filterfile)
+ {
+ add_loader(load_re_filterfile);
+ }
+#endif /* def PCRS */
+
+#ifdef JAR_FILES
+ if ( NULL != jarfile )
+ {
+ if ( NULL == (jar = fopen(jarfile, "a")) )
+ {
+ log_error(LOG_LEVEL_ERROR, "can't open jarfile '%s': %E", jarfile);
+ configret = 1;
+ return;
+ }
+ setbuf(jar, NULL);
+ }
+#endif /* def JAR_FILES */
+
+ if ( NULL == haddr )
+ {
+ haddr = strdup( HADDR_DEFAULT );
+ }
+
+ if ( NULL != haddr )
+ {
+ if ((p = strchr(haddr, ':')))
+ {
+ *p++ = '\0';
+ if (*p)
+ {
+ hport = atoi(p);
+ }
+ }
+
+ if (hport <= 0)
+ {
+ *--p = ':';
+ log_error(LOG_LEVEL_ERROR, "invalid bind port spec %s", haddr);
+ configret = 1;
+ return;
+ }
+ if (*haddr == '\0')
+ {
+ haddr = NULL;
+ }
+ }
+
+ if (run_loader(NULL))
+ {
+ configret = 1;
+ return;
+ }
+
+#ifdef JAR_FILES
+ /*
+ * If we're logging cookies in a cookie jar, and the user has not
+ * supplied any wafers, and the user has not told us to suppress the
+ * vanilla wafer, then send the vanilla wafer.
+ */
+ if ((jarfile != NULL)
+ && (wafer_list->next == NULL)
+ && (suppress_vanilla_wafer == 0))
+ {
+ enlist(wafer_list, VANILLA_WAFER);
+ }
+#endif /* def JAR_FILES */
+
+ end_proxy_args();
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _LOADCFG_H
+#define _LOADCFG_H
+#define LOADCFG_H_VERSION "$Id: loadcfg.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/loadcfg.h,v $
+ *
+ * Purpose : Loads settings from the configuration file into
+ * global variables. This file contains both the
+ * routine to load the configuration and the global
+ * variables it writes to.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: loadcfg.h,v $
+ *
+ *********************************************************************/
+\f
+
+/* Declare struct FILE for vars and funcs. */
+#include <stdio.h>
+
+/* All of our project's data types. */
+#include "project.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global variables */
+
+#ifdef TOGGLE
+/* indicates if ijb is enabled */
+extern int g_bToggleIJB;
+#endif
+
+extern int debug;
+extern int multi_threaded;
+
+#if defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST)
+extern int tinygif;
+extern const char *tinygifurl;\r
+#endif /* defined(DETECT_MSIE_IMAGES) || defined(USE_IMAGE_LIST) */
+
+extern const char *logfile;
+
+extern const char *configfile;
+
+#ifdef ACL_FILES
+extern const char *aclfile;
+#endif /* def ACL_FILES */
+
+extern const char *blockfile;
+extern const char *cookiefile;
+extern const char *forwardfile;
+
+#ifdef USE_IMAGE_LIST
+extern const char *imagefile;
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef KILLPOPUPS
+extern const char *popupfile;
+#endif /* def KILLPOPUPS */
+
+#ifdef TRUST_FILES
+extern const char *trustfile;
+#endif /* def TRUST_FILES */
+
+#ifdef PCRS
+extern const char *re_filterfile;
+#endif /* def PCRS */
+
+#ifdef PCRS
+extern int re_filter_all;
+#endif /* def PCRS */
+
+#ifdef KILLPOPUPS
+extern int kill_all_popups; /* Not recommended really .. */
+#endif /* def KILLPOPUPS */
+
+#ifdef JAR_FILES
+extern const char *jarfile;
+extern FILE *jar;
+#endif /* def JAR_FILES */
+
+extern const char *referrer;
+extern const char *uagent;
+extern const char *from;
+
+#ifndef SPLIT_PROXY_ARGS
+extern const char *suppress_message;
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+extern int suppress_vanilla_wafer;
+extern int add_forwarded;
+
+extern struct list wafer_list[];
+extern struct list xtra_list[];
+
+#ifdef TRUST_FILES
+extern struct list trust_info[];
+extern struct url_spec *trust_list[];
+#endif /* def TRUST_FILES */
+
+extern const char *haddr;
+extern int hport;
+
+#ifndef SPLIT_PROXY_ARGS
+extern int suppress_blocklists; /* suppress listing sblock and simage */
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+extern struct proxy_args proxy_args[1];
+
+extern int configret;
+extern int config_changed;
+
+
+/* The load_config function is now going to call:
+ * init_proxy_args, so it will need argc and argv.
+ * Since load_config will also be a signal handler,
+ * we need to have these globally available.
+ */
+extern int Argc;
+extern const char **Argv;
+
+
+extern void load_config( int );
+
+
+/* Revision control strings from this header and associated .c file */
+extern const char loadcfg_rcs[];
+extern const char loadcfg_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _JCC_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+const char loaders_rcs[] = "$Id: loaders.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/loaders.c,v $
+ *
+ * Purpose : Functions to load and unload the various
+ * configuration files. Also contains code to manage
+ * the list of active loaders, and to automatically
+ * unload files that are no longer in use.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: loaders.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <malloc.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include "project.h"
+#include "loaders.h"
+#include "encode.h"
+#include "filters.h"
+#include "parsers.h"
+#include "jcc.h"
+#include "ssplit.h"
+#include "miscutil.h"
+#include "errlog.h"
+#include "gateway.h"
+
+#ifndef SPLIT_PROXY_ARGS
+/* For strsav */
+#include "showargs.h"
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+const char loaders_h_rcs[] = LOADERS_H_VERSION;
+
+/* Fix a problem with Solaris. There should be no effect on other
+ * platforms.
+ * Solaris's isspace() is a macro which uses it's argument directly
+ * as an array index. Therefore we need to make sure that high-bit
+ * characters generate +ve values, and ideally we also want to make
+ * the argument match the declared parameter type of "int".
+ */
+#define ijb_isspace(__X) isspace((int)(unsigned char)(__X))
+
+
+#define NLOADERS 8
+static int (*loaders[NLOADERS])(struct client_state *);
+
+
+/*
+ * Currently active files.
+ * These are also entered in the main linked list of files.
+ */
+static struct file_list *current_blockfile = NULL;
+static struct file_list *current_cookiefile = NULL;
+static struct file_list *current_forwardfile = NULL;
+
+#ifdef ACL_FILES
+static struct file_list *current_aclfile = NULL;
+#endif /* def ACL_FILES */
+
+#ifdef USE_IMAGE_LIST
+static struct file_list *current_imagefile = NULL;
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef KILLPOPUPS
+static struct file_list * current_popupfile = NULL;
+#endif /* def KILLPOPUPS */
+
+#ifdef TRUST_FILES
+static struct file_list *current_trustfile = NULL;
+#endif /* def TRUST_FILES */
+
+#ifdef PCRS
+static struct file_list *current_re_filterfile = NULL;
+#endif /* def PCRS */
+
+
+/*********************************************************************
+ *
+ * Function : sweep
+ *
+ * Description : Basically a mark and sweep garbage collector, it is run
+ * (by the parent thread) every once in a while to reclaim memory.
+ *
+ * It uses a mark and sweep strategy:
+ * 1) mark all files as inactive
+ *
+ * 2) check with each client:
+ * if it is active, mark its files as active
+ * if it is inactive, free its resources
+ *
+ * 3) free the resources of all of the files that
+ * are still marked as inactive (and are obsolete).
+ *
+ * N.B. files that are not obsolete don't have an unloader defined.
+ *
+ * Parameters : None
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void sweep(void)
+{
+ struct file_list *fl, *nfl;
+ struct client_state *csp, *ncsp;
+
+ /* clear all of the file's active flags */
+ for ( fl = files->next; NULL != fl; fl = fl->next )
+ {
+ fl->active = 0;
+ }
+
+ for (csp = clients; csp && (ncsp = csp->next) ; csp = csp->next)
+ {
+ if (ncsp->active)
+ {
+ /* mark this client's files as active */
+
+ if (ncsp->blist) /* block files */
+ {
+ ncsp->blist->active = 1;
+ }
+
+ if (ncsp->clist) /* cookie files */
+ {
+ ncsp->clist->active = 1;
+ }
+
+ /* FIXME: These were left out of the "10" release. Should they be here? */
+ if (ncsp->flist) /* forward files */
+ {
+ ncsp->flist->active = 1;
+ }
+
+#ifdef ACL_FILES
+ if (ncsp->alist) /* acl files */
+ {
+ ncsp->alist->active = 1;
+ }
+#endif /* def ACL_FILES */
+
+#ifdef USE_IMAGE_LIST
+ if (ncsp->ilist) /* image files */
+ {
+ ncsp->ilist->active = 1;
+ }
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef KILLPOPUPS
+ if (ncsp->plist) /* killpopup files */
+ {
+ ncsp->plist->active = 1;
+ }
+#endif /* def KILLPOPUPS */
+
+#ifdef PCRS
+ if (ncsp->rlist) /* perl re files */
+ {
+ ncsp->rlist->active = 1;
+ }
+#endif /* def PCRS */
+
+#ifdef TRUST_FILES
+ if (ncsp->tlist) /* trust files */
+ {
+ ncsp->tlist->active = 1;
+ }
+#endif /* def TRUST_FILES */
+
+ }
+ else
+ {
+ /* this client one is not active, release its resources */
+ csp->next = ncsp->next;
+
+ freez(ncsp->ip_addr_str);
+ freez(ncsp->referrer);
+ freez(ncsp->x_forwarded);
+ freez(ncsp->ip_addr_str);
+ freez(ncsp->iob->buf);
+
+ free_http_request(ncsp->http);
+
+ destroy_list(ncsp->headers);
+ destroy_list(ncsp->cookie_list);
+
+#ifdef STATISTICS
+ urls_read++;
+ if (ncsp->rejected)
+ {
+ urls_rejected++;
+ }
+#endif /* def STATISTICS */
+
+ freez(ncsp);
+ }
+ }
+
+ for (fl = files; fl && (nfl = fl->next) ; fl = fl->next)
+ {
+ if ( ( 0 == nfl->active ) && ( NULL != nfl->unloader ) )
+ {
+ fl->next = nfl->next;
+
+ (nfl->unloader)(nfl->f);
+
+#ifndef SPLIT_PROXY_ARGS
+ freez(nfl->proxy_args);
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ freez(nfl->filename);
+
+ freez(nfl);
+ }
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : unload_url
+ *
+ * Description : Called from the "unloaders". Freez the url
+ * structure elements.
+ *
+ * Parameters :
+ * 1 : url = pointer to a url_spec structure.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void unload_url(struct url_spec *url)
+{
+ if (url == NULL) return;
+
+ freez(url->spec);
+ freez(url->domain);
+ freez(url->dbuf);
+ freez(url->dvec);
+ freez(url->path);
+#ifdef REGEX
+ if (url->preg)
+ {
+ regfree(url->preg);
+ freez(url->preg);
+ }
+#endif
+
+}
+
+
+#ifdef ACL_FILES
+/*********************************************************************
+ *
+ * Function : unload_aclfile
+ *
+ * Description : Unloads an aclfile.
+ *
+ * Parameters :
+ * 1 : f = the data structure associated with the aclfile.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void unload_aclfile(void *f)
+{
+ struct access_control_list *b = (struct access_control_list *)f;
+ if (b == NULL) return;
+
+ unload_aclfile(b->next);
+
+ freez(b);
+
+}
+#endif /* def ACL_FILES */
+
+/*********************************************************************
+ *
+ * Function : unload_blockfile
+ *
+ * Description : Unloads a blockfile.
+ *
+ * Parameters :
+ * 1 : f = the data structure associated with the blockfile.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void unload_blockfile(void *f)
+{
+ struct block_spec *b = (struct block_spec *)f;
+ if (b == NULL) return;
+
+ unload_blockfile(b->next);
+
+ unload_url(b->url);
+
+ freez(b);
+
+}
+
+
+#ifdef USE_IMAGE_LIST
+/*********************************************************************
+ *
+ * Function : unload_imagefile
+ *
+ * Description : Unloads an imagefile.
+ *
+ * Parameters :
+ * 1 : f = the data structure associated with the imagefile.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void unload_imagefile(void *f)
+{
+ struct block_spec *b = (struct block_spec *)f;
+ if (b == NULL) return;
+
+ unload_imagefile(b->next);
+
+ unload_url(b->url);
+
+ freez(b);
+
+}
+#endif /* def USE_IMAGE_LIST */
+
+
+/*********************************************************************
+ *
+ * Function : unload_cookiefile
+ *
+ * Description : Unloads a cookiefile.
+ *
+ * Parameters :
+ * 1 : f = the data structure associated with the cookiefile.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void unload_cookiefile(void *f)
+{
+ struct cookie_spec *b = (struct cookie_spec *)f;
+ if (b == NULL) return;
+
+ unload_cookiefile(b->next);
+
+ unload_url(b->url);
+
+ freez(b);
+
+}
+
+
+#ifdef TRUST_FILES
+/*********************************************************************
+ *
+ * Function : unload_trustfile
+ *
+ * Description : Unloads a trustfile.
+ *
+ * Parameters :
+ * 1 : f = the data structure associated with the trustfile.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void unload_trustfile(void *f)
+{
+ struct block_spec *b = (struct block_spec *)f;
+ if (b == NULL) return;
+
+ unload_trustfile(b->next);
+
+ unload_url(b->url);
+
+ freez(b);
+
+}
+#endif /* def TRUST_FILES */
+
+
+/*********************************************************************
+ *
+ * Function : unload_forwardfile
+ *
+ * Description : Unloads a forwardfile.
+ *
+ * Parameters :
+ * 1 : f = the data structure associated with the forwardfile.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void unload_forwardfile(void *f)
+{
+ struct forward_spec *b = (struct forward_spec *)f;
+ if (b == NULL) return;
+
+ unload_forwardfile(b->next);
+
+ unload_url(b->url);
+
+ freez(b->gw->gateway_host);
+ freez(b->gw->forward_host);
+
+ freez(b);
+
+}
+
+
+#ifdef PCRS
+/*********************************************************************
+ *
+ * Function : unload_re_filterfile
+ *
+ * Description : Unload the re_filter list.
+ *
+ * Parameters :
+ * 1 : f = the data structure associated with the filterfile.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void unload_re_filterfile(void *f)
+{
+ pcrs_job *joblist;
+ struct re_filterfile_spec *b = (struct re_filterfile_spec *)f;
+
+ if (b == NULL) return;
+
+ destroy_list(b->patterns);
+
+ joblist = b->joblist;
+ while ( NULL != (joblist = pcrs_free_job(joblist)) ) {}
+
+ freez(b);
+
+}
+#endif /* def PCRS */
+
+
+#ifdef KILLPOPUPS
+/*********************************************************************
+ *
+ * Function : unload_popupfile
+ *
+ * Description : Free the lists of blocked, and allowed popup sites.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void unload_popupfile(void * b)
+{
+ struct popup_settings * data = (struct popup_settings *) b;
+ struct popup_blocklist * cur = NULL;
+ struct popup_blocklist * temp= NULL;
+
+ /* Free the blocked list. */
+ cur = data->blocked;
+ while (cur != NULL)
+ {
+ temp = cur->next;
+ freez (cur->host_name);
+ free (cur);
+ cur = temp;
+ }
+ data->blocked = NULL;
+
+ /* Free the allowed list. */
+ cur = data->allowed;
+ while (cur != NULL)
+ {
+ temp = cur->next;
+ freez (cur->host_name);
+ free (cur);
+ cur = temp;
+ }
+ data->allowed = NULL;
+
+}
+#endif /* def KILLPOPUPS */
+
+
+/*********************************************************************
+ *
+ * Function : check_file_changed
+ *
+ * Description : Helper function to check if a file needs reloading.
+ * If "current" is still current, return it. Otherwise
+ * allocates a new (zeroed) "struct file_list", fills
+ * in the disk file name and timestamp, and returns it.
+ *
+ * Parameters :
+ * 1 : current = The file_list currently being used - will
+ * be checked to see if it is out of date.
+ * May be NULL (which is treated as out of
+ * date).
+ * 2 : filename = Name of file to check.
+ * 3 : newfl = New file list. [Output only]
+ * This will be set to NULL, OR a struct
+ * file_list newly allocated on the
+ * heap, with the filename and lastmodified
+ * fields filled, standard header giving file
+ * name in proxy_args, and all others zeroed.
+ * (proxy_args is only filled in if
+ * SPLIT_PROXY_ARGS and !suppress_blocklists).
+ *
+ * Returns : If file unchanged: 0 (and sets newfl == NULL)
+ * If file changed: 1 and sets newfl != NULL
+ * On error: 1 and sets newfl == NULL
+ *
+ *********************************************************************/
+static int check_file_changed(const struct file_list * current,
+ const char * filename,
+ struct file_list ** newfl)
+{
+ struct file_list *fs;
+ struct stat statbuf[1];
+
+ *newfl = NULL;
+
+ if (stat(filename, statbuf) < 0)
+ {
+ /* Error, probably file not found. */
+ return 1;
+ }
+
+ if (current
+ && (current->lastmodified == statbuf->st_mtime)
+ && (0 == strcmp(current->filename, filename)))
+ {
+ return 0;
+ }
+
+ fs = (struct file_list *)zalloc(sizeof(struct file_list));
+
+ if (fs == NULL)
+ {
+ /* Out of memory error */
+ return 1;
+ }
+
+ fs->filename = strdup(filename);
+ fs->lastmodified = statbuf->st_mtime;
+
+ if (fs->filename == NULL)
+ {
+ /* Out of memory error */
+ freez (fs);
+ return 1;
+ }
+
+#ifndef SPLIT_PROXY_ARGS
+ if (!suppress_blocklists)
+ {
+ char * p = html_encode(filename);
+ if (p)
+ {
+ fs->proxy_args = strsav(fs->proxy_args, "<h2>The file `");\r
+ fs->proxy_args = strsav(fs->proxy_args, p);\r
+ fs->proxy_args = strsav(fs->proxy_args, \r
+ "' contains the following patterns</h2>\n");\r
+ freez(p);\r
+ }
+ fs->proxy_args = strsav(fs->proxy_args, "<pre>");
+ }
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ *newfl = fs;
+ return 1;
+}
+
+
+/*********************************************************************
+ *
+ * Function : read_config_line
+ *
+ * Description : Read a single non-empty line from a file and return
+ * it. Trims comments, leading and trailing whitespace.
+ * Also wites the file to fs->proxy_args.
+ *
+ * Parameters :
+ * 1 : buf = Buffer to use.
+ * 2 : buflen = Size of buffer in bytes.
+ * 3 : fp = File to read from
+ * 4 : fs = File will be written to fs->proxy_args. May
+ * be NULL to disable this feature.
+ *
+ * Returns : NULL on EOF or error
+ * Otherwise, returns buf.
+ *
+ *********************************************************************/
+char *read_config_line(char *buf, int buflen, FILE *fp, struct file_list *fs)
+{
+ char *p, *q;
+ char linebuf[BUFSIZ];
+
+ while (fgets(linebuf, sizeof(linebuf), fp))
+ {
+#ifndef SPLIT_PROXY_ARGS
+ if (fs && !suppress_blocklists)
+ {
+ char *html_line = html_encode(linebuf);
+ if (html_line != NULL)
+ {
+ fs->proxy_args = strsav(fs->proxy_args, html_line);
+ freez(html_line);
+ }
+ fs->proxy_args = strsav(fs->proxy_args, "<br>");
+ }
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ /* Trim off newline and any comment */
+ if ((p = strpbrk(linebuf, "\r\n#")) != NULL)
+ {
+ *p = '\0';
+ }
+
+ /* Trim leading whitespace */
+ p = linebuf;
+ while (*p && ijb_isspace(*p))
+ {
+ *p++;
+ }
+
+ if (*p)
+ {
+ /* There is something other than whitespace on the line. */
+
+ /* Move the data to the start of buf */
+ if (p != linebuf)
+ {
+ /* strcpy that can cope with overlap. */
+ q = linebuf;
+ while ((*q++ = *p++) != '\0')
+ {
+ /* Do nothing */
+ }
+ }
+
+ /* Trim trailing whitespace */
+ p = linebuf + strlen(linebuf) - 1;
+
+ /*
+ * Note: the (p >= retval) below is paranoia, it's not really needed.
+ * When p == retval then ijb_isspace(*p) will be false and we'll drop
+ * out of the loop.
+ */
+ while ((p >= linebuf) && ijb_isspace(*p))
+ {
+ p--;
+ }
+ p[1] = '\0';
+
+ /* More paranoia. This if statement is always true. */
+ if (*linebuf)
+ {
+ strcpy(buf, linebuf);
+ return buf;
+ }
+ }
+ }
+
+ /* EOF */
+ return NULL;
+}
+
+
+#ifdef ACL_FILES
+/*********************************************************************
+ *
+ * Function : load_aclfile
+ *
+ * Description : Read and parse an aclfile and add to files list.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 => Ok, everything else is an error.
+ *
+ *********************************************************************/
+int load_aclfile(struct client_state *csp)
+{
+ FILE *fp;
+ char buf[BUFSIZ], *v[3], *p;
+ int i;
+ struct access_control_list *a, *bl;
+ struct file_list *fs;
+
+ if (!check_file_changed(current_aclfile, aclfile, &fs))
+ {
+ /* No need to load */
+ if (csp)
+ {
+ csp->alist = current_aclfile;
+ }
+ return(0);
+ }
+ if (!fs)
+ {
+ goto load_aclfile_error;
+ }
+
+ fs->f = bl = (struct access_control_list *)zalloc(sizeof(*bl));
+ if (bl == NULL)
+ {
+ freez(fs->filename);
+ freez(fs);
+ goto load_aclfile_error;
+ }
+
+ fp = fopen(aclfile, "r");
+
+ if (fp == NULL)
+ {
+ goto load_aclfile_error;
+ }
+
+ while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
+ {
+ i = ssplit(buf, " \t", v, SZ(v), 1, 1);
+
+ /* allocate a new node */
+ a = (struct access_control_list *) zalloc(sizeof(*a));
+
+ if (a == NULL)
+ {
+ fclose(fp);
+ freez(fs->f);
+ freez(fs->filename);
+ freez(fs);
+ goto load_aclfile_error;
+ }
+
+ /* add it to the list */
+ a->next = bl->next;
+ bl->next = a;
+
+ switch (i)
+ {
+ case 3:
+ if (acl_addr(v[2], a->dst) < 0)
+ {
+ goto load_aclfile_error;
+ }
+ /* no break */
+
+ case 2:
+ if (acl_addr(v[1], a->src) < 0)
+ {
+ goto load_aclfile_error;
+ }
+
+ p = v[0];
+ if (strcmpic(p, "permit") == 0)
+ {
+ a->action = ACL_PERMIT;
+ break;
+ }
+
+ if (strcmpic(p, "deny") == 0)
+ {
+ a->action = ACL_DENY;
+ break;
+ }
+ /* no break */
+
+ default:
+ goto load_aclfile_error;
+ }
+ }
+
+ fclose(fp);
+
+#ifndef SPLIT_PROXY_ARGS
+ if (!suppress_blocklists)
+ {
+ fs->proxy_args = strsav(fs->proxy_args, "</pre>");
+ }
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ if (current_aclfile)
+ {
+ current_aclfile->unloader = unload_aclfile;
+ }
+
+ fs->next = files->next;
+ files->next = fs;
+ current_aclfile = fs;
+
+ if (csp)
+ {
+ csp->alist = fs;
+ }
+
+ return(0);
+
+load_aclfile_error:
+ log_error(LOG_LEVEL_ERROR, "can't load access control list %s: %E", aclfile);
+ return(-1);
+
+}
+#endif /* def ACL_FILES */
+
+
+/*********************************************************************
+ *
+ * Function : load_blockfile
+ *
+ * Description : Read and parse a blockfile and add to files list.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 => Ok, everything else is an error.
+ *
+ *********************************************************************/
+int load_blockfile(struct client_state *csp)
+{
+ FILE *fp;
+
+ struct block_spec *b, *bl;
+ char buf[BUFSIZ], *p, *q;
+ int port, reject;
+ struct file_list *fs;
+ struct url_spec url[1];
+
+ if (!check_file_changed(current_blockfile, blockfile, &fs))
+ {
+ /* No need to load */
+ if (csp)
+ {
+ csp->blist = current_blockfile;
+ }
+ return(0);
+ }
+ if (!fs)
+ {
+ goto load_blockfile_error;
+ }
+
+ fs->f = bl = (struct block_spec *) zalloc(sizeof(*bl));
+ if (bl == NULL)
+ {
+ goto load_blockfile_error;
+ }
+
+ if ((fp = fopen(blockfile, "r")) == NULL)
+ {
+ goto load_blockfile_error;
+ }
+
+ while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
+ {
+ reject = 1;
+
+ if (*buf == '~')
+ {
+ reject = 0;
+ p = buf;
+ q = p+1;
+ while ((*p++ = *q++))
+ {
+ /* nop */
+ }
+ }
+
+ /* skip lines containing only ~ */
+ if (*buf == '\0')
+ {
+ continue;
+ }
+
+ /* allocate a new node */
+ if (((b = zalloc(sizeof(*b))) == NULL)
+#ifdef REGEX
+ || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
+#endif
+ )
+ {
+ fclose(fp);
+ goto load_blockfile_error;
+ }
+
+ /* add it to the list */
+ b->next = bl->next;
+ bl->next = b;
+
+ /* save a copy of the orignal specification */
+ if ((b->url->spec = strdup(buf)) == NULL)
+ {
+ fclose(fp);
+ goto load_blockfile_error;
+ }
+
+ b->reject = reject;
+
+ if ((p = strchr(buf, '/')))
+ {
+ b->url->path = strdup(p);
+ b->url->pathlen = strlen(b->url->path);
+ *p = '\0';
+ }
+ else
+ {
+ b->url->path = NULL;
+ b->url->pathlen = 0;
+ }
+#ifdef REGEX
+ if (b->url->path)
+ {
+ int errcode;
+ char rebuf[BUFSIZ];
+
+ sprintf(rebuf, "^(%s)", b->url->path);
+
+ errcode = regcomp(b->url->preg, rebuf,
+ (REG_EXTENDED|REG_NOSUB|REG_ICASE));
+
+ if (errcode)
+ {
+ size_t errlen =
+ regerror(errcode,
+ b->url->preg, buf, sizeof(buf));
+
+ buf[errlen] = '\0';
+
+ log_error(LOG_LEVEL_ERROR, "error compiling %s: %s\n",
+ b->url->spec, buf);
+ fclose(fp);
+ goto load_blockfile_error;
+ }
+ }
+ else
+ {
+ freez(b->url->preg);
+ }
+#endif
+ if ((p = strchr(buf, ':')) == NULL)
+ {
+ port = 0;
+ }
+ else
+ {
+ *p++ = '\0';
+ port = atoi(p);
+ }
+
+ b->url->port = port;
+
+ if ((b->url->domain = strdup(buf)) == NULL)
+ {
+ fclose(fp);
+ goto load_blockfile_error;
+ }
+
+ /* split domain into components */
+ *url = dsplit(b->url->domain);
+ b->url->dbuf = url->dbuf;
+ b->url->dcnt = url->dcnt;
+ b->url->dvec = url->dvec;
+ }
+
+ fclose(fp);
+
+#ifndef SPLIT_PROXY_ARGS
+ if (!suppress_blocklists)
+ {
+ fs->proxy_args = strsav(fs->proxy_args, "</pre>");
+ }
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ /* the old one is now obsolete */
+ if (current_blockfile)
+ {
+ current_blockfile->unloader = unload_blockfile;
+ }
+
+ fs->next = files->next;
+ files->next = fs;
+ current_blockfile = fs;
+
+ if (csp)
+ {
+ csp->blist = fs;
+ }
+
+ return(0);
+
+load_blockfile_error:
+ log_error(LOG_LEVEL_ERROR, "can't load blockfile '%s': %E", blockfile);
+ return(-1);
+
+}
+
+
+#ifdef USE_IMAGE_LIST
+/*********************************************************************
+ *
+ * Function : load_imagefile
+ *
+ * Description : Read and parse an imagefile and add to files list.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 => Ok, everything else is an error.
+ *
+ *********************************************************************/
+int load_imagefile(struct client_state *csp)
+{
+ FILE *fp;
+
+ struct block_spec *b, *bl;
+ char buf[BUFSIZ], *p, *q;
+ int port, reject;
+ struct file_list *fs;
+ struct url_spec url[1];
+
+ if (!check_file_changed(current_imagefile, imagefile, &fs))
+ {
+ /* No need to load */
+ if (csp)
+ {
+ csp->ilist = current_imagefile;
+ }
+ return(0);
+ }
+ if (!fs)
+ {
+ goto load_imagefile_error;
+ }
+
+ fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
+ if (bl == NULL)
+ {
+ goto load_imagefile_error;
+ }
+
+ if ((fp = fopen(imagefile, "r")) == NULL)
+ {
+ goto load_imagefile_error;
+ }
+
+ while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
+ {
+ reject = 1;
+
+ if (*buf == '~')
+ {
+ reject = 0;
+ p = buf;
+ q = p+1;
+ while ((*p++ = *q++))
+ {
+ /* nop */
+ }
+ }
+
+ /* skip lines containing only ~ */
+ if (*buf == '\0')
+ {
+ continue;
+ }
+
+ /* allocate a new node */
+ if (((b = zalloc(sizeof(*b))) == NULL)
+#ifdef REGEX
+ || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
+#endif
+ )
+ {
+ fclose(fp);
+ goto load_imagefile_error;
+ }
+
+ /* add it to the list */
+ b->next = bl->next;
+ bl->next = b;
+
+ /* save a copy of the orignal specification */
+ if ((b->url->spec = strdup(buf)) == NULL)
+ {
+ fclose(fp);
+ goto load_imagefile_error;
+ }
+
+ b->reject = reject;
+
+ if ((p = strchr(buf, '/')))
+ {
+ b->url->path = strdup(p);
+ b->url->pathlen = strlen(b->url->path);
+ *p = '\0';
+ }
+ else
+ {
+ b->url->path = NULL;
+ b->url->pathlen = 0;
+ }
+#ifdef REGEX
+ if (b->url->path)
+ {
+ int errcode;
+ char rebuf[BUFSIZ];
+
+ sprintf(rebuf, "^(%s)", b->url->path);
+
+ errcode = regcomp(b->url->preg, rebuf,
+ (REG_EXTENDED|REG_NOSUB|REG_ICASE));
+
+ if (errcode)
+ {
+ size_t errlen =
+ regerror(errcode,
+ b->url->preg, buf, sizeof(buf));
+
+ buf[errlen] = '\0';
+
+ log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
+ b->url->spec, buf);
+ fclose(fp);
+ goto load_imagefile_error;
+ }
+ }
+ else
+ {
+ freez(b->url->preg);
+ }
+#endif
+ if ((p = strchr(buf, ':')) == NULL)
+ {
+ port = 0;
+ }
+ else
+ {
+ *p++ = '\0';
+ port = atoi(p);
+ }
+
+ b->url->port = port;
+
+ if ((b->url->domain = strdup(buf)) == NULL)
+ {
+ fclose(fp);
+ goto load_imagefile_error;
+ }
+
+ /* split domain into components */
+ *url = dsplit(b->url->domain);
+ b->url->dbuf = url->dbuf;
+ b->url->dcnt = url->dcnt;
+ b->url->dvec = url->dvec;
+ }
+#ifndef SPLIT_PROXY_ARGS
+ if (!suppress_blocklists)
+ fs->proxy_args = strsav(fs->proxy_args, "</pre>");
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ fclose(fp);
+
+#ifndef SPLIT_PROXY_ARGS
+ if (!suppress_blocklists)
+ {
+ fs->proxy_args = strsav(fs->proxy_args, "</pre>");
+ }
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ /* the old one is now obsolete */
+ if (current_imagefile)
+ {
+ current_imagefile->unloader = unload_imagefile;
+ }
+
+ fs->next = files->next;
+ files->next = fs;
+ current_imagefile = fs;
+
+ if (csp)
+ {
+ csp->ilist = fs;
+ }
+
+ return(0);
+
+load_imagefile_error:
+ log_error(LOG_LEVEL_ERROR, "can't load imagefile '%s': %E", imagefile);
+ return(-1);
+
+}
+#endif /* def USE_IMAGE_LIST */
+
+
+/*********************************************************************
+ *
+ * Function : load_cookiefile
+ *
+ * Description : Read and parse a cookiefile and add to files list.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 => Ok, everything else is an error.
+ *
+ *********************************************************************/
+int load_cookiefile(struct client_state *csp)
+{
+ FILE *fp;
+
+ struct cookie_spec *b, *bl;
+ char buf[BUFSIZ], *p, *q;
+ int port, user_cookie, server_cookie;
+ struct file_list *fs;
+ struct url_spec url[1];
+
+ if (!check_file_changed(current_cookiefile, cookiefile, &fs))
+ {
+ /* No need to load */
+ if (csp)
+ {
+ csp->clist = current_cookiefile;
+ }
+ return(0);
+ }
+ if (!fs)
+ {
+ goto load_cookie_error;
+ }
+
+ fs->f = bl = (struct cookie_spec *)zalloc(sizeof(*bl));
+ if (bl == NULL)
+ {
+ goto load_cookie_error;
+ }
+
+ if ((fp = fopen(cookiefile, "r")) == NULL)
+ {
+ goto load_cookie_error;
+ }
+
+ while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
+ {
+ p = buf;
+
+ switch ((int)*p)
+ {
+ case '>':
+ server_cookie = 0;
+ user_cookie = 1;
+ p++;
+ break;
+
+ case '<':
+ server_cookie = 1;
+ user_cookie = 0;
+ p++;
+ break;
+
+ case '~':
+ server_cookie = 0;
+ user_cookie = 0;
+ p++;
+ break;
+
+ default:
+ server_cookie = 1;
+ user_cookie = 1;
+ break;
+ }
+
+ /*
+ * Elide any of the "special" chars from the
+ * front of the pattern
+ */
+ q = buf;
+ if (p > q) while ((*q++ = *p++))
+ {
+ /* nop */
+ }
+
+ /* skip lines containing only "special" chars */
+ if (*buf == '\0')
+ {
+ continue;
+ }
+
+ /* allocate a new node */
+ if (((b = zalloc(sizeof(*b))) == NULL)
+#ifdef REGEX
+ || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
+#endif
+ )
+ {
+ fclose(fp);
+ goto load_cookie_error;
+ }
+
+ /* add it to the list */
+ b->next = bl->next;
+ bl->next = b;
+
+ /* save a copy of the orignal specification */
+ if ((b->url->spec = strdup(buf)) == NULL)
+ {
+ fclose(fp);
+ goto load_cookie_error;
+ }
+
+ b->send_user_cookie = user_cookie;
+ b->accept_server_cookie = server_cookie;
+
+ if ((p = strchr(buf, '/')))
+ {
+ b->url->path = strdup(p);
+ b->url->pathlen = strlen(b->url->path);
+ *p = '\0';
+ }
+ else
+ {
+ b->url->path = NULL;
+ b->url->pathlen = 0;
+ }
+#ifdef REGEX
+ if (b->url->path)
+ {
+ int errcode;
+ char rebuf[BUFSIZ];
+
+ sprintf(rebuf, "^(%s)", b->url->path);
+
+ errcode = regcomp(b->url->preg, rebuf,
+ (REG_EXTENDED|REG_NOSUB|REG_ICASE));
+ if (errcode)
+ {
+ size_t errlen =
+ regerror(errcode,
+ b->url->preg, buf, sizeof(buf));
+
+ buf[errlen] = '\0';
+
+ log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
+ b->url->spec, buf);
+ fclose(fp);
+ goto load_cookie_error;
+ }
+ }
+ else
+ {
+ freez(b->url->preg);
+ }
+#endif
+ if ((p = strchr(buf, ':')) == NULL)
+ {
+ port = 0;
+ }
+ else
+ {
+ *p++ = '\0';
+ port = atoi(p);
+ }
+
+ b->url->port = port;
+
+ if ((b->url->domain = strdup(buf)) == NULL)
+ {
+ fclose(fp);
+ goto load_cookie_error;
+ }
+
+ /* split domain into components */
+
+ *url = dsplit(b->url->domain);
+ b->url->dbuf = url->dbuf;
+ b->url->dcnt = url->dcnt;
+ b->url->dvec = url->dvec;
+ }
+
+ fclose(fp);
+
+#ifndef SPLIT_PROXY_ARGS
+ if (!suppress_blocklists)
+ {
+ fs->proxy_args = strsav(fs->proxy_args, "</pre>");
+ }
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ /* the old one is now obsolete */
+ if (current_cookiefile)
+ {
+ current_cookiefile->unloader = unload_cookiefile;
+ }
+
+ fs->next = files->next;
+ files->next = fs;
+ current_cookiefile = fs;
+
+ if (csp)
+ {
+ csp->clist = fs;
+ }
+
+ return(0);
+
+load_cookie_error:
+ log_error(LOG_LEVEL_ERROR, "can't load cookiefile '%s': %E", cookiefile);
+ return(-1);
+
+}
+
+
+#ifdef TRUST_FILES
+/*********************************************************************
+ *
+ * Function : load_trustfile
+ *
+ * Description : Read and parse a trustfile and add to files list.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 => Ok, everything else is an error.
+ *
+ *********************************************************************/
+int load_trustfile(struct client_state *csp)
+{
+ FILE *fp;
+
+ struct block_spec *b, *bl;
+ struct url_spec **tl;
+
+ char buf[BUFSIZ], *p, *q;
+ int port, reject, trusted;
+ struct file_list *fs;
+ struct url_spec url[1];
+
+ if (!check_file_changed(current_trustfile, trustfile, &fs))
+ {
+ /* No need to load */
+ if (csp)
+ {
+ csp->tlist = current_trustfile;
+ }
+ return(0);
+ }
+ if (!fs)
+ {
+ goto load_trustfile_error;
+ }
+
+ fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
+ if (bl == NULL)
+ {
+ goto load_trustfile_error;
+ }
+
+ if ((fp = fopen(trustfile, "r")) == NULL)
+ {
+ goto load_trustfile_error;
+ }
+
+ tl = trust_list;
+
+ while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
+ {
+ trusted = 0;
+ reject = 1;
+
+ if (*buf == '+')
+ {
+ trusted = 1;
+ *buf = '~';
+ }
+
+ if (*buf == '~')
+ {
+ reject = 0;
+ p = buf;
+ q = p+1;
+ while ((*p++ = *q++))
+ {
+ /* nop */
+ }
+ }
+
+ /* skip blank lines */
+ if (*buf == '\0')
+ {
+ continue;
+ }
+
+ /* allocate a new node */
+ if (((b = zalloc(sizeof(*b))) == NULL)
+#ifdef REGEX
+ || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
+#endif
+ )
+ {
+ fclose(fp);
+ goto load_trustfile_error;
+ }
+
+ /* add it to the list */
+ b->next = bl->next;
+ bl->next = b;
+
+ /* save a copy of the orignal specification */
+ if ((b->url->spec = strdup(buf)) == NULL)
+ {
+ fclose(fp);
+ goto load_trustfile_error;
+ }
+
+ b->reject = reject;
+
+ if ((p = strchr(buf, '/')))
+ {
+ b->url->path = strdup(p);
+ b->url->pathlen = strlen(b->url->path);
+ *p = '\0';
+ }
+ else
+ {
+ b->url->path = NULL;
+ b->url->pathlen = 0;
+ }
+#ifdef REGEX
+ if (b->url->path)
+ {
+ int errcode;
+ char rebuf[BUFSIZ];
+
+ sprintf(rebuf, "^(%s)", b->url->path);
+
+ errcode = regcomp(b->url->preg, rebuf,
+ (REG_EXTENDED|REG_NOSUB|REG_ICASE));
+
+ if (errcode)
+ {
+ size_t errlen =
+ regerror(errcode,
+ b->url->preg, buf, sizeof(buf));
+
+ buf[errlen] = '\0';
+
+ log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
+ b->url->spec, buf);
+ fclose(fp);
+ goto load_trustfile_error;
+ }
+ }
+ else
+ {
+ freez(b->url->preg);
+ }
+#endif
+ if ((p = strchr(buf, ':')) == NULL)
+ {
+ port = 0;
+ }
+ else
+ {
+ *p++ = '\0';
+ port = atoi(p);
+ }
+
+ b->url->port = port;
+
+ if ((b->url->domain = strdup(buf)) == NULL)
+ {
+ fclose(fp);
+ goto load_trustfile_error;
+ }
+
+ /* split domain into components */
+ *url = dsplit(b->url->domain);
+ b->url->dbuf = url->dbuf;
+ b->url->dcnt = url->dcnt;
+ b->url->dvec = url->dvec;
+
+ /*
+ * save a pointer to URL's spec in the list of trusted URL's, too
+ */
+ if (trusted)
+ {
+ *tl++ = b->url;
+ }
+ }
+
+ *tl = NULL;
+
+ fclose(fp);
+
+#ifndef SPLIT_PROXY_ARGS
+ if (!suppress_blocklists)
+ {
+ fs->proxy_args = strsav(fs->proxy_args, "</pre>");
+ }
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ /* the old one is now obsolete */
+ if (current_trustfile)
+ {
+ current_trustfile->unloader = unload_trustfile;
+ }
+
+ fs->next = files->next;
+ files->next = fs;
+ current_trustfile = fs;
+
+ if (csp)
+ {
+ csp->tlist = fs;
+ }
+
+ return(0);
+
+load_trustfile_error:
+ log_error(LOG_LEVEL_ERROR, "can't load trustfile '%s': %E", trustfile);
+ return(-1);
+
+}
+#endif /* def TRUST_FILES */
+
+
+/*********************************************************************
+ *
+ * Function : load_forwardfile
+ *
+ * Description : Read and parse a forwardfile and add to files list.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 => Ok, everything else is an error.
+ *
+ *********************************************************************/
+int load_forwardfile(struct client_state *csp)
+{
+ FILE *fp;
+
+ struct forward_spec *b, *bl;
+ char buf[BUFSIZ], *p, *q, *tmp;
+ char *vec[4];
+ int port, n, reject;
+ struct file_list *fs;
+ const struct gateway *gw;
+ struct url_spec url[1];
+
+ if (!check_file_changed(current_forwardfile, forwardfile, &fs))
+ {
+ /* No need to load */
+ if (csp)
+ {
+ csp->flist = current_forwardfile;
+ }
+ return(0);
+ }
+ if (!fs)
+ {
+ goto load_forwardfile_error;
+ }
+
+ fs->f = bl = (struct forward_spec *)zalloc(sizeof(*bl));
+
+ if ((fs == NULL) || (bl == NULL))
+ {
+ goto load_forwardfile_error;
+ }
+
+ if ((fp = fopen(forwardfile, "r")) == NULL)
+ {
+ goto load_forwardfile_error;
+ }
+
+ tmp = NULL;
+
+ while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
+ {
+ freez(tmp);
+
+ tmp = strdup(buf);
+
+ n = ssplit(tmp, " \t", vec, SZ(vec), 1, 1);
+
+ if (n != 4)
+ {
+ log_error(LOG_LEVEL_ERROR, "error in forwardfile: %s", buf);
+ continue;
+ }
+
+ strcpy(buf, vec[0]);
+
+ reject = 1;
+
+ if (*buf == '~')
+ {
+ reject = 0;
+ p = buf;
+ q = p+1;
+ while ((*p++ = *q++))
+ {
+ /* nop */
+ }
+ }
+
+ /* skip lines containing only ~ */
+ if (*buf == '\0')
+ {
+ continue;
+ }
+
+ /* allocate a new node */
+ if (((b = zalloc(sizeof(*b))) == NULL)
+#ifdef REGEX
+ || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
+#endif
+ )
+ {
+ fclose(fp);
+ goto load_forwardfile_error;
+ }
+
+ /* add it to the list */
+ b->next = bl->next;
+ bl->next = b;
+
+ /* save a copy of the orignal specification */
+ if ((b->url->spec = strdup(buf)) == NULL)
+ {
+ fclose(fp);
+ goto load_forwardfile_error;
+ }
+
+ b->reject = reject;
+
+ if ((p = strchr(buf, '/')))
+ {
+ b->url->path = strdup(p);
+ b->url->pathlen = strlen(b->url->path);
+ *p = '\0';
+ }
+ else
+ {
+ b->url->path = NULL;
+ b->url->pathlen = 0;
+ }
+#ifdef REGEX
+ if (b->url->path)
+ {
+ int errcode;
+ char rebuf[BUFSIZ];
+
+ sprintf(rebuf, "^(%s)", b->url->path);
+
+ errcode = regcomp(b->url->preg, rebuf,
+ (REG_EXTENDED|REG_NOSUB|REG_ICASE));
+
+ if (errcode)
+ {
+ size_t errlen = regerror(errcode, b->url->preg, buf, sizeof(buf));
+
+ buf[errlen] = '\0';
+
+ log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
+ b->url->spec, buf);
+ fclose(fp);
+ goto load_forwardfile_error;
+ }
+ }
+ else
+ {
+ freez(b->url->preg);
+ }
+#endif
+ if ((p = strchr(buf, ':')) == NULL)
+ {
+ port = 0;
+ }
+ else
+ {
+ *p++ = '\0';
+ port = atoi(p);
+ }
+
+ b->url->port = port;
+
+ if ((b->url->domain = strdup(buf)) == NULL)
+ {
+ fclose(fp);
+ goto load_forwardfile_error;
+ }
+
+ /* split domain into components */
+ *url = dsplit(b->url->domain);
+ b->url->dbuf = url->dbuf;
+ b->url->dcnt = url->dcnt;
+ b->url->dvec = url->dvec;
+
+ /* now parse the gateway specs */
+
+ p = vec[2];
+
+ for (gw = gateways; gw->name; gw++)
+ {
+ if (strcmp(gw->name, p) == 0)
+ {
+ break;
+ }
+ }
+
+ if (gw->name == NULL)
+ {
+ goto load_forwardfile_error;
+ }
+
+ /* save this as the gateway type */
+ *b->gw = *gw;
+
+ /* now parse the gateway host[:port] spec */
+ p = vec[3];
+
+ if (strcmp(p, ".") != 0)
+ {
+ b->gw->gateway_host = strdup(p);
+
+ if ((p = strchr(b->gw->gateway_host, ':')))
+ {
+ *p++ = '\0';
+ b->gw->gateway_port = atoi(p);
+ }
+
+ if (b->gw->gateway_port <= 0)
+ {
+ goto load_forwardfile_error;
+ }
+ }
+
+ /* now parse the forwarding spec */
+ p = vec[1];
+
+ if (strcmp(p, ".") != 0)
+ {
+ b->gw->forward_host = strdup(p);
+
+ if ((p = strchr(b->gw->forward_host, ':')))
+ {
+ *p++ = '\0';
+ b->gw->forward_port = atoi(p);
+ }
+
+ if (b->gw->forward_port <= 0)
+ {
+ b->gw->forward_port = 8000;
+ }
+ }
+ }
+
+ freez(tmp);
+
+ fclose(fp);
+
+#ifndef SPLIT_PROXY_ARGS
+ if (!suppress_blocklists)
+ {
+ fs->proxy_args = strsav(fs->proxy_args, "</pre>");
+ }
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ /* the old one is now obsolete */
+ if (current_forwardfile)
+ {
+ current_forwardfile->unloader = unload_forwardfile;
+ }
+
+ fs->next = files->next;
+ files->next = fs;
+ current_forwardfile = fs;
+
+ if (csp)
+ {
+ csp->flist = fs;
+ }
+
+ return(0);
+
+load_forwardfile_error:
+ log_error(LOG_LEVEL_ERROR, "can't load forwardfile '%s': %E", forwardfile);
+ return(-1);
+
+}
+
+
+#ifdef PCRS
+/*********************************************************************
+ *
+ * Function : load_re_filterfile
+ *
+ * Description : Load the re_filterfile. Each non-comment, non-empty
+ * line is instantly added to the joblist, which is
+ * a chained list of pcrs_job structs.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 => Ok, everything else is an error.
+ *
+ *********************************************************************/
+int load_re_filterfile(struct client_state *csp)
+{
+ FILE *fp;
+
+ struct re_filterfile_spec *bl;
+ struct file_list *fs;
+
+ char buf[BUFSIZ];
+ int error;
+ pcrs_job *dummy;
+
+#ifndef SPLIT_PROXY_ARGS
+ char *p;
+#endif /* ndef SPLIT_PROXY_ARGS */
+ if (!check_file_changed(current_re_filterfile, re_filterfile, &fs))
+ {
+ /* No need to load */
+ if (csp)
+ {
+ csp->rlist = current_re_filterfile;
+ }
+ return(0);
+ }
+ if (!fs)
+ {
+ goto load_re_filterfile_error;
+ }
+
+ fs->f = bl = (struct re_filterfile_spec *)zalloc(sizeof(*bl));
+ if (bl == NULL)
+ {
+ goto load_re_filterfile_error;
+ }
+
+ /* Open the file or fail */
+ if ((fp = fopen(re_filterfile, "r")) == NULL)
+ {
+ goto load_re_filterfile_error;
+ }
+
+ /* Read line by line */
+ while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
+ {
+ enlist( bl->patterns, buf );
+
+ /* We have a meaningful line -> make it a job */
+ if ((dummy = pcrs_make_job(buf, &error)) == NULL)
+ {
+ log_error(LOG_LEVEL_REF,
+ "Adding re_filter job %s failed with error %d.", buf, error);
+ continue;
+ }
+ else
+ {
+ dummy->next = bl->joblist;
+ bl->joblist = dummy;
+ log_error(LOG_LEVEL_REF, "Adding re_filter job %s succeeded.", buf);
+ }
+ }
+
+ fclose(fp);
+
+#ifndef SPLIT_PROXY_ARGS
+ if (!suppress_blocklists)
+ {
+ fs->proxy_args = strsav(fs->proxy_args, "</pre>");
+ }
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ /* the old one is now obsolete */
+ if ( NULL != current_re_filterfile )
+ {
+ current_re_filterfile->unloader = unload_re_filterfile;
+ }
+
+ fs->next = files->next;
+ files->next = fs;
+ current_re_filterfile = fs;
+
+ if (csp)
+ {
+ csp->rlist = fs;
+ }
+
+ return( 0 );
+
+load_re_filterfile_error:
+ log_error(LOG_LEVEL_ERROR, "can't load re_filterfile '%s': %E", re_filterfile);
+ return(-1);
+
+}
+#endif /* def PCRS */
+
+
+#ifdef KILLPOPUPS
+/*********************************************************************
+ *
+ * Function : load_popupfile
+ *
+ * Description : Load, and parse the popup blocklist.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 => success, else there was an error.
+ *
+ *********************************************************************/
+int load_popupfile(struct client_state *csp)
+{
+ FILE *fp;
+ char buf[BUFSIZ], *p, *q;
+ struct popup_blocklist *entry = NULL;
+ struct popup_settings * data;
+ struct file_list *fs;
+ p = buf;
+ q = buf;
+
+ if (!check_file_changed(current_popupfile, popupfile, &fs))
+ {
+ /* No need to load */
+ if (csp)
+ {
+ csp->plist = current_popupfile;
+ }
+ return(0);
+ }
+ if (!fs)
+ {
+ goto load_popupfile_error;
+ }
+
+ fs->f = data = (struct popup_settings *)zalloc(sizeof(*data));
+ if (data == NULL)
+ {
+ goto load_popupfile_error;
+ }
+
+ if ((fp = fopen(popupfile, "r")) == NULL)
+ {
+ goto load_popupfile_error;
+ }
+
+ while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
+ {
+ entry = (struct popup_blocklist*)zalloc(sizeof(struct popup_blocklist));
+ if (!entry)
+ {
+ fclose( fp );
+ goto load_popupfile_error;
+ }
+
+ /* Handle allowed hosts. */
+ if ( *buf == '~' )
+ {
+ /* Rememeber: skip the tilde */
+ entry->host_name = strdup( buf + 1 );
+ if (!entry->host_name)
+ {
+ fclose( fp );
+ goto load_popupfile_error;
+ }
+
+ entry->next = data->allowed;
+ data->allowed = entry;
+ }
+ else
+ {
+ /* Blocked host */
+ entry->host_name = strdup( buf );
+ if (!entry->host_name)
+ {
+ fclose( fp );
+ goto load_popupfile_error;
+ }
+
+ entry->next = data->blocked;
+ data->blocked = entry;
+ }
+ }
+
+ fclose( fp );
+
+#ifndef SPLIT_PROXY_ARGS
+ if (!suppress_blocklists)
+ {
+ fs->proxy_args = strsav(fs->proxy_args, "</pre>");
+ }
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ /* the old one is now obsolete */
+ if ( NULL != current_popupfile )
+ {
+ current_popupfile->unloader = unload_popupfile;
+ }
+
+ fs->next = files->next;
+ files->next = fs;
+ current_popupfile = fs;
+
+ if (csp)
+ {
+ csp->plist = fs;
+ }
+
+ return( 0 );
+
+load_popupfile_error:
+ log_error(LOG_LEVEL_ERROR, "can't load popupfile '%s': %E", popupfile);
+ return(-1);
+
+}
+#endif /* def KILLPOPUPS */
+
+
+
+/*********************************************************************
+ *
+ * Function : add_loader
+ *
+ * Description : Called from `load_config'. Called once for each input
+ * file found in config.
+ *
+ * Parameters :
+ * 1 : loader = pointer to a function that can parse and load
+ * the appropriate config file.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void add_loader(int (*loader)(struct client_state *))
+{
+ int i;
+
+ for (i=0; i < NLOADERS; i++)
+ {
+ if (loaders[i] == NULL)
+ {
+ loaders[i] = loader;
+ break;
+ }
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : run_loader
+ *
+ * Description : Called from `load_config' and `listen_loop'. This
+ * function keeps the "csp" current with any file mods
+ * since the last loop. If a file is unchanged, the
+ * loader functions do NOT reload the file.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 => Ok, everything else is an error.
+ *
+ *********************************************************************/
+int run_loader(struct client_state *csp)
+{
+ int ret = 0;
+ int i;
+
+ for (i=0; i < NLOADERS; i++)
+ {
+ if (loaders[i] == NULL)
+ {
+ break;
+ }
+ ret |= (loaders[i])(csp);
+ }
+ return(ret);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : remove_all_loaders
+ *
+ * Description : Remove all loaders from the list.
+ *
+ * Parameters : N/A
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void remove_all_loaders(void)
+{
+ memset( loaders, 0, sizeof( loaders ) );
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _LOADERS_H
+#define _LOADERS_H
+#define LOADERS_H_VERSION "$Id: loaders.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/loaders.h,v $
+ *
+ * Purpose : Functions to load and unload the various
+ * configuration files. Also contains code to manage
+ * the list of active loaders, and to automatically
+ * unload files that are no longer in use.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: loaders.h,v $
+ *
+ *********************************************************************/
+\f
+
+#include "project.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void sweep(void);
+extern char *read_config_line(char *buf, int buflen, FILE *fp, struct file_list *fs);
+
+extern int load_blockfile(struct client_state *csp);
+extern int load_cookiefile(struct client_state *csp);
+extern int load_forwardfile(struct client_state *csp);
+
+#ifdef ACL_FILES
+extern int load_aclfile(struct client_state *csp);
+#endif /* def ACL_FILES */
+
+#ifdef USE_IMAGE_LIST
+extern int load_imagefile(struct client_state *csp);
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef KILLPOPUPS
+extern int load_popupfile(struct client_state *csp);
+#endif /* def KILLPOPUPS */
+
+#ifdef TRUST_FILES
+extern int load_trustfile(struct client_state *csp);
+#endif /* def TRUST_FILES */
+
+#ifdef PCRS
+extern int load_re_filterfile(struct client_state *csp);
+#endif /* def PCRS */
+
+extern void add_loader(int (*loader)(struct client_state *));
+extern int run_loader(struct client_state *csp);
+extern void remove_all_loaders(void);
+
+#ifdef PCRS
+extern int load_re_filterfile(struct client_state *csp);
+#endif /* def PCRS */
+
+#ifdef KILLPOPUPS
+extern int load_popupfile(struct client_state *csp);
+#endif /* def KILLPOPUPS */
+
+/* Revision control strings from this header and associated .c file */
+extern const char loaders_rcs[];
+extern const char loaders_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _LOADERS_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+const char miscutil_rcs[] = "$Id: miscutil.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/miscutil.c,v $
+ *
+ * Purpose : zalloc, hash_string, safe_strerror, strcmpic,
+ * strncmpic, and MinGW32 strdup functions. These are
+ * each too small to deserve their own file but don't
+ * really fit in any other file.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: miscutil.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <ctype.h>
+
+#include "miscutil.h"
+
+const char miscutil_h_rcs[] = MISCUTIL_H_VERSION;
+
+/* Fix a problem with Solaris. There should be no effect on other
+ * platforms.
+ * Solaris's isspace() is a macro which uses it's argument directly
+ * as an array index. Therefore we need to make sure that high-bit
+ * characters generate +ve values, and ideally we also want to make
+ * the argument match the declared parameter type of "int".
+ */
+#define ijb_tolower(__X) tolower((int)(unsigned char)(__X))
+
+/*********************************************************************
+ *
+ * Function : zalloc
+ *
+ * Description : Malloc some memory and set it to '\0'.
+ * The way calloc() ought to be -acjc
+ *
+ * Parameters :
+ * 1 : size = Size of memory chunk to return.
+ *
+ * Returns : Pointer to newly malloc'd memory chunk.
+ *
+ *********************************************************************/
+void *zalloc(int size)
+{
+ void * ret;
+
+ if ((ret = (void *)malloc(size)) != NULL)
+ {
+ memset(ret, 0, size);
+ }
+
+ return(ret);
+}
+
+
+/*********************************************************************
+ *
+ * Function : hash_string
+ *
+ * Description : Take a string and compute a (hopefuly) unique numeric
+ * integer value. This has several uses, but being able
+ * to "switch" a string the one of my favorites.
+ *
+ * Parameters :
+ * 1 : s : string to be hashed.
+ *
+ * Returns : an unsigned long variable with the hashed value.
+ *
+ *********************************************************************/
+unsigned long hash_string( const char* s )
+{
+ unsigned long h = 0ul;
+
+ for ( ; *s; ++s )
+ {
+ h = 5 * h + *s;
+ }
+
+ return (h);
+
+}
+
+
+#ifdef __MINGW32__
+/*********************************************************************
+ *
+ * Function : strdup
+ *
+ * Description : For some reason (which is beyond me), gcc and WIN32
+ * don't like strdup. When a "free" is executed on a
+ * strdup'd ptr, it can at times freez up! So I just
+ * replaced it and problem was solved.
+ *
+ * Parameters :
+ * 1 : s = string to duplicate
+ *
+ * Returns : Pointer to newly malloc'ed copy of the string.
+ *
+ *********************************************************************/
+char *strdup( const char *s )
+{
+ char * result = (char *)malloc( strlen(s)+1 );
+
+ if (result != NULL)
+ {
+ strcpy( result, s );
+ }
+
+ return( result );
+}
+
+#endif /* def __MINGW32__ */
+
+
+
+/*********************************************************************
+ *
+ * Function : safe_strerror
+ *
+ * Description : Variant of the library routine strerror() which will
+ * work on systems without the library routine, and
+ * which should never return NULL.
+ *
+ * Parameters :
+ * 1 : err = the `errno' of the last operation.
+ *
+ * Returns : An "English" string of the last `errno'. Allocated
+ * with strdup(), so caller frees. May be NULL if the
+ * system is out of memory.
+ *
+ *********************************************************************/
+char *safe_strerror(int err)
+{
+ char *s = NULL;
+ char buf[BUFSIZ];
+
+
+#ifndef NOSTRERROR
+ s = strerror(err);
+#endif /* NOSTRERROR */
+
+ if (s == NULL)
+ {
+ sprintf(buf, "(errno = %d)", err);
+ s = buf;
+ }
+
+ return(strdup(s));
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : strcmpic
+ *
+ * Description : Case insensitive string comparison
+ *
+ * Parameters :
+ * 1 : s1 = string 1 to compare
+ * 2 : s2 = string 2 to compare
+ *
+ * Returns : 0 if s1==s2, Negative if s1<s2, Positive if s1>s2
+ *
+ *********************************************************************/
+int strcmpic(char *s1, char *s2)
+{
+ while (*s1 && *s2)
+ {
+ if ( ( *s1 != *s2 ) && ( ijb_tolower(*s1) != ijb_tolower(*s2) ) )
+ {
+ break;
+ }
+ s1++, s2++;
+ }
+ return(ijb_tolower(*s1) - ijb_tolower(*s2));
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : strncmpic
+ *
+ * Description : Case insensitive string comparison (upto n characters)
+ *
+ * Parameters :
+ * 1 : s1 = string 1 to compare
+ * 2 : s2 = string 2 to compare
+ * 3 : n = maximum characters to compare
+ *
+ * Returns : 0 if s1==s2, Negative if s1<s2, Positive if s1>s2
+ *
+ *********************************************************************/
+int strncmpic(char *s1, char *s2, size_t n)
+{
+ if (n <= 0) return(0);
+
+ while (*s1 && *s2)
+ {
+ if ( ( *s1 != *s2 ) && ( ijb_tolower(*s1) != ijb_tolower(*s2) ) )
+ {
+ break;
+ }
+
+ if (--n <= 0) break;
+
+ s1++, s2++;
+ }
+ return(ijb_tolower(*s1) - ijb_tolower(*s2));
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _MISCUTIL_H
+#define _MISCUTIL_H
+#define MISCUTIL_H_VERSION "$Id: miscutil.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/miscutil.h,v $
+ *
+ * Purpose : zalloc, hash_string, safe_strerror, strcmpic,
+ * strncmpic, and MinGW32 strdup functions. These are
+ * each too small to deserve their own file but don't
+ * really fit in any other file.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: miscutil.h,v $
+ *
+ *********************************************************************/
+\f
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+extern void *zalloc(int size);
+
+extern unsigned long hash_string(const char* s);
+
+extern char *safe_strerror(int err);
+
+extern int strcmpic(char *s1, char *s2);
+extern int strncmpic(char *s1, char *s2, size_t n);
+
+#ifdef __MINGW32__
+extern char *strdup(const char *s);
+#endif /* def __MINGW32__ */
+
+/* Revision control strings from this header and associated .c file */
+extern const char miscutil_rcs[];
+extern const char miscutil_h_rcs[];
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* ndef _MISCUTIL_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+const char parsers_rcs[] = "$Id: parsers.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/parsers.c,v $
+ *
+ * Purpose : Declares functions to parse/crunch headers and pages.
+ * Functions declared include:
+ * `add_to_iob', `client_cookie_adder', `client_from',
+ * `client_referrer', `client_send_cookie', `client_ua',
+ * `client_uagent', `client_x_forwarded',
+ * `client_x_forwarded_adder', `client_xtra_adder',
+ * `content_type', `crumble', `destroy_list', `enlist',
+ * `flush_socket', `free_http_request', `get_header',
+ * `list_to_text', `match', `parse_http_request', `sed',
+ * and `server_set_cookie'.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: parsers.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include "project.h"
+#include "parsers.h"
+#include "encode.h"
+#include "filters.h"
+#include "loaders.h"
+#include "showargs.h"
+#include "jcc.h"
+#include "ssplit.h"
+#include "errlog.h"
+#include "jbsockets.h"
+#include "miscutil.h"
+
+const char parsers_h_rcs[] = PARSERS_H_VERSION;
+
+/* Fix a problem with Solaris. There should be no effect on other
+ * platforms.
+ * Solaris's isspace() is a macro which uses it's argument directly
+ * as an array index. Therefore we need to make sure that high-bit
+ * characters generate +ve values, and ideally we also want to make
+ * the argument match the declared parameter type of "int".
+ *
+ * Why did they write a character function that can't take a simple
+ * "char" argument? Doh!
+ */
+#define ijb_isupper(__X) isupper((int)(unsigned char)(__X))
+#define ijb_tolower(__X) tolower((int)(unsigned char)(__X))
+
+
+const struct parsers client_patterns[] = {
+ { "referer:", 8, client_referrer },
+ { "user-agent:", 11, client_uagent },
+ { "ua-", 3, client_ua },
+ { "from:", 5, client_from },
+ { "cookie:", 7, client_send_cookie },
+ { "x-forwarded-for:", 16, client_x_forwarded },
+ { "proxy-connection:", 17, crumble },
+#ifdef DENY_GZIP
+ { "Accept-Encoding: gzip", 21, crumble },
+#endif /* def DENY_GZIP */
+#if defined(DETECT_MSIE_IMAGES)
+ { "Accept:", 7, client_accept },
+#endif /* defined(DETECT_MSIE_IMAGES) */
+#ifdef FORCE_LOAD
+ { "Host:", 5, client_host },
+#endif /* def FORCE_LOAD */
+/* { "if-modified-since:", 18, crumble }, */
+ { NULL, 0, NULL }
+};
+
+const struct interceptors intercept_patterns[] = {
+ { "show-proxy-args", 14, show_proxy_args },
+#ifdef TRUST_FILES
+ { "ij-untrusted-url", 14, ij_untrusted_url },
+#endif /* def TRUST_FILES */
+ { NULL, 0, NULL }
+};
+
+const struct parsers server_patterns[] = {
+ { "set-cookie:", 11, server_set_cookie },
+ { "connection:", 11, crumble },
+#ifdef PCRS
+ { "Content-Type:", 13, content_type },
+ { "Content-Length:", 15, crumble },
+#endif /* def PCRS */
+ { NULL, 0, NULL }
+};
+
+
+void (* const add_client_headers[])(struct client_state *) = {
+ client_cookie_adder,
+ client_x_forwarded_adder,
+ client_xtra_adder,
+ NULL
+};
+
+
+void (* const add_server_headers[])(struct client_state *) = {
+ NULL
+};
+
+
+/*********************************************************************
+ *
+ * Function : match
+ *
+ * Description : Do a `strncmpic' on every pattern in pats.
+ *
+ * Parameters :
+ * 1 : buf = a string to match to a list of patterns
+ * 2 : pats = list of strings to compare against buf.
+ *
+ * Returns : Return the matching "struct parsers *",
+ * or NULL if no pattern matches.
+ *
+ *********************************************************************/
+static const struct parsers *match(char *buf, const struct parsers *pats)
+{
+ const struct parsers *v;
+
+ if (buf == NULL)
+ {
+ /* hit me */
+ log_error(LOG_LEVEL_ERROR, "NULL parameter to match()");
+ return(NULL);
+ }
+
+ for (v = pats; v->str ; v++)
+ {
+ if (strncmpic(buf, v->str, v->len) == 0)
+ {
+ return(v);
+ }
+ }
+ return(NULL);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : flush_socket
+ *
+ * Description : Write any pending "buffered" content.
+ *
+ * Parameters :
+ * 1 : fd = file descriptor of the socket to read
+ * 2 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : On success, the number of bytes written are returned (zero
+ * indicates nothing was written). On error, -1 is returned,
+ * and errno is set appropriately. If count is zero and the
+ * file descriptor refers to a regular file, 0 will be
+ * returned without causing any other effect. For a special
+ * file, the results are not portable.
+ *
+ *********************************************************************/
+int flush_socket(int fd, struct client_state *csp)
+{
+ struct iob *iob = csp->iob;
+ int n = iob->eod - iob->cur;
+
+ if (n <= 0)
+ {
+ return(0);
+ }
+
+ n = write_socket(fd, iob->cur, n);
+ iob->eod = iob->cur = iob->buf;
+ return(n);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : add_to_iob
+ *
+ * Description : Add content to the buffered page.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : buf = holds the content to be added to the page
+ * 3 : n = number of bytes to be added
+ *
+ * Returns : Number of bytes in the content buffer.
+ *
+ *********************************************************************/
+int add_to_iob(struct client_state *csp, char *buf, int n)
+{
+ struct iob *iob = csp->iob;
+ int have, need;
+ char *p;
+
+ have = iob->eod - iob->cur;
+
+ if (n <= 0)
+ {
+ return(have);
+ }
+
+ need = have + n;
+
+ if ((p = (char *)malloc(need + 1)) == NULL)
+ {
+ log_error(LOG_LEVEL_ERROR, "malloc() iob failed: %E");
+ return(-1);
+ }
+
+ if (have)
+ {
+ /* there is something in the buffer - save it */
+ memcpy(p, iob->cur, have);
+
+ /* replace the buffer with the new space */
+ freez(iob->buf);
+ iob->buf = p;
+
+ /* point to the end of the data */
+ p += have;
+ }
+ else
+ {
+ /* the buffer is empty, free it and reinitialize */
+ freez(iob->buf);
+ iob->buf = p;
+ }
+
+ /* copy the new data into the iob buffer */
+ memcpy(p, buf, n);
+
+ /* point to the end of the data */
+ p += n;
+
+ /* null terminate == cheap insurance */
+ *p = '\0';
+
+ /* set the pointers to the new values */
+ iob->cur = iob->buf;
+ iob->eod = p;
+
+ return(need);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : get_header
+ *
+ * Description : This (odd) routine will parse the csp->iob
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : Any one of the following:
+ *
+ * 1) a pointer to a dynamically allocated string that contains a header line
+ * 2) NULL indicating that the end of the header was reached
+ * 3) "" indicating that the end of the iob was reached before finding
+ * a complete header line.
+ *
+ *********************************************************************/
+char *get_header(struct client_state *csp)
+{
+ struct iob *iob;
+ char *p, *q, *ret;
+ iob = csp->iob;
+
+ if ((iob->cur == NULL)
+ || ((p = strchr(iob->cur, '\n')) == NULL))
+ {
+ return(""); /* couldn't find a complete header */
+ }
+
+ *p = '\0';
+
+ ret = strdup(iob->cur);
+
+ iob->cur = p+1;
+
+ if ((q = strchr(ret, '\r'))) *q = '\0';
+
+ /* is this a blank linke (i.e. the end of the header) ? */
+ if (*ret == '\0')
+ {
+ freez(ret);
+ return(NULL);
+ }
+
+ return(ret);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : enlist
+ *
+ * Description : Append a string into a specified string list.
+ *
+ * Parameters :
+ * 1 : h = pointer to list 'dummy' header
+ * 2 : s = string to add to the list
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void enlist(struct list *h, const char *s)
+{
+ struct list *n = (struct list *)malloc(sizeof(*n));
+ struct list *l;
+
+ if (n)
+ {
+ n->str = strdup(s);
+ n->next = NULL;
+
+ if ((l = h->last))
+ {
+ l->next = n;
+ }
+ else
+ {
+ h->next = n;
+ }
+
+ h->last = n;
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : destroy_list
+ *
+ * Description : Destroy a string list (opposite of enlist)
+ *
+ * Parameters :
+ * 1 : h = pointer to list 'dummy' header
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void destroy_list(struct list *h)
+{
+ struct list *p, *n;
+
+ for (p = h->next; p ; p = n)
+ {
+ n = p->next;
+ freez(p->str);
+ freez(p);
+ }
+
+ memset(h, '\0', sizeof(*h));
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : list_to_text
+ *
+ * Description : "Flaten" a string list into 1 long \r\n delimited string.
+ *
+ * Parameters :
+ * 1 : h = pointer to list 'dummy' header
+ *
+ * Returns : NULL on malloc error, else new long string.
+ *
+ *********************************************************************/
+static char *list_to_text(struct list *h)
+{
+ struct list *p;
+ char *ret = NULL;
+ char *s;
+ int size;
+
+ size = 0;
+
+ for (p = h->next; p ; p = p->next)
+ {
+ if (p->str)
+ {
+ size += strlen(p->str) + 2;
+ }
+ }
+
+ if ((ret = (char *)malloc(size + 1)) == NULL)
+ {
+ return(NULL);
+ }
+
+ ret[size] = '\0';
+
+ s = ret;
+
+ for (p = h->next; p ; p = p->next)
+ {
+ if (p->str)
+ {
+ strcpy(s, p->str);
+ s += strlen(s);
+ *s++ = '\r'; *s++ = '\n';
+ }
+ }
+
+ return(ret);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : sed
+ *
+ * Description : add, delete or modify lines in the HTTP header streams.
+ * On entry, it receives a linked list of headers space
+ * that was allocated dynamically (both the list nodes
+ * and the header contents).
+ *
+ * As a side effect it frees the space used by the original
+ * header lines.
+ *
+ * Parameters :
+ * 1 : pats = list of patterns to match against headers
+ * 2 : more_headers = list of functions to add more
+ * headers (client or server)
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : Single pointer to a fully formed header.
+ *
+ *********************************************************************/
+char *sed(const struct parsers pats[], void (* const more_headers[])(struct client_state *), struct client_state *csp)
+{
+ struct list *p;
+ const struct parsers *v;
+ char *hdr;
+ void (* const *f)();
+
+ for (p = csp->headers->next; p ; p = p->next)
+ {
+ log_error(LOG_LEVEL_HEADER, "scan: %s", p->str);
+
+ if ((v = match(p->str, pats)))
+ {
+ hdr = v->parser(v, p->str, csp);
+ freez(p->str);
+ p->str = hdr;
+ }
+
+ }
+
+ /* place any additional headers on the csp->headers list */
+ for (f = more_headers; *f ; f++)
+ {
+ (*f)(csp);
+ }
+
+ /* add the blank line at the end of the header */
+ enlist(csp->headers, "");
+
+ hdr = list_to_text(csp->headers);
+
+ return(hdr);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : free_http_request
+ *
+ * Description : Freez a http_request structure
+ *
+ * Parameters :
+ * 1 : http = points to a http_request structure to free
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void free_http_request(struct http_request *http)
+{
+ freez(http->cmd);
+ freez(http->gpc);
+ freez(http->host);
+ freez(http->hostport);
+ freez(http->path);
+ freez(http->ver);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : parse_http_request
+ *
+ * Description : Parse out the host and port from the URL. Find the
+ * hostname & path, port (if ':'), and/or password (if '@')
+ *
+ * Parameters :
+ * 1 : req = URL (or is it URI?) to break down
+ * 2 : http = pointer to the http structure to hold elements
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void parse_http_request(char *req, struct http_request *http, struct client_state *csp)
+{
+ char *buf, *v[10], *url, *p;
+ int n;
+
+ memset(http, '\0', sizeof(*http));
+
+ http->cmd = strdup(req);
+
+ buf = strdup(req);
+
+ n = ssplit(buf, " \r\n", v, SZ(v), 1, 1);
+
+ if (n == 3)
+ {
+ /* this could be a CONNECT request */
+ if (strcmpic(v[0], "connect") == 0)
+ {
+ http->ssl = 1;
+ http->gpc = strdup(v[0]);
+ http->hostport = strdup(v[1]);
+ http->ver = strdup(v[2]);
+ }
+
+#ifdef WEBDAV
+
+/* This next line is a little ugly, but it simplifies the if statement below. */
+/* Basically if using webDAV, we want the OR condition to use these too. */
+
+/*
+ * by haroon
+ * These are the headers as defined in RFC2518 to add webDAV support
+ */
+
+#define OR_WEBDAV || \
+ (0 == strcmpic(v[0], "propfind")) || \
+ (0 == strcmpic(v[0], "proppatch")) || \
+ (0 == strcmpic(v[0], "move")) || \
+ (0 == strcmpic(v[0], "copy")) || \
+ (0 == strcmpic(v[0], "mkcol")) || \
+ (0 == strcmpic(v[0], "lock")) || \
+ (0 == strcmpic(v[0], "unlock"))
+
+#else /* No webDAV support is enabled. Provide an empty OR_WEBDAV macro. */
+
+#define OR_WEBDAV
+
+#endif
+
+ /* or it could be a GET or a POST (possibly webDAV too) */
+ if ((strcmpic(v[0], "get") == 0) ||
+ (strcmpic(v[0], "head") == 0) OR_WEBDAV ||
+ (strcmpic(v[0], "post") == 0))
+ {
+ http->ssl = 0;
+ http->gpc = strdup(v[0]);
+ url = v[1];
+ http->ver = strdup(v[2]);
+
+ if (strncmpic(url, "http://", 7) == 0)
+ {
+ url += 7;
+ }
+ else if (strncmpic(url, "https://", 8) == 0)
+ {
+ url += 8;
+ }
+ else
+ {
+ url = NULL;
+ }
+
+ if (url && (p = strchr(url, '/')))
+ {
+ http->path = strdup(p);
+ *p = '\0';
+ http->hostport = strdup(url);
+ }
+ }
+ }
+
+ freez(buf);
+
+
+ if (http->hostport == NULL)
+ {
+ free_http_request(http);
+ return;
+ }
+
+ buf = strdup(http->hostport);
+
+
+ /* check if url contains password */
+ n = ssplit(buf, "@", v, SZ(v), 1, 1);
+ if (n == 2)
+ {
+ char * newbuf = NULL;
+ newbuf = strdup(v[1]);
+ freez(buf);
+ buf = newbuf;
+ }
+
+ n = ssplit(buf, ":", v, SZ(v), 1, 1);
+
+ if (n == 1)
+ {
+ http->host = strdup(v[0]);
+ http->port = 80;
+ }
+
+ if (n == 2)
+ {
+ http->host = strdup(v[0]);
+ http->port = atoi(v[1]);
+ }
+
+ freez(buf);
+
+ if (http->host == NULL)
+ {
+ free_http_request(http);
+ }
+
+ if (http->path == NULL)
+ {
+ http->path = strdup("");
+ }
+
+}
+
+
+/* here begins the family of parser functions that reformat header lines */
+
+
+/*********************************************************************
+ *
+ * Function : crumble
+ *
+ * Description : This is called if a header matches a pattern to "crunch"
+ *
+ * Parameters :
+ * 1 : v = Pointer to parsers structure, which basically holds
+ * headers (client or server) that we want to "crunch"
+ * 2 : s = header (from sed) to "crunch"
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : Always NULL.
+ *
+ *********************************************************************/
+char *crumble(const struct parsers *v, char *s, struct client_state *csp)
+{
+ log_error(LOG_LEVEL_HEADER, "crunch!");
+ return(NULL);
+
+}
+
+
+#ifdef PCRS
+
+/*********************************************************************
+ *
+ * Function : content_type
+ *
+ * Description : Is this a text/* or javascript MIME Type?
+ *
+ * Parameters :
+ * 1 : v = ignored
+ * 2 : s = header string we are "considering"
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : A duplicate string pointer to this header (ie. pass thru)
+ *
+ *********************************************************************/
+char *content_type(const struct parsers *v, char *s, struct client_state *csp)
+{
+ if (strstr (s, " text/") || strstr (s, "application/x-javascript"))
+ csp->is_text = 1;
+ else
+ csp->is_text = 0;
+
+ return(strdup(s));
+
+}
+
+#endif /* def PCRS */
+
+
+/*********************************************************************
+ *
+ * Function : client_referrer
+ *
+ * Description : Handle the "referer" config setting properly.
+ * Called from `sed'.
+ *
+ * Parameters :
+ * 1 : v = ignored
+ * 2 : s = header (from sed) to "crunch"
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : NULL if crunched, or a malloc'ed string with the original
+ * or modified header
+ *
+ *********************************************************************/
+char *client_referrer(const struct parsers *v, char *s, struct client_state *csp)
+{
+#ifdef FORCE_LOAD
+ /* Since the referrer can include the prefix even
+ * even if the request itself is non-forced, we must
+ * clean it unconditionally
+ */
+ strclean(s, FORCE_PREFIX);
+#endif /* def FORCE_LOAD */
+
+ csp->referrer = strdup(s);
+
+ if (referrer == NULL)
+ {
+ log_error(LOG_LEVEL_HEADER, "crunch!");
+ return(NULL);
+ }
+
+ if (*referrer == '.')
+ {
+ return(strdup(s));
+ }
+
+ if (*referrer == '@')
+ {
+ if (csp->send_user_cookie)
+ {
+ return(strdup(s));
+ }
+ else
+ {
+ log_error(LOG_LEVEL_HEADER, "crunch!");
+ return(NULL);
+ }
+ }
+
+ /*
+ * New option §: Forge a referer as http://[hostname:port of REQUEST]/
+ * to fool stupid checks for in-site links
+ */
+
+ if (*referrer == '§')
+ {
+ if (csp->send_user_cookie)
+ {
+ return(strdup(s));
+ }
+ else
+ {
+ log_error(LOG_LEVEL_HEADER, "crunch+forge!");
+ s = strsav(NULL, "Referer: ");
+ s = strsav(s, "http://");
+ s = strsav(s, csp->http->hostport);
+ s = strsav(s, "/");
+ return(s);
+ }
+ }
+
+ log_error(LOG_LEVEL_HEADER, "modified");
+
+ s = strsav( NULL, "Referer: " );
+ s = strsav( s, referrer );
+ return(s);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : client_uagent
+ *
+ * Description : Handle the "user-agent" config setting properly.
+ * Called from `sed'.
+ *
+ * Parameters :
+ * 1 : v = ignored
+ * 2 : s = header (from sed) to "crunch"
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : A malloc'ed pointer to the default agent, or
+ * a malloc'ed string pointer to this header (ie. pass thru).
+ *
+ *********************************************************************/
+char *client_uagent(const struct parsers *v, char *s, struct client_state *csp)
+{
+#ifdef DETECT_MSIE_IMAGES
+ if (strstr (s, "MSIE "))
+ {
+ /* This is Microsoft Internet Explorer.
+ * Enable auto-detect.
+ */
+ csp->accept_types |= ACCEPT_TYPE_IS_MSIE;
+ }
+#endif /* def DETECT_MSIE_IMAGES */
+
+ if (uagent == NULL)
+ {
+ log_error(LOG_LEVEL_HEADER, "default");
+ return(strdup(DEFAULT_USER_AGENT));
+ }
+
+ if (*uagent == '.')
+ {
+ return(strdup(s));
+ }
+
+ if (*uagent == '@')
+ {
+ if (csp->send_user_cookie)
+ {
+ return(strdup(s));
+ }
+ else
+ {
+ log_error(LOG_LEVEL_HEADER, "default");
+ return(strdup(DEFAULT_USER_AGENT));
+ }
+ }
+
+ log_error(LOG_LEVEL_HEADER, "modified");
+
+ s = strsav( NULL, "User-Agent: " );
+ s = strsav( s, uagent );
+ return(s);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : client_ua
+ *
+ * Description : Handle "ua-" headers properly. Called from `sed'.
+ *
+ * Parameters :
+ * 1 : v = ignored
+ * 2 : s = header (from sed) to "crunch"
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : NULL if crunched, or a malloc'ed string to original header
+ *
+ *********************************************************************/
+char *client_ua(const struct parsers *v, char *s, struct client_state *csp)
+{
+ if (uagent == NULL)
+ {
+ log_error(LOG_LEVEL_HEADER, "crunch!");
+ return(NULL);
+ }
+
+ if (*uagent == '.')
+ {
+ return(strdup(s));
+ }
+
+ if (*uagent == '@')
+ {
+ if (csp->send_user_cookie)
+ {
+ return(strdup(s));
+ }
+ else
+ {
+ log_error(LOG_LEVEL_HEADER, "crunch!");
+ return(NULL);
+ }
+ }
+
+ log_error(LOG_LEVEL_HEADER, "crunch!");
+ return(NULL);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : client_from
+ *
+ * Description : Handle the "from" config setting properly.
+ * Called from `sed'.
+ *
+ * Parameters :
+ * 1 : v = ignored
+ * 2 : s = header (from sed) to "crunch"
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : NULL if crunched, or a malloc'ed string to
+ * modified/original header.
+ *
+ *********************************************************************/
+char *client_from(const struct parsers *v, char *s, struct client_state *csp)
+{
+ /* if not set, zap it */
+ if (from == NULL)
+ {
+ log_error(LOG_LEVEL_HEADER, "crunch!");
+ return(NULL);
+ }
+
+ if (*from == '.')
+ {
+ return(strdup(s));
+ }
+
+ log_error(LOG_LEVEL_HEADER, " modified");
+
+ s = strsav( NULL, "From: " );
+ s = strsav( s, from );
+ return(s);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : client_send_cookie
+ *
+ * Description : Handle the "cookie" header properly. Called from `sed'.
+ * If cookie is accepted, add it to the cookie_list,
+ * else we crunch it. Mmmmmmmmmmm ... cookie ......
+ *
+ * Parameters :
+ * 1 : v = pattern of cookie `sed' found matching
+ * 2 : s = header (from sed) to "crunch"
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : Always NULL.
+ *
+ *********************************************************************/
+char *client_send_cookie(const struct parsers *v, char *s, struct client_state *csp)
+{
+ if (csp->send_user_cookie)
+ {
+ enlist(csp->cookie_list, s + v->len + 1);
+ }
+ else
+ {
+ log_error(LOG_LEVEL_HEADER, " crunch!");
+ }
+
+ /*
+ * Always return NULL here. The cookie header
+ * will be sent at the end of the header.
+ */
+ return(NULL);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : client_x_forwarded
+ *
+ * Description : Handle the "x-forwarded-for" config setting properly,
+ * also used in the add_client_headers list. Called from `sed'.
+ *
+ * Parameters :
+ * 1 : v = ignored
+ * 2 : s = header (from sed) to "crunch"
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : Always NULL.
+ *
+ *********************************************************************/
+char *client_x_forwarded(const struct parsers *v, char *s, struct client_state *csp)
+{
+ if (add_forwarded)
+ {
+ csp->x_forwarded = strdup(s);
+ }
+
+ /*
+ * Always return NULL, since this information
+ * will be sent at the end of the header.
+ */
+
+ return(NULL);
+
+}
+
+#if defined(DETECT_MSIE_IMAGES)
+/*********************************************************************
+ *
+ * Function : client_accept
+ *
+ * Description : Detect whether the client wants HTML or an image.
+ * Clients do not always make this information available
+ * in a sane way. Always passes the header through
+ * the proxy unchanged.
+ *
+ * Parameters :
+ * 1 : v = Ignored.
+ * 2 : s = Header string. Null terminated.
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : Duplicate of argument s.
+ *
+ *********************************************************************/
+char *client_accept(const struct parsers *v, char *s, struct client_state *csp)
+{
+#ifdef DETECT_MSIE_IMAGES
+ if (strstr (s, "image/gif"))
+ {
+ /* Client will accept HTML. If this seems counterintuitive,
+ * blame Microsoft.
+ */
+ csp->accept_types |= ACCEPT_TYPE_MSIE_HTML;
+ }
+ else
+ {
+ csp->accept_types |= ACCEPT_TYPE_MSIE_IMAGE;
+ }
+#endif /* def DETECT_MSIE_IMAGES */
+
+ return(strdup(s));
+
+}
+#endif /* defined(DETECT_MSIE_IMAGES) */
+
+
+
+/* the following functions add headers directly to the header list */
+
+
+/*********************************************************************
+ *
+ * Function : client_cookie_adder
+ *
+ * Description : Used in the add_client_headers list. Called from `sed'.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void client_cookie_adder(struct client_state *csp)
+{
+ struct list *l;
+ char *tmp = NULL;
+ char *e;
+
+ for (l = csp->cookie_list->next; l ; l = l->next)
+ {
+ if (tmp)
+ {
+ tmp = strsav(tmp, "; ");
+ }
+ tmp = strsav(tmp, l->str);
+ }
+
+ for (l = wafer_list->next; l ; l = l->next)
+ {
+ if (tmp)
+ {
+ tmp = strsav(tmp, "; ");
+ }
+
+ if ((e = cookie_encode(l->str)))
+ {
+ tmp = strsav(tmp, e);
+ freez(e);
+ }
+ }
+
+ if (tmp)
+ {
+ char *ret;
+
+ ret = strdup("Cookie: ");
+ ret = strsav(ret, tmp);
+ log_error(LOG_LEVEL_HEADER, "addh: %s", ret);
+ enlist(csp->headers, ret);
+ freez(tmp);
+ freez(ret);
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : client_xtra_adder
+ *
+ * Description : Used in the add_client_headers list. Called from `sed'.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void client_xtra_adder(struct client_state *csp)
+{
+ struct list *l;
+
+ for (l = xtra_list->next; l ; l = l->next)
+ {
+ log_error(LOG_LEVEL_HEADER, "addh: %s", l->str);
+ enlist(csp->headers, l->str);
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : client_x_forwarded_adder
+ *
+ * Description : Used in the add_client_headers list. Called from `sed'.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void client_x_forwarded_adder(struct client_state *csp)
+{
+ char *p = NULL;
+
+ if (add_forwarded == 0) return;
+
+ if (csp->x_forwarded)
+ {
+ p = strsav(p, csp->x_forwarded);
+ p = strsav(p, ", ");
+ p = strsav(p, csp->ip_addr_str);
+ }
+ else
+ {
+ p = strsav(p, "X-Forwarded-For: ");
+ p = strsav(p, csp->ip_addr_str);
+ }
+
+ log_error(LOG_LEVEL_HEADER, "addh: %s", p);
+ enlist(csp->headers, p);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : server_set_cookie
+ *
+ * Description : Handle the server "cookie" header properly.
+ * Log cookie to the jar file. Then "crunch" it,
+ * or accept it. Called from `sed'.
+ *
+ * Parameters :
+ * 1 : v = parser pattern that matched this header
+ * 2 : s = header that matched this pattern
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : `crumble' or a newly malloc'ed string.
+ *
+ *********************************************************************/
+char *server_set_cookie(const struct parsers *v, char *s, struct client_state *csp)
+{
+#ifdef JAR_FILES
+ if (jar)
+ {
+ fprintf(jar, "%s\t%s\n", csp->http->host, (s + v->len + 1));
+ }
+#endif /* def JAR_FILES */
+
+ if (csp->accept_server_cookie == 0)
+ {
+ return(crumble(v, s, csp));
+ }
+
+ return(strdup(s));
+
+}
+
+
+#ifdef FORCE_LOAD
+/*********************************************************************
+ *
+ * Function : client_host
+ *
+ * Description : Clean the FORCE_PREFIX out of the 'host' http
+ * header, if we use force
+ *
+ * Parameters :
+ * 1 : v = ignored
+ * 2 : s = header (from sed) to clean
+ * 3 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : A malloc'ed pointer to the cleaned host header
+ *
+ *********************************************************************/
+char *client_host(const struct parsers *v, char *s, struct client_state *csp)
+{
+ char *cleanhost = strdup(s);
+
+ if(csp->force)
+ strclean(cleanhost, FORCE_PREFIX);
+
+ return(cleanhost);
+}
+#endif /* def FORCE_LOAD */
+
+
+#ifdef FORCE_LOAD
+/*********************************************************************
+ *
+ * Function : strclean
+ *
+ * Description : In-Situ-Eliminate all occurances of substring in
+ * string
+ *
+ * Parameters :
+ * 1 : string = string to clean
+ * 2 : substring = substring to eliminate
+ *
+ * Returns : Number of eliminations
+ *
+ *********************************************************************/
+int strclean(const char *string, const char *substring)
+{
+ int hits = 0, len = strlen(substring);
+ char *pos, *p;
+
+ while((pos = strstr(string, substring)))
+ {
+ p = pos + len;
+ do
+ {
+ *(p - len) = *p;
+ }
+ while (*p++ != '\0');
+
+ hits++;
+ }
+
+ return(hits);
+}
+#endif /* def FORCE_LOAD */
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _PARSERS_H
+#define _PARSERS_H
+#define PARSERS_H_VERSION "$Id: parsers.h,v 1.1 2001/05/13 21:57:06 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/parsers.h,v $
+ *
+ * Purpose : Declares functions to parse/crunch headers and pages.
+ * Functions declared include:
+ * `add_to_iob', `client_cookie_adder', `client_from',
+ * `client_referrer', `client_send_cookie', `client_ua',
+ * `client_uagent', `client_x_forwarded',
+ * `client_x_forwarded_adder', `client_xtra_adder',
+ * `content_type', `crumble', `destroy_list', `enlist',
+ * `flush_socket', `free_http_request', `get_header',
+ * `list_to_text', `match', `parse_http_request', `sed',
+ * and `server_set_cookie'.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: parsers.h,v $
+ *
+ *********************************************************************/
+\f
+
+#include "project.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const struct parsers client_patterns[];
+extern const struct parsers server_patterns[];
+extern const struct interceptors intercept_patterns[];
+
+extern void (* const add_client_headers[])(struct client_state *);
+extern void (* const add_server_headers[])(struct client_state *);
+
+extern int flush_socket(int fd, struct client_state *csp);
+extern int add_to_iob(struct client_state *csp, char *buf, int n);
+extern char *get_header(struct client_state *csp);
+extern void enlist(struct list *h, const char *s);
+extern void destroy_list(struct list *h);
+
+extern char *sed(const struct parsers pats[], void (* const more_headers[])(struct client_state *), struct client_state *csp);
+
+extern void free_http_request(struct http_request *http);
+extern void parse_http_request(char *req, struct http_request *http, struct client_state *csp);
+
+extern char *crumble(const struct parsers *v, char *s, struct client_state *csp);
+
+extern char *client_referrer(const struct parsers *v, char *s, struct client_state *csp);
+extern char *client_uagent(const struct parsers *v, char *s, struct client_state *csp);
+extern char *client_ua(const struct parsers *v, char *s, struct client_state *csp);
+extern char *client_from(const struct parsers *v, char *s, struct client_state *csp);
+extern char *client_send_cookie(const struct parsers *v, char *s, struct client_state *csp);
+extern char *client_x_forwarded(const struct parsers *v, char *s, struct client_state *csp);
+extern void client_cookie_adder(struct client_state *csp);
+extern void client_xtra_adder(struct client_state *csp);
+extern void client_x_forwarded_adder(struct client_state *csp);
+extern char *server_set_cookie(const struct parsers *v, char *s, struct client_state *csp);
+
+#ifdef PCRS
+extern char *content_type(const struct parsers *v, char *s, struct client_state *csp);
+#endif /* def PCRS */
+
+#ifdef FORCE_LOAD
+char *client_host(const struct parsers *v, char *s, struct client_state *csp);
+int strclean(const char *string, const char *substring);
+#endif /* def FORCE_LOAD */
+
+#if defined(DETECT_MSIE_IMAGES)
+extern char *client_accept(const struct parsers *v, char *s, struct client_state *csp);
+#endif /* defined(DETECT_MSIE_IMAGES) */
+
+/* Revision control strings from this header and associated .c file */
+extern const char parsers_rcs[];
+extern const char parsers_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _PARSERS_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* This file is automatically written by the dftables auxiliary
+program. If you edit it by hand, you might like to edit the Makefile to
+prevent its ever being regenerated.
+
+This file is #included in the compilation of pcre.c to build the default
+character tables which are used when no tables are passed to the compile
+function. */
+
+static unsigned char pcre_default_tables[] = {
+
+/* This table is a lower casing table. */
+
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,
+ 104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,
+ 120,121,122, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,
+ 104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,
+ 120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,
+ 136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,
+ 152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,
+ 168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,
+ 184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,
+ 200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,
+ 216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,
+ 232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,
+ 248,249,250,251,252,253,254,255,
+
+/* This table is a case flipping table. */
+
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 97, 98, 99,100,101,102,103,
+ 104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,
+ 120,121,122, 91, 92, 93, 94, 95,
+ 96, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,
+ 136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,
+ 152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,
+ 168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,
+ 184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,
+ 200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,
+ 216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,
+ 232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,
+ 248,249,250,251,252,253,254,255,
+
+/* This table contains bit maps for various character classes.
+Each map is 32 bytes long and the bits run from the least
+significant end of each byte. The classes that have their own
+maps are: space, xdigit, digit, upper, lower, word, graph
+print, punct, and cntrl. Other classes are built from combinations. */
+
+ 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
+ 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
+ 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,
+ 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+/* This table identifies various classes of character by individual bits:
+ 0x01 white space character
+ 0x02 letter
+ 0x04 decimal digit
+ 0x08 hexadecimal digit
+ 0x10 alphanumeric or '_'
+ 0x80 regular expression metacharacter or binary zero
+*/
+
+ 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */
+ 0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
+ 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */
+ 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */
+ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */
+ 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */
+ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */
+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */
+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */
+ 0x12,0x12,0x12,0x80,0x00,0x00,0x80,0x10, /* X - _ */
+ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */
+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */
+ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */
+ 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */
+
+/* End of chartables.c */
--- /dev/null
+/* config.h. Generated automatically by configure. */
+
+/* On Unix systems config.in is converted by configure into config.h. PCRE is
+written in Standard C, but there are a few non-standard things it can cope
+with, allowing it to run on SunOS4 and other "close to standard" systems.
+
+On a non-Unix system you should just copy this file into config.h and change
+the definitions of HAVE_STRERROR and HAVE_MEMMOVE to 1. Unfortunately, because
+of the way autoconf works, these cannot be made the defaults. If your system
+has bcopy() and not memmove(), change the definition of HAVE_BCOPY instead of
+HAVE_MEMMOVE. If your system has neither bcopy() nor memmove(), leave them both
+as 0; an emulation function will be used. */
+
+/* Define to empty if the keyword does not work. */
+
+/* #undef const */
+
+/* Define to `unsigned' if <stddef.h> doesn't define size_t. */
+
+/* #undef size_t */
+
+/* The following two definitions are mainly for the benefit of SunOS4, which
+doesn't have the strerror() or memmove() functions that should be present in
+all Standard C libraries. The macros HAVE_STRERROR and HAVE_MEMMOVE should
+normally be defined with the value 1 for other systems, but unfortunately we
+can't make this the default because "configure" files generated by autoconf
+will only change 0 to 1; they won't change 1 to 0 if the functions are not
+found. If HAVE_MEMMOVE is set to 1, the value of HAVE_BCOPY is not relevant. */
+
+#define HAVE_STRERROR 1
+#define HAVE_MEMMOVE 1
+#define HAVE_BCOPY 1
+
+/* End */
--- /dev/null
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun ltconfig.
+#
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell, and then maybe $echo will work.
+ exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# The name of this program.
+progname=`$echo "$0" | sed 's%^.*/%%'`
+modename="$progname"
+
+# Constants.
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.3.4
+TIMESTAMP=" (1.385.2.196 1999/12/07 21:47:57)"
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+SP2NL='tr \040 \012'
+NL2SP='tr \015\012 \040\040'
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+ save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+ save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+if test "$LTCONFIG_VERSION" != "$VERSION"; then
+ echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ echo "$modename: not configured to build any kind of library" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+# Parse our command line options once, thoroughly.
+while test $# -gt 0
+do
+ arg="$1"
+ shift
+
+ case "$arg" in
+ -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case "$prev" in
+ execute_dlfiles)
+ eval "$prev=\"\$$prev \$arg\""
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case "$arg" in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+ exit 0
+ ;;
+
+ --config)
+ sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0
+ exit 0
+ ;;
+
+ --debug)
+ echo "$progname: enabling shell trace mode"
+ set -x
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ echo "enable shared libraries"
+ else
+ echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ echo "enable static libraries"
+ else
+ echo "disable static libraries"
+ fi
+ exit 0
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --quiet | --silent)
+ show=:
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$modename: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+fi
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ case "$nonopt" in
+ *cc | *++ | gcc* | *-gcc*)
+ mode=link
+ for arg
+ do
+ case "$arg" in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx | *strace | *truss)
+ mode=execute
+ ;;
+ *install*|cp|mv)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$modename --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case "$mode" in
+ # libtool compile mode
+ compile)
+ modename="$modename: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ lastarg=
+ srcfile="$nonopt"
+ suppress_output=
+
+ user_target=no
+ for arg
+ do
+ # Accept any command-line options.
+ case "$arg" in
+ -o)
+ if test "$user_target" != "no"; then
+ $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+ exit 1
+ fi
+ user_target=next
+ ;;
+
+ -static)
+ build_old_libs=yes
+ continue
+ ;;
+ esac
+
+ case "$user_target" in
+ next)
+ # The next one is the -o target name
+ user_target=yes
+ continue
+ ;;
+ yes)
+ # We got the output file
+ user_target=set
+ libobj="$arg"
+ continue
+ ;;
+ esac
+
+ # Accept the current argument as the source file.
+ lastarg="$srcfile"
+ srcfile="$arg"
+
+ # Aesthetically quote the previous argument.
+
+ # Backslashify any backslashes, double quotes, and dollar signs.
+ # These are the only characters that are still specially
+ # interpreted inside of double-quoted scrings.
+ lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly in scan
+ # sets, so we specify it separately.
+ case "$lastarg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ # Add the previous argument to base_compile.
+ if test -z "$base_compile"; then
+ base_compile="$lastarg"
+ else
+ base_compile="$base_compile $lastarg"
+ fi
+ done
+
+ case "$user_target" in
+ set)
+ ;;
+ no)
+ # Get the name of the library object.
+ libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+ ;;
+ *)
+ $echo "$modename: you must specify a target with \`-o'" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ xform='[cCFSfmso]'
+ case "$libobj" in
+ *.ada) xform=ada ;;
+ *.adb) xform=adb ;;
+ *.ads) xform=ads ;;
+ *.asm) xform=asm ;;
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.f90) xform=f90 ;;
+ *.for) xform=for ;;
+ esac
+
+ libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+ case "$libobj" in
+ *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+ *)
+ $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test -z "$base_compile"; then
+ $echo "$modename: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ removelist="$obj $libobj"
+ else
+ removelist="$libobj"
+ fi
+
+ $run $rm $removelist
+ trap "$run $rm $removelist; exit 1" 1 2 15
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test "$compiler_c_o" = no; then
+ output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext}
+ lockfile="$output_obj.lock"
+ removelist="$removelist $output_obj $lockfile"
+ trap "$run $rm $removelist; exit 1" 1 2 15
+ else
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test "$need_locks" = yes; then
+ until ln "$0" "$lockfile" 2>/dev/null; do
+ $show "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test "$need_locks" = warn; then
+ if test -f "$lockfile"; then
+ echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+ echo $srcfile > "$lockfile"
+ fi
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ # All platforms use -DPIC, to notify preprocessed assembler code.
+ command="$base_compile $srcfile $pic_flag -DPIC"
+ if test "$build_old_libs" = yes; then
+ lo_libobj="$libobj"
+ dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$libobj"; then
+ dir="$objdir"
+ else
+ dir="$dir/$objdir"
+ fi
+ libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
+
+ if test -d "$dir"; then
+ $show "$rm $libobj"
+ $run $rm $libobj
+ else
+ $show "$mkdir $dir"
+ $run $mkdir $dir
+ status=$?
+ if test $status -ne 0 && test ! -d $dir; then
+ exit $status
+ fi
+ fi
+ fi
+ if test "$compiler_o_lo" = yes; then
+ output_obj="$libobj"
+ command="$command -o $output_obj"
+ elif test "$compiler_c_o" = yes; then
+ output_obj="$obj"
+ command="$command -o $output_obj"
+ fi
+
+ $run $rm "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ test -n "$output_obj" && $run $rm $removelist
+ exit 1
+ fi
+
+ if test "$need_locks" = warn &&
+ test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+ echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test x"$output_obj" != x"$libobj"; then
+ $show "$mv $output_obj $libobj"
+ if $run $mv $output_obj $libobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # If we have no pic_flag, then copy the object into place and finish.
+ if test -z "$pic_flag" && test "$build_old_libs" = yes; then
+ # Rename the .lo from within objdir to obj
+ if test -f $obj; then
+ $show $rm $obj
+ $run $rm $obj
+ fi
+
+ $show "$mv $libobj $obj"
+ if $run $mv $libobj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+
+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$obj"; then
+ xdir="."
+ else
+ xdir="$xdir"
+ fi
+ baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"`
+ libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
+ # Now arrange that obj and lo_libobj become the same file
+ $show "(cd $xdir && $LN_S $baseobj $libobj)"
+ if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then
+ exit 0
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Allow error messages only from the first compilation.
+ suppress_output=' >/dev/null 2>&1'
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ command="$base_compile $srcfile"
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ output_obj="$obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ $run $rm "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ $run $rm $removelist
+ exit 1
+ fi
+
+ if test "$need_locks" = warn &&
+ test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+ echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+
+ # Just move the object if needed
+ if test x"$output_obj" != x"$obj"; then
+ $show "$mv $output_obj $obj"
+ if $run $mv $output_obj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we do not
+ # accidentally link it into a program.
+ if test "$build_libtool_libs" != yes; then
+ $show "echo timestamp > $libobj"
+ $run eval "echo timestamp > \$libobj" || exit $?
+ else
+ # Move the .lo from within objdir
+ $show "$mv $libobj $lo_libobj"
+ if $run $mv $libobj $lo_libobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+ fi
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $rm "$lockfile"
+ fi
+
+ exit 0
+ ;;
+
+ # libtool link mode
+ link)
+ modename="$modename: link"
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # which system we are compiling for in order to pass an extra
+ # flag for every libtool invokation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll which has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+
+ # This is a source program that is used to create dlls on Windows
+ # Don't remove nor modify the starting and closing comments
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# # ifdef __CYGWIN32__
+# # define __CYGWIN__ __CYGWIN32__
+# # endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+# __hDllInstance_base = hInst;
+# return TRUE;
+# }
+# /* ltdll.c ends here */
+ # This is a source program that is used to create import libraries
+ # on Windows for dlls which lack them. Don't remove nor modify the
+ # starting and closing comments
+# /* impgen.c starts here */
+# /* Copyright (C) 1999 Free Software Foundation, Inc.
+#
+# This file is part of GNU libtool.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# */
+#
+# #include <stdio.h> /* for printf() */
+# #include <unistd.h> /* for open(), lseek(), read() */
+# #include <fcntl.h> /* for O_RDONLY, O_BINARY */
+# #include <string.h> /* for strdup() */
+#
+# static unsigned int
+# pe_get16 (fd, offset)
+# int fd;
+# int offset;
+# {
+# unsigned char b[2];
+# lseek (fd, offset, SEEK_SET);
+# read (fd, b, 2);
+# return b[0] + (b[1]<<8);
+# }
+#
+# static unsigned int
+# pe_get32 (fd, offset)
+# int fd;
+# int offset;
+# {
+# unsigned char b[4];
+# lseek (fd, offset, SEEK_SET);
+# read (fd, b, 4);
+# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# static unsigned int
+# pe_as32 (ptr)
+# void *ptr;
+# {
+# unsigned char *b = ptr;
+# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# int
+# main (argc, argv)
+# int argc;
+# char *argv[];
+# {
+# int dll;
+# unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+# unsigned long export_rva, export_size, nsections, secptr, expptr;
+# unsigned long name_rvas, nexp;
+# unsigned char *expdata, *erva;
+# char *filename, *dll_name;
+#
+# filename = argv[1];
+#
+# dll = open(filename, O_RDONLY|O_BINARY);
+# if (!dll)
+# return 1;
+#
+# dll_name = filename;
+#
+# for (i=0; filename[i]; i++)
+# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':')
+# dll_name = filename + i +1;
+#
+# pe_header_offset = pe_get32 (dll, 0x3c);
+# opthdr_ofs = pe_header_offset + 4 + 20;
+# num_entries = pe_get32 (dll, opthdr_ofs + 92);
+#
+# if (num_entries < 1) /* no exports */
+# return 1;
+#
+# export_rva = pe_get32 (dll, opthdr_ofs + 96);
+# export_size = pe_get32 (dll, opthdr_ofs + 100);
+# nsections = pe_get16 (dll, pe_header_offset + 4 +2);
+# secptr = (pe_header_offset + 4 + 20 +
+# pe_get16 (dll, pe_header_offset + 4 + 16));
+#
+# expptr = 0;
+# for (i = 0; i < nsections; i++)
+# {
+# char sname[8];
+# unsigned long secptr1 = secptr + 40 * i;
+# unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+# unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+# unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+# lseek(dll, secptr1, SEEK_SET);
+# read(dll, sname, 8);
+# if (vaddr <= export_rva && vaddr+vsize > export_rva)
+# {
+# expptr = fptr + (export_rva - vaddr);
+# if (export_rva + export_size > vaddr + vsize)
+# export_size = vsize - (export_rva - vaddr);
+# break;
+# }
+# }
+#
+# expdata = (unsigned char*)malloc(export_size);
+# lseek (dll, expptr, SEEK_SET);
+# read (dll, expdata, export_size);
+# erva = expdata - export_rva;
+#
+# nexp = pe_as32 (expdata+24);
+# name_rvas = pe_as32 (expdata+32);
+#
+# printf ("EXPORTS\n");
+# for (i = 0; i<nexp; i++)
+# {
+# unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
+# printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
+# }
+#
+# return 0;
+# }
+# /* impgen.c ends here */
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ compile_command="$nonopt"
+ finalize_command="$nonopt"
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ linkopts=
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval lib_search_path=\`\$echo \"X \${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ lib_search_path=
+ fi
+ # now prepend the system-specific ones
+ eval lib_search_path=\"$sys_lib_search_path_spec\$lib_search_path\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ avoid_version=no
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ link_against_libtool_libs=
+ ltlibs=
+ module=no
+ objs=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case "$arg" in
+ -all-static | -static)
+ if test "X$arg" = "X-all-static"; then
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ else
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ fi
+ build_libtool_libs=no
+ build_old_libs=yes
+ prefer_static_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test $# -gt 0; do
+ arg="$1"
+ shift
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case "$prev" in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case "$prev" in
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ preload=yes
+ fi
+ case "$arg" in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test "$dlself" = no; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$dlprefiles $arg"
+ fi
+ prev=
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols="$arg"
+ if test ! -f "$arg"; then
+ $echo "$modename: symbol file \`$arg' does not exist"
+ exit 1
+ fi
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case "$arg" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit 1
+ ;;
+ esac
+ if test "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi
+
+ prevarg="$arg"
+
+ case "$arg" in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+ continue
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: not more than one -exported-symbols argument allowed"
+ exit 1
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -L*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+ # We need an absolute path.
+ case "$dir" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ absdir="$dir"
+ fi
+ dir="$absdir"
+ ;;
+ esac
+ case " $deplibs " in
+ *" $arg "*) ;;
+ *) deplibs="$deplibs $arg";;
+ esac
+ case " $lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir";;
+ esac
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
+ case ":$dllsearchpath:" in
+ ::) dllsearchpath="$dllsearchdir";;
+ *":$dllsearchdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dllsearchdir";;
+ esac
+ ;;
+ esac
+ ;;
+
+ -l*)
+ if test "$arg" = "-lc"; then
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
+ # These systems don't actually have c library (as such)
+ continue
+ ;;
+ esac
+ elif test "$arg" = "-lm"; then
+ case "$host" in
+ *-*-cygwin* | *-*-beos*)
+ # These systems don't actually have math library (as such)
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+ # We need an absolute path.
+ case "$dir" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit 1
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ continue
+ ;;
+
+ -static)
+ # If we have no pic_flag, then this is the same as -all-static.
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.o | *.obj | *.a | *.lib)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A library object.
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
+ prev=
+ fi
+ libobjs="$libobjs $arg"
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ dlname=
+ libdir=
+ library_names=
+ old_library=
+
+ # Check to see that this really is a libtool archive.
+ if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variable installed.
+ installed=yes
+
+ # Read the .la file
+ # If there is no directory component, then add one.
+ case "$arg" in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+
+ if test -z "$linklib"; then
+ $echo "$modename: cannot find name of link library for \`$arg'" 1>&2
+ exit 1
+ fi
+
+ # Find the relevant object directory and library name.
+ name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'`
+
+ if test "X$installed" = Xyes; then
+ dir="$libdir"
+ else
+ dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$arg"; then
+ dir="$objdir"
+ else
+ dir="$dir/$objdir"
+ fi
+ fi
+
+ if test -n "$dependency_libs"; then
+ # Extract -R and -L from dependency_libs
+ temp_deplibs=
+ for deplib in $dependency_libs; do
+ case "$deplib" in
+ -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ case " $rpath $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ -L*) case "$compile_command $temp_deplibs " in
+ *" $deplib "*) ;;
+ *) temp_deplibs="$temp_deplibs $deplib";;
+ esac
+ temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ case " $lib_search_path " in
+ *" $temp_dir "*) ;;
+ *) lib_search_path="$lib_search_path $temp_dir";;
+ esac
+ ;;
+ *) temp_deplibs="$temp_deplibs $deplib";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ if test -z "$libdir"; then
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $dir/$old_library"
+ old_convenience="$old_convenience $dir/$old_library"
+ deplibs="$deplibs$dependency_libs"
+ compile_command="$compile_command $dir/$old_library$dependency_libs"
+ finalize_command="$finalize_command $dir/$old_library$dependency_libs"
+ continue
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking statically,
+ # we need to preload.
+ prev=dlprefiles
+ else
+ # We should not create a dependency on this library, but we
+ # may need any libraries it requires.
+ compile_command="$compile_command$dependency_libs"
+ finalize_command="$finalize_command$dependency_libs"
+ prev=
+ continue
+ fi
+ fi
+
+ # The library was specified with -dlpreopen.
+ if test "$prev" = dlprefiles; then
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ dlprefiles="$dlprefiles $dir/$old_library"
+ else
+ dlprefiles="$dlprefiles $dir/$linklib"
+ fi
+ prev=
+ fi
+
+ if test -n "$library_names" &&
+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ link_against_libtool_libs="$link_against_libtool_libs $arg"
+ if test -n "$shlibpath_var"; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *) temp_rpath="$temp_rpath $dir" ;;
+ esac
+ fi
+
+ # We need an absolute path.
+ case "$dir" in
+ [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ absdir="$dir"
+ fi
+ ;;
+ esac
+
+ # This is the magic to use -rpath.
+ # Skip directories that are in the system default run-time
+ # search path, unless they have been requested with -R.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+
+ lib_linked=yes
+ case "$hardcode_action" in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ compile_command="$compile_command $dir/$linklib"
+ deplibs="$deplibs $dir/$linklib"
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
+ if test -n "$dllsearchpath"; then
+ dllsearchpath="$dllsearchpath:$dllsearchdir"
+ else
+ dllsearchpath="$dllsearchdir"
+ fi
+ ;;
+ esac
+ elif test "$hardcode_minus_L" = no; then
+ case "$host" in
+ *-*-sunos*)
+ compile_shlibpath="$compile_shlibpath$dir:"
+ ;;
+ esac
+ case "$compile_command " in
+ *" -L$dir "*) ;;
+ *) compile_command="$compile_command -L$dir";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -L$dir -l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ case ":$compile_shlibpath:" in
+ *":$dir:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$dir:";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+
+ relink)
+ if test "$hardcode_direct" = yes; then
+ compile_command="$compile_command $absdir/$linklib"
+ deplibs="$deplibs $absdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ case "$compile_command " in
+ *" -L$absdir "*) ;;
+ *) compile_command="$compile_command -L$absdir";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -L$absdir -l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case ":$compile_shlibpath:" in
+ *":$absdir:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$absdir:";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+
+ *)
+ lib_linked=no
+ ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ $echo "$modename: configuration error: unsupported hardcode properties"
+ exit 1
+ fi
+
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ finalize_command="$finalize_command $libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ case "$finalize_command " in
+ *" -L$libdir "*) ;;
+ *) finalize_command="$finalize_command -L$libdir";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case ":$finalize_shlibpath:" in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ case "$finalize_command " in
+ *" -L$dir "*) ;;
+ *) finalize_command="$finalize_command -L$libdir";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ fi
+ else
+ # Transform directly to old archives if we don't build new libraries.
+ if test -n "$pic_flag" && test -z "$old_library"; then
+ $echo "$modename: cannot find static library for \`$arg'" 1>&2
+ exit 1
+ fi
+
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_command="$compile_command $dir/$linklib"
+ finalize_command="$finalize_command $dir/$linklib"
+ else
+ case "$compile_command " in
+ *" -L$dir "*) ;;
+ *) compile_command="$compile_command -L$dir";;
+ esac
+ compile_command="$compile_command -l$name"
+ case "$finalize_command " in
+ *" -L$dir "*) ;;
+ *) finalize_command="$finalize_command -L$dir";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ fi
+ fi
+
+ # Add in any libraries that this one depends upon.
+ compile_command="$compile_command$dependency_libs"
+ finalize_command="$finalize_command$dependency_libs"
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+ done
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+ libobjs_save="$libobjs"
+
+ case "$output" in
+ "")
+ $echo "$modename: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *.a | *.lib)
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$modename: error: cannot link libtool libraries into archives" 1>&2
+ exit 1
+ fi
+
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+ fi
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs="$output"
+ ;;
+
+ *.la)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case "$outputname" in
+ lib*)
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ if test "$module" = no; then
+ $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+ if test "$need_lib_prefix" != no; then
+ # Add the "lib" prefix for modules if required
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ eval libname=\"$libname_spec\"
+ else
+ libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ fi
+ ;;
+ esac
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+
+ if test -n "$objs"; then
+ $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1
+ exit 1
+ fi
+
+ # How the heck are we supposed to write a wrapper for a shared library?
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2
+ exit 1
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2
+ fi
+
+ set dummy $rpath
+ if test $# -gt 2; then
+ $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; then
+ # Building a libtool convenience library.
+ libext=al
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+ dependency_libs="$deplibs"
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+ fi
+ else
+
+ # Parse the version information argument.
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ IFS="$save_ifs"
+
+ if test -n "$8"; then
+ $echo "$modename: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ current="$2"
+ revision="$3"
+ age="$4"
+
+ # Check that each of the things are valid numbers.
+ case "$current" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$revision" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$age" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test $age -gt $current; then
+ $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case "$version_type" in
+ none) ;;
+
+ irix)
+ major=`expr $current - $age + 1`
+ versuffix="$major.$revision"
+ verstring="sgi$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test $loop != 0; do
+ iface=`expr $revision - $loop`
+ loop=`expr $loop - 1`
+ verstring="sgi$major.$iface:$verstring"
+ done
+ ;;
+
+ linux)
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ major=`expr $current - $age`
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test $loop != 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current";
+ ;;
+
+ windows)
+ # Like Linux, but with '-' rather than '.', since we only
+ # want one extension on Windows 95.
+ major=`expr $current - $age`
+ versuffix="-$major-$age-$revision"
+ ;;
+
+ *)
+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ verstring="0.0"
+ if test "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+
+ dependency_libs="$deplibs"
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *)
+ # Add libc to deplibs on all other systems.
+ deplibs="$deplibs -lc"
+ ;;
+ esac
+ fi
+
+ # Create the output directory, or remove our outputs if we need to.
+ if test -d $output_objdir; then
+ $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
+ $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
+ else
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ status=$?
+ if test $status -ne 0 && test ! -d $output_objdir; then
+ exit $status
+ fi
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ if test "$build_libtool_libs" = yes; then
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=""
+ versuffix=""
+ major=""
+ newdeplibs=
+ droppeddeps=no
+ case "$deplibs_check_method" in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behaviour.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $rm conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $rm conftest
+ $CC -o conftest conftest.c $deplibs
+ if test $? -eq 0 ; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+ # Error occured in the first compile. Let's try to salvage the situation:
+ # Compile a seperate program for each library.
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" ; then
+ $rm conftest
+ $CC -o conftest conftest.c $i
+ # Did it work?
+ if test $? -eq 0 ; then
+ ldd_output=`ldd conftest`
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning! Library $i is needed by this library but I was not able to"
+ echo "*** make it link in! You will probably need to install it or some"
+ echo "*** library that it depends on before this library will be fully"
+ echo "*** functional. Installing it before continuing would be even better."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method
+ file_magic_regex="`expr \"$deplibs_check_method\" : \"$2 \(.*\)\"`"
+ for a_deplib in $deplibs; do
+ name="`expr $a_deplib : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null \
+ | grep " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | sed 's/.* -> //'`
+ case "$potliblink" in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+ | sed 10q \
+ | egrep "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+ -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' |
+ grep . >/dev/null; then
+ echo
+ if test "X$deplibs_check_method" = "Xnone"; then
+ echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ fi
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; then
+ echo
+ echo "*** Warning: libtool could not satisfy all declared inter-library"
+ echo "*** dependencies of module $libname. Therefore, libtool will create"
+ echo "*** a static module, that should work as long as the dlopening"
+ echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ echo "*** The inter-library dependencies that have been dropped here will be"
+ echo "*** automatically added whenever a program is linked with this library"
+ echo "*** or is declared to -dlopen it."
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+ # Get the real and link names of the library.
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ lib="$output_objdir/$realname"
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Ensure that we have .o objects for linkers which dislike .lo
+ # (e.g. aix) in case we are running --disable-static
+ for obj in $libobjs; do
+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$obj"; then
+ xdir="."
+ else
+ xdir="$xdir"
+ fi
+ baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
+ if test ! -f $xdir/$oldobj; then
+ $show "(cd $xdir && ${LN_S} $baseobj $oldobj)"
+ $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $?
+ fi
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ eval cmds=\"$export_symbols_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ if test -n "$export_symbols_regex"; then
+ $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+ $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+ $run eval '$mv "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+ fi
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${outputname}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ for xlib in $convenience; do
+ # Extract the objects.
+ case "$xlib" in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linkopts="$linkopts $flag"
+ fi
+
+ # Do each of the archive commands.
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval cmds=\"$archive_expsym_cmds\"
+ else
+ eval cmds=\"$archive_cmds\"
+ fi
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ *.lo | *.o | *.obj)
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$modename: error: cannot link libtool libraries into objects" 1>&2
+ exit 1
+ fi
+
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+ fi
+
+ case "$output" in
+ *.lo)
+ if test -n "$objs"; then
+ $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit 1
+ fi
+ libobj="$output"
+ obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # reload_cmds runs $LD directly, so let us get rid of
+ # -Wl from whole_archive_flag_spec
+ wl=
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${obj}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ for xlib in $convenience; do
+ # Extract the objects.
+ case "$xlib" in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+ fi
+
+ # Create the old-style object.
+ reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs"
+
+ output="$obj"
+ eval cmds=\"$reload_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit 0
+ fi
+
+ if test "$build_libtool_libs" != yes; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ $show "echo timestamp > $libobj"
+ $run eval "echo timestamp > $libobj" || exit $?
+ exit 0
+ fi
+
+ if test -n "$pic_flag"; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output="$libobj"
+ eval cmds=\"$reload_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ else
+ # Just create a symlink.
+ $show $rm $libobj
+ $run $rm $libobj
+ xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$libobj"; then
+ xdir="."
+ else
+ xdir="$xdir"
+ fi
+ baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
+ oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
+ $show "(cd $xdir && $LN_S $oldobj $baseobj)"
+ $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $?
+ fi
+
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit 0
+ ;;
+
+ # Anything else should be a program.
+ *)
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+ fi
+
+ if test "$preload" = yes; then
+ if test "$dlopen" = unknown && test "$dlopen_self" = unknown &&
+ test "$dlopen_self_static" = unknown; then
+ $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+ fi
+ fi
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$compile_rpath " in
+ *" $libdir "*) ;;
+ *) compile_rpath="$compile_rpath $libdir" ;;
+ esac
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath="$rpath"
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath="$rpath"
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+
+ # Create the binary in the object directory, then wrap it.
+ if test ! -d $output_objdir; then
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ status=$?
+ if test $status -ne 0 && test ! -d $output_objdir; then
+ exit $status
+ fi
+ fi
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ dlsyms=
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${outputname}S.c"
+ else
+ $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+ fi
+ fi
+
+ if test -n "$dlsyms"; then
+ case "$dlsyms" in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist="$output_objdir/${outputname}.nm"
+
+ $show "$rm $nlist ${nlist}S ${nlist}T"
+ $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+ # Parse the name list into a source file.
+ $show "creating $output_objdir/$dlsyms"
+
+ test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; then
+ $show "generating symbol list for \`$output'"
+
+ test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for arg in $progfiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$output.exp"
+ $run $rm $export_symbols
+ $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ else
+ $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
+ $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ name=`echo "$arg" | sed -e 's%^.*/%%'`
+ $run eval 'echo ": $name " >> "$nlist"'
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -z "$run"; then
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $mv "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then
+ :
+ else
+ grep -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+ else
+ echo '/* NONE */' >> "$output_objdir/$dlsyms"
+ fi
+
+ $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+ sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \
+ -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \
+ < "$nlist" >> "$output_objdir/$dlsyms"
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ {0, (lt_ptr_t) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ fi
+
+ pic_flag_for_symtable=
+ case "$host" in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)\r
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";;
+ esac;;
+ *-*-hpux*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DPIC";;
+ esac
+ esac
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+ # Clean up the generated files.
+ $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+ $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+ # Transform the symbol file into the correct name.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ ;;
+ *)
+ $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+ exit 1
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+ fi
+
+ if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ link_command="$compile_command$compile_rpath"
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$link_command"
+ $run eval "$link_command"
+ status=$?
+
+ # Delete the generated files.
+ if test -n "$dlsyms"; then
+ $show "$rm $output_objdir/${outputname}S.${objext}"
+ $run $rm "$output_objdir/${outputname}S.${objext}"
+ fi
+
+ exit $status
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case "$dir" in
+ [\\/]* | [A-Za-z]:[\\/]*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+ $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+ $echo "$modename: \`$output' will be relinked during installation" 1>&2
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Quote $echo for shipping.
+ if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
+ case "$0" in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$0 --fallback-echo";;
+ esac
+ qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) output=`echo $output|sed 's,.exe$,,'` ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit 1" 1 2 15
+
+ $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variable:
+ link_against_libtool_libs='$link_against_libtool_libs'
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ echo=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$echo works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$echo will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $echo >> $output "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; then
+ echo >> $output "\
+ program=lt-'$outputname'
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" || \\
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $mkdir \"\$progdir\"
+ else
+ $rm \"\$progdir/\$file\"
+ fi"
+
+ echo >> $output "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if (cd \"\$thisdir\" && eval \$relink_command); then :
+ else
+ $rm \"\$progdir/\$file\"
+ exit 1
+ fi
+ fi
+
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $rm \"\$progdir/\$program\";
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $rm \"\$progdir/\$file\"
+ fi"
+ else
+ echo >> $output "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ echo >> $output "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $echo >> $output "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $echo >> $output "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $echo >> $output "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ *-*-cygwin* | *-*-mingw | *-*-os2*)
+ # win32 systems need to use the prog path for dll
+ # lookup to work
+ $echo >> $output "\
+ exec \$progdir\\\\\$program \${1+\"\$@\"}
+"
+ ;;
+ *)
+ $echo >> $output "\
+ # Export the path to the program.
+ PATH=\"\$progdir:\$PATH\"
+ export PATH
+
+ exec \$program \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $echo >> $output "\
+ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+ exit 1
+ fi
+ else
+ # The program doesn't exist.
+ \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
+ \$echo \"This script is just a wrapper for \$program.\" 1>&2
+ echo \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit 1
+ fi
+fi\
+"
+ chmod +x $output
+ fi
+ exit 0
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ # Add in members from convenience archives.
+ for xlib in $addlibs; do
+ # Extract the objects.
+ case "$xlib" in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ eval cmds=\"$old_archive_from_new_cmds\"
+ else
+ # Ensure that we have .o objects in place in case we decided
+ # not to build a shared library, and have fallen back to building
+ # static libs even though --disable-static was passed!
+ for oldobj in $oldobjs; do
+ if test ! -f $oldobj; then
+ xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$oldobj"; then
+ xdir="."
+ else
+ xdir="$xdir"
+ fi
+ baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'`
+ obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
+ $show "(cd $xdir && ${LN_S} $obj $baseobj)"
+ $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $?
+ fi
+ done
+
+ eval cmds=\"$old_archive_cmds\"
+ fi
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$generated"; then
+ $show "${rm}r$generated"
+ $run ${rm}r$generated
+ fi
+
+ # Now create the libtool archive.
+ case "$output" in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.$libext"
+ $show "creating $output"
+
+ if test -n "$xrpath"; then
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ done
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ for installed in no yes; do
+ if test "$installed" = yes; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output="$output_objdir/$outputname"i
+ fi
+ $rm $output
+ $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$dlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'\
+"
+ done
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+ $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $?
+ ;;
+ esac
+ exit 0
+ ;;
+
+ # libtool install mode
+ install)
+ modename="$modename: install"
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then
+ # Aesthetically quote it.
+ arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ arg="$nonopt"
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest="$arg"
+ continue
+ fi
+
+ case "$arg" in
+ -d) isdir=yes ;;
+ -f) prev="-f" ;;
+ -g) prev="-g" ;;
+ -m) prev="-m" ;;
+ -o) prev="-o" ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*) ;;
+
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest="$arg"
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$modename: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$modename: no file or destination specified" 1>&2
+ else
+ $echo "$modename: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test "$isdir" = yes; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test $# -gt 2; then
+ $echo "$modename: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+ fi
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case "$file" in
+ *.lo) ;;
+ *)
+ $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case "$file" in
+ *.a | *.lib)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ library_names=
+ old_library=
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/"
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$realname $destdir/$realname"
+ $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $?
+
+ if test $# -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ for linkname
+ do
+ if test "$linkname" != "$realname"; then
+ $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ fi
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ eval cmds=\"$postinstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ instname="$dir/$name"i
+ $show "$install_prog $instname $destdir/$name"
+ $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case "$destfile" in
+ *.lo)
+ staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+ ;;
+ *.o | *.obj)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit 0
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Do a test to see if this is really a libtool program.
+ if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ link_against_libtool_libs=
+ relink_command=
+
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$link_against_libtool_libs"; then
+ $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2
+ exit 1
+ fi
+
+ finalize=yes
+ for lib in $link_against_libtool_libs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case "$lib" in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`"
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ if test "$finalize" = yes && test -z "$run"; then
+ tmpdir="/tmp"
+ test -n "$TMPDIR" && tmpdir="$TMPDIR"
+ tmpdir="$tmpdir/libtool-$$"
+ if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
+ else
+ $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
+ continue
+ fi
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ ${rm}r "$tmpdir"
+ continue
+ fi
+ file="$outputname"
+ else
+ $echo "$modename: warning: cannot relink \`$file'" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ $show "$install_prog$stripme $file $destfile"
+ $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+ test -n "$outputname" && ${rm}r "$tmpdir"
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ # Do each command in the postinstall commands.
+ eval cmds=\"$old_postinstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec $SHELL $0 --finish$current_libdirs
+ exit 1
+ fi
+
+ exit 0
+ ;;
+
+ # libtool finish mode
+ finish)
+ modename="$modename: finish"
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ eval cmds=\"$finish_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || admincmds="$admincmds
+ $cmd"
+ done
+ IFS="$save_ifs"
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $run eval "$cmds" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ test "$show" = : && exit 0
+
+ echo "----------------------------------------------------------------------"
+ echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ echo " $libdir"
+ done
+ echo
+ echo "If you ever happen to want to link against installed libraries"
+ echo "in a given directory, LIBDIR, you must either use libtool, and"
+ echo "specify the full pathname of the library, or use \`-LLIBDIR'"
+ echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
+ echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ echo " - add LIBDIR to the \`$runpath_var' environment variable"
+ echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ echo " - use the \`$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ echo " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+ fi
+ echo
+ echo "See any operating system documentation about shared libraries for"
+ echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ echo "----------------------------------------------------------------------"
+ exit 0
+ ;;
+
+ # libtool execute mode
+ execute)
+ modename="$modename: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$modename: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit 1
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test ! -f "$file"; then
+ $echo "$modename: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ dir=
+ case "$file" in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit 1
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case "$file" in
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved enviroment variables
+ if test "${save_LC_ALL+set}" = set; then
+ LC_ALL="$save_LC_ALL"; export LC_ALL
+ fi
+ if test "${save_LANG+set}" = set; then
+ LANG="$save_LANG"; export LANG
+ fi
+
+ # Now actually exec the command.
+ eval "exec \$cmd$args"
+
+ $echo "$modename: cannot exec \$cmd$args"
+ exit 1
+ else
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ fi
+ $echo "$cmd$args"
+ exit 0
+ fi
+ ;;
+
+ # libtool uninstall mode
+ uninstall)
+ modename="$modename: uninstall"
+ rm="$nonopt"
+ files=
+
+ for arg
+ do
+ case "$arg" in
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$modename: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ for file in $files; do
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ rmfiles="$file"
+
+ case "$name" in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $dir/$n"
+ done
+ test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library"
+
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ eval cmds=\"$postuninstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ eval cmds=\"$old_postuninstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ done
+ IFS="$save_ifs"
+ fi
+
+ # FIXME: should reinstall the best remaining shared library.
+ fi
+ ;;
+
+ *.lo)
+ if test "$build_old_libs" = yes; then
+ oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
+ rmfiles="$rmfiles $dir/$oldobj"
+ fi
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+ ;;
+
+ *)
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+ ;;
+ esac
+ done
+ exit 0
+ ;;
+
+ "")
+ $echo "$modename: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+fi # test -z "$show_help"
+
+# We need to display help for each of the modes.
+case "$mode" in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+-n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --version print version information
+
+MODE must be one of the following:
+
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE."
+ exit 0
+ ;;
+
+compile)
+ $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -static always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+ ;;
+
+execute)
+ $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+finish)
+ $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed."
+ ;;
+
+install)
+ $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+link)
+ $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -static do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+uninstall)
+ $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+*)
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+esac
+
+echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
--- /dev/null
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/*
+This is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language. See
+the file Tech.Notes for some information on the internals.
+
+Written by: Philip Hazel <ph10@cam.ac.uk>
+
+ Copyright (c) 1997-2000 University of Cambridge
+
+-----------------------------------------------------------------------------
+Permission is granted to anyone to use this software for any purpose on any
+computer system, and to redistribute it freely, subject to the following
+restrictions:
+
+1. This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+2. The origin of this software must not be misrepresented, either by
+ explicit claim or by omission.
+
+3. Altered versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+4. If PCRE is embedded in any software that is released under the GNU
+ General Purpose Licence (GPL), then the terms of that licence shall
+ supersede any condition above with which it is incompatible.
+-----------------------------------------------------------------------------
+*/
+
+
+/* Define DEBUG to get debugging output on stdout. */
+
+/* #define DEBUG */
+
+/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef
+inline, and there are *still* stupid compilers about that don't like indented
+pre-processor statements. I suppose it's only been 10 years... */
+
+#ifdef DEBUG
+#define DPRINTF(p) printf p
+#else
+#define DPRINTF(p) /*nothing*/
+#endif
+
+/* Include the internals header, which itself includes Standard C headers plus
+the external pcre header. */
+
+#include "internal.h"
+
+
+/* Allow compilation as C++ source code, should anybody want to do that. */
+
+#ifdef __cplusplus
+#define class pcre_class
+#endif
+
+
+/* Number of items on the nested bracket stacks at compile time. This should
+not be set greater than 200. */
+
+#define BRASTACK_SIZE 200
+
+
+/* The number of bytes in a literal character string above which we can't add
+any more is different when UTF-8 characters may be encountered. */
+
+#ifdef SUPPORT_UTF8
+#define MAXLIT 250
+#else
+#define MAXLIT 255
+#endif
+
+
+/* Min and max values for the common repeats; for the maxima, 0 => infinity */
+
+static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
+static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
+
+/* Text forms of OP_ values and things, for debugging (not all used) */
+
+#ifdef DEBUG
+static const char *OP_names[] = {
+ "End", "\\A", "\\B", "\\b", "\\D", "\\d",
+ "\\S", "\\s", "\\W", "\\w", "\\Z", "\\z",
+ "Opt", "^", "$", "Any", "chars", "not",
+ "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
+ "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
+ "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
+ "*", "*?", "+", "+?", "?", "??", "{", "{",
+ "class", "Ref", "Recurse",
+ "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not",
+ "AssertB", "AssertB not", "Reverse", "Once", "Cond", "Cref",
+ "Brazero", "Braminzero", "Bra"
+};
+#endif
+
+/* Table for handling escaped characters in the range '0'-'z'. Positive returns
+are simple data values; negative values are for special things like \d and so
+on. Zero means further processing is needed (for things like \x), or the escape
+is invalid. */
+
+static const short int escapes[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 7 */
+ 0, 0, ':', ';', '<', '=', '>', '?', /* 8 - ? */
+ '@', -ESC_A, -ESC_B, 0, -ESC_D, 0, 0, 0, /* @ - G */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */
+ 0, 0, 0, -ESC_S, 0, 0, 0, -ESC_W, /* P - W */
+ 0, 0, -ESC_Z, '[', '\\', ']', '^', '_', /* X - _ */
+ '`', 7, -ESC_b, 0, -ESC_d, 27, '\f', 0, /* ` - g */
+ 0, 0, 0, 0, 0, 0, '\n', 0, /* h - o */
+ 0, 0, '\r', -ESC_s, '\t', 0, 0, -ESC_w, /* p - w */
+ 0, 0, -ESC_z /* x - z */
+};
+
+/* Tables of names of POSIX character classes and their lengths. The list is
+terminated by a zero length entry. The first three must be alpha, upper, lower,
+as this is assumed for handling case independence. */
+
+static const char *posix_names[] = {
+ "alpha", "lower", "upper",
+ "alnum", "ascii", "cntrl", "digit", "graph",
+ "print", "punct", "space", "word", "xdigit" };
+
+static const uschar posix_name_lengths[] = {
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };
+
+/* Table of class bit maps for each POSIX class; up to three may be combined
+to form the class. */
+
+static const int posix_class_maps[] = {
+ cbit_lower, cbit_upper, -1, /* alpha */
+ cbit_lower, -1, -1, /* lower */
+ cbit_upper, -1, -1, /* upper */
+ cbit_digit, cbit_lower, cbit_upper, /* alnum */
+ cbit_print, cbit_cntrl, -1, /* ascii */
+ cbit_cntrl, -1, -1, /* cntrl */
+ cbit_digit, -1, -1, /* digit */
+ cbit_graph, -1, -1, /* graph */
+ cbit_print, -1, -1, /* print */
+ cbit_punct, -1, -1, /* punct */
+ cbit_space, -1, -1, /* space */
+ cbit_word, -1, -1, /* word */
+ cbit_xdigit,-1, -1 /* xdigit */
+};
+
+
+/* Definition to allow mutual recursion */
+
+static BOOL
+ compile_regex(int, int, int *, uschar **, const uschar **, const char **,
+ BOOL, int, int *, int *, compile_data *);
+
+/* Structure for building a chain of data that actually lives on the
+stack, for holding the values of the subject pointer at the start of each
+subpattern, so as to detect when an empty string has been matched by a
+subpattern - to break infinite loops. */
+
+typedef struct eptrblock {
+ struct eptrblock *prev;
+ const uschar *saved_eptr;
+} eptrblock;
+
+/* Flag bits for the match() function */
+
+#define match_condassert 0x01 /* Called to check a condition assertion */
+#define match_isgroup 0x02 /* Set if start of bracketed group */
+
+
+
+/*************************************************
+* Global variables *
+*************************************************/
+
+/* PCRE is thread-clean and doesn't use any global variables in the normal
+sense. However, it calls memory allocation and free functions via the two
+indirections below, which are can be changed by the caller, but are shared
+between all threads. */
+
+void *(*pcre_malloc)(size_t) = malloc;
+void (*pcre_free)(void *) = free;
+
+
+
+/*************************************************
+* Macros and tables for character handling *
+*************************************************/
+
+/* When UTF-8 encoding is being used, a character is no longer just a single
+byte. The macros for character handling generate simple sequences when used in
+byte-mode, and more complicated ones for UTF-8 characters. */
+
+#ifndef SUPPORT_UTF8
+#define GETCHARINC(c, eptr) c = *eptr++;
+#define GETCHARLEN(c, eptr, len) c = *eptr;
+#define BACKCHAR(eptr)
+
+#else /* SUPPORT_UTF8 */
+
+/* Get the next UTF-8 character, advancing the pointer */
+
+#define GETCHARINC(c, eptr) \
+ c = *eptr++; \
+ if (md->utf8 && (c & 0xc0) == 0xc0) \
+ { \
+ int a = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \
+ int s = 6 - a; /* Amount to shift next byte */ \
+ c &= utf8_table3[a]; /* Low order bits from first byte */ \
+ while (a-- > 0) \
+ { \
+ c |= (*eptr++ & 0x3f) << s; \
+ s += 6; \
+ } \
+ }
+
+/* Get the next UTF-8 character, not advancing the pointer, setting length */
+
+#define GETCHARLEN(c, eptr, len) \
+ c = *eptr; \
+ len = 1; \
+ if (md->utf8 && (c & 0xc0) == 0xc0) \
+ { \
+ int i; \
+ int a = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \
+ int s = 6 - a; /* Amount to shift next byte */ \
+ c &= utf8_table3[a]; /* Low order bits from first byte */ \
+ for (i = 1; i <= a; i++) \
+ { \
+ c |= (eptr[i] & 0x3f) << s; \
+ s += 6; \
+ } \
+ len += a; \
+ }
+
+/* If the pointer is not at the start of a character, move it back until
+it is. */
+
+#define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr--;
+
+#endif
+
+
+
+/*************************************************
+* Default character tables *
+*************************************************/
+
+/* A default set of character tables is included in the PCRE binary. Its source
+is built by the maketables auxiliary program, which uses the default C ctypes
+functions, and put in the file chartables.c. These tables are used by PCRE
+whenever the caller of pcre_compile() does not provide an alternate set of
+tables. */
+
+#include "chartables.c"
+
+
+
+#ifdef SUPPORT_UTF8
+/*************************************************
+* Tables for UTF-8 support *
+*************************************************/
+
+/* These are the breakpoints for different numbers of bytes in a UTF-8
+character. */
+
+static int utf8_table1[] = { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
+
+/* These are the indicator bits and the mask for the data bits to set in the
+first byte of a character, indexed by the number of additional bytes. */
+
+static int utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
+static int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
+
+/* Table of the number of extra characters, indexed by the first character
+masked with 0x3f. The highest number for a valid UTF-8 character is in fact
+0x3d. */
+
+static uschar utf8_table4[] = {
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
+
+
+/*************************************************
+* Convert character value to UTF-8 *
+*************************************************/
+
+/* This function takes an integer value in the range 0 - 0x7fffffff
+and encodes it as a UTF-8 character in 0 to 6 bytes.
+
+Arguments:
+ cvalue the character value
+ buffer pointer to buffer for result - at least 6 bytes long
+
+Returns: number of characters placed in the buffer
+*/
+
+static int
+ord2utf8(int cvalue, uschar *buffer)
+{
+register int i, j;
+for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++)
+ if (cvalue <= utf8_table1[i]) break;
+*buffer++ = utf8_table2[i] | (cvalue & utf8_table3[i]);
+cvalue >>= 6 - i;
+for (j = 0; j < i; j++)
+ {
+ *buffer++ = 0x80 | (cvalue & 0x3f);
+ cvalue >>= 6;
+ }
+return i + 1;
+}
+#endif
+
+
+
+/*************************************************
+* Return version string *
+*************************************************/
+
+#define STRING(a) # a
+#define XSTRING(s) STRING(s)
+
+const char *
+pcre_version(void)
+{
+return XSTRING(PCRE_MAJOR) "." XSTRING(PCRE_MINOR) " " XSTRING(PCRE_DATE);
+}
+
+
+
+
+/*************************************************
+* (Obsolete) Return info about compiled pattern *
+*************************************************/
+
+/* This is the original "info" function. It picks potentially useful data out
+of the private structure, but its interface was too rigid. It remains for
+backwards compatibility. The public options are passed back in an int - though
+the re->options field has been expanded to a long int, all the public options
+at the low end of it, and so even on 16-bit systems this will still be OK.
+Therefore, I haven't changed the API for pcre_info().
+
+Arguments:
+ external_re points to compiled code
+ optptr where to pass back the options
+ first_char where to pass back the first character,
+ or -1 if multiline and all branches start ^,
+ or -2 otherwise
+
+Returns: number of capturing subpatterns
+ or negative values on error
+*/
+
+int
+pcre_info(const pcre *external_re, int *optptr, int *first_char)
+{
+const real_pcre *re = (const real_pcre *)external_re;
+if (re == NULL) return PCRE_ERROR_NULL;
+if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
+if (optptr != NULL) *optptr = (int)(re->options & PUBLIC_OPTIONS);
+if (first_char != NULL)
+ *first_char = ((re->options & PCRE_FIRSTSET) != 0)? re->first_char :
+ ((re->options & PCRE_STARTLINE) != 0)? -1 : -2;
+return re->top_bracket;
+}
+
+
+
+/*************************************************
+* Return info about compiled pattern *
+*************************************************/
+
+/* This is a newer "info" function which has an extensible interface so
+that additional items can be added compatibly.
+
+Arguments:
+ external_re points to compiled code
+ external_study points to study data, or NULL
+ what what information is required
+ where where to put the information
+
+Returns: 0 if data returned, negative on error
+*/
+
+int
+pcre_fullinfo(const pcre *external_re, const pcre_extra *study_data, int what,
+ void *where)
+{
+const real_pcre *re = (const real_pcre *)external_re;
+const real_pcre_extra *study = (const real_pcre_extra *)study_data;
+
+if (re == NULL || where == NULL) return PCRE_ERROR_NULL;
+if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
+
+switch (what)
+ {
+ case PCRE_INFO_OPTIONS:
+ *((unsigned long int *)where) = re->options & PUBLIC_OPTIONS;
+ break;
+
+ case PCRE_INFO_SIZE:
+ *((size_t *)where) = re->size;
+ break;
+
+ case PCRE_INFO_CAPTURECOUNT:
+ *((int *)where) = re->top_bracket;
+ break;
+
+ case PCRE_INFO_BACKREFMAX:
+ *((int *)where) = re->top_backref;
+ break;
+
+ case PCRE_INFO_FIRSTCHAR:
+ *((int *)where) =
+ ((re->options & PCRE_FIRSTSET) != 0)? re->first_char :
+ ((re->options & PCRE_STARTLINE) != 0)? -1 : -2;
+ break;
+
+ case PCRE_INFO_FIRSTTABLE:
+ *((const uschar **)where) =
+ (study != NULL && (study->options & PCRE_STUDY_MAPPED) != 0)?
+ study->start_bits : NULL;
+ break;
+
+ case PCRE_INFO_LASTLITERAL:
+ *((int *)where) =
+ ((re->options & PCRE_REQCHSET) != 0)? re->req_char : -1;
+ break;
+
+ default: return PCRE_ERROR_BADOPTION;
+ }
+
+return 0;
+}
+
+
+
+#ifdef DEBUG
+/*************************************************
+* Debugging function to print chars *
+*************************************************/
+
+/* Print a sequence of chars in printable format, stopping at the end of the
+subject if the requested.
+
+Arguments:
+ p points to characters
+ length number to print
+ is_subject TRUE if printing from within md->start_subject
+ md pointer to matching data block, if is_subject is TRUE
+
+Returns: nothing
+*/
+
+static void
+pchars(const uschar *p, int length, BOOL is_subject, match_data *md)
+{
+int c;
+if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
+while (length-- > 0)
+ if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c);
+}
+#endif
+
+
+
+
+/*************************************************
+* Handle escapes *
+*************************************************/
+
+/* This function is called when a \ has been encountered. It either returns a
+positive value for a simple escape such as \n, or a negative value which
+encodes one of the more complicated things such as \d. When UTF-8 is enabled,
+a positive value greater than 255 may be returned. On entry, ptr is pointing at
+the \. On exit, it is on the final character of the escape sequence.
+
+Arguments:
+ ptrptr points to the pattern position pointer
+ errorptr points to the pointer to the error message
+ bracount number of previous extracting brackets
+ options the options bits
+ isclass TRUE if inside a character class
+ cd pointer to char tables block
+
+Returns: zero or positive => a data character
+ negative => a special escape sequence
+ on error, errorptr is set
+*/
+
+static int
+check_escape(const uschar **ptrptr, const char **errorptr, int bracount,
+ int options, BOOL isclass, compile_data *cd)
+{
+const uschar *ptr = *ptrptr;
+int c, i;
+
+/* If backslash is at the end of the pattern, it's an error. */
+
+c = *(++ptr);
+if (c == 0) *errorptr = ERR1;
+
+/* Digits or letters may have special meaning; all others are literals. */
+
+else if (c < '0' || c > 'z') {}
+
+/* Do an initial lookup in a table. A non-zero result is something that can be
+returned immediately. Otherwise further processing may be required. */
+
+else if ((i = escapes[c - '0']) != 0) c = i;
+
+/* Escapes that need further processing, or are illegal. */
+
+else
+ {
+ const uschar *oldptr;
+ switch (c)
+ {
+ /* The handling of escape sequences consisting of a string of digits
+ starting with one that is not zero is not straightforward. By experiment,
+ the way Perl works seems to be as follows:
+
+ Outside a character class, the digits are read as a decimal number. If the
+ number is less than 10, or if there are that many previous extracting
+ left brackets, then it is a back reference. Otherwise, up to three octal
+ digits are read to form an escaped byte. Thus \123 is likely to be octal
+ 123 (cf \0123, which is octal 012 followed by the literal 3). If the octal
+ value is greater than 377, the least significant 8 bits are taken. Inside a
+ character class, \ followed by a digit is always an octal number. */
+
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+
+ if (!isclass)
+ {
+ oldptr = ptr;
+ c -= '0';
+ while ((cd->ctypes[ptr[1]] & ctype_digit) != 0)
+ c = c * 10 + *(++ptr) - '0';
+ if (c < 10 || c <= bracount)
+ {
+ c = -(ESC_REF + c);
+ break;
+ }
+ ptr = oldptr; /* Put the pointer back and fall through */
+ }
+
+ /* Handle an octal number following \. If the first digit is 8 or 9, Perl
+ generates a binary zero byte and treats the digit as a following literal.
+ Thus we have to pull back the pointer by one. */
+
+ if ((c = *ptr) >= '8')
+ {
+ ptr--;
+ c = 0;
+ break;
+ }
+
+ /* \0 always starts an octal number, but we may drop through to here with a
+ larger first octal digit. */
+
+ case '0':
+ c -= '0';
+ while(i++ < 2 && (cd->ctypes[ptr[1]] & ctype_digit) != 0 &&
+ ptr[1] != '8' && ptr[1] != '9')
+ c = c * 8 + *(++ptr) - '0';
+ c &= 255; /* Take least significant 8 bits */
+ break;
+
+ /* \x is complicated when UTF-8 is enabled. \x{ddd} is a character number
+ which can be greater than 0xff, but only if the ddd are hex digits. */
+
+ case 'x':
+#ifdef SUPPORT_UTF8
+ if (ptr[1] == '{' && (options & PCRE_UTF8) != 0)
+ {
+ const uschar *pt = ptr + 2;
+ register int count = 0;
+ c = 0;
+ while ((cd->ctypes[*pt] & ctype_xdigit) != 0)
+ {
+ count++;
+ c = c * 16 + cd->lcc[*pt] -
+ (((cd->ctypes[*pt] & ctype_digit) != 0)? '0' : 'W');
+ pt++;
+ }
+ if (*pt == '}')
+ {
+ if (c < 0 || count > 8) *errorptr = ERR34;
+ ptr = pt;
+ break;
+ }
+ /* If the sequence of hex digits does not end with '}', then we don't
+ recognize this construct; fall through to the normal \x handling. */
+ }
+#endif
+
+ /* Read just a single hex char */
+
+ c = 0;
+ while (i++ < 2 && (cd->ctypes[ptr[1]] & ctype_xdigit) != 0)
+ {
+ ptr++;
+ c = c * 16 + cd->lcc[*ptr] -
+ (((cd->ctypes[*ptr] & ctype_digit) != 0)? '0' : 'W');
+ }
+ break;
+
+ /* Other special escapes not starting with a digit are straightforward */
+
+ case 'c':
+ c = *(++ptr);
+ if (c == 0)
+ {
+ *errorptr = ERR2;
+ return 0;
+ }
+
+ /* A letter is upper-cased; then the 0x40 bit is flipped */
+
+ if (c >= 'a' && c <= 'z') c = cd->fcc[c];
+ c ^= 0x40;
+ break;
+
+ /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any
+ other alphameric following \ is an error if PCRE_EXTRA was set; otherwise,
+ for Perl compatibility, it is a literal. This code looks a bit odd, but
+ there used to be some cases other than the default, and there may be again
+ in future, so I haven't "optimized" it. */
+
+ default:
+ if ((options & PCRE_EXTRA) != 0) switch(c)
+ {
+ default:
+ *errorptr = ERR3;
+ break;
+ }
+ break;
+ }
+ }
+
+*ptrptr = ptr;
+return c;
+}
+
+
+
+/*************************************************
+* Check for counted repeat *
+*************************************************/
+
+/* This function is called when a '{' is encountered in a place where it might
+start a quantifier. It looks ahead to see if it really is a quantifier or not.
+It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd}
+where the ddds are digits.
+
+Arguments:
+ p pointer to the first char after '{'
+ cd pointer to char tables block
+
+Returns: TRUE or FALSE
+*/
+
+static BOOL
+is_counted_repeat(const uschar *p, compile_data *cd)
+{
+if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE;
+while ((cd->ctypes[*p] & ctype_digit) != 0) p++;
+if (*p == '}') return TRUE;
+
+if (*p++ != ',') return FALSE;
+if (*p == '}') return TRUE;
+
+if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE;
+while ((cd->ctypes[*p] & ctype_digit) != 0) p++;
+return (*p == '}');
+}
+
+
+
+/*************************************************
+* Read repeat counts *
+*************************************************/
+
+/* Read an item of the form {n,m} and return the values. This is called only
+after is_counted_repeat() has confirmed that a repeat-count quantifier exists,
+so the syntax is guaranteed to be correct, but we need to check the values.
+
+Arguments:
+ p pointer to first char after '{'
+ minp pointer to int for min
+ maxp pointer to int for max
+ returned as -1 if no max
+ errorptr points to pointer to error message
+ cd pointer to character tables clock
+
+Returns: pointer to '}' on success;
+ current ptr on error, with errorptr set
+*/
+
+static const uschar *
+read_repeat_counts(const uschar *p, int *minp, int *maxp,
+ const char **errorptr, compile_data *cd)
+{
+int min = 0;
+int max = -1;
+
+while ((cd->ctypes[*p] & ctype_digit) != 0) min = min * 10 + *p++ - '0';
+
+if (*p == '}') max = min; else
+ {
+ if (*(++p) != '}')
+ {
+ max = 0;
+ while((cd->ctypes[*p] & ctype_digit) != 0) max = max * 10 + *p++ - '0';
+ if (max < min)
+ {
+ *errorptr = ERR4;
+ return p;
+ }
+ }
+ }
+
+/* Do paranoid checks, then fill in the required variables, and pass back the
+pointer to the terminating '}'. */
+
+if (min > 65535 || max > 65535)
+ *errorptr = ERR5;
+else
+ {
+ *minp = min;
+ *maxp = max;
+ }
+return p;
+}
+
+
+
+/*************************************************
+* Find the fixed length of a pattern *
+*************************************************/
+
+/* Scan a pattern and compute the fixed length of subject that will match it,
+if the length is fixed. This is needed for dealing with backward assertions.
+
+Arguments:
+ code points to the start of the pattern (the bracket)
+ options the compiling options
+
+Returns: the fixed length, or -1 if there is no fixed length
+*/
+
+static int
+find_fixedlength(uschar *code, int options)
+{
+int length = -1;
+
+register int branchlength = 0;
+register uschar *cc = code + 3;
+
+/* Scan along the opcodes for this branch. If we get to the end of the
+branch, check the length against that of the other branches. */
+
+for (;;)
+ {
+ int d;
+ register int op = *cc;
+ if (op >= OP_BRA) op = OP_BRA;
+
+ switch (op)
+ {
+ case OP_BRA:
+ case OP_ONCE:
+ case OP_COND:
+ d = find_fixedlength(cc, options);
+ if (d < 0) return -1;
+ branchlength += d;
+ do cc += (cc[1] << 8) + cc[2]; while (*cc == OP_ALT);
+ cc += 3;
+ break;
+
+ /* Reached end of a branch; if it's a ket it is the end of a nested
+ call. If it's ALT it is an alternation in a nested call. If it is
+ END it's the end of the outer call. All can be handled by the same code. */
+
+ case OP_ALT:
+ case OP_KET:
+ case OP_KETRMAX:
+ case OP_KETRMIN:
+ case OP_END:
+ if (length < 0) length = branchlength;
+ else if (length != branchlength) return -1;
+ if (*cc != OP_ALT) return length;
+ cc += 3;
+ branchlength = 0;
+ break;
+
+ /* Skip over assertive subpatterns */
+
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ do cc += (cc[1] << 8) + cc[2]; while (*cc == OP_ALT);
+ cc += 3;
+ break;
+
+ /* Skip over things that don't match chars */
+
+ case OP_REVERSE:
+ cc++;
+ /* Fall through */
+
+ case OP_CREF:
+ case OP_OPT:
+ cc++;
+ /* Fall through */
+
+ case OP_SOD:
+ case OP_EOD:
+ case OP_EODN:
+ case OP_CIRC:
+ case OP_DOLL:
+ case OP_NOT_WORD_BOUNDARY:
+ case OP_WORD_BOUNDARY:
+ cc++;
+ break;
+
+ /* Handle char strings. In UTF-8 mode we must count characters, not bytes.
+ This requires a scan of the string, unfortunately. We assume valid UTF-8
+ strings, so all we do is reduce the length by one for byte whose bits are
+ 10xxxxxx. */
+
+ case OP_CHARS:
+ branchlength += *(++cc);
+#ifdef SUPPORT_UTF8
+ for (d = 1; d <= *cc; d++)
+ if ((cc[d] & 0xc0) == 0x80) branchlength--;
+#endif
+ cc += *cc + 1;
+ break;
+
+ /* Handle exact repetitions */
+
+ case OP_EXACT:
+ case OP_TYPEEXACT:
+ branchlength += (cc[1] << 8) + cc[2];
+ cc += 4;
+ break;
+
+ /* Handle single-char matchers */
+
+ case OP_NOT_DIGIT:
+ case OP_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_WORDCHAR:
+ case OP_ANY:
+ branchlength++;
+ cc++;
+ break;
+
+
+ /* Check a class for variable quantification */
+
+ case OP_CLASS:
+ cc += (*cc == OP_REF)? 2 : 33;
+
+ switch (*cc)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ return -1;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ if ((cc[1] << 8) + cc[2] != (cc[3] << 8) + cc[4]) return -1;
+ branchlength += (cc[1] << 8) + cc[2];
+ cc += 5;
+ break;
+
+ default:
+ branchlength++;
+ }
+ break;
+
+ /* Anything else is variable length */
+
+ default:
+ return -1;
+ }
+ }
+/* Control never gets here */
+}
+
+
+
+
+/*************************************************
+* Check for POSIX class syntax *
+*************************************************/
+
+/* This function is called when the sequence "[:" or "[." or "[=" is
+encountered in a character class. It checks whether this is followed by an
+optional ^ and then a sequence of letters, terminated by a matching ":]" or
+".]" or "=]".
+
+Argument:
+ ptr pointer to the initial [
+ endptr where to return the end pointer
+ cd pointer to compile data
+
+Returns: TRUE or FALSE
+*/
+
+static BOOL
+check_posix_syntax(const uschar *ptr, const uschar **endptr, compile_data *cd)
+{
+int terminator; /* Don't combine these lines; the Solaris cc */
+terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */
+if (*(++ptr) == '^') ptr++;
+while ((cd->ctypes[*ptr] & ctype_letter) != 0) ptr++;
+if (*ptr == terminator && ptr[1] == ']')
+ {
+ *endptr = ptr;
+ return TRUE;
+ }
+return FALSE;
+}
+
+
+
+
+/*************************************************
+* Check POSIX class name *
+*************************************************/
+
+/* This function is called to check the name given in a POSIX-style class entry
+such as [:alnum:].
+
+Arguments:
+ ptr points to the first letter
+ len the length of the name
+
+Returns: a value representing the name, or -1 if unknown
+*/
+
+static int
+check_posix_name(const uschar *ptr, int len)
+{
+register int yield = 0;
+while (posix_name_lengths[yield] != 0)
+ {
+ if (len == posix_name_lengths[yield] &&
+ strncmp((const char *)ptr, posix_names[yield], len) == 0) return yield;
+ yield++;
+ }
+return -1;
+}
+
+
+
+
+/*************************************************
+* Compile one branch *
+*************************************************/
+
+/* Scan the pattern, compiling it into the code vector.
+
+Arguments:
+ options the option bits
+ brackets points to number of brackets used
+ code points to the pointer to the current code point
+ ptrptr points to the current pattern pointer
+ errorptr points to pointer to error message
+ optchanged set to the value of the last OP_OPT item compiled
+ reqchar set to the last literal character required, else -1
+ countlits set to count of mandatory literal characters
+ cd contains pointers to tables
+
+Returns: TRUE on success
+ FALSE, with *errorptr set on error
+*/
+
+static BOOL
+compile_branch(int options, int *brackets, uschar **codeptr,
+ const uschar **ptrptr, const char **errorptr, int *optchanged,
+ int *reqchar, int *countlits, compile_data *cd)
+{
+int repeat_type, op_type;
+int repeat_min, repeat_max;
+int bravalue, length;
+int greedy_default, greedy_non_default;
+int prevreqchar;
+int condcount = 0;
+int subcountlits = 0;
+register int c;
+register uschar *code = *codeptr;
+uschar *tempcode;
+const uschar *ptr = *ptrptr;
+const uschar *tempptr;
+uschar *previous = NULL;
+uschar class[32];
+
+/* Set up the default and non-default settings for greediness */
+
+greedy_default = ((options & PCRE_UNGREEDY) != 0);
+greedy_non_default = greedy_default ^ 1;
+
+/* Initialize no required char, and count of literals */
+
+*reqchar = prevreqchar = -1;
+*countlits = 0;
+
+/* Switch on next character until the end of the branch */
+
+for (;; ptr++)
+ {
+ BOOL negate_class;
+ int class_charcount;
+ int class_lastchar;
+ int newoptions;
+ int condref;
+ int subreqchar;
+
+ c = *ptr;
+ if ((options & PCRE_EXTENDED) != 0)
+ {
+ if ((cd->ctypes[c] & ctype_space) != 0) continue;
+ if (c == '#')
+ {
+ /* The space before the ; is to avoid a warning on a silly compiler
+ on the Macintosh. */
+ while ((c = *(++ptr)) != 0 && c != '\n') ;
+ continue;
+ }
+ }
+
+ switch(c)
+ {
+ /* The branch terminates at end of string, |, or ). */
+
+ case 0:
+ case '|':
+ case ')':
+ *codeptr = code;
+ *ptrptr = ptr;
+ return TRUE;
+
+ /* Handle single-character metacharacters */
+
+ case '^':
+ previous = NULL;
+ *code++ = OP_CIRC;
+ break;
+
+ case '$':
+ previous = NULL;
+ *code++ = OP_DOLL;
+ break;
+
+ case '.':
+ previous = code;
+ *code++ = OP_ANY;
+ break;
+
+ /* Character classes. These always build a 32-byte bitmap of the permitted
+ characters, except in the special case where there is only one character.
+ For negated classes, we build the map as usual, then invert it at the end.
+ */
+
+ case '[':
+ previous = code;
+ *code++ = OP_CLASS;
+
+ /* If the first character is '^', set the negation flag and skip it. */
+
+ if ((c = *(++ptr)) == '^')
+ {
+ negate_class = TRUE;
+ c = *(++ptr);
+ }
+ else negate_class = FALSE;
+
+ /* Keep a count of chars so that we can optimize the case of just a single
+ character. */
+
+ class_charcount = 0;
+ class_lastchar = -1;
+
+ /* Initialize the 32-char bit map to all zeros. We have to build the
+ map in a temporary bit of store, in case the class contains only 1
+ character, because in that case the compiled code doesn't use the
+ bit map. */
+
+ memset(class, 0, 32 * sizeof(uschar));
+
+ /* Process characters until ] is reached. By writing this as a "do" it
+ means that an initial ] is taken as a data character. */
+
+ do
+ {
+ if (c == 0)
+ {
+ *errorptr = ERR6;
+ goto FAILED;
+ }
+
+ /* Handle POSIX class names. Perl allows a negation extension of the
+ form [:^name]. A square bracket that doesn't match the syntax is
+ treated as a literal. We also recognize the POSIX constructions
+ [.ch.] and [=ch=] ("collating elements") and fault them, as Perl
+ 5.6 does. */
+
+ if (c == '[' &&
+ (ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') &&
+ check_posix_syntax(ptr, &tempptr, cd))
+ {
+ BOOL local_negate = FALSE;
+ int posix_class, i;
+ register const uschar *cbits = cd->cbits;
+
+ if (ptr[1] != ':')
+ {
+ *errorptr = ERR31;
+ goto FAILED;
+ }
+
+ ptr += 2;
+ if (*ptr == '^')
+ {
+ local_negate = TRUE;
+ ptr++;
+ }
+
+ posix_class = check_posix_name(ptr, tempptr - ptr);
+ if (posix_class < 0)
+ {
+ *errorptr = ERR30;
+ goto FAILED;
+ }
+
+ /* If matching is caseless, upper and lower are converted to
+ alpha. This relies on the fact that the class table starts with
+ alpha, lower, upper as the first 3 entries. */
+
+ if ((options & PCRE_CASELESS) != 0 && posix_class <= 2)
+ posix_class = 0;
+
+ /* Or into the map we are building up to 3 of the static class
+ tables, or their negations. */
+
+ posix_class *= 3;
+ for (i = 0; i < 3; i++)
+ {
+ int taboffset = posix_class_maps[posix_class + i];
+ if (taboffset < 0) break;
+ if (local_negate)
+ for (c = 0; c < 32; c++) class[c] |= ~cbits[c+taboffset];
+ else
+ for (c = 0; c < 32; c++) class[c] |= cbits[c+taboffset];
+ }
+
+ ptr = tempptr + 1;
+ class_charcount = 10; /* Set > 1; assumes more than 1 per class */
+ continue;
+ }
+
+ /* Backslash may introduce a single character, or it may introduce one
+ of the specials, which just set a flag. Escaped items are checked for
+ validity in the pre-compiling pass. The sequence \b is a special case.
+ Inside a class (and only there) it is treated as backspace. Elsewhere
+ it marks a word boundary. Other escapes have preset maps ready to
+ or into the one we are building. We assume they have more than one
+ character in them, so set class_count bigger than one. */
+
+ if (c == '\\')
+ {
+ c = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd);
+ if (-c == ESC_b) c = '\b';
+ else if (c < 0)
+ {
+ register const uschar *cbits = cd->cbits;
+ class_charcount = 10;
+ switch (-c)
+ {
+ case ESC_d:
+ for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_digit];
+ continue;
+
+ case ESC_D:
+ for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_digit];
+ continue;
+
+ case ESC_w:
+ for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_word];
+ continue;
+
+ case ESC_W:
+ for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_word];
+ continue;
+
+ case ESC_s:
+ for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_space];
+ continue;
+
+ case ESC_S:
+ for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_space];
+ continue;
+
+ default:
+ *errorptr = ERR7;
+ goto FAILED;
+ }
+ }
+
+ /* Fall through if single character, but don't at present allow
+ chars > 255 in UTF-8 mode. */
+
+#ifdef SUPPORT_UTF8
+ if (c > 255)
+ {
+ *errorptr = ERR33;
+ goto FAILED;
+ }
+#endif
+ }
+
+ /* A single character may be followed by '-' to form a range. However,
+ Perl does not permit ']' to be the end of the range. A '-' character
+ here is treated as a literal. */
+
+ if (ptr[1] == '-' && ptr[2] != ']')
+ {
+ int d;
+ ptr += 2;
+ d = *ptr;
+
+ if (d == 0)
+ {
+ *errorptr = ERR6;
+ goto FAILED;
+ }
+
+ /* The second part of a range can be a single-character escape, but
+ not any of the other escapes. Perl 5.6 treats a hyphen as a literal
+ in such circumstances. */
+
+ if (d == '\\')
+ {
+ const uschar *oldptr = ptr;
+ d = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd);
+
+#ifdef SUPPORT_UTF8
+ if (d > 255)
+ {
+ *errorptr = ERR33;
+ goto FAILED;
+ }
+#endif
+ /* \b is backslash; any other special means the '-' was literal */
+
+ if (d < 0)
+ {
+ if (d == -ESC_b) d = '\b'; else
+ {
+ ptr = oldptr - 2;
+ goto SINGLE_CHARACTER; /* A few lines below */
+ }
+ }
+ }
+
+ if (d < c)
+ {
+ *errorptr = ERR8;
+ goto FAILED;
+ }
+
+ for (; c <= d; c++)
+ {
+ class[c/8] |= (1 << (c&7));
+ if ((options & PCRE_CASELESS) != 0)
+ {
+ int uc = cd->fcc[c]; /* flip case */
+ class[uc/8] |= (1 << (uc&7));
+ }
+ class_charcount++; /* in case a one-char range */
+ class_lastchar = c;
+ }
+ continue; /* Go get the next char in the class */
+ }
+
+ /* Handle a lone single character - we can get here for a normal
+ non-escape char, or after \ that introduces a single character. */
+
+ SINGLE_CHARACTER:
+
+ class [c/8] |= (1 << (c&7));
+ if ((options & PCRE_CASELESS) != 0)
+ {
+ c = cd->fcc[c]; /* flip case */
+ class[c/8] |= (1 << (c&7));
+ }
+ class_charcount++;
+ class_lastchar = c;
+ }
+
+ /* Loop until ']' reached; the check for end of string happens inside the
+ loop. This "while" is the end of the "do" above. */
+
+ while ((c = *(++ptr)) != ']');
+
+ /* If class_charcount is 1 and class_lastchar is not negative, we saw
+ precisely one character. This doesn't need the whole 32-byte bit map.
+ We turn it into a 1-character OP_CHAR if it's positive, or OP_NOT if
+ it's negative. */
+
+ if (class_charcount == 1 && class_lastchar >= 0)
+ {
+ if (negate_class)
+ {
+ code[-1] = OP_NOT;
+ }
+ else
+ {
+ code[-1] = OP_CHARS;
+ *code++ = 1;
+ }
+ *code++ = class_lastchar;
+ }
+
+ /* Otherwise, negate the 32-byte map if necessary, and copy it into
+ the code vector. */
+
+ else
+ {
+ if (negate_class)
+ for (c = 0; c < 32; c++) code[c] = ~class[c];
+ else
+ memcpy(code, class, 32);
+ code += 32;
+ }
+ break;
+
+ /* Various kinds of repeat */
+
+ case '{':
+ if (!is_counted_repeat(ptr+1, cd)) goto NORMAL_CHAR;
+ ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorptr, cd);
+ if (*errorptr != NULL) goto FAILED;
+ goto REPEAT;
+
+ case '*':
+ repeat_min = 0;
+ repeat_max = -1;
+ goto REPEAT;
+
+ case '+':
+ repeat_min = 1;
+ repeat_max = -1;
+ goto REPEAT;
+
+ case '?':
+ repeat_min = 0;
+ repeat_max = 1;
+
+ REPEAT:
+ if (previous == NULL)
+ {
+ *errorptr = ERR9;
+ goto FAILED;
+ }
+
+ /* If the next character is '?' this is a minimizing repeat, by default,
+ but if PCRE_UNGREEDY is set, it works the other way round. Advance to the
+ next character. */
+
+ if (ptr[1] == '?')
+ { repeat_type = greedy_non_default; ptr++; }
+ else repeat_type = greedy_default;
+
+ /* If previous was a string of characters, chop off the last one and use it
+ as the subject of the repeat. If there was only one character, we can
+ abolish the previous item altogether. A repeat with a zero minimum wipes
+ out any reqchar setting, backing up to the previous value. We must also
+ adjust the countlits value. */
+
+ if (*previous == OP_CHARS)
+ {
+ int len = previous[1];
+
+ if (repeat_min == 0) *reqchar = prevreqchar;
+ *countlits += repeat_min - 1;
+
+ if (len == 1)
+ {
+ c = previous[2];
+ code = previous;
+ }
+ else
+ {
+ c = previous[len+1];
+ previous[1]--;
+ code--;
+ }
+ op_type = 0; /* Use single-char op codes */
+ goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */
+ }
+
+ /* If previous was a single negated character ([^a] or similar), we use
+ one of the special opcodes, replacing it. The code is shared with single-
+ character repeats by adding a suitable offset into repeat_type. */
+
+ else if ((int)*previous == OP_NOT)
+ {
+ op_type = OP_NOTSTAR - OP_STAR; /* Use "not" opcodes */
+ c = previous[1];
+ code = previous;
+ goto OUTPUT_SINGLE_REPEAT;
+ }
+
+ /* If previous was a character type match (\d or similar), abolish it and
+ create a suitable repeat item. The code is shared with single-character
+ repeats by adding a suitable offset into repeat_type. */
+
+ else if ((int)*previous < OP_EODN || *previous == OP_ANY)
+ {
+ op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */
+ c = *previous;
+ code = previous;
+
+ OUTPUT_SINGLE_REPEAT:
+
+ /* If the maximum is zero then the minimum must also be zero; Perl allows
+ this case, so we do too - by simply omitting the item altogether. */
+
+ if (repeat_max == 0) goto END_REPEAT;
+
+ /* Combine the op_type with the repeat_type */
+
+ repeat_type += op_type;
+
+ /* A minimum of zero is handled either as the special case * or ?, or as
+ an UPTO, with the maximum given. */
+
+ if (repeat_min == 0)
+ {
+ if (repeat_max == -1) *code++ = OP_STAR + repeat_type;
+ else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;
+ else
+ {
+ *code++ = OP_UPTO + repeat_type;
+ *code++ = repeat_max >> 8;
+ *code++ = (repeat_max & 255);
+ }
+ }
+
+ /* The case {1,} is handled as the special case + */
+
+ else if (repeat_min == 1 && repeat_max == -1)
+ *code++ = OP_PLUS + repeat_type;
+
+ /* The case {n,n} is just an EXACT, while the general case {n,m} is
+ handled as an EXACT followed by an UPTO. An EXACT of 1 is optimized. */
+
+ else
+ {
+ if (repeat_min != 1)
+ {
+ *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */
+ *code++ = repeat_min >> 8;
+ *code++ = (repeat_min & 255);
+ }
+
+ /* If the mininum is 1 and the previous item was a character string,
+ we either have to put back the item that got cancelled if the string
+ length was 1, or add the character back onto the end of a longer
+ string. For a character type nothing need be done; it will just get
+ put back naturally. Note that the final character is always going to
+ get added below. */
+
+ else if (*previous == OP_CHARS)
+ {
+ if (code == previous) code += 2; else previous[1]++;
+ }
+
+ /* For a single negated character we also have to put back the
+ item that got cancelled. */
+
+ else if (*previous == OP_NOT) code++;
+
+ /* If the maximum is unlimited, insert an OP_STAR. */
+
+ if (repeat_max < 0)
+ {
+ *code++ = c;
+ *code++ = OP_STAR + repeat_type;
+ }
+
+ /* Else insert an UPTO if the max is greater than the min. */
+
+ else if (repeat_max != repeat_min)
+ {
+ *code++ = c;
+ repeat_max -= repeat_min;
+ *code++ = OP_UPTO + repeat_type;
+ *code++ = repeat_max >> 8;
+ *code++ = (repeat_max & 255);
+ }
+ }
+
+ /* The character or character type itself comes last in all cases. */
+
+ *code++ = c;
+ }
+
+ /* If previous was a character class or a back reference, we put the repeat
+ stuff after it, but just skip the item if the repeat was {0,0}. */
+
+ else if (*previous == OP_CLASS || *previous == OP_REF)
+ {
+ if (repeat_max == 0)
+ {
+ code = previous;
+ goto END_REPEAT;
+ }
+ if (repeat_min == 0 && repeat_max == -1)
+ *code++ = OP_CRSTAR + repeat_type;
+ else if (repeat_min == 1 && repeat_max == -1)
+ *code++ = OP_CRPLUS + repeat_type;
+ else if (repeat_min == 0 && repeat_max == 1)
+ *code++ = OP_CRQUERY + repeat_type;
+ else
+ {
+ *code++ = OP_CRRANGE + repeat_type;
+ *code++ = repeat_min >> 8;
+ *code++ = repeat_min & 255;
+ if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */
+ *code++ = repeat_max >> 8;
+ *code++ = repeat_max & 255;
+ }
+ }
+
+ /* If previous was a bracket group, we may have to replicate it in certain
+ cases. */
+
+ else if ((int)*previous >= OP_BRA || (int)*previous == OP_ONCE ||
+ (int)*previous == OP_COND)
+ {
+ register int i;
+ int ketoffset = 0;
+ int len = code - previous;
+ uschar *bralink = NULL;
+
+ /* If the maximum repeat count is unlimited, find the end of the bracket
+ by scanning through from the start, and compute the offset back to it
+ from the current code pointer. There may be an OP_OPT setting following
+ the final KET, so we can't find the end just by going back from the code
+ pointer. */
+
+ if (repeat_max == -1)
+ {
+ register uschar *ket = previous;
+ do ket += (ket[1] << 8) + ket[2]; while (*ket != OP_KET);
+ ketoffset = code - ket;
+ }
+
+ /* The case of a zero minimum is special because of the need to stick
+ OP_BRAZERO in front of it, and because the group appears once in the
+ data, whereas in other cases it appears the minimum number of times. For
+ this reason, it is simplest to treat this case separately, as otherwise
+ the code gets far too mess. There are several special subcases when the
+ minimum is zero. */
+
+ if (repeat_min == 0)
+ {
+ /* If we set up a required char from the bracket, we must back off
+ to the previous value and reset the countlits value too. */
+
+ if (subcountlits > 0)
+ {
+ *reqchar = prevreqchar;
+ *countlits -= subcountlits;
+ }
+
+ /* If the maximum is also zero, we just omit the group from the output
+ altogether. */
+
+ if (repeat_max == 0)
+ {
+ code = previous;
+ goto END_REPEAT;
+ }
+
+ /* If the maximum is 1 or unlimited, we just have to stick in the
+ BRAZERO and do no more at this point. */
+
+ if (repeat_max <= 1)
+ {
+ memmove(previous+1, previous, len);
+ code++;
+ *previous++ = OP_BRAZERO + repeat_type;
+ }
+
+ /* If the maximum is greater than 1 and limited, we have to replicate
+ in a nested fashion, sticking OP_BRAZERO before each set of brackets.
+ The first one has to be handled carefully because it's the original
+ copy, which has to be moved up. The remainder can be handled by code
+ that is common with the non-zero minimum case below. We just have to
+ adjust the value or repeat_max, since one less copy is required. */
+
+ else
+ {
+ int offset;
+ memmove(previous+4, previous, len);
+ code += 4;
+ *previous++ = OP_BRAZERO + repeat_type;
+ *previous++ = OP_BRA;
+
+ /* We chain together the bracket offset fields that have to be
+ filled in later when the ends of the brackets are reached. */
+
+ offset = (bralink == NULL)? 0 : previous - bralink;
+ bralink = previous;
+ *previous++ = offset >> 8;
+ *previous++ = offset & 255;
+ }
+
+ repeat_max--;
+ }
+
+ /* If the minimum is greater than zero, replicate the group as many
+ times as necessary, and adjust the maximum to the number of subsequent
+ copies that we need. */
+
+ else
+ {
+ for (i = 1; i < repeat_min; i++)
+ {
+ memcpy(code, previous, len);
+ code += len;
+ }
+ if (repeat_max > 0) repeat_max -= repeat_min;
+ }
+
+ /* This code is common to both the zero and non-zero minimum cases. If
+ the maximum is limited, it replicates the group in a nested fashion,
+ remembering the bracket starts on a stack. In the case of a zero minimum,
+ the first one was set up above. In all cases the repeat_max now specifies
+ the number of additional copies needed. */
+
+ if (repeat_max >= 0)
+ {
+ for (i = repeat_max - 1; i >= 0; i--)
+ {
+ *code++ = OP_BRAZERO + repeat_type;
+
+ /* All but the final copy start a new nesting, maintaining the
+ chain of brackets outstanding. */
+
+ if (i != 0)
+ {
+ int offset;
+ *code++ = OP_BRA;
+ offset = (bralink == NULL)? 0 : code - bralink;
+ bralink = code;
+ *code++ = offset >> 8;
+ *code++ = offset & 255;
+ }
+
+ memcpy(code, previous, len);
+ code += len;
+ }
+
+ /* Now chain through the pending brackets, and fill in their length
+ fields (which are holding the chain links pro tem). */
+
+ while (bralink != NULL)
+ {
+ int oldlinkoffset;
+ int offset = code - bralink + 1;
+ uschar *bra = code - offset;
+ oldlinkoffset = (bra[1] << 8) + bra[2];
+ bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;
+ *code++ = OP_KET;
+ *code++ = bra[1] = offset >> 8;
+ *code++ = bra[2] = (offset & 255);
+ }
+ }
+
+ /* If the maximum is unlimited, set a repeater in the final copy. We
+ can't just offset backwards from the current code point, because we
+ don't know if there's been an options resetting after the ket. The
+ correct offset was computed above. */
+
+ else code[-ketoffset] = OP_KETRMAX + repeat_type;
+ }
+
+ /* Else there's some kind of shambles */
+
+ else
+ {
+ *errorptr = ERR11;
+ goto FAILED;
+ }
+
+ /* In all case we no longer have a previous item. */
+
+ END_REPEAT:
+ previous = NULL;
+ break;
+
+
+ /* Start of nested bracket sub-expression, or comment or lookahead or
+ lookbehind or option setting or condition. First deal with special things
+ that can come after a bracket; all are introduced by ?, and the appearance
+ of any of them means that this is not a referencing group. They were
+ checked for validity in the first pass over the string, so we don't have to
+ check for syntax errors here. */
+
+ case '(':
+ newoptions = options;
+ condref = -1;
+
+ if (*(++ptr) == '?')
+ {
+ int set, unset;
+ int *optset;
+
+ switch (*(++ptr))
+ {
+ case '#': /* Comment; skip to ket */
+ ptr++;
+ while (*ptr != ')') ptr++;
+ continue;
+
+ case ':': /* Non-extracting bracket */
+ bravalue = OP_BRA;
+ ptr++;
+ break;
+
+ case '(':
+ bravalue = OP_COND; /* Conditional group */
+ if ((cd->ctypes[*(++ptr)] & ctype_digit) != 0)
+ {
+ condref = *ptr - '0';
+ while (*(++ptr) != ')') condref = condref*10 + *ptr - '0';
+ if (condref == 0)
+ {
+ *errorptr = ERR35;
+ goto FAILED;
+ }
+ ptr++;
+ }
+ else ptr--;
+ break;
+
+ case '=': /* Positive lookahead */
+ bravalue = OP_ASSERT;
+ ptr++;
+ break;
+
+ case '!': /* Negative lookahead */
+ bravalue = OP_ASSERT_NOT;
+ ptr++;
+ break;
+
+ case '<': /* Lookbehinds */
+ switch (*(++ptr))
+ {
+ case '=': /* Positive lookbehind */
+ bravalue = OP_ASSERTBACK;
+ ptr++;
+ break;
+
+ case '!': /* Negative lookbehind */
+ bravalue = OP_ASSERTBACK_NOT;
+ ptr++;
+ break;
+
+ default: /* Syntax error */
+ *errorptr = ERR24;
+ goto FAILED;
+ }
+ break;
+
+ case '>': /* One-time brackets */
+ bravalue = OP_ONCE;
+ ptr++;
+ break;
+
+ case 'R': /* Pattern recursion */
+ *code++ = OP_RECURSE;
+ ptr++;
+ continue;
+
+ default: /* Option setting */
+ set = unset = 0;
+ optset = &set;
+
+ while (*ptr != ')' && *ptr != ':')
+ {
+ switch (*ptr++)
+ {
+ case '-': optset = &unset; break;
+
+ case 'i': *optset |= PCRE_CASELESS; break;
+ case 'm': *optset |= PCRE_MULTILINE; break;
+ case 's': *optset |= PCRE_DOTALL; break;
+ case 'x': *optset |= PCRE_EXTENDED; break;
+ case 'U': *optset |= PCRE_UNGREEDY; break;
+ case 'X': *optset |= PCRE_EXTRA; break;
+
+ default:
+ *errorptr = ERR12;
+ goto FAILED;
+ }
+ }
+
+ /* Set up the changed option bits, but don't change anything yet. */
+
+ newoptions = (options | set) & (~unset);
+
+ /* If the options ended with ')' this is not the start of a nested
+ group with option changes, so the options change at this level. At top
+ level there is nothing else to be done (the options will in fact have
+ been set from the start of compiling as a result of the first pass) but
+ at an inner level we must compile code to change the ims options if
+ necessary, and pass the new setting back so that it can be put at the
+ start of any following branches, and when this group ends, a resetting
+ item can be compiled. */
+
+ if (*ptr == ')')
+ {
+ if ((options & PCRE_INGROUP) != 0 &&
+ (options & PCRE_IMS) != (newoptions & PCRE_IMS))
+ {
+ *code++ = OP_OPT;
+ *code++ = *optchanged = newoptions & PCRE_IMS;
+ }
+ options = newoptions; /* Change options at this level */
+ previous = NULL; /* This item can't be repeated */
+ continue; /* It is complete */
+ }
+
+ /* If the options ended with ':' we are heading into a nested group
+ with possible change of options. Such groups are non-capturing and are
+ not assertions of any kind. All we need to do is skip over the ':';
+ the newoptions value is handled below. */
+
+ bravalue = OP_BRA;
+ ptr++;
+ }
+ }
+
+ /* Else we have a referencing group; adjust the opcode. */
+
+ else
+ {
+ if (++(*brackets) > EXTRACT_MAX)
+ {
+ *errorptr = ERR13;
+ goto FAILED;
+ }
+ bravalue = OP_BRA + *brackets;
+ }
+
+ /* Process nested bracketed re. Assertions may not be repeated, but other
+ kinds can be. We copy code into a non-register variable in order to be able
+ to pass its address because some compilers complain otherwise. Pass in a
+ new setting for the ims options if they have changed. */
+
+ previous = (bravalue >= OP_ONCE)? code : NULL;
+ *code = bravalue;
+ tempcode = code;
+
+ if (!compile_regex(
+ options | PCRE_INGROUP, /* Set for all nested groups */
+ ((options & PCRE_IMS) != (newoptions & PCRE_IMS))?
+ newoptions & PCRE_IMS : -1, /* Pass ims options if changed */
+ brackets, /* Bracket level */
+ &tempcode, /* Where to put code (updated) */
+ &ptr, /* Input pointer (updated) */
+ errorptr, /* Where to put an error message */
+ (bravalue == OP_ASSERTBACK ||
+ bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */
+ condref, /* Condition reference number */
+ &subreqchar, /* For possible last char */
+ &subcountlits, /* For literal count */
+ cd)) /* Tables block */
+ goto FAILED;
+
+ /* At the end of compiling, code is still pointing to the start of the
+ group, while tempcode has been updated to point past the end of the group
+ and any option resetting that may follow it. The pattern pointer (ptr)
+ is on the bracket. */
+
+ /* If this is a conditional bracket, check that there are no more than
+ two branches in the group. */
+
+ if (bravalue == OP_COND)
+ {
+ uschar *tc = code;
+ condcount = 0;
+
+ do {
+ condcount++;
+ tc += (tc[1] << 8) | tc[2];
+ }
+ while (*tc != OP_KET);
+
+ if (condcount > 2)
+ {
+ *errorptr = ERR27;
+ goto FAILED;
+ }
+ }
+
+ /* Handle updating of the required character. If the subpattern didn't
+ set one, leave it as it was. Otherwise, update it for normal brackets of
+ all kinds, forward assertions, and conditions with two branches. Don't
+ update the literal count for forward assertions, however. If the bracket
+ is followed by a quantifier with zero repeat, we have to back off. Hence
+ the definition of prevreqchar and subcountlits outside the main loop so
+ that they can be accessed for the back off. */
+
+ if (subreqchar > 0 &&
+ (bravalue >= OP_BRA || bravalue == OP_ONCE || bravalue == OP_ASSERT ||
+ (bravalue == OP_COND && condcount == 2)))
+ {
+ prevreqchar = *reqchar;
+ *reqchar = subreqchar;
+ if (bravalue != OP_ASSERT) *countlits += subcountlits;
+ }
+
+ /* Now update the main code pointer to the end of the group. */
+
+ code = tempcode;
+
+ /* Error if hit end of pattern */
+
+ if (*ptr != ')')
+ {
+ *errorptr = ERR14;
+ goto FAILED;
+ }
+ break;
+
+ /* Check \ for being a real metacharacter; if not, fall through and handle
+ it as a data character at the start of a string. Escape items are checked
+ for validity in the pre-compiling pass. */
+
+ case '\\':
+ tempptr = ptr;
+ c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd);
+
+ /* Handle metacharacters introduced by \. For ones like \d, the ESC_ values
+ are arranged to be the negation of the corresponding OP_values. For the
+ back references, the values are ESC_REF plus the reference number. Only
+ back references and those types that consume a character may be repeated.
+ We can test for values between ESC_b and ESC_Z for the latter; this may
+ have to change if any new ones are ever created. */
+
+ if (c < 0)
+ {
+ if (-c >= ESC_REF)
+ {
+ previous = code;
+ *code++ = OP_REF;
+ *code++ = -c - ESC_REF;
+ }
+ else
+ {
+ previous = (-c > ESC_b && -c < ESC_Z)? code : NULL;
+ *code++ = -c;
+ }
+ continue;
+ }
+
+ /* Data character: reset and fall through */
+
+ ptr = tempptr;
+ c = '\\';
+
+ /* Handle a run of data characters until a metacharacter is encountered.
+ The first character is guaranteed not to be whitespace or # when the
+ extended flag is set. */
+
+ NORMAL_CHAR:
+ default:
+ previous = code;
+ *code = OP_CHARS;
+ code += 2;
+ length = 0;
+
+ do
+ {
+ if ((options & PCRE_EXTENDED) != 0)
+ {
+ if ((cd->ctypes[c] & ctype_space) != 0) continue;
+ if (c == '#')
+ {
+ /* The space before the ; is to avoid a warning on a silly compiler
+ on the Macintosh. */
+ while ((c = *(++ptr)) != 0 && c != '\n') ;
+ if (c == 0) break;
+ continue;
+ }
+ }
+
+ /* Backslash may introduce a data char or a metacharacter. Escaped items
+ are checked for validity in the pre-compiling pass. Stop the string
+ before a metaitem. */
+
+ if (c == '\\')
+ {
+ tempptr = ptr;
+ c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd);
+ if (c < 0) { ptr = tempptr; break; }
+
+ /* If a character is > 127 in UTF-8 mode, we have to turn it into
+ two or more characters in the UTF-8 encoding. */
+
+#ifdef SUPPORT_UTF8
+ if (c > 127 && (options & PCRE_UTF8) != 0)
+ {
+ uschar buffer[8];
+ int len = ord2utf8(c, buffer);
+ for (c = 0; c < len; c++) *code++ = buffer[c];
+ length += len;
+ continue;
+ }
+#endif
+ }
+
+ /* Ordinary character or single-char escape */
+
+ *code++ = c;
+ length++;
+ }
+
+ /* This "while" is the end of the "do" above. */
+
+ while (length < MAXLIT && (cd->ctypes[c = *(++ptr)] & ctype_meta) == 0);
+
+ /* Update the last character and the count of literals */
+
+ prevreqchar = (length > 1)? code[-2] : *reqchar;
+ *reqchar = code[-1];
+ *countlits += length;
+
+ /* Compute the length and set it in the data vector, and advance to
+ the next state. */
+
+ previous[1] = length;
+ if (length < MAXLIT) ptr--;
+ break;
+ }
+ } /* end of big loop */
+
+/* Control never reaches here by falling through, only by a goto for all the
+error states. Pass back the position in the pattern so that it can be displayed
+to the user for diagnosing the error. */
+
+FAILED:
+*ptrptr = ptr;
+return FALSE;
+}
+
+
+
+
+/*************************************************
+* Compile sequence of alternatives *
+*************************************************/
+
+/* On entry, ptr is pointing past the bracket character, but on return
+it points to the closing bracket, or vertical bar, or end of string.
+The code variable is pointing at the byte into which the BRA operator has been
+stored. If the ims options are changed at the start (for a (?ims: group) or
+during any branch, we need to insert an OP_OPT item at the start of every
+following branch to ensure they get set correctly at run time, and also pass
+the new options into every subsequent branch compile.
+
+Argument:
+ options the option bits
+ optchanged new ims options to set as if (?ims) were at the start, or -1
+ for no change
+ brackets -> int containing the number of extracting brackets used
+ codeptr -> the address of the current code pointer
+ ptrptr -> the address of the current pattern pointer
+ errorptr -> pointer to error message
+ lookbehind TRUE if this is a lookbehind assertion
+ condref >= 0 for OPT_CREF setting at start of conditional group
+ reqchar -> place to put the last required character, or a negative number
+ countlits -> place to put the shortest literal count of any branch
+ cd points to the data block with tables pointers
+
+Returns: TRUE on success
+*/
+
+static BOOL
+compile_regex(int options, int optchanged, int *brackets, uschar **codeptr,
+ const uschar **ptrptr, const char **errorptr, BOOL lookbehind, int condref,
+ int *reqchar, int *countlits, compile_data *cd)
+{
+const uschar *ptr = *ptrptr;
+uschar *code = *codeptr;
+uschar *last_branch = code;
+uschar *start_bracket = code;
+uschar *reverse_count = NULL;
+int oldoptions = options & PCRE_IMS;
+int branchreqchar, branchcountlits;
+
+*reqchar = -1;
+*countlits = INT_MAX;
+code += 3;
+
+/* At the start of a reference-based conditional group, insert the reference
+number as an OP_CREF item. */
+
+if (condref >= 0)
+ {
+ *code++ = OP_CREF;
+ *code++ = condref;
+ }
+
+/* Loop for each alternative branch */
+
+for (;;)
+ {
+ int length;
+
+ /* Handle change of options */
+
+ if (optchanged >= 0)
+ {
+ *code++ = OP_OPT;
+ *code++ = optchanged;
+ options = (options & ~PCRE_IMS) | optchanged;
+ }
+
+ /* Set up dummy OP_REVERSE if lookbehind assertion */
+
+ if (lookbehind)
+ {
+ *code++ = OP_REVERSE;
+ reverse_count = code;
+ *code++ = 0;
+ *code++ = 0;
+ }
+
+ /* Now compile the branch */
+
+ if (!compile_branch(options, brackets, &code, &ptr, errorptr, &optchanged,
+ &branchreqchar, &branchcountlits, cd))
+ {
+ *ptrptr = ptr;
+ return FALSE;
+ }
+
+ /* Fill in the length of the last branch */
+
+ length = code - last_branch;
+ last_branch[1] = length >> 8;
+ last_branch[2] = length & 255;
+
+ /* Save the last required character if all branches have the same; a current
+ value of -1 means unset, while -2 means "previous branch had no last required
+ char". */
+
+ if (*reqchar != -2)
+ {
+ if (branchreqchar >= 0)
+ {
+ if (*reqchar == -1) *reqchar = branchreqchar;
+ else if (*reqchar != branchreqchar) *reqchar = -2;
+ }
+ else *reqchar = -2;
+ }
+
+ /* Keep the shortest literal count */
+
+ if (branchcountlits < *countlits) *countlits = branchcountlits;
+ DPRINTF(("literal count = %d min=%d\n", branchcountlits, *countlits));
+
+ /* If lookbehind, check that this branch matches a fixed-length string,
+ and put the length into the OP_REVERSE item. Temporarily mark the end of
+ the branch with OP_END. */
+
+ if (lookbehind)
+ {
+ *code = OP_END;
+ length = find_fixedlength(last_branch, options);
+ DPRINTF(("fixed length = %d\n", length));
+ if (length < 0)
+ {
+ *errorptr = ERR25;
+ *ptrptr = ptr;
+ return FALSE;
+ }
+ reverse_count[0] = (length >> 8);
+ reverse_count[1] = length & 255;
+ }
+
+ /* Reached end of expression, either ')' or end of pattern. Insert a
+ terminating ket and the length of the whole bracketed item, and return,
+ leaving the pointer at the terminating char. If any of the ims options
+ were changed inside the group, compile a resetting op-code following. */
+
+ if (*ptr != '|')
+ {
+ length = code - start_bracket;
+ *code++ = OP_KET;
+ *code++ = length >> 8;
+ *code++ = length & 255;
+ if (optchanged >= 0)
+ {
+ *code++ = OP_OPT;
+ *code++ = oldoptions;
+ }
+ *codeptr = code;
+ *ptrptr = ptr;
+ return TRUE;
+ }
+
+ /* Another branch follows; insert an "or" node and advance the pointer. */
+
+ *code = OP_ALT;
+ last_branch = code;
+ code += 3;
+ ptr++;
+ }
+/* Control never reaches here */
+}
+
+
+
+
+/*************************************************
+* Find first significant op code *
+*************************************************/
+
+/* This is called by several functions that scan a compiled expression looking
+for a fixed first character, or an anchoring op code etc. It skips over things
+that do not influence this. For one application, a change of caseless option is
+important.
+
+Arguments:
+ code pointer to the start of the group
+ options pointer to external options
+ optbit the option bit whose changing is significant, or
+ zero if none are
+ optstop TRUE to return on option change, otherwise change the options
+ value and continue
+
+Returns: pointer to the first significant opcode
+*/
+
+static const uschar*
+first_significant_code(const uschar *code, int *options, int optbit,
+ BOOL optstop)
+{
+for (;;)
+ {
+ switch ((int)*code)
+ {
+ case OP_OPT:
+ if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit))
+ {
+ if (optstop) return code;
+ *options = (int)code[1];
+ }
+ code += 2;
+ break;
+
+ case OP_CREF:
+ code += 2;
+ break;
+
+ case OP_WORD_BOUNDARY:
+ case OP_NOT_WORD_BOUNDARY:
+ code++;
+ break;
+
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ do code += (code[1] << 8) + code[2]; while (*code == OP_ALT);
+ code += 3;
+ break;
+
+ default:
+ return code;
+ }
+ }
+/* Control never reaches here */
+}
+
+
+
+
+/*************************************************
+* Check for anchored expression *
+*************************************************/
+
+/* Try to find out if this is an anchored regular expression. Consider each
+alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket
+all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then
+it's anchored. However, if this is a multiline pattern, then only OP_SOD
+counts, since OP_CIRC can match in the middle.
+
+A branch is also implicitly anchored if it starts with .* and DOTALL is set,
+because that will try the rest of the pattern at all possible matching points,
+so there is no point trying them again.
+
+Arguments:
+ code points to start of expression (the bracket)
+ options points to the options setting
+
+Returns: TRUE or FALSE
+*/
+
+static BOOL
+is_anchored(register const uschar *code, int *options)
+{
+do {
+ const uschar *scode = first_significant_code(code + 3, options,
+ PCRE_MULTILINE, FALSE);
+ register int op = *scode;
+ if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND)
+ { if (!is_anchored(scode, options)) return FALSE; }
+ else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR) &&
+ (*options & PCRE_DOTALL) != 0)
+ { if (scode[1] != OP_ANY) return FALSE; }
+ else if (op != OP_SOD &&
+ ((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC))
+ return FALSE;
+ code += (code[1] << 8) + code[2];
+ }
+while (*code == OP_ALT);
+return TRUE;
+}
+
+
+
+/*************************************************
+* Check for starting with ^ or .* *
+*************************************************/
+
+/* This is called to find out if every branch starts with ^ or .* so that
+"first char" processing can be done to speed things up in multiline
+matching and for non-DOTALL patterns that start with .* (which must start at
+the beginning or after \n).
+
+Argument: points to start of expression (the bracket)
+Returns: TRUE or FALSE
+*/
+
+static BOOL
+is_startline(const uschar *code)
+{
+do {
+ const uschar *scode = first_significant_code(code + 3, NULL, 0, FALSE);
+ register int op = *scode;
+ if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND)
+ { if (!is_startline(scode)) return FALSE; }
+ else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR)
+ { if (scode[1] != OP_ANY) return FALSE; }
+ else if (op != OP_CIRC) return FALSE;
+ code += (code[1] << 8) + code[2];
+ }
+while (*code == OP_ALT);
+return TRUE;
+}
+
+
+
+/*************************************************
+* Check for fixed first char *
+*************************************************/
+
+/* Try to find out if there is a fixed first character. This is called for
+unanchored expressions, as it speeds up their processing quite considerably.
+Consider each alternative branch. If they all start with the same char, or with
+a bracket all of whose alternatives start with the same char (recurse ad lib),
+then we return that char, otherwise -1.
+
+Arguments:
+ code points to start of expression (the bracket)
+ options pointer to the options (used to check casing changes)
+
+Returns: -1 or the fixed first char
+*/
+
+static int
+find_firstchar(const uschar *code, int *options)
+{
+register int c = -1;
+do {
+ int d;
+ const uschar *scode = first_significant_code(code + 3, options,
+ PCRE_CASELESS, TRUE);
+ register int op = *scode;
+
+ if (op >= OP_BRA) op = OP_BRA;
+
+ switch(op)
+ {
+ default:
+ return -1;
+
+ case OP_BRA:
+ case OP_ASSERT:
+ case OP_ONCE:
+ case OP_COND:
+ if ((d = find_firstchar(scode, options)) < 0) return -1;
+ if (c < 0) c = d; else if (c != d) return -1;
+ break;
+
+ case OP_EXACT: /* Fall through */
+ scode++;
+
+ case OP_CHARS: /* Fall through */
+ scode++;
+
+ case OP_PLUS:
+ case OP_MINPLUS:
+ if (c < 0) c = scode[1]; else if (c != scode[1]) return -1;
+ break;
+ }
+
+ code += (code[1] << 8) + code[2];
+ }
+while (*code == OP_ALT);
+return c;
+}
+
+
+
+
+
+/*************************************************
+* Compile a Regular Expression *
+*************************************************/
+
+/* This function takes a string and returns a pointer to a block of store
+holding a compiled version of the expression.
+
+Arguments:
+ pattern the regular expression
+ options various option bits
+ errorptr pointer to pointer to error text
+ erroroffset ptr offset in pattern where error was detected
+ tables pointer to character tables or NULL
+
+Returns: pointer to compiled data block, or NULL on error,
+ with errorptr and erroroffset set
+*/
+
+pcre *
+pcre_compile(const char *pattern, int options, const char **errorptr,
+ int *erroroffset, const unsigned char *tables)
+{
+real_pcre *re;
+int length = 3; /* For initial BRA plus length */
+int runlength;
+int c, reqchar, countlits;
+int bracount = 0;
+int top_backref = 0;
+int branch_extra = 0;
+int branch_newextra;
+unsigned int brastackptr = 0;
+size_t size;
+uschar *code;
+const uschar *ptr;
+compile_data compile_block;
+int brastack[BRASTACK_SIZE];
+uschar bralenstack[BRASTACK_SIZE];
+
+#ifdef DEBUG
+uschar *code_base, *code_end;
+#endif
+
+/* Can't support UTF8 unless PCRE has been compiled to include the code. */
+
+#ifndef SUPPORT_UTF8
+if ((options & PCRE_UTF8) != 0)
+ {
+ *errorptr = ERR32;
+ return NULL;
+ }
+#endif
+
+/* We can't pass back an error message if errorptr is NULL; I guess the best we
+can do is just return NULL. */
+
+if (errorptr == NULL) return NULL;
+*errorptr = NULL;
+
+/* However, we can give a message for this error */
+
+if (erroroffset == NULL)
+ {
+ *errorptr = ERR16;
+ return NULL;
+ }
+*erroroffset = 0;
+
+if ((options & ~PUBLIC_OPTIONS) != 0)
+ {
+ *errorptr = ERR17;
+ return NULL;
+ }
+
+/* Set up pointers to the individual character tables */
+
+if (tables == NULL) tables = pcre_default_tables;
+compile_block.lcc = tables + lcc_offset;
+compile_block.fcc = tables + fcc_offset;
+compile_block.cbits = tables + cbits_offset;
+compile_block.ctypes = tables + ctypes_offset;
+
+/* Reflect pattern for debugging output */
+
+DPRINTF(("------------------------------------------------------------------\n"));
+DPRINTF(("%s\n", pattern));
+
+/* The first thing to do is to make a pass over the pattern to compute the
+amount of store required to hold the compiled code. This does not have to be
+perfect as long as errors are overestimates. At the same time we can detect any
+internal flag settings. Make an attempt to correct for any counted white space
+if an "extended" flag setting appears late in the pattern. We can't be so
+clever for #-comments. */
+
+ptr = (const uschar *)(pattern - 1);
+while ((c = *(++ptr)) != 0)
+ {
+ int min, max;
+ int class_charcount;
+
+ if ((options & PCRE_EXTENDED) != 0)
+ {
+ if ((compile_block.ctypes[c] & ctype_space) != 0) continue;
+ if (c == '#')
+ {
+ /* The space before the ; is to avoid a warning on a silly compiler
+ on the Macintosh. */
+ while ((c = *(++ptr)) != 0 && c != '\n') ;
+ continue;
+ }
+ }
+
+ switch(c)
+ {
+ /* A backslashed item may be an escaped "normal" character or a
+ character type. For a "normal" character, put the pointers and
+ character back so that tests for whitespace etc. in the input
+ are done correctly. */
+
+ case '\\':
+ {
+ const uschar *save_ptr = ptr;
+ c = check_escape(&ptr, errorptr, bracount, options, FALSE, &compile_block);
+ if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
+ if (c >= 0)
+ {
+ ptr = save_ptr;
+ c = '\\';
+ goto NORMAL_CHAR;
+ }
+ }
+ length++;
+
+ /* A back reference needs an additional char, plus either one or 5
+ bytes for a repeat. We also need to keep the value of the highest
+ back reference. */
+
+ if (c <= -ESC_REF)
+ {
+ int refnum = -c - ESC_REF;
+ if (refnum > top_backref) top_backref = refnum;
+ length++; /* For single back reference */
+ if (ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block))
+ {
+ ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block);
+ if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
+ if ((min == 0 && (max == 1 || max == -1)) ||
+ (min == 1 && max == -1))
+ length++;
+ else length += 5;
+ if (ptr[1] == '?') ptr++;
+ }
+ }
+ continue;
+
+ case '^':
+ case '.':
+ case '$':
+ case '*': /* These repeats won't be after brackets; */
+ case '+': /* those are handled separately */
+ case '?':
+ length++;
+ continue;
+
+ /* This covers the cases of repeats after a single char, metachar, class,
+ or back reference. */
+
+ case '{':
+ if (!is_counted_repeat(ptr+1, &compile_block)) goto NORMAL_CHAR;
+ ptr = read_repeat_counts(ptr+1, &min, &max, errorptr, &compile_block);
+ if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
+ if ((min == 0 && (max == 1 || max == -1)) ||
+ (min == 1 && max == -1))
+ length++;
+ else
+ {
+ length--; /* Uncount the original char or metachar */
+ if (min == 1) length++; else if (min > 0) length += 4;
+ if (max > 0) length += 4; else length += 2;
+ }
+ if (ptr[1] == '?') ptr++;
+ continue;
+
+ /* An alternation contains an offset to the next branch or ket. If any ims
+ options changed in the previous branch(es), and/or if we are in a
+ lookbehind assertion, extra space will be needed at the start of the
+ branch. This is handled by branch_extra. */
+
+ case '|':
+ length += 3 + branch_extra;
+ continue;
+
+ /* A character class uses 33 characters. Don't worry about character types
+ that aren't allowed in classes - they'll get picked up during the compile.
+ A character class that contains only one character uses 2 or 3 bytes,
+ depending on whether it is negated or not. Notice this where we can. */
+
+ case '[':
+ class_charcount = 0;
+ if (*(++ptr) == '^') ptr++;
+ do
+ {
+ if (*ptr == '\\')
+ {
+ int ch = check_escape(&ptr, errorptr, bracount, options, TRUE,
+ &compile_block);
+ if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
+ if (-ch == ESC_b) class_charcount++; else class_charcount = 10;
+ }
+ else class_charcount++;
+ ptr++;
+ }
+ while (*ptr != 0 && *ptr != ']');
+
+ /* Repeats for negated single chars are handled by the general code */
+
+ if (class_charcount == 1) length += 3; else
+ {
+ length += 33;
+
+ /* A repeat needs either 1 or 5 bytes. */
+
+ if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block))
+ {
+ ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block);
+ if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
+ if ((min == 0 && (max == 1 || max == -1)) ||
+ (min == 1 && max == -1))
+ length++;
+ else length += 5;
+ if (ptr[1] == '?') ptr++;
+ }
+ }
+ continue;
+
+ /* Brackets may be genuine groups or special things */
+
+ case '(':
+ branch_newextra = 0;
+
+ /* Handle special forms of bracket, which all start (? */
+
+ if (ptr[1] == '?')
+ {
+ int set, unset;
+ int *optset;
+
+ switch (c = ptr[2])
+ {
+ /* Skip over comments entirely */
+ case '#':
+ ptr += 3;
+ while (*ptr != 0 && *ptr != ')') ptr++;
+ if (*ptr == 0)
+ {
+ *errorptr = ERR18;
+ goto PCRE_ERROR_RETURN;
+ }
+ continue;
+
+ /* Non-referencing groups and lookaheads just move the pointer on, and
+ then behave like a non-special bracket, except that they don't increment
+ the count of extracting brackets. Ditto for the "once only" bracket,
+ which is in Perl from version 5.005. */
+
+ case ':':
+ case '=':
+ case '!':
+ case '>':
+ ptr += 2;
+ break;
+
+ /* A recursive call to the regex is an extension, to provide the
+ facility which can be obtained by $(?p{perl-code}) in Perl 5.6. */
+
+ case 'R':
+ if (ptr[3] != ')')
+ {
+ *errorptr = ERR29;
+ goto PCRE_ERROR_RETURN;
+ }
+ ptr += 3;
+ length += 1;
+ break;
+
+ /* Lookbehinds are in Perl from version 5.005 */
+
+ case '<':
+ if (ptr[3] == '=' || ptr[3] == '!')
+ {
+ ptr += 3;
+ branch_newextra = 3;
+ length += 3; /* For the first branch */
+ break;
+ }
+ *errorptr = ERR24;
+ goto PCRE_ERROR_RETURN;
+
+ /* Conditionals are in Perl from version 5.005. The bracket must either
+ be followed by a number (for bracket reference) or by an assertion
+ group. */
+
+ case '(':
+ if ((compile_block.ctypes[ptr[3]] & ctype_digit) != 0)
+ {
+ ptr += 4;
+ length += 2;
+ while ((compile_block.ctypes[*ptr] & ctype_digit) != 0) ptr++;
+ if (*ptr != ')')
+ {
+ *errorptr = ERR26;
+ goto PCRE_ERROR_RETURN;
+ }
+ }
+ else /* An assertion must follow */
+ {
+ ptr++; /* Can treat like ':' as far as spacing is concerned */
+ if (ptr[2] != '?' ||
+ (ptr[3] != '=' && ptr[3] != '!' && ptr[3] != '<') )
+ {
+ ptr += 2; /* To get right offset in message */
+ *errorptr = ERR28;
+ goto PCRE_ERROR_RETURN;
+ }
+ }
+ break;
+
+ /* Else loop checking valid options until ) is met. Anything else is an
+ error. If we are without any brackets, i.e. at top level, the settings
+ act as if specified in the options, so massage the options immediately.
+ This is for backward compatibility with Perl 5.004. */
+
+ default:
+ set = unset = 0;
+ optset = &set;
+ ptr += 2;
+
+ for (;; ptr++)
+ {
+ c = *ptr;
+ switch (c)
+ {
+ case 'i':
+ *optset |= PCRE_CASELESS;
+ continue;
+
+ case 'm':
+ *optset |= PCRE_MULTILINE;
+ continue;
+
+ case 's':
+ *optset |= PCRE_DOTALL;
+ continue;
+
+ case 'x':
+ *optset |= PCRE_EXTENDED;
+ continue;
+
+ case 'X':
+ *optset |= PCRE_EXTRA;
+ continue;
+
+ case 'U':
+ *optset |= PCRE_UNGREEDY;
+ continue;
+
+ case '-':
+ optset = &unset;
+ continue;
+
+ /* A termination by ')' indicates an options-setting-only item;
+ this is global at top level; otherwise nothing is done here and
+ it is handled during the compiling process on a per-bracket-group
+ basis. */
+
+ case ')':
+ if (brastackptr == 0)
+ {
+ options = (options | set) & (~unset);
+ set = unset = 0; /* To save length */
+ }
+ /* Fall through */
+
+ /* A termination by ':' indicates the start of a nested group with
+ the given options set. This is again handled at compile time, but
+ we must allow for compiled space if any of the ims options are
+ set. We also have to allow for resetting space at the end of
+ the group, which is why 4 is added to the length and not just 2.
+ If there are several changes of options within the same group, this
+ will lead to an over-estimate on the length, but this shouldn't
+ matter very much. We also have to allow for resetting options at
+ the start of any alternations, which we do by setting
+ branch_newextra to 2. Finally, we record whether the case-dependent
+ flag ever changes within the regex. This is used by the "required
+ character" code. */
+
+ case ':':
+ if (((set|unset) & PCRE_IMS) != 0)
+ {
+ length += 4;
+ branch_newextra = 2;
+ if (((set|unset) & PCRE_CASELESS) != 0) options |= PCRE_ICHANGED;
+ }
+ goto END_OPTIONS;
+
+ /* Unrecognized option character */
+
+ default:
+ *errorptr = ERR12;
+ goto PCRE_ERROR_RETURN;
+ }
+ }
+
+ /* If we hit a closing bracket, that's it - this is a freestanding
+ option-setting. We need to ensure that branch_extra is updated if
+ necessary. The only values branch_newextra can have here are 0 or 2.
+ If the value is 2, then branch_extra must either be 2 or 5, depending
+ on whether this is a lookbehind group or not. */
+
+ END_OPTIONS:
+ if (c == ')')
+ {
+ if (branch_newextra == 2 && (branch_extra == 0 || branch_extra == 3))
+ branch_extra += branch_newextra;
+ continue;
+ }
+
+ /* If options were terminated by ':' control comes here. Fall through
+ to handle the group below. */
+ }
+ }
+
+ /* Extracting brackets must be counted so we can process escapes in a
+ Perlish way. */
+
+ else bracount++;
+
+ /* Non-special forms of bracket. Save length for computing whole length
+ at end if there's a repeat that requires duplication of the group. Also
+ save the current value of branch_extra, and start the new group with
+ the new value. If non-zero, this will either be 2 for a (?imsx: group, or 3
+ for a lookbehind assertion. */
+
+ if (brastackptr >= sizeof(brastack)/sizeof(int))
+ {
+ *errorptr = ERR19;
+ goto PCRE_ERROR_RETURN;
+ }
+
+ bralenstack[brastackptr] = branch_extra;
+ branch_extra = branch_newextra;
+
+ brastack[brastackptr++] = length;
+ length += 3;
+ continue;
+
+ /* Handle ket. Look for subsequent max/min; for certain sets of values we
+ have to replicate this bracket up to that many times. If brastackptr is
+ 0 this is an unmatched bracket which will generate an error, but take care
+ not to try to access brastack[-1] when computing the length and restoring
+ the branch_extra value. */
+
+ case ')':
+ length += 3;
+ {
+ int minval = 1;
+ int maxval = 1;
+ int duplength;
+
+ if (brastackptr > 0)
+ {
+ duplength = length - brastack[--brastackptr];
+ branch_extra = bralenstack[brastackptr];
+ }
+ else duplength = 0;
+
+ /* Leave ptr at the final char; for read_repeat_counts this happens
+ automatically; for the others we need an increment. */
+
+ if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2, &compile_block))
+ {
+ ptr = read_repeat_counts(ptr+2, &minval, &maxval, errorptr,
+ &compile_block);
+ if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
+ }
+ else if (c == '*') { minval = 0; maxval = -1; ptr++; }
+ else if (c == '+') { maxval = -1; ptr++; }
+ else if (c == '?') { minval = 0; ptr++; }
+
+ /* If the minimum is zero, we have to allow for an OP_BRAZERO before the
+ group, and if the maximum is greater than zero, we have to replicate
+ maxval-1 times; each replication acquires an OP_BRAZERO plus a nesting
+ bracket set - hence the 7. */
+
+ if (minval == 0)
+ {
+ length++;
+ if (maxval > 0) length += (maxval - 1) * (duplength + 7);
+ }
+
+ /* When the minimum is greater than zero, 1 we have to replicate up to
+ minval-1 times, with no additions required in the copies. Then, if
+ there is a limited maximum we have to replicate up to maxval-1 times
+ allowing for a BRAZERO item before each optional copy and nesting
+ brackets for all but one of the optional copies. */
+
+ else
+ {
+ length += (minval - 1) * duplength;
+ if (maxval > minval) /* Need this test as maxval=-1 means no limit */
+ length += (maxval - minval) * (duplength + 7) - 6;
+ }
+ }
+ continue;
+
+ /* Non-special character. For a run of such characters the length required
+ is the number of characters + 2, except that the maximum run length is 255.
+ We won't get a skipped space or a non-data escape or the start of a #
+ comment as the first character, so the length can't be zero. */
+
+ NORMAL_CHAR:
+ default:
+ length += 2;
+ runlength = 0;
+ do
+ {
+ if ((options & PCRE_EXTENDED) != 0)
+ {
+ if ((compile_block.ctypes[c] & ctype_space) != 0) continue;
+ if (c == '#')
+ {
+ /* The space before the ; is to avoid a warning on a silly compiler
+ on the Macintosh. */
+ while ((c = *(++ptr)) != 0 && c != '\n') ;
+ continue;
+ }
+ }
+
+ /* Backslash may introduce a data char or a metacharacter; stop the
+ string before the latter. */
+
+ if (c == '\\')
+ {
+ const uschar *saveptr = ptr;
+ c = check_escape(&ptr, errorptr, bracount, options, FALSE,
+ &compile_block);
+ if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
+ if (c < 0) { ptr = saveptr; break; }
+
+#ifdef SUPPORT_UTF8
+ if (c > 127 && (options & PCRE_UTF8) != 0)
+ {
+ int i;
+ for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++)
+ if (c <= utf8_table1[i]) break;
+ runlength += i;
+ }
+#endif
+ }
+
+ /* Ordinary character or single-char escape */
+
+ runlength++;
+ }
+
+ /* This "while" is the end of the "do" above. */
+
+ while (runlength < MAXLIT &&
+ (compile_block.ctypes[c = *(++ptr)] & ctype_meta) == 0);
+
+ ptr--;
+ length += runlength;
+ continue;
+ }
+ }
+
+length += 4; /* For final KET and END */
+
+if (length > 65539)
+ {
+ *errorptr = ERR20;
+ return NULL;
+ }
+
+/* Compute the size of data block needed and get it, either from malloc or
+externally provided function. We specify "code[0]" in the offsetof() expression
+rather than just "code", because it has been reported that one broken compiler
+fails on "code" because it is also an independent variable. It should make no
+difference to the value of the offsetof(). */
+
+size = length + offsetof(real_pcre, code[0]);
+re = (real_pcre *)(pcre_malloc)(size);
+
+if (re == NULL)
+ {
+ *errorptr = ERR21;
+ return NULL;
+ }
+
+/* Put in the magic number, and save the size, options, and table pointer */
+
+re->magic_number = MAGIC_NUMBER;
+re->size = size;
+re->options = options;
+re->tables = tables;
+
+/* Set up a starting, non-extracting bracket, then compile the expression. On
+error, *errorptr will be set non-NULL, so we don't need to look at the result
+of the function here. */
+
+ptr = (const uschar *)pattern;
+code = re->code;
+*code = OP_BRA;
+bracount = 0;
+(void)compile_regex(options, -1, &bracount, &code, &ptr, errorptr, FALSE, -1,
+ &reqchar, &countlits, &compile_block);
+re->top_bracket = bracount;
+re->top_backref = top_backref;
+
+/* If not reached end of pattern on success, there's an excess bracket. */
+
+if (*errorptr == NULL && *ptr != 0) *errorptr = ERR22;
+
+/* Fill in the terminating state and check for disastrous overflow, but
+if debugging, leave the test till after things are printed out. */
+
+*code++ = OP_END;
+
+#ifndef DEBUG
+if (code - re->code > length) *errorptr = ERR23;
+#endif
+
+/* Give an error if there's back reference to a non-existent capturing
+subpattern. */
+
+if (top_backref > re->top_bracket) *errorptr = ERR15;
+
+/* Failed to compile */
+
+if (*errorptr != NULL)
+ {
+ (pcre_free)(re);
+ PCRE_ERROR_RETURN:
+ *erroroffset = ptr - (const uschar *)pattern;
+ return NULL;
+ }
+
+/* If the anchored option was not passed, set flag if we can determine that the
+pattern is anchored by virtue of ^ characters or \A or anything else (such as
+starting with .* when DOTALL is set).
+
+Otherwise, see if we can determine what the first character has to be, because
+that speeds up unanchored matches no end. If not, see if we can set the
+PCRE_STARTLINE flag. This is helpful for multiline matches when all branches
+start with ^. and also when all branches start with .* for non-DOTALL matches.
+*/
+
+if ((options & PCRE_ANCHORED) == 0)
+ {
+ int temp_options = options;
+ if (is_anchored(re->code, &temp_options))
+ re->options |= PCRE_ANCHORED;
+ else
+ {
+ int ch = find_firstchar(re->code, &temp_options);
+ if (ch >= 0)
+ {
+ re->first_char = ch;
+ re->options |= PCRE_FIRSTSET;
+ }
+ else if (is_startline(re->code))
+ re->options |= PCRE_STARTLINE;
+ }
+ }
+
+/* Save the last required character if there are at least two literal
+characters on all paths, or if there is no first character setting. */
+
+if (reqchar >= 0 && (countlits > 1 || (re->options & PCRE_FIRSTSET) == 0))
+ {
+ re->req_char = reqchar;
+ re->options |= PCRE_REQCHSET;
+ }
+
+/* Print out the compiled data for debugging */
+
+#ifdef DEBUG
+
+printf("Length = %d top_bracket = %d top_backref = %d\n",
+ length, re->top_bracket, re->top_backref);
+
+if (re->options != 0)
+ {
+ printf("%s%s%s%s%s%s%s%s%s\n",
+ ((re->options & PCRE_ANCHORED) != 0)? "anchored " : "",
+ ((re->options & PCRE_CASELESS) != 0)? "caseless " : "",
+ ((re->options & PCRE_ICHANGED) != 0)? "case state changed " : "",
+ ((re->options & PCRE_EXTENDED) != 0)? "extended " : "",
+ ((re->options & PCRE_MULTILINE) != 0)? "multiline " : "",
+ ((re->options & PCRE_DOTALL) != 0)? "dotall " : "",
+ ((re->options & PCRE_DOLLAR_ENDONLY) != 0)? "endonly " : "",
+ ((re->options & PCRE_EXTRA) != 0)? "extra " : "",
+ ((re->options & PCRE_UNGREEDY) != 0)? "ungreedy " : "");
+ }
+
+if ((re->options & PCRE_FIRSTSET) != 0)
+ {
+ if (isprint(re->first_char)) printf("First char = %c\n", re->first_char);
+ else printf("First char = \\x%02x\n", re->first_char);
+ }
+
+if ((re->options & PCRE_REQCHSET) != 0)
+ {
+ if (isprint(re->req_char)) printf("Req char = %c\n", re->req_char);
+ else printf("Req char = \\x%02x\n", re->req_char);
+ }
+
+code_end = code;
+code_base = code = re->code;
+
+while (code < code_end)
+ {
+ int charlength;
+
+ printf("%3d ", code - code_base);
+
+ if (*code >= OP_BRA)
+ {
+ printf("%3d Bra %d", (code[1] << 8) + code[2], *code - OP_BRA);
+ code += 2;
+ }
+
+ else switch(*code)
+ {
+ case OP_OPT:
+ printf(" %.2x %s", code[1], OP_names[*code]);
+ code++;
+ break;
+
+ case OP_COND:
+ printf("%3d Cond", (code[1] << 8) + code[2]);
+ code += 2;
+ break;
+
+ case OP_CREF:
+ printf(" %.2d %s", code[1], OP_names[*code]);
+ code++;
+ break;
+
+ case OP_CHARS:
+ charlength = *(++code);
+ printf("%3d ", charlength);
+ while (charlength-- > 0)
+ if (isprint(c = *(++code))) printf("%c", c); else printf("\\x%02x", c);
+ break;
+
+ case OP_KETRMAX:
+ case OP_KETRMIN:
+ case OP_ALT:
+ case OP_KET:
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ case OP_ONCE:
+ printf("%3d %s", (code[1] << 8) + code[2], OP_names[*code]);
+ code += 2;
+ break;
+
+ case OP_REVERSE:
+ printf("%3d %s", (code[1] << 8) + code[2], OP_names[*code]);
+ code += 2;
+ break;
+
+ case OP_STAR:
+ case OP_MINSTAR:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ if (*code >= OP_TYPESTAR)
+ printf(" %s", OP_names[code[1]]);
+ else if (isprint(c = code[1])) printf(" %c", c);
+ else printf(" \\x%02x", c);
+ printf("%s", OP_names[*code++]);
+ break;
+
+ case OP_EXACT:
+ case OP_UPTO:
+ case OP_MINUPTO:
+ if (isprint(c = code[3])) printf(" %c{", c);
+ else printf(" \\x%02x{", c);
+ if (*code != OP_EXACT) printf("0,");
+ printf("%d}", (code[1] << 8) + code[2]);
+ if (*code == OP_MINUPTO) printf("?");
+ code += 3;
+ break;
+
+ case OP_TYPEEXACT:
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ printf(" %s{", OP_names[code[3]]);
+ if (*code != OP_TYPEEXACT) printf(",");
+ printf("%d}", (code[1] << 8) + code[2]);
+ if (*code == OP_TYPEMINUPTO) printf("?");
+ code += 3;
+ break;
+
+ case OP_NOT:
+ if (isprint(c = *(++code))) printf(" [^%c]", c);
+ else printf(" [^\\x%02x]", c);
+ break;
+
+ case OP_NOTSTAR:
+ case OP_NOTMINSTAR:
+ case OP_NOTPLUS:
+ case OP_NOTMINPLUS:
+ case OP_NOTQUERY:
+ case OP_NOTMINQUERY:
+ if (isprint(c = code[1])) printf(" [^%c]", c);
+ else printf(" [^\\x%02x]", c);
+ printf("%s", OP_names[*code++]);
+ break;
+
+ case OP_NOTEXACT:
+ case OP_NOTUPTO:
+ case OP_NOTMINUPTO:
+ if (isprint(c = code[3])) printf(" [^%c]{", c);
+ else printf(" [^\\x%02x]{", c);
+ if (*code != OP_NOTEXACT) printf(",");
+ printf("%d}", (code[1] << 8) + code[2]);
+ if (*code == OP_NOTMINUPTO) printf("?");
+ code += 3;
+ break;
+
+ case OP_REF:
+ printf(" \\%d", *(++code));
+ code ++;
+ goto CLASS_REF_REPEAT;
+
+ case OP_CLASS:
+ {
+ int i, min, max;
+ code++;
+ printf(" [");
+
+ for (i = 0; i < 256; i++)
+ {
+ if ((code[i/8] & (1 << (i&7))) != 0)
+ {
+ int j;
+ for (j = i+1; j < 256; j++)
+ if ((code[j/8] & (1 << (j&7))) == 0) break;
+ if (i == '-' || i == ']') printf("\\");
+ if (isprint(i)) printf("%c", i); else printf("\\x%02x", i);
+ if (--j > i)
+ {
+ printf("-");
+ if (j == '-' || j == ']') printf("\\");
+ if (isprint(j)) printf("%c", j); else printf("\\x%02x", j);
+ }
+ i = j;
+ }
+ }
+ printf("]");
+ code += 32;
+
+ CLASS_REF_REPEAT:
+
+ switch(*code)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ printf("%s", OP_names[*code]);
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ min = (code[1] << 8) + code[2];
+ max = (code[3] << 8) + code[4];
+ if (max == 0) printf("{%d,}", min);
+ else printf("{%d,%d}", min, max);
+ if (*code == OP_CRMINRANGE) printf("?");
+ code += 4;
+ break;
+
+ default:
+ code--;
+ }
+ }
+ break;
+
+ /* Anything else is just a one-node item */
+
+ default:
+ printf(" %s", OP_names[*code]);
+ break;
+ }
+
+ code++;
+ printf("\n");
+ }
+printf("------------------------------------------------------------------\n");
+
+/* This check is done here in the debugging case so that the code that
+was compiled can be seen. */
+
+if (code - re->code > length)
+ {
+ *errorptr = ERR23;
+ (pcre_free)(re);
+ *erroroffset = ptr - (uschar *)pattern;
+ return NULL;
+ }
+#endif
+
+return (pcre *)re;
+}
+
+
+
+/*************************************************
+* Match a back-reference *
+*************************************************/
+
+/* If a back reference hasn't been set, the length that is passed is greater
+than the number of characters left in the string, so the match fails.
+
+Arguments:
+ offset index into the offset vector
+ eptr points into the subject
+ length length to be matched
+ md points to match data block
+ ims the ims flags
+
+Returns: TRUE if matched
+*/
+
+static BOOL
+match_ref(int offset, register const uschar *eptr, int length, match_data *md,
+ unsigned long int ims)
+{
+const uschar *p = md->start_subject + md->offset_vector[offset];
+
+#ifdef DEBUG
+if (eptr >= md->end_subject)
+ printf("matching subject <null>");
+else
+ {
+ printf("matching subject ");
+ pchars(eptr, length, TRUE, md);
+ }
+printf(" against backref ");
+pchars(p, length, FALSE, md);
+printf("\n");
+#endif
+
+/* Always fail if not enough characters left */
+
+if (length > md->end_subject - eptr) return FALSE;
+
+/* Separate the caselesss case for speed */
+
+if ((ims & PCRE_CASELESS) != 0)
+ {
+ while (length-- > 0)
+ if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE;
+ }
+else
+ { while (length-- > 0) if (*p++ != *eptr++) return FALSE; }
+
+return TRUE;
+}
+
+
+
+/*************************************************
+* Match from current position *
+*************************************************/
+
+/* On entry ecode points to the first opcode, and eptr to the first character
+in the subject string, while eptrb holds the value of eptr at the start of the
+last bracketed group - used for breaking infinite loops matching zero-length
+strings.
+
+Arguments:
+ eptr pointer in subject
+ ecode position in code
+ offset_top current top pointer
+ md pointer to "static" info for the match
+ ims current /i, /m, and /s options
+ eptrb pointer to chain of blocks containing eptr at start of
+ brackets - for testing for empty matches
+ flags can contain
+ match_condassert - this is an assertion condition
+ match_isgroup - this is the start of a bracketed group
+
+Returns: TRUE if matched
+*/
+
+static BOOL
+match(register const uschar *eptr, register const uschar *ecode,
+ int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,
+ int flags)
+{
+unsigned long int original_ims = ims; /* Save for resetting on ')' */
+eptrblock newptrb;
+
+/* At the start of a bracketed group, add the current subject pointer to the
+stack of such pointers, to be re-instated at the end of the group when we hit
+the closing ket. When match() is called in other circumstances, we don't add to
+the stack. */
+
+if ((flags & match_isgroup) != 0)
+ {
+ newptrb.prev = eptrb;
+ newptrb.saved_eptr = eptr;
+ eptrb = &newptrb;
+ }
+
+/* Now start processing the operations. */
+
+for (;;)
+ {
+ int op = (int)*ecode;
+ int min, max, ctype;
+ register int i;
+ register int c;
+ BOOL minimize = FALSE;
+
+ /* Opening capturing bracket. If there is space in the offset vector, save
+ the current subject position in the working slot at the top of the vector. We
+ mustn't change the current values of the data slot, because they may be set
+ from a previous iteration of this group, and be referred to by a reference
+ inside the group.
+
+ If the bracket fails to match, we need to restore this value and also the
+ values of the final offsets, in case they were set by a previous iteration of
+ the same bracket.
+
+ If there isn't enough space in the offset vector, treat this as if it were a
+ non-capturing bracket. Don't worry about setting the flag for the error case
+ here; that is handled in the code for KET. */
+
+ if (op > OP_BRA)
+ {
+ int number = op - OP_BRA;
+ int offset = number << 1;
+
+#ifdef DEBUG
+ printf("start bracket %d subject=", number);
+ pchars(eptr, 16, TRUE, md);
+ printf("\n");
+#endif
+
+ if (offset < md->offset_max)
+ {
+ int save_offset1 = md->offset_vector[offset];
+ int save_offset2 = md->offset_vector[offset+1];
+ int save_offset3 = md->offset_vector[md->offset_end - number];
+
+ DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
+ md->offset_vector[md->offset_end - number] = eptr - md->start_subject;
+
+ do
+ {
+ if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
+ return TRUE;
+ ecode += (ecode[1] << 8) + ecode[2];
+ }
+ while (*ecode == OP_ALT);
+
+ DPRINTF(("bracket %d failed\n", number));
+
+ md->offset_vector[offset] = save_offset1;
+ md->offset_vector[offset+1] = save_offset2;
+ md->offset_vector[md->offset_end - number] = save_offset3;
+ return FALSE;
+ }
+
+ /* Insufficient room for saving captured contents */
+
+ else op = OP_BRA;
+ }
+
+ /* Other types of node can be handled by a switch */
+
+ switch(op)
+ {
+ case OP_BRA: /* Non-capturing bracket: optimized */
+ DPRINTF(("start bracket 0\n"));
+ do
+ {
+ if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
+ return TRUE;
+ ecode += (ecode[1] << 8) + ecode[2];
+ }
+ while (*ecode == OP_ALT);
+ DPRINTF(("bracket 0 failed\n"));
+ return FALSE;
+
+ /* Conditional group: compilation checked that there are no more than
+ two branches. If the condition is false, skipping the first branch takes us
+ past the end if there is only one branch, but that's OK because that is
+ exactly what going to the ket would do. */
+
+ case OP_COND:
+ if (ecode[3] == OP_CREF) /* Condition is extraction test */
+ {
+ int offset = ecode[4] << 1; /* Doubled reference number */
+ return match(eptr,
+ ecode + ((offset < offset_top && md->offset_vector[offset] >= 0)?
+ 5 : 3 + (ecode[1] << 8) + ecode[2]),
+ offset_top, md, ims, eptrb, match_isgroup);
+ }
+
+ /* The condition is an assertion. Call match() to evaluate it - setting
+ the final argument TRUE causes it to stop at the end of an assertion. */
+
+ else
+ {
+ if (match(eptr, ecode+3, offset_top, md, ims, NULL,
+ match_condassert | match_isgroup))
+ {
+ ecode += 3 + (ecode[4] << 8) + ecode[5];
+ while (*ecode == OP_ALT) ecode += (ecode[1] << 8) + ecode[2];
+ }
+ else ecode += (ecode[1] << 8) + ecode[2];
+ return match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup);
+ }
+ /* Control never reaches here */
+
+ /* Skip over conditional reference data if encountered (should not be) */
+
+ case OP_CREF:
+ ecode += 2;
+ break;
+
+ /* End of the pattern. If PCRE_NOTEMPTY is set, fail if we have matched
+ an empty string - recursion will then try other alternatives, if any. */
+
+ case OP_END:
+ if (md->notempty && eptr == md->start_match) return FALSE;
+ md->end_match_ptr = eptr; /* Record where we ended */
+ md->end_offset_top = offset_top; /* and how many extracts were taken */
+ return TRUE;
+
+ /* Change option settings */
+
+ case OP_OPT:
+ ims = ecode[1];
+ ecode += 2;
+ DPRINTF(("ims set to %02lx\n", ims));
+ break;
+
+ /* Assertion brackets. Check the alternative branches in turn - the
+ matching won't pass the KET for an assertion. If any one branch matches,
+ the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
+ start of each branch to move the current point backwards, so the code at
+ this level is identical to the lookahead case. */
+
+ case OP_ASSERT:
+ case OP_ASSERTBACK:
+ do
+ {
+ if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup)) break;
+ ecode += (ecode[1] << 8) + ecode[2];
+ }
+ while (*ecode == OP_ALT);
+ if (*ecode == OP_KET) return FALSE;
+
+ /* If checking an assertion for a condition, return TRUE. */
+
+ if ((flags & match_condassert) != 0) return TRUE;
+
+ /* Continue from after the assertion, updating the offsets high water
+ mark, since extracts may have been taken during the assertion. */
+
+ do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
+ ecode += 3;
+ offset_top = md->end_offset_top;
+ continue;
+
+ /* Negative assertion: all branches must fail to match */
+
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK_NOT:
+ do
+ {
+ if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup))
+ return FALSE;
+ ecode += (ecode[1] << 8) + ecode[2];
+ }
+ while (*ecode == OP_ALT);
+
+ if ((flags & match_condassert) != 0) return TRUE;
+
+ ecode += 3;
+ continue;
+
+ /* Move the subject pointer back. This occurs only at the start of
+ each branch of a lookbehind assertion. If we are too close to the start to
+ move back, this match function fails. When working with UTF-8 we move
+ back a number of characters, not bytes. */
+
+ case OP_REVERSE:
+#ifdef SUPPORT_UTF8
+ c = (ecode[1] << 8) + ecode[2];
+ for (i = 0; i < c; i++)
+ {
+ eptr--;
+ BACKCHAR(eptr)
+ }
+#else
+ eptr -= (ecode[1] << 8) + ecode[2];
+#endif
+
+ if (eptr < md->start_subject) return FALSE;
+ ecode += 3;
+ break;
+
+ /* Recursion matches the current regex, nested. If there are any capturing
+ brackets started but not finished, we have to save their starting points
+ and reinstate them after the recursion. However, we don't know how many
+ such there are (offset_top records the completed total) so we just have
+ to save all the potential data. There may be up to 99 such values, which
+ is a bit large to put on the stack, but using malloc for small numbers
+ seems expensive. As a compromise, the stack is used when there are fewer
+ than 16 values to store; otherwise malloc is used. A problem is what to do
+ if the malloc fails ... there is no way of returning to the top level with
+ an error. Save the top 15 values on the stack, and accept that the rest
+ may be wrong. */
+
+ case OP_RECURSE:
+ {
+ BOOL rc;
+ int *save;
+ int stacksave[15];
+
+ c = md->offset_max;
+
+ if (c < 16) save = stacksave; else
+ {
+ save = (int *)(pcre_malloc)((c+1) * sizeof(int));
+ if (save == NULL)
+ {
+ save = stacksave;
+ c = 15;
+ }
+ }
+
+ for (i = 1; i <= c; i++)
+ save[i] = md->offset_vector[md->offset_end - i];
+ rc = match(eptr, md->start_pattern, offset_top, md, ims, eptrb,
+ match_isgroup);
+ for (i = 1; i <= c; i++)
+ md->offset_vector[md->offset_end - i] = save[i];
+ if (save != stacksave) (pcre_free)(save);
+ if (!rc) return FALSE;
+
+ /* In case the recursion has set more capturing values, save the final
+ number, then move along the subject till after the recursive match,
+ and advance one byte in the pattern code. */
+
+ offset_top = md->end_offset_top;
+ eptr = md->end_match_ptr;
+ ecode++;
+ }
+ break;
+
+ /* "Once" brackets are like assertion brackets except that after a match,
+ the point in the subject string is not moved back. Thus there can never be
+ a move back into the brackets. Check the alternative branches in turn - the
+ matching won't pass the KET for this kind of subpattern. If any one branch
+ matches, we carry on as at the end of a normal bracket, leaving the subject
+ pointer. */
+
+ case OP_ONCE:
+ {
+ const uschar *prev = ecode;
+ const uschar *saved_eptr = eptr;
+
+ do
+ {
+ if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
+ break;
+ ecode += (ecode[1] << 8) + ecode[2];
+ }
+ while (*ecode == OP_ALT);
+
+ /* If hit the end of the group (which could be repeated), fail */
+
+ if (*ecode != OP_ONCE && *ecode != OP_ALT) return FALSE;
+
+ /* Continue as from after the assertion, updating the offsets high water
+ mark, since extracts may have been taken. */
+
+ do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
+
+ offset_top = md->end_offset_top;
+ eptr = md->end_match_ptr;
+
+ /* For a non-repeating ket, just continue at this level. This also
+ happens for a repeating ket if no characters were matched in the group.
+ This is the forcible breaking of infinite loops as implemented in Perl
+ 5.005. If there is an options reset, it will get obeyed in the normal
+ course of events. */
+
+ if (*ecode == OP_KET || eptr == saved_eptr)
+ {
+ ecode += 3;
+ break;
+ }
+
+ /* The repeating kets try the rest of the pattern or restart from the
+ preceding bracket, in the appropriate order. We need to reset any options
+ that changed within the bracket before re-running it, so check the next
+ opcode. */
+
+ if (ecode[3] == OP_OPT)
+ {
+ ims = (ims & ~PCRE_IMS) | ecode[4];
+ DPRINTF(("ims set to %02lx at group repeat\n", ims));
+ }
+
+ if (*ecode == OP_KETRMIN)
+ {
+ if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
+ match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
+ return TRUE;
+ }
+ else /* OP_KETRMAX */
+ {
+ if (match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
+ match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) return TRUE;
+ }
+ }
+ return FALSE;
+
+ /* An alternation is the end of a branch; scan along to find the end of the
+ bracketed group and go to there. */
+
+ case OP_ALT:
+ do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
+ break;
+
+ /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating
+ that it may occur zero times. It may repeat infinitely, or not at all -
+ i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper
+ repeat limits are compiled as a number of copies, with the optional ones
+ preceded by BRAZERO or BRAMINZERO. */
+
+ case OP_BRAZERO:
+ {
+ const uschar *next = ecode+1;
+ if (match(eptr, next, offset_top, md, ims, eptrb, match_isgroup))
+ return TRUE;
+ do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
+ ecode = next + 3;
+ }
+ break;
+
+ case OP_BRAMINZERO:
+ {
+ const uschar *next = ecode+1;
+ do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
+ if (match(eptr, next+3, offset_top, md, ims, eptrb, match_isgroup))
+ return TRUE;
+ ecode++;
+ }
+ break;
+
+ /* End of a group, repeated or non-repeating. If we are at the end of
+ an assertion "group", stop matching and return TRUE, but record the
+ current high water mark for use by positive assertions. Do this also
+ for the "once" (not-backup up) groups. */
+
+ case OP_KET:
+ case OP_KETRMIN:
+ case OP_KETRMAX:
+ {
+ const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
+ const uschar *saved_eptr = eptrb->saved_eptr;
+
+ eptrb = eptrb->prev; /* Back up the stack of bracket start pointers */
+
+ if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
+ *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
+ *prev == OP_ONCE)
+ {
+ md->end_match_ptr = eptr; /* For ONCE */
+ md->end_offset_top = offset_top;
+ return TRUE;
+ }
+
+ /* In all other cases except a conditional group we have to check the
+ group number back at the start and if necessary complete handling an
+ extraction by setting the offsets and bumping the high water mark. */
+
+ if (*prev != OP_COND)
+ {
+ int number = *prev - OP_BRA;
+ int offset = number << 1;
+
+#ifdef DEBUG
+ printf("end bracket %d", number);
+ printf("\n");
+#endif
+
+ if (number > 0)
+ {
+ if (offset >= md->offset_max) md->offset_overflow = TRUE; else
+ {
+ md->offset_vector[offset] =
+ md->offset_vector[md->offset_end - number];
+ md->offset_vector[offset+1] = eptr - md->start_subject;
+ if (offset_top <= offset) offset_top = offset + 2;
+ }
+ }
+ }
+
+ /* Reset the value of the ims flags, in case they got changed during
+ the group. */
+
+ ims = original_ims;
+ DPRINTF(("ims reset to %02lx\n", ims));
+
+ /* For a non-repeating ket, just continue at this level. This also
+ happens for a repeating ket if no characters were matched in the group.
+ This is the forcible breaking of infinite loops as implemented in Perl
+ 5.005. If there is an options reset, it will get obeyed in the normal
+ course of events. */
+
+ if (*ecode == OP_KET || eptr == saved_eptr)
+ {
+ ecode += 3;
+ break;
+ }
+
+ /* The repeating kets try the rest of the pattern or restart from the
+ preceding bracket, in the appropriate order. */
+
+ if (*ecode == OP_KETRMIN)
+ {
+ if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
+ match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
+ return TRUE;
+ }
+ else /* OP_KETRMAX */
+ {
+ if (match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
+ match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) return TRUE;
+ }
+ }
+ return FALSE;
+
+ /* Start of subject unless notbol, or after internal newline if multiline */
+
+ case OP_CIRC:
+ if (md->notbol && eptr == md->start_subject) return FALSE;
+ if ((ims & PCRE_MULTILINE) != 0)
+ {
+ if (eptr != md->start_subject && eptr[-1] != '\n') return FALSE;
+ ecode++;
+ break;
+ }
+ /* ... else fall through */
+
+ /* Start of subject assertion */
+
+ case OP_SOD:
+ if (eptr != md->start_subject) return FALSE;
+ ecode++;
+ break;
+
+ /* Assert before internal newline if multiline, or before a terminating
+ newline unless endonly is set, else end of subject unless noteol is set. */
+
+ case OP_DOLL:
+ if ((ims & PCRE_MULTILINE) != 0)
+ {
+ if (eptr < md->end_subject) { if (*eptr != '\n') return FALSE; }
+ else { if (md->noteol) return FALSE; }
+ ecode++;
+ break;
+ }
+ else
+ {
+ if (md->noteol) return FALSE;
+ if (!md->endonly)
+ {
+ if (eptr < md->end_subject - 1 ||
+ (eptr == md->end_subject - 1 && *eptr != '\n')) return FALSE;
+
+ ecode++;
+ break;
+ }
+ }
+ /* ... else fall through */
+
+ /* End of subject assertion (\z) */
+
+ case OP_EOD:
+ if (eptr < md->end_subject) return FALSE;
+ ecode++;
+ break;
+
+ /* End of subject or ending \n assertion (\Z) */
+
+ case OP_EODN:
+ if (eptr < md->end_subject - 1 ||
+ (eptr == md->end_subject - 1 && *eptr != '\n')) return FALSE;
+ ecode++;
+ break;
+
+ /* Word boundary assertions */
+
+ case OP_NOT_WORD_BOUNDARY:
+ case OP_WORD_BOUNDARY:
+ {
+ BOOL prev_is_word = (eptr != md->start_subject) &&
+ ((md->ctypes[eptr[-1]] & ctype_word) != 0);
+ BOOL cur_is_word = (eptr < md->end_subject) &&
+ ((md->ctypes[*eptr] & ctype_word) != 0);
+ if ((*ecode++ == OP_WORD_BOUNDARY)?
+ cur_is_word == prev_is_word : cur_is_word != prev_is_word)
+ return FALSE;
+ }
+ break;
+
+ /* Match a single character type; inline for speed */
+
+ case OP_ANY:
+ if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == '\n')
+ return FALSE;
+ if (eptr++ >= md->end_subject) return FALSE;
+#ifdef SUPPORT_UTF8
+ if (md->utf8)
+ while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
+#endif
+ ecode++;
+ break;
+
+ case OP_NOT_DIGIT:
+ if (eptr >= md->end_subject ||
+ (md->ctypes[*eptr++] & ctype_digit) != 0)
+ return FALSE;
+ ecode++;
+ break;
+
+ case OP_DIGIT:
+ if (eptr >= md->end_subject ||
+ (md->ctypes[*eptr++] & ctype_digit) == 0)
+ return FALSE;
+ ecode++;
+ break;
+
+ case OP_NOT_WHITESPACE:
+ if (eptr >= md->end_subject ||
+ (md->ctypes[*eptr++] & ctype_space) != 0)
+ return FALSE;
+ ecode++;
+ break;
+
+ case OP_WHITESPACE:
+ if (eptr >= md->end_subject ||
+ (md->ctypes[*eptr++] & ctype_space) == 0)
+ return FALSE;
+ ecode++;
+ break;
+
+ case OP_NOT_WORDCHAR:
+ if (eptr >= md->end_subject ||
+ (md->ctypes[*eptr++] & ctype_word) != 0)
+ return FALSE;
+ ecode++;
+ break;
+
+ case OP_WORDCHAR:
+ if (eptr >= md->end_subject ||
+ (md->ctypes[*eptr++] & ctype_word) == 0)
+ return FALSE;
+ ecode++;
+ break;
+
+ /* Match a back reference, possibly repeatedly. Look past the end of the
+ item to see if there is repeat information following. The code is similar
+ to that for character classes, but repeated for efficiency. Then obey
+ similar code to character type repeats - written out again for speed.
+ However, if the referenced string is the empty string, always treat
+ it as matched, any number of times (otherwise there could be infinite
+ loops). */
+
+ case OP_REF:
+ {
+ int length;
+ int offset = ecode[1] << 1; /* Doubled reference number */
+ ecode += 2; /* Advance past the item */
+
+ /* If the reference is unset, set the length to be longer than the amount
+ of subject left; this ensures that every attempt at a match fails. We
+ can't just fail here, because of the possibility of quantifiers with zero
+ minima. */
+
+ length = (offset >= offset_top || md->offset_vector[offset] < 0)?
+ md->end_subject - eptr + 1 :
+ md->offset_vector[offset+1] - md->offset_vector[offset];
+
+ /* Set up for repetition, or handle the non-repeated case */
+
+ switch (*ecode)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ c = *ecode++ - OP_CRSTAR;
+ minimize = (c & 1) != 0;
+ min = rep_min[c]; /* Pick up values from tables; */
+ max = rep_max[c]; /* zero for max => infinity */
+ if (max == 0) max = INT_MAX;
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ minimize = (*ecode == OP_CRMINRANGE);
+ min = (ecode[1] << 8) + ecode[2];
+ max = (ecode[3] << 8) + ecode[4];
+ if (max == 0) max = INT_MAX;
+ ecode += 5;
+ break;
+
+ default: /* No repeat follows */
+ if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
+ eptr += length;
+ continue; /* With the main loop */
+ }
+
+ /* If the length of the reference is zero, just continue with the
+ main loop. */
+
+ if (length == 0) continue;
+
+ /* First, ensure the minimum number of matches are present. We get back
+ the length of the reference string explicitly rather than passing the
+ address of eptr, so that eptr can be a register variable. */
+
+ for (i = 1; i <= min; i++)
+ {
+ if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
+ eptr += length;
+ }
+
+ /* If min = max, continue at the same level without recursion.
+ They are not both allowed to be zero. */
+
+ if (min == max) continue;
+
+ /* If minimizing, keep trying and advancing the pointer */
+
+ if (minimize)
+ {
+ for (i = min;; i++)
+ {
+ if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+ if (i >= max || !match_ref(offset, eptr, length, md, ims))
+ return FALSE;
+ eptr += length;
+ }
+ /* Control never gets here */
+ }
+
+ /* If maximizing, find the longest string and work backwards */
+
+ else
+ {
+ const uschar *pp = eptr;
+ for (i = min; i < max; i++)
+ {
+ if (!match_ref(offset, eptr, length, md, ims)) break;
+ eptr += length;
+ }
+ while (eptr >= pp)
+ {
+ if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+ eptr -= length;
+ }
+ return FALSE;
+ }
+ }
+ /* Control never gets here */
+
+
+
+ /* Match a character class, possibly repeatedly. Look past the end of the
+ item to see if there is repeat information following. Then obey similar
+ code to character type repeats - written out again for speed. */
+
+ case OP_CLASS:
+ {
+ const uschar *data = ecode + 1; /* Save for matching */
+ ecode += 33; /* Advance past the item */
+
+ switch (*ecode)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ c = *ecode++ - OP_CRSTAR;
+ minimize = (c & 1) != 0;
+ min = rep_min[c]; /* Pick up values from tables; */
+ max = rep_max[c]; /* zero for max => infinity */
+ if (max == 0) max = INT_MAX;
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ minimize = (*ecode == OP_CRMINRANGE);
+ min = (ecode[1] << 8) + ecode[2];
+ max = (ecode[3] << 8) + ecode[4];
+ if (max == 0) max = INT_MAX;
+ ecode += 5;
+ break;
+
+ default: /* No repeat follows */
+ min = max = 1;
+ break;
+ }
+
+ /* First, ensure the minimum number of matches are present. */
+
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject) return FALSE;
+ GETCHARINC(c, eptr) /* Get character; increment eptr */
+
+#ifdef SUPPORT_UTF8
+ /* We do not yet support class members > 255 */
+ if (c > 255) return FALSE;
+#endif
+
+ if ((data[c/8] & (1 << (c&7))) != 0) continue;
+ return FALSE;
+ }
+
+ /* If max == min we can continue with the main loop without the
+ need to recurse. */
+
+ if (min == max) continue;
+
+ /* If minimizing, keep testing the rest of the expression and advancing
+ the pointer while it matches the class. */
+
+ if (minimize)
+ {
+ for (i = min;; i++)
+ {
+ if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+ if (i >= max || eptr >= md->end_subject) return FALSE;
+ GETCHARINC(c, eptr) /* Get character; increment eptr */
+
+#ifdef SUPPORT_UTF8
+ /* We do not yet support class members > 255 */
+ if (c > 255) return FALSE;
+#endif
+ if ((data[c/8] & (1 << (c&7))) != 0) continue;
+ return FALSE;
+ }
+ /* Control never gets here */
+ }
+
+ /* If maximizing, find the longest possible run, then work backwards. */
+
+ else
+ {
+ const uschar *pp = eptr;
+ int len = 1;
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject) break;
+ GETCHARLEN(c, eptr, len) /* Get character, set length if UTF-8 */
+
+#ifdef SUPPORT_UTF8
+ /* We do not yet support class members > 255 */
+ if (c > 255) break;
+#endif
+ if ((data[c/8] & (1 << (c&7))) == 0) break;
+ eptr += len;
+ }
+
+ while (eptr >= pp)
+ {
+ if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+
+#ifdef SUPPORT_UTF8
+ BACKCHAR(eptr)
+#endif
+ }
+ return FALSE;
+ }
+ }
+ /* Control never gets here */
+
+ /* Match a run of characters */
+
+ case OP_CHARS:
+ {
+ register int length = ecode[1];
+ ecode += 2;
+
+#ifdef DEBUG /* Sigh. Some compilers never learn. */
+ if (eptr >= md->end_subject)
+ printf("matching subject <null> against pattern ");
+ else
+ {
+ printf("matching subject ");
+ pchars(eptr, length, TRUE, md);
+ printf(" against pattern ");
+ }
+ pchars(ecode, length, FALSE, md);
+ printf("\n");
+#endif
+
+ if (length > md->end_subject - eptr) return FALSE;
+ if ((ims & PCRE_CASELESS) != 0)
+ {
+ while (length-- > 0)
+ if (md->lcc[*ecode++] != md->lcc[*eptr++])
+ return FALSE;
+ }
+ else
+ {
+ while (length-- > 0) if (*ecode++ != *eptr++) return FALSE;
+ }
+ }
+ break;
+
+ /* Match a single character repeatedly; different opcodes share code. */
+
+ case OP_EXACT:
+ min = max = (ecode[1] << 8) + ecode[2];
+ ecode += 3;
+ goto REPEATCHAR;
+
+ case OP_UPTO:
+ case OP_MINUPTO:
+ min = 0;
+ max = (ecode[1] << 8) + ecode[2];
+ minimize = *ecode == OP_MINUPTO;
+ ecode += 3;
+ goto REPEATCHAR;
+
+ case OP_STAR:
+ case OP_MINSTAR:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_QUERY:
+ case OP_MINQUERY:
+ c = *ecode++ - OP_STAR;
+ minimize = (c & 1) != 0;
+ min = rep_min[c]; /* Pick up values from tables; */
+ max = rep_max[c]; /* zero for max => infinity */
+ if (max == 0) max = INT_MAX;
+
+ /* Common code for all repeated single-character matches. We can give
+ up quickly if there are fewer than the minimum number of characters left in
+ the subject. */
+
+ REPEATCHAR:
+ if (min > md->end_subject - eptr) return FALSE;
+ c = *ecode++;
+
+ /* The code is duplicated for the caseless and caseful cases, for speed,
+ since matching characters is likely to be quite common. First, ensure the
+ minimum number of matches are present. If min = max, continue at the same
+ level without recursing. Otherwise, if minimizing, keep trying the rest of
+ the expression and advancing one matching character if failing, up to the
+ maximum. Alternatively, if maximizing, find the maximum number of
+ characters and work backwards. */
+
+ DPRINTF(("matching %c{%d,%d} against subject %.*s\n", c, min, max,
+ max, eptr));
+
+ if ((ims & PCRE_CASELESS) != 0)
+ {
+ c = md->lcc[c];
+ for (i = 1; i <= min; i++)
+ if (c != md->lcc[*eptr++]) return FALSE;
+ if (min == max) continue;
+ if (minimize)
+ {
+ for (i = min;; i++)
+ {
+ if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+ if (i >= max || eptr >= md->end_subject ||
+ c != md->lcc[*eptr++])
+ return FALSE;
+ }
+ /* Control never gets here */
+ }
+ else
+ {
+ const uschar *pp = eptr;
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject || c != md->lcc[*eptr]) break;
+ eptr++;
+ }
+ while (eptr >= pp)
+ if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+ return FALSE;
+ }
+ /* Control never gets here */
+ }
+
+ /* Caseful comparisons */
+
+ else
+ {
+ for (i = 1; i <= min; i++) if (c != *eptr++) return FALSE;
+ if (min == max) continue;
+ if (minimize)
+ {
+ for (i = min;; i++)
+ {
+ if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+ if (i >= max || eptr >= md->end_subject || c != *eptr++) return FALSE;
+ }
+ /* Control never gets here */
+ }
+ else
+ {
+ const uschar *pp = eptr;
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject || c != *eptr) break;
+ eptr++;
+ }
+ while (eptr >= pp)
+ if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+ return FALSE;
+ }
+ }
+ /* Control never gets here */
+
+ /* Match a negated single character */
+
+ case OP_NOT:
+ if (eptr >= md->end_subject) return FALSE;
+ ecode++;
+ if ((ims & PCRE_CASELESS) != 0)
+ {
+ if (md->lcc[*ecode++] == md->lcc[*eptr++]) return FALSE;
+ }
+ else
+ {
+ if (*ecode++ == *eptr++) return FALSE;
+ }
+ break;
+
+ /* Match a negated single character repeatedly. This is almost a repeat of
+ the code for a repeated single character, but I haven't found a nice way of
+ commoning these up that doesn't require a test of the positive/negative
+ option for each character match. Maybe that wouldn't add very much to the
+ time taken, but character matching *is* what this is all about... */
+
+ case OP_NOTEXACT:
+ min = max = (ecode[1] << 8) + ecode[2];
+ ecode += 3;
+ goto REPEATNOTCHAR;
+
+ case OP_NOTUPTO:
+ case OP_NOTMINUPTO:
+ min = 0;
+ max = (ecode[1] << 8) + ecode[2];
+ minimize = *ecode == OP_NOTMINUPTO;
+ ecode += 3;
+ goto REPEATNOTCHAR;
+
+ case OP_NOTSTAR:
+ case OP_NOTMINSTAR:
+ case OP_NOTPLUS:
+ case OP_NOTMINPLUS:
+ case OP_NOTQUERY:
+ case OP_NOTMINQUERY:
+ c = *ecode++ - OP_NOTSTAR;
+ minimize = (c & 1) != 0;
+ min = rep_min[c]; /* Pick up values from tables; */
+ max = rep_max[c]; /* zero for max => infinity */
+ if (max == 0) max = INT_MAX;
+
+ /* Common code for all repeated single-character matches. We can give
+ up quickly if there are fewer than the minimum number of characters left in
+ the subject. */
+
+ REPEATNOTCHAR:
+ if (min > md->end_subject - eptr) return FALSE;
+ c = *ecode++;
+
+ /* The code is duplicated for the caseless and caseful cases, for speed,
+ since matching characters is likely to be quite common. First, ensure the
+ minimum number of matches are present. If min = max, continue at the same
+ level without recursing. Otherwise, if minimizing, keep trying the rest of
+ the expression and advancing one matching character if failing, up to the
+ maximum. Alternatively, if maximizing, find the maximum number of
+ characters and work backwards. */
+
+ DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
+ max, eptr));
+
+ if ((ims & PCRE_CASELESS) != 0)
+ {
+ c = md->lcc[c];
+ for (i = 1; i <= min; i++)
+ if (c == md->lcc[*eptr++]) return FALSE;
+ if (min == max) continue;
+ if (minimize)
+ {
+ for (i = min;; i++)
+ {
+ if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+ if (i >= max || eptr >= md->end_subject ||
+ c == md->lcc[*eptr++])
+ return FALSE;
+ }
+ /* Control never gets here */
+ }
+ else
+ {
+ const uschar *pp = eptr;
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject || c == md->lcc[*eptr]) break;
+ eptr++;
+ }
+ while (eptr >= pp)
+ if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+ return FALSE;
+ }
+ /* Control never gets here */
+ }
+
+ /* Caseful comparisons */
+
+ else
+ {
+ for (i = 1; i <= min; i++) if (c == *eptr++) return FALSE;
+ if (min == max) continue;
+ if (minimize)
+ {
+ for (i = min;; i++)
+ {
+ if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+ if (i >= max || eptr >= md->end_subject || c == *eptr++) return FALSE;
+ }
+ /* Control never gets here */
+ }
+ else
+ {
+ const uschar *pp = eptr;
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject || c == *eptr) break;
+ eptr++;
+ }
+ while (eptr >= pp)
+ if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+ return FALSE;
+ }
+ }
+ /* Control never gets here */
+
+ /* Match a single character type repeatedly; several different opcodes
+ share code. This is very similar to the code for single characters, but we
+ repeat it in the interests of efficiency. */
+
+ case OP_TYPEEXACT:
+ min = max = (ecode[1] << 8) + ecode[2];
+ minimize = TRUE;
+ ecode += 3;
+ goto REPEATTYPE;
+
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ min = 0;
+ max = (ecode[1] << 8) + ecode[2];
+ minimize = *ecode == OP_TYPEMINUPTO;
+ ecode += 3;
+ goto REPEATTYPE;
+
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ c = *ecode++ - OP_TYPESTAR;
+ minimize = (c & 1) != 0;
+ min = rep_min[c]; /* Pick up values from tables; */
+ max = rep_max[c]; /* zero for max => infinity */
+ if (max == 0) max = INT_MAX;
+
+ /* Common code for all repeated single character type matches */
+
+ REPEATTYPE:
+ ctype = *ecode++; /* Code for the character type */
+
+ /* First, ensure the minimum number of matches are present. Use inline
+ code for maximizing the speed, and do the type test once at the start
+ (i.e. keep it out of the loop). Also we can test that there are at least
+ the minimum number of bytes before we start, except when doing '.' in
+ UTF8 mode. Leave the test in in all cases; in the special case we have
+ to test after each character. */
+
+ if (min > md->end_subject - eptr) return FALSE;
+ if (min > 0) switch(ctype)
+ {
+ case OP_ANY:
+#ifdef SUPPORT_UTF8
+ if (md->utf8)
+ {
+ for (i = 1; i <= min; i++)
+ {
+ if (eptr >= md->end_subject ||
+ (*eptr++ == '\n' && (ims & PCRE_DOTALL) == 0))
+ return FALSE;
+ while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
+ }
+ break;
+ }
+#endif
+ /* Non-UTF8 can be faster */
+ if ((ims & PCRE_DOTALL) == 0)
+ { for (i = 1; i <= min; i++) if (*eptr++ == '\n') return FALSE; }
+ else eptr += min;
+ break;
+
+ case OP_NOT_DIGIT:
+ for (i = 1; i <= min; i++)
+ if ((md->ctypes[*eptr++] & ctype_digit) != 0) return FALSE;
+ break;
+
+ case OP_DIGIT:
+ for (i = 1; i <= min; i++)
+ if ((md->ctypes[*eptr++] & ctype_digit) == 0) return FALSE;
+ break;
+
+ case OP_NOT_WHITESPACE:
+ for (i = 1; i <= min; i++)
+ if ((md->ctypes[*eptr++] & ctype_space) != 0) return FALSE;
+ break;
+
+ case OP_WHITESPACE:
+ for (i = 1; i <= min; i++)
+ if ((md->ctypes[*eptr++] & ctype_space) == 0) return FALSE;
+ break;
+
+ case OP_NOT_WORDCHAR:
+ for (i = 1; i <= min; i++)
+ if ((md->ctypes[*eptr++] & ctype_word) != 0)
+ return FALSE;
+ break;
+
+ case OP_WORDCHAR:
+ for (i = 1; i <= min; i++)
+ if ((md->ctypes[*eptr++] & ctype_word) == 0)
+ return FALSE;
+ break;
+ }
+
+ /* If min = max, continue at the same level without recursing */
+
+ if (min == max) continue;
+
+ /* If minimizing, we have to test the rest of the pattern before each
+ subsequent match. */
+
+ if (minimize)
+ {
+ for (i = min;; i++)
+ {
+ if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE;
+ if (i >= max || eptr >= md->end_subject) return FALSE;
+
+ c = *eptr++;
+ switch(ctype)
+ {
+ case OP_ANY:
+ if ((ims & PCRE_DOTALL) == 0 && c == '\n') return FALSE;
+#ifdef SUPPORT_UTF8
+ if (md->utf8)
+ while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
+#endif
+ break;
+
+ case OP_NOT_DIGIT:
+ if ((md->ctypes[c] & ctype_digit) != 0) return FALSE;
+ break;
+
+ case OP_DIGIT:
+ if ((md->ctypes[c] & ctype_digit) == 0) return FALSE;
+ break;
+
+ case OP_NOT_WHITESPACE:
+ if ((md->ctypes[c] & ctype_space) != 0) return FALSE;
+ break;
+
+ case OP_WHITESPACE:
+ if ((md->ctypes[c] & ctype_space) == 0) return FALSE;
+ break;
+
+ case OP_NOT_WORDCHAR:
+ if ((md->ctypes[c] & ctype_word) != 0) return FALSE;
+ break;
+
+ case OP_WORDCHAR:
+ if ((md->ctypes[c] & ctype_word) == 0) return FALSE;
+ break;
+ }
+ }
+ /* Control never gets here */
+ }
+
+ /* If maximizing it is worth using inline code for speed, doing the type
+ test once at the start (i.e. keep it out of the loop). */
+
+ else
+ {
+ const uschar *pp = eptr;
+ switch(ctype)
+ {
+ case OP_ANY:
+
+ /* Special code is required for UTF8, but when the maximum is unlimited
+ we don't need it. */
+
+#ifdef SUPPORT_UTF8
+ if (md->utf8 && max < INT_MAX)
+ {
+ if ((ims & PCRE_DOTALL) == 0)
+ {
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject || *eptr++ == '\n') break;
+ while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
+ }
+ }
+ else
+ {
+ for (i = min; i < max; i++)
+ {
+ eptr++;
+ while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
+ }
+ }
+ break;
+ }
+#endif
+ /* Non-UTF8 can be faster */
+ if ((ims & PCRE_DOTALL) == 0)
+ {
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject || *eptr == '\n') break;
+ eptr++;
+ }
+ }
+ else
+ {
+ c = max - min;
+ if (c > md->end_subject - eptr) c = md->end_subject - eptr;
+ eptr += c;
+ }
+ break;
+
+ case OP_NOT_DIGIT:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
+ break;
+ eptr++;
+ }
+ break;
+
+ case OP_DIGIT:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
+ break;
+ eptr++;
+ }
+ break;
+
+ case OP_NOT_WHITESPACE:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
+ break;
+ eptr++;
+ }
+ break;
+
+ case OP_WHITESPACE:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
+ break;
+ eptr++;
+ }
+ break;
+
+ case OP_NOT_WORDCHAR:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
+ break;
+ eptr++;
+ }
+ break;
+
+ case OP_WORDCHAR:
+ for (i = min; i < max; i++)
+ {
+ if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
+ break;
+ eptr++;
+ }
+ break;
+ }
+
+ while (eptr >= pp)
+ {
+ if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
+ return TRUE;
+#ifdef SUPPORT_UTF8
+ if (md->utf8)
+ while (eptr > pp && (*eptr & 0xc0) == 0x80) eptr--;
+#endif
+ }
+ return FALSE;
+ }
+ /* Control never gets here */
+
+ /* There's been some horrible disaster. */
+
+ default:
+ DPRINTF(("Unknown opcode %d\n", *ecode));
+ md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
+ return FALSE;
+ }
+
+ /* Do not stick any code in here without much thought; it is assumed
+ that "continue" in the code above comes out to here to repeat the main
+ loop. */
+
+ } /* End of main loop */
+/* Control never reaches here */
+}
+
+
+
+
+/*************************************************
+* Execute a Regular Expression *
+*************************************************/
+
+/* This function applies a compiled re to a subject string and picks out
+portions of the string if it matches. Two elements in the vector are set for
+each substring: the offsets to the start and end of the substring.
+
+Arguments:
+ external_re points to the compiled expression
+ external_extra points to "hints" from pcre_study() or is NULL
+ subject points to the subject string
+ length length of subject string (may contain binary zeros)
+ start_offset where to start in the subject string
+ options option bits
+ offsets points to a vector of ints to be filled in with offsets
+ offsetcount the number of elements in the vector
+
+Returns: > 0 => success; value is the number of elements filled in
+ = 0 => success, but offsets is not big enough
+ -1 => failed to match
+ < -1 => some kind of unexpected problem
+*/
+
+int
+pcre_exec(const pcre *external_re, const pcre_extra *external_extra,
+ const char *subject, int length, int start_offset, int options, int *offsets,
+ int offsetcount)
+{
+int resetcount, ocount;
+int first_char = -1;
+int req_char = -1;
+int req_char2 = -1;
+unsigned long int ims = 0;
+match_data match_block;
+const uschar *start_bits = NULL;
+const uschar *start_match = (const uschar *)subject + start_offset;
+const uschar *end_subject;
+const uschar *req_char_ptr = start_match - 1;
+const real_pcre *re = (const real_pcre *)external_re;
+const real_pcre_extra *extra = (const real_pcre_extra *)external_extra;
+BOOL using_temporary_offsets = FALSE;
+BOOL anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
+BOOL startline = (re->options & PCRE_STARTLINE) != 0;
+
+if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
+
+if (re == NULL || subject == NULL ||
+ (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
+if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
+
+match_block.start_pattern = re->code;
+match_block.start_subject = (const uschar *)subject;
+match_block.end_subject = match_block.start_subject + length;
+end_subject = match_block.end_subject;
+
+match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
+match_block.utf8 = (re->options & PCRE_UTF8) != 0;
+
+match_block.notbol = (options & PCRE_NOTBOL) != 0;
+match_block.noteol = (options & PCRE_NOTEOL) != 0;
+match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
+
+match_block.errorcode = PCRE_ERROR_NOMATCH; /* Default error */
+
+match_block.lcc = re->tables + lcc_offset;
+match_block.ctypes = re->tables + ctypes_offset;
+
+/* The ims options can vary during the matching as a result of the presence
+of (?ims) items in the pattern. They are kept in a local variable so that
+restoring at the exit of a group is easy. */
+
+ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL);
+
+/* If the expression has got more back references than the offsets supplied can
+hold, we get a temporary bit of working store to use during the matching.
+Otherwise, we can use the vector supplied, rounding down its size to a multiple
+of 3. */
+
+ocount = offsetcount - (offsetcount % 3);
+
+if (re->top_backref > 0 && re->top_backref >= ocount/3)
+ {
+ ocount = re->top_backref * 3 + 3;
+ match_block.offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int));
+ if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
+ using_temporary_offsets = TRUE;
+ DPRINTF(("Got memory to hold back references\n"));
+ }
+else match_block.offset_vector = offsets;
+
+match_block.offset_end = ocount;
+match_block.offset_max = (2*ocount)/3;
+match_block.offset_overflow = FALSE;
+
+/* Compute the minimum number of offsets that we need to reset each time. Doing
+this makes a huge difference to execution time when there aren't many brackets
+in the pattern. */
+
+resetcount = 2 + re->top_bracket * 2;
+if (resetcount > offsetcount) resetcount = ocount;
+
+/* Reset the working variable associated with each extraction. These should
+never be used unless previously set, but they get saved and restored, and so we
+initialize them to avoid reading uninitialized locations. */
+
+if (match_block.offset_vector != NULL)
+ {
+ register int *iptr = match_block.offset_vector + ocount;
+ register int *iend = iptr - resetcount/2 + 1;
+ while (--iptr >= iend) *iptr = -1;
+ }
+
+/* Set up the first character to match, if available. The first_char value is
+never set for an anchored regular expression, but the anchoring may be forced
+at run time, so we have to test for anchoring. The first char may be unset for
+an unanchored pattern, of course. If there's no first char and the pattern was
+studied, there may be a bitmap of possible first characters. */
+
+if (!anchored)
+ {
+ if ((re->options & PCRE_FIRSTSET) != 0)
+ {
+ first_char = re->first_char;
+ if ((ims & PCRE_CASELESS) != 0) first_char = match_block.lcc[first_char];
+ }
+ else
+ if (!startline && extra != NULL &&
+ (extra->options & PCRE_STUDY_MAPPED) != 0)
+ start_bits = extra->start_bits;
+ }
+
+/* For anchored or unanchored matches, there may be a "last known required
+character" set. If the PCRE_CASELESS is set, implying that the match starts
+caselessly, or if there are any changes of this flag within the regex, set up
+both cases of the character. Otherwise set the two values the same, which will
+avoid duplicate testing (which takes significant time). This covers the vast
+majority of cases. It will be suboptimal when the case flag changes in a regex
+and the required character in fact is caseful. */
+
+if ((re->options & PCRE_REQCHSET) != 0)
+ {
+ req_char = re->req_char;
+ req_char2 = ((re->options & (PCRE_CASELESS | PCRE_ICHANGED)) != 0)?
+ (re->tables + fcc_offset)[req_char] : req_char;
+ }
+
+/* Loop for handling unanchored repeated matching attempts; for anchored regexs
+the loop runs just once. */
+
+do
+ {
+ int rc;
+ register int *iptr = match_block.offset_vector;
+ register int *iend = iptr + resetcount;
+
+ /* Reset the maximum number of extractions we might see. */
+
+ while (iptr < iend) *iptr++ = -1;
+
+ /* Advance to a unique first char if possible */
+
+ if (first_char >= 0)
+ {
+ if ((ims & PCRE_CASELESS) != 0)
+ while (start_match < end_subject &&
+ match_block.lcc[*start_match] != first_char)
+ start_match++;
+ else
+ while (start_match < end_subject && *start_match != first_char)
+ start_match++;
+ }
+
+ /* Or to just after \n for a multiline match if possible */
+
+ else if (startline)
+ {
+ if (start_match > match_block.start_subject + start_offset)
+ {
+ while (start_match < end_subject && start_match[-1] != '\n')
+ start_match++;
+ }
+ }
+
+ /* Or to a non-unique first char after study */
+
+ else if (start_bits != NULL)
+ {
+ while (start_match < end_subject)
+ {
+ register int c = *start_match;
+ if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break;
+ }
+ }
+
+#ifdef DEBUG /* Sigh. Some compilers never learn. */
+ printf(">>>> Match against: ");
+ pchars(start_match, end_subject - start_match, TRUE, &match_block);
+ printf("\n");
+#endif
+
+ /* If req_char is set, we know that that character must appear in the subject
+ for the match to succeed. If the first character is set, req_char must be
+ later in the subject; otherwise the test starts at the match point. This
+ optimization can save a huge amount of backtracking in patterns with nested
+ unlimited repeats that aren't going to match. We don't know what the state of
+ case matching may be when this character is hit, so test for it in both its
+ cases if necessary. However, the different cased versions will not be set up
+ unless PCRE_CASELESS was given or the casing state changes within the regex.
+ Writing separate code makes it go faster, as does using an autoincrement and
+ backing off on a match. */
+
+ if (req_char >= 0)
+ {
+ register const uschar *p = start_match + ((first_char >= 0)? 1 : 0);
+
+ /* We don't need to repeat the search if we haven't yet reached the
+ place we found it at last time. */
+
+ if (p > req_char_ptr)
+ {
+ /* Do a single test if no case difference is set up */
+
+ if (req_char == req_char2)
+ {
+ while (p < end_subject)
+ {
+ if (*p++ == req_char) { p--; break; }
+ }
+ }
+
+ /* Otherwise test for either case */
+
+ else
+ {
+ while (p < end_subject)
+ {
+ register int pp = *p++;
+ if (pp == req_char || pp == req_char2) { p--; break; }
+ }
+ }
+
+ /* If we can't find the required character, break the matching loop */
+
+ if (p >= end_subject) break;
+
+ /* If we have found the required character, save the point where we
+ found it, so that we don't search again next time round the loop if
+ the start hasn't passed this character yet. */
+
+ req_char_ptr = p;
+ }
+ }
+
+ /* When a match occurs, substrings will be set for all internal extractions;
+ we just need to set up the whole thing as substring 0 before returning. If
+ there were too many extractions, set the return code to zero. In the case
+ where we had to get some local store to hold offsets for backreferences, copy
+ those back references that we can. In this case there need not be overflow
+ if certain parts of the pattern were not used. */
+
+ match_block.start_match = start_match;
+ if (!match(start_match, re->code, 2, &match_block, ims, NULL, match_isgroup))
+ continue;
+
+ /* Copy the offset information from temporary store if necessary */
+
+ if (using_temporary_offsets)
+ {
+ if (offsetcount >= 4)
+ {
+ memcpy(offsets + 2, match_block.offset_vector + 2,
+ (offsetcount - 2) * sizeof(int));
+ DPRINTF(("Copied offsets from temporary memory\n"));
+ }
+ if (match_block.end_offset_top > offsetcount)
+ match_block.offset_overflow = TRUE;
+
+ DPRINTF(("Freeing temporary memory\n"));
+ (pcre_free)(match_block.offset_vector);
+ }
+
+ rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
+
+ if (match_block.offset_end < 2) rc = 0; else
+ {
+ offsets[0] = start_match - match_block.start_subject;
+ offsets[1] = match_block.end_match_ptr - match_block.start_subject;
+ }
+
+ DPRINTF((">>>> returning %d\n", rc));
+ return rc;
+ }
+
+/* This "while" is the end of the "do" above */
+
+while (!anchored &&
+ match_block.errorcode == PCRE_ERROR_NOMATCH &&
+ start_match++ < end_subject);
+
+if (using_temporary_offsets)
+ {
+ DPRINTF(("Freeing temporary memory\n"));
+ (pcre_free)(match_block.offset_vector);
+ }
+
+DPRINTF((">>>> returning %d\n", match_block.errorcode));
+
+return match_block.errorcode;
+}
+
+/* End of pcre.c */
--- /dev/null
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* Copyright (c) 1997-2000 University of Cambridge */
+
+#ifndef _PCRE_H
+#define _PCRE_H
+
+/* The file pcre.h is build by "configure". Do not edit it; instead
+make changes to pcre.in. */
+
+#define PCRE_MAJOR 3
+#define PCRE_MINOR 4
+#define PCRE_DATE 22-Aug-2000
+
+/* Win32 uses DLL by default */
+
+#ifdef _WIN32
+# ifdef STATIC
+# define PCRE_DL_IMPORT
+# else
+# define PCRE_DL_IMPORT __declspec(dllimport)
+# endif
+#else
+# define PCRE_DL_IMPORT
+#endif
+
+/* Have to include stdlib.h in order to ensure that size_t is defined;
+it is needed here for malloc. */
+
+#include <stdlib.h>
+
+/* Allow for C++ users */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Options */
+
+#define PCRE_CASELESS 0x0001
+#define PCRE_MULTILINE 0x0002
+#define PCRE_DOTALL 0x0004
+#define PCRE_EXTENDED 0x0008
+#define PCRE_ANCHORED 0x0010
+#define PCRE_DOLLAR_ENDONLY 0x0020
+#define PCRE_EXTRA 0x0040
+#define PCRE_NOTBOL 0x0080
+#define PCRE_NOTEOL 0x0100
+#define PCRE_UNGREEDY 0x0200
+#define PCRE_NOTEMPTY 0x0400
+#define PCRE_UTF8 0x0800
+
+/* Exec-time and get-time error codes */
+
+#define PCRE_ERROR_NOMATCH (-1)
+#define PCRE_ERROR_NULL (-2)
+#define PCRE_ERROR_BADOPTION (-3)
+#define PCRE_ERROR_BADMAGIC (-4)
+#define PCRE_ERROR_UNKNOWN_NODE (-5)
+#define PCRE_ERROR_NOMEMORY (-6)
+#define PCRE_ERROR_NOSUBSTRING (-7)
+
+/* Request types for pcre_fullinfo() */
+
+#define PCRE_INFO_OPTIONS 0
+#define PCRE_INFO_SIZE 1
+#define PCRE_INFO_CAPTURECOUNT 2
+#define PCRE_INFO_BACKREFMAX 3
+#define PCRE_INFO_FIRSTCHAR 4
+#define PCRE_INFO_FIRSTTABLE 5
+#define PCRE_INFO_LASTLITERAL 6
+
+/* Types */
+
+typedef void pcre;
+typedef void pcre_extra;
+
+/* Store get and free functions. These can be set to alternative malloc/free
+functions if required. Some magic is required for Win32 DLL; it is null on
+other OS. */
+
+PCRE_DL_IMPORT extern void *(*pcre_malloc)(size_t);
+PCRE_DL_IMPORT extern void (*pcre_free)(void *);
+
+#undef PCRE_DL_IMPORT
+
+/* Functions */
+
+extern pcre *pcre_compile(const char *, int, const char **, int *,
+ const unsigned char *);
+extern int pcre_copy_substring(const char *, int *, int, int, char *, int);
+extern int pcre_exec(const pcre *, const pcre_extra *, const char *,
+ int, int, int, int *, int);
+extern void pcre_free_substring(const char *);
+extern void pcre_free_substring_list(const char **);
+extern int pcre_get_substring(const char *, int *, int, int, const char **);
+extern int pcre_get_substring_list(const char *, int *, int, const char ***);
+extern int pcre_info(const pcre *, int *, int *);
+extern int pcre_fullinfo(const pcre *, const pcre_extra *, int, void *);
+extern unsigned const char *pcre_maketables(void);
+extern pcre_extra *pcre_study(const pcre *, int, const char **);
+extern const char *pcre_version(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* End of pcre.h */
--- /dev/null
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* Copyright (c) 1997-2000 University of Cambridge */
+
+#ifndef _PCRE_H
+#define _PCRE_H
+
+/* The file pcre.h is build by "configure". Do not edit it; instead
+make changes to pcre.in. */
+
+#define PCRE_MAJOR @PCRE_MAJOR@
+#define PCRE_MINOR @PCRE_MINOR@
+#define PCRE_DATE @PCRE_DATE@
+
+/* Win32 uses DLL by default */
+
+#ifdef _WIN32
+# ifdef STATIC
+# define PCRE_DL_IMPORT
+# else
+# define PCRE_DL_IMPORT __declspec(dllimport)
+# endif
+#else
+# define PCRE_DL_IMPORT
+#endif
+
+/* Have to include stdlib.h in order to ensure that size_t is defined;
+it is needed here for malloc. */
+
+#include <stdlib.h>
+
+/* Allow for C++ users */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Options */
+
+#define PCRE_CASELESS 0x0001
+#define PCRE_MULTILINE 0x0002
+#define PCRE_DOTALL 0x0004
+#define PCRE_EXTENDED 0x0008
+#define PCRE_ANCHORED 0x0010
+#define PCRE_DOLLAR_ENDONLY 0x0020
+#define PCRE_EXTRA 0x0040
+#define PCRE_NOTBOL 0x0080
+#define PCRE_NOTEOL 0x0100
+#define PCRE_UNGREEDY 0x0200
+#define PCRE_NOTEMPTY 0x0400
+#define PCRE_UTF8 0x0800
+
+/* Exec-time and get-time error codes */
+
+#define PCRE_ERROR_NOMATCH (-1)
+#define PCRE_ERROR_NULL (-2)
+#define PCRE_ERROR_BADOPTION (-3)
+#define PCRE_ERROR_BADMAGIC (-4)
+#define PCRE_ERROR_UNKNOWN_NODE (-5)
+#define PCRE_ERROR_NOMEMORY (-6)
+#define PCRE_ERROR_NOSUBSTRING (-7)
+
+/* Request types for pcre_fullinfo() */
+
+#define PCRE_INFO_OPTIONS 0
+#define PCRE_INFO_SIZE 1
+#define PCRE_INFO_CAPTURECOUNT 2
+#define PCRE_INFO_BACKREFMAX 3
+#define PCRE_INFO_FIRSTCHAR 4
+#define PCRE_INFO_FIRSTTABLE 5
+#define PCRE_INFO_LASTLITERAL 6
+
+/* Types */
+
+typedef void pcre;
+typedef void pcre_extra;
+
+/* Store get and free functions. These can be set to alternative malloc/free
+functions if required. Some magic is required for Win32 DLL; it is null on
+other OS. */
+
+PCRE_DL_IMPORT extern void *(*pcre_malloc)(size_t);
+PCRE_DL_IMPORT extern void (*pcre_free)(void *);
+
+#undef PCRE_DL_IMPORT
+
+/* Functions */
+
+extern pcre *pcre_compile(const char *, int, const char **, int *,
+ const unsigned char *);
+extern int pcre_copy_substring(const char *, int *, int, int, char *, int);
+extern int pcre_exec(const pcre *, const pcre_extra *, const char *,
+ int, int, int, int *, int);
+extern void pcre_free_substring(const char *);
+extern void pcre_free_substring_list(const char **);
+extern int pcre_get_substring(const char *, int *, int, int, const char **);
+extern int pcre_get_substring_list(const char *, int *, int, const char ***);
+extern int pcre_info(const pcre *, int *, int *);
+extern int pcre_fullinfo(const pcre *, const pcre_extra *, int, void *);
+extern unsigned const char *pcre_maketables(void);
+extern pcre_extra *pcre_study(const pcre *, int, const char **);
+extern const char *pcre_version(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* End of pcre.h */
--- /dev/null
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/*
+This is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language. See
+the file Tech.Notes for some information on the internals.
+
+This module is a wrapper that provides a POSIX API to the underlying PCRE
+functions.
+
+Written by: Philip Hazel <ph10@cam.ac.uk>
+
+ Copyright (c) 1997-2000 University of Cambridge
+
+-----------------------------------------------------------------------------
+Permission is granted to anyone to use this software for any purpose on any
+computer system, and to redistribute it freely, subject to the following
+restrictions:
+
+1. This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+2. The origin of this software must not be misrepresented, either by
+ explicit claim or by omission.
+
+3. Altered versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+4. If PCRE is embedded in any software that is released under the GNU
+ General Purpose Licence (GPL), then the terms of that licence shall
+ supersede any condition above with which it is incompatible.
+-----------------------------------------------------------------------------
+*/
+
+#include "internal.h"
+#include "pcreposix.h"
+#include "stdlib.h"
+
+
+
+/* Corresponding tables of PCRE error messages and POSIX error codes. */
+
+static const char *estring[] = {
+ ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10,
+ ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20,
+ ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR29, ERR29, ERR30,
+ ERR31 };
+
+static int eint[] = {
+ REG_EESCAPE, /* "\\ at end of pattern" */
+ REG_EESCAPE, /* "\\c at end of pattern" */
+ REG_EESCAPE, /* "unrecognized character follows \\" */
+ REG_BADBR, /* "numbers out of order in {} quantifier" */
+ REG_BADBR, /* "number too big in {} quantifier" */
+ REG_EBRACK, /* "missing terminating ] for character class" */
+ REG_ECTYPE, /* "invalid escape sequence in character class" */
+ REG_ERANGE, /* "range out of order in character class" */
+ REG_BADRPT, /* "nothing to repeat" */
+ REG_BADRPT, /* "operand of unlimited repeat could match the empty string" */
+ REG_ASSERT, /* "internal error: unexpected repeat" */
+ REG_BADPAT, /* "unrecognized character after (?" */
+ REG_ESIZE, /* "too many capturing parenthesized sub-patterns" */
+ REG_EPAREN, /* "missing )" */
+ REG_ESUBREG, /* "back reference to non-existent subpattern" */
+ REG_INVARG, /* "erroffset passed as NULL" */
+ REG_INVARG, /* "unknown option bit(s) set" */
+ REG_EPAREN, /* "missing ) after comment" */
+ REG_ESIZE, /* "too many sets of parentheses" */
+ REG_ESIZE, /* "regular expression too large" */
+ REG_ESPACE, /* "failed to get memory" */
+ REG_EPAREN, /* "unmatched brackets" */
+ REG_ASSERT, /* "internal error: code overflow" */
+ REG_BADPAT, /* "unrecognized character after (?<" */
+ REG_BADPAT, /* "lookbehind assertion is not fixed length" */
+ REG_BADPAT, /* "malformed number after (?(" */
+ REG_BADPAT, /* "conditional group containe more than two branches" */
+ REG_BADPAT, /* "assertion expected after (?(" */
+ REG_BADPAT, /* "(?p must be followed by )" */
+ REG_ECTYPE, /* "unknown POSIX class name" */
+ REG_BADPAT, /* "POSIX collating elements are not supported" */
+ REG_INVARG, /* "this version of PCRE is not compiled with PCRE_UTF8 support" */
+ REG_BADPAT, /* "characters with values > 255 are not yet supported in classes" */
+ REG_BADPAT, /* "character value in \x{...} sequence is too large" */
+ REG_BADPAT /* "invalid condition (?(0)" */
+};
+
+/* Table of texts corresponding to POSIX error codes */
+
+static const char *pstring[] = {
+ "", /* Dummy for value 0 */
+ "internal error", /* REG_ASSERT */
+ "invalid repeat counts in {}", /* BADBR */
+ "pattern error", /* BADPAT */
+ "? * + invalid", /* BADRPT */
+ "unbalanced {}", /* EBRACE */
+ "unbalanced []", /* EBRACK */
+ "collation error - not relevant", /* ECOLLATE */
+ "bad class", /* ECTYPE */
+ "bad escape sequence", /* EESCAPE */
+ "empty expression", /* EMPTY */
+ "unbalanced ()", /* EPAREN */
+ "bad range inside []", /* ERANGE */
+ "expression too big", /* ESIZE */
+ "failed to get memory", /* ESPACE */
+ "bad back reference", /* ESUBREG */
+ "bad argument", /* INVARG */
+ "match failed" /* NOMATCH */
+};
+
+
+
+
+/*************************************************
+* Translate PCRE text code to int *
+*************************************************/
+
+/* PCRE compile-time errors are given as strings defined as macros. We can just
+look them up in a table to turn them into POSIX-style error codes. */
+
+static int
+pcre_posix_error_code(const char *s)
+{
+size_t i;
+for (i = 0; i < sizeof(estring)/sizeof(char *); i++)
+ if (strcmp(s, estring[i]) == 0) return eint[i];
+return REG_ASSERT;
+}
+
+
+
+/*************************************************
+* Translate error code to string *
+*************************************************/
+
+size_t
+regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
+{
+const char *message, *addmessage;
+size_t length, addlength;
+
+message = (errcode >= (int)(sizeof(pstring)/sizeof(char *)))?
+ "unknown error code" : pstring[errcode];
+length = strlen(message) + 1;
+
+addmessage = " at offset ";
+addlength = (preg != NULL && (int)preg->re_erroffset != -1)?
+ strlen(addmessage) + 6 : 0;
+
+if (errbuf_size > 0)
+ {
+ if (addlength > 0 && errbuf_size >= length + addlength)
+ sprintf(errbuf, "%s%s%-6d", message, addmessage, (int)preg->re_erroffset);
+ else
+ {
+ strncpy(errbuf, message, errbuf_size - 1);
+ errbuf[errbuf_size-1] = 0;
+ }
+ }
+
+return length + addlength;
+}
+
+
+
+
+/*************************************************
+* Free store held by a regex *
+*************************************************/
+
+void
+regfree(regex_t *preg)
+{
+(pcre_free)(preg->re_pcre);
+}
+
+
+
+
+/*************************************************
+* Compile a regular expression *
+*************************************************/
+
+/*
+Arguments:
+ preg points to a structure for recording the compiled expression
+ pattern the pattern to compile
+ cflags compilation flags
+
+Returns: 0 on success
+ various non-zero codes on failure
+*/
+
+int
+regcomp(regex_t *preg, const char *pattern, int cflags)
+{
+const char *errorptr;
+int erroffset;
+int options = 0;
+
+if ((cflags & REG_ICASE) != 0) options |= PCRE_CASELESS;
+if ((cflags & REG_NEWLINE) != 0) options |= PCRE_MULTILINE;
+
+preg->re_pcre = pcre_compile(pattern, options, &errorptr, &erroffset, NULL);
+preg->re_erroffset = erroffset;
+
+if (preg->re_pcre == NULL) return pcre_posix_error_code(errorptr);
+
+preg->re_nsub = pcre_info(preg->re_pcre, NULL, NULL);
+return 0;
+}
+
+
+
+
+/*************************************************
+* Match a regular expression *
+*************************************************/
+
+/* Unfortunately, PCRE requires 3 ints of working space for each captured
+substring, so we have to get and release working store instead of just using
+the POSIX structures as was done in earlier releases when PCRE needed only 2
+ints. */
+
+int
+regexec(regex_t *preg, const char *string, size_t nmatch,
+ regmatch_t pmatch[], int eflags)
+{
+int rc;
+int options = 0;
+int *ovector = NULL;
+
+if ((eflags & REG_NOTBOL) != 0) options |= PCRE_NOTBOL;
+if ((eflags & REG_NOTEOL) != 0) options |= PCRE_NOTEOL;
+
+preg->re_erroffset = (size_t)(-1); /* Only has meaning after compile */
+
+if (nmatch > 0)
+ {
+ ovector = (int *)malloc(sizeof(int) * nmatch * 3);
+ if (ovector == NULL) return REG_ESPACE;
+ }
+
+rc = pcre_exec(preg->re_pcre, NULL, string, (int)strlen(string), 0, options,
+ ovector, nmatch * 3);
+
+if (rc == 0) rc = nmatch; /* All captured slots were filled in */
+
+if (rc >= 0)
+ {
+ size_t i;
+ for (i = 0; i < rc; i++)
+ {
+ pmatch[i].rm_so = ovector[i*2];
+ pmatch[i].rm_eo = ovector[i*2+1];
+ }
+ if (ovector != NULL) free(ovector);
+ for (; i < nmatch; i++) pmatch[i].rm_so = pmatch[i].rm_eo = -1;
+ return 0;
+ }
+
+else
+ {
+ if (ovector != NULL) free(ovector);
+ switch(rc)
+ {
+ case PCRE_ERROR_NOMATCH: return REG_NOMATCH;
+ case PCRE_ERROR_NULL: return REG_INVARG;
+ case PCRE_ERROR_BADOPTION: return REG_INVARG;
+ case PCRE_ERROR_BADMAGIC: return REG_INVARG;
+ case PCRE_ERROR_UNKNOWN_NODE: return REG_ASSERT;
+ case PCRE_ERROR_NOMEMORY: return REG_ESPACE;
+ default: return REG_ASSERT;
+ }
+ }
+}
+
+/* End of pcreposix.c */
--- /dev/null
+const char pcrs_rcs[] = "$Id: pcrs.c,v 1.1 2001/05/13 21:57:07 administrator Exp $";
+
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/pcrs.c,v $
+ *
+ * Purpose : This is the pre-pre-alpha realease of libpcrs. It is only
+ * published at this (ugly) stage of development, because it is
+ * needed for a new feature in JunkBuster.
+ *
+ * Apart from the code being quite a mess, no inconsistencies,
+ * memory leaks or functional bugs **should** be present.
+ *
+ * While you ROTFL at the code, you could just as well mail me
+ * (andreas@oesterhelt.org) with advice for improvement.
+ *
+ * pcrs is a supplement to the brilliant pcre library by Philip
+ * Hazel (ph10@cam.ac.uk) and adds Perl-style substitution. That
+ * is, it mimics Perl's 's' operator.
+ *
+ * Currently, there's no documentation besides comments and the
+ * source itself ;-)
+ *
+ * Copyright : Written and copyright by andreas@oesterhelt.org
+ *
+ * Revisions :
+ * $Log: pcrs.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include <pcre.h>
+#include <string.h>
+#include "pcrs.h"
+const char pcrs_h_rcs[] = PCRS_H_VERSION;
+
+
+/*********************************************************************
+ *
+ * Function : my_strsep
+ *
+ * Description : Convenience function. It acts like strsep, except that
+ * it respects quoting of the delimiter character with the
+ * quote character. (And, of course, quoting the quote char
+ * with itself.) Called from `pcrs_make_job'.
+ *
+ * Parameters :
+ * 1 : token = current token
+ * 2 : text = string to tokenize
+ * 3 : delimiter = single character deliminter
+ * 4 : quote_char = character to cause quoting
+ *
+ * Returns : -1 => failure, else the length of the token found.
+ * In the latter case, *text is the token's start.
+ *
+ *********************************************************************/
+int my_strsep(char *token, char **text, char delimiter, char quote_char)
+{
+ int i, k=0, limit, quoted = FALSE;
+
+ limit = strlen(*text);
+ if ( 0 == limit )
+ {
+ return -1;
+ }
+
+ token[0] = '\0';
+
+ for (i=0; i < limit; i++)
+ {
+ if (text[0][i] == delimiter && !quoted)
+ {
+ *text += 1;
+ break;
+ }
+ else if (text[0][i] == quote_char && !quoted && i+1 < limit && text[0][i+1] == delimiter)
+ {
+ quoted = TRUE;
+ continue;
+ }
+ token[k++] = text[0][i];
+ quoted = FALSE;
+ }
+ token[k] = '\0';
+ *text += i;
+ return k;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : pcrs_compile_perl_options
+ *
+ * Description : This function parses a string containing the options to
+ * Perl's s/// operator. It returns an integer that is the
+ * pcre equivalent of the symbolic optstring.
+ * Since pcre doesn't know about Perl's 'g' (global) option,
+ * but pcrs needs it, the globalflag integer is set if 'g'
+ * is encountered.
+ *
+ * Parameters :
+ * 1 : optstring = string with options in perl syntax
+ * 2 : globalflag = see description
+ *
+ * Returns : option integer suitable for pcre
+ *
+ *********************************************************************/
+int pcrs_compile_perl_options(char *optstring, int *globalflag)
+{
+ int i, rc = 0;
+ *globalflag = 0;
+ for (i=0; i < strlen(optstring); i++)
+ {
+ switch(optstring[i])
+ {
+ case 'e': break;
+ case 'g': *globalflag = 1; break;
+ case 'i': rc |= PCRE_CASELESS; break;
+ case 'm': rc |= PCRE_MULTILINE; break;
+ case 'o': break;
+ case 's': rc |= PCRE_DOTALL; break;
+ case 'x': rc |= PCRE_EXTENDED; break;
+ default: break;
+ }
+ }
+ return rc;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : pcrs_compile_replacement
+ *
+ * Description : This function takes a Perl-style replacement (2nd argument
+ * to the s/// operator and returns a compiled pcrs_substitute,
+ * or NULL if memory allocation for the substitute structure
+ * fails.
+ *
+ * Parameters :
+ * 1 : replacement = replacement part of s/// operator
+ * in perl syntax
+ * 2 : errptr = pointer to an integer in which error
+ * conditions can be returned.
+ *
+ * Returns : pcrs_substitute data structure, or NULL if an
+ * error is encountered. In that case, *errptr has
+ * the reason.
+ *
+ *********************************************************************/
+pcrs_substitute *pcrs_compile_replacement(char *replacement, int *errptr)
+{
+ int length, i, k = 0, l = 0, quoted = 0, idx;
+ char *text, *num_ptr, *numbers = "0123456789";
+ pcrs_substitute *r;
+
+ r = (pcrs_substitute *)malloc(sizeof(pcrs_substitute));
+ if (r == NULL) return NULL;
+ memset(r, '\0', sizeof(pcrs_substitute));
+
+ text = strdup(replacement); /* must be free()d by caller */
+ if (text == NULL)
+ {
+ *errptr = PCRS_ERR_NOMEM;
+ free(r);
+ return NULL;
+ }
+
+ length = strlen(replacement);
+
+ for (i=0; i < length; i++)
+ {
+ /* Backslash treatment */
+ if (replacement[i] == '\\')
+ {
+ if (quoted)
+ {
+ text[k++] = replacement[i];
+ quoted = 0;
+ }
+ else
+ {
+ quoted = 1;
+ }
+ continue;
+ }
+
+ /* Dollar treatment */
+ if (replacement[i] == '$' && !quoted && i < length - 1)
+ {
+ if (strchr("0123456789&", replacement[i + 1]) == NULL)
+ {
+ text[k++] = replacement[i];
+ }
+ else
+ {
+ r->block_length[l] = k - r->block_offset[l];
+ r->backref[l] = 0;
+ if (replacement[i + 1] != '&')
+ {
+ while ((num_ptr = strchr(numbers, replacement[++i])) != NULL && i < length)
+ {
+ idx = num_ptr - numbers;
+ r->backref[l] = r->backref[l] * 10 + idx;
+ }
+ i--;
+ }
+ else
+ i++;
+ if (r->backref[l] < PCRS_MAX_SUBMATCHES)
+ r->backref_count[r->backref[l]] += 1;
+ l++;
+ r->block_offset[l] = k;
+ }
+ continue;
+ }
+
+ /* Plain char treatment */
+ text[k++] = replacement[i];
+ quoted = 0;
+ }
+
+ text[k] = '\0';
+ r->text = text;
+ r->backrefs = l;
+ r->block_length[l] = k - r->block_offset[l];
+ return r;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : pcrs_free_job
+ *
+ * Description : Frees the memory used by a pcrs_job struct and its
+ * dependant structures. Returns a pointer to the next
+ * job, if there was any, or NULL otherwise.
+ *
+ * Parameters :
+ * 1 : job = pointer to the pcrs_job structure to be freed
+ *
+ * Returns : a pointer to the next job, if there was any, or
+ * NULL otherwise.
+ *
+ *********************************************************************/
+pcrs_job *pcrs_free_job(pcrs_job *job)
+{
+ pcrs_job *next;
+
+ if (job == NULL)
+ {
+ return NULL;
+ }
+ else
+ {
+ next = job->next;
+ if (job->pattern != NULL) free(job->pattern);
+ if (job->hints != NULL) free(job->hints);
+ if (job->substitute != NULL)
+ {
+ if (job->substitute->text != NULL) free(job->substitute->text);
+ free(job->substitute);
+ }
+ free(job);
+ }
+ return next;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : pcrs_make_job
+ *
+ * Description : Main entry point. Takes a string with a Perl-style
+ * s/// command and returns a corresponding pcrs_job,
+ * or NULL if compiling the job fails at any stage.
+ * Diagnostics could obviously be improved.
+ *
+ * Parameters :
+ * 1 : command = string with perl-style s/// command
+ * 2 : errptr = pointer to an integer in which error
+ * conditions can be returned.
+ *
+ * Returns : a corresponding pcrs_job data structure, or NULL
+ * if an error was encountered. In that case, *errptr
+ * has the reason.
+ *
+ *********************************************************************/
+pcrs_job *pcrs_make_job(char *command, int *errptr)
+{
+ char *dummy, *token, delimiter;
+ const char *error;
+ int i = 0, globalflag;
+ pcrs_job *newjob;
+
+ /* Get and init memory */
+ if ((newjob = (pcrs_job *)malloc(sizeof(pcrs_job))) == NULL)
+ {
+ *errptr = PCRS_ERR_NOMEM;
+ return NULL;
+ }
+ memset(newjob, '\0', sizeof(pcrs_job));
+
+ /* Command too short? */
+ if (strlen(command) < 4)
+ {
+ *errptr = PCRS_ERR_CMDSYNTAX;
+ pcrs_free_job(newjob);
+ return NULL;
+ }
+
+ /* Split command into tokens and handle them */
+ delimiter = command[1];
+ token = (char *)malloc(strlen(command)); /* current token */
+ dummy = (char *)malloc(strlen(command)); /* must store pattern, since we can't */
+ /* use it until the options are known */
+ while (my_strsep(token, &command, delimiter, '\\') >= 0)
+ {
+ switch (i)
+ {
+ /* We don't care about the command and assume 's' */
+ case 0:
+ break;
+
+ /* The pattern */
+ case 1:
+ strcpy(dummy, token);
+ break;
+
+ /* The substitute */
+ case 2:
+ newjob->substitute = pcrs_compile_replacement(token, errptr);
+ if (newjob->substitute == NULL)
+ {
+ pcrs_free_job(newjob);
+ return NULL;
+ }
+ break;
+
+ /* The options */
+ case 3:
+ newjob->options = pcrs_compile_perl_options(token, &globalflag);
+ newjob->globalflag = globalflag;
+ break;
+
+ /* There shouldn't be anything else! */
+ default:
+ *errptr = PCRS_ERR_CMDSYNTAX;
+ pcrs_free_job(newjob);
+ return NULL;
+ }
+ i++;
+ }
+ free(token);
+
+ /* Compile the pattern */
+ newjob->pattern = pcre_compile(dummy, newjob->options, &error, errptr, NULL);
+ if (newjob->pattern == NULL)
+ {
+ pcrs_free_job(newjob);
+ return NULL;
+ }
+ free(dummy);
+
+ /*
+ * Generate hints. This has little overhead, since the
+ * hints will be NULL for a boring pattern anyway.
+ */
+ newjob->hints = pcre_study(newjob->pattern, 0, &error);
+ if (error != NULL)
+ {
+ *errptr = PCRS_ERR_STUDY;
+ pcrs_free_job(newjob);
+ return NULL;
+ }
+
+ return newjob;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : create_pcrs_job
+ *
+ * Description : Create a job from all its components, if you don't
+ * have a Perl command to start from. Rather boring.
+ *
+ * Parameters :
+ * 1 : pattern = pointer to pcre pattern
+ * 2 : hints = pointer to pcre hints
+ * 3 : options = options in pcre format
+ * 4 : globalflag = flag that indicates if global matching is desired
+ * 5 : substitute = pointer to pcrs_substitute data structure
+ * 2 : errptr = pointer to an integer in which error
+ * conditions can be returned.
+ *
+ * Returns : pcrs_job structure, or NULL if an error was encountered.
+ * In that case, *errptr has the reason why.
+ *
+ *********************************************************************/
+pcrs_job *create_pcrs_job(pcre *pattern, pcre_extra *hints, int options, int globalflag, pcrs_substitute *substitute, int *errptr)
+{
+ pcrs_job *newjob;
+
+ if ((newjob = (pcrs_job *)malloc(sizeof(pcrs_job))) == NULL)
+ {
+ *errptr = PCRS_ERR_NOMEM;
+ return NULL;
+ }
+ memset(newjob, '\0', sizeof(pcrs_job));
+
+ newjob->pattern = pattern;
+ newjob->hints = hints;
+ newjob->options = options;
+ newjob->globalflag = globalflag;
+ newjob->substitute = substitute;
+
+ return(newjob);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : pcrs_exec_substitution
+ *
+ * Description : Modify the subject by executing the regular substitution
+ * defined by the job. Since the result may be longer than
+ * the subject, its space requirements are precalculated in
+ * the matching phase and new memory is allocated accordingly.
+ * It is the caller's responsibility to free the result when
+ * it's no longer needed.
+ *
+ * Parameters :
+ * 1 : job = the pcrs_job to be executed
+ * 2 : subject = the subject (== original) string
+ * 3 : subject_length = the subject's length
+ * 4 : result = char** for returning the result
+ * 5 : result_length = int* for returning the result's length
+ *
+ * Returns : the number of substitutions that were made. May be > 1
+ * if job->globalflag was set
+ *
+ *********************************************************************/
+int pcrs_exec_substitution(pcrs_job *job, char *subject, int subject_length, char **result, int *result_length)
+{
+ int offsets[3 * PCRS_MAX_SUBMATCHES],
+ offset = 0, i=0, k, matches_found, newsize, submatches;
+ pcrs_match matches[PCRS_MAX_MATCHES];
+ char *result_offset;
+
+ newsize=subject_length;
+
+ /* Find.. */
+ while ((submatches = pcre_exec(job->pattern, job->hints, subject, subject_length, offset, 0, offsets, 99)) > 0)
+ {
+ matches[i].submatches = submatches;
+ for (k=0; k < submatches; k++)
+ {
+ matches[i].submatch_offset[k] = offsets[2 * k];
+ matches[i].submatch_length[k] = offsets[2 * k + 1] - offsets[2 * k]; /* Non-found optional submatches have length -1-(-1)==0 */
+ newsize += matches[i].submatch_length[k] * job->substitute->backref_count[k]; /* reserve mem for each submatch as often as it is ref'd */
+ }
+ newsize += strlen(job->substitute->text) - matches[i].submatch_length[0]; /* plus replacement text size minus match text size */
+
+ /* Non-global search or limit reached? */
+ if (++i >= PCRS_MAX_MATCHES || !job->globalflag ) break;
+
+ /* Don't loop on empty matches */
+ if (offsets[1] == offset)
+ if (offset < subject_length)
+ offset++;
+ else
+ break;
+ /* Go find the next one */
+ else
+ offset = offsets[1];
+ }
+ if (submatches < -1) return submatches; /* Pass pcre error through */
+ matches_found = i;
+
+ /* ..get memory ..*/
+ if ((*result = (char *)malloc(newsize)) == NULL) /* must be free()d by caller */
+ {
+ return PCRS_ERR_NOMEM;
+ }
+
+ /* ..and replace */
+ offset = 0;
+ result_offset = *result;
+
+ for (i=0; i < matches_found; i++)
+ {
+ memcpy(result_offset, subject + offset, matches[i].submatch_offset[0] - offset); /* copy the chunk preceding the match */
+ result_offset += matches[i].submatch_offset[0] - offset;
+
+ /* For every segment of the substitute.. */
+ for (k=0; k <= job->substitute->backrefs; k++)
+ {
+ /* ...copy its text.. */
+ memcpy(result_offset, job->substitute->text + job->substitute->block_offset[k], job->substitute->block_length[k]);
+ result_offset += job->substitute->block_length[k];
+
+ /* ..plus, if it's not the last chunk (i.e.: There IS a backref).. */
+ if (k != job->substitute->backrefs
+ /* ..and a nonempty match.. */
+ && matches[i].submatch_length[job->substitute->backref[k]] > 0
+ /* ..and in legal range, ... */
+ && job->substitute->backref[k] <= PCRS_MAX_SUBMATCHES)
+ {
+ /* copy the submatch that is ref'd. */
+ memcpy(
+ result_offset,
+ subject + matches[i].submatch_offset[job->substitute->backref[k]],
+ matches[i].submatch_length[job->substitute->backref[k]]
+ );
+ result_offset += matches[i].submatch_length[job->substitute->backref[k]];
+ }
+ }
+ offset = matches[i].submatch_offset[0] + matches[i].submatch_length[0];
+ }
+
+ /* Copy the rest. */
+ memcpy(result_offset, subject + offset, subject_length - offset);
+
+ *result_length = newsize;
+ return matches_found;
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _PCRS_H
+#define _PCRS_H
+
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/pcrs.h,v $
+ *
+ * Purpose : This is the pre-pre-alpha realease of libpcrs. It is only
+ * published at this (ugly) stage of development, because it is
+ * needed for a new feature in JunkBuster.
+ *
+ * Apart from the code being quite a mess, no inconsistencies,
+ * memory leaks or functional bugs **should** be present.
+ *
+ * While you ROTFL at the code, you could just as well mail me
+ * (oes@paradis.rhein.de) with advice for improvement.
+ *
+ * pcrs is a supplement to the brilliant pcre library by Philip
+ * Hazel (ph10@cam.ac.uk) and adds Perl-style substitution. That
+ * is, it mimics Perl's 's' operator.
+ *
+ * Currently, there's no documentation besides comments and the
+ * source itself ;-)
+ *
+ * Copyright : Written and copyright 2001 by Sourceforge IJBSWA team.
+ *
+ * Revisions :
+ * $Log: pcrs.h,v $
+ * Revision 1.4 2001/05/11 01:57:02 rodney
+ * Added new file header standard w/RCS control tags.
+ *
+ * revision 1.3 2001/05/08 02:38:13 rodney
+ * Changed C++ "//" style comment to C style comments.
+ *
+ * revision 1.2 2001/04/30 02:39:24 rodney
+ * Made this pcrs.h file conditionally included.
+ *
+ * revision 1.1 2001/04/16 21:10:38 rodney
+ * Initial checkin
+ *
+ *********************************************************************/
+
+#define PCRS_H_VERSION "$Id: pcrs.h,v 1.1 2001/05/13 21:57:07 administrator Exp $"
+\f
+
+
+#include <pcre.h>
+
+#define FALSE 0
+#define TRUE 1
+#define PCRS_MAX_MATCHES 300
+#define PCRS_MAX_SUBMATCHES 33
+#define CHARBUFSIZ BUFSIZ * sizeof(char)
+
+#define PCRS_ERR_NOMEM -10 /* Failed to acquire memory. */
+#define PCRS_ERR_CMDSYNTAX -11 /* Syntax of s///-command */
+#define PCRS_ERR_STUDY -12 /* pcre error while studying the pattern */
+
+typedef struct S_PCRS_SUBSTITUTE {
+ char *text;
+ int backrefs;
+ int block_offset[PCRS_MAX_SUBMATCHES];
+ int block_length[PCRS_MAX_SUBMATCHES];
+ int backref[PCRS_MAX_SUBMATCHES];
+ int backref_count[PCRS_MAX_SUBMATCHES];
+} pcrs_substitute;
+
+typedef struct S_PCRS_MATCH {
+ /* char *buffer; */
+ int submatches;
+ int submatch_offset[PCRS_MAX_SUBMATCHES];
+ int submatch_length[PCRS_MAX_SUBMATCHES];
+} pcrs_match;
+
+typedef struct S_PCRS_JOB {
+ pcre *pattern;
+ pcre_extra *hints;
+ int options;
+ int globalflag;
+ int successflag;
+ pcrs_substitute *substitute;
+ struct S_PCRS_JOB *next;
+} pcrs_job;
+
+extern int pcrs_compile_perl_options(char *optstring, int *globalflag);
+extern pcrs_substitute *pcrs_compile_replacement(char *replacement, int *errptr);
+extern pcrs_job *pcrs_free_job(pcrs_job *job);
+extern pcrs_job *pcrs_make_job(char *command, int *errptr);
+extern pcrs_job *create_pcrs_job(pcre *pattern, pcre_extra *hints, int options, int globalflag, pcrs_substitute *substitute, int *errptr);
+extern int pcrs_exec_substitution(pcrs_job *job, char *subject, int subject_length, char **result, int *result_length);
+
+
+#endif /* ndef _PCRS_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#
+# $Id: popup,v 1.1 2001/04/16 21:10:38 rodney Exp $
+#
+# This is the configuration file for blocking Javascript popup windows,
+# it specifies both hosts to block from, and hosts to allow the popups
+# from.
+#
+# The format is the hostname to block, or allow.
+#
+# eg:
+#
+# www.geocities.com # block all popups from geocities.
+#
+# ~www.trusted-host.com # Allow popups from the trusted host domain.
+#
+#
+# If a site is not explicitly blocked popups will be allowed, the
+# "allowable" syntax with "~" exists as a marker that you've explicitly
+# allowed something.
+#
+# Order is not relevant - an allowable entry overrides a blocked entry,
+# e.g.
+# ~myhost.com # Allows myhost.com
+# myhost.com # _Still_ allowed.
+#
+# Steve Kemp
+# ---
+# http://www.tardis.ed.ac.uk/~skx/junk/ for more details.
+#
+#
+
+
+
+# This is for the test page, at http://www.tardis.ed.ac.uk/~skx/junk/
+www.tardis.ed.ac.uk
+
+#
+# Samples, uncomment to use:
+#
+
+# members.tripod.co.uk
+# www.geocities.com
+# ~windowsupdates.microsoft.com
+# ~updates.microsoft.com
\ No newline at end of file
--- /dev/null
+#ifndef _PROJECT_H
+#define _PROJECT_H
+#define PROJECT_H_VERSION "$Id: project.h,v 1.1 2001/05/13 21:57:07 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/project.h,v $
+ *
+ * Purpose : Defines data structures which are widely used in the
+ * project. Does not define any variables or functions
+ * (though it does declare some macros).
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: project.h,v $
+ *
+ *********************************************************************/
+\f
+
+/* Declare struct FILE for vars and funcs. */
+#include <stdio.h>
+
+/* Need time_t for file_list */
+#include <time.h>
+
+/*
+ * Include appropriate regular expression libraries.
+ *
+ * PCRS ==> Include pcre
+ * REGEX && PCRE ==> Include pcre and pcreposix
+ * REGEX && !PCRE ==> Include gnu_regex
+ *
+ * STATIC ==> Use #include "pcre.h" (compiling at same time)
+ * !STATIC ==> Use #include <pcre.h> (System library)
+ *
+ */
+#if (defined(REGEX) && defined(PCRE)) || defined(PCRS)
+# ifdef STATIC
+# include "pcre.h"
+# else
+# include <pcre.h>
+# endif
+#endif /* (defined(REGEX) && defined(PCRE)) || defined(PCRS) */
+
+#if defined(REGEX) && defined(PCRE)
+# ifdef STATIC
+# include "pcreposix.h"
+# else
+# include <pcreposix.h>
+# endif
+#endif /* defined(REGEX) && defined(PCRE) */
+
+#if defined(REGEX) && !defined(PCRE)
+# include "gnu_regex.h"
+#endif
+
+#ifdef PCRS
+#include "pcrs.h"
+#endif /* def PCRS */
+
+#ifdef AMIGA
+#include "amiga.h"
+#endif /* def AMIGA */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FOREVER 1
+
+/* Default IP and port to listen on */
+#define HADDR_DEFAULT "127.0.0.1"
+#define HADDR_PORT 8000
+
+
+/* Need this for struct gateway */
+struct client_state;
+
+
+struct http_request
+{
+ char *cmd;
+ char *gpc;
+ char *host;
+ int port;
+ char *path;
+ char *ver;
+ char *hostport; /* "host[:port]" */
+ int ssl;
+};
+
+
+struct gateway
+{
+ /* generic attributes */
+ char *name;
+ int (*conn)(const struct gateway *, struct http_request *, struct client_state *);
+ int type;
+
+ /* domain specific attributes */
+ char *gateway_host;
+ int gateway_port;
+
+ char *forward_host;
+ int forward_port;
+};
+
+
+struct proxy_args
+{
+ char *header;
+ char *invocation;
+ char *gateways;
+ char *trailer;
+};
+
+
+struct iob
+{
+ char *buf;
+ char *cur;
+ char *eod;
+};
+
+
+struct list
+{
+ char *str;
+ struct list *last;
+ struct list *next;
+};
+
+#define IOB_PEEK(CSP) ((CSP->iob->cur > CSP->iob->eod) ? (CSP->iob->eod - CSP->iob->cur) : 0)
+#define IOB_RESET(CSP) if(CSP->iob->buf) free(CSP->iob->buf); memset(CSP->iob, '\0', sizeof(CSP->iob));
+
+
+/* Constants defining bitmask for csp->accept_types */
+
+#ifdef DETECT_MSIE_IMAGES
+
+/* MSIE detected by user-agent string */
+#define ACCEPT_TYPE_IS_MSIE 0x0001
+
+/*
+ * *If* this is MSIE, it wants an image. (Or this is a shift-reload, or
+ * it's got an image from this URL before... yuck!)
+ * Only meaningful if ACCEPT_TYPE_IS_MSIE set
+ */
+#define ACCEPT_TYPE_MSIE_IMAGE 0x0002
+
+/*
+ * *If* this is MSIE, it wants a HTML document.
+ * Only meaningful if ACCEPT_TYPE_IS_MSIE set
+ */
+#define ACCEPT_TYPE_MSIE_HTML 0x0004
+
+#endif /* def DETECT_MSIE_IMAGES */
+
+
+struct client_state
+{
+ int send_user_cookie;
+ int accept_server_cookie;
+ int cfd;
+ int sfd;
+
+#ifdef STATISTICS
+ /* 1 if this URL was rejected, 0 otherwise. Allows actual stats inc to
+ * occur in main thread only for thread-safety.
+ */
+ int rejected;
+#endif /* def STATISTICS */
+
+#ifdef FORCE_LOAD
+ int force;
+#endif /* def FORCE_LOAD */
+
+#ifdef TOGGLE
+ /*
+ * by haroon - most of credit to srt19170
+ * We add an "on/off" toggle here that is used to effectively toggle
+ * the Junkbuster off or on
+ */
+ int toggled_on;
+#endif
+
+ char *ip_addr_str;
+ long ip_addr_long;
+ char *referrer;
+
+#if defined(DETECT_MSIE_IMAGES)
+ /* Types the client will accept.
+ * Bitmask - see ACCEPT_TYPE_XXX constants.
+ */
+ int accept_types;
+#endif /* defined(DETECT_MSIE_IMAGES) */
+
+ const struct gateway *gw;
+ struct http_request http[1];
+
+ struct iob iob[1];
+
+ struct list headers[1];
+ struct list cookie_list[1];
+#ifdef PCRS
+ int is_text;
+#endif /* def PCRS */
+
+ char *x_forwarded;
+
+ int active;
+
+ /* files associated with this client */
+ struct file_list *blist; /* blockfile */
+ struct file_list *clist; /* cookiefile */
+ struct file_list *flist; /* forwardfile */
+
+#ifdef ACL_FILES
+ struct file_list *alist; /* aclfile */
+#endif /* def ACL_FILES */
+
+#ifdef USE_IMAGE_LIST
+ struct file_list *ilist; /* imagefile */
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef KILLPOPUPS
+ struct file_list *plist; /* kill popup file */
+#endif /* def KILLPOPUPS */
+
+#ifdef PCRS
+ struct file_list *rlist; /* Perl re_filterfile */
+#endif /* def PCRS */
+
+#ifdef TRUST_FILES
+ struct file_list *tlist; /* trustfile */
+#endif /* def TRUST_FILES */
+
+ struct client_state *next;
+};
+
+
+struct parsers
+{
+ char *str;
+ char len;
+ char *(*parser)(const struct parsers *, char *, struct client_state *);
+};
+
+
+struct interceptors
+{
+ char *str;
+ char len;
+ char *(*interceptor)(struct http_request *http, struct client_state *csp);
+};
+
+
+/* this allows the proxy to permit/block access to any host and/or path */
+
+struct url_spec
+{
+ char *spec;
+ char *domain;
+ char *dbuf;
+ char **dvec;
+ int dcnt;
+ int toplevel;
+
+ char *path;
+ int pathlen;
+ int port;
+#ifdef REGEX
+ regex_t *preg;
+#endif
+};
+
+
+struct file_list
+{
+ /*
+ * this is a pointer to the data structures associated with the file.
+ * Read-only once the structure has been created.
+ */
+ void *f;
+
+ /* Normally NULL. When we are finished with file (i.e. when we have
+ * loaded a new one), set to a pointer to an unloader function.
+ * Unloader will be called by sweep() (called from main loop) when
+ * all clients using this file are done. This prevents threading
+ * problems.
+ */
+ void (*unloader)(void *);
+
+ /* Used internally by sweep(). Do not access from elsewhere. */
+ int active;
+
+#ifndef SPLIT_PROXY_ARGS
+ /* String to be displayed as part of show-proxy-args display.
+ * Read-only once the structure has been created.
+ */
+ char *proxy_args;
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ /* Following variables allow us to check if file has been changed.
+ * Read-only once the structure has been created.
+ */
+ time_t lastmodified;
+ char * filename;
+
+ /* Pointer to next entry in the linked list of all "file_list"s.
+ * This linked list is so that sweep() can navigate it.
+ * Since sweep() can remove items from the list, we must be careful
+ * to only access this value from main thread (when we know sweep
+ * won't be running).
+ */
+ struct file_list *next;
+};
+
+
+struct block_spec
+{
+ struct url_spec url[1];
+ int reject;
+ struct block_spec *next;
+};
+
+
+struct cookie_spec
+{
+ struct url_spec url[1];
+ int send_user_cookie;
+ int accept_server_cookie;
+ struct cookie_spec *next;
+};
+
+
+struct forward_spec
+{
+ struct url_spec url[1];
+ int reject;
+ struct gateway gw[1];
+ struct forward_spec *next;
+};
+
+
+#ifdef PCRS
+struct re_filterfile_spec
+{
+ struct list patterns[1];
+ /* See README.re_filter */
+ pcrs_job *joblist;
+};
+#endif /* def PCRS */
+
+
+#ifdef KILLPOPUPS
+/* Entries on popup blocklist */
+struct popup_blocklist
+{
+ char *host_name;
+ struct popup_blocklist *next;
+};
+
+/* Actual type used in file object */
+struct popup_settings
+{
+ struct popup_blocklist *blocked;
+ struct popup_blocklist *allowed;
+};
+#endif /* def KILLPOPUPS */
+
+#ifdef ACL_FILES
+#define ACL_PERMIT 1 /* accept connection request */
+#define ACL_DENY 2 /* reject connection request */
+
+struct access_control_addr
+{
+ unsigned long addr;
+ unsigned long mask;
+ unsigned long port;
+};
+
+struct access_control_list
+{
+ struct access_control_addr src[1];
+ struct access_control_addr dst[1];
+
+ short action;
+ struct access_control_list *next;
+};
+#endif /* def ACL_FILES */
+
+#define SZ(X) (sizeof(X) / sizeof(*X))
+
+#define WHITEBG "<body bgcolor=\"#ffffff\" link=\"#000078\" alink=\"#ff0022\" vlink=\"#787878\">\n"
+#define BODY "<body bgcolor=\"#f8f8f0\" link=\"#000078\" alink=\"#ff0022\" vlink=\"#787878\">\n"
+#define BANNER "<strong>Internet J<small>UNK<i><font color=\"red\">BUSTER</font></i></small></strong>"
+
+#ifdef FORCE_LOAD
+/*\r
+ * FIXME: Unfortunately, IE lowercases the domain name. JunkBuster does\r
+ * a case-sensitive compare. JunkBuster should be modified to do a\r
+ * case-insensitive compatison. As a temporary workaround, I've lowercased\r
+ * the FORCE_PREFIX.\r
+ *\r
+ * #define FORCE_PREFIX "IJB-FORCE-LOAD-"\r
+ */\r
+#define FORCE_PREFIX "ijb-force-load-"\r
+#endif /* def FORCE_LOAD */
+
+#define HOME_PAGE_URL "http://ijbswa.sourceforge.net/"
+#define REDIRECT_URL HOME_PAGE_URL "redirect.php?v=" VERSION "&to="
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _PROJECT_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+# Filterfile for the Regular Substitution Module
+#
+# Syntax: One Perl-Style substitution per line.
+# For Details see the perlre, perlop and pcre manpages.
+# Note that you are free to choose the delimter as you
+# see fit.
+#
+
+# Kill OnUnload popups. Yummy.
+# check it out on http://www.zdnet.com/zdsubs/yahoo/tree/yfs.html
+#
+s/(<body .*?)onunload(.*?>)/$1never$2/i
+
+# Kill refresh tags. I like to refresh myself. Manually.
+# check it out on http://www.airport-cgn.de/ and go to the arrivals page.
+#
+s/<meta[^>]*http-equiv[^>]*refresh[^>]*>/<!--no refresh for me-->/i
+s/<meta[^>]*http-equiv="?page-enter"?[^>]*content=[^>]*>/<!--no page enter for me-->/i
+
+# If I allow popups, I want them to be rezizable and have a location and status bar:
+# check it out on http://www.airport-cgn.de/ and go to the arrivals page.
+#
+s/resizable="?(no|0)"?/resizable=1/ig
+s/noresize/yesresize/ig
+s/location="?(no|0)"?/location=1/ig
+s/status="?(no|0)"?/status=1/ig
+s/scrolling="?(no|0|Auto)"?/scrolling=1/ig
+s/menubar="?(no|0)"?/menubar=1/ig
+#s/framespacing="?(no|0)"?//ig
+#s/margin(height|width)=[0-9]*//gi
+
+# Remove frameborder=0 and border=0 from framesets
+s/(<frameset[ -z]+)(frame)?border="?(no|0)"?/$1/ig
+
+# The status bar is for displaying link targets, not pointless buzzwords.
+# Again, check it out on http://www.airport-cgn.de/
+#
+s/status='.*?';*//ig
+
+# Kill *all* popups a la popup.c. (But for *all* sites, so I wouldn't do that.)
+#
+# JavaScript: s/window\.open\(/who_wants_this_to.open(/ig
+# HTML : s/target="?_blank"?/target_who/g
+
+# Fun stuff:
+#
+s/microsoft(?!.com)/<b>MicroSuck<\/b>/ig
+
+# Crude parental filtering? (Use along with a suitable blocklist).
+# Shows how to deny access to whole page based on a keyword.
+#
+# (Note: Middlesex, Sussex and Essex are counties in the UK, not rude words)
+# (Note #2: Is 'sex' a rude word?!)
+#
+#s%^.*(?<!middle)(?<!sus)(?<!es)sex.*$%<html><head><title>Blocked</title></head><body><h3>Blocked due to possible adult content. Please see <a href="http://dmoz.org/Kids_and_Teens/">this site</a>.</h3></body></html>%is
+#s+^.*warez.*$+<html><head><title>No Warez</title></head><body><h3>You're not searching for illegal stuff, are you?</h3></body></html>+is
+
+# http://www.farscapezone.com/wwwboard/messages/1451.html
+s/(\w+) was tired/<b>$1 needed more coffee<\/b>/ig
+
+# I'm sure you'll find more uses.
+# Please send your cool additions to junkbuster-users@yahoogroups.com
--- /dev/null
+const char showargs_rcs[] = "$Id: showargs.c,v 1.1 2001/05/13 21:57:07 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/showargs.c,v $
+ *
+ * Purpose : Contains various utility routines needed to
+ * generate the show-proxy-args page.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: showargs.c,v $
+ *
+ *********************************************************************/
+\f
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <malloc.h>
+#include <errno.h>
+
+#include "showargs.h"
+#include "jcc.h"
+#include "encode.h"
+#include "parsers.h"
+#include "errlog.h"
+#include "miscutil.h"
+#include "gateway.h"
+
+const char showargs_h_rcs[] = SHOWARGS_H_VERSION;
+
+/*********************************************************************
+ *
+ * Function : strsav
+ *
+ * Description : Reallocate "old" and append text to it. This makes
+ * it easier to append to malloc'd strings.
+ *
+ * Parameters :
+ * 1 : old = Old text that is to be extended. Will be
+ * free()d by this routine.
+ * 2 : text_to_append = Text to be appended to old.
+ *
+ * Returns : Pointer to newly malloc'ed appended string.
+ * If there is no text to append, return old. Caller
+ * must free().
+ *
+ *********************************************************************/
+char *strsav(char *old, const char *text_to_append)
+{
+ int old_len, new_len;
+ char *p;
+
+ if (( text_to_append == NULL) || (*text_to_append == '\0'))
+ {
+ return(old);
+ }
+
+ if (NULL != old)
+ {
+ old_len = strlen(old);
+ }
+ else
+ {
+ old_len = 0;
+ }
+
+ new_len = old_len + strlen(text_to_append) + 1;
+
+ if (old)
+ {
+ if ((p = realloc(old, new_len)) == NULL)
+ {
+ log_error(LOG_LEVEL_ERROR, "realloc(%d) bytes for proxy_args failed!", new_len);
+ exit(1);
+ }
+ }
+ else
+ {
+ if ((p = (char *)malloc(new_len)) == NULL)
+ {
+ log_error(LOG_LEVEL_ERROR, "malloc(%d) bytes for proxy_args failed!", new_len);
+ exit(1);
+ }
+ }
+
+ strcpy(p + old_len, text_to_append);
+ return(p);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : savearg
+ *
+ * Description : Called from `load_config'. It saves each non-empty
+ * and non-comment line from config into a list. This
+ * list is used to create the show-proxy-args page.
+ *
+ * Parameters :
+ * 1 : c = config setting that was found
+ * 2 : o = the setting's argument (if any)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void savearg(char *c, char *o)
+{
+ char buf[BUFSIZ];
+
+ *buf = '\0';
+
+ if ( ( NULL != c ) && ( '\0' != *c ) )
+ {
+ if ((c = html_encode(c)))
+ {
+ sprintf(buf, "<a href=\"" REDIRECT_URL "option#%s\">%s</a> ", c, c);
+ }
+ freez(c);
+ }
+ if ( ( NULL != o ) && ( '\0' != *o ) )
+ {
+ if ((o = html_encode(o)))
+ {
+ if (strncmpic(o, "http://", 7) == 0)
+ {
+ strcat(buf, "<a href=\"");
+ strcat(buf, o);
+ strcat(buf, "\">");
+ strcat(buf, o);
+ strcat(buf, "</a>");
+ }
+ else
+ {
+ strcat(buf, o);
+ }
+ }
+ freez(o);
+ }
+
+ strcat(buf, "<br>\n");
+
+ proxy_args->invocation = strsav(proxy_args->invocation, buf);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : init_proxy_args
+ *
+ * Description : Create the "top" of the show-proxy-args page.
+ *
+ * Parameters :
+ * 1 : argc = argument count (same as in main)
+ * 2 : argv[] = program arguments (same as in main)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void init_proxy_args(int argc, const char *argv[])
+{
+ const struct gateway *g;
+ int i;
+
+ freez(proxy_args->header);
+ freez(proxy_args->invocation);
+ freez(proxy_args->gateways);
+ freez(proxy_args->trailer);
+
+
+ proxy_args->header = strsav(proxy_args->header,
+ "HTTP/1.0 200 OK\n"
+ "Server: IJ/" VERSION "\n"
+ "Content-type: text/html\n\n"
+
+ "<html>"
+ "<head>"
+ "<title>Internet Junkbuster Proxy Status</title>"
+ "</head>\n"
+ "<body bgcolor=\"#f8f8f0\" link=\"#000078\" alink=\"#ff0022\" vlink=\"#787878\">\n"
+ "<center>\n"
+ "<h1>" BANNER "\n"
+ "<a href=\"" REDIRECT_URL "faq#show\">Proxy Status</a>\n"
+ "</h1></center>\n"
+ "<h2>You are using the " BANNER " <sup><small><small>TM</small></small></sup></h2>\n"
+ "Version: " VERSION "\n"
+ "<br>Home page: <a href=\"" HOME_PAGE_URL "\">" HOME_PAGE_URL "</a>\n"\r
+ "<p>\n"
+ );
+
+ proxy_args->header = strsav(proxy_args->header,
+ "<h2>The program was invoked as follows</h2>\n");
+
+ for (i=0; i < argc; i++)
+ {
+ proxy_args->header = strsav(proxy_args->header, argv[i]);
+ proxy_args->header = strsav(proxy_args->header, " ");
+ }
+ proxy_args->header = strsav(proxy_args->header, "<br>\n");
+
+
+ proxy_args->invocation = strsav(
+ proxy_args->invocation,
+ "<br>\n"
+ "and the following options were set in the configuration file"
+ "<br><br>\n"
+ );
+
+
+ proxy_args->gateways = strsav(proxy_args->gateways,
+ "<h2>It supports the following gateway protocols:</h2>\n");
+
+ for (g = gateways; g->name; g++)
+ {
+ proxy_args->gateways = strsav(proxy_args->gateways, g->name);
+ proxy_args->gateways = strsav(proxy_args->gateways, " ");
+ }
+ proxy_args->gateways = strsav(proxy_args->gateways, "<br>\n");
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : end_proxy_args
+ *
+ * Description : Create the "bottom" of the show-proxy-args page.
+ *
+ * Parameters : None
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void end_proxy_args(void)
+{
+ char *b = NULL;
+ char buf[BUFSIZ];
+
+ /* Instead of including *all* dot h's in the project (thus creating a
+ * tremendous amount of dependencies), I will concede to declaring them
+ * as extern's. This forces the developer to add to this list, but oh well.
+ */
+
+#ifndef SPLIT_PROXY_ARGS
+ if (suppress_blocklists && suppress_message!=NULL)
+ {
+ b = strsav(b, "<h2>File contents</h2>\n");
+ b = strsav(b, suppress_message);
+ b = strsav(b, "\n");
+ }
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+ b = strsav(b, "<h2>Source versions:</h2>\n");
+ b = strsav(b, "<pre>");
+
+#define SHOW_RCS(__x) \
+ { \
+ extern const char __x[]; \
+ sprintf(buf, "%s\n", __x); \
+ b = strsav(b, buf); \
+ }
+
+ /* In alphabetical order */
+#ifdef __MINGW32__
+ SHOW_RCS(cygwin_h_rcs)
+#endif
+ SHOW_RCS(encode_h_rcs)
+ SHOW_RCS(encode_rcs)
+ SHOW_RCS(errlog_h_rcs)
+ SHOW_RCS(errlog_rcs)
+ SHOW_RCS(filters_h_rcs)
+ SHOW_RCS(filters_rcs)
+ SHOW_RCS(gateway_h_rcs)
+ SHOW_RCS(gateway_rcs)
+#ifdef GNU_REGEX
+ SHOW_RCS(gnu_regex_h_rcs)
+ SHOW_RCS(gnu_regex_rcs)
+#endif /* def GNU_REGEX */
+ SHOW_RCS(jbsockets_h_rcs)
+ SHOW_RCS(jbsockets_rcs)
+ SHOW_RCS(jcc_h_rcs)
+ SHOW_RCS(jcc_rcs)
+#ifdef KILLPOPUPS
+ SHOW_RCS(killpopup_h_rcs)
+ SHOW_RCS(killpopup_rcs)
+#endif /* def KILLPOPUPS */
+ SHOW_RCS(loadcfg_h_rcs)
+ SHOW_RCS(loadcfg_rcs)
+ SHOW_RCS(loaders_h_rcs)
+ SHOW_RCS(loaders_rcs)
+ SHOW_RCS(miscutil_h_rcs)
+ SHOW_RCS(miscutil_rcs)
+ SHOW_RCS(parsers_h_rcs)
+ SHOW_RCS(parsers_rcs)
+#ifdef PCRS
+ SHOW_RCS(pcrs_rcs)
+ SHOW_RCS(pcrs_h_rcs)
+#endif /* def PCRS */
+ SHOW_RCS(project_h_rcs)
+ SHOW_RCS(showargs_h_rcs)
+ SHOW_RCS(showargs_rcs)
+ SHOW_RCS(ssplit_h_rcs)
+ SHOW_RCS(ssplit_rcs)
+#ifdef _WIN32
+ SHOW_RCS(w32log_h_rcs)
+ SHOW_RCS(w32log_rcs)
+ SHOW_RCS(w32res_h_rcs)
+ SHOW_RCS(w32rulesdlg_h_rcs)
+ SHOW_RCS(w32rulesdlg_rcs)
+ SHOW_RCS(w32taskbar_h_rcs)
+ SHOW_RCS(w32taskbar_rcs)
+ SHOW_RCS(win32_h_rcs)
+ SHOW_RCS(win32_rcs)
+#endif /* def _WIN32 */
+
+#undef SHOW_RCS
+
+ b = strsav(b, "</pre>\n");
+
+ b = strsav(b, "<h2>Conditional defines:</h2>\n<ul>");
+
+#ifdef REGEX
+ b = strsav(b, " <li><code>#define <b>REGEX</b></code> - Support for regular expressions in the path specs.</li>\n");
+#else /* ifndef REGEX */
+ b = strsav(b, " <li><code>#undef <b>REGEX</b></code> - No support for regular expressions in the path specs.</li>\n");
+#endif /* ndef REGEX */
+\r
+#ifdef PCRE\r
+ b = strsav(b, " <li><code>#define <b>PCRE</b></code> - Use PCRE rather than old GNU regex library.</li>\n");\r
+#else /* ifndef PCRE */\r
+ b = strsav(b, " <li><code>#undef <b>PCRE</b></code> - Use old GNU regex library rather than PCRE.</li>\n");\r
+#endif /* ndef PCRE */\r
+
+#ifdef PCRS
+ b = strsav(b, " <li><code>#define <b>PCRS</b></code> - Enables arbitrary content modification regexps.</li>\n");
+#else /* ifndef PCRS */
+ b = strsav(b, " <li><code>#undef <b>PCRS</b></code> - Disables arbitrary content modification regexps.</li>\n");
+#endif /* ndef PCRS */
+\r
+#ifdef TOGGLE\r
+ b = strsav(b, " <li><code>#define <b>TOGGLE</b></code> - Allow JunkBuster to be \"disabled\" so it is just a normal non-blocking non-anonymizing proxy.</li>\n");\r
+#else /* ifndef TOGGLE */\r
+ b = strsav(b, " <li><code>#undef <b>TOGGLE</b></code> - Do not allow JunkBuster to be \"disabled\" so it is just a normal non-blocking non-anonymizing proxy.</li>\n");\r
+#endif /* ndef TOGGLE */\r
+\r
+#ifdef FORCE_LOAD\r
+ b = strsav(b, " <li><code>#define <b>FORCE_LOAD</b></code> - Enables bypassing filtering for a single page using the prefix \"" FORCE_PREFIX "\".</li>\n");\r
+#else /* ifndef FORCE_LOAD */\r
+ b = strsav(b, " <li><code>#undef <b>FORCE_LOAD</b></code> - Disables bypassing filtering for a single page.</li>\n");\r
+#endif /* ndef FORCE_LOAD */\r
+
+#ifdef DENY_GZIP
+ b = strsav(b, " <li><code>#define <b>DENY_GZIP</b></code> - Prevents requests from being compressed - required for PCRS.</li>\n");
+#else /* ifndef DENY_GZIP */
+ b = strsav(b, " <li><code>#undef <b>DENY_GZIP</b></code> - Allows requests to be compressed if the browser and server support it.</li>\n");
+#endif /* ndef DENY_GZIP */
+
+#ifdef STATISTICS
+ b = strsav(b, " <li><code>#define <b>STATISTICS</b></code> - Enables statistics function.</li>\n");
+#else /* ifndef STATISTICS */
+ b = strsav(b, " <li><code>#undef <b>STATISTICS</b></code> - Disables statistics function.</li>\n");
+#endif /* ndef STATISTICS */
+
+#ifdef SPLIT_PROXY_ARGS
+ b = strsav(b, " <li><code>#define <b>SPLIT_PROXY_ARGS</b></code> - Split this page up by placing the configuration files on separate pages.</li>\n");
+#else /* ifndef SPLIT_PROXY_ARGS */
+ b = strsav(b, " <li><code>#undef <b>SPLIT_PROXY_ARGS</b></code> - This page contains the text of the configuration files, they are not split onto separate pages.</li>\n");
+#endif /* ndef SPLIT_PROXY_ARGS */
+
+#ifdef KILLPOPUPS
+ b = strsav(b, " <li><code>#define <b>KILLPOPUPS</b></code> - Enables killing JavaScript popups.</li>\n");
+#else /* ifndef KILLPOPUPS */
+ b = strsav(b, " <li><code>#undef <b>KILLPOPUPS</b></code> - Disables killing JavaScript popups.</li>\n");
+#endif /* ndef KILLPOPUPS */
+
+#ifdef WEBDAV
+ b = strsav(b, " <li><code>#define <b>WEBDAV</b></code> - Enables support for webDAV - e.g. stops Microsoft Outlook from accessing HotMail e-mail.</li>\n");
+#else /* ifndef WEBDAV */
+ b = strsav(b, " <li><code>#undef <b>WEBDAV</b></code> - Disables support for webDAV - e.g. so Microsoft Outlook can access HotMail e-mail.</li>\n");
+#endif /* ndef WEBDAV */
+
+#ifdef DETECT_MSIE_IMAGES
+ b = strsav(b, " <li><code>#define <b>DETECT_MSIE_IMAGES</b></code> - Enables detecting image requests automatically for MSIE.</li>\n");
+#else /* ifndef DETECT_MSIE_IMAGES */
+ b = strsav(b, " <li><code>#undef <b>DETECT_MSIE_IMAGES</b></code> - Disables detecting image requests automatically for MSIE.</li>\n");
+#endif /* ndef DETECT_MSIE_IMAGES */
+
+#ifdef USE_IMAGE_LIST
+ b = strsav(b, " <li><code>#define <b>USE_IMAGE_LIST</b></code> - Enables using image list to detect images.</li>\n");
+#else /* ifndef USE_IMAGE_LIST */
+ b = strsav(b, " <li><code>#undef <b>USE_IMAGE_LIST</b></code> - Disables using image list to detect images.</li>\n");
+#endif /* ndef USE_IMAGE_LIST */
+
+#ifdef ACL_FILES
+ b = strsav(b, " <li><code>#define <b>ACL_FILES</b></code> - Enables the use of ACL files to control access to the proxy by IP address.</li>\n");
+#else /* ifndef ACL_FILES */
+ b = strsav(b, " <li><code>#undef <b>ACL_FILES</b></code> - Disables the use of ACL files to control access to the proxy by IP address.</li>\n");
+#endif /* ndef ACL_FILES */
+\r
+#ifdef TRUST_FILES
+ b = strsav(b, " <li><code>#define <b>TRUST_FILES</b></code> - Enables the use of trust files.</li>\n");
+#else /* ifndef TRUST_FILES */
+ b = strsav(b, " <li><code>#undef <b>TRUST_FILES</b></code> - Disables the use of trust files.</li>\n");
+#endif /* ndef TRUST_FILES */
+
+#ifdef JAR_FILES\r
+ b = strsav(b, " <li><code>#define <b>JAR_FILES</b></code> - Enables the use of jar files to capture cookies.</li>\n");\r
+#else /* ifndef JAR_FILES */\r
+ b = strsav(b, " <li><code>#undef <b>JAR_FILES</b></code> - Disables the use of jar files to capture cookies.</li>\n");\r
+#endif /* ndef JAR_FILES */\r
+
+ b = strsav(b, "</ul>\n<br>\n");
+
+ b = strsav(b,
+ "<small><small><p>\n"
+ "Code and documentation of the " BANNER " Proxy"
+ "<sup><small>TM</small></sup>\n"
+ "<a href=\"http://www.junkbusters.com/ht/en/legal.html#copy\">\n" "Copyright</a>© 1997 Junkbusters Corporation\n"
+ "<a href=\"http://www.junkbusters.com/ht/en/legal.html#marks\"><sup><small>TM</small></sup></a><br>\n"
+ "Copying and distribution permitted under the"
+ "<a href=\"http://www.gnu.org/copyleft/gpl.html\">\n"
+ "<small>GNU</small></a> "
+ "General Public License.\n"
+ "</small>"
+ "<address><kbd>webmaster@junkbusters.com</kbd></address>"
+ "</small>"
+ "</body></html>\n"
+ );
+
+ proxy_args->trailer = b;
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _SHOWARGS_H
+#define _SHOWARGS_H
+#define SHOWARGS_H_VERSION "$Id: showargs.h,v 1.1 2001/05/13 21:57:07 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/showargs.h,v $
+ *
+ * Purpose : Contains various utility routines needed to
+ * generate the show-proxy-args page.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: showargs.h,v $
+ *
+ *********************************************************************/
+\f
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *strsav(char *old, const char *text_to_append);
+extern void savearg(char *c, char *o);
+
+extern void init_proxy_args(int argc, const char *argv[]);
+extern void end_proxy_args(void);
+
+/* Revision control strings from this header and associated .c file */
+extern const char showargs_rcs[];
+extern const char showargs_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _SHOWARGS_H */
--- /dev/null
+const char ssplit_rcs[] = "$Id: ssplit.c,v 1.1 2001/05/13 21:57:07 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/ssplit.c,v $
+ *
+ * Purpose : A function to split a string at specified deliminters.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: ssplit.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>\r
+
+#ifdef _WIN32
+#include <malloc.h>
+#endif
+
+#include "ssplit.h"
+#include "miscutil.h"
+
+const char ssplit_h_rcs[] = SSPLIT_H_VERSION;
+
+/* Define this for lots of debugging information to stdout */
+/* #define SSPLIT_VERBOSE */
+
+#ifdef SSPLIT_VERBOSE
+/*********************************************************************
+ *
+ * Function : print
+ *
+ * Description : Debugging routine to spit info on stdout. Not very
+ * useful to the non-console based IJB compiles.
+ *
+ * Parameters :
+ * 1 : v = an array of strings
+ * 2 : n = number of strings in `v' to dump to stdout
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void print(char **v, int n)
+{
+ int i;
+ printf("dump %d strings\n", n);
+ for (i=0; i < n; i++)
+ {
+ printf("%d '%s'\n", i, v[i]);
+ }
+
+}
+#endif /* def SSPLIT_VERBOSE */
+
+
+/*********************************************************************
+ *
+ * Function : ssplit
+ *
+ * Description : Split a string using deliminters in `c'. Results go
+ * into `v'.
+ *
+ * Parameters :
+ * 1 : s = string to split
+ * 2 : c = array of delimiters
+ * 3 : v[] = results vector (aka. array)
+ * 4 : n = number of usable slots in the vector (aka. array size)
+ * 5 : m = consecutive delimiters means multiple fields?
+ * 6 : l = ignore leading field separators?
+ *
+ * Returns : -1 => failure, else the number of fields put in `v'.
+ *
+ *********************************************************************/
+int ssplit(char *s, char *c, char *v[], int n, int m, int l)
+{
+ char t[256];
+ char **x = NULL;
+ int xsize = 0;
+ unsigned char *p, b;
+ int xi = 0;
+ int vi = 0;
+ int i;
+ int last_was_null;
+
+ if (!s)
+ {
+ return(-1);
+ }
+
+ memset(t, '\0', sizeof(t));
+
+ p = (unsigned char *) c;
+
+ if (!p)
+ {
+ p = (unsigned char *) " \t"; /* default field separators */
+ }
+
+ while (*p)
+ {
+ t[*p++] = 1; /* separator */
+ }
+
+ t['\0'] = 2; /* terminator */
+ t['\n'] = 2; /* terminator */
+
+ p = (unsigned char *) s;
+
+ if (l)/* are we to skip leading separators ? */
+ {
+ while ((b = t[*p]) != 2)
+ {
+ if (b != 1)
+ {
+ break;
+ }
+ p++;
+ }
+ }
+
+ xsize = 256;
+
+ x = (char **) zalloc((xsize) * sizeof(char *));
+
+ x[xi++] = (char *) p; /* first pointer is the beginning of string */
+
+ /* first pass: save pointers to the field separators */
+ while ((b = t[*p]) != 2)
+ {
+ if (b == 1) /* if the char is a separator ... */
+ {
+ *p++ = '\0'; /* null terminate the substring */
+
+ if (xi == xsize)
+ {
+ /* get another chunk */
+ int new_xsize = xsize + 256;
+ char **new_x = (char **)zalloc((new_xsize) * sizeof(char *));
+
+ for (i=0; i < xsize; i++)
+ {
+ new_x[i] = x[i];
+ }
+
+ free(x);
+ xsize = new_xsize;
+ x = new_x;
+ }
+ x[xi++] = (char *) p; /* save pointer to beginning of next string */
+ }
+ else
+ {
+ p++;
+ }
+ }
+ *p = '\0'; /* null terminate the substring */
+
+
+#ifdef SSPLIT_VERBOSE
+ if (DEBUG(HDR))
+ {
+ print(x, xi); /* debugging */
+ }
+#endif /* def SSPLIT_VERBOSE */
+
+
+ /* second pass: copy the relevant pointers to the output vector */
+ last_was_null = 0;
+ for (i=0 ; i < xi; i++)
+ {
+ if (m)
+ {
+ /* there are NO null fields */
+ if (*x[i] == 0)
+ {
+ continue;
+ }
+ }
+ if (vi < n)
+ {
+ v[vi++] = x[i];
+ }
+ else
+ {
+ free(x);
+ return(-1); /* overflow */
+ }
+ }
+ free(x);
+
+#ifdef SSPLIT_VERBOSE
+ if (DEBUG(HDR))
+ {
+ print(v, vi); /* debugging */
+ }
+#endif /* def SSPLIT_VERBOSE */
+
+ return(vi);
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _SSPLIT_H
+#define _SSPLIT_H
+#define SSPLIT_H_VERSION "$Id: ssplit.h,v 1.1 2001/05/13 21:57:07 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/ssplit.h,v $
+ *
+ * Purpose : A function to split a string at specified deliminters.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: ssplit.h,v $
+ *
+ *********************************************************************/
+\f
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int ssplit(char *s, char *c, char *v[], int n, int m, int l);
+
+/* Revision control strings from this header and associated .c file */
+extern const char ssplit_rcs[];
+extern const char ssplit_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _SSPLIT_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+# Illustrative Trustfile for the Internet Junkbuster
+#
+# Copyright 1997-8 Junkbusters Corp. For distribution, modification and use
+# under the GNU General Public License. These files come with NO WARRANTY.
+# See http://www.junkbusters.com/ht/en/gpl.html or README file for details.
+
+# For this file to have any effect, the line beginning "trustfile" must
+# be commented in, with the name of this file following the word "trustfile"
+
+# Trustfiles are an experimental feature used for building "whitelists"
+# (versus the usual "blacklists" in a blockfile). Most people don't use it.
+# For more detail, see http://www.junkbusters.com/ht/en/ijbman.html#trustfile
+#
+# This is like parsed exactly like a blockfile, except that a '+'
+# in column one is treated like a '~' (i.e. doesn't block) and
+# it adds the spec to the trusted-referer list.
+#
+# Also, the default is to block any URL that is NOT mentioned on this list.
+#
+# While browsing, the domains for URLs that are referred by a trusted referer
+# are added to this list. Thus this acts as a "white-list" of OK places
+# to browse. Note this means that the file will grow longer with use.
+#
+# Example: to allow only links that came from yahooligans, uncomment this line
+# +yahooligans.com
+# and remove the last line (* alone), which unblock everything:
+*
--- /dev/null
+# Microsoft Developer Studio Project File - Name="vc_junkbuster" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 5.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Application" 0x0101\r
+\r
+CFG=vc_junkbuster - Win32 Release\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "vc_junkbuster.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "vc_junkbuster.mak" CFG="vc_junkbuster - Win32 Release"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "vc_junkbuster - Win32 Release" (based on "Win32 (x86) Application")\r
+!MESSAGE "vc_junkbuster - Win32 Debug" (based on "Win32 (x86) Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF "$(CFG)" == "vc_junkbuster - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "vc_release"\r
+# PROP BASE Intermediate_Dir "vc_release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "vc_release"\r
+# PROP Intermediate_Dir "vc_release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c\r
+# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "pcre" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "STATIC" /FR /YX /FD /c\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32\r
+# ADD BASE RSC /l 0x809 /d "NDEBUG"\r
+# ADD RSC /l 0x809 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib ws2_32.lib comctl32.lib /nologo /subsystem:windows /machine:I386\r
+\r
+!ELSEIF "$(CFG)" == "vc_junkbuster - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "vc_debug"\r
+# PROP BASE Intermediate_Dir "vc_debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "vc_debug"\r
+# PROP Intermediate_Dir "vc_debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c\r
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /O2 /I "pcre" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "STATIC" /YX /FD /c\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32\r
+# ADD BASE RSC /l 0x809 /d "_DEBUG"\r
+# ADD RSC /l 0x809 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib ws2_32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "vc_junkbuster - Win32 Release"\r
+# Name "vc_junkbuster - Win32 Debug"\r
+# Begin Group "JunkBuster"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\amiga.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\amiga.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\config.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\errlog.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\errlog.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\filters.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\filters.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\jcc.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\jcc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\killpopup.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\killpopup.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\loadcfg.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\loadcfg.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\loaders.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\loaders.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\parsers.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\parsers.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\project.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\showargs.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\showargs.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Win32"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\cygwin.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32log.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32log.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32res.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32rulesdlg.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32rulesdlg.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32taskbar.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32taskbar.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\win32.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\win32.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Resources"\r
+\r
+# PROP Default_Filter "rc,ico,bmp"\r
+# Begin Source File\r
+\r
+SOURCE=.\icons\denyrule.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\icons\ico00001.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\icons\ico00002.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\icons\ico00003.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\icons\ico00004.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\icons\ico00005.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\icons\ico00006.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\icons\ico00007.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\icons\ico00008.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\icons\icon1.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\icons\idle.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\icons\junkbust.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32.rc\r
+# End Source File\r
+# End Group\r
+# Begin Group "PCRE"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\pcre\chartables.c\r
+\r
+!IF "$(CFG)" == "vc_junkbuster - Win32 Release"\r
+\r
+!ELSEIF "$(CFG)" == "vc_junkbuster - Win32 Debug"\r
+\r
+# PROP Exclude_From_Build 1\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\pcre\config.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\pcre\get.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\pcre\internal.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\pcre\maketables.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\pcre\pcre.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\pcre\pcre.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\pcre\pcreposix.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\pcre\pcreposix.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\pcre\study.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "PCRS"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\pcrs.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\pcrs.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Sockets"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\gateway.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\gateway.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\jbsockets.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\jbsockets.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Utilities"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=.\encode.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\encode.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\miscutil.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\miscutil.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ssplit.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ssplit.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
--- /dev/null
+Microsoft Developer Studio Workspace File, Format Version 5.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "vc_junkbuster"=".\vc_junkbuster.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
--- /dev/null
+/*********************************************************************\r
+ *\r
+ * File : $Source: $\r
+ *\r
+ * Purpose : Windows GUI resource script.\r
+ *\r
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge\r
+ * IJBSWA team. http://ijbswa.sourceforge.net\r
+ *\r
+ * Based on the Internet Junkbuster originally written\r
+ * by and Copyright (C) 1997 Anonymous Coders and \r
+ * Junkbusters Corporation. http://www.junkbusters.com\r
+ *\r
+ * This program is free software; you can redistribute it \r
+ * and/or modify it under the terms of the GNU General\r
+ * Public License as published by the Free Software\r
+ * Foundation; either version 2 of the License, or (at\r
+ * your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will\r
+ * be useful, but WITHOUT ANY WARRANTY; without even the\r
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A\r
+ * PARTICULAR PURPOSE. See the GNU General Public\r
+ * License for more details.\r
+ *\r
+ * The GNU General Public License should be included with\r
+ * this file. If not, you can view it at\r
+ * http://www.gnu.org/copyleft/gpl.html\r
+ * or write to the Free Software Foundation, Inc., 59\r
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
+ *\r
+ * Revisions :\r
+ * $Log:$\r
+ *\r
+ *********************************************************************/\r
+\r
+#include <windows.h>\r
+#include "config.h"\r
+#include "w32res.h"\r
+\r
+#ifdef __MINGW32__\r
+#include "cygwin.h"\r
+#endif\r
+\r
+/****************************************************************************\r
+ * Language-neutral resources\r
+ ****************************************************************************/\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)\r
+#ifdef _WIN32\r
+/* LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL */\r
+#pragma code_page(1252)\r
+#endif /* _WIN32 */\r
+\r
+/*\r
+ * Icons\r
+ *\r
+ * Icon with lowest ID value placed first to ensure application icon\r
+ * remains consistent on all systems.\r
+ */\r
+IDI_JUNKBUSTER ICON DISCARDABLE "icons/junkbust.ico"\r
+IDI_JUNKBUSTER1 ICON DISCARDABLE "icons/ico00001.ico"\r
+IDI_JUNKBUSTER2 ICON DISCARDABLE "icons/ico00002.ico"\r
+IDI_JUNKBUSTER3 ICON DISCARDABLE "icons/ico00003.ico"\r
+IDI_JUNKBUSTER4 ICON DISCARDABLE "icons/ico00004.ico"\r
+IDI_JUNKBUSTER5 ICON DISCARDABLE "icons/ico00005.ico"\r
+IDI_JUNKBUSTER6 ICON DISCARDABLE "icons/ico00006.ico"\r
+IDI_JUNKBUSTER7 ICON DISCARDABLE "icons/ico00007.ico"\r
+IDI_JUNKBUSTER8 ICON DISCARDABLE "icons/ico00008.ico"\r
+IDI_IDLE ICON DISCARDABLE "icons/idle.ico"\r
+\r
+#endif /* Neutral resources */\r
+\r
+\r
+/****************************************************************************\r
+ * English (U.S.) resources\r
+ ****************************************************************************/\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+/* LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US */\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+/*\r
+ * Menus\r
+ */\r
+\r
+IDR_TRAYMENU MENU DISCARDABLE\r
+BEGIN\r
+ POPUP "Popup"\r
+ BEGIN\r
+ MENUITEM "E&xit JunkBuster", ID_FILE_EXIT\r
+ MENUITEM SEPARATOR\r
+ POPUP "&Options"\r
+ BEGIN\r
+ MENUITEM "&Junkbuster...", ID_TOOLS_EDITJUNKBUSTER\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "&Blockers...", ID_TOOLS_EDITBLOCKERS\r
+ MENUITEM "&Cookies...", ID_TOOLS_EDITCOOKIES\r
+ MENUITEM "&Forward...", ID_TOOLS_EDITFORWARD\r
+#ifdef ACL_FILES\r
+ MENUITEM "&Access Control Lists...", ID_TOOLS_EDITACLS\r
+#endif /* def ACL_FILES */\r
+#ifdef USE_IMAGE_LIST\r
+ MENUITEM "&Images...", ID_TOOLS_EDITIMAGE\r
+#endif /* def USE_IMAGE_LIST */\r
+#ifdef KILLPOPUPS\r
+ MENUITEM "&Popups...", ID_TOOLS_EDITPOPUPS\r
+#endif /* def KILLPOPUPS */\r
+#ifdef PCRS\r
+ MENUITEM "Perl &Regexps...", ID_TOOLS_EDITPERLRE\r
+#endif /* def PCRS */\r
+#ifdef TRUST_FILES\r
+ MENUITEM "&Trust...", ID_TOOLS_EDITTRUST\r
+#endif /* def TRUST_FILES */\r
+ END\r
+ MENUITEM SEPARATOR\r
+#ifdef TOGGLE\r
+ MENUITEM "&Enable", ID_TOGGLE_IJB, CHECKED\r
+#endif\r
+ MENUITEM "&Reload config", ID_RELOAD_CONFIG\r
+ MENUITEM "Show &JunkBuster Window", ID_SHOWWINDOW\r
+ END\r
+END\r
+\r
+IDR_LOGVIEW MENU DISCARDABLE\r
+BEGIN\r
+ POPUP "&File"\r
+ BEGIN\r
+ MENUITEM "E&xit", ID_FILE_EXIT\r
+ END\r
+ POPUP "&Edit"\r
+ BEGIN\r
+ MENUITEM "Copy", ID_EDIT_COPY\r
+ END\r
+ POPUP "&View"\r
+ BEGIN\r
+ MENUITEM "&Clear Log", ID_VIEW_CLEARLOG\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "&Log Messages", ID_VIEW_LOGMESSAGES, CHECKED\r
+ MENUITEM "Message &Highlighting", ID_VIEW_MESSAGEHIGHLIGHTING, CHECKED\r
+ MENUITEM "Limit &Buffer Size", ID_VIEW_LIMITBUFFERSIZE, CHECKED\r
+ MENUITEM "&Activity Animation", ID_VIEW_ACTIVITYANIMATION, CHECKED\r
+ END\r
+ POPUP "&Options"\r
+ BEGIN\r
+#ifdef TOGGLE\r
+ MENUITEM "&Enable", ID_TOGGLE_IJB, CHECKED\r
+ MENUITEM "&Reload config", ID_RELOAD_CONFIG\r
+ MENUITEM SEPARATOR\r
+#endif\r
+ MENUITEM "&Junkbuster...", ID_TOOLS_EDITJUNKBUSTER\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "&Blockers...", ID_TOOLS_EDITBLOCKERS\r
+ MENUITEM "&Cookies...", ID_TOOLS_EDITCOOKIES\r
+ MENUITEM "&Forward...", ID_TOOLS_EDITFORWARD\r
+#ifdef ACL_FILES\r
+ MENUITEM "&Access Control Lists...",ID_TOOLS_EDITACLS\r
+#endif /* def ACL_FILES */\r
+#ifdef USE_IMAGE_LIST\r
+ MENUITEM "&Images...", ID_TOOLS_EDITIMAGE\r
+#endif /* def USE_IMAGE_LIST */\r
+#ifdef KILLPOPUPS\r
+ MENUITEM "&Popups...", ID_TOOLS_EDITPOPUPS\r
+#endif /* def KILLPOPUPS */\r
+#ifdef PCRS\r
+ MENUITEM "Perl &Regexps...", ID_TOOLS_EDITPERLRE\r
+#endif /* def PCRS */\r
+#ifdef TRUST_FILES\r
+ MENUITEM "&Trust...", ID_TOOLS_EDITTRUST\r
+#endif /* def TRUST_FILES */\r
+ END\r
+ POPUP "&Help"\r
+ BEGIN\r
+ MENUITEM "Junkbuster &FAQ", ID_HELP_FAQ\r
+ MENUITEM "Junkbuster &Manual", ID_HELP_MANUAL\r
+ MENUITEM "GNU &General Public Licence", ID_HELP_GPL\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "Junkbuster Status...", ID_HELP_STATUS\r
+ MENUITEM SEPARATOR\r
+ MENUITEM "About Junkbuster...", ID_HELP_ABOUTJUNKBUSTER\r
+ END\r
+END\r
+\r
+IDR_POPUP_SELECTION MENU DISCARDABLE\r
+BEGIN\r
+ POPUP "Popup"\r
+ BEGIN\r
+ MENUITEM "&Copy", ID_EDIT_COPY\r
+ END\r
+END\r
+\r
+\r
+/*\r
+ * Accelerators\r
+ */\r
+\r
+IDR_ACCELERATOR ACCELERATORS DISCARDABLE\r
+BEGIN\r
+ "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT\r
+END\r
+\r
+/*\r
+ * Icons\r
+ *\r
+ * Icon with lowest ID value placed first to ensure application icon\r
+ * remains consistent on all systems.\r
+ */\r
+IDI_DENYRULE ICON DISCARDABLE "icons/denyrule.ico"\r
+IDI_ALLOWRULE ICON DISCARDABLE "icons/icon1.ico"\r
+\r
+/*\r
+ * Dialog\r
+ */\r
+\r
+IDD_RULES DIALOG DISCARDABLE 0, 0, 239, 225\r
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "Blockers"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+ GROUPBOX "New Rule",IDC_STATIC,5,5,230,55\r
+ LTEXT "For:",IDC_STATIC,10,15,13,8\r
+ EDITTEXT IDC_NEW,10,25,220,12,ES_AUTOHSCROLL\r
+ COMBOBOX IDC_ACTION,10,40,75,37,CBS_DROPDOWNLIST | CBS_SORT |\r
+ WS_VSCROLL | WS_TABSTOP\r
+ PUSHBUTTON "C&reate!",IDC_CREATE,90,40,50,14\r
+ GROUPBOX "Rules",IDC_STATIC,5,65,230,135\r
+ CONTROL "List1",IDC_RULES,"SysListView32",LVS_REPORT |\r
+ LVS_SHOWSELALWAYS | LVS_EDITLABELS | WS_BORDER |\r
+ WS_TABSTOP,10,75,220,100\r
+ PUSHBUTTON "Move &Up",IDC_MOVEUP,10,180,50,14,WS_DISABLED\r
+ PUSHBUTTON "Move &Down",IDC_MOVEDOWN,65,180,50,14,WS_DISABLED\r
+ PUSHBUTTON "&Delete",IDC_DELETE,120,180,50,14,WS_DISABLED\r
+ PUSHBUTTON "&Save",IDC_SAVE,130,205,50,14\r
+ PUSHBUTTON "&Cancel",IDCANCEL,185,205,50,14\r
+END\r
+\r
+\r
+/*\r
+ * DESIGNINFO\r
+ */\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+GUIDELINES DESIGNINFO DISCARDABLE\r
+BEGIN\r
+ IDD_RULES, DIALOG\r
+ BEGIN\r
+ LEFTMARGIN, 7\r
+ RIGHTMARGIN, 232\r
+ TOPMARGIN, 7\r
+ BOTTOMMARGIN, 218\r
+ END\r
+END\r
+#endif // APSTUDIO_INVOKED\r
+\r
+\r
+/*\r
+ * String Table\r
+ */\r
+\r
+STRINGTABLE DISCARDABLE\r
+BEGIN\r
+ IDS_NEW_BLOCKER "Create rule for ""%s""..."\r
+END\r
+\r
+#endif /* English (U.S.) resources */\r
--- /dev/null
+const char w32log_rcs[] = "$Id: w32log.c,v 1.1 2001/05/13 21:57:07 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/w32log.c,v $
+ *
+ * Purpose : Functions for creating and destroying the log window,
+ * ouputting strings, processing messages and so on.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Written by and Copyright (C) 1999 Adam Lock
+ * <locka@iol.ie>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: w32log.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <windows.h>
+#include <richedit.h>
+
+#include "project.h"
+#include "w32log.h"
+#include "w32taskbar.h"
+#include "w32rulesdlg.h"
+#include "win32.h"
+#include "w32res.h"
+#include "jcc.h"
+#include "miscutil.h"
+#include "errlog.h"
+
+const char w32res_h_rcs[] = W32RES_H_VERSION;
+
+#ifdef __MINGW32__
+#include "cygwin.h"
+const char cygwin_h_rcs[] = CYGWIN_H_VERSION;
+#endif
+
+const char w32log_h_rcs[] = W32LOG_H_VERSION;
+
+/*
+ * Timers and the various durations
+ */
+#define TIMER_ANIM_ID 1
+#define TIMER_ANIM_TIME 100
+#define TIMER_ANIMSTOP_ID 2
+#define TIMER_ANIMSTOP_TIME 1000
+#define TIMER_CLIPBUFFER_ID 3
+#define TIMER_CLIPBUFFER_TIME 1000
+#define TIMER_CLIPBUFFER_FORCE_ID 4
+#define TIMER_CLIPBUFFER_FORCE_TIME 5000
+
+/*
+ * Styles of text that can be output
+ */
+#define STYLE_NONE 0
+#define STYLE_HIGHLIGHT 1
+#define STYLE_LINK 2
+#define STYLE_HEADER 3
+
+/*
+ * Number of frames of animation in tray activity sequence
+ */
+#define ANIM_FRAMES 8
+
+#define DEFAULT_MAX_BUFFER_LINES 200
+#define DEFAULT_LOG_FONT_NAME "MS Sans Serif"
+#define DEFAULT_LOG_FONT_SIZE 8
+
+/*
+ * These values affect the way the log window behaves, they should be read
+ * from a file but for the moment, they are hardcoded here. Some options are
+ * configurable through the UI.
+ */
+
+/* Indicates whether task bar shows activity animation */
+BOOL g_bShowActivityAnimation = 1;
+
+/* Indicates if the log window appears on the task bar */
+BOOL g_bShowOnTaskBar = 0;
+
+/* Indicates whether closing the log window really just hides it */
+BOOL g_bCloseHidesWindow = 1;
+
+/* Indicates if messages are logged at all */
+BOOL g_bLogMessages = 1;
+
+/* Indicates whether log messages are highlighted */
+BOOL g_bHighlightMessages = 1;
+
+/* Indicates if buffer is limited in size */
+BOOL g_bLimitBufferSize = 1;
+
+/* Maximum number of lines allowed in buffer when limited */
+int g_nMaxBufferLines = DEFAULT_MAX_BUFFER_LINES;
+
+/* Font to use */
+char g_szFontFaceName[255] = DEFAULT_LOG_FONT_NAME;
+
+/* Size of font to use */
+int g_nFontSize = DEFAULT_LOG_FONT_SIZE;
+
+
+#ifdef REGEX
+/* Regular expression for detected URLs */
+#define RE_URL "http:[^ \n\r]*"
+
+/*
+ * Regular expressions that are used to perform highlight in the log window
+ */
+static struct _Pattern
+{
+ const char *str;
+ int style;
+ regex_t buffer;
+} patterns_to_highlight[] =
+{
+ /* url headers */
+ { RE_URL, STYLE_LINK },
+/* { "[a-zA-Z0-9]+\\.[a-zA-Z0-9]+\\.[a-zA-Z0-9]+\\.[^ \n\r]*", STYLE_LINK }, */
+ /* interesting text to highlight */
+ { "crunch!", STYLE_HIGHLIGHT },
+ /* http headers */
+ { "referer:", STYLE_HEADER },
+ { "proxy-connection:", STYLE_HEADER },
+ { "proxy-agent:", STYLE_HEADER },
+ { "user-agent:", STYLE_HEADER },
+ { "host:", STYLE_HEADER },
+ { "accept:", STYLE_HEADER },
+ { "accept-encoding:", STYLE_HEADER },
+ { "accept-language:", STYLE_HEADER },
+ { "accept-charset:", STYLE_HEADER },
+ { "accept-ranges:", STYLE_HEADER },
+ { "date:", STYLE_HEADER },
+ { "cache-control:", STYLE_HEADER },
+ { "cache-last-checked:", STYLE_HEADER },
+ { "connection:", STYLE_HEADER },
+ { "content-type", STYLE_HEADER },
+ { "content-length", STYLE_HEADER },
+ { "cookie", STYLE_HEADER },
+ { "last-modified:", STYLE_HEADER },
+ { "pragma:", STYLE_HEADER },
+ { "server:", STYLE_HEADER },
+ { "etag:", STYLE_HEADER },
+ { "expires:", STYLE_HEADER },
+ { "warning:", STYLE_HEADER },
+ /* this is the terminator statement - do not delete! */
+ { NULL, STYLE_NONE }
+};
+#endif /* def REGEX */
+
+
+/*
+ * Public variables
+ */
+HWND g_hwndLogFrame;
+
+/*
+ * Private variables
+ */
+static CRITICAL_SECTION g_criticalsection;
+static HWND g_hwndTray;
+static HWND g_hwndLogBox;
+static WNDPROC g_fnLogBox;
+static HICON g_hiconAnim[ANIM_FRAMES];
+static HICON g_hiconIdle;
+static HICON g_hiconApp;
+static int g_nAnimFrame;
+static BOOL g_bClipPending = FALSE;
+static int g_nRichEditVersion = 0;
+
+/*
+ * Private functions
+ */
+static HWND CreateLogWindow(HINSTANCE hInstance, int nCmdShow);
+static HWND CreateHiddenLogOwnerWindow(HINSTANCE hInstance);
+static LRESULT CALLBACK LogWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static LRESULT CALLBACK LogOwnerWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static LRESULT CALLBACK LogRichEditProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static BOOL InitRichEdit(void);
+static void LogClipBuffer(void);
+static void LogCreatePatternMatchingBuffers(void);
+static void LogDestroyPatternMatchingBuffers(void);
+static int LogPutStringNoMatch(const char *pszText, int style);
+
+
+/*********************************************************************
+ *
+ * Function : InitLogWindow
+ *
+ * Description : Initialise the log window.
+ *
+ * Parameters : None
+ *
+ * Returns : Always TRUE (there should be error checking on the resources).
+ *
+ *********************************************************************/
+BOOL InitLogWindow(void)
+{
+ int i;
+
+ /* Load the icons */
+ g_hiconIdle = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_IDLE));
+ for (i = 0; i < ANIM_FRAMES; i++)
+ {
+ g_hiconAnim[i] = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_JUNKBUSTER1 + i));
+ }
+ g_hiconApp = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_JUNKBUSTER));
+
+ /* Create the user interface */
+ g_hwndLogFrame = CreateLogWindow(g_hInstance, g_nCmdShow);
+ g_hwndTray = CreateTrayWindow(g_hInstance);
+ TrayAddIcon(g_hwndTray, 1, g_hiconApp, "Junkbuster");
+
+ /* Create pattern matching buffers (for highlighting */
+ LogCreatePatternMatchingBuffers();
+
+ /* Create a critical section to protect multi-threaded access to certain things */
+ InitializeCriticalSection(&g_criticalsection);
+
+ return TRUE;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : TermLogWindow
+ *
+ * Description : Cleanup the logwindow.
+ *
+ * Parameters : None
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void TermLogWindow(void)
+{
+ int i;
+
+ LogDestroyPatternMatchingBuffers();
+
+ TrayDeleteIcon(g_hwndTray, 1);
+ DeleteObject(g_hiconApp);
+ DeleteObject(g_hiconIdle);
+ for (i = 0; i < ANIM_FRAMES; i++)
+ {
+ DeleteObject(g_hiconAnim[i]);
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : LogCreatePatternMatchingBuffers
+ *
+ * Description : Compile the pattern matching buffers.
+ *
+ * Parameters : None
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void LogCreatePatternMatchingBuffers(void)
+{
+#ifdef REGEX
+ int i;
+ for (i = 0; patterns_to_highlight[i].str != NULL; i++)
+ {
+ regcomp(&patterns_to_highlight[i].buffer, patterns_to_highlight[i].str, REG_ICASE);
+ }
+#endif
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : LogDestroyPatternMatchingBuffers
+ *
+ * Description : Free up the pattern matching buffers.
+ *
+ * Parameters : None
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void LogDestroyPatternMatchingBuffers(void)
+{
+#ifdef REGEX
+ int i;
+ for (i = 0; patterns_to_highlight[i].str != NULL; i++)
+ {
+ regfree(&patterns_to_highlight[i].buffer);
+ }
+#endif
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : LogGetURLUnderCursor
+ *
+ * Description : Returns the URL from under the cursor (remember to free it!).
+ *
+ * Parameters : None
+ *
+ * Returns : NULL or a pointer to an URL string.
+ *
+ *********************************************************************/
+char *LogGetURLUnderCursor(void)
+{
+ char *szResult = NULL;
+#ifdef REGEX
+ regex_t re;
+ POINT ptCursor;
+ POINTL ptl;
+ DWORD nPos;
+ DWORD nWordStart = 0;
+ DWORD nWordEnd = 0;
+
+ regcomp(&re, RE_URL, REG_ICASE);
+
+ /* Get the position of the cursor over the text window */
+ GetCursorPos(&ptCursor);
+ ScreenToClient(g_hwndLogBox, &ptCursor);
+ ptl.x = ptCursor.x;
+ ptl.y = ptCursor.y;
+
+ /* Search backwards and fowards to obtain the word that is highlighted */
+ nPos = LOWORD(SendMessage(g_hwndLogBox, EM_CHARFROMPOS, 0, (LPARAM) &ptl));
+ nWordStart = SendMessage(g_hwndLogBox, EM_FINDWORDBREAK, WB_LEFT, nPos);
+ nWordEnd = SendMessage(g_hwndLogBox, EM_FINDWORDBREAK, WB_RIGHTBREAK, nPos);
+
+ /* Compare the string to the pattern */
+ if (nWordEnd > nWordStart)
+ {
+ TEXTRANGE range;
+ regmatch_t match;
+
+ range.chrg.cpMin = nWordStart;
+ range.chrg.cpMax = nWordEnd;
+ range.lpstrText = (LPSTR)zalloc(nWordEnd - nWordStart + 1);
+ SendMessage(g_hwndLogBox, EM_GETTEXTRANGE, 0, (LPARAM) &range);
+
+ if (regexec(&re, range.lpstrText, 1, &match, 0) == 0)
+ {
+ szResult = range.lpstrText;
+ }
+ else
+ {
+ free(range.lpstrText);
+ }
+
+ regfree(&re);
+ }
+#endif
+ return szResult;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : LogPutString
+ *
+ * Description : Inserts text into the logging window. This is really
+ * a REGEXP aware wrapper function to `LogPutStringNoMatch'.
+ *
+ * Parameters :
+ * 1 : pszText = pointer to string going to the log window
+ *
+ * Returns : 1 => success, else the return code from `LogPutStringNoMatch'.
+ * FIXME: this is backwards to the rest of IJB and to common
+ * programming practice. Please use 0 => success instead.
+ *
+ *********************************************************************/
+int LogPutString(const char *pszText)
+{
+#ifdef REGEX
+ int i;
+#endif
+ int result = 0;
+
+ if (pszText == NULL || strlen(pszText) == 0)
+ {
+ return 1;
+ }
+
+ if (!g_bLogMessages)
+ {
+ return 1;
+ }
+
+ /* Critical section stops multiple threads doing nasty interactions that
+ * foul up the highlighting and output.
+ */
+ EnterCriticalSection(&g_criticalsection);
+
+#ifdef REGEX
+ if (g_bHighlightMessages)
+ {
+ regmatch_t match;
+
+ /* First things first, regexp scan for various things that we would like highlighted */
+ for (i = 0; patterns_to_highlight[i].str != NULL; i++)
+ {
+ if (regexec(&patterns_to_highlight[i].buffer, pszText, 1, &match, 0) == 0)
+ {
+ char *pszBefore = NULL;
+ char *pszMatch = NULL;
+ char *pszAfter = NULL;
+ int nMatchSize;
+
+ /* Split the string up into pieces representing the strings, before
+ at and after the matching pattern
+ */
+ if (match.rm_so > 0)
+ {
+ pszBefore = (char *)malloc((match.rm_so + 1) * sizeof(char));
+ memset(pszBefore, 0, (match.rm_so + 1) * sizeof(char));
+ strncpy(pszBefore, pszText, match.rm_so);
+ }
+ if (match.rm_eo < strlen(pszText))
+ {
+ pszAfter = strdup(&pszText[match.rm_eo]);
+ }
+ nMatchSize = match.rm_eo - match.rm_so;
+ pszMatch = (char *)malloc(nMatchSize + 1);
+ strncpy(pszMatch, &pszText[match.rm_so], nMatchSize);
+ pszMatch[nMatchSize] = '\0';
+
+ /* Recursively call LogPutString */
+ if (pszBefore)
+ {
+ LogPutString(pszBefore);
+ free(pszBefore);
+ }
+ if (pszMatch)
+ {
+ LogPutStringNoMatch(pszMatch, patterns_to_highlight[i].style);
+ free(pszMatch);
+ }
+ if (pszAfter)
+ {
+ LogPutString(pszAfter);
+ free(pszAfter);
+ }
+
+ result = 1;
+ goto end;
+ }
+ }
+ }
+#endif
+
+ result = LogPutStringNoMatch(pszText, STYLE_NONE);
+
+#ifdef REGEX
+end:
+#endif
+ LeaveCriticalSection(&g_criticalsection);
+
+ return result;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : LogPutStringNoMatch
+ *
+ * Description : Puts a string into the logging window.
+ *
+ * Parameters :
+ * 1 : pszText = pointer to string going to the log window
+ * 2 : style = STYLE_NONE, STYLE_HEADER, STYLE_HIGHLIGHT, or STYLE_LINK
+ *
+ * Returns : Always 1 => success.
+ * FIXME: this is backwards to the rest of IJB and to common
+ * programming practice. Please use 0 => success instead.
+ *
+ *********************************************************************/
+int LogPutStringNoMatch(const char *pszText, int style)
+{
+ CHARRANGE range;
+ CHARFORMAT format;
+ int nTextLength;
+
+ assert(g_hwndLogBox);
+ if (g_hwndLogBox == NULL)
+ {
+ return 1;
+ }
+
+ /* TODO preserve existing selection */
+
+ /* Go to the end of the text */
+ nTextLength = GetWindowTextLength(g_hwndLogBox);
+ range.cpMin = nTextLength;
+ range.cpMax = nTextLength;
+ SendMessage(g_hwndLogBox, EM_EXSETSEL, 0, (LPARAM) &range);
+
+ /* Apply a formatting style */
+ memset(&format, 0, sizeof(format));
+ format.cbSize = sizeof(format);
+ format.dwMask = CFM_BOLD | CFM_UNDERLINE | CFM_STRIKEOUT | CFM_ITALIC | CFM_COLOR | CFM_FACE | CFM_SIZE;
+ format.yHeight = (g_nFontSize * 1440) / 72;
+ strcpy(format.szFaceName, g_szFontFaceName);
+ if (style == STYLE_NONE)
+ {
+ /* DO NOTHING */
+ format.dwEffects |= CFE_AUTOCOLOR;
+ }
+ else if (style == STYLE_HEADER)
+ {
+ format.dwEffects |= CFE_AUTOCOLOR | CFE_ITALIC;
+ }
+ else if (style == STYLE_HIGHLIGHT)
+ {
+ format.dwEffects |= CFE_AUTOCOLOR | CFE_BOLD;
+ }
+ else if (style == STYLE_LINK)
+ {
+ format.dwEffects |= CFE_UNDERLINE;
+ format.crTextColor = RGB(0, 0, 255);
+ }
+ SendMessage(g_hwndLogBox, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &format);
+
+ /* Append text to the end */
+ SendMessage(g_hwndLogBox, EM_REPLACESEL, FALSE, (LPARAM) pszText);
+
+ /* TODO Restore the old selection */
+
+ /* Purge buffer */
+ if (strchr(pszText, '\n') != NULL)
+ {
+ SetTimer(g_hwndLogFrame, TIMER_CLIPBUFFER_ID, TIMER_CLIPBUFFER_TIME, NULL);
+ if (!g_bClipPending)
+ {
+ /* Set the force clip timer going. This timer ensures clipping is done
+ intermittently even when there is a sustained burst of logging
+ */
+ SetTimer(g_hwndLogFrame, TIMER_CLIPBUFFER_FORCE_ID, TIMER_CLIPBUFFER_FORCE_TIME, NULL);
+ }
+ g_bClipPending = TRUE;
+ }
+
+ return 1;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : LogShowActivity
+ *
+ * Description : Start the spinner.
+ *
+ * Parameters : None
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void LogShowActivity(void)
+{
+ /* Start some activity timers */
+ if (g_bShowActivityAnimation)
+ {
+ SetTimer(g_hwndLogFrame, TIMER_ANIM_ID, TIMER_ANIM_TIME, NULL);
+ SetTimer(g_hwndLogFrame, TIMER_ANIMSTOP_ID, TIMER_ANIMSTOP_TIME, NULL);
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : LogClipBuffer
+ *
+ * Description : Prunes old lines from the log.
+ *
+ * Parameters : None
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void LogClipBuffer(void)
+{
+ int nLines = SendMessage(g_hwndLogBox, EM_GETLINECOUNT, 0, 0);
+ if (g_bLimitBufferSize && nLines > g_nMaxBufferLines)
+ {
+ /* Compute the range representing the lines to be deleted */
+ LONG nLastLineToDelete = nLines - g_nMaxBufferLines;
+ LONG nLastChar = SendMessage(g_hwndLogBox, EM_LINEINDEX, nLastLineToDelete, 0);
+ CHARRANGE range;
+ range.cpMin = 0;
+ range.cpMax = nLastChar;
+
+ /* TODO get current selection */
+
+ /* TODO adjust and clip old selection against range to be deleted */
+
+ /* Select range and erase it (turning off autoscroll to prevent
+ nasty scrolling) */
+ SendMessage(g_hwndLogBox, EM_SETOPTIONS, ECOOP_XOR, ECO_AUTOVSCROLL);
+ SendMessage(g_hwndLogBox, EM_EXSETSEL, 0, (LPARAM) &range);
+ SendMessage(g_hwndLogBox, EM_REPLACESEL, FALSE, (LPARAM) "");
+ SendMessage(g_hwndLogBox, EM_SETOPTIONS, ECOOP_XOR, ECO_AUTOVSCROLL);
+
+ /* Restore old selection */
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : CreateHiddenLogOwnerWindow
+ *
+ * Description : Creates a hidden owner window that stops the log
+ * window appearing in the task bar.
+ *
+ * Parameters :
+ * 1 : hInstance = application's instance handle
+ *
+ * Returns : Handle to newly created window.
+ *
+ *********************************************************************/
+HWND CreateHiddenLogOwnerWindow(HINSTANCE hInstance)
+{
+ static const char *szWndName = "JunkbusterLogLogOwner";
+ WNDCLASS wc;
+ HWND hwnd;
+
+ wc.style = 0;
+ wc.lpfnWndProc = LogOwnerWindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = 0;
+ wc.hCursor = 0;
+ wc.hbrBackground = 0;
+ wc.lpszMenuName = 0;
+ wc.lpszClassName = szWndName;
+
+ RegisterClass(&wc);
+
+ hwnd = CreateWindow(szWndName, szWndName,
+ WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, NULL, NULL, hInstance, NULL );
+
+ return hwnd;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : LogOwnerWindowProc
+ *
+ * Description : Dummy procedure that does nothing special.
+ *
+ * Parameters :
+ * 1 : hwnd = window handle
+ * 2 : uMsg = message number
+ * 3 : wParam = first param for this message
+ * 4 : lParam = next param for this message
+ *
+ * Returns : Same as `DefWindowProc'.
+ *
+ *********************************************************************/
+LRESULT CALLBACK LogOwnerWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : CreateLogWindow
+ *
+ * Description : Create the logging window.
+ *
+ * Parameters :
+ * 1 : hInstance = application's instance handle
+ * 2 : nCmdShow = window show value (MIN, MAX, NORMAL, etc...)
+ *
+ * Returns : Handle to newly created window.
+ *
+ *********************************************************************/
+HWND CreateLogWindow(HINSTANCE hInstance, int nCmdShow)
+{
+ static const char *szWndName = "JunkbusterLogWindow";
+ static const char *szWndTitle = "Junkbuster";
+
+ HWND hwnd = NULL;
+ HWND hwndOwner = (g_bShowOnTaskBar) ? NULL : CreateHiddenLogOwnerWindow(hInstance);
+ HWND hwndChild = NULL;
+ RECT rcClient;
+ WNDCLASSEX wc;
+
+ memset(&wc, 0, sizeof(wc));
+ wc.cbSize = sizeof(wc);
+ wc.style = CS_DBLCLKS;
+ wc.lpfnWndProc = LogWindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = g_hiconApp;
+ wc.hCursor = 0;
+ wc.hbrBackground = 0;
+ wc.lpszMenuName = MAKEINTRESOURCE(IDR_LOGVIEW);
+ wc.lpszClassName = szWndName;
+ wc.hbrBackground = GetStockObject(WHITE_BRUSH);
+ RegisterClassEx(&wc);
+
+ hwnd = CreateWindowEx(WS_EX_APPWINDOW, szWndName, szWndTitle,
+ WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, hwndOwner, NULL, hInstance, NULL);
+
+ /* Now create a child list box */
+ GetClientRect(hwnd, &rcClient);
+
+ /* Create a rich edit control */
+ InitRichEdit();
+ g_hwndLogBox = CreateWindowEx(0, (g_nRichEditVersion == 0x0100) ? "RichEdit" : RICHEDIT_CLASS, "",
+ ES_AUTOVSCROLL | ES_MULTILINE | ES_READONLY | ES_NOHIDESEL | WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
+ rcClient.left, rcClient.top, rcClient.right, rcClient.bottom,
+ hwnd, NULL, hInstance, NULL);
+/* SendMessage(g_hwndLogBox, EM_SETWORDWRAPMODE, 0, 0); */
+
+ /* Subclass the control to catch certain messages */
+ g_fnLogBox = (WNDPROC) GetWindowLong(g_hwndLogBox, GWL_WNDPROC);
+ SetWindowLong(g_hwndLogBox, GWL_WNDPROC, (LONG) LogRichEditProc);
+
+ /* Minimizing looks stupid when the log window is not on the task bar, so hide instead */
+ if (!g_bShowOnTaskBar &&
+ (nCmdShow == SW_SHOWMINIMIZED ||
+ nCmdShow == SW_MINIMIZE ||
+ nCmdShow == SW_SHOWMINNOACTIVE))
+ {
+ nCmdShow = SW_HIDE;
+ }
+
+ ShowWindow(hwnd, nCmdShow);
+ UpdateWindow(hwnd);
+
+ GetClientRect(g_hwndLogFrame, &rcClient);
+ SetWindowPos(g_hwndLogBox, NULL, rcClient.left, rcClient.top, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, SWP_NOZORDER);
+
+ return hwnd;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : InitRichEdit
+ *
+ * Description : Initialise the rich edit control library.
+ *
+ * Parameters : None
+ *
+ * Returns : TRUE => success, FALSE => failure.
+ * FIXME: this is backwards to the rest of IJB and to common
+ * programming practice. Please use 0 => success instead.
+ *
+ *********************************************************************/
+BOOL InitRichEdit(void)
+{
+ static HINSTANCE hInstRichEdit;
+ if (hInstRichEdit == NULL)
+ {
+ g_nRichEditVersion = 0;
+ hInstRichEdit = LoadLibraryA("RICHED20.DLL");
+ if (hInstRichEdit)
+ {
+ g_nRichEditVersion = _RICHEDIT_VER;
+ }
+ else
+ {
+ hInstRichEdit = LoadLibraryA("RICHED32.DLL");
+ if (hInstRichEdit)
+ {
+ g_nRichEditVersion = 0x0100;
+ }
+ }
+ }
+ return (hInstRichEdit != NULL) ? TRUE : FALSE;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : ShowLogWindow
+ *
+ * Description : Shows or hides the log window. We will also raise the
+ * window on a show command in case it is buried.
+ *
+ * Parameters :
+ * 1 : bShow = TRUE to show, FALSE to mimize/hide
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void ShowLogWindow(BOOL bShow)
+{
+ if (bShow)
+ {
+ SetForegroundWindow(g_hwndLogFrame);
+ SetWindowPos(g_hwndLogFrame, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
+ }
+ else if (g_bShowOnTaskBar)
+ {
+ ShowWindow(g_hwndLogFrame, SW_MINIMIZE);
+ }
+ else
+ {
+ ShowWindow(g_hwndLogFrame, SW_HIDE);
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : EditFile
+ *
+ * Description : Opens the specified setting file for editing.
+ *
+ * Parameters :
+ * 1 : filename = filename from the config (aka junkbstr.txt) file.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void EditFile(const char *filename)
+{
+ if (filename)
+ {
+ ShellExecute(g_hwndLogFrame, "open", filename, NULL, NULL, SW_SHOWNORMAL);
+ }
+
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* Windows message handlers */
+/*--------------------------------------------------------------------------*/
+
+
+/*********************************************************************
+ *
+ * Function : OnLogRButtonUp
+ *
+ * Description : Handler for WM_RBUTTONUP messages.
+ *
+ * Parameters :
+ * 1 : nModifier = wParam from mouse message (unused)
+ * 2 : x = x coordinate of the mouse event
+ * 3 : y = y coordinate of the mouse event
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void OnLogRButtonUp(int nModifier, int x, int y)
+{
+ HMENU hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_POPUP_SELECTION));
+ if (hMenu != NULL)
+ {
+ HMENU hMenuPopup = GetSubMenu(hMenu, 0);
+ char *szURL;
+
+ /* Check if there is a selection */
+ CHARRANGE range;
+ SendMessage(g_hwndLogBox, EM_EXGETSEL, 0, (LPARAM) &range);
+ if (range.cpMin == range.cpMax)
+ {
+ EnableMenuItem(hMenuPopup, ID_EDIT_COPY, MF_BYCOMMAND | MF_GRAYED);
+ }
+ else
+ {
+ EnableMenuItem(hMenuPopup, ID_EDIT_COPY, MF_BYCOMMAND | MF_ENABLED);
+ }
+
+ /* Check if cursor is over a link */
+ szURL = LogGetURLUnderCursor();
+ if (szURL)
+ {
+ MENUITEMINFO item;
+ TCHAR szMenuItemTemplate[1000];
+ char *szMenuItem;
+
+ memset(&item, 0, sizeof(item));
+ item.cbSize = sizeof(item);
+ item.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
+ item.fType = MFT_STRING;
+ item.fState = MFS_ENABLED;
+ item.wID = ID_NEW_BLOCKER;
+
+ /* Put the item into the menu */
+ memset(szMenuItemTemplate, 0, sizeof(szMenuItemTemplate));
+ LoadString(g_hInstance, IDS_NEW_BLOCKER, szMenuItemTemplate, sizeof(szMenuItemTemplate) / sizeof(szMenuItemTemplate[0]));
+
+ szMenuItem = (char *)malloc(strlen(szMenuItemTemplate) + strlen(szURL) + 1);
+ sprintf(szMenuItem, szMenuItemTemplate, szURL);
+
+ item.dwTypeData = szMenuItem;
+ item.cch = strlen(szMenuItem);
+
+ InsertMenuItem(hMenuPopup, 1, TRUE, &item);
+
+ SetDefaultRule(szURL);
+
+ free(szURL);
+ }
+
+ /* Display the popup */
+ TrackPopupMenu(hMenuPopup, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON, x, y, 0, g_hwndLogFrame, NULL);
+ DestroyMenu(hMenu);
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : OnLogCommand
+ *
+ * Description : Handler for WM_COMMAND messages.
+ *
+ * Parameters :
+ * 1 : nCommand = the command portion of the menu selection event
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void OnLogCommand(int nCommand)
+{
+ switch (nCommand)
+ {
+ case ID_SHOWWINDOW:
+ ShowLogWindow(TRUE);
+ break;
+
+ case ID_FILE_EXIT:
+ PostMessage(g_hwndLogFrame, WM_CLOSE, 0, 0);
+ break;
+
+ case ID_EDIT_COPY:
+ SendMessage(g_hwndLogBox, WM_COPY, 0, 0);
+ break;
+
+ case ID_VIEW_CLEARLOG:
+ SendMessage(g_hwndLogBox, WM_SETTEXT, 0, (LPARAM) "");
+ break;
+
+ case ID_VIEW_LOGMESSAGES:
+ g_bLogMessages = !g_bLogMessages;
+ /* SaveLogSettings(); */
+ break;
+
+ case ID_VIEW_MESSAGEHIGHLIGHTING:
+ g_bHighlightMessages = !g_bHighlightMessages;
+ /* SaveLogSettings(); */
+ break;
+
+ case ID_VIEW_LIMITBUFFERSIZE:
+ g_bLimitBufferSize = !g_bLimitBufferSize;
+ /* SaveLogSettings(); */
+ break;
+
+ case ID_VIEW_ACTIVITYANIMATION:
+ g_bShowActivityAnimation = !g_bShowActivityAnimation;
+ /* SaveLogSettings(); */
+ break;
+
+#ifdef TOGGLE
+ /* by haroon - change toggle to its opposite value */
+ case ID_TOGGLE_IJB:
+ g_bToggleIJB = !g_bToggleIJB;
+ if (g_bToggleIJB)
+ {
+ log_error(LOG_LEVEL_INFO, "Now toggled ON.");
+ }
+ else
+ {
+ log_error(LOG_LEVEL_INFO, "Now toggled OFF.");
+ }
+ break;
+#endif
+
+ case ID_RELOAD_CONFIG:
+ configret = 0;
+ load_config( 1 );
+
+ if ( configret )
+ {
+ log_error(LOG_LEVEL_ERROR, "load_config encountered a problem! You should probably restart IJB.");
+ }
+ else
+ {
+ log_error(LOG_LEVEL_INFO, "Configuration has been reloaded.");
+ }
+ break;
+
+ case ID_TOOLS_EDITJUNKBUSTER:
+ EditFile(configfile);
+ break;
+
+ case ID_TOOLS_EDITBLOCKERS:
+ EditFile(blockfile);
+ break;
+
+ case ID_TOOLS_EDITCOOKIES:
+ EditFile(cookiefile);
+ break;
+
+ case ID_TOOLS_EDITFORWARD:
+ EditFile(forwardfile);
+ break;
+
+#ifdef ACL_FILES
+ case ID_TOOLS_EDITACLS:
+ EditFile(aclfile);
+ break;
+#endif /* def ACL_FILES */
+
+#ifdef USE_IMAGE_LIST
+ case ID_TOOLS_EDITIMAGE:
+ EditFile(imagefile);
+ break;
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef PCRS
+ case ID_TOOLS_EDITPERLRE:
+ EditFile(re_filterfile);
+ break;
+#endif
+
+#ifdef KILLPOPUPS
+ case ID_TOOLS_EDITPOPUPS:
+ EditFile(popupfile);
+ break;
+#endif /* def KILLPOPUPS */
+
+#ifdef TRUST_FILES
+ case ID_TOOLS_EDITTRUST:
+ EditFile(trustfile);
+ break;
+#endif /* def TRUST_FILES */
+
+ case ID_NEW_BLOCKER:
+ ShowRulesDialog(g_hwndLogFrame);
+ break;
+
+ case ID_HELP_GPL:
+ ShellExecute(g_hwndLogFrame, "open", "gpl.html", NULL, NULL, SW_SHOWNORMAL);
+ break;
+
+ case ID_HELP_FAQ:
+ ShellExecute(g_hwndLogFrame, "open", "ijbfaq.html", NULL, NULL, SW_SHOWNORMAL);
+ break;
+
+ case ID_HELP_MANUAL:
+ ShellExecute(g_hwndLogFrame, "open", "ijbman.html", NULL, NULL, SW_SHOWNORMAL);
+ break;
+
+ case ID_HELP_STATUS:
+ ShellExecute(g_hwndLogFrame, "open", "Junkbuster Status.URL", NULL, NULL, SW_SHOWNORMAL);
+ break;
+
+ case ID_HELP_ABOUTJUNKBUSTER:
+ MessageBox(g_hwndLogFrame, win32_blurb, "Junkbuster Information", MB_OK);
+ break;
+
+ default:
+ /* DO NOTHING */
+ break;
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : OnLogInitMenu
+ *
+ * Description : Handler for WM_INITMENU messages. Enable, disable,
+ * check, and/or uncheck menu options as apropos.
+ *
+ * Parameters :
+ * 1 : hmenu = handle to menu to "make current"
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void OnLogInitMenu(HMENU hmenu)
+{
+ /* Only enable editors if there is a file to edit */
+ EnableMenuItem(hmenu, ID_TOOLS_EDITCOOKIES, MF_BYCOMMAND | (cookiefile ? MF_ENABLED : MF_GRAYED));
+ EnableMenuItem(hmenu, ID_TOOLS_EDITBLOCKERS, MF_BYCOMMAND | (blockfile ? MF_ENABLED : MF_GRAYED));
+ EnableMenuItem(hmenu, ID_TOOLS_EDITFORWARD, MF_BYCOMMAND | (forwardfile ? MF_ENABLED : MF_GRAYED));
+#ifdef ACL_FILES
+ EnableMenuItem(hmenu, ID_TOOLS_EDITACLS, MF_BYCOMMAND | (aclfile ? MF_ENABLED : MF_GRAYED));
+#endif /* def ACL_FILES */
+#ifdef USE_IMAGE_LIST
+ EnableMenuItem(hmenu, ID_TOOLS_EDITIMAGE, MF_BYCOMMAND | (imagefile ? MF_ENABLED : MF_GRAYED));
+#endif /* def USE_IMAGE_LIST */
+#ifdef KILLPOPUPS
+ EnableMenuItem(hmenu, ID_TOOLS_EDITPOPUPS, MF_BYCOMMAND | (popupfile ? MF_ENABLED : MF_GRAYED));
+#endif /* def KILLPOPUPS */
+#ifdef PCRS
+ EnableMenuItem(hmenu, ID_TOOLS_EDITPERLRE, MF_BYCOMMAND | (re_filterfile ? MF_ENABLED : MF_GRAYED));
+#endif
+#ifdef TRUST_FILES
+ EnableMenuItem(hmenu, ID_TOOLS_EDITTRUST, MF_BYCOMMAND | (trustfile ? MF_ENABLED : MF_GRAYED));
+#endif /* def TRUST_FILES */
+
+ /* Check/uncheck options */
+ CheckMenuItem(hmenu, ID_VIEW_LOGMESSAGES, MF_BYCOMMAND | (g_bLogMessages ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hmenu, ID_VIEW_MESSAGEHIGHLIGHTING, MF_BYCOMMAND | (g_bHighlightMessages ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hmenu, ID_VIEW_LIMITBUFFERSIZE, MF_BYCOMMAND | (g_bLimitBufferSize ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(hmenu, ID_VIEW_ACTIVITYANIMATION, MF_BYCOMMAND | (g_bShowActivityAnimation ? MF_CHECKED : MF_UNCHECKED));
+#ifdef TOGGLE
+ /* by haroon - menu item for Enable toggle on/off */
+ CheckMenuItem(hmenu, ID_TOGGLE_IJB, MF_BYCOMMAND | (g_bToggleIJB ? MF_CHECKED : MF_UNCHECKED));
+#endif
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : OnLogTimer
+ *
+ * Description : Handler for WM_TIMER messages.
+ *
+ * Parameters :
+ * 1 : nTimer = timer id (animation start/stop or clip buffer)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void OnLogTimer(int nTimer)
+{
+ switch (nTimer)
+ {
+ case TIMER_ANIM_ID:
+ TraySetIcon(g_hwndTray, 1, g_hiconAnim[g_nAnimFrame++ % ANIM_FRAMES]);
+ break;
+
+ case TIMER_ANIMSTOP_ID:
+ g_nAnimFrame = 0;
+ TraySetIcon(g_hwndTray, 1, g_hiconIdle);
+ KillTimer(g_hwndLogFrame, TIMER_ANIM_ID);
+ KillTimer(g_hwndLogFrame, TIMER_ANIMSTOP_ID);
+ break;
+
+ case TIMER_CLIPBUFFER_ID:
+ case TIMER_CLIPBUFFER_FORCE_ID:
+ LogClipBuffer();
+ g_bClipPending = FALSE;
+ KillTimer(g_hwndLogFrame, TIMER_CLIPBUFFER_ID);
+ KillTimer(g_hwndLogFrame, TIMER_CLIPBUFFER_FORCE_ID);
+ break;
+
+ default:
+ /* DO NOTHING */
+ break;
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : LogRichEditProc
+ *
+ * Description : Window subclass routine handles some events for the rich edit control.
+ *
+ * Parameters :
+ * 1 : hwnd = window handle of the rich edit control
+ * 2 : uMsg = message number
+ * 3 : wParam = first param for this message
+ * 4 : lParam = next param for this message
+ *
+ * Returns : Appropriate M$ window message handler codes.
+ *
+ *********************************************************************/
+LRESULT CALLBACK LogRichEditProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_RBUTTONUP:
+ {
+ POINT pt;
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+ ClientToScreen(hwnd, &pt);
+ OnLogRButtonUp(wParam, pt.x, pt.y);
+ }
+ return 0;
+ }
+ return CallWindowProc(g_fnLogBox, hwnd, uMsg, wParam, lParam);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : LogWindowProc
+ *
+ * Description : Windows call back routine handles events on the log window.
+ *
+ * Parameters :
+ * 1 : hwnd = handle of the logging window
+ * 2 : uMsg = message number
+ * 3 : wParam = first param for this message
+ * 4 : lParam = next param for this message
+ *
+ * Returns : Appropriate M$ window message handler codes.
+ *
+ *********************************************************************/
+LRESULT CALLBACK LogWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_CREATE:
+ return 0;
+
+ case WM_CLOSE:
+ /* This is the end - beautiful friend - the end */
+ DestroyWindow(g_hwndLogBox);
+ DestroyWindow(g_hwndLogFrame);
+ return 0;
+
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_SHOWWINDOW:
+ case WM_SIZE:
+ /* Resize the logging window to fit the new frame */
+ if (g_hwndLogBox)
+ {
+ RECT rc;
+ GetClientRect(g_hwndLogFrame, &rc);
+ SetWindowPos(g_hwndLogBox, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER);
+ }
+ return 0;
+
+ case WM_INITMENU:
+ OnLogInitMenu((HMENU) wParam);
+ return 0;
+
+ case WM_TIMER:
+ OnLogTimer(wParam);
+ return 0;
+
+ case WM_COMMAND:
+ OnLogCommand(LOWORD(wParam));
+ return 0;
+
+ case WM_SYSCOMMAND:
+ switch (wParam)
+ {
+ case SC_CLOSE:
+ if (g_bCloseHidesWindow)
+ {
+ ShowLogWindow(FALSE);
+ return 0;
+ }
+ break;
+ case SC_MINIMIZE:
+ ShowLogWindow(FALSE);
+ return 0;
+ }
+ break;
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _W32LOG_H
+#define _W32LOG_H
+#define W32LOG_H_VERSION "$Id: w32log.h,v 1.1 2001/05/13 21:57:07 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/w32log.h,v $
+ *
+ * Purpose : Functions for creating and destroying the log window,
+ * ouputting strings, processing messages and so on.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Written by and Copyright (C) 1999 Adam Lock
+ * <locka@iol.ie>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: w32log.h,v $
+ *
+ *********************************************************************/
+\f
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern HWND g_hwndLogFrame;
+
+/* Indicates whether task bar shows activity animation */
+extern BOOL g_bShowActivityAnimation;
+
+/* Indicates if the log window appears on the task bar */
+extern BOOL g_bShowOnTaskBar;
+
+/* Indicates whether closing the log window really just hides it */
+extern BOOL g_bCloseHidesWindow;
+
+/* Indicates if messages are logged at all */
+extern BOOL g_bLogMessages;
+
+/* Indicates whether log messages are highlighted */
+extern BOOL g_bHighlightMessages;
+
+/* Indicates if buffer is limited in size */
+extern BOOL g_bLimitBufferSize;
+
+/* Maximum number of lines allowed in buffer when limited */
+extern int g_nMaxBufferLines;
+
+/* Font to use */
+extern char g_szFontFaceName[255];
+
+/* Size of font to use */
+extern int g_nFontSize;
+
+
+extern int LogPutString(const char *pszText);
+extern BOOL InitLogWindow(void);
+extern void TermLogWindow(void);
+extern void ShowLogWindow(BOOL bShow);
+extern void LogShowActivity(void);
+
+/* Revision control strings from this header and associated .c file */
+extern const char w32log_rcs[];
+extern const char w32log_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _W32LOG_H */
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _W32RES_H
+#define _W32RES_H
+#define W32RES_H_VERSION "$Id: w32res.h,v 1.1 2001/05/13 21:57:07 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/w32res.h,v $
+ *
+ * Purpose : Identifiers for Windows GUI resources.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Based on the Internet Junkbuster originally written
+ * by and Copyright (C) 1997 Anonymous Coders and
+ * Junkbusters Corporation. http://www.junkbusters.com
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: w32res.h,v $
+ *
+ *********************************************************************/
+
+#define IDS_NEW_BLOCKER 1
+
+#define ID_NEW_BLOCKER 100
+#define IDR_TRAYMENU 101
+#define IDI_IDLE 102
+#define IDR_LOGVIEW 103
+#define IDR_ACCELERATOR 104
+#define IDR_POPUP_SELECTION 105
+#define IDD_RULES 106
+#define IDI_DENYRULE 107
+#define IDI_ALLOWRULE 108
+
+#define IDI_JUNKBUSTER 200
+#define IDI_JUNKBUSTER1 201
+#define IDI_JUNKBUSTER2 202
+#define IDI_JUNKBUSTER3 203
+#define IDI_JUNKBUSTER4 204
+#define IDI_JUNKBUSTER5 205
+#define IDI_JUNKBUSTER6 206
+#define IDI_JUNKBUSTER7 207
+#define IDI_JUNKBUSTER8 208
+
+#define IDC_NEW 300
+#define IDC_ACTION 301
+#define IDC_RULES 302
+#define IDC_CREATE 303
+#define IDC_MOVEUP 304
+#define IDC_MOVEDOWN 305
+#define IDC_DELETE 306
+#define IDC_SAVE 307
+
+#define ID_SHOWWINDOW 4000
+#define ID_HELP_ABOUTJUNKBUSTER 4001
+#define ID_FILE_EXIT 4002
+#define ID_VIEW_CLEARLOG 4003
+#define ID_VIEW_LOGMESSAGES 4004
+#define ID_VIEW_MESSAGEHIGHLIGHTING 4005
+#define ID_VIEW_LIMITBUFFERSIZE 4006
+#define ID_VIEW_ACTIVITYANIMATION 4007
+#define ID_HELP_FAQ 4008
+#define ID_HELP_MANUAL 4009
+#define ID_HELP_GPL 4010
+#define ID_HELP_STATUS 4011
+#ifdef TOGGLE
+#define ID_TOGGLE_IJB 4012
+#endif
+#define ID_RELOAD_CONFIG 4013
+
+/* Break these out so they are easier to extend, but keep consecutive */
+#define ID_TOOLS_EDITJUNKBUSTER 5000
+#define ID_TOOLS_EDITBLOCKERS 5001
+#define ID_TOOLS_EDITCOOKIES 5002
+#define ID_TOOLS_EDITFORWARD 5003
+
+#ifdef ACL_FILES
+#define ID_TOOLS_EDITACLS 5005
+#endif /* def ACL_FILES */
+
+#ifdef USE_IMAGE_LIST
+#define ID_TOOLS_EDITIMAGE 5006
+#endif /* def USE_IMAGE_LIST */
+
+#ifdef KILLPOPUPS
+#define ID_TOOLS_EDITPOPUPS 5007
+#endif /* def KILLPOPUPS */
+
+#ifdef PCRS
+#define ID_TOOLS_EDITPERLRE 5008
+#endif /* def PCRS */
+
+#ifdef TRUST_FILES
+#define ID_TOOLS_EDITTRUST 5004
+#endif /* def TRUST_FILES */
+
+/*
+ * The following symbols are declared in <afxres.h> in VC++.
+ * However, mingw32 doesn't have that header. Let's
+ * always declare them here, for consistency.
+ * These are the VC++ values.
+ */
+#define IDC_STATIC (-1)
+#define ID_EDIT_COPY 30000
+
+
+#endif /* ndef _W32RES_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+const char w32rulesdlg_rcs[] = "$Id: w32rulesdlg.c,v 1.1 2001/05/13 21:57:07 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/w32rulesdlg.c,v $
+ *
+ * Purpose : A dialog to allow GUI editing of the rules.
+ * Unfinished.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Written by and Copyright (C) 1999 Adam Lock
+ * <locka@iol.ie>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: w32rulesdlg.c,v $
+ *
+ *********************************************************************/
+\f
+#include "config.h"
+
+#include <stdio.h>
+
+#include <windows.h>
+#include <commctrl.h>
+
+#include "w32res.h"
+#include "w32rulesdlg.h"
+#include "win32.h"
+
+#ifdef __MINGW32__
+#include "cygwin.h"
+#endif
+
+const char w32rulesdlg_h_rcs[] = W32RULESDLG_H_VERSION;
+
+const int nSmallIconWidth = 16;
+const int nSmallIconHeight = 16;
+
+static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+static HIMAGELIST g_hImageList = NULL;
+static char *g_pszDefaultRule;
+static BOOL g_bDirty = FALSE;
+
+
+
+/*********************************************************************
+ *
+ * Function : ShowRulesDialog
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndParent = (what?)
+ *
+ * Returns : (Please fill me in!)
+ *
+ *********************************************************************/
+int ShowRulesDialog(HWND hwndParent)
+{
+ DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_RULES), hwndParent, DialogProc);
+ return TRUE;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : SetDefaultRule
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : pszRule = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void SetDefaultRule(const char *pszRule)
+{
+ if (pszRule == NULL)
+ {
+ if (g_pszDefaultRule)
+ {
+ free(g_pszDefaultRule);
+ g_pszDefaultRule = NULL;
+ }
+ }
+ else
+ {
+ g_pszDefaultRule = strdup(pszRule);
+ }
+
+}
+
+
+#define IMAGE_ALLOW 0
+#define IMAGE_DENY 1
+
+/*********************************************************************
+ *
+ * Function : InsertRule
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndListView = (what?)
+ * 2 : pszRule = (what?)
+ * 3 : bAllow = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void InsertRule(HWND hwndListView, const char *pszRule, BOOL bAllow)
+{
+ LVITEM item;
+ item.mask = LVIF_TEXT | LVIF_IMAGE;
+ item.pszText = (char *)pszRule;
+ item.iItem = ListView_GetItemCount(hwndListView) + 1;
+ item.iSubItem = 0;
+ item.iImage = bAllow ? IMAGE_ALLOW : IMAGE_DENY;
+ ListView_InsertItem(hwndListView, &item);
+ /* TODO add subitem for whether the rule is always or never */
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : SetDirty
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : bDirty = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void SetDirty(BOOL bDirty)
+{
+ g_bDirty = bDirty;
+ /* TODO Change some values */
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : OnInitDialog
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndDlg = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void OnInitDialog(HWND hwndDlg)
+{
+ LVCOLUMN aCols[2];
+ HWND hwndListView;
+ RECT rcListView;
+ int cx;
+
+ if (g_hImageList == NULL)
+ {
+ /* Create image list and add icons */
+ HICON hIconDeny = LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_DENYRULE), IMAGE_ICON, nSmallIconWidth, nSmallIconHeight, 0);
+ HICON hIconAllow = LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_ALLOWRULE), IMAGE_ICON, nSmallIconWidth, nSmallIconHeight, 0);
+ g_hImageList = ImageList_Create(nSmallIconWidth, nSmallIconHeight, ILC_COLOR | ILC_MASK, 0, 10);
+ ImageList_AddIcon(g_hImageList, hIconAllow);
+ ImageList_AddIcon(g_hImageList, hIconDeny);
+ }
+
+ /* Set the default rule value if there is one */
+ if (g_pszDefaultRule)
+ {
+ SetDlgItemText(hwndDlg, IDC_NEW, g_pszDefaultRule);
+ SetDefaultRule(NULL);
+ }
+
+ /* Initialise the list view */
+ hwndListView = GetDlgItem(hwndDlg, IDC_RULES);
+ ListView_SetImageList(hwndListView, g_hImageList, LVSIL_SMALL);
+ GetClientRect(hwndListView, &rcListView);
+ cx = rcListView.right - rcListView.left;
+ aCols[0].mask = LVCF_TEXT | LVCF_WIDTH;
+ aCols[0].pszText = "Rule";
+ aCols[0].cx = (70 * cx) / 100;
+ aCols[1].mask = LVCF_TEXT | LVCF_WIDTH;
+ aCols[1].pszText = "Applies when";
+ aCols[1].cx = cx - aCols[0].cx;
+ ListView_InsertColumn(hwndListView, 0, &aCols[0]);
+ ListView_InsertColumn(hwndListView, 1, &aCols[1]);
+
+ /* Read and add rules to the list */
+ /* TODO */
+ InsertRule(hwndListView, "Test rule 1", TRUE);
+ InsertRule(hwndListView, "Test rule 2", TRUE);
+ InsertRule(hwndListView, "Test rule 3", FALSE);
+ InsertRule(hwndListView, "Test rule 4", FALSE);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : GetFirstSelectedItem
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndDlg = (what?)
+ *
+ * Returns : (Please fill me in!)
+ *
+ *********************************************************************/
+static int GetFirstSelectedItem(HWND hwndDlg)
+{
+ /* Check for selected items */
+ HWND hwndListView = GetDlgItem(hwndDlg, IDC_RULES);
+ int nItem = -1;
+ do
+ {
+ nItem = ListView_GetNextItem(hwndListView, nItem, LVNI_SELECTED);
+ if (nItem >= 0)
+ {
+ return nItem;
+ }
+ } while (nItem >= 0);
+ return -1;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : OnRulesItemChanged
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndDlg = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void OnRulesItemChanged(HWND hwndDlg)
+{
+ int nItem = GetFirstSelectedItem(hwndDlg);
+ HWND hwndListView = GetDlgItem(hwndDlg, IDC_RULES);
+ int nItems = ListView_GetItemCount(hwndListView);
+ BOOL bHaveSelection = (nItem >= 0) ? TRUE : FALSE;
+ BOOL bMoveUp = (bHaveSelection && nItem > 0) ? TRUE : FALSE;
+ BOOL bMoveDown = (bHaveSelection && nItem < nItems - 1) ? TRUE : FALSE;
+
+ /* Enable/disable buttons */
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), bHaveSelection);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), bMoveUp);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), bMoveDown);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : MoveRules
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndDlg = (what?)
+ * 2 : bMoveUp = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void MoveRules(HWND hwndDlg, BOOL bMoveUp)
+{
+}
+
+
+/*********************************************************************
+ *
+ * Function : OnMoveRuleUpClick
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndDlg = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void OnMoveRuleUpClick(HWND hwndDlg)
+{
+}
+
+
+/*********************************************************************
+ *
+ * Function : OnMoveRuleDownClick
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndDlg = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void OnMoveRuleDownClick(HWND hwndDlg)
+{
+}
+
+
+/*********************************************************************
+ *
+ * Function : OnCreateRuleClick
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndDlg = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void OnCreateRuleClick(HWND hwndDlg)
+{
+}
+
+
+/*********************************************************************
+ *
+ * Function : OnDeleteRuleClick
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndDlg = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void OnDeleteRuleClick(HWND hwndDlg)
+{
+ /* Get selection and remove it */
+ int nItem = GetFirstSelectedItem(hwndDlg);
+ if (nItem >= 0)
+ {
+ LVITEM item;
+ HWND hwndListView = GetDlgItem(hwndDlg, IDC_RULES);
+ item.mask = LVIF_PARAM;
+ item.iItem = nItem;
+ item.iSubItem = 0;
+ ListView_GetItem(hwndListView, &item);
+ /* TODO erase data stored with item */
+ ListView_DeleteItem(hwndListView, nItem);
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : OnCommand
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndDlg = (what?)
+ * 2 : nCommand = (what?)
+ * 3 : nNotifyCode = (what?)
+ * 4 : hwndItem = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void OnCommand(HWND hwndDlg, int nCommand, int nNotifyCode, HWND hwndItem)
+{
+ switch (nCommand)
+ {
+ case IDCANCEL:
+ case IDC_SAVE:
+ EndDialog(hwndDlg, IDOK);
+ break;
+ case IDC_CREATE:
+ if (nNotifyCode == BN_CLICKED)
+ {
+ OnCreateRuleClick(hwndDlg);
+ }
+ break;
+ case IDC_DELETE:
+ if (nNotifyCode == BN_CLICKED)
+ {
+ OnDeleteRuleClick(hwndDlg);
+ }
+ break;
+ case IDC_MOVEUP:
+ if (nNotifyCode == BN_CLICKED)
+ {
+ OnMoveRuleUpClick(hwndDlg);
+ }
+ break;
+ case IDC_MOVEDOWN:
+ if (nNotifyCode == BN_CLICKED)
+ {
+ OnMoveRuleDownClick(hwndDlg);
+ }
+ break;
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : OnNotify
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndDlg = (what?)
+ * 2 : nIdCtrl = (what?)
+ * 3 : pnmh = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void OnNotify(HWND hwndDlg, int nIdCtrl, LPNMHDR pnmh)
+{
+ switch (nIdCtrl)
+ {
+ case IDC_RULES:
+ switch (pnmh->code)
+ {
+ case LVN_ITEMCHANGED:
+ OnRulesItemChanged(hwndDlg);
+ break;
+ }
+ break;
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : OnDestroy
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndDlg = (what?)
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void OnDestroy(HWND hwndDlg)
+{
+ /* TODO any destruction cleanup */
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : DialogProc
+ *
+ * Description : (Please fill me in!)
+ *
+ * Parameters :
+ * 1 : hwndDlg = (what?)
+ * 2 : uMsg = (what?)
+ * 3 : wParam = (what?)
+ * 4 : lParam = (what?)
+ *
+ * Returns : (Please fill me in!)
+ *
+ *********************************************************************/
+static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ OnInitDialog(hwndDlg);
+ return TRUE;
+
+ case WM_DESTROY:
+ OnDestroy(hwndDlg);
+ return TRUE;
+
+ case WM_COMMAND:
+ OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam), (HWND) lParam);
+ break;
+
+ case WM_NOTIFY:
+ OnNotify(hwndDlg, (int) wParam, (LPNMHDR) lParam);
+ break;
+ }
+ return FALSE;
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _W32RULESDLG_H
+#define _W32RULESDLG_H
+#define W32RULESDLG_H_VERSION "$Id: w32rulesdlg.h,v 1.1 2001/05/13 21:57:07 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/w32rulesdlg.h,v $
+ *
+ * Purpose : A dialog to allow GUI editing of the rules.
+ * Unfinished.
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Written by and Copyright (C) 1999 Adam Lock
+ * <locka@iol.ie>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: w32rulesdlg.h,v $
+ *
+ *********************************************************************/
+\f
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int ShowRulesDialog(HWND hwndParent);
+extern void SetDefaultRule(const char *pszRule);
+
+/* Revision control strings from this header and associated .c file */
+extern const char w32rulesdlg_rcs[];
+extern const char w32rulesdlg_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _W32RULESDLG_H */
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+const char w32taskbar_rcs[] = "$Id: w32taskbar.c,v 1.1 2001/05/13 21:57:07 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/w32taskbar.c,v $
+ *
+ * Purpose : Functions for creating, setting and destroying the
+ * workspace tray icon
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Written by and Copyright (C) 1999 Adam Lock
+ * <locka@iol.ie>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: w32taskbar.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include <windows.h>
+
+#include "w32taskbar.h"
+#include "w32res.h"
+#include "w32log.h"
+
+const char w32taskbar_h_rcs[] = W32TASKBAR_H_VERSION;
+
+#define WM_TRAYMSG WM_USER+1
+
+static HMENU g_hmenuTray;
+static HWND g_hwndTrayX;
+
+static LRESULT CALLBACK TrayProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+/*********************************************************************
+ *
+ * Function : CreateTrayWindow
+ *
+ * Description : Creates and returns the invisible window responsible for processing tray messages.
+ *
+ * Parameters :
+ * 1 : hInstance = instance handle of this application
+ *
+ * Returns : Handle of the systray window.
+ *
+ *********************************************************************/
+HWND CreateTrayWindow(HINSTANCE hInstance)
+{
+ WNDCLASS wc;
+ static const char *szWndName = "JunkbusterTrayWindow";
+
+ wc.style = 0;
+ wc.lpfnWndProc = TrayProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = 0;
+ wc.hCursor = 0;
+ wc.hbrBackground = 0;
+ wc.lpszMenuName = 0;
+ wc.lpszClassName = szWndName;
+
+ RegisterClass(&wc);
+
+ g_hwndTrayX = CreateWindow(szWndName, szWndName,
+ WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, NULL, NULL, hInstance, NULL );
+
+ ShowWindow(g_hwndTrayX, SW_HIDE);
+ UpdateWindow(g_hwndTrayX);
+
+ g_hmenuTray = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_TRAYMENU));
+
+ return g_hwndTrayX;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : TraySetIcon
+ *
+ * Description : Sets the tray icon to the specified shape.
+ *
+ * Parameters :
+ * 1 : hwnd = handle of the systray window
+ * 2 : uID = user message number to notify systray window
+ * 3 : hicon = set the current icon to this handle
+ *
+ * Returns : Same value as `Shell_NotifyIcon'.
+ *
+ *********************************************************************/
+BOOL TraySetIcon(HWND hwnd, UINT uID, HICON hicon)
+{
+ NOTIFYICONDATA nid;
+
+ memset(&nid, 0, sizeof(nid));
+
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = hwnd;
+ nid.uID = uID;
+ nid.uFlags = NIF_ICON;
+ nid.uCallbackMessage = 0;
+ nid.hIcon = hicon;
+
+ return( Shell_NotifyIcon(NIM_MODIFY, &nid) );
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : TrayAddIcon
+ *
+ * Description : Adds a tray icon.
+ *
+ * Parameters :
+ * 1 : hwnd = handle of the systray window
+ * 2 : uID = user message number to notify systray window
+ * 3 : hicon = handle of icon to add to systray window
+ * 4 : pszToolTip = tool tip when mouse hovers over systray window
+ *
+ * Returns : Same as `Shell_NotifyIcon'.
+ *
+ *********************************************************************/
+BOOL TrayAddIcon(HWND hwnd, UINT uID, HICON hicon, const char *pszToolTip)
+{
+ NOTIFYICONDATA nid;
+
+ memset(&nid, 0, sizeof(nid));
+
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = hwnd;
+ nid.uID = uID;
+ nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
+ nid.uCallbackMessage = WM_TRAYMSG;
+ nid.hIcon = hicon;
+
+ if (pszToolTip)
+ {
+ strcpy(nid.szTip, pszToolTip);
+ }
+
+ return( Shell_NotifyIcon(NIM_ADD, &nid) );
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : TrayDeleteIcon
+ *
+ * Description : Deletes a tray icon.
+ *
+ * Parameters :
+ * 1 : hwnd = handle of the systray window
+ * 2 : uID = user message number to notify systray window
+ *
+ * Returns : Same as `Shell_NotifyIcon'.
+ *
+ *********************************************************************/
+BOOL TrayDeleteIcon(HWND hwnd, UINT uID)
+{
+ NOTIFYICONDATA nid;
+
+ memset(&nid, 0, sizeof(nid));
+
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = hwnd;
+ nid.uID = uID;
+
+ return( Shell_NotifyIcon(NIM_DELETE, &nid) );
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : TrayProc
+ *
+ * Description : Call back procedure processes tray messages.
+ *
+ * Parameters :
+ * 1 : hwnd = handle of the systray window
+ * 2 : msg = message number
+ * 3 : wParam = first param for this message
+ * 4 : lParam = next param for this message
+ *
+ * Returns : Appropriate M$ window message handler codes.
+ *
+ *********************************************************************/
+LRESULT CALLBACK TrayProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_CREATE:
+ return 0;
+
+ case WM_CLOSE:
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_TRAYMSG:
+ {
+ UINT uID = (UINT) wParam;
+ UINT uMouseMsg = (UINT) lParam;
+
+ if (uMouseMsg == WM_RBUTTONDOWN)
+ {
+ POINT pt;
+ HMENU hmenu = GetSubMenu(g_hmenuTray,0);
+ GetCursorPos(&pt);
+ SetForegroundWindow(g_hwndLogFrame);
+ TrackPopupMenu(hmenu, TPM_LEFTALIGN | TPM_TOPALIGN, pt.x, pt.y, 0, g_hwndLogFrame, NULL);
+ PostMessage(g_hwndLogFrame, WM_NULL, 0, 0 ) ;
+ }
+ else if (uMouseMsg == WM_LBUTTONDBLCLK)
+ {
+ ShowLogWindow(TRUE);
+ }
+ }
+ return 0;
+
+ default:
+ /* DO NOTHING */
+ break;
+ }
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+}
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _W32TASKBAR_H
+#define _W32TASKBAR_H
+#define W32TASKBAR_H_VERSION "$Id: w32taskbar.h,v 1.1 2001/05/13 21:57:07 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/w32taskbar.h,v $
+ *
+ * Purpose : Functions for creating, setting and destroying the
+ * workspace tray icon
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Written by and Copyright (C) 1999 Adam Lock
+ * <locka@iol.ie>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: w32taskbar.h,v $
+ *
+ *********************************************************************/
+\f
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern HWND CreateTrayWindow(HINSTANCE hInstance);
+extern BOOL TrayAddIcon(HWND hwnd, UINT uID, HICON hicon, const char *pszToolTip);
+extern BOOL TraySetIcon(HWND hwnd, UINT uID, HICON hicon);
+extern BOOL TrayDeleteIcon(HWND hwnd, UINT uID);
+
+/* Revision control strings from this header and associated .c file */
+extern const char w32taskbar_rcs[];
+extern const char w32taskbar_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _W32TASKBAR_H */
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+const char win32_rcs[] = "$Id: win32.c,v 1.1 2001/05/13 21:57:07 administrator Exp $";
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/win32.c,v $
+ *
+ * Purpose : Win32 User Interface initialization and message loop
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Written by and Copyright (C) 1999 Adam Lock
+ * <locka@iol.ie>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: win32.c,v $
+ *
+ *********************************************************************/
+\f
+
+#include "config.h"
+
+#ifdef _WIN32
+
+#include <stdio.h>
+
+#include "project.h"
+#include "jcc.h"
+
+/* Uncomment this if you want to build Win32 as a console app */
+/* #define _WIN_CONSOLE */
+
+#include <windows.h>
+
+#include <stdarg.h>
+#include <process.h>
+
+#include "win32.h"
+
+const char win32_h_rcs[] = WIN32_H_VERSION;
+
+const char win32_blurb[] =
+"Internet Junkbuster Proxy(TM) Version " VERSION " for Windows is Copyright (C) 1997-8\n"
+"by Junkbusters Corp. This is free software; it may be used and copied under\n"
+"the GNU General Public License: http://www.gnu.org/copyleft/gpl.html .\n"
+"This program comes with ABSOLUTELY NO WARRANTY OF ANY KIND.\n"
+"\n"
+"For information about how to to configure the proxy and your browser, see\n"
+" " REDIRECT_URL "win\n"
+"\n"
+"The Internet Junkbuster Proxy(TM) is running and ready to serve!\n"
+"";
+
+#ifdef _WIN_CONSOLE
+
+int hideConsole = 0;
+
+#else
+
+HINSTANCE g_hInstance;
+int g_nCmdShow;
+
+static void __cdecl UserInterfaceThread(void *);
+
+#endif
+
+
+/*********************************************************************
+ *
+ * Function : WinMain
+ *
+ * Description : M$ Windows "main" routine:
+ * parse the `lpCmdLine' param into main's argc and argv variables,
+ * start the user interface thread (for the systray window), and
+ * call main (i.e. patch execution into normal IJB startup).
+ *
+ * Parameters :
+ * 1 : hInstance = instance handle of this IJB execution
+ * 2 : hPrevInstance = instance handle of previous IJB execution
+ * 3 : lpCmdLine = command line string which started IJB
+ * 4 : nCmdShow = window show value (MIN, MAX, NORMAL, etc...)
+ *
+ * Returns : `main' never returns, so WinMain will also never return.
+ *
+ *********************************************************************/
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
+{
+ int argc = 0;
+ int i;
+ int res;
+ char **argv = NULL;
+ char *pszArgs = NULL;
+ char *pszLastTok;
+ char szModule[MAX_PATH+1];
+#ifndef _WIN_CONSOLE
+ HANDLE hInitCompleteEvent = NULL;
+#endif
+
+ /* Split command line into arguments */
+ pszArgs = (char *)malloc(strlen(lpCmdLine) + 1);
+ strcpy(pszArgs, lpCmdLine);
+
+ GetModuleFileName(hInstance, szModule, MAX_PATH);
+
+ /* Count number of spaces */
+ argc = 1;
+ if (strlen(pszArgs) > 0)
+ {
+ pszLastTok = pszArgs;
+ do
+ {
+ argc++;
+ pszLastTok = strchr(pszLastTok+1, ' ');
+ } while (pszLastTok);
+ }
+
+ /* Allocate array of strings */
+ argv = (char **)malloc(sizeof(char *) * argc);
+
+ /* step through command line replacing spaces with zeros, initialise array */
+ argv[0] = szModule;
+ i = 1;
+ pszLastTok = pszArgs;
+ do
+ {
+ argv[i] = pszLastTok;
+ pszLastTok = strchr(pszLastTok+1, ' ');
+ if (pszLastTok)
+ {
+ while (*pszLastTok != '\0' && *pszLastTok == ' ')
+ {
+ *pszLastTok = '\0';
+ pszLastTok++;
+ }
+ }
+ i++;
+ } while (pszLastTok && *pszLastTok != '\0');
+
+#ifndef _WIN_CONSOLE
+ /* Create a user-interface thread and wait for it to initialise */
+ hInitCompleteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ g_hInstance = hInstance;
+ g_nCmdShow = nCmdShow;
+ _beginthread(UserInterfaceThread, 0, &hInitCompleteEvent);
+ WaitForSingleObject(hInitCompleteEvent, INFINITE);
+ DeleteObject(hInitCompleteEvent);
+#endif
+
+#ifdef __MINGW32__
+ res = _main( argc, argv );
+#else
+ res = main( argc, argv );
+#endif
+
+ /* Cleanup */
+ free(argv);
+ free(pszArgs);
+
+ return res;
+
+}
+
+#endif
+
+/*********************************************************************
+ *
+ * Function : InitWin32
+ *
+ * Description : Initialise windows, setting up the console or windows as appropriate.
+ *
+ * Parameters : None
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void InitWin32(void)
+{
+ WORD wVersionRequested;
+ WSADATA wsaData;
+
+#ifdef _WIN_CONSOLE
+ SetProcessShutdownParameters(0x100, SHUTDOWN_NORETRY);
+ if (hideConsole)
+ {
+ FreeConsole();
+ }
+#endif
+ wVersionRequested = MAKEWORD(2, 0);
+ if (WSAStartup(wVersionRequested, &wsaData) != 0)
+ {
+#ifndef _WIN_CONSOLE
+ MessageBox(NULL, "Cannot initialize WinSock library", "Internet JunkBuster Error",
+ MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST);
+#endif
+ exit(1);
+ }
+
+}
+
+
+#ifndef _WIN_CONSOLE
+#include <signal.h>
+#include <assert.h>
+
+#include "win32.h"
+#include "w32log.h"
+
+
+/*********************************************************************
+ *
+ * Function : UserInterfaceThread
+ *
+ * Description : User interface thread. WinMain will wait for us to set
+ * the hInitCompleteEvent before patching over to `main'.
+ * This ensures the systray window is active before beginning
+ * IJB operations.
+ *
+ * Parameters :
+ * 1 : pData = pointer to `hInitCompleteEvent'.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void __cdecl UserInterfaceThread(void *pData)
+{
+ MSG msg;
+ HANDLE hInitCompleteEvent = *((HANDLE *) pData);
+
+ /* Initialise */
+ InitLogWindow();
+ SetEvent(hInitCompleteEvent);
+
+ /* Enter a message processing loop */
+ while (GetMessage(&msg, (HWND) NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ /* Cleanup */
+ TermLogWindow();
+
+ /* Time to die... */
+ raise(SIGINT);
+
+}
+
+
+#endif
+
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/
--- /dev/null
+#ifndef _WIN32_H
+#define _WIN32_H
+#define WIN32_H_VERSION "$Id: win32.h,v 1.1 2001/05/13 21:57:07 administrator Exp $"
+/*********************************************************************
+ *
+ * File : $Source: /home/administrator/cvs/ijb/win32.h,v $
+ *
+ * Purpose : Win32 User Interface initialization and message loop
+ *
+ * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * IJBSWA team. http://ijbswa.sourceforge.net
+ *
+ * Written by and Copyright (C) 1999 Adam Lock
+ * <locka@iol.ie>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * The GNU General Public License should be included with
+ * this file. If not, you can view it at
+ * http://www.gnu.org/copyleft/gpl.html
+ * or write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Revisions :
+ * $Log: win32.h,v $
+ *
+ *********************************************************************/
+\f
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char win32_blurb[];
+
+extern void InitWin32(void);
+
+#ifdef _WIN_CONSOLE
+extern int hideConsole;
+#endif /*def _WIN_CONSOLE */
+
+extern HINSTANCE g_hInstance;
+extern int g_nCmdShow;
+
+extern int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
+
+/* Revision control strings from this header and associated .c file */
+extern const char win32_rcs[];
+extern const char win32_h_rcs[];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ndef _WIN32_H */
+
+/*
+ Local Variables:
+ tab-width: 3
+ end:
+*/