From: oes Date: Tue, 15 May 2001 13:59:57 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: v_2_9_3 X-Git-Url: http://www.privoxy.org/gitweb/?a=commitdiff_plain;h=c75584ebcc79f939fb4ec9c8f842cef6692640c7;p=privoxy.git *** empty log message *** --- diff --git a/Junkbuster Status.URL b/Junkbuster Status.URL new file mode 100644 index 00000000..6c95de6d Binary files /dev/null and b/Junkbuster Status.URL differ diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000..8c670b88 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,281 @@ +# 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: diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 00000000..edf5c08a --- /dev/null +++ b/acconfig.h @@ -0,0 +1,178 @@ +#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 $ + * + *********************************************************************/ + +@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 */ diff --git a/aclfile b/aclfile new file mode 100644 index 00000000..6a265a89 --- /dev/null +++ b/aclfile @@ -0,0 +1,102 @@ +# 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. +# diff --git a/amiga.c b/amiga.c new file mode 100644 index 00000000..cd228986 --- /dev/null +++ b/amiga.c @@ -0,0 +1,234 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#ifdef AMIGA + +#include +#include + +#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 */ diff --git a/amiga.h b/amiga.h new file mode 100644 index 00000000..6f132d0b --- /dev/null +++ b/amiga.h @@ -0,0 +1,88 @@ +#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 $ + * + *********************************************************************/ + + +#define _KERNEL +#include +#undef _KERNEL + +#define __NOLIBBASE__ +#include +#undef __NOLIBBASE__ + +#include +#include +#include +#include + +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 */ diff --git a/blocklist b/blocklist new file mode 100644 index 00000000..7b48f3af --- /dev/null +++ b/blocklist @@ -0,0 +1,1060 @@ +# +# 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 . +# +# 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 +/*.*/mainos/*.*/.*\.gif +/*.*/mainos/*.*/.*\.jpe?g + +# more from a finnish friend Petri Haapio +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 +194.251.243.50/cgi-bin/banner + +www.dime.net/ad +www.iltalehti.fi/ad +www.iltalehti.fi/ilmkuvat +www.mtv3.fi/mainoskuvat + +# +/*.*/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 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 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 +# Banner.xxLINK.nl/ + +# Mark Lutz +/.*/*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!!! + diff --git a/config b/config new file mode 100644 index 00000000..3ba741b3 --- /dev/null +++ b/config @@ -0,0 +1,207 @@ +# 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 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" +# +# default: Kill the referrer-header from the client +# 'text' : Always send 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 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 + + diff --git a/config.h b/config.h new file mode 100644 index 00000000..4d71f86b --- /dev/null +++ b/config.h @@ -0,0 +1,195 @@ +/* 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 $ + * + *********************************************************************/ + + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to `unsigned' if 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 */ diff --git a/config.h.in b/config.h.in new file mode 100644 index 00000000..930ca660 --- /dev/null +++ b/config.h.in @@ -0,0 +1,194 @@ +/* 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 $ + * + *********************************************************************/ + + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to `unsigned' if 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 */ diff --git a/configure b/configure new file mode 100755 index 00000000..6c620ec3 --- /dev/null +++ b/configure @@ -0,0 +1,1968 @@ +#! /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 <> confdefs.h <> confdefs.h <> confdefs.h <&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 <&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 < +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 < +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 < +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 <&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 <&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 < +#include +#include +#include +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 +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 +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 < +#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 <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 < +#if STDC_HEADERS +#include +#include +#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 < +/* 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 <&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 </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 < 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 <> $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 <> $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 <> $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 <> $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 + + diff --git a/configure.in b/configure.in new file mode 100644 index 00000000..492d6edc --- /dev/null +++ b/configure.in @@ -0,0 +1,257 @@ +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) + diff --git a/cookiefile b/cookiefile new file mode 100644 index 00000000..f17f4b0c --- /dev/null +++ b/cookiefile @@ -0,0 +1,67 @@ +# +# 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 + + + + diff --git a/cygwin.h b/cygwin.h new file mode 100644 index 00000000..4568ea82 --- /dev/null +++ b/cygwin.h @@ -0,0 +1,63 @@ +#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: +*/ diff --git a/doc/USER_DOC_IS_WIDELY_OBSOLETED b/doc/USER_DOC_IS_WIDELY_OBSOLETED new file mode 100644 index 00000000..e69de29b diff --git a/doc/changes.txt b/doc/changes.txt new file mode 100644 index 00000000..6aa14820 --- /dev/null +++ b/doc/changes.txt @@ -0,0 +1,991 @@ +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 (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 (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 " 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 and #include 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 * +***************************************************************************** +(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 * +***************************************************************************** + +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 * +***************************************************************************** +(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 * +***************************************************************************** +(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 * +***************************************************************************** + +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 * +***************************************************************************** + diff --git a/doc/gpl.html b/doc/gpl.html new file mode 100644 index 00000000..7f0b6107 --- /dev/null +++ b/doc/gpl.html @@ -0,0 +1,567 @@ + + + + + + + + + + + + +The GNU General Public License + + + + + + + + + +

+ +Junkbusters +

+ +
+

The GNU General Public License +

+
+ +
+

+We did not write the GPL: the Free Software Foundation did + +

+
+ +

<Feedback>  +The GPL allows copying and changing of copyrighted documents +

+

+The Free Software Foundation +(FSF) +is a non-profit institution +that designed the GNU General Public License (GPL) to promote the +publication of free software. +The GPL is used by thousands of programmers +who want to give others the right to copy and modify +the source code of their programs. Millions of people benefit from this. +

+We use the GPL +to allow everyone to use, copy and modify the +Internet Junkbuster +as they wish. +Companies can use it for commercial purposes, +but they are not permitted to use it in products that they claim +as their property +without negotiating a separate agreement with us beforehand. +

+The GPL +can also be used +on documents written in human languages. +We give everyone permission to use everything on our web site under the GPL. +This means that you do not have to break copyright laws in order +to print a page or email a screen of the text to someone, for example. +Many sites do not permit you to do these things. +

+If you have a home page, +we recommend that you consider using the GPL to +allow others the right to copy and use all the documents you create for it. +If you just mark a page as copyright, they won't even +legally be able to print it. +If you don't state you are its copyright owner, +they could change it slightly and claim it as their own property. +By marking it with both copyright and GPL notices +you allow them to copy it but not to claim +anything derived from it as their own. +

+The GPL protects your +JUNKBUSTERS DECLARATION, +Spam Offer, +and all documents from us that you publish on your home page +or distribute to direct marketers by any other means. +By making your +DECLARATION +available to them under the GPL, you are +permitting them use to it, but never to claim it as their property, +even if they transform it. +

+The +remainder of this page is the text of the GPL. +As legal documents go it's relatively clear, +but unfortunately it's fairly long because it has to cover +a lot of details specific to computer programs +that may not be relevant to +DECLARATIONs. +The hypertext links are ours, and should not be misinterpreted +as an indication of emphasis by the FSF. +

+

--- Back to Top of Page ---

+
+

+Version 2, June 1991 + +

+
+
+Copyright 1989, 1991 +
+Free Software Foundation, Inc. +
+675 Mass Ave. +
+Cambridge, MA 02139 +
+USA +
+Everyone +is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +

<Feedback>  +Preamble +

+

+The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. +

+When we speak of free software, +we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. +

+To protect your rights, +we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. +

+For example, +if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. +

+We protect your rights with two steps: +(1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. +

+Also, +for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. +

+Finally, +any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. +

+The precise terms and conditions +for copying, distribution and +modification follow. +

+ +

<Feedback>  +GNU General Public License: Terms and Conditions for Copying, Distribution and Modification +

+

+O. +This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, +translation +is included without limitation in +the term "modification".) Each licensee is addressed as "you". +

+Activities +other than copying, distribution and modification are not covered by this License; +they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +

+Whether that is true depends on what the Program does. +

    +
  1. +You may copy +and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. +

    +You may charge a fee +for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. +

  2. +You may modify +your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: +
      +
    1. +You must cause +the modified files to carry prominent notices +stating that you changed the files and the date of any change. +
    2. +You must +cause any work that you distribute or publish, that in +whole or in part contains or is derived from the Program or any +part thereof, to be licensed as a whole at no charge to all third +parties under the terms of this License. +
    3. +If the modified program +normally reads commands interactively +when run, you must cause it, when started running for such +interactive use in the most ordinary way, to print or display an +announcement including an appropriate copyright notice and a +notice that there is no warranty (or else, saying that you provide +a warranty) and that users may redistribute the program under +these conditions, and telling the user how to view a copy of this +License. (Exception: if the Program itself is interactive but +does not normally print such an announcement, your work based on +the Program is not required to print an announcement.) +
    +

    +These requirements +apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. +

    +Thus, +it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. +

    +In addition, +mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. +

  3. +You may copy +and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: +
      +
    1. +Accompany it +with the complete corresponding machine-readable +source code, which must be distributed under the terms of Sections +1 and 2 above on a medium customarily used for software interchange; or, +
    2. +Accompany it with a written offer, +valid for at least three +years, to give any third party, for a charge no more than your +cost of physically performing source distribution, a complete +machine-readable copy of the corresponding source code, to be +distributed under the terms of Sections 1 and 2 above on a medium +customarily used for software interchange; or, +
    3. +Accompany it +with the information you received as to the offer +to distribute corresponding source code. (This alternative is +allowed only for noncommercial distribution and only if you +received the program in object code or executable form with such +an offer, in accord with Subsection b above.) +
    +

    +The source code +for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. +

    +If distribution of executable or object code is made +by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. +

  4. +You may not copy, +modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. +
  5. +You are not required +to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. +
  6. +Each time you redistribute +the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. +
  7. +If, as a consequence of a court judgment +or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. +

    +If any portion +of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. +

    +It is not the purpose +of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. +

    +This section +is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. +

  8. +If the distribution +and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. +
  9. +The Free Software Foundation +may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. +
  10. +If you wish to incorporate parts +of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. +

    +NO WARRANTY +

  11. +BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, +THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. +
  12. +IN NO EVENT UNLESS REQUIRED +BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. +
+END OF TERMS AND CONDITIONS +

+ +

<Feedback>  +Appendix: How to Apply These Terms to Your New Programs +

+

+If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. +

+To do so, +attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. +

+<one line +to give the program's name and a brief idea of what it +does.> +Copyright (C) 19yy +<name of +author> +

+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. +

+

+Also add +information on how to contact you by electronic and paper mail. +

+If the program is interactive, +make it output a short notice like this +when it starts in an interactive mode: +

+Gnomovision version 69, Copyright (C) 19yy name of author +Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +This is free software, and you are welcome to redistribute it +under certain conditions; type `show c' for details. +
+

+The hypothetical +commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. +

+You should also get your employer +(if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: +

+Yoyodyne, Inc., hereby disclaims all copyright interest in the program +`Gnomovision' (which makes passes at compilers) written by James Hacker. + +<signature +of +Ty Coon>, +1 April 1989 +
+Ty Coon, President of Vice +
+

+This General Public License +does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. +

+

--- Back to Top of Page ---

+ +Home + · + + + · Site Map + + · Legal + + · Privacy + + · Cookies + + · Banner Ads + + · Telemarketing + + · Mail + + · Spam + +
+ +
+ + +

+Copyright © 1996-8 Junkbusters +® Corporation. +Copying and distribution permitted under +the GNU +General Public License. + + +1998/10/31 +http://www.junkbusters.com/ht/en/gpl.html + +

webmaster@junkbusters.com
+
+ + diff --git a/doc/ijbfaq.html b/doc/ijbfaq.html new file mode 100644 index 00000000..ab7e7989 --- /dev/null +++ b/doc/ijbfaq.html @@ -0,0 +1,3186 @@ + + + + + + + + + + + + +Internet Junkbuster Frequently Asked Questions + + + + + + + + + +
+

Internet JUNKBUSTER Frequently Asked Questions +

+
+ +

+Download for UNIX + + · (Download for Windows 95/NT) + + · (Other OS) + + · Configuring Browsers + + · Installation + + · For Companies + + · Blocking + + · Cookies + + · Anonymity + + · Security + + · (Technical Manual) +

+

+
+

+The Top Ten Questions + +

+
+
For a list of the questions on this page (without the answers), +see our +Table of Contents. +It also contains detailed pointers into our pages +on +cookies +and on busting +junk e-mail, +junk mail +and +telemarketing calls. + +

<Feedback>  +What is the Internet Junkbuster Proxy and what does it do for me? +

+

+The +Internet Junkbuster +Proxy +TM +is +free +privacy-enhancing software that can be run on your PC or by your +ISP +or company. +It blocks requests for +URLs +(typically banner ads) +that match its +blockfile. +It also deletes unauthorized +cookies +and other +unwanted identifying +header information +that is exchanged between web servers and browsers. +These headers are not normally accessible to users +(even though they may contain information that's important to your privacy), +but with the +Internet Junkbuster +you can see almost +anything you want +and control everything you're likely to need. +You +decide what's junk. +SM +Many people +publish +their blockfiles to help others get started. +

+ +

<Feedback>  +Is there a license fee / warranty / registration form / expiration? +

+

+No, none of these. +It's completely free of charge. +Junkbusters +offers you the software to copy, use, modify and distribute +as you wish, forever, at +no charge +under the +GNU General Public License. +

+It comes with +no warranty of any kind. +

+You don't have to register, +in fact we don't even provide a way to do so: +the practice of registering software is +usually just an +excuse +to send you solicitations and +sell your name +and information about your behavior. +You are welcome to obtain and use our software as anonymously you wish. +(Your +IP +address will naturally be +disclosed +when you download it, +so if you work for a web ad company +you might want to use a service such as the +lpwa.com +when you get it. +We +never +want to be given any information that you consider private or confidential.) +

+We are often asked why we give away a product that many +would happily pay for. +The answer is that we are determined to carry out our +mission: +to free the world from junk communications. +

+ +

<Feedback>  +Does it run on Windows? On a Mac? On the AOL browser? +

+

+For the latest information on availability, see the +Distribution Information +page. +We +don't +think it will ever run on +Windows 3.1. +But you don't need to have it running on your computer +if you get your +ISP +or Systems Administrator at +work +to run it. +

+ +

<Feedback>  +How can I get my ISP to run the Internet Junkbuster? +

+

+Try their sales or support department +(depending on whether you are already a customer). +You might send them email including the following +URL: +
+   http://www.junkbusters.com/ht/en/ijbfaq.html#isps +
+You could mention that many +other +ISPs +provide it, +and that you regard it as an important part of your decision on +where to buy Internet service. +

+ +

<Feedback>  +Who chooses the options that control what is blocked? +

+

+Whoever starts the +Internet Junkbuster +chooses the options and the blockfile. +If your +ISP +runs it for you, they have to make these decision +(though +some +may give you a choice of proxies, +and a way to suggest new +URLs +to block). +If you run it on your computer, +You +decide what's junk. +SM +

+ +

<Feedback>  +How do I download and run the program on my computer? +

+

+It depends on your platform. +If you are using Windows 95 or NT, +see our separate page on +installing under Windows. +If you have a C compiler and are using almost any flavor of +UNIX ® +you +download it, compile it, start it running, +and then +configure your browser. +Several precompiled packages are also available through links in our +distribution page, +which lists all available platforms. +

+If you are using a platform for which we have no current +availability, +you are welcome to port the code. +If you do this and you would like us to consider publishing your ported version, +please +tell us. +

+ +

<Feedback>  +How can I tell which blockfile and options are being used? +

+

+Just point your browser to +http://internet.junkbuster.com/cgi-bin/show-proxy-args +or to any +URL +ending in +show-proxy-args +(even if it doesn't exist). +It needn't exist because the +Internet Junkbuster 2.0 +intercepts the request, blocks it, +and returns in its place +information about itself. +Using the +URL +above is useful for checking that your browser really is +going through an +Internet Junkbuster, +because the +junkbuster.com +server returns a warning if the request actually gets to it. +Some people set the home page of their browser to such a +URL +to be sure that it is configured to use the proxy. +

+If you wish to check the header information +your proxy is actually sending, +a visit to +http://internet.junkbuster.com/cgi-bin/show-http-headers +will give you the more relevant ones first. +You might also like to turn the proxy +off +and compare the difference. (Don't forget to turn it back on again.) +

+ +

<Feedback>  +My browser started giving me ``server not responding'' messages +

+

+Once your browser is told to use a proxy such as the +Internet Junkbuster, +it thinks of it as its server for everything, +so this message means it can't talk to the proxy. +The +Internet Junkbuster +may not be running, +or you may have specified its proxy +address +incorrectly. +Check that the details you entered are correct. +If you have +telnet +you can try connecting to the appropriate port to see if the +Internet Junkbuster +is running. +If your +ISP +is running the +Internet Junkbuster, +you may want to check with them. +If you are running it yourself under +UNIX ®, +try looking at a +ps ax +to see if it is running. +The +port +specified in its options should be the same one as your +browser has configured. +

+ +

<Feedback>  +I've got this great idea for a new feature. Who do I tell? +

+

+We'd be very interested to hear it, but please bear a few things in mind. +

+

+ +

<Feedback>  +My question isn't listed here. Who do I ask for support? +

+

+If you find using our free product +harder than you're used to for consumer software, +there are many +commercial alternatives +that you could consider. +

+The answer to detailed technical questions may be answered in +manual page, +or in the source code. +Also double-check this page for an answer: +using the ``find'' feature on your browser for likely keywords may help. +Our site also has a +search +feature. +

+Many people post requests for help and responses on +Usenet. +

+If your +ISP +is providing +the +Internet Junkbuster +for you, +and your question is about how to use it, +check their web page before asking them. +

+Even though we don't offer the kind of +support you might expect if you paid a lot of money for a software product, +you can still ask us. +But before you do, please consider whether +you could ask someone closer to you. +And please be patient if we're slow to reply: we +never charge consumers +for our services, +so we have to subsidize consumers with revenue from companies, +and our resources are limited. +

+If your company or organization +would be interested in a maintenance contract +with phone and email support, +hard copy documentation and source code and pre-compiled binaries on tape +or disk, +please +ask us +for a quote. +

+

--- Back to Top of Page ---

+
+
+

+Configuring your browser to talk to the Internet Junkbuster + +

+
+
+

<Feedback>  +What is the proxy address of the Internet Junkbuster? +

+

+If you set up +the +Internet Junkbuster +to run on the computer you browse from +(rather than your +ISP's server +or some networked computer at work), +the proxy will be on +localhost +(which is the special name used by every computer on the Internet to +refer to itself) +and +the port will be +8000 +(unless you have told the +Internet Junkbuster +to +run on a different port with the +listen-address +option). +So you when +configuring your browser's proxy settings +you typically enter the word +localhost +in the two boxes next to + +HTTP +and + +Secure, +and the number +8000 +in the two boxes labelled +to the right of those boxes. +

+If your +ISP +or company is running +the +Internet Junkbuster +for you, +they will tell you the address to use. +It will be the name of the computer it's running on +(or possibly its numeric IP address), +plus a port number. +Port 8000 is the default, so assume this number if it is not specified. +Sometimes a colon is used to glue them together, +as in +junkbuster.fictitous-pro-privacy-isp.net:8000 +but +with most browsers +you do not type the colon, +you enter the address and port number in separate boxes. +

+ +

<Feedback>  +How do I tell the browser where to find the Internet Junkbuster? +

+

+All current browsers can be told the address of a proxy to use. +You enter the same information in two fields in your browser's proxy +configuration screen (see list below): one for +HTTP, +and one for the Secure Protocol (assuming your browser supports +SSL). +If you find some information already entered for your proxy, +see the +next question. +Here are the menus you go through to get to the proxy configuration settings. +(We also recommend that you +disable Java, +which is a separate operation.) +Make notes on the changes you make so you know how to undo them! +You will need to know what you did +in case you wish to +discontinue +using the proxy. +

    +
  • +For +Netscape +2.01, 2.02 and 3.0 +[Graphic Illustration]: + +Options; + +Network Preferences; + +Proxies; + +Manual Proxy Configuration View ; +enter +proxy address details +under + +HTTP +and + +Security Proxy; +click on + +OK; +click on the next + +OK. +
    +With Netscape 2.0, +follow with + +Options, + +Save Options. +
    +With Netscape 4.X series, you first have to go through + +Edit/Preferences. +[Graphic Illustration] +Then in the frame on the left, +click on triangle pointing to the right towards the word + +Advanced; +it will switch to a triangle pointing down; +and the words + +Cache, + +Proxies +and + +Disk Space +appear. +Click on + +Proxies +and the frame on the right will +display a banner saying + +Proxies Configure proxies to access the Internet. +Click the radio button labeled + +Manual proxy configuration +then click the button labeled + +View; +enter +proxy address details +under + +HTTP +and + +Security Proxy; +click on + +OK; +click on the next + +OK. +
  • +For +Internet Explorer 3.0: + +View; + +Options; + +Connections; +tick + +Connect through proxy server +box; + +Settings; +enter +proxy address details + +HTTP +Box, with port number in the second box; +same with + +Secure; +click on + +OK. +
  • +For Internet Explorer 2.0: + +View; + +Options; + +Proxy; +enter +proxy address details +click on + +OK. +
  • +On NT for MS-IE: + +Control Panel; + +Internet; + +Advanced; + +Proxy. +
  • +For MS-IE 4.0: seems to be almost the same as for +3.0, + +View; + +Internet Options; + +Connections; +tick + +Connect through proxy server +box; + +Settings; +enter +proxy address details + +HTTP +Box, with port number in the second box; +same with + +Secure; +click on + +OK. +Note that 4.0 has + +Advanced +settings to allow +HTTP +1.1 through proxies; +these must be disabled because the proxy does not currently understand +HTTP +1.1. +Please +tell us +if you see any other differences. +
  • +For NCSA Mosaic for Windows: + +Options, + +Preferences, + +Proxy; +enter +proxy address details +under + +HTTP. +
  • +For +Opera: + +Preferences, + +Proxy servers; +check the box next to HTTP; +enter the server and port number in the box on the other side; +click on + +OK. +
  • +For +Lynx, +Mosaic/X, +Grail, +and +W3O +Arena, +you can specify the proxy via environment variables +before starting the application. +This will probably be done with something like either +
    +   setenv http_proxy http://localhost:8000/ +
    +or +
    +   http_proxy=http://junkbuster.fictitous-pro-privacy-isp.net:8000/ export http_proxy +
    +depending on your shell and where the +Internet Junkbuster +lives. +
+If your browser is not listed here, +or if you notice an error, please +tell us +the correct procedure. +

+ +

<Feedback>  +What should I do if I find another proxy is already configured? +

+

+Some +ISPs +and companies require all Web traffic to go through their proxy. +In this case you would find your proxy configuration with values already set, +possibly under +Automatic Proxy Configuration +(in the case of +Netscape +and +MS-IE 3.0 +and above). +It's probably a firewall proxy between your company and the outside world, +or a +caching proxy +if you're using an +ISP. +

+What needs to be done in this case is to +use the +forwardfile +option +to tell the +Internet Junkbuster +the address of the other proxy. +Specify a different (unused) port number +with the +listen-address +option, +and configure your browser to +use that port. +If you haven't done this kind of thing before, +it's probably best to consult your systems administrator or +ISP +about it; +check their web page first. +

+ +

<Feedback>  +What if I want to stop using the Internet Junkbuster? +

+

+Just go through the same procedure you used to start your +browser using the +Internet Junkbuster, +but remove the details you put in +(or if there was something there before, restore it). +You may need to use + +Save Options +to make this change permanent. +On Netscape 3.0 you can go through + +Options; + +Network Preferences; + +Proxies +and click on + +No Proxy +to turn it off, and later click on + +Manual Proxy Configuration +if you want to start using it again. +(No need to enter the again details under + +View +as you did the +first time; +they should remain there unchanged.) +

+This stops your browser talking to the proxy; +shutting down the proxy +is a different matter. +

+ +

<Feedback>  +Automatic dialing isn't working any more. How do I fix it? +

+

+Some browsers (such as MSIE-4) can be configured to dial your +ISP +automatically when you click on a link, +but this feature gets disabled if you specify a proxy running on your +own computer +(with address +localhost +or +127.0.0.1) +because these addresses don't require dialing. +The +Internet Junkbuster +knows nothing about dialing, so it doesn't work. +To make automatic dialing work, +make up a name such as +junkbuster.ijb +and use that name in the proxy settings +instead of +localhost, +and then add the line +127.0.0.1 junkbuster.ijb +to the file +c:\windows\hosts +(if there already is a line beginning with +127.0.0.1 +just add +junkbuster.ijb +at the end of it.) +

+This should also work Netscape Communicator 4 on +machines where IE-4 has been installed. +

+

--- Back to Top of Page ---

+
+
+

+Setting up the Internet Junkbuster on your local computer + +

+
+
The next two sections assume you wish to compile the code +with your own C compiler. +If you just want to use the +.exe +file provided for Windows, +see the +Windows Installation page. + +

<Feedback>  +How do I compile the code under Unix? +

+

+If you are running Redhat +Linux +you may prefer to use the +rpm +instead of the following procedure. +

    +
  1. +First +download the tar file +(~286k) +and +uncompress and extract the files from it with this command +
    +   uncompress -c ijb20.tar.Z | tar xf - +

    +

  2. +If your operating system is from +Sun +or +HP +examine the +Makefile +and make any changes indicated inside. +
  3. +Run +
    +
    +   make +

    +

  4. +Copy the sample configuration file +(junkbstr.ini, +previously called +sconfig.txt +and other names in earlier releases) +to some convenient place such as +/usr/local/lib/junkbuster/configfile +or whatever you choose. +The sample file has all the options commented out. +You can remove the +# +character on any that you want, but it may be better to +leave this until to later. +Run it asynchronously: +
    +
    +   junkbuster configfile & +

    +If you are running a version earlier than 2.0 you can start it with +junkbuster & +

    +

  5. +Configure your browser (described +above). +
  6. +Verify that the +Internet Junkbuster +is working (described +above). +
  7. +Decide on the options you really want, +kill +the +process +and start it again. The most popular option is +blockfile +to block ads. +A sample blockfile is provided as an illustration, +but it doesn't really stop many ads. +More comprehensive ones are available +elsewhere. +
  8. +You'll probably want to add an entry to +/etc/rc.d/rc.local +or equivalent to start it at boot time. +(Any output you specify should be redirected to a file. +And don't forget the +& +at the end to run it asynchronously or your system will seize +up after the next reboot.) +
+

+ +

<Feedback>  +How do I compile the code under Windows? +

+

+A binary is currently being supplied with the source code, +but if you prefer to compile it yourself here is the likely procedure. +Most of these steps are repeated in our checklist for +installation under Windows. +

    +
  1. +First +click here to download the zip file +called +ijb20.zip +(~208k), +then uncompress and unpack the zip archive using a tool like +WinZip. +
  2. +Now the distribution (source and sample files) +will be in a folder +called +ijb20. +Go into that folder and then edit the Makefile for +your system, +removing the comment character +(#) +in the lines related to Win32. +Then type: +
    +   nmake +
    +This should create an executable called +junkbstr.exe. +For information on issues with various compilers, see the +Distribution Information +page. +
  3. +Run the executable with the command: +
    +   junkbstr +
    +The program will produce a message +indicating that it has started and is ready to serve. +

    +(Version 2.0.1 and above uses +the file +junkbstr.ini +as the config file +if it exists and no argument was given. If you have an earlier +version or if you want it to use a different config file, +simply specify that file as the argument.) +

  4. +Configure your browser (described +above). +
  5. +Check the proxy is working (described +below). +
  6. +To have the proxy start itself automatically +when you login to Win95, +drop the ``shortcut'' to the +junkbstr +executable into the StartUp folder: +
    +   C:\Windows\Start Menu\Programs\StartUp +
    +You might want to change the shortcut's +Properties->Shortcut +to +Run: Minimized. +If you specify the +hide-console +option then the +DOS +window will vanish after it starts. +

    +WinNT users can put it into their own +StartUp folders or the Administrator +can put it into the system's global StartUp folder. +For details on how to make this a service under NT +see our +Windows page. +

+

+ +

<Feedback>  +How do I check that the proxy is working? +

+

+Pick a page from somewhere (such as your bookmarks, or just one +that your browser was pointing to) +and + +Reload +it. +If you get a message along the lines of ``server not responding, +using cached copy instead,'' see the advice +above. +If the page reloads OK, check that your browser is actually +talking to the proxy by going to +http://internet.junkbuster.com/cgi-bin/show-proxy-args +or any +URL +ending in +show-proxy-args +(as described +below, +the proxy should intercept the request.) +When you see ``Internet Junkbuster Proxy Status,'' +you'll know it's working. +

+ +

<Feedback>  +How and why would I have this proxy chained with other proxies? +

+

+You may need the +forwarding +feature to ``daisy chain'' the +Internet Junkbuster +to another proxy, perhaps an +anonymizing +proxy to +conceal +your +IP +address, +or a +caching proxy +from your +ISP, +or a +firewall +proxy between your company and the outside world. +Version 2.0 +can be even configured to forward +selectively +according to the +URL +requested: +for example, connecting directly to trusted hosts, +but going through an anonymizing or firewall proxy for all other hosts. +

+Network administrators might use it to provide +transparent access to multiple networks without +modifying browser configurations. +Most browsers also provide a way of +specifying hosts that the browser +connects to directly, bypassing the proxy. Some provide a method for +Automatic Proxy Configuration. +A well written +Internet Junkbuster +configuration can be much more flexible and powerful. +

+An +ISP's +caching proxy +would typically be called something like +cache.your-isp.net:8080 +(as described on you +ISP's +web page); +you would put this information in your +forwardfile +as described in our manual. +Your browser would be configured to +the +Internet Junkbuster +for +HTTP +and Security Proxies as before, +but you probably want to tell it to use the caching proxy +for +FTP +and other protocols. +If your +ISP +is running +the +Internet Junkbuster +for you, +they have probably already decided whether to chain with a caching proxy. +

+ +

<Feedback>  +How does the Internet Junkbuster work with SOCKS gateways? +

+

+There is support for some +gateways +in +Version 1.4 +and above. +The gateway protocol used to be specified on the command line; +it is +now specified +in the same file as +forwarding. +Note that the browser's proxy configuration must +not +specify a +SOCKS +host; +it should specify the proxy as described +above. +

+ +

<Feedback>  +How do I configure it to be just a plain old proxy? +

+

+To get the proxy to do as little as possible (which means not deleting any +sensitive headers), place in your +configuration file the following three lines (each ending in a space +then a period) to stop it changing sensitive headers: +
+   referer . +
+   from . +
+   user-agent . +
+   cookiefile mycookiefile +
+The fourth line is also needed to specify a +cookiefile +that might be called +mycookiefile +containing a single line with a +* +character, to allow all cookies through. +

+ +

<Feedback>  +How do I shut down the proxy (to restart it)? +

+

+It depends on your platform. Under Windows, use + +Ctrl-Break +in the +DOS +window or +the old three-fingered salute of + +Ctrl-Alt-Delete +and select + +End Task. +Under +UNIX ® +you'll need to +kill +the +junkbuster +process. +If you don't know the process number to give to +kill, try this: +ps ax | grep junkbuster +
+

+

--- Back to Top of Page ---

+
+
+

+Information for companies + +

+
+
+

<Feedback>  +What do advertising companies think of this kind of technology? +

+

+We've seen only a few public comments from the advertising industry on this, +other than +SEC filings. +First, the president of the Internet Advertising Bureau told +CNET +that he wasn't worried by banner blockers. +Second, after the Federal Trade Commission's +workshop +where we gave a live demonstration of our proxy before +many eminent representatives of the industry, +the +Direct Marketing Association +made the following +statement in the closing paragraphs +of their +summary comments +to the Commission. +

+Clever shareware developers have come up with products that +can obliterate cookies and advertisements for those consumers +who have these concerns. +The Internet is a market that is so democratic and flexible +that it is easy for companies and software +developers to respond to a perceived market need. +
+Their attitude seems to be that they would prefer that +people use technical solutions +to protect their privacy than have protections +imposed by legislation or government regulations. +So, do you perceive a market need? +Then here are some ways to flex your democratic muscles. +

+ +

<Feedback>  +Should we provide the Internet Junkbuster for our employees? +

+

+That depends. Try this quick three-point test. +

    +
  1. +Do you want to spend your communications budget +on bandwidth that wastes your employees' time by forcing them to wait +for a lot of annoying distractions while they're trying to +do their jobs? +
  2. +Do you want current and potential vendors +to know quantitative details about the +software and hardware platforms +that you have? +
  3. +Do you want your competitors to be able to +track +exactly which of your +employees are checking out their web sites? +
+If the answer to all three questions is yes, +then you probably don't have any need for this kind of product. +

+ +

<Feedback>  +Can our company get commercial support for the software? +

+

+Yes, +ask us +for a quote on a maintenance contract with your choice of +phone and email support, +hard copy documentation, +source code and pre-compiled binaries on tape or disk, +and email alerting of upgrades and issues. +We also offer consulting services to help set up ``stealth browsing'' +capabilities to help reduce the footprints left while doing competitive +analysis and other Web work where confidentiality is critical. +

+ +

<Feedback>  +I run an ISP. What issues should I consider before offering it? +

+

+Many +ISPs +who offer the proxy to their customers have told us that +most of their customers are +delighted with it +(although one reported that a customer complaint that without banner ads, +surfing was like reading a novel: we recommend making it optional). +Many +ISPs +like it because it reduces bandwidth requirements. +To help get you started, +here's a checklist we've developed from working with a few +ISPs. +You may think of more, +and we'd be interested if you're willing to +share them +with us. +

    +
  1. +If you get more than one request for +the +Internet Junkbuster +you may want to tell your customers on your News page that you +already +know about it and are assessing it. +
  2. +Try the software and +verify +that it performs satisfactorily. +
  3. +Determine whether your customers perceive the service as +valuable +(and therefore worth the time to set up). +We've had reports of many delighted customers. +
  4. +Assess the +level of +security +associated with the software. +If access is to be +restricted +(to just dial-in ports, for example) +how is this to be done? +
  5. +Consider +whether to expect any additional load on computing resources required, +and any change in use of bandwidth due to the blocking of large +GIFs. +
  6. +Choose the +options +you wish to provide. +
  7. +Decide whether you want +to offer a choice of configurations, such some of these four. +
      +
    1. +Banners +Blocked, +Wafer with +No-Cookie-Copyright +notice +
    2. +Cookies +not stopped +(cookiefile +with just a +* +in it), +User Agent +specified as +Lynx +
    3. +Cookies from browser +allowed, +permitting +registered services +
    4. +A proxy for +kids. +
    +If you run a +caching proxy, +decide whether the +Internet Junkbuster +will chain with it by default, +and whether to offer an alternate with no caching. +(Some +ISPs +don't, because they want to give customers an incentive to use caching +and save bandwidth.) +
  8. +Decide on a naming scheme for your +proxies. +If you're running only one +proxy on one machine, +the simplest way is to just use port 8000 on your main machine, +such as +our-isp.net. +But it would probably be safer to put an entry in your name server +and call it something like +junkbuster.our-isp.net. +If running several proxies, you could either use different ports +on the same machine, or if you have +the opportunity to distribute the load over +a few machines +you could +use different hostname aliases such as +banner.junkbuster.our-isp.net, +lynx.junkbuster.our-isp.net +and +oneway.junkbuster.our-isp.net +(corresponding to the examples in the previous point). +You may want to set up +Automatic Proxy Configuration. +
  9. +Prepare a page +explaining the +Internet Junkbuster +to your customers. +Here's are some examples from +Australia, +Germany, +Florida, +New York/New Jersey/Pennsylvania, +North Carolina, +Texas, +and +Utah. +You are welcome to copy and modify +material +from +Junkbusters +according to the +GPL. +You might want to set up a process to check this page periodically +and update it when it changes. +(A few links can probably serve as well as lot of copying however.) +A typical page would probably specify the following. +
    +
  10. +Invite a small number of technologically sophisticated +customers to beta-test the service. +
  11. +Announce general availability on your ``News'' page. +Tell us +if you would like to be included on a list of +ISPs +offering the +Internet Junkbuster. +
+

+ +

<Feedback>  +What's a Proxy Server Server and how can I make money as one? +

+

+Other organizations with web presence and some bandwidth to spare +can set up as +Proxy Server Servers + +(PS2s). +The idea here is to allow users to choose their proxy configuration, +and provide it to them on a semi-permanent basis. +Users would fill in a form specifying what options they want in +their proxy, +possibly even at a very high level, such as +``no ads'' +or ``no nudity.'' +This information is sent to a +CGI +script that +configures a proxy, starts it running, and returns its address and port number +(possibly along with configuration instructions for the browser +that the user specified.) +

+Users +could be charged +a subscription fee, +or the service could be thrown in free in the hope of +improving customer retention for some existing business +(which is what +ISPs +are doing). +It might be possible to make money by +inserting new ads in the holes left where others were blocked, +but the original owners might object. +PS2s +could differentiate themselves +by providing frequently updated and comprehensive +blocking of ads, or of offensive material based on their own grading system. +Some content providers might do it for the chance to be the +only company that the consumer permits to set cookies. +(Identification could even be done via cookies, +but this might not be popular with the kind of user who wants a proxy.) +PS2s +might sell specific or aggregate information about their +users' browsing habits, +so the agreement with users on whether they are permitted to do this +would be important to both sides. +

+If your organization +establishes a +Proxy Server Service +you would like publicized, +please +notify us. +

+

--- Back to Top of Page ---

+
+
+

+Blocking + +

+
+
+

<Feedback>  +Where can I get an example blockfile that stops most ads? +

+

+The sample blockfile we provide blocks almost nothing, +and we do not publish blockfiles that stop almost all banner ads. +But others have; you can find them by +asking Altavista. +You can add any part of the new file to your old one +(probably called +sblock.ini +if you haven't changed the default name in the latest version) +or your just replace it completely. +You +probably +don't need to restart the proxy. +

+If you develop an interesting blocklist and publish it on the Web, +you might want to include the word ``junkbuster'' in it +and use the word ``blocklist'' in the file name given in the +URL +so that others can find it with the query given in the previous sentence. +

+ +

<Feedback>  +If I see an ad I wish I hadn't, how do I stop it? +

+

+If your +ISP +is running the +Internet Junkbuster, +they should have a policy on whether they accept suggestions from +their customers on what to block. Consult their web page. +

+If you are running +the +Internet Junkbuster +yourself, you have complete control over what gets through. +Just add a pattern to cover the offending +URL +to your blockfile. +Version 1.3 and later automatically rereads the blockfile when it changes, +but if you're running an earlier version you'll +have to +stop it +and restart it. +

+To choose a pattern you'll first need to find the +URL +of the ad you want cover. +

+Some people use the +debug +1 +option to display each +URL +in a window as the request is sent to the server. +It's then usually an easy task to pick the offending +URL +from the list of recent candidates. +

+Alternatively, +you can use + +View Document Info +(or + +View Document Source +if your browser doesn't have that). +The + +Info +feature has the advantage of showing you the full +URL +including the host name, +which may not be specified in the source: +there you might see something like +SRC="/ads/click_here_or_die.gif" +indicating only the +path. +(The host name is assumed to be the same as the one the page came from.) +

+But ads often +come from a different site, in which case you +might see something like +SRC="grabem.n.trackem.com/Ad/Infinitum/SpaceID=1666" +or longer. +If the company looks like a pure ad warehouse +(as in the last case), +you may want to place just its domain name in the blockfile, +which blocks all +URLs +from that site. +

+If the ad comes from a server +that you really want some content from, +you can include enough of the path +to avoid zapping stuff you might want. +In the first example above, +/ads/ +would seem to be enough. +If you don't include the domain name, +the pattern applies to all sites, +so you don't want such patterns +to be too general: +for example +/ad +would block +/admin/salaries/ +on your company's internal site. +

+To speed the blocking of images, some +UNIX ® +users create a +shell script called +Image: +containing a line such as +echo $1 | sed s/http:..// >> $HOME/lib/blockfile +that adds its argument to the user's blockfile. +Once an offending image has been be found using + +View Document Info +it's easy to cut-and-paste the line (or part of it) into a shell window. +The same script can be linked to a file called +Frame: +to dealing with framed documents, +and +junkbuster: +to accept the output of the +debug +option. +

+When compiled without the +regular expressions +option, the +Internet Junkbuster +uses only very simple (and fast) matching methods. +The pattern +/banners +will not stop +/images/banners/huge.gif +getting through: you would have to include the pattern +/images/banners +or something that matches in full from the left. +So you can get what you want here, +the matcher understands +POSIX +regular expressions: +you can use +/*.*/banners +to block +and any +URL +containing +/banners +(even in the middle of the path). +(In Versions 1.1 through 1.4 +they were an option at compile time; +from Version 2.0 they have become the default.) +Regular expressions give you +many more features +than this, +but if you're not already familiar with them you probably won't +need to know anything beyond the +/*.*/ +idiom. +If you do, a +man egrep +is probably a good starting point). +

+Don't forget the +/ +(slash) +at the beginning of the path. +If you leave it out the line will be interpreted as a domain name, +so +ad +would block all sites from Andorra +(since +.ad +is the two-letter +country code +for that principality). +

+For a detailed technical description +of how pattern matching is done, +see the +manual. +

+ +

<Feedback>  +How come this ad is still getting through anyway? +

+

+If the ad had been displayed before you included its +URL +in the blockfile, +it will probably be held in cache for some time, +so it will be displayed without the need for any request to the server. +Using the +debug +1 +option to show each +URL +as it is fetched is a good way to see exactly what is happening. +

+If new items seem to be getting through, +check that you are +really running +the proxy with the right blockfile in the options. +Check the blockfile for +exceptions. +

+Some sites may have different ways of inserting ads, +such as via +Java. +If you have ideas on how to block new kinds +of junk not currently covered, please +tell us. +

+ +

<Feedback>  +How do I stop it blocking a URL that I actually want? +

+

+You can change the patterns so they don't cover it, +or use a simple feature in Version 1.1 and later: a line beginning with a +~ +character means that a +URL +blocked by previous patterns that matches the rest of +the line is let through. +For example, +the pattern +/ad +would block +/addasite.html +but not if followed by +~/addasite +in the blockfile. +Or suppose you want to see everything that comes from +a site you like, even if it looks like an ad: simply put +~aSiteYouLike.com +at the +end +of the blockfile. +(Order is important, because the last matching line wins.) +

+As well as unblocking +pages that were unintentionally blocked, +this feature is useful for unblocking ads from a specific source. +This might be because you are interested in those particular ones, +or if you have an explicit agreement to accept certain ads, +such as those from a free web-based email provider. +

+ +

<Feedback>  +Can I block sites I don't want my children to see? +

+

+Yes, but remember that +children who are technically sophisticated enough +to use the browsers' proxy configuration options +could of course bypass any proxy. +This kind of technology can be used as a gentle barrier to remind +or guide the child, +but nobody should expect it to replace the parent's role +in setting and enforcing standards of online behavior for their children. +

+Some +ISPs +are starting to provide specialized proxies to protect children. +There are two basic approaches: the ``black list'' and the ``white list'' +approach. +The black list approach allows the child +to go anywhere not explicitly prohibited; the white list permits visits +only to sites explicitly designated as acceptable. +

+It's very easy for +anyone to +compile a white list from a page of ``recommended +kids sites'' and to configure an +Internet Junkbuster +to allow access to those sites only. +If you compile with the +regex +option, +you can place a +* +(asterisk) as the first line of the blockfile (which blocks everything), +and then list +exceptions +after that. +Be careful to make the exception sufficiently broad: +for example, using +~www.uexpress.com/ups/comics/ch/ +as the exception for +Calvin and Hobbes +would block some of the graphic elements on the page; +you would probably want a wider exception such as +~www.uexpress.com/ups/ +to permit them. +

+Version 2.0 has an experimental feature +to permit only sites mentioned in a nominated +trusted site. +This allows organizations to build lists of sites for kids to browse, +and the software automatically restricts access to those on the list. +

+Many filtering +products +actually scan for keywords in +the text of pages they retrieve +before presenting it, +but +the +Internet Junkbuster +does not do this. +Building a perfectly reliable black list system is hard, +because it's very difficult to state +in advance +exactly +what is obscene or unsuitable. +For more info see our +links +page. +

+ +

<Feedback>  +What do I see when a page or graphic is blocked by the proxy? +

+

+You usually see a broken image icon, +but it depends on several factors beyond the proxy's control. +If asked for a +URL +matching its blockfile, the proxy returns an +HTML +page containing a message identifying itself +(currently the two words ``Internet Junkbuster'') +with a status 202 (Accepted) instead of the usual 200 (OK). +(Versions 1.X returned an error 404: Forbidden, which caused +strange behavior in some cases.) +Status 202 is described in the +HTTP +RFC +as indicating that the request has been accepted but not completed, +and that it might complete successfully in the future +(in our case, if the blockfile were changed). +

+The broken image icon is most common +because the browser is usually expecting a graphic. +But if it was expecting text, or if the page happens to be using certain +HTML +extensions +such as +layer +and your browser is a late model from Microsoft, +you may see the words ``Internet Junkbuster'' displayed as a hot link. +

+Clicking on the link takes you to an explanation of +the pattern in the blockfile that caused the block, +so that you can edit the blockfile and go back and reload if you really +want to see what was blocked. The explanatory link is generated by +the proxy and is automatically intercepted based on its ending in +ij-blocked-url; +even though the site is specified as +http://internet.junkbuster.com +no request should actually made to that site. +If one is, it means that the proxy was been removed after it +generated the link. +

+To summarize: +the identifying link to the blocking explanation +is usually turned into a broken image icon, +but it may be displayed on a page alone, +or they may may be restricted to the particular frame, layer or graphic area +specified in the page containing them. +The proxy has no way of knowing the context in which a +URL +will be used and cannot control how the blocking message will be rendered. +

+ +

<Feedback>  +Why not replace blocked banners with something invisible? +

+

+Many users have suggested to us +that blocked banners should be replaced by a something like a +1x1 transparent +GIF +to make the page would look as if there was nothing ever there. +Apart from making it harder to catch unintended blocking, +this might also displease the owners of the page, +who could argue that such a change constitutes a copyright infringement. +We think that merely failing to allow an included graphic to be accessed +would probably not be considered an infringement: +after all this is what happens when a browser +is configured not to load images automatically. +However, we are +not +lawyers, +so anyone in doubt should take appropriate advice. +

+In a context where the copyright issue is resolved +satisfactorily, +a proxy could simply return a status 301 or 302 and +specify a replacement +URL +in a +Location +and/or +URI +header. +An alternative would be to use inline code to return a +1 x 1 clear +GIF. +We do not publish sample code for this, +and we have no way of stopping +others +who have. +

+ +

<Feedback>  +Why not block banners based on the dimensions of the image? +

+

+Many users have pointed out that most banner ads come in standard sizes, +so why not block all +GIFs +of those sizes? +This would theoretically be without fetching the object +because the dimensions are usually given in the +IMG +tag, +but it would require substantial changes in the code, +and we doubt whether it would be much more effective than a good block list. +

+ +

<Feedback>  +What about non-graphic advertising within the pages I want? +

+

+The +Internet Junkbuster +deliberately +does not provide a way of automatically editing the contents of a page, +to remove textual advertising or +to repair the holes left by blocked banners. +Other packages such as +WebFilter +do. +

+For the same reason, +it has no way of stopping a new browser +window being created, because this is done through the +target +attribute in the +<a> +and +<base> +elements, +not through headers. +Nor do we plan to add a feature to +paralyze animated +GIFs. +

+ +

<Feedback>  +Does it block ads on the broadcasting ``push'' systems? How about pop-up ads? +

+

+We haven't tried it but we expect it would probably +work on image ads on push channels. +See also +adchoice. +

+Disabling +Javascript +stops some pop-up ads. +One problem is that some advertisers throw open a new +browser window to frame the ad. The ad is easily blocked, +but the empty window remains. You can kill it easily, but this is a chore. +We don't see how to stop them other than editing the +HTML +from the parent window, which we +don't +like to do. +

+The +TBTF +newsletter warned subscribers to push information that +in IE4, +LOGTARGET +allows +servers to determine the +URLs +viewed at their site even if accessed from cache or through a proxy. +If you use this browser see our instructions on +how to disable +this. +

+If you find you have experience using the proxy with push, +or have any other advice about it, please +tell us. +

+

--- Back to Top of Page ---

+
+
+

+Cookies + +

+
+
For background information on cookies see our +page describing their dangers. + +

<Feedback>  +Might some cookies still get through? How can I stop them? +

+

+Yes, you should expect the occasional cookie to make it through to your browser. +We know of at least three ways this can happen; +please +tell us +if you find any others. +One way is in secure documents, which are explained +below. +

+A +few +sites set cookies using a line such as +<META HTTP-EQUIV="Set-Cookie" CONTENT="flavor=chocolate"> +in the +HEAD +section of an +HTML +document. +Cookies can also be + +set and read +in +JavaScript. +To see if this is happening in a document, +view its source, look in the +head +for a section tagged +script language="JavaScript". +If it contains a reference to +document.cookie, +the page can manipulate your cookie file without sending any cookie headers. +The +Internet Junkbuster +does not tamper with these methods. +Fortunately they are rarely used at the moment. +If a cookie gets set, it should be stopped +by the proxy on its way back to the server when a page is requested, +but it can still be read in Javascript. +bu +

+To prevent cookies breaking through, +always +keep +cookie alerts +turned on in your browser, +and +disable +Java and Javascript. +Making the files +hard to write +may also help. +

+ +

<Feedback>  +Exactly how do cookies get created and stored anyway? +

+

+When a web site's server sends you a page it also sends +certain ``header information'' which your browser records but does not display. +One of these is a +Set-Cookie +header, which specifies the cookie information that the server wants your browser to record. +Similarly, when your browser requests a page it also sends headers, specifying +information such as the graphics formats it understands. +If a cookie has previously been set by a site that matches the +URL +it is about to request, +your browser adds a +Cookie +header quoting the previous information. +

+For more background information on how cookies +can damage your privacy, see our +page on cookies. +For highly detailed technical information see the +RFC. +The +Internet Junkbuster +will show you all headers you use the +debug +8 +option, +or you can get a sample from our +demonstration page. +

+ +

<Feedback>  +If cookies can't get through, will some things stop working for me? +

+

+Possibly. +Some personalized services including certain + +chat +rooms +require cookies. +Newspapers that require + +registration +or + +subscription +will not automatically recognize you if you don't send them the cookie they +assigned you. And there are a very small number of sites that do +strange things with cookies; they don't work for anyone that blocks +cookies by any means. +Some sites such as +Microsoft +explain that their content is so wonderfully compelling that +they will withhold it from you unless you submit to their +inserting cookies. +

+If you want such sites to be given your cookies, +you can use the +cookiefile +option provided you are running +Version 1.2 or later +yourself. +Simply include the domain name of those sites in the +cookiefile +specified by this option. +If it still doesn't work, +the problem may be in +other headers. +

+It's possible to let cookies out but not in, +which is enough to keep some sites happy, but not all of them: +one newspaper site seems to go into an endless frenzy +if deprived of fresh cookies. +A cookiefile containing +a single line consisting of the two characters +>* +(greater-than and star) permits server-bound cookies only. +The +* +is a +wildcard +that matches all domains. +

+If someone else is running the +Internet Junkbuster +for you and has a version +that + +passes server-bound cookies through, +you can try editing your browser's cookie +file to contain just the ones you want, +and restart your browser. +To subscribe to a new service like this +after you have started using the +Internet Junkbuster, +you can try the following: +tell your browser to +stop using +the +Internet Junkbuster, +fill out and submit your subscription details +(allowing that web site to set a cookie), +then +reconfigure your browser to use the +Internet Junkbuster +again +(and stop more cookies being sent). +This also requires the +cookiefile +option, +and its success depends on the Web site +not wanting to change your cookies at every session. +For this reason it does not work at some major newspaper sites, for example. +But you may prefer to +look at whether other sites provide the same +or better services without demanding the opportunity +to track your behavior. +The web is a buyer's market where most prices are zero: +very few people pay +for content with money, so why should you pay with your privacy? +

+ +

<Feedback>  +Can I control cookies on a per-site basis? +

+

+Yes, since version 1.2 the +Internet Junkbuster +has included advanced cookie management facilities. +Unless you specify otherwise, +cookies are discarded (``crumbled'') by the +Internet Junkbuster +whether they came from the server or the browser. +In Version 1.2 and later you can +use the +cookiefile +option +to specify when cookies are to be passed through intact. +It uses the same syntax and +matching +algorithm as the blockfile. +

+If the +URL +matches a pattern in the +cookiefile +then cookies are let through in both the browser's request for the +URL +and in the server's response. +One-way permissions can be +specified by starting the line with the +> +or +< +character. +For example, a cookiefile consisting of the four lines +
+   org +
+   >send-user-cookies.org +
+   <accept-server-cookies.org +
+   ~block-all-cookies.org +
+allows cookies to and from +.org +domains only, with the following exceptions: +

    +
  1. +Cookies sent from servers in the domain +send-user-cookies.org +are blocked on their way to the client, +but cookies sent by the browser to that domain are still be fed to them. +
  2. +The cookies of +accept-server-cookies.org +check in to the proxy and are passed through to the browser, +but when they come back to the proxy they never check out. +
  3. +All cookies to and from +block-all-cookies.org +are blocked. +
+

+If +the +junkbuster +was compiled with the regular expressions option +they may be used in paths. +Any logging to a +``cookie jar'' +is separate and not affected. +

+It's important to give hosts you want to be able +to set cookies sufficient breadth. For example, +instead of +www.yahoo.com +use +yahoo.com +because the company uses many different hosts ending in that domain. +

+ +

<Feedback>  +Can I make up my own fake cookies (wafers) to feed to servers? +

+

+Yes, +using the +wafer +option. +We coined the term +wafer +to describe cookies chosen by a user, +not the Web server. +Servers may not find wafers as tasty as the cookies +they make themselves. +But users may enjoy controlling servers' diets for various reasons, +such as the following. +

    +
  • +Users who consider cookies to +be an unwelcome intrusion and a waste +of their disk space can respond in kind. +By writing ``signature wafers'' they can +express their feelings about cookies, +in a place that the people +in charge of them are most likely to notice. +
  • +Sites running a proxy +that logs cookies to a file +(such as the +Internet Junkbuster +does with the +jarfile +option on) +may want to notify +servers that their cookies are being intercepted, +deleted or copied. +One possible reason for doing this is the uncertain copyright status +of cookie strings. +Nothing +here should be taken as legal advice: we are simply raising a question +for any interested parties to consider, +and make no representation that such measures are necessary or sufficient. +Concerned proxy sites might decide to send a wafer +(named ``NOTICE'' for example) +containing text along the lines of the following. +
    +

    +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. +
    +

    +Any company that tries to argue in court that the proxy site +was breaching their copyright in the cookies would +be met with the defense that the proxy site gave that company +the opportunity to protect its copyright by simply +not sending cookies after receiving the notice. +

    +Cookies can be as long as four thousand characters, +so there's plenty of space for lawyerly verbosity, +but white space, commas, and semi-colons are +prohibited. +Spaces can be turned into underscores. +Alternatively, +a +URL +could be sent as the cookie value, +pointing to a document containing a notice, +perhaps with a suggestive value such as +
    +http://www.junkbusters.com/ht/en/ijbfaq.html#licenses_on_cookies_refused +
    +But including the notice directly would probably be preferable +because the addressee does not have to look it up. +

    +The +Internet Junkbuster 2.0 +currently sends a full notice as a +``vanilla wafer'' +if cookies are being logged to a cookie jar +and no other wafers have been specified. +It can be suppressed with the +suppress-vanilla-wafer +option, +which might be used in situations where there is an established understanding +between the proxy and all who serve it. +

+

+Junkbusters provides a +CGI +script that lets you +see +your wafers as they appear to servers. +

+Wafers confuse a few fragile servers. +If this troubles you, don't use this option. +

+Any wafers specified are sent to +all sites regardless of the cookiefile. +They are appended after any genuine cookies, +to maintain compliance with +RFC 2109 +in the event that a path was specified for a cookie. +The +RFC's provisions regarding the +$ +character +(such as the +Version +attribute) +are transparent +to the proxy; it simply quotes what was recited by the browser. +

+If you want to send wafers only to specific sites, +you could try putting them your browser's cookie file in a format +conforming to the Netscape +specification, +and then specify in the proxy's cookiefile that cookies are to be +sent to +but not accepted from those sites, so they can't overwrite the file. +This may work with Netscape but not all other browsers. +

+ +

<Feedback>  +Why would anyone want to save their cookies in a ``cookie jar?'' +

+

+We provided this capability just in case anyone wants it. +There are a few possible reasons. +

    +
  • +It's conceivable that +marketing companies might one day +buy +history files and cookie jars from consumers +in the same way that they currently pay them to fill out survey forms. +With this information they could +gather psychographic information, +see which competitors' sites the consumer has visited, +and discover what advertising is being targeted at them. +
  • +Some consumers might +employ semi-automated means of sorting through +their cookie jars, selecting which ones to place in their cookies +file for use by their browsers. +Their decisions could be based on payments offered, +privacy rating systems such as +TRUSTe +proposes, +or their own opinion of the company. +It could be done manually or with software. +
  • +Users may even start ``sharing'' cookies among themselves, +sending back cookies that servers generated for other visitors. +Servers that aren't expecting this possibility +will be misled about their visitors' identities. +Cookies could be shared among users on a single machine, +or across continents via +FTP +and anonymous remailers. +Privacy activists may promote +cookie disinformation campaigns +as a way to defend the public against abuse. +If a significant percentage of people send disinformative cookies, +user tracking via cookies may become less reliable and less used. +
+

+

--- Back to Top of Page ---

+
+
+

+Anonymity + +

+
+
For details +on how your identity can be revealed while you surf, +see our page on +privacy. +Once you start using +the +Internet Junkbuster +you should find that much of the information +previously indicated on that page will no longer be provided. +If the +REMOTE HOST +indicating your IP address is too close for comfort, +see our suggestions +below +on how to +conceal +your IP address. +We also recommend that you +disable JavaScript +and +Java. + +

<Feedback>  +If I use the Internet Junkbuster, will my anonymity be guaranteed? +

+

+No. Your chances of remaining anonymous are improved, +but unless you are an expert on Internet security +it would be safest to assume that everything you do on the Web +can be attributed to you personally. +

+The +Internet Junkbuster +removes various information about you, +but it's still possible that web sites can find out who you are. +Here's one way this can happen. +

+A few browsers +disclose the user's email address +in certain situations, such as when transferring a file by +FTP. +The +Internet Junkbuster 2.0 +does not filter the +FTP +stream. +If you need this feature, or are concerned about the mail handler +of your browser disclosing your email address, +you might consider +products such as +NSClean. +

+Browsers downloaded as binaries +could use non-standard headers to give out any information +they can have access to: see the manufacturer's license agreement. +It's impossible to anticipate and prevent every breach of privacy that +might occur. +The professionally paranoid prefer browsers available as source code, +because anticipating their behavior is easier. +

+ +

<Feedback>  +Why should I trust my ISP or Junkbusters with my browsing data? +

+

+You shouldn't have to trust us, and you certainly don't have to. +We do not run the proxy as a service, +where we could observe your online behavior. +We provide source code so that everyone can see that the proxy isn't +doing anything sneaky. +

+You are already trusting your +ISP +not to look at an awful lot of information on what you do. +They probably post a +privacy policy +on their site to reassure you. +If they run a proxy for you, using it could actually +make it slightly easier for them to monitor you, +but we doubt that any sane +ISP +would try this, +because if it were discovered customers would desert them. +

+ +

<Feedback>  +What private information from server-bound headers is removed? +

+

+The +Internet Junkbuster +pounces on the following +HTTP +headers in requests to servers, +unless instructed otherwise in the options. +

    +
  • +The +FROM +header, +which a few browsers use to tell your email address to servers, +is dropped +unless the +from +option is set. +
  • +The +USER_AGENT +header +is changed to indicate that the browser is +currently Mozilla (Netscape) 3.01 Gold +with an unremarkable Macintosh configuration. +Misidentification helps resist certain +attacks. +If your browser and hardware happen to be accurately identified, +you might want to change the default. +(Earlier versions of the +Internet Junkbuster +indicated different details; +by altering them periodically we aim to hinder anyone trying to +infer +whether our proxy is present.) +If you don't like the idea +of incorrectly identifying your computer as a Mac, +set it accordingly. + +
  • +The +REFERER +header +(which indicates where the +URL +currently being requested was found) +is dropped. +A single static referer to replace all +real referers may be specified using the +referer +option. +Where no referer is provided by the browser, none is added; +the +add-header +option with arguments such as +-x 'Referer: http://me.me.me' +can be used to send a bogus referer with every request. +
+In +Version 1.4 +and later you can use the +-r @ +option to selectively disclose +REFERER +and +USER_AGENT +to only those sites you nominate. +

+Some browsers +send Referer and User-Agent information under different non-standard headers. +The +Internet Junkbuster 2.0 +stops +UA +headers, +but others may get through. +This information is also available via JavaScript, +so +disable disable +it. +Some search engines +encode the query you typed +in the +URL +that goes to advertisers to target a banner ad at you, +so you will need to block the ad as well as the referer header, +unless you want them (and anyone they might +buy data +from) +to know +everything you ever search for. +

+If you have JavaScript enabled (the default on +most browsers) servers can use it to obtain Referer and User Agent, +as well as your plug-ins. +We recommend +disabling +JavaScript and Java. +

+Currently no +HTTP +response headers (browser bound) +are removed, +not even the +Forwarded: +or +X-Forwarded-For: +headers. +Nor are any added, +unless requested. +We are considering a more flexible header management system for +a future version. +

+ +

<Feedback>  +Might some things break because header information is changed? +

+

+Possibly. If used with a browser less advanced than Netscape 3.0 or IE-3, +indicating an advanced browser +may encourage pages containing extensions that confuse your browser. +If this becomes a problem +upgrade your browser or +use the +user-agent +option to indicate an +older browser. +In +Version 1.4 +and later you can selectively reveal your real browser +to only those sites you nominate. +

+Because different browsers +use different encodings of Russian characters, +certain web servers convert pages on-the-fly according to the User Agent +header. Giving a User Agent with the wrong operating system or +browser manufacturer causes some Russian sites to be garbled; +Russian surfers should +change it +to something closer. +

+Some +page access counters +work by looking at the referer; +they may fail or break when deprived. +

+Some sites depend on getting a referer header, +such as +uclick.com, +which serves comic strips +for many newspaper sites, +including +Doonsbury +for the +Washington Post. +(If you click on that last link, you can then get to a page containing +the strip via the +same +URL +we've linked to under +Doonsbury, +but if you click on the +Doonsbury +link directly, it gives you an error message suggesting that you +use a browser that supports referers.) +In +Version 1.4 +and later you can use the +-r @ +option +and place a line like +>uclick.com +in your cookiefile. +Wired News +used to use referer to decide whether to add a navigation column to +the page, but they have changed that. +

+The weather maps of +Intellicast +have been blocked by their server when no referer or cookie is provided. +You can use the same countermeasure with a line such as +>208.194.150.32 +(or simply get your weather information +elsewhere). +

+Some software vendors, including +Intuit +use +USER_AGENT +to decide which versions of their products to display to you. +With the +default +you get Mac versions. +

+As a last resort if a site you need doesn't seem to be working, +the +proxy configuration +of many browsers allow you to specify + +No Proxy For +any hostname you want. +

+We had reports that on some versions of Netscape the +What's New +feature did not work with the proxy, +but we think we fixed this in Version 2.0.1. +

+ +

<Feedback>  +How is misidentifying my browser good for security and privacy? +

+

+Almost +every +major release of both leading browsers has contained +bugs that allow malicious servers to compromise your privacy and security. +Known bugs are quickly fixed, but millions of copies of the affected +software remain out there, and yours is probably one of them. +The +header +that normally identifies your browser tells such servers exactly which attacks +to use against you. +By misidentifying your browser you reduce the likelihood that they +will be able to mount a successful attack. +

+ +

<Feedback>  +Does the Internet Junkbuster conceal my IP address? +

+

+Web sites get the IP address of any proxy or browser they serve pages to. +If you run the proxy on your own computer the IP address disclosed +is the same as your browser would, unless you use the +forwardfile +option is used to chain to another proxy, +in which case servers only get the last IP address in the chain. +Chaining slightly slows browsing of course, but it improves anonymity. +

+One public proxy that you can +forward to is +lpwa.com +port 8000. +Read about its privacy-enhancing +features and the authentication procedures first, +and note that it blocks +referer +in almost all cases, +as well as some +other headers. +

+ +

<Feedback>  +How can I set the proxy to remember my LPWA password? +

+

+After you log in to +LPWA +it tells your browser to send a +Proxy-authorization +header with each request. +Whenever you shut down the browser and start again with a new browser, +you need to log in again. +If you are the only person using the +Internet Junkbuster +proxy, you can avoid repeated logins to +LPWA +by telling the +Internet Junkbuster +to send the information by placing a line such as +
+   add-header Proxy-authorization: Basic ZHVtbXk=. +
+in the configuration file. +The exact example above +does not work +because the code +ZHVtbXk=. +is a bogus one that +LPWA +would never generate; +follow the procedure below to generate a valid one. +

    +
  1. +Restart your +Internet Junkbuster +with +debug 8 +so you can see the +headers. +
  2. +Log in to +LPWA +and go to any other site. +
  3. +Find the +Proxy-authorization +header from the debug output and paste it +after the word +add-header +into the config file. +Also change the debug value back again. +
  4. +Shut down your browser, start it up again, and +restart the proxy. Test that it works. +
+This trick is convenient for sole users, but is not suitable when +more than one person uses the proxy, because they will all get the +same +LPWA +identity. +

+ +

<Feedback>  +Does the Internet Junkbuster thwart identification by identd? +

+

+We think so, +provided you are not the user running the +proxy. +If your computer (or your +ISP's) +is running the +identd +demon, +servers can ask it for the identity of the +user making the request at time you request a page from them. +But if you're going through a proxy, +they will identify the user name associated with the proxy, not you. +A visit to +http://ident.junkbusters.com +lets you see what's happening. +This test is (quite rightly) blocked by many +firewalls; +just interrupt the transfer if you get an abnormal wait after clicking. +Running other applications +may also expose you via +identd; +the proxy of course doesn't help then. +

+ +

<Feedback>  +Can web sites tell that I'm using the Internet Junkbuster? +

+

+With the default options the proxy doesn't announce itself. +Obvious indications such as +Keep-Alive +headers are +deleted, +but sites might notice that you can cancel cookies faster than +any human could possibly click on a mouse. +(If you want to provide a +plausible explanation for this, +change the User Agent header to a +cookie-free +or +cookie-crunching +browser). +

+But when certain options +are used they could figure out something's going on, +even if they're not pushing cookies. +If you use blocking +they can tell from their logs that the graphics in their pages +are not being requested selectively. +The +add-forwarded-header +option explicitly announces to the server that a proxy is present, +and +sending them +wafers +is of course a dead giveaway. +

+

--- Back to Top of Page ---

+
+
+

+Security + +

+
+
+

<Feedback>  +What happens with Secure Documents (SSL, https:)? +

+

+If you enter a +``Secure Document Area,'' +cookies and other header information +such as User Agent and Referer +are sent encrypted, +so they cannot be filtered. +We recommend getting your browser to alert you when this happens. +(On Netscape: + +Options; + +Security; + +General; + +Show an alert before entering a secure document space.) +We also recommend adding the line +:443 +to the blockfile to stop all but sites specified in an exception +after that line from using SSL. +

+It may be possible to filter encrypted cookies +by combining the blocking proxy with a cryptographic proxy along +the lines of +SafePassage, +but we have not tried this. +

+ +

<Feedback>  +Will using this as my Security Proxy compromise security? +

+

+We're not security experts, but we don't think so. +The whole point of +SSL +is that the +contents of messages are + +encrypted +by the time +they leave the browser and the server. +Eavesdroppers (including proxies) can see where your messages are going +whether you are running a proxy or not, +but they only get to see the contents after they have been encrypted. +

+ +

<Feedback>  +Can I restrict use of the proxy to a set of nominated IP addresses? +

+

+Yes, we added an +access control +file in Version 2.0. +But before you use it please consider why you want to do it. +If the reason is security, +it probably means you need a firewall. +

+The +listen-address +option provides a way of binding the proxy to a single IP address/port. +The right way to do this is to choose a port inside your firewall, and +deny access to it to those outside the firewall. +The +Internet Junkbuster +is not a firewall proxy; +it should not be expected to solve security problems. +

+For background information on firewalls, +see +Yahoo +or a +magazine article +or these well-known books: +Firewalls and Internet Security: Repelling the Wily Hacker +by +William R. Cheswick +and +Steven M. Bellovin +or +Building Internet Firewalls +by +D. Brent Chapman +and +Elizabeth D. Zwicky. +There's + +free Linux software +available, +and a large number of +commercial +products and services. +For an excellent security overview, primer, and compendium reference, see +Practical Unix and Internet Security +by +Simson Garfinkel +and +Gene Spafford. +

+ +

<Feedback>  +Are there any security risks for ISPs or others who offer the proxy? +

+

+Yes. +As with any service offered over the Internet, +hackers can try to misuse it. +A well-run +ISP +will have professionals who are experienced at assessing and containing +these risks. +

+It's possible to set up your machine so +that other people can have access to your proxy, +but if you lack expertise in computer security +you probably shouldn't have your computer configured to offer +this or any other service to the outside world. +

+Hackers can attempt to gain access +to the machine by various attacks, +which we have tried to guard against but don't guarantee to thwart. +They can also use the ``anonymizing'' quality of proxies +to try to cover their tracks while hacking other computers. +For this reason we recommend preventing it being used +as an anonymous +telnet +by putting the pattern +:23 +in the blockfile (it's included as standard equipment). +(Actually the current implementation incidentally blocks telnet due to the +way headers are handled, but it's best not to rely on this.) +If you wish to block all ports except the default +HTTP +port 80, +you can put the lines +
+   : +
+   ~:80 +
+at the beginning of the blockfile, but be aware that some servers +run on non-default ports (e.g. 8080). You might also want to add the line +~:443 +to allow +SSL. +

+On +UNIX ® +systems it is neither necessary nor desirable for the proxy to run as root. +

+Versions 2.0.1 and below may be vulnerable to remote +exploitation of a memory buffer bug; for security reasons all users +are encouraged to +upgrade. +

+If you find any security holes in the code +please +tell us, +along with any suggestions you may have for fixing it. +However, we do not claim that we will be able to do so. +

+We distribute this code in the hope that people +will find it useful, but we provide +no warranty +for it, +and we are not responsible for anyone's use or misuse of it. +

+You may also want to check back periodically for updated versions of the code. +We do not +maintain a mailing list. +To get quick updates, bookmark our +Distribution Information +page. +

+

--- Back to Top of Page ---

+ +Home + · + + + · Site Map + + · Legal + + · Privacy + + · Cookies + + · Banner Ads + + · Telemarketing + + · Mail + + · Spam + +
+ +
+ + +

+Copyright © 1996-8 Junkbusters +® Corporation. +Copying and distribution permitted under +the GNU +General Public License. + + +1998/10/31 +http://www.junkbusters.com/ht/en/ijbfaq.html + +

webmaster@junkbusters.com
+
+ + diff --git a/doc/ijbman.html b/doc/ijbman.html new file mode 100644 index 00000000..710cddb0 --- /dev/null +++ b/doc/ijbman.html @@ -0,0 +1,920 @@ + + + + + + + + + + + + +Internet Junkbuster Technical Information + + + + + + + + + +
+

Internet JUNKBUSTER Technical Information +

+
+ +

+Options + + · Checking Options + + · Installation + + · Copyright + + · (FAQ) +

+

+
+

+Manual Page + +

+
+
A copy of this page +in standard +man +macro format +is included in the +tar archive. + +

<Feedback>  +Name +

+

+junkbuster +- The +Internet Junkbuster +Proxy +TM +

+ +

<Feedback>  +Synopsis +

+

+junkbuster +configfile +(Version 2.0 onwards) +
+junkbstr.exe +configfile +(Windows) +
+junkbuster +[-a] +[-y] +[-s] +[-c] +[-v] +
+[-u user_agent] +[-r referer] +[-t from] +
+[-b blockfile] +[-j jarfile] +[-l logfile] +
+[-w NAME=VALUE] +[-x Header_text] +
+[-h [bind_host_address][:bind_port]] +
+[-f forward_host[:port]] +[-d N] +
+[-g gw_protocol[:[gw_host][:gw_port]]] +
+(Version 1.4 and earlier) +

+ +

<Feedback>  +Description +

+

+junkbuster +is an instrumentable proxy that filters the +HTTP +stream between +web servers and browsers. +Its main purpose is to enhance privacy. +

+Versions before 2.0 used command-line options; +Versions from 2.0 onward use a configuration file. +The following descriptions of the options first give the older +command-line usage, then the new configfile line. +

+In Versions 2.0.1 upwards on Windows, +a start-up message is printed and the configuration is read from the file +junkbstr.ini +if it exists and no argument was given. +

+All files except the configfile +are checked for changes before each page is fetched, +so they may edited without restarting the proxy. +

Options +

+

-b blockfile
blockfile  blockfile
+Block +requests to +URLs +matching any pattern given in the lines of the +blockfile. +The +junkbuster +instead returns status 202, indicating that the request has been accepted +(though not completed), +and a +message identifying itself +(though the browser may +display only a broken image icon). +(Versions before 2.0 returned an error 403 (Forbidden).) +The syntax of a pattern is +[domain][:port][/path] +(the +http:// +or +https:// +protocol part is omitted). +To decide if a pattern matches a target, the domains are compared first, +then the paths. +

+To compare the domains, +the pattern domain and the target +domain specified in the +URL +are each broken into their components. +(Components are separated by the +. +(period) character.) +Next each of the target components +is compared with the corresponding pattern component: last with last, +next-to-last with next-to-last, and so on. +(This is called +right-anchored +matching.) +If all of the pattern components find their match in the target, +then the domains are considered a match. +Case is irrelevant when comparing domain components. +

+A successfully +matching pattern can be an anchored substring of a target, but +not vice versa. +Thus if a pattern doesn't specify a domain, +it matches all domains. +Furthermore, when comparing two components, +the components must either match in their entirety or up to a wildcard +* +(star character) in the pattern. The wildcard feature +implements only a "prefix" match capability ("abc*" vs. "abcdefg"), +not suffix matching ("*efg" vs. "abcdefg") or +infix matching ("abc*efg" vs. "abcdefg"). +The feature is restricted to the domain component; +it is unrelated to the optional +regular expression +feature in the path +(described below). +

+If a numeric port +is specified in the pattern domain, then the target port must +match as well. The default port in a target is port 80. +

+If the domain and port match, +then the target +URL +path is checked for +a match against the path in the pattern. +Paths are compared with a simple case-sensitive +left-anchored substring comparison. +Once again, the pattern can be an +anchored substring of the target, but not vice versa. +A path of +/ +(slash) would match all paths. Wildcards are not considered in +path comparisons. +

+For example, the target +URL +
+   the.yellow-brick-road.com/TinMan/has_no_brain +
+would be matched (and blocked) by the following patterns +
+   yellow-brick-road.com +
+and +
+   Yellow*.COM +
+and +
+   /TinM +
+but not +
+   follow.the.yellow-brick-road.com +
+or +
+   /tinman +
+

+Comments in a blockfile start with a +# +(hash) character and end at a new line. +Blank lines are also ignored. +

+Lines beginning with a +~ +(tilde) character are taken to be +exceptions: +a +URL +blocked by previous patterns that matches the rest of +the line is let through. (The last match wins.) +

+Patterns +may contain +POSIX +regular expressions +provided the +junkbuster +was compiled with this option +(the default in Version 2.0 on). +The idiom +/*.*/ad +can then be used +to match any +URL +containing +/ad +(such as +http://nomatterwhere.com/images/advert/g3487.gif +for example). +These expressions +don't work +in the domain part. +

+In version 1.3 and later +the blockfile and cookiefile are checked for changes before each request. +

-w NAME=VALUE
wafer  NAME=VALUE
+Specifies a pair to be sent as a cookie with every request +to the server. +(Such boring cookies are called +wafers.) +This option may be called more than once to generate multiple wafers. +The original +Netscape specification +prohibited +semi-colons, commas and white space; +these characters will be +URL-encoded +if used in wafers. + + +The Path and Domain attributes are not currently supported. +

-c cookiefile
cookiefile  cookiefile
+Enforce the cookie management policy specified in the +cookiefile. +If this option is not used all cookies are silently crunched, +so that users who never want cookies aren't bothered by browsers +asking whether each cookie should be accepted. +However, cookies can +still get through +via +JavaScript +and +SSL, +so alerts should be left on. +

+In Version 1.2 and later +this option must be followed by a +filename +containing instructions on which sites are allowed to +receive and set cookies. +By default cookies are dropped in both the browser's request +and the server's response, unless the +URL +requested matches an entry in the +cookiefile. +The matching algorithm is the same as for the blockfile. +A leading +> +character allows +server-bound +cookies only; +a +< +allows only browser-bound cookies; +a +~ +character stops cookies in +both directions. +Thus a cookiefile containing a single line with the two characters +>* +will pass on all cookies to servers but not give any new ones to the browser. +

-j jarfile
jarfile  jarfile
+All Set-cookie attempts by the server are +logged +to +jarfile. +If no wafer is specified, +one containing a +canned notice +(the +vanilla wafer) +is added as an alert to the server +unless the +suppress-vanilla-wafer + +option is invoked. +

-v
suppress-vanilla-wafer
+Suppress the vanilla wafer. +

-t from
from  from
+If the browser +discloses an email address +in the +FROM +header (most don't), +replace it with +from. +If +from +is set to +. +(the period character) +the +FROM +is passed to the server unchanged. +The default is to delete the +FROM +header. +

-r referer
referer  referer
+Whenever the browser discloses the +URL +that +led to +the current request, +replace it with +referer. +If +referer +is set to +. +(period) +the +URL +is passed to the server unchanged. +In +Version 1.4 +and later, if referer is set to +@ +(at) the +URL +is sent in cases where the cookiefile +specifies that a cookie would be sent. +(No way to send bogus referers selectively is provided.) +The default is to delete Referer. +

+Version 2.0 also accepts the spelling +referrer, +which most dictionaries consider correct. +

-u user-agent
user-agent  user-agent
+Information disclosed by the browser +about itself +is replaced with the value +user-agent. +If +user-agent +is set to +. +(period) +the +User-Agent +header is passed to the server unchanged, +along with any +UA +headers produced by +MS-IE +(which would otherwise be deleted). +In +Version 1.4 +and later, if +user-agent +is set to +@ +(at) these headers are sent unchanged in cases where the cookiefile +specifies that a cookie would be sent, +otherwise only default +User-Agent +header is sent. +That default +is Mozilla/3.0 (Netscape) +with an unremarkable +Macintosh +configuration. +If used with a browser less advanced than Mozilla/3.0 or IE-3, the default +may encourage pages containing extensions that confuse the browser. + +

-h [host][:port]
listen-address  [host][:port]
+If +host +is specified, +bind the +junkbuster +to that +IP +address. +If a +port +is specified, use it. +The default +port +is 8000; +the default host is +localhost. +Before Version 2.0.2, +the default was to bind to all +IP +addresses +(INADDR_ANY); +but this has been restricted to +localhost +to avoid unintended security breaches. +(To open the proxy to all, use the line +
+   listen-address :8000 +
+in the configuration file.) +

-f forward_host[:port]
forwardfile  forwardfile
+Version 1.X required all +HTTP +requests from the client to be forwarded to the same destination. +Version 2.0 takes its routing specification from a +forwardfile, +allowing selection of the proxy (a.k.a. forwarding host) and gateway +according to the +URL. +Here is a typical line. +
+
+*         lpwa.com:8000      .      .
+
+

+Each line contains four fields: +target, +forward_to, +via_gateway_type +and +gateway. +As usual, the +last +target +domain that matches the requested +URL +wins, +and the +* +character alone matches any domain. +The target domain need not be a fully qualified +hostname; it can be a general domain such as +com +or +co.uk +or even just a port number. +For example, because +LPWA +does not handle +SSL, +the line above will typically be followed by a line such as +
+

+:443  .      .      .
+
+to allow SSL transactions to proceed directly. +The cautious would also +add an entry in their blockfile to stop transactions +to port 443 for all but specified trusted sites. +

+If the winning +forward_to +field is +. +(the dot character) the proxy connects +directly to the server given in the +URL, +otherwise it forwards to the host and port number specified. +The default port is 8000. +The +via_gateway_type +and +gateway +fields also use a dot to indicate no gateway protocol. +The gateway protocols are explained +below. +

+The example line above in a forwardfile alone +would send everything through port 8000 at +lpwa.com +with no gateway protocol, +and is equivalent to the old +-f lpwa.com:8000 +with no +-g +option. +For more information see the example file provided with the distribution. +

+Configure with care: no loop detection is performed. +When setting up chains of proxies that might loop back, try adding +Squid. +

-g gw_protocol[:[gw_host][:gw_port]]
+Use +gw_protocol +as the gateway protocol. +This option was introduced in Version 1.4, +but was folded into the +forwardfile +option in Version 2.0. +The default is to use no gateway protocol; +this may be explicitly specified as +direct +on the command line +or the dot character in the forwardfile. +The +SOCKS4 +protocol may be specified as +socks +or +socks4. +The +SOCKS4A +protocol is specified as +socks4a. +The +SOCKS5 +protocol is not currently supported. +The default +SOCKS +gw_port +is 1080. +

+The user's browser should +not +be +configured +to use +SOCKS; +the proxy conducts the negotiations, not the browser. +

+The user identification capabilities of +SOCKS4 +are deliberately not used; +the user is always identified to the +SOCKS +server as +userid=anonymous. +If the server's policy is to reject requests from +anonymous, +the proxy will not work. +Use a +debug +value of 3 +to see the status returned by the server. +

-d N
debug  N
+Set debug mode. +The most common value is 1, +to +pinpoint +offensive +URLs, +so they can be added to the blockfile. +The value of +N +is a bitwise +logical-OR +of the following values: +
+1 = URLs (show each URL requested by the browser);
+2 = Connections (show each connection to or from the proxy);
+4 = I/O (log I/O errors);
+8 = Headers (as each header is scanned, show the header and what is done to it);
+16 = Log everything (including debugging traces and the contents of the pages).
+Multiple +debug +lines are permitted; they are logical OR-ed together. +

+Because most browsers send several requests in parallel +the debugging output may appear intermingled, so the +single-threaded +option is recommended when using +debug +with +N +greater than 1. + +

-y
add-forwarded-header
+Add +X-Forwarded-For +headers to the server-bound +HTTP +stream +indicating the client +IP +address +to the server, +in the new style of +Squid 1.1.4. +If you want the traditional +HTTP_FORWARDED +response header, add it manually with the +-x +option. + +

-x HeaderText
add-header  HeaderText
+Add the +HeaderText +verbatim to requests to the server. +Typical uses include +adding old-style forwarding notices such as +Forwarded: by http://pro-privacy-isp.net +and reinstating the +Proxy-Connection: Keep-Alive +header +(which the +junkbuster +deletes so as +not +to reveal its existence). +No checking is done for correctness or plausibility, +so it can be used to throw any old trash into the server-bound +HTTP +stream. +Please don't litter. + +

-s
single-threaded
+Doesn't +fork() +a separate process +(or create a separate thread) +to handle each connection. +Useful when debugging to keep the process single threaded. +

-l logfile
logfile  logfile
+Write all debugging data into +logfile. +The default +logfile +is the standard output. +


aclfile  aclfile
+Unless this option is used, the proxy talks to anyone who can connect to it, +and everyone who can has equal permissions on where they can go. +An access file allows restrictions to be placed on these two policies, +by distinguishing some +source +IP +addresses and/or +some +destination +addresses. +(If a +forwarder or a gateway +is being used, its address is considered the destination address, +not the ultimate +IP +address of the +URL +requested.) +

+Each line of the access file begins with +either the word +permit +or +deny +followed by source and (optionally) destination addresses +to be matched against those of the +HTTP +request. +The last matching line specifies the result: if it was a +deny +line or if no line matched, +the request will be refused. +

+A source or destination +can be specified as a single numeric +IP +address, +or with a hostname, provided that the host's name +can be resolved to a numeric address: this cannot be used to block all +.mil +domains for example, +because there is no single address associated with that domain name. +Either form may be followed by a slash and an integer +N, +specifying a subnet mask of +N +bits. +For example, +permit 207.153.200.72/24 +matches the entire Class-C subnet from +207.153.200.0 +through 207.153.200.255. +(A netmask of 255.255.255.0 corresponds to 24 bits of +ones in the netmask, as with +*_MASKLEN=24.) +A value of 16 would be used for a Class-B subnet. +A value of zero for +N +in the subnet mask length will cause any address to match; +this can be used to express a default rule. +For more information see the example file provided with the distribution. +

+If you like these access controls +you should probably have +firewall; +they are not intended to replace one. +


trustfile  trustfile
+This feature is experimental, has not been fully documented and is +very subject to change. +The goal is for parents to be able to choose a page or site whose +links they regard suitable for their +young children +and for the proxy to allow access only to sites mentioned there. +To do this the proxy examines the +referer +variable on each page request to check they resulted from +a click on the ``trusted referer'' site: if so the referred site +is added to a list of trusted sites, so that the child can +then move around that site. +There are several uncertainties in this scheme that experience may be +able to iron out; check back in the months ahead. +


trust_info_url  trust_info_url
+When access is denied due to lack of a trusted referer, this +URL +is displayed with a message pointing the user to it for further information. +


hide-console
+In the Windows version only, instructs the program +to disconnect from and hide the command console after starting. +

-a
+(Obsolete) Accept the server's +Set-cookie +headers, passing them through to the browser. +This option was removed in Version 1.2 +and replaced by an improvement to the +-c +option. +
+

+ +

<Feedback>  +Installation and Use +

+

+Browsers must be told where to find the +junkbuster +(e.g. +localhost +port 8000). +To set the +HTTP +proxy in Netscape 3.0, +go through: + +Options; + +Network Preferences; + +Proxies; + +Manual Proxy Configuration; + +View. +See the +FAQ +for other browsers. +The +Security Proxy +should also be set to the same values, +otherwise +shttp: +URLs +won't work. +

+Note the limitations +explained in the +FAQ. +

+ +

<Feedback>  +Checking Options +

+

+To allow users to +check +that a +junkbuster +is running and how it is configured, +it intercepts requests for any +URL +ending in +/show-proxy-args +and blocks it, +returning instead returns information on its +version number and +current configuration +including the contents of its blockfile. +To get an explicit warning that no +junkbuster +intervened if the proxy was not configured, +it's best to point it to a +URL +that does this, such as +http://internet.junkbuster.com/cgi-bin/show-proxy-args +on Junkbusters's website. +

+ +

<Feedback>  +See Also +

+

+http://www.junkbusters.com/ht/en/ijbfaq.html +
+http://www.junkbusters.com/ht/en/cookies.html +
+http://internet.junkbuster.com/cgi-bin/show-proxy-args +
+http://www.cis.ohio-state.edu/htbin/rfc/rfc2109.html +
+http://squid.nlanr.net/Squid/ +
+http://www-math.uni-paderborn.de/~axel/ +

+ +

<Feedback>  +Copyright and GPL +

+

+Written and copyright by the Anonymous Coders and Junkbusters Corporation +and made available under the +GNU General Public License (GPL). +This software comes with +NO WARRANTY. +Internet Junkbuster +Proxy +is a +trademark +of Junkbusters Corporation. +

+

--- Back to Top of Page ---

+ +Home + · + + + · Site Map + + · Legal + + · Privacy + + · Cookies + + · Banner Ads + + · Telemarketing + + · Mail + + · Spam + +
+ +
+ + +

+Copyright © 1996-8 Junkbusters +® Corporation. +Copying and distribution permitted under +the GNU +General Public License. + + +1998/10/31 +http://www.junkbusters.com/ht/en/ijbman.html + +

webmaster@junkbusters.com
+
+ + diff --git a/encode.c b/encode.c new file mode 100644 index 00000000..42d07443 --- /dev/null +++ b/encode.c @@ -0,0 +1,400 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include +#include + +#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 + * 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) +{ + /* 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 = url_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 : 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; + + if (buf) + { + 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'; + } + + return(buf); + +} + + +/* + Local Variables: + tab-width: 3 + end: +*/ diff --git a/encode.h b/encode.h new file mode 100644 index 00000000..ba0b6cf0 --- /dev/null +++ b/encode.h @@ -0,0 +1,65 @@ +#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 $ + * + *********************************************************************/ + + +#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: +*/ diff --git a/errlog.c b/errlog.c new file mode 100644 index 00000000..54b26873 --- /dev/null +++ b/errlog.c @@ -0,0 +1,407 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#endif /* ndef _WIN32 */ + +#include +/* #include */ + +#ifdef _WIN32 +#include +#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: +*/ + diff --git a/errlog.h b/errlog.h new file mode 100644 index 00000000..24ce2856 --- /dev/null +++ b/errlog.h @@ -0,0 +1,80 @@ +#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 $ + * + *********************************************************************/ + + +#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: +*/ + diff --git a/filters.c b/filters.c new file mode 100644 index 00000000..29cee478 --- /dev/null +++ b/filters.c @@ -0,0 +1,1529 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#include +#else +#include +#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" + "\n" + "\n" + "Internet Junkbuster: Request for blocked URL\n" + "\n" + WHITEBG + "

" + BANNER + "

\n" + "

Your request for %s%s
\n" + "was blocked because it matches the following pattern " + "in the blockfile: %s\n

" +#ifdef FORCE_LOAD + "

Go there anyway.

" +#endif /* def FORCE_LOAD */ + "\n" + "\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" + "\n" + "\n" + "Internet Junkbuster: Request for untrusted URL\n" + "\n" + WHITEBG + "
" + "" + BANNER + "" + "
" + "\n" + "\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" + + "" + "" + "Internet Junkbuster Proxy Status - "); + s = strsav(s, file_description); + s = strsav(s, + "" + "\n" + "\n" + "
\n" + "

" BANNER "\n"); + s = strsav(s, file_description); + s = strsav(s, + "

\n" + "

Back to proxy status

\n" + "

"); + s = strsav(s, file_description); + s = strsav(s, + "

\n" + "Contents of file ""); + p = html_encode(filename); + s = strsav(s, p); + freez(p); + s = strsav(s, + "":
\n" + "

\n" + "
");
+      
+      if ((fp = fopen(filename, "r")) == NULL)
+      {
+         s = strsav(s, "

ERROR OPENING FILE!

");
+      }
+      else
+      {
+         while (fgets(buf, sizeof(buf), fp))
+         {
+            p = html_encode(buf);
+            if (p)
+            {
+               s = strsav(s, p);
+               freez(p);
+               s = strsav(s, "
"); + } + } + fclose(fp); + } + + s = strsav(s, + "
\n" + "
\n" + "

Back to proxy status

\n" + "
\n" + "

\n" + "Code and documentation of the " BANNER " Proxy" + "TM\n" + "\n" "Copyright© 1997 Junkbusters Corporation\n" + "TM
\n" + "Copying and distribution permitted under the" + "\n" + "GNU " + "General Public License.\n" + "
" + "

webmaster@junkbusters.com
" + "
" + "\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, + "

The following files are in use:

\n" + "

(Click a filename to view it)

\n" + ""); + +#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" + "\n" + "\n" + "Internet Junkbuster: Request for untrusted URL\n" + "\n" + BODY + "

" + BANNER + "

" + "The " BANNER " Proxy " + "" + "(" HOME_PAGE_URL ") " + "intercepted the request for %s%s\n" + "because the URL is not trusted.\n" + "

\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 "); + strsav(p, refer); + strsav(p, "
\n"); + + freez(hostport); + freez(path ); + freez(refer ); + + p = strsav(p, "

The following referrers are trusted

\n"); + + for (tl = trust_list; (t = *tl) ; tl++) + { + sprintf(buf, "%s
\n", t->spec); + p = strsav(p, buf); + } + + if (trust_info->next) + { + struct list *l; + + strcpy(buf, + "

" + "You can learn more about what this means " + "and what you may be able to do about it by " + "reading the following documents:
\n" + "

    \n" + ); + + p = strsav(p, buf); + + for (l = trust_info->next; l ; l = l->next) + { + sprintf(buf, + "
  1. %s
    \n", + l->str, l->str); + p = strsav(p, buf); + } + + p = strsav(p, "
\n"); + } + + p = strsav(p, "\n" "\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,"

Statistics for this " BANNER ":

\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: +*/ diff --git a/filters.h b/filters.h new file mode 100644 index 00000000..68af5195 --- /dev/null +++ b/filters.h @@ -0,0 +1,106 @@ +#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 $ + * + *********************************************************************/ + + +#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: +*/ diff --git a/forward b/forward new file mode 100644 index 00000000..be4c7870 --- /dev/null +++ b/forward @@ -0,0 +1,97 @@ +# 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. + diff --git a/gateway.c b/gateway.c new file mode 100644 index 00000000..2ccf1676 --- /dev/null +++ b/gateway.c @@ -0,0 +1,287 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include +#include + +#ifdef _WIN32 +#include +#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: +*/ diff --git a/gateway.h b/gateway.h new file mode 100644 index 00000000..69145552 --- /dev/null +++ b/gateway.h @@ -0,0 +1,69 @@ +#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 $ + * + *********************************************************************/ + + +#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: +*/ diff --git a/icons/denyrule.ico b/icons/denyrule.ico new file mode 100644 index 00000000..e5aa2506 Binary files /dev/null and b/icons/denyrule.ico differ diff --git a/icons/ico00001.ico b/icons/ico00001.ico new file mode 100644 index 00000000..a01ccfcc Binary files /dev/null and b/icons/ico00001.ico differ diff --git a/icons/ico00002.ico b/icons/ico00002.ico new file mode 100644 index 00000000..b7de068b Binary files /dev/null and b/icons/ico00002.ico differ diff --git a/icons/ico00003.ico b/icons/ico00003.ico new file mode 100644 index 00000000..99e09803 Binary files /dev/null and b/icons/ico00003.ico differ diff --git a/icons/ico00004.ico b/icons/ico00004.ico new file mode 100644 index 00000000..35b76d4d Binary files /dev/null and b/icons/ico00004.ico differ diff --git a/icons/ico00005.ico b/icons/ico00005.ico new file mode 100644 index 00000000..db9bddf7 Binary files /dev/null and b/icons/ico00005.ico differ diff --git a/icons/ico00006.ico b/icons/ico00006.ico new file mode 100644 index 00000000..5e1f3fa8 Binary files /dev/null and b/icons/ico00006.ico differ diff --git a/icons/ico00007.ico b/icons/ico00007.ico new file mode 100644 index 00000000..6ec504d7 Binary files /dev/null and b/icons/ico00007.ico differ diff --git a/icons/ico00008.ico b/icons/ico00008.ico new file mode 100644 index 00000000..e6bc72f3 Binary files /dev/null and b/icons/ico00008.ico differ diff --git a/icons/icon1.ico b/icons/icon1.ico new file mode 100644 index 00000000..b96fe7c2 Binary files /dev/null and b/icons/icon1.ico differ diff --git a/icons/idle.ico b/icons/idle.ico new file mode 100644 index 00000000..99470b54 Binary files /dev/null and b/icons/idle.ico differ diff --git a/icons/junkbust.ico b/icons/junkbust.ico new file mode 100644 index 00000000..41aafd0a Binary files /dev/null and b/icons/junkbust.ico differ diff --git a/imagelist b/imagelist new file mode 100644 index 00000000..e83fed0d --- /dev/null +++ b/imagelist @@ -0,0 +1,34 @@ +# +# 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 +# +# 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 diff --git a/jbsockets.c b/jbsockets.c new file mode 100644 index 00000000..c5f73c9c --- /dev/null +++ b/jbsockets.c @@ -0,0 +1,476 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + +#include +#include +#include + +#else + +#include +#include +#include +#include +#include +#include + +#ifndef __BEOS__ +#include +#include +#else +#include +#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) + 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) + CloseSocket(fd); +#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: +*/ diff --git a/jbsockets.h b/jbsockets.h new file mode 100644 index 00000000..6d77c4c5 --- /dev/null +++ b/jbsockets.h @@ -0,0 +1,72 @@ +#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 $ + * + *********************************************************************/ + + +#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: +*/ diff --git a/jcc.c b/jcc.c new file mode 100644 index 00000000..e6d06bd7 --- /dev/null +++ b/jcc.c @@ -0,0 +1,1224 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + +# include +# include +# include +# include +# ifdef TOGGLE +# include +# endif /* def TOGGLE */ + +# include "win32.h" +# ifndef _WIN_CONSOLE +# include "w32log.h" +# endif /* ndef _WIN_CONSOLE */ + +#else /* ifndef _WIN32 */ + +# include +# include +# include +# include +# include + +# ifdef __BEOS__ +# include /* BeOS has select() for sockets only. */ +# include /* declarations for threads and stuff. */ +# endif + +# ifndef FD_ZERO +# include +# 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 "\n" + +static const char CFAIL[] = + "HTTP/1.0 503 Connect failed\n" + "Content-Type: text/html\n\n" + "\n" + "\n" + "Internet Junkbuster: Connect failed\n" + "\n" + BODY + "

" + BANNER + "

" + "TCP connection to '%s' failed: %s.\n
" + "\n" + "\n"; + +static const char CNXDOM[] = + "HTTP/1.0 404 Non-existent domain\n" + "Content-Type: text/html\n\n" + "\n" + "\n" + "Internet Junkbuster: Non-existent domain\n" + "\n" + BODY + "

" + BANNER + "

" + "No such domain: %s\n" + "\n" + "\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" + "Expires: Thu Jul 31, 1997 07:42:22 pm GMT\r\n" + "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" + "Expires: Thu Jul 31, 1997 07:42:22 pm GMT\r\n" + "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;"; + +static const char FWGIF[] = + "HTTP/1.0 302 Blocked Advert\r\n" + "Pragma: no-cache\r\n" + "Last-Modified: Thu Jul 31, 1997 07:42:22 pm GMT\r\n" + "Expires: Thu Jul 31, 1997 07:42:22 pm GMT\r\n" + "Location: "; + +#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) + { + break; /* no HTTP request! */ + } + + if (*req == '\0') + { + continue; /* more to come! */ + } + +#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)) + { + write_socket(csp->cfd, FWGIF, sizeof(FWGIF)-1); + write_socket(csp->cfd, tinygifurl, strlen(tinygifurl)); + } + 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"); + +#ifdef AMIGA + if(!childs) + { + exit(1); + } +#endif + 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) +#define SELECTED_ONE_OPTION + csp->cfd = ReleaseSocket(csp->cfd, -1); + if((child_id = (int)CreateNewProcTags( + NP_Entry, (ULONG)server_thread, + NP_Output, Output(), + NP_CloseOutput, FALSE, + NP_Name, (ULONG)"junkbuster child", + NP_StackSize, 20*1024, + TAG_DONE))) + { + childs++; + ((struct Task *)child_id)->tc_UserData = csp; + Signal((struct Task *)child_id, SIGF_SINGLE); + Wait(SIGF_SINGLE); + } +#endif + +#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: +*/ diff --git a/jcc.h b/jcc.h new file mode 100644 index 00000000..fcafbb71 --- /dev/null +++ b/jcc.h @@ -0,0 +1,96 @@ +#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 $ + * + *********************************************************************/ + + +/* Declare struct FILE for vars and funcs. */ +#include + +/* 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: +*/ diff --git a/junkbstr.txt b/junkbstr.txt new file mode 100644 index 00000000..cbe21048 --- /dev/null +++ b/junkbstr.txt @@ -0,0 +1,206 @@ +# 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 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" +# +# default: Kill the referrer-header from the client +# 'text' : Always send 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 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 + + diff --git a/junkbuster.1 b/junkbuster.1 new file mode 100644 index 00000000..d88294da --- /dev/null +++ b/junkbuster.1 @@ -0,0 +1,871 @@ +.TH JUNKBUSTER 1 "http://www.junkbusters.com/ht/en/ijb2.0man.html" +.SH NAME +\fBjunkbuster\fP +- The +Internet Junkbuster +Proxy +\s-2(TM)\s+2 +.SH SYNOPSIS +\fBjunkbuster\fP +\fI\&configfile\fP +(Version 2.0 onwards) +.br +\fBjunkbstr.exe\fP +\fI\&configfile\fP +(Windows) +.br +\fBjunkbuster\fP +[-a] +[-y] +[-s] +[-c] +[-v] +.br +[-u user_agent] +[-r referer] +[-t from] +.br +[-b blockfile] +[-j jarfile] +[-l logfile] +.br +[-w NAME=VALUE] +[-x Header_text] +.br +[-h [bind_host_address][:bind_port]] +.br +[-f forward_host[:port]] +[-d N] +.br +[-g gw_protocol[:[gw_host][:gw_port]]] +.br +(Version 1.4 and earlier) +.SH DESCRIPTION +\fBjunkbuster\fP +is an instrumentable proxy that filters the +\s-2HTTP\s0 +stream between +web servers and browsers. +Its main purpose is to enhance privacy. +.P +Versions before 2.0 used command-line options; +Versions from 2.0 onward use a configuration file. +The following descriptions of the options first give the older +command-line usage, then the new configfile line. +.P +In Versions 2.0.1 upwards on Windows, +a start-up message is printed and the configuration is read from the file +\fC\&junkbstr.ini\fP +if it exists and no argument was given. +.P +All files except the configfile +are checked for changes before each page is fetched, +so they may edited without restarting the proxy. +.SS OPTIONS +.TP +.\" anchor: o_b blockfile +\fI-b blockfile\fP (Old) blockfile \fIblockfile\fP (New) +Block\" ijbfaq.html#blocking +requests to +\s-2URL\s0s +matching any pattern given in the lines of the +\fI\&blockfile\fP. +The +\fBjunkbuster\fP +instead returns status 202, indicating that the request has been accepted +(though not completed), +and a +message identifying itself\" ijbfaq.html#show +(though the browser may +display only a broken image icon). +(Versions before 2.0 returned an error 403 (Forbidden).) +The syntax of a pattern is +\fB\&[domain][:port][/path]\fP +(the +\fB\&http://\fP +or +\fB\&https://\fP +protocol part is omitted). +To decide if a pattern matches a target, the domains are compared first, +then the paths. +.P +To compare the domains, +the pattern domain and the target +domain specified in the +\s-2URL\s0 +are each broken into their components. +(Components are separated by the +\fC\&.\fP +(period) character.) +Next each of the target components +is compared with the corresponding pattern component: last with last, +next-to-last with next-to-last, and so on. +(This is called +\fIright-anchored\fP +matching.) +If all of the pattern components find their match in the target, +then the domains are considered a match. +Case is irrelevant when comparing domain components. +.P +A successfully +matching pattern can be an anchored substring of a target, but +not vice versa. +Thus if a pattern doesn't specify a domain, +it matches all domains. +.\" anchor: wildcard +Furthermore, when comparing two components, +the components must either match in their entirety or up to a wildcard +\fC\&* \fP +(star character) in the pattern. The wildcard feature +implements only a "prefix" match capability ("abc*" vs. "abcdefg"), +not suffix matching ("*efg" vs. "abcdefg") or +infix matching ("abc*efg" vs. "abcdefg"). +The feature is restricted to the domain component; +it is unrelated to the optional +regular expression +feature in the path +(described below).\" ijbman.html#regex +.P +If a numeric port +is specified in the pattern domain, then the target port must +match as well. The default port in a target is port 80. +.P +If the domain and port match, +then the target +\s-2URL\s0 +path is checked for +a match against the path in the pattern. +Paths are compared with a simple case-sensitive +left-anchored substring comparison. +Once again, the pattern can be an +anchored substring of the target, but not vice versa. +A path of +\fC\&/\fP +(slash) would match all paths. Wildcards are not considered in +path comparisons. +.P +For example, the target +\s-2URL\s0 +.br +.ti +0.25i +\fB\&the.yellow-brick-road.com/TinMan/has_no_brain\fP +.br +would be matched (and blocked) by the following patterns +.br +.ti +0.25i +\fB\&yellow-brick-road.com\fP +.br +and +.br +.ti +0.25i +\fB\&Yellow*.COM\fP +.br +and +.br +.ti +0.25i +\fB\&/TinM\fP +.br +but not +.br +.ti +0.25i +\fB\&follow.the.yellow-brick-road.com\fP +.br +or +.br +.ti +0.25i +\fB\&/tinman\fP +.br +.P +Comments in a blockfile start with a +\fB\&#\fP +(hash) character and end at a new line. +Blank lines are also ignored. +.P +Lines beginning with a +\fC\&~\fP +(tilde) character are taken to be +exceptions:\" ijbfaq.html#exceptions +a +\s-2URL\s0 +blocked by previous patterns that matches the rest of +the line is let through. (The last match wins.) +.P +Patterns +may contain +\s-2POSIX\s0 +regular expressions\" ijbfaq.html#regex +provided the +\fBjunkbuster\fP +was compiled with this option +(the default in Version 2.0 on). +The idiom +\fC\&/*.*/ad\fP +can then be used +to match any +\s-2URL\s0 +containing +\fC\&/ad\fP +(such as +\fC\&http://nomatterwhere.com/images/advert/g3487.gif\fP +for example). +These expressions +don't work\" ijbman.html#substring +in the domain part. +.P +In version 1.3 and later +the blockfile and cookiefile are checked for changes before each request. +.TP +tinygif \fIN\fP +Set appearance of blocked GIFs. You can select one of the following +values: +.br +.br +\h'-\w"0 = "u'0 = Show a ``broken icon'' in the browser +.br +\h'-\w"1 = "u'1 = Show a one pixel transparent GIF +.br +\h'-\w"2 = "u'2 = Show a GIF with the word ``JUNKBUSTER'' +.TP +popupfile \fI\&popup\fP +Sets the name of the popupfile. If uncommented, the popupfile +controls on which sites Javascript popup windows are disabled. +.TP +.\" anchor: o_w wafer +\fI-w NAME=VALUE\fP (Old) wafer \fINAME=VALUE\fP (New) +Specifies a pair to be sent as a cookie with every request +to the server.\" ijbfaq.html#wafers +(Such boring cookies are called +\fI\&wafers\fP.) +This option may be called more than once to generate multiple wafers. +The original +Netscape specification +prohibited +semi-colons, commas and white space; +these characters will be +\s-2URL\s0-encoded +if used in wafers. +The Path and Domain attributes are not currently supported. +.TP +.\" anchor: o_c cookiefile +\fI-c cookiefile\fP (Old) cookiefile \fIcookiefile\fP (New) +Enforce the cookie management policy specified in the +\fI\&cookiefile.\fP +.\" anchor: java +If this option is not used all cookies are silently crunched, +so that users who never want cookies aren't bothered by browsers +asking whether each cookie should be accepted. +However, cookies can +still get through\" ijbfaq.html#breakthrough +via +JavaScript\" links.html#javascript +and +\s-2SSL\s0, +so alerts should be left on. +.P +In Version 1.2 and later +this option must be followed by a +filename\" ijbfaq.html#crumble +containing instructions on which sites are allowed to +receive and set cookies. +.\" anchor: drop +By default cookies are dropped in both the browser's request +and the server's response, unless the +\s-2URL\s0 +requested matches an entry in the +\fI\&cookiefile\fP. +The matching algorithm is the same as for the blockfile. +A leading +\fC\&>\fP +character allows +server-bound\" ijbfaq.html#directional +cookies only; +a +\fC\&<\fP +allows only browser-bound cookies; +a +\fC\&~\fP +character stops cookies in +both directions.\" ijbfaq.html#crumble +Thus a cookiefile containing a single line with the two characters +\fC\&>*\fP +will pass on all cookies to servers but not give any new ones to the browser. +.TP +.\" anchor: o_j jarfile +\fI-j jarfile\fP (Old) jarfile \fIjarfile\fP (New) +All Set-cookie attempts by the server are +logged\" ijbfaq.html#jar +to +\fI\&jarfile\fP. +If no wafer is specified, +one containing a +canned notice\" ijbfaq.html#notice +(the +\fI\&vanilla wafer\fP) +is added as an alert to the server +unless the +suppress-vanilla-wafer\" ijbman.html#suppress-vanilla-wafer +option is invoked. +.TP +.\" anchor: o_v suppress-vanilla-wafer +\fI-v\fP (Old) suppress-vanilla-wafer \fI\fP (New) +Suppress the vanilla wafer. +.TP +.\" anchor: o_t from +\fI-t from\fP (Old) from \fIfrom\fP (New) +If the browser +discloses an email address\" ijbfaq.html#from +in the +\fB\&FROM\fP +header (most don't), +replace it with +\fI\&from.\fP +If +\fI\&from\fP +is set to +\fB\&.\fP +(the period character) +the +\fB\&FROM\fP +is passed to the server unchanged. +The default is to delete the +\fB\&FROM\fP +header. +.TP +.\" anchor: o_r referer +\fI-r referer\fP (Old) referer \fIreferer\fP (New) +Whenever the browser discloses the +\s-2URL\s0 +that +led to\" ijbfaq.html#referer +the current request, +replace it with +\fI\&referer.\fP +If +\fI\&referer\fP +is set to +\fB\&.\fP +(period) +the +\s-2URL\s0 +is passed to the server unchanged. +In +Version 1.4 +and later, if referer is set to +\fB\&@\fP +(at) the +\s-2URL\s0 +is sent in cases where the cookiefile +specifies that a cookie would be sent. +(No way to send bogus referers selectively is provided.) +The default is to delete Referer. +.P +Version 2.0 also accepts the spelling +\fC\&referrer\fP, +which most dictionaries consider correct. +.TP +.\" anchor: o_u user-agent +\fI-u user-agent\fP (Old) user-agent \fIuser-agent\fP (New) +Information disclosed by the browser +about itself\" ijbfaq.html#agent +is replaced with the value +\fI\&user-agent.\fP +If +\fI\&user-agent\fP +is set to +\fB\&.\fP +(period) +the +\fB\&User-Agent\fP +header is passed to the server unchanged, +along with any +\fB\&UA\fP +headers produced by +\s-2MS-IE\s0 +(which would otherwise be deleted). +In +Version 1.4 +and later, if +\fI\&user-agent\fP +is set to +\fB\&@\fP +(at) these headers are sent unchanged in cases where the cookiefile +specifies that a cookie would be sent, +otherwise only default +\fB\&User-Agent\fP +header is sent. +That default +is Mozilla/3.0 (Netscape) +with an unremarkable +Macintosh\" ijbfaq.html#infer +configuration. +If used with a browser less advanced than Mozilla/3.0 or IE-3, the default +may encourage pages containing extensions that confuse the browser. +.TP +.\" anchor: o_h listen-address +\fI-h [host][:port]\fP (Old) listen-address \fI[host][:port]\fP (New) +If +\fI\&host\fP +is specified, +bind the +\fBjunkbuster\fP +to that +\s-2IP\s0 +address. +If a +\fI\&port\fP +is specified, use it. +The default +port +is 8000; +the default host is +\fC\&localhost\fP. +Before Version 2.0.2, +the default was to bind to all +\s-2IP\s0 +addresses +(\fB\&INADDR_ANY\fP); +but this has been restricted to +\fB\&localhost\fP +to avoid unintended security breaches. +(To open the proxy to all, use the line +.br +.ti +0.25i +\fB\&listen-address :8000\fP +.br +in the configuration file.) +.TP +.\" anchor: o_f forwardfile +\fI-f forward_host[:port]\fP (Old) forwardfile \fIforwardfile\fP (New) +Version 1.X required all +\s-2HTTP\s0 +requests from the client to be forwarded to the same destination. +Version 2.0 takes its routing specification from a +\fI\&forwardfile\fP, +allowing selection of the proxy (a.k.a. forwarding host) and gateway +according to the +\s-2URL\s0. +Here is a typical line. +.br +.ft CW +.S 8 +.nf +.sp +* lpwa.com:8000 . . +.S +.ft +.fi +.sp + +.P +Each line contains four fields: +\fB\&target\fP, +\fB\&forward_to\fP, +\fB\&via_gateway_type\fP +and +\fB\&gateway\fP. +As usual, the +last\" ijbman.html#compare +\fB\&target\fP +domain that matches the requested +\s-2URL\s0 +wins, +and the +\fC\&*\fP +character alone matches any domain. +The target domain need not be a fully qualified +hostname; it can be a general domain such as +\fC\&com\fP +or +\fC\&co.uk\fP +or even just a port number. +.\" anchor: nose +For example, because +LPWA +does not handle +SSL,\" ijbfaq.html#encrypt +the line above will typically be followed by a line such as +.br +.ft CW +.S 8 +.nf +.sp +:443 . . . +.S +.ft +.fi +.sp + +to allow SSL transactions to proceed directly. +The cautious would also +add an entry in their blockfile to stop transactions +to port 443 for all but specified trusted sites. +.P +If the winning +\fB\&forward_to\fP +field is +\fC\&.\fP +(the dot character) the proxy connects +directly to the server given in the +\s-2URL\s0, +otherwise it forwards to the host and port number specified. +The default port is 8000. +The +\fC\&via_gateway_type\fP +and +\fC\&gateway\fP +fields also use a dot to indicate no gateway protocol. +The gateway protocols are explained +below.\" ijbman.html#o_g +.P +The example line above in a forwardfile alone +would send everything through port 8000 at +\fC\&lpwa.com\fP +with no gateway protocol, +and is equivalent to the old +\fC\&-f lpwa.com:8000\fP +with no +\fC\&-g\fP +option. +For more information see the example file provided with the distribution. +.P +Configure with care: no loop detection is performed. +When setting up chains of proxies that might loop back, try adding +Squid.\" ijbman.html#squid +.TP +.\" anchor: o_g +\fI-g gw_protocol[:[gw_host][:gw_port]]\fP (Old) +Use +\fI\&gw_protocol\fP +as the gateway protocol. +This option was introduced in Version 1.4, +but was folded into the +forwardfile\" ijbman.html#forwardfile +option in Version 2.0. +The default is to use no gateway protocol; +this may be explicitly specified as +\fB\&direct\fP +on the command line +or the dot character in the forwardfile. +The +\fC\&SOCKS4\fP +protocol may be specified as +\fB\&socks\fP +or +\fB\&socks4\fP. +The +\fC\&SOCKS4A\fP +protocol is specified as +\fB\&socks4a\fP. +The +\fC\&SOCKS5\fP +protocol is not currently supported. +The default +\s-2SOCKS\s0 +\fI\&gw_port\fP +is 1080. +.P +The user's browser should +\fInot\fP +be +configured\" ijbfaq.html#socks +to use +\fC\&SOCKS\fP; +the proxy conducts the negotiations, not the browser. +.P +The user identification capabilities of +\fC\&SOCKS4\fP +are deliberately not used; +the user is always identified to the +\fC\&SOCKS\fP +server as +\fC\&userid=anonymous\fP. +If the server's policy is to reject requests from +\fC\&anonymous\fP, +the proxy will not work. +Use a +debug\" ijbman.html#o_d +value of 3 +to see the status returned by the server. +.TP +.\" anchor: o_d debug +\fI-d N\fP (Old) debug \fIN\fP (New) +Set debug mode. +The most common value is 1, +to +pinpoint\" ijbfaq.html#pinpoint +offensive +\s-2URL\s0s, +so they can be added to the blockfile. +The value of +\fB\&N\fP +is a bitwise +logical-\s-2OR\s0 +of the following values: +.br +.br +\h'-\w"1 = "u'1 = URLs (show each URL requested by the browser); +.br +\h'-\w"2 = "u'2 = Connections (show each connection to or from the proxy); +.br +\h'-\w"4 = "u'4 = I/O (log I/O errors); +.br +\h'-\w"8 = "u'8 = Headers (as each header is scanned, show the header and what is done to it); +.br +\h'-\w"16 = "u'16 = Log everything (including debugging traces and the contents of the pages). +.\" anchor: or +Multiple +\fB\&debug\fP +lines are permitted; they are logical OR-ed together. +.P +Because most browsers send several requests in parallel +the debugging output may appear intermingled, so the +single-threaded\" ijbman.html#single-threaded +option is recommended when using +debug\" ijbman.html#debug +with +\fB\&N\fP +greater than 1. +.TP +.\" anchor: o_y add-forwarded-header +\fI-y\fP (Old) add-forwarded-header \fI\fP (New) +Add +\fB\&X-Forwarded-For\fP +headers to the server-bound +\s-2HTTP\s0 +stream +indicating the client +\s-2IP\s0 +address +to the server,\" ijbfaq.html#detect +in the new style of +Squid 1.1.4.\" ijbman.html#squid +If you want the traditional +\fC\&HTTP_FORWARDED\fP +response header, add it manually with the +-x\" ijbman.html#o_x +option. +.TP +.\" anchor: o_x add-header +\fI-x HeaderText\fP (Old) add-header \fIHeaderText\fP (New) +Add the +\fI\&HeaderText\fP +verbatim to requests to the server. +Typical uses include +adding old-style forwarding notices such as +\fB\&Forwarded: by http://pro-privacy-isp.net\fP +and reinstating the +\fB\&Proxy-Connection: Keep-Alive\fP +header +(which the +\fBjunkbuster\fP +deletes so as +not\" ijbfaq.html#detect +to reveal its existence). +No checking is done for correctness or plausibility, +so it can be used to throw any old trash into the server-bound +\s-2HTTP\s0 +stream. +Please don't litter. +.TP +.\" anchor: o_s single-threaded +\fI-s\fP (Old) single-threaded \fI\fP (New) +Doesn't +\fB\&fork()\fP +a separate process +(or create a separate thread) +to handle each connection. +Useful when debugging to keep the process single threaded. +.TP +.\" anchor: o_l logfile +\fI-l logfile\fP (Old) logfile \fIlogfile\fP (New) +Write all debugging data into +\fI\&logfile.\fP +The default +\fI\&logfile\fP +is the standard output. +.TP +.\" anchor: o_acl aclfile +aclfile \fIaclfile\fP (New) +Unless this option is used, the proxy talks to anyone who can connect to it, +and everyone who can has equal permissions on where they can go. +An access file allows restrictions to be placed on these two policies, +by distinguishing some +\fIsource\fP +\s-2IP\s0 +addresses and/or +some +\fIdestination\fP +addresses. +(If a +forwarder or a gateway\" ijbman.html#forwardfile +is being used, its address is considered the destination address, +not the ultimate +\s-2IP\s0 +address of the +\s-2URL\s0 +requested.) +.P +Each line of the access file begins with +either the word +\fB\&permit\fP +or +\fB\&deny\fP +followed by source and (optionally) destination addresses +to be matched against those of the +\s-2HTTP\s0 +request. +The last matching line specifies the result: if it was a +\fB\&deny\fP +line or if no line matched, +the request will be refused. +.P +A source or destination +can be specified as a single numeric +\s-2IP\s0 +address, +or with a hostname, provided that the host's name +can be resolved to a numeric address: this cannot be used to block all +\fB\&.mil \fP +domains for example, +because there is no single address associated with that domain name. +Either form may be followed by a slash and an integer +\fB\&N\fP, +specifying a subnet mask of +\fB\&N\fP +bits. +For example, +\fB\&permit 207.153.200.72/24\fP +matches the entire Class-C subnet from +207.153.200.0 +through 207.153.200.255. +(A netmask of 255.255.255.0 corresponds to 24 bits of +ones in the netmask, as with +\fC\&*_MASKLEN=24\fP.) +A value of 16 would be used for a Class-B subnet. +A value of zero for +\fB\&N\fP +in the subnet mask length will cause any address to match; +this can be used to express a default rule. +For more information see the example file provided with the distribution. +.P +If you like these access controls +you should probably have +firewall;\" ijbfaq.html#firewall +they are not intended to replace one. +.TP +.\" anchor: o_tf trustfile +trustfile \fItrustfile\fP (New) +This feature is experimental, has not been fully documented and is +very subject to change. +The goal is for parents to be able to choose a page or site whose +links they regard suitable for their +young children\" ijbfaq.html#children +and for the proxy to allow access only to sites mentioned there. +To do this the proxy examines the +referer\" ijbman.html#o_r +variable on each page request to check they resulted from +a click on the ``trusted referer'' site: if so the referred site +is added to a list of trusted sites, so that the child can +then move around that site. +There are several uncertainties in this scheme that experience may be +able to iron out; check back in the months ahead. +.TP +.\" anchor: o_ti trust_info_url +trust_info_url \fItrust_info_url\fP (New) +When access is denied due to lack of a trusted referer, this +\s-2URL\s0 +is displayed with a message pointing the user to it for further information. +.TP +.\" anchor: o_hc hide-console +hide-console \fI\fP (New) +In the Windows version only, instructs the program +to disconnect from and hide the command console after starting. +.TP +.\" anchor: o_a +\fI-a\fP (Old) +(Obsolete) Accept the server's +\fB\&Set-cookie\fP +headers, passing them through to the browser. +.\" anchor: obsolete +This option was removed in Version 1.2 +and replaced by an improvement to the +-c\" ijbman.html#o_c +option. +.LE +.SH INSTALLATION AND USE +Browsers must be told where to find the +\fBjunkbuster\fP +(e.g. +\fB\&localhost\fP +port 8000). +To set the +\s-2HTTP\s0 +proxy in Netscape 3.0, +go through: +\fB\&Options\fP; +\fB\&Network Preferences\fP; +\fB\&Proxies\fP; +\fB\&Manual Proxy Configuration\fP; +\fB\&View\fP. +See the +\s-2FAQ\s0 +for other browsers. +The +Security Proxy\" ijbfaq.html#security +should also be set to the same values, +otherwise +\fB\&shttp:\fP +\s-2URL\s0s +won't work. +.P +Note the limitations +explained in the +\s-2FAQ\s0. +.SH CHECKING OPTIONS +To allow users to +check\" ijbfaq.html#show +that a +\fBjunkbuster\fP +is running and how it is configured, +it intercepts requests for any +\s-2URL\s0 +ending in +\fB\&/show-proxy-args\fP +and blocks it, +returning instead returns information on its +version number and +current configuration +including the contents of its blockfile. +To get an explicit warning that no +\fBjunkbuster\fP +intervened if the proxy was not configured, +it's best to point it to a +\s-2URL\s0 +that does this, such as +http://internet.junkbuster.com/cgi-bin/show-proxy-args +on Junkbusters's website. +.SH SEE ALSO +http://www.waldherr.org/junkbuster/\" waldherr.org# +.br +http://www.junkbusters.com/ht/en/ijbfaq.html\" ijbfaq.html# +.br +http://www.junkbusters.com/ht/en/cookies.html\" cookies.html# +.br +http://internet.junkbuster.com/cgi-bin/show-proxy-args +.br +http://www.cis.ohio-state.edu/htbin/rfc/rfc2109.html +.br +http://squid.nlanr.net/Squid/ +.br +http://www-math.uni-paderborn.de/~axel/ +.SH COPYRIGHT AND GPL +Written and copyright by the Anonymous Coders and Junkbusters Corporation +and made available under the +GNU General Public License (GPL).\" gpl.html# +This software comes with +NO WARRANTY.\" gpl.html#nowarr +Internet Junkbuster +Proxy +is a +trademark\" legal.html#marks +of Junkbusters Corporation. diff --git a/junkbuster.init b/junkbuster.init new file mode 100644 index 00000000..c74b6b7a --- /dev/null +++ b/junkbuster.init @@ -0,0 +1,149 @@ +#!/bin/sh +# +# $Id: junkbuster.init,v 1.2 2001/04/30 02:36:54 rodney Exp $ +# +# This is file is either +# +# /etc/rc.d/init.d/junkbuster +# +# or +# +# /sbin/init.d/junkbuster +# +# and was put here by the junkbuster rpm +# +# junkbuster This shell script takes care of starting and stopping +# junkbuster. +# +# This works only correctly if the user `nobody' is allowed +# to be in the directory where this file is called +# (for example: /root is NOT ok) +# --------------------------------------------------------------------------- +# Force /bin/sh as shell (padraic@renaghan.com). +# Augmented with help by Sterling +# Hints from mjohnson11@uswest.net +# Hints from rochedav@primenet.com +# --------------------------------------------------------------------------- +# These lines are needed so Redhat's config tools will "see" this script: +# chkconfig: 35 84 09 +# description: Blocks annoying ads from the internet, along with cookies \ +# and a few other privacy features. +# processname: junkbuster +# config: /etc/junkbuster/config + + +# --------------------------------------------------------------------------- +# +# SuSE only +# +# --------------------------------------------------------------------------- +if [ -f /etc/rc.config ]; then + +# Author: Daniel Bischof , 1999 +# Adjustment: Axel Braun , 17.08.2000 +. /etc/rc.config +#base=${0##*/} +#link=${base#*[SK][0-9][0-9]} +#test $link = $base && START_IJB=yes +#test "$START_IJB" = "yes" || exit 0 +return=$rc_done +case "$1" in + start) + echo -n "Starting The Internet Junkbuster" + su - nobody -c 'nohup /usr/sbin/junkbuster /etc/junkbuster/config < /dev/null > /dev/null &' + sleep 1 + echo -e "$return" + ;; + stop) + echo -n "Shutting down The Internet Junkbuster" + killproc -TERM /usr/sbin/junkbuster || return=$rc_failed + echo -e "$return" + ;; + restart|reload) + echo -n "Reload The Internet Junkbuster" + killproc -HUP /usr/sbin/junkbuster || return=$rc_failed + echo -e "$return" + ;; + status) + checkproc /usr/sbin/junkbuster && echo OK || echo No process + ;; + *) + echo "Usage: $0 {start|restart|status|stop}" + exit 1 +esac +test "$return" = "$rc_done" || exit 1 +exit 0 + +else +# --------------------------------------------------------------------------- +# +# RedHat only +# +# --------------------------------------------------------------------------- + +# Source function library. +if [ -f /etc/rc.d/init.d/functions ]; then +. /etc/rc.d/init.d/functions +fi + +if [ -f /etc/sysconfig/network ]; then +. /etc/sysconfig/network +fi + +# Check that networking is up. +[ ${NETWORKING} = "no" ] && exit 0 + +[ -f /etc/junkbuster/config ] || exit 0 + +[ -f /usr/sbin/junkbuster ] || exit 0 + +RETVAL=0 + +# See how we were called. +case "$1" in + + start) + # abort if already started + pid=`pidofproc junkbuster` + [ -n "$pid" ] && ps h $pid >/dev/null 2>&1 && \ + echo -n "Already started: " && status junkbuster && \ + exit 0 + + # Start daemon. + echo -n "Starting junkbuster:" && RETVAL=1 + ulimit -c 0 + su - nobody -s /bin/sh -c '/usr/sbin/junkbuster /etc/junkbuster/config' & + sleep 1 + pid=`pidofproc junkbuster` + [ -n "$pid" ] && ps h $pid >/dev/null 2>&1 && RETVAL=0 && echo_success && touch /var/lock/subsys/junkbuster + [ $RETVAL -eq 1 ] && echo_failure + echo + ;; + + stop) + # Stop daemon. + echo -n "Shutting down junkbuster:" + killproc junkbuster + RETVAL=$? + [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/junkbuster + echo + ;; + + status) + status junkbuster + RETVAL=$? + ;; + + restart|reload) + $0 stop && $0 start + ;; + + *) + echo "Usage: junkbuster {start|stop|status|restart|reload}" + exit 1 +esac + +exit $RETVAL + +fi + diff --git a/junkbuster.logrotate b/junkbuster.logrotate new file mode 100644 index 00000000..e8e8b92d --- /dev/null +++ b/junkbuster.logrotate @@ -0,0 +1,22 @@ +# +# 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 +#} diff --git a/junkbuster.monthly b/junkbuster.monthly new file mode 100644 index 00000000..44ff3496 --- /dev/null +++ b/junkbuster.monthly @@ -0,0 +1,44 @@ +#!/bin/sh + +# $Id: junkbuster.monthly,v 1.1 2001/04/16 21:10:38 rodney Exp $ +# +# bug fixed, which downloaded all three files to the file blocklist +# +# Revised: Mon Dec 06 10:46:08 PST 1999 by Jon Hamkins +# Hints by Ulrik Haugen +# Hints by mirjamv@theochem.kun.nl +# +set -e + +# blocklist +wget -q --output-document=/etc/junkbuster/blocklist.new \ + http://www.waldherr.org/blocklist + +mv -f /etc/junkbuster/blocklist.new /etc/junkbuster/blocklist + +if [ -f /etc/junkbuster/blocklist.local ] ; then + cat /etc/junkbuster/blocklist.local >> /etc/junkbuster/blocklist +fi +chmod 644 /etc/junkbuster/blocklist + +# cookiefile +wget -q --output-document=/etc/junkbuster/cookiefile.new \ + http://www.waldherr.org/cookiefile + +mv -f /etc/junkbuster/cookiefile.new /etc/junkbuster/cookiefile + +if [ -f /etc/junkbuster/cookiefile.local ] ; then + cat /etc/junkbuster/cookiefile.local >> /etc/junkbuster/cookiefile +fi +chmod 644 /etc/junkbuster/cookiefile + +# imagelist +wget -q --output-document=/etc/junkbuster/imagelist.new \ + http://www.waldherr.org/imagelist + +mv -f /etc/junkbuster/imagelist.new /etc/junkbuster/imagelist + +if [ -f /etc/junkbuster/imagelist.local ] ; then + cat /etc/junkbuster/imagelist.local >> /etc/junkbuster/imagelist +fi +chmod 644 /etc/junkbuster/imagelist diff --git a/junkbuster.weekly b/junkbuster.weekly new file mode 100644 index 00000000..bc07b231 --- /dev/null +++ b/junkbuster.weekly @@ -0,0 +1,21 @@ +#!/bin/sh + +# $Id: junkbuster.weekly,v 1.1 2001/04/16 21:10:38 rodney Exp $ + +# Revised: Mon Dec 06 10:46:08 PST 1999 by Jon Hamkins +# Hints by Ulrik Haugen +# Hints by mirjamv@theochem.kun.nl + +set -e + +# blocklist +wget -q --output-document=/etc/junkbuster/blocklist.new \ + http://www.waldherr.org/blocklist + +mv -f /etc/junkbuster/blocklist.new /etc/junkbuster/blocklist + +if [ -f /etc/junkbuster/blocklist.local ] ; then + cat /etc/junkbuster/blocklist.local >> /etc/junkbuster/blocklist +fi + +chmod 644 /etc/junkbuster/blocklist diff --git a/killpopup.c b/killpopup.c new file mode 100644 index 00000000..7004962d --- /dev/null +++ b/killpopup.c @@ -0,0 +1,245 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#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, "'); + if (q) + { + /* we are now between */ + 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: +*/ diff --git a/killpopup.h b/killpopup.h new file mode 100644 index 00000000..42602ea2 --- /dev/null +++ b/killpopup.h @@ -0,0 +1,59 @@ +#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 $ + * + *********************************************************************/ + + +#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: +*/ diff --git a/loadcfg.c b/loadcfg.c new file mode 100644 index 00000000..f29d6654 --- /dev/null +++ b/loadcfg.c @@ -0,0 +1,869 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + +# include +# include +# include +# include +# ifdef TOGGLE +# include +# endif /* def TOGGLE */ + +# include "win32.h" +# ifndef _WIN_CONSOLE +# include "w32log.h" +# endif /* ndef _WIN_CONSOLE */ + +#else /* ifndef _WIN32 */ + +# include +# include +# include +# include +# include + +#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; +#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; + 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 : + 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 : + freez((char *)tinygifurl); + tinygif = atoi(arg); + if(3 == tinygif) + { + p = arg; + while((*p >= '0') && (*p <= '9')) + { + p++; + } + while((*p == ' ') || (*p == '\t')) + { + p++; + } + if (*p) + { + q = malloc(strlen(p) + 5); + if (q) + { + strcpy(q, p); + strcat(q, "\r\n\r\n"); + tinygifurl = q; + } + } + } + if ((tinygif != 1) && + (tinygif != 2) && + ((tinygif != 3) || (tinygifurl==NULL)) ) + { + log_error(LOG_LEVEL_ERROR, "tinygif setting invalid."); + } + 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 : + freez((char *)cookiefile); + cookiefile = strdup(arg); + continue; + + case hash_logfile : + freez((char *)logfile); + logfile = strdup(arg); + continue; + + case hash_blockfile : + freez((char *)blockfile); + blockfile = strdup(arg); + continue; + +#ifdef USE_IMAGE_LIST + case hash_imagefile : + freez((char *)imagefile); + imagefile = strdup(arg); + continue; +#endif /* def USE_IMAGE_LIST */ + +#ifdef JAR_FILES + case hash_jarfile : + freez((char *)jarfile); + jarfile = strdup(arg); + continue; +#endif /* def JAR_FILES */ + + case hash_listen_address : + freez((char *)haddr); + haddr = strdup(arg); + continue; + + case hash_forwardfile : + freez((char *)forwardfile); + forwardfile = strdup(arg); + continue; + +#ifdef ACL_FILES + case hash_aclfile : + freez((char *)aclfile); + aclfile = strdup(arg); + continue; +#endif /* def ACL_FILES */ + +#ifdef KILLPOPUPS + case hash_popupfile : + 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 : + 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 : + 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 : + freez((char *)referrer); + referrer = strdup(arg); + continue; + + case hash_from : + 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, "
\nWARNING: unrecognized directive : %s

\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: +*/ diff --git a/loadcfg.h b/loadcfg.h new file mode 100644 index 00000000..e567b7e0 --- /dev/null +++ b/loadcfg.h @@ -0,0 +1,168 @@ +#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 $ + * + *********************************************************************/ + + +/* Declare struct FILE for vars and funcs. */ +#include + +/* 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; +#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: +*/ diff --git a/loaders.c b/loaders.c new file mode 100644 index 00000000..71ff3fa0 --- /dev/null +++ b/loaders.c @@ -0,0 +1,2254 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#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, "

The file `"); + fs->proxy_args = strsav(fs->proxy_args, p); + fs->proxy_args = strsav(fs->proxy_args, + "' contains the following patterns

\n"); + freez(p); + } + fs->proxy_args = strsav(fs->proxy_args, "
");
+   }
+#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, "
"); + } +#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, "
"); + } +#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, ""); + } +#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, ""); +#endif /* ndef SPLIT_PROXY_ARGS */ + + fclose(fp); + +#ifndef SPLIT_PROXY_ARGS + if (!suppress_blocklists) + { + fs->proxy_args = strsav(fs->proxy_args, ""); + } +#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, ""); + } +#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, ""); + } +#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, ""); + } +#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, ""); + } +#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, ""); + } +#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: +*/ diff --git a/loaders.h b/loaders.h new file mode 100644 index 00000000..0551a6e9 --- /dev/null +++ b/loaders.h @@ -0,0 +1,103 @@ +#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 $ + * + *********************************************************************/ + + +#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: +*/ diff --git a/miscutil.c b/miscutil.c new file mode 100644 index 00000000..1257a99d --- /dev/null +++ b/miscutil.c @@ -0,0 +1,252 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include +#include +#include +#include + +#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 s1s2 + * + *********************************************************************/ +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 s1s2 + * + *********************************************************************/ +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: +*/ diff --git a/miscutil.h b/miscutil.h new file mode 100644 index 00000000..0a6b95e1 --- /dev/null +++ b/miscutil.h @@ -0,0 +1,75 @@ +#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 $ + * + *********************************************************************/ + + +#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: +*/ diff --git a/parsers.c b/parsers.c new file mode 100644 index 00000000..f56c0b7c --- /dev/null +++ b/parsers.c @@ -0,0 +1,1298 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#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: +*/ diff --git a/parsers.h b/parsers.h new file mode 100644 index 00000000..14025448 --- /dev/null +++ b/parsers.h @@ -0,0 +1,114 @@ +#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 $ + * + *********************************************************************/ + + +#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: +*/ diff --git a/pcre/chartables.c b/pcre/chartables.c new file mode 100644 index 00000000..9055da2d --- /dev/null +++ b/pcre/chartables.c @@ -0,0 +1,183 @@ +/************************************************* +* 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 */ diff --git a/pcre/config.h b/pcre/config.h new file mode 100644 index 00000000..048b8c35 --- /dev/null +++ b/pcre/config.h @@ -0,0 +1,34 @@ +/* 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 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 */ diff --git a/pcre/ltmain.sh b/pcre/ltmain.sh new file mode 100644 index 00000000..50515ad0 --- /dev/null +++ b/pcre/ltmain.sh @@ -0,0 +1,4012 @@ +# 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 , 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 <&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 +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #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 +# 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 /* for printf() */ +# #include /* for open(), lseek(), read() */ +# #include /* for O_RDONLY, O_BINARY */ +# #include /* 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&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 </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*) + 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: diff --git a/pcre/pcre.c b/pcre/pcre.c new file mode 100644 index 00000000..5149f8da --- /dev/null +++ b/pcre/pcre.c @@ -0,0 +1,5151 @@ +/************************************************* +* 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 + + 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 "); +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 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 */ diff --git a/pcre/pcre.h b/pcre/pcre.h new file mode 100644 index 00000000..e5a875a7 --- /dev/null +++ b/pcre/pcre.h @@ -0,0 +1,110 @@ +/************************************************* +* 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 + +/* 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 */ diff --git a/pcre/pcre.in b/pcre/pcre.in new file mode 100644 index 00000000..1dffb02b --- /dev/null +++ b/pcre/pcre.in @@ -0,0 +1,110 @@ +/************************************************* +* 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 + +/* 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 */ diff --git a/pcre/pcreposix.c b/pcre/pcreposix.c new file mode 100644 index 00000000..6aeb8828 --- /dev/null +++ b/pcre/pcreposix.c @@ -0,0 +1,280 @@ +/************************************************* +* 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 + + 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 */ diff --git a/pcrs.c b/pcrs.c new file mode 100644 index 00000000..cd0c94a8 --- /dev/null +++ b/pcrs.c @@ -0,0 +1,540 @@ +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 $ + * + *********************************************************************/ + + +#include +#include +#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: +*/ diff --git a/pcrs.h b/pcrs.h new file mode 100644 index 00000000..ba77c38a --- /dev/null +++ b/pcrs.h @@ -0,0 +1,99 @@ +#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 $" + + + +#include + +#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: +*/ diff --git a/popup b/popup new file mode 100644 index 00000000..07f0c36b --- /dev/null +++ b/popup @@ -0,0 +1,44 @@ +# +# $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 diff --git a/project.h b/project.h new file mode 100644 index 00000000..5f4324ae --- /dev/null +++ b/project.h @@ -0,0 +1,447 @@ +#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 $ + * + *********************************************************************/ + + +/* Declare struct FILE for vars and funcs. */ +#include + +/* Need time_t for file_list */ +#include + +/* + * 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 (System library) + * + */ +#if (defined(REGEX) && defined(PCRE)) || defined(PCRS) +# ifdef STATIC +# include "pcre.h" +# else +# include +# endif +#endif /* (defined(REGEX) && defined(PCRE)) || defined(PCRS) */ + +#if defined(REGEX) && defined(PCRE) +# ifdef STATIC +# include "pcreposix.h" +# else +# include +# 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 "\n" +#define BODY "\n" +#define BANNER "Internet JUNKBUSTER" + +#ifdef FORCE_LOAD +/* + * FIXME: Unfortunately, IE lowercases the domain name. JunkBuster does + * a case-sensitive compare. JunkBuster should be modified to do a + * case-insensitive compatison. As a temporary workaround, I've lowercased + * the FORCE_PREFIX. + * + * #define FORCE_PREFIX "IJB-FORCE-LOAD-" + */ +#define FORCE_PREFIX "ijb-force-load-" +#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: +*/ diff --git a/re_filterfile b/re_filterfile new file mode 100644 index 00000000..16c073bf --- /dev/null +++ b/re_filterfile @@ -0,0 +1,62 @@ +# 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/()/$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/]*http-equiv[^>]*refresh[^>]*>//i +s/]*http-equiv="?page-enter"?[^>]*content=[^>]*>//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/(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%^.*(?Blocked

Blocked due to possible adult content. Please see this site.

%is +#s+^.*warez.*$+No Warez

You're not searching for illegal stuff, are you?

+is + +# http://www.farscapezone.com/wwwboard/messages/1451.html +s/(\w+) was tired/$1 needed more coffee<\/b>/ig + +# I'm sure you'll find more uses. +# Please send your cool additions to junkbuster-users@yahoogroups.com diff --git a/showargs.c b/showargs.c new file mode 100644 index 00000000..0a7cc2c8 --- /dev/null +++ b/showargs.c @@ -0,0 +1,467 @@ +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 $ + * + *********************************************************************/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#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, "%s ", c, c); + } + freez(c); + } + if ( ( NULL != o ) && ( '\0' != *o ) ) + { + if ((o = html_encode(o))) + { + if (strncmpic(o, "http://", 7) == 0) + { + strcat(buf, ""); + strcat(buf, o); + strcat(buf, ""); + } + else + { + strcat(buf, o); + } + } + freez(o); + } + + strcat(buf, "
\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" + + "" + "" + "Internet Junkbuster Proxy Status" + "\n" + "\n" + "
\n" + "

" BANNER "\n" + "Proxy Status\n" + "

\n" + "

You are using the " BANNER " TM

\n" + "Version: " VERSION "\n" + "
Home page: " HOME_PAGE_URL "\n" + "

\n" + ); + + proxy_args->header = strsav(proxy_args->header, + "

The program was invoked as follows

\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, "
\n"); + + + proxy_args->invocation = strsav( + proxy_args->invocation, + "
\n" + "and the following options were set in the configuration file" + "

\n" + ); + + + proxy_args->gateways = strsav(proxy_args->gateways, + "

It supports the following gateway protocols:

\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, "
\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, "

File contents

\n"); + b = strsav(b, suppress_message); + b = strsav(b, "\n"); + } +#endif /* ndef SPLIT_PROXY_ARGS */ + + b = strsav(b, "

Source versions:

\n"); + b = strsav(b, "
");
+
+#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, "
\n"); + + b = strsav(b, "

Conditional defines:

\n
    "); + +#ifdef REGEX + b = strsav(b, "
  • #define REGEX - Support for regular expressions in the path specs.
  • \n"); +#else /* ifndef REGEX */ + b = strsav(b, "
  • #undef REGEX - No support for regular expressions in the path specs.
  • \n"); +#endif /* ndef REGEX */ + +#ifdef PCRE + b = strsav(b, "
  • #define PCRE - Use PCRE rather than old GNU regex library.
  • \n"); +#else /* ifndef PCRE */ + b = strsav(b, "
  • #undef PCRE - Use old GNU regex library rather than PCRE.
  • \n"); +#endif /* ndef PCRE */ + +#ifdef PCRS + b = strsav(b, "
  • #define PCRS - Enables arbitrary content modification regexps.
  • \n"); +#else /* ifndef PCRS */ + b = strsav(b, "
  • #undef PCRS - Disables arbitrary content modification regexps.
  • \n"); +#endif /* ndef PCRS */ + +#ifdef TOGGLE + b = strsav(b, "
  • #define TOGGLE - Allow JunkBuster to be \"disabled\" so it is just a normal non-blocking non-anonymizing proxy.
  • \n"); +#else /* ifndef TOGGLE */ + b = strsav(b, "
  • #undef TOGGLE - Do not allow JunkBuster to be \"disabled\" so it is just a normal non-blocking non-anonymizing proxy.
  • \n"); +#endif /* ndef TOGGLE */ + +#ifdef FORCE_LOAD + b = strsav(b, "
  • #define FORCE_LOAD - Enables bypassing filtering for a single page using the prefix \"" FORCE_PREFIX "\".
  • \n"); +#else /* ifndef FORCE_LOAD */ + b = strsav(b, "
  • #undef FORCE_LOAD - Disables bypassing filtering for a single page.
  • \n"); +#endif /* ndef FORCE_LOAD */ + +#ifdef DENY_GZIP + b = strsav(b, "
  • #define DENY_GZIP - Prevents requests from being compressed - required for PCRS.
  • \n"); +#else /* ifndef DENY_GZIP */ + b = strsav(b, "
  • #undef DENY_GZIP - Allows requests to be compressed if the browser and server support it.
  • \n"); +#endif /* ndef DENY_GZIP */ + +#ifdef STATISTICS + b = strsav(b, "
  • #define STATISTICS - Enables statistics function.
  • \n"); +#else /* ifndef STATISTICS */ + b = strsav(b, "
  • #undef STATISTICS - Disables statistics function.
  • \n"); +#endif /* ndef STATISTICS */ + +#ifdef SPLIT_PROXY_ARGS + b = strsav(b, "
  • #define SPLIT_PROXY_ARGS - Split this page up by placing the configuration files on separate pages.
  • \n"); +#else /* ifndef SPLIT_PROXY_ARGS */ + b = strsav(b, "
  • #undef SPLIT_PROXY_ARGS - This page contains the text of the configuration files, they are not split onto separate pages.
  • \n"); +#endif /* ndef SPLIT_PROXY_ARGS */ + +#ifdef KILLPOPUPS + b = strsav(b, "
  • #define KILLPOPUPS - Enables killing JavaScript popups.
  • \n"); +#else /* ifndef KILLPOPUPS */ + b = strsav(b, "
  • #undef KILLPOPUPS - Disables killing JavaScript popups.
  • \n"); +#endif /* ndef KILLPOPUPS */ + +#ifdef WEBDAV + b = strsav(b, "
  • #define WEBDAV - Enables support for webDAV - e.g. stops Microsoft Outlook from accessing HotMail e-mail.
  • \n"); +#else /* ifndef WEBDAV */ + b = strsav(b, "
  • #undef WEBDAV - Disables support for webDAV - e.g. so Microsoft Outlook can access HotMail e-mail.
  • \n"); +#endif /* ndef WEBDAV */ + +#ifdef DETECT_MSIE_IMAGES + b = strsav(b, "
  • #define DETECT_MSIE_IMAGES - Enables detecting image requests automatically for MSIE.
  • \n"); +#else /* ifndef DETECT_MSIE_IMAGES */ + b = strsav(b, "
  • #undef DETECT_MSIE_IMAGES - Disables detecting image requests automatically for MSIE.
  • \n"); +#endif /* ndef DETECT_MSIE_IMAGES */ + +#ifdef USE_IMAGE_LIST + b = strsav(b, "
  • #define USE_IMAGE_LIST - Enables using image list to detect images.
  • \n"); +#else /* ifndef USE_IMAGE_LIST */ + b = strsav(b, "
  • #undef USE_IMAGE_LIST - Disables using image list to detect images.
  • \n"); +#endif /* ndef USE_IMAGE_LIST */ + +#ifdef ACL_FILES + b = strsav(b, "
  • #define ACL_FILES - Enables the use of ACL files to control access to the proxy by IP address.
  • \n"); +#else /* ifndef ACL_FILES */ + b = strsav(b, "
  • #undef ACL_FILES - Disables the use of ACL files to control access to the proxy by IP address.
  • \n"); +#endif /* ndef ACL_FILES */ + +#ifdef TRUST_FILES + b = strsav(b, "
  • #define TRUST_FILES - Enables the use of trust files.
  • \n"); +#else /* ifndef TRUST_FILES */ + b = strsav(b, "
  • #undef TRUST_FILES - Disables the use of trust files.
  • \n"); +#endif /* ndef TRUST_FILES */ + +#ifdef JAR_FILES + b = strsav(b, "
  • #define JAR_FILES - Enables the use of jar files to capture cookies.
  • \n"); +#else /* ifndef JAR_FILES */ + b = strsav(b, "
  • #undef JAR_FILES - Disables the use of jar files to capture cookies.
  • \n"); +#endif /* ndef JAR_FILES */ + + b = strsav(b, "
\n
\n"); + + b = strsav(b, + "

\n" + "Code and documentation of the " BANNER " Proxy" + "TM\n" + "\n" "Copyright© 1997 Junkbusters Corporation\n" + "TM
\n" + "Copying and distribution permitted under the" + "\n" + "GNU " + "General Public License.\n" + "
" + "

webmaster@junkbusters.com
" + "
" + "\n" + ); + + proxy_args->trailer = b; + +} + + +/* + Local Variables: + tab-width: 3 + end: +*/ diff --git a/showargs.h b/showargs.h new file mode 100644 index 00000000..82b511c5 --- /dev/null +++ b/showargs.h @@ -0,0 +1,60 @@ +#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 $ + * + *********************************************************************/ + + +#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 */ diff --git a/ssplit.c b/ssplit.c new file mode 100644 index 00000000..81246fdf --- /dev/null +++ b/ssplit.c @@ -0,0 +1,235 @@ +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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include + +#ifdef _WIN32 +#include +#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: +*/ diff --git a/ssplit.h b/ssplit.h new file mode 100644 index 00000000..39bd9934 --- /dev/null +++ b/ssplit.h @@ -0,0 +1,61 @@ +#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 $ + * + *********************************************************************/ + + +#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: +*/ diff --git a/trust b/trust new file mode 100644 index 00000000..d1a9fe21 --- /dev/null +++ b/trust @@ -0,0 +1,27 @@ +# 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: +* diff --git a/vc_junkbuster.dsp b/vc_junkbuster.dsp new file mode 100644 index 00000000..f9acd6b5 --- /dev/null +++ b/vc_junkbuster.dsp @@ -0,0 +1,387 @@ +# Microsoft Developer Studio Project File - Name="vc_junkbuster" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=vc_junkbuster - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "vc_junkbuster.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "vc_junkbuster.mak" CFG="vc_junkbuster - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "vc_junkbuster - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "vc_junkbuster - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "vc_junkbuster - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "vc_release" +# PROP BASE Intermediate_Dir "vc_release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "vc_release" +# PROP Intermediate_Dir "vc_release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "pcre" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "STATIC" /FR /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# 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 + +!ELSEIF "$(CFG)" == "vc_junkbuster - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "vc_debug" +# PROP BASE Intermediate_Dir "vc_debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "vc_debug" +# PROP Intermediate_Dir "vc_debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /O2 /I "pcre" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "STATIC" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# 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 + +!ENDIF + +# Begin Target + +# Name "vc_junkbuster - Win32 Release" +# Name "vc_junkbuster - Win32 Debug" +# Begin Group "JunkBuster" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\amiga.c +# End Source File +# Begin Source File + +SOURCE=.\amiga.h +# End Source File +# Begin Source File + +SOURCE=.\config.h +# End Source File +# Begin Source File + +SOURCE=.\errlog.c +# End Source File +# Begin Source File + +SOURCE=.\errlog.h +# End Source File +# Begin Source File + +SOURCE=.\filters.c +# End Source File +# Begin Source File + +SOURCE=.\filters.h +# End Source File +# Begin Source File + +SOURCE=.\jcc.c +# End Source File +# Begin Source File + +SOURCE=.\jcc.h +# End Source File +# Begin Source File + +SOURCE=.\killpopup.c +# End Source File +# Begin Source File + +SOURCE=.\killpopup.h +# End Source File +# Begin Source File + +SOURCE=.\loadcfg.c +# End Source File +# Begin Source File + +SOURCE=.\loadcfg.h +# End Source File +# Begin Source File + +SOURCE=.\loaders.c +# End Source File +# Begin Source File + +SOURCE=.\loaders.h +# End Source File +# Begin Source File + +SOURCE=.\parsers.c +# End Source File +# Begin Source File + +SOURCE=.\parsers.h +# End Source File +# Begin Source File + +SOURCE=.\project.h +# End Source File +# Begin Source File + +SOURCE=.\showargs.c +# End Source File +# Begin Source File + +SOURCE=.\showargs.h +# End Source File +# End Group +# Begin Group "Win32" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\cygwin.h +# End Source File +# Begin Source File + +SOURCE=.\w32log.c +# End Source File +# Begin Source File + +SOURCE=.\w32log.h +# End Source File +# Begin Source File + +SOURCE=.\w32res.h +# End Source File +# Begin Source File + +SOURCE=.\w32rulesdlg.c +# End Source File +# Begin Source File + +SOURCE=.\w32rulesdlg.h +# End Source File +# Begin Source File + +SOURCE=.\w32taskbar.c +# End Source File +# Begin Source File + +SOURCE=.\w32taskbar.h +# End Source File +# Begin Source File + +SOURCE=.\win32.c +# End Source File +# Begin Source File + +SOURCE=.\win32.h +# End Source File +# End Group +# Begin Group "Resources" + +# PROP Default_Filter "rc,ico,bmp" +# Begin Source File + +SOURCE=.\icons\denyrule.ico +# End Source File +# Begin Source File + +SOURCE=.\icons\ico00001.ico +# End Source File +# Begin Source File + +SOURCE=.\icons\ico00002.ico +# End Source File +# Begin Source File + +SOURCE=.\icons\ico00003.ico +# End Source File +# Begin Source File + +SOURCE=.\icons\ico00004.ico +# End Source File +# Begin Source File + +SOURCE=.\icons\ico00005.ico +# End Source File +# Begin Source File + +SOURCE=.\icons\ico00006.ico +# End Source File +# Begin Source File + +SOURCE=.\icons\ico00007.ico +# End Source File +# Begin Source File + +SOURCE=.\icons\ico00008.ico +# End Source File +# Begin Source File + +SOURCE=.\icons\icon1.ico +# End Source File +# Begin Source File + +SOURCE=.\icons\idle.ico +# End Source File +# Begin Source File + +SOURCE=.\icons\junkbust.ico +# End Source File +# Begin Source File + +SOURCE=.\w32.rc +# End Source File +# End Group +# Begin Group "PCRE" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\pcre\chartables.c + +!IF "$(CFG)" == "vc_junkbuster - Win32 Release" + +!ELSEIF "$(CFG)" == "vc_junkbuster - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\pcre\config.h +# End Source File +# Begin Source File + +SOURCE=.\pcre\get.c +# End Source File +# Begin Source File + +SOURCE=.\pcre\internal.h +# End Source File +# Begin Source File + +SOURCE=.\pcre\maketables.c +# End Source File +# Begin Source File + +SOURCE=.\pcre\pcre.c +# End Source File +# Begin Source File + +SOURCE=.\pcre\pcre.h +# End Source File +# Begin Source File + +SOURCE=.\pcre\pcreposix.c +# End Source File +# Begin Source File + +SOURCE=.\pcre\pcreposix.h +# End Source File +# Begin Source File + +SOURCE=.\pcre\study.c +# End Source File +# End Group +# Begin Group "PCRS" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\pcrs.c +# End Source File +# Begin Source File + +SOURCE=.\pcrs.h +# End Source File +# End Group +# Begin Group "Sockets" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\gateway.c +# End Source File +# Begin Source File + +SOURCE=.\gateway.h +# End Source File +# Begin Source File + +SOURCE=.\jbsockets.c +# End Source File +# Begin Source File + +SOURCE=.\jbsockets.h +# End Source File +# End Group +# Begin Group "Utilities" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\encode.c +# End Source File +# Begin Source File + +SOURCE=.\encode.h +# End Source File +# Begin Source File + +SOURCE=.\miscutil.c +# End Source File +# Begin Source File + +SOURCE=.\miscutil.h +# End Source File +# Begin Source File + +SOURCE=.\ssplit.c +# End Source File +# Begin Source File + +SOURCE=.\ssplit.h +# End Source File +# End Group +# End Target +# End Project diff --git a/vc_junkbuster.dsw b/vc_junkbuster.dsw new file mode 100644 index 00000000..a275c02a --- /dev/null +++ b/vc_junkbuster.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "vc_junkbuster"=".\vc_junkbuster.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/w32.aps b/w32.aps new file mode 100644 index 00000000..85caaa5c Binary files /dev/null and b/w32.aps differ diff --git a/w32.rc b/w32.rc new file mode 100644 index 00000000..99cdac26 --- /dev/null +++ b/w32.rc @@ -0,0 +1,267 @@ +/********************************************************************* + * + * File : $Source: $ + * + * Purpose : Windows GUI resource script. + * + * 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:$ + * + *********************************************************************/ + +#include +#include "config.h" +#include "w32res.h" + +#ifdef __MINGW32__ +#include "cygwin.h" +#endif + +/**************************************************************************** + * Language-neutral resources + ****************************************************************************/ + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +/* LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL */ +#pragma code_page(1252) +#endif /* _WIN32 */ + +/* + * Icons + * + * Icon with lowest ID value placed first to ensure application icon + * remains consistent on all systems. + */ +IDI_JUNKBUSTER ICON DISCARDABLE "icons/junkbust.ico" +IDI_JUNKBUSTER1 ICON DISCARDABLE "icons/ico00001.ico" +IDI_JUNKBUSTER2 ICON DISCARDABLE "icons/ico00002.ico" +IDI_JUNKBUSTER3 ICON DISCARDABLE "icons/ico00003.ico" +IDI_JUNKBUSTER4 ICON DISCARDABLE "icons/ico00004.ico" +IDI_JUNKBUSTER5 ICON DISCARDABLE "icons/ico00005.ico" +IDI_JUNKBUSTER6 ICON DISCARDABLE "icons/ico00006.ico" +IDI_JUNKBUSTER7 ICON DISCARDABLE "icons/ico00007.ico" +IDI_JUNKBUSTER8 ICON DISCARDABLE "icons/ico00008.ico" +IDI_IDLE ICON DISCARDABLE "icons/idle.ico" + +#endif /* Neutral resources */ + + +/**************************************************************************** + * English (U.S.) resources + ****************************************************************************/ + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +/* LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US */ +#pragma code_page(1252) +#endif //_WIN32 + +/* + * Menus + */ + +IDR_TRAYMENU MENU DISCARDABLE +BEGIN + POPUP "Popup" + BEGIN + MENUITEM "E&xit JunkBuster", ID_FILE_EXIT + MENUITEM SEPARATOR + POPUP "&Options" + BEGIN + MENUITEM "&Junkbuster...", ID_TOOLS_EDITJUNKBUSTER + MENUITEM SEPARATOR + MENUITEM "&Blockers...", ID_TOOLS_EDITBLOCKERS + MENUITEM "&Cookies...", ID_TOOLS_EDITCOOKIES + MENUITEM "&Forward...", ID_TOOLS_EDITFORWARD +#ifdef ACL_FILES + MENUITEM "&Access Control Lists...", ID_TOOLS_EDITACLS +#endif /* def ACL_FILES */ +#ifdef USE_IMAGE_LIST + MENUITEM "&Images...", ID_TOOLS_EDITIMAGE +#endif /* def USE_IMAGE_LIST */ +#ifdef KILLPOPUPS + MENUITEM "&Popups...", ID_TOOLS_EDITPOPUPS +#endif /* def KILLPOPUPS */ +#ifdef PCRS + MENUITEM "Perl &Regexps...", ID_TOOLS_EDITPERLRE +#endif /* def PCRS */ +#ifdef TRUST_FILES + MENUITEM "&Trust...", ID_TOOLS_EDITTRUST +#endif /* def TRUST_FILES */ + END + MENUITEM SEPARATOR +#ifdef TOGGLE + MENUITEM "&Enable", ID_TOGGLE_IJB, CHECKED +#endif + MENUITEM "&Reload config", ID_RELOAD_CONFIG + MENUITEM "Show &JunkBuster Window", ID_SHOWWINDOW + END +END + +IDR_LOGVIEW MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "E&xit", ID_FILE_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "Copy", ID_EDIT_COPY + END + POPUP "&View" + BEGIN + MENUITEM "&Clear Log", ID_VIEW_CLEARLOG + MENUITEM SEPARATOR + MENUITEM "&Log Messages", ID_VIEW_LOGMESSAGES, CHECKED + MENUITEM "Message &Highlighting", ID_VIEW_MESSAGEHIGHLIGHTING, CHECKED + MENUITEM "Limit &Buffer Size", ID_VIEW_LIMITBUFFERSIZE, CHECKED + MENUITEM "&Activity Animation", ID_VIEW_ACTIVITYANIMATION, CHECKED + END + POPUP "&Options" + BEGIN +#ifdef TOGGLE + MENUITEM "&Enable", ID_TOGGLE_IJB, CHECKED + MENUITEM "&Reload config", ID_RELOAD_CONFIG + MENUITEM SEPARATOR +#endif + MENUITEM "&Junkbuster...", ID_TOOLS_EDITJUNKBUSTER + MENUITEM SEPARATOR + MENUITEM "&Blockers...", ID_TOOLS_EDITBLOCKERS + MENUITEM "&Cookies...", ID_TOOLS_EDITCOOKIES + MENUITEM "&Forward...", ID_TOOLS_EDITFORWARD +#ifdef ACL_FILES + MENUITEM "&Access Control Lists...",ID_TOOLS_EDITACLS +#endif /* def ACL_FILES */ +#ifdef USE_IMAGE_LIST + MENUITEM "&Images...", ID_TOOLS_EDITIMAGE +#endif /* def USE_IMAGE_LIST */ +#ifdef KILLPOPUPS + MENUITEM "&Popups...", ID_TOOLS_EDITPOPUPS +#endif /* def KILLPOPUPS */ +#ifdef PCRS + MENUITEM "Perl &Regexps...", ID_TOOLS_EDITPERLRE +#endif /* def PCRS */ +#ifdef TRUST_FILES + MENUITEM "&Trust...", ID_TOOLS_EDITTRUST +#endif /* def TRUST_FILES */ + END + POPUP "&Help" + BEGIN + MENUITEM "Junkbuster &FAQ", ID_HELP_FAQ + MENUITEM "Junkbuster &Manual", ID_HELP_MANUAL + MENUITEM "GNU &General Public Licence", ID_HELP_GPL + MENUITEM SEPARATOR + MENUITEM "Junkbuster Status...", ID_HELP_STATUS + MENUITEM SEPARATOR + MENUITEM "About Junkbuster...", ID_HELP_ABOUTJUNKBUSTER + END +END + +IDR_POPUP_SELECTION MENU DISCARDABLE +BEGIN + POPUP "Popup" + BEGIN + MENUITEM "&Copy", ID_EDIT_COPY + END +END + + +/* + * Accelerators + */ + +IDR_ACCELERATOR ACCELERATORS DISCARDABLE +BEGIN + "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT +END + +/* + * Icons + * + * Icon with lowest ID value placed first to ensure application icon + * remains consistent on all systems. + */ +IDI_DENYRULE ICON DISCARDABLE "icons/denyrule.ico" +IDI_ALLOWRULE ICON DISCARDABLE "icons/icon1.ico" + +/* + * Dialog + */ + +IDD_RULES DIALOG DISCARDABLE 0, 0, 239, 225 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Blockers" +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX "New Rule",IDC_STATIC,5,5,230,55 + LTEXT "For:",IDC_STATIC,10,15,13,8 + EDITTEXT IDC_NEW,10,25,220,12,ES_AUTOHSCROLL + COMBOBOX IDC_ACTION,10,40,75,37,CBS_DROPDOWNLIST | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "C&reate!",IDC_CREATE,90,40,50,14 + GROUPBOX "Rules",IDC_STATIC,5,65,230,135 + CONTROL "List1",IDC_RULES,"SysListView32",LVS_REPORT | + LVS_SHOWSELALWAYS | LVS_EDITLABELS | WS_BORDER | + WS_TABSTOP,10,75,220,100 + PUSHBUTTON "Move &Up",IDC_MOVEUP,10,180,50,14,WS_DISABLED + PUSHBUTTON "Move &Down",IDC_MOVEDOWN,65,180,50,14,WS_DISABLED + PUSHBUTTON "&Delete",IDC_DELETE,120,180,50,14,WS_DISABLED + PUSHBUTTON "&Save",IDC_SAVE,130,205,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,185,205,50,14 +END + + +/* + * DESIGNINFO + */ + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_RULES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 232 + TOPMARGIN, 7 + BOTTOMMARGIN, 218 + END +END +#endif // APSTUDIO_INVOKED + + +/* + * String Table + */ + +STRINGTABLE DISCARDABLE +BEGIN + IDS_NEW_BLOCKER "Create rule for ""%s""..." +END + +#endif /* English (U.S.) resources */ diff --git a/w32log.c b/w32log.c new file mode 100644 index 00000000..975c5e0f --- /dev/null +++ b/w32log.c @@ -0,0 +1,1321 @@ +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 + * + * + * 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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include +#include + +#include +#include + +#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: +*/ diff --git a/w32log.h b/w32log.h new file mode 100644 index 00000000..85b43754 --- /dev/null +++ b/w32log.h @@ -0,0 +1,96 @@ +#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 + * + * + * 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 $ + * + *********************************************************************/ + + +#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: +*/ diff --git a/w32res.h b/w32res.h new file mode 100644 index 00000000..7fb57b6a --- /dev/null +++ b/w32res.h @@ -0,0 +1,130 @@ +#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 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: +*/ diff --git a/w32rulesdlg.c b/w32rulesdlg.c new file mode 100644 index 00000000..845995b0 --- /dev/null +++ b/w32rulesdlg.c @@ -0,0 +1,532 @@ +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 + * + * + * 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 $ + * + *********************************************************************/ + +#include "config.h" + +#include + +#include +#include + +#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: +*/ diff --git a/w32rulesdlg.h b/w32rulesdlg.h new file mode 100644 index 00000000..991a8bd0 --- /dev/null +++ b/w32rulesdlg.h @@ -0,0 +1,63 @@ +#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 + * + * + * 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 $ + * + *********************************************************************/ + + +#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: +*/ diff --git a/w32taskbar.c b/w32taskbar.c new file mode 100644 index 00000000..62f269d0 --- /dev/null +++ b/w32taskbar.c @@ -0,0 +1,262 @@ +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 + * + * + * 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 $ + * + *********************************************************************/ + + +#include "config.h" + +#include + +#include + +#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: +*/ diff --git a/w32taskbar.h b/w32taskbar.h new file mode 100644 index 00000000..9ba21fbd --- /dev/null +++ b/w32taskbar.h @@ -0,0 +1,65 @@ +#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 + * + * + * 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 $ + * + *********************************************************************/ + + +#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: +*/ diff --git a/win32.c b/win32.c new file mode 100644 index 00000000..2252dc1f --- /dev/null +++ b/win32.c @@ -0,0 +1,273 @@ +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 + * + * + * 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 $ + * + *********************************************************************/ + + +#include "config.h" + +#ifdef _WIN32 + +#include + +#include "project.h" +#include "jcc.h" + +/* Uncomment this if you want to build Win32 as a console app */ +/* #define _WIN_CONSOLE */ + +#include + +#include +#include + +#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 +#include + +#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: +*/ diff --git a/win32.h b/win32.h new file mode 100644 index 00000000..3011f478 --- /dev/null +++ b/win32.h @@ -0,0 +1,71 @@ +#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 + * + * + * 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 $ + * + *********************************************************************/ + + +#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: +*/