From c75584ebcc79f939fb4ec9c8f842cef6692640c7 Mon Sep 17 00:00:00 2001 From: oes Date: Tue, 15 May 2001 13:59:57 +0000 Subject: [PATCH] *** empty log message *** --- Junkbuster Status.URL | Bin 0 -> 56 bytes Makefile.in | 281 ++ acconfig.h | 178 ++ aclfile | 102 + amiga.c | 234 ++ amiga.h | 88 + blocklist | 1060 ++++++ config | 207 ++ config.h | 195 ++ config.h.in | 194 ++ configure | 1968 ++++++++++++ configure.in | 257 ++ cookiefile | 67 + cygwin.h | 63 + doc/USER_DOC_IS_WIDELY_OBSOLETED | 0 doc/changes.txt | 991 ++++++ doc/gpl.html | 567 ++++ doc/ijbfaq.html | 3186 ++++++++++++++++++ doc/ijbman.html | 920 ++++++ encode.c | 400 +++ encode.h | 65 + errlog.c | 407 +++ errlog.h | 80 + filters.c | 1529 +++++++++ filters.h | 106 + forward | 97 + gateway.c | 287 ++ gateway.h | 69 + icons/denyrule.ico | Bin 0 -> 318 bytes icons/ico00001.ico | Bin 0 -> 318 bytes icons/ico00002.ico | Bin 0 -> 318 bytes icons/ico00003.ico | Bin 0 -> 318 bytes icons/ico00004.ico | Bin 0 -> 318 bytes icons/ico00005.ico | Bin 0 -> 318 bytes icons/ico00006.ico | Bin 0 -> 318 bytes icons/ico00007.ico | Bin 0 -> 318 bytes icons/ico00008.ico | Bin 0 -> 318 bytes icons/icon1.ico | Bin 0 -> 318 bytes icons/idle.ico | Bin 0 -> 318 bytes icons/junkbust.ico | Bin 0 -> 318 bytes imagelist | 34 + jbsockets.c | 476 +++ jbsockets.h | 72 + jcc.c | 1224 +++++++ jcc.h | 96 + junkbstr.txt | 206 ++ junkbuster.1 | 871 +++++ junkbuster.init | 149 + junkbuster.logrotate | 22 + junkbuster.monthly | 44 + junkbuster.weekly | 21 + killpopup.c | 245 ++ killpopup.h | 59 + loadcfg.c | 869 +++++ loadcfg.h | 168 + loaders.c | 2254 +++++++++++++ loaders.h | 103 + miscutil.c | 252 ++ miscutil.h | 75 + parsers.c | 1298 ++++++++ parsers.h | 114 + pcre/chartables.c | 183 ++ pcre/config.h | 34 + pcre/ltmain.sh | 4012 +++++++++++++++++++++++ pcre/pcre.c | 5151 ++++++++++++++++++++++++++++++ pcre/pcre.h | 110 + pcre/pcre.in | 110 + pcre/pcreposix.c | 280 ++ pcrs.c | 540 ++++ pcrs.h | 99 + popup | 44 + project.h | 447 +++ re_filterfile | 62 + showargs.c | 467 +++ showargs.h | 60 + ssplit.c | 235 ++ ssplit.h | 61 + trust | 27 + vc_junkbuster.dsp | 387 +++ vc_junkbuster.dsw | 29 + w32.aps | Bin 0 -> 43740 bytes w32.rc | 267 ++ w32log.c | 1321 ++++++++ w32log.h | 96 + w32res.h | 130 + w32rulesdlg.c | 532 +++ w32rulesdlg.h | 63 + w32taskbar.c | 262 ++ w32taskbar.h | 65 + win32.c | 273 ++ win32.h | 71 + 91 files changed, 37668 insertions(+) create mode 100644 Junkbuster Status.URL create mode 100644 Makefile.in create mode 100644 acconfig.h create mode 100644 aclfile create mode 100644 amiga.c create mode 100644 amiga.h create mode 100644 blocklist create mode 100644 config create mode 100644 config.h create mode 100644 config.h.in create mode 100755 configure create mode 100644 configure.in create mode 100644 cookiefile create mode 100644 cygwin.h create mode 100644 doc/USER_DOC_IS_WIDELY_OBSOLETED create mode 100644 doc/changes.txt create mode 100644 doc/gpl.html create mode 100644 doc/ijbfaq.html create mode 100644 doc/ijbman.html create mode 100644 encode.c create mode 100644 encode.h create mode 100644 errlog.c create mode 100644 errlog.h create mode 100644 filters.c create mode 100644 filters.h create mode 100644 forward create mode 100644 gateway.c create mode 100644 gateway.h create mode 100644 icons/denyrule.ico create mode 100644 icons/ico00001.ico create mode 100644 icons/ico00002.ico create mode 100644 icons/ico00003.ico create mode 100644 icons/ico00004.ico create mode 100644 icons/ico00005.ico create mode 100644 icons/ico00006.ico create mode 100644 icons/ico00007.ico create mode 100644 icons/ico00008.ico create mode 100644 icons/icon1.ico create mode 100644 icons/idle.ico create mode 100644 icons/junkbust.ico create mode 100644 imagelist create mode 100644 jbsockets.c create mode 100644 jbsockets.h create mode 100644 jcc.c create mode 100644 jcc.h create mode 100644 junkbstr.txt create mode 100644 junkbuster.1 create mode 100644 junkbuster.init create mode 100644 junkbuster.logrotate create mode 100644 junkbuster.monthly create mode 100644 junkbuster.weekly create mode 100644 killpopup.c create mode 100644 killpopup.h create mode 100644 loadcfg.c create mode 100644 loadcfg.h create mode 100644 loaders.c create mode 100644 loaders.h create mode 100644 miscutil.c create mode 100644 miscutil.h create mode 100644 parsers.c create mode 100644 parsers.h create mode 100644 pcre/chartables.c create mode 100644 pcre/config.h create mode 100644 pcre/ltmain.sh create mode 100644 pcre/pcre.c create mode 100644 pcre/pcre.h create mode 100644 pcre/pcre.in create mode 100644 pcre/pcreposix.c create mode 100644 pcrs.c create mode 100644 pcrs.h create mode 100644 popup create mode 100644 project.h create mode 100644 re_filterfile create mode 100644 showargs.c create mode 100644 showargs.h create mode 100644 ssplit.c create mode 100644 ssplit.h create mode 100644 trust create mode 100644 vc_junkbuster.dsp create mode 100644 vc_junkbuster.dsw create mode 100644 w32.aps create mode 100644 w32.rc create mode 100644 w32log.c create mode 100644 w32log.h create mode 100644 w32res.h create mode 100644 w32rulesdlg.c create mode 100644 w32rulesdlg.h create mode 100644 w32taskbar.c create mode 100644 w32taskbar.h create mode 100644 win32.c create mode 100644 win32.h diff --git a/Junkbuster Status.URL b/Junkbuster Status.URL new file mode 100644 index 0000000000000000000000000000000000000000..6c95de6d7dd1d98bf88e8084020edb372acbfdd1 GIT binary patch literal 56 zcma#{%qvMP%1bQ?&d4t+NiHpkC|D9W#> L)J-f(FJ=G$T<;X} literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..e5aa250604fb73ae2bedf554aed994cdac982f02 GIT binary patch literal 318 zcmZvXF%H5o6hmJnB$SCxtT1xSGBMIMw~5pP^bClhbH##0rC=vy!-?%L|No@~I-S1n zF)ke(?V^*j*s+sBD*8_b&}A5^NmY_klDm=1C1+Qnjw4G$7*z#`Q7$$Qs@)55ERNhG z3fvN+5+TI8BJ-$4f!8$h+o_wLZtxS94@|Gh=K>FLo#B0l?Ib_wFMGI7a9d&C{PxN( D6JJL~ literal 0 HcmV?d00001 diff --git a/icons/ico00001.ico b/icons/ico00001.ico new file mode 100644 index 0000000000000000000000000000000000000000..a01ccfcc21be40f9544ec56ece51b1ef1959e311 GIT binary patch literal 318 zcmZ{fF&2a%3`7UCUn*O9RC`R0vd=Q7;7FEsI1{jQ1DPKZ2ml0*loDj$0Bj;%nM@B@ zsX%jmlL~O6)&VL*wAM%!x=-}3h|Zyu1hJG%pwK21Xh}v#$pi0t%(OjZA~H5(XXoMl e%*-!vu(SPuYX{B`-?|L1{Qo~w?b)X@I(q|+urs9q literal 0 HcmV?d00001 diff --git a/icons/ico00002.ico b/icons/ico00002.ico new file mode 100644 index 0000000000000000000000000000000000000000..b7de068bfb0955a50c032c7647a9fa430e962bbd GIT binary patch literal 318 zcmZ{fJr;x@41@=Ed#P-fm&)fUIf}KX;7FEs>Vz_o>GEr3BW8eRLP8h zFBPa=pQHdBD8)f#idrkFM(YEuDPz!8k|3I80!AB9qA3|WEIXccr>V0J8X3K?`8oSI bZ@ups_ntrCnE2L@N8$h9OucKJ_Gs@Pk+?EF literal 0 HcmV?d00001 diff --git a/icons/ico00003.ico b/icons/ico00003.ico new file mode 100644 index 0000000000000000000000000000000000000000..99e09803c6d75c852d24ca2ec61fd723f5568196 GIT binary patch literal 318 zcmZ{fI}QUO3`B?B^r6~zk*kPPa+K6Q1xHGmj?7@9NKs9l-yzjv4rng>pH2wddx%XS=J>L5P>P|DI literal 0 HcmV?d00001 diff --git a/icons/ico00005.ico b/icons/ico00005.ico new file mode 100644 index 0000000000000000000000000000000000000000..db9bddf7afda264305923365f94db5315f48e554 GIT binary patch literal 318 zcmZ{fF%kkH3`HNSm5o%kGO3(BCFkK39LdrS|A$$tH6i~cfeZjio^!_bO7Jih?i5Ah zDuq7vOe$zm>w;7%y?4uDzRGjmR=cps dk2CRoI#J;Bg!f%V5Cogm$V4Jjc|;zQvuwyIIFg|mRx|oc)`97o?cujlV&t6VcqHj&l6DH2 zbVjAI^hlb-RBHj0QezD0##~c#x*{32EZS-g6QbZn;vux-oIFg|mb`Mwv>cI4y4_`=T*D;`TdhT)$`%|r6}Lbw6W@B5xhm|7Mm^265M7}kbNN`13-|cl(4-5JWPcvSrNEO zp-(-N3R={Ma+fT`QnEmiZ8-5(j1wguoZ5<4HFyCn_k2j_(n|}csrBbB>{p?N(pNp zU~3odOd_yRh1%=CQb3ndhN&u2Yn6M@`lU4|q2rdzM{&fMryg?7_PDyb9z-?Y?i|;i oSNq`Gz0l;vw4L1;~mrO#lD@ literal 0 HcmV?d00001 diff --git a/icons/idle.ico b/icons/idle.ico new file mode 100644 index 0000000000000000000000000000000000000000..99470b54e0402ab4b18229f78ee0eb5121583796 GIT binary patch literal 318 zcmZ{fI}*bn3`7@_-c)YGsPg!foF%1B!I4s?BfH2R7fFP)PawnxNF1dU$hHKmB10>c zk#MI1ed;f103EFbs7%p&Csi2JF@`b*hn6JBW|e@^4k+2(+zr|HC%szGzG$<~Uea|& i%yY0J$m3`Iy63p}{QzDI-+GH^{Qo~w?cApx^?m?J**^6E literal 0 HcmV?d00001 diff --git a/icons/junkbust.ico b/icons/junkbust.ico new file mode 100644 index 0000000000000000000000000000000000000000..41aafd0a203a7c7e451b068f5a08b265e775b72b GIT binary patch literal 318 zcmZ{fyA8uI3`9?`O957u)-E%qM&kekyh_Rx0q8r?fs4cxd5;oBeSpHzT7&FafQQJ? z%El;|seldrCmo=p_XL$G%#2hah9g25gF{OaRCgobv=d79@CZkZ{X;iT`VW27*-M7b i$azf~l01IYuY1mW-z)H1_|_?-^Z$3I+IOFN)O!GjlywgP literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..85caaa5c571734407b6ccc4b68904d88032d2b26 GIT binary patch literal 43740 zcmeHw37DK!mG((UfFK&&cWomgL6+L9ni+*!zUr>z>#C-f?gXP{(&>aCB$x$IQG?64 zpu)^Jqd2YzD8XH4aYu2+4aIHTcieTxeFhcn|9#K7_gku3{PRD`Jo7w%L8t1z@45TE z=bpQLpNPl={+5>P4?k0%B3#GgZ(8Q1hVP}N6^>tXwEH2)Un|l$eap-fCmMSe4xGQZ zd;h*I8}{tpGP`%r&MoKe+%epB?zUlWI62G=FI?DiQ9gI--Ua$S5kXDhdui#2DBR3( zakwXfI}U%8Ss|dE!h|TwLB9%_NJR| zz?a;FkNe_}o0o1{TDnP&UAp-;{C~qu_I=aX_f5*fFTR%;hPjWm?;FIv5xnwoJTBf_ zA1w0IwMgp`_IJ=1F_Sd%A?M}jhkow?nF;(YE!_owA66g9a%AbPkmHU!4*#ywQeQDr z_AAHy+;L^Ua@{&6Ue@8`zW9Sqe6Q56brbfr{J&Q@_>lhwuoAxy9YV`_KqR)?(JqYTZNE@Kq2Z|X`X|5<5{ z2@5CgM}OY3|JYbLj_VxLJQI*KeZP9l&mCFz?E5SerxMs~wTKQKx=PEQx`Rb|=qf8v zU*OJZ;K;u#&3y-#JqN5m*6vr2wEH8+{M>P6e+;!UK5WDK#iA8CN!v8FGTkWqlYEi; z?~|-}m;ZOA!FO=kf1DZlBRc2Ek+MH(%+DQH_9&$ZM$f{+*H!$+4=Z6g#v1#CS1w*{>P%^S`C+QP5uZxPD-|$?GbwyP(p@BcJ?cc8^hA z_ouaUJ~>v7<7K~Qr0kCw^YcGm_9#M>lB_&*(pC6>Vx4_sz*Tqrz0SG$t)*}7m4-v- zs2lxAdE}Gbg4td9XK433#>#QL?2nP}V~#cf$)%-L_*-1YkH{4=D|_SuIeYKK)QFL_zude*7oEaU>9l3 z%hk{X)<|~2&vum(`72EACg9iF0Ye!budFtk@MY;Zm}&>c1_+O>f@#PcV7Xo(PlSu@ zU=GY8QpC?|kb}C0!`fkq@6nViDM!oI;0>FQ8Ti_V|9r^{_-odtQI_vC!rzHppXa{W z=5}kSN6WQqS*PdYk1dw1>Htb>2SR4-J>XBmZ;|K7YY{VB2Yp|t@=t_B6(Q08R>fJ? z%eU?SxB9YNBX+a|UswOXUo77*uF#rh+c#bGy0y!d80)x+T02XN_PRePGlLr4jkd5A z;qh~5?Ub}-plxIdEn>H}5V8~K;|H`4?n3J@9YGDUTlI)~)_<=519A1xa@cy<%hP@Q zpuBo*6(R2dm(-`rw*U?o6Zo@!x=Z6sui=d9YxYFbl-3v7e|#8g5Y9PcVO)m3nK>}J z=6R-}v+2Yw(-gnk%m`8GKU&04aQ~1cJ|+E6oeOD9V2T z&>KXYAM;6R|5?Ja>-T;ua^o-T@0Rb0d=q~^gK2r|@|yvd73;xidnh?9-i%b2@2! z4$7rY=DzY3r0(PuOG}p;B}c4yh~rL_jq)%#1>Cb72fI+Yv*kp|$z9|$a0j6SPQd86 zs9I}L9^z!alW~EQZMx+C_*NPsjfPIl&3cVv`8Xx)@e$;*VqG z?V6U1rey}&@j|49dVL@lI7y^iWvfm$J0{zJzl%`z{$uhNJNcZ-pCAo{%#x<K}&_Jy|AV#a39GaI0Dmvp3$;*Qxv393g@3-cv{Xhx= z<%1+JRw<%T=92EBf#8^|QLE*;$nn$5 zt$|lJ(QyLyHj(Wi%BO*-Gx7+qNW`!+8?+smm6ILVs&_n?lT#en9E4%7-VK5_a)*gj zhQI#9CRkDEG z%iP9cSR3^Foi=MWE00vD8$&sHltT4tyB>rT%F7vw%)~+kIa8rpwZ4%e6>jw+=zg_E z=OkJ%o%JxNY745fn*itr{Xth_ZlLoK=}otqefUAaqL?nr1RXbTIizW(TN%PE081)vL2ARAVOx(wnW;3FI=gNEuAG)nV## zS*Upe?O+p=lFLy6FpPGC&OBy@bWV3>)PDi`g6=TTl;?_=Rna||rF02%I=Z^8sc8+Z zEYObt&{&xBTtzmkyBCB(T_q;vY( zn3=6MGJr}M%)(+QODHQCpd+aqp&V8OVkl22Pjwtg6$lkDpNpX)p(2NhNUB7r1icqS zWkO{RK#^31P(_}QfF=n|LS0g71|7LI8*V06h3X_$ZLoGrHH@DzpH>I#jNL zgId1}l|!t7VTV{FsJE!&00o>$6Kc(=BD}cNl#3N*vnnz@+ga#;?Vi`gw#kBODGFd^X!^36q$Vcm=46^G8F{XAGEtSRJkL3q zs!C2SGbef;oOyY^b23$xg1o>vnW{=rUg(@mRiz}CJ10|BDPtLo@uD?`9aTM(8TlK9 zpies?Yh^Mkf2&C7bxSoPFIA))AzAqclZn+$H774KsRWjnmz$i^LDho1!h}3flvgS+ z+wIhYUTI2sSyOBCj=|8+4kKn3UHkFdJ4G zWV0&Qsath9+%-9*?slhLRmIe-%k}1?%93q1-L$ z2TBHpg`<$1l;~$wrV-4|bf6v+38~2!l=AHX!;0mqE?-oliQzu!p+Q3#!S`D;sel6c zvf^fzFd7S|iOCJ+(M;-tZco)WnrcSAs_;w)rh<=LePFcznuRpo3L9xECtp_z6*dTZ zo7-4{LFvE%_=du09k3;7n6{f8qYCmZrL-Z?)-$*ywcNgV+BzdtUFCgJ}dv>C1IPG4uot@{?p4Q z;k^7rVeJ>l(^OP&`Lg^}sd@+IMj}u7N%>h!U=9Eqm!($7$}c=V)9&}-S)ew+PnR$HN*cuID? z{LX;hpof0j=myAI4^s#E{RrM0Kvm~>ppaqJyRCk!UJWt*AfD&m5bCYoncdu|_N$hd zs;o3r4e|{g7|?2cAoDe>D9}SP3%*indIU^Dw(HP-<8 zhP^o_#}OE6qd-yIRb86w?qq!yo53IV24k)F!Z3!u!3L|O*l9nVPG0P#DOWT1siFd;z%;}iC2vY2oQ1_xQyd}9RLxMy!qTZLsD?@c&q+gZ4)s>7n9v6bO-I%|45flJ6`V_gMVV3% z=1QauvY4Dqr_kBXtSjwoSz1a_bwpEdgx-`55gt_o?1zntV(BI5wi;$rW??&o3S-b# zn`@>wRqJfhCV|1Oo#KLq8FtxxUOFizZ1wt)w}Q;3$eK##FG`nA{SQFoTaQoa4uVvOO!)BM)Dsv$S{}^XygVa8 zL~4p_p%!96o*47rcWiGItpOAbqi zf9*lkPQ7Y#oE&Bhf8%l5B-L)$&-8MbHTyP0EWr0|P#4PB7qKqPVt9 zS|U+@hZ%pRQD~WICMPddrqS)pHj!YRj_07+{=vu54VoyA={TN(yi7T)V6uMm&?Z+K z0Q1(6tX!kWEZU-`Iu8|ctqJ+1<2+QyYZV$`z1{p3$62{~sE_N7#Vl)ts>th=Qfq94o0K;w=Z2>dwkmH_mc=!DCimui;x4Y(X{TElRmTawOD1-m0wH(d}S+=#oSQOE~gT1vsZ+nz`-uc_O{DZLL2mUvW-b+|S8Zox2YWo|mu1F5Md_ z$k$`UycFdd4ytvq2{VIjns256^;ni~r9ksrky}nB(;3F=oh*6yVYloLTwt z3Ymtz(#0ysiKpb&%g^Y>0(KjFAKXQYmL#Mam%JN&4Y_;9CQblf4 zpt{Kclkz(PS|Vtgzo)}W0*!HrE*3i)AvPoRw@Kz@g>yUMf~+Lq3LL}Z5wX*}lw?&5 zIbUU2ZCDp7M$mkZq!TNN1MDIphf%tZBCdNCZxscHqOq3fva!aa+6;Y~EXHHV zb!r>9DTI;tSUPPn5rfp7>C)*pMy9*0l-^9ggK58RwxX%B@!rFsHMcSjEGzePV71oi zVsT`8;MPr`XYaLAW~#$zaKpqk1)!T^Js3^kK?)~!CNXCnft+kXCRPeZs9_HqBpB7@ zVa{D^aqIE~BnBmdT|nJ!g<|0;4~6{3Z3AMbcr4lz&dI4UrW?L_IW0zX7rG!BLtLq( zV=5ZQ#K9IGiLzv5VprA#qWH@uz)IHGJ*|#POlm?rsgB8&GCzkUkFYh>W@}|#p)Efu z0c#T^j%q$5fxGrfrjU^{6O6SN5>RecBc|guZcbrqhR($(t@*m44m^=5bN(hSnV`$b zub062N5Zk1Rks0@3bBc*Pi-Nym9-U2Y$78w(oxXwxS%y+rlU~8Dnt(CECmyr%PgQS z;_nTy(a;UCWbD>$*vvDTP|i`(&+RG(1K*{1o$IRmSylG$0?oJWUC9O$G)gk&%OOaJE{U4%A_ns#M$} z9eiS{nX()8hMbgP_%w$rOLN4rn%k!jiE==k<@IuzMyc&Q5u3VA+S-HtcJZv2%hi`Q zy@W4yub018GT1aki@_#JHB8hc>p2_B-+PgEXLSBc3AC?JUhHL1tuq~4jWV(l%1b<1 zt=EIuel%TBfh?NRm0loenrK^tNDcxo^#Yu%x$bPi7r?&EvwduoxGZ|#74R?jym3Lp z?TR4;G@wvk;dwK9k~}&{D6fooo9{-e-UtAFE0kAxfmjh+4+`ZfPeoeY(jCfcJk#xC zy}#P<%hcB9L%G`XVZWQ^8A2%6L_Ch2q?UXvSrEC_i)gw=Wh|K2dKssMonffu=epN* zUW8jvSP_WIPt`{#hdd9>oGgCTJE2_f>1F#0nqFKj)^Y*GHL+ga=>5A%ii?6BZF$de zGl;@-&2qiGX{FSAeppk*iQ(#B6ikemr~`S2f>=qY&-GKel6NX&%SLV+x+3pV5J!3% zZj&%0?^dV|)2`=0jN9)~&`Q~%7_{H3XuD(4F+U9T$)y_97nw*c|Gf zcvfy!2a+*UorPieNp;R()q!1nwgtO2FP~Ddw;5Xl1^Ki(8m%VIsC`C%!v<|)&huGy z;9!D=T$X=#f;F7T`<(vv)7DA(yty&S;g%R|gD)u1Wk{F^d{JHVC?8G*zN9XhvNOg0HC)rZc9?f_3Dts~e-VU`qQ9b)d3?uG=!wGD1b( zqD-SVt8uXxVPWjs9&|;ea8ADCVV?{wG9~l!T~8*Hsazo6Qx2!Yc-+py5uEvGVx|D#z*MupRf5); zJCOif_3Ld)L`TpV3@wjPey2n?T5vKCAbzhzZF6GVKz-4Z9KnRuHYc|=NUA1Yp=9#t zmij{v3FQdo>_mv#Z&8q|m6_^RHzy5C41Gr`k+k{DPcD?Blp3__(?NY>(i>u0qudyS zq3{^<)x)YPyjgQ_D#Vq^om2v+Y~t~NafWhdB@!)2lY+7LE=pKqj83((hx}6a(8N(x506afL*+l!) zhWk*Wee9QMnWJ&JUnd&wikywkG~If`Q>6zs!yPnRZTdc)D)kPjtqOw=6`Vg;jo zlSi2TXVDnfC_uPhCBuDp1mS;{jfuM!xY$wgY#d_L7AKAK?F|0>&(n{PUVTV&A7$A@ zTabn#ZmGKoMJ0hD?l`*2VFunb)S2OmV#Rz)QLgJpgJ}~DRHhZ5?FMrR9LFnKiu-ZA znZc6f28H6;STlp;p&J#9Ct^)BPze>ZJ$pO(+{|ECV@6?E47#|6Y|&(BD;VzxG`R=c zQ83<}Xl9YISq1x8Z07bOGnPfh&QcVnBF>`I#!ws?>na`{+G%Eysh(oKh#3H~HBfK{ z%PMGp{=7^xi@eP#Lo*Y_=4|L@7Wtc3B5uQ4LrvMFFz0TpJ3lj$$0)4pYlMBpJoX6b z)OfCur|t5&aR6D9L%TUxSKrzL#^0ViYXMZbMyWOg1lj40X9N zG$$9h5G*@}X5|Tny8IZLk-dh_#N~mbRr?IY@LTIJq1Y$hZ;*?>rD$0W80z9Tv?LcA z>Wb6QqFiLCi{H?KTx@73Y{Yek!`x3YSbHoIfD_+Ojs+7niqqkj#6+T2agzKgF_EZQ zoH~DMOeAU-C)A&2L`@fJnME9AKWLaKVnP|YGy!3zj?FLNMVzko-rMy~7q+3{6?ul? z%%fW`rhHkR8RNe36if1~81-G2;ziyD@6@|~l{cR&!oGcuVXazFok1#!*c^VYLGx7{ zHy~1w=NWWqFZdZMMe}y4c^D z8|J2-bD^~a0$S3@R}iS)nG5It7NFeq1$HyIji!bHvmPNFDpb|GV1wcF}#RPmC$#n5zi z-sV7;9VRFl-uqn?x~W7`6ZHW@leyBI`1o!luO}rx%3tm-QBFQam+nPis(2F}xDlks z`#w$w7Rh-Ft0 zj~ineFqrpWRxq(>1H1k!is}6jtmHcT7FPCG6(3-B)5TuA!(q{XP4SQiLnE9P_SY51 zMs{x=c9=#<%laD%R|ox0Jo3|a4dt5=6A%A3vHF%W?G85(VAL`!ombtWI3~>)BC#;8 z`>Hw%`nD3VG#j0^-f^M%8_IVSp0DBzhQD^j<$+MXYY_})YPy)rWr0w>4{&CPGXyTm zOf4fnQ4FUCA}lLE^>W-6(0tZ%@-r_OgL(OR5^US@Z>=D|FxX$$z=`~#{8BMifUR0t zxHzPnki~J-z(t7jxk@0lSj6;aerpx^Z<9~MlX9zaI zYBl+d4~MPYj%Q?Qb@{CiCkZ#?HV^lwQKpvmKzEkj z!9J9z9o7qi$8VxmLfnmvFDBHBvO-~WD}N>;Q!mL%1!JTvM<~*q>1)Yq!s-=S<-%;^ z#71WZGke=ns80&+tRgnlH}3Iq#onf>^_m>%3E#kDUv)W3$zW!-znPKO2F<41q^LLK zXeCimx(eYoTH+iAvc?CUY`>X$Q;zWjJCx2@dBsLEfqQ6o^5HJSX60DVj-|JelRNu> zXR2N9q+5`AS?fKe@PZuY<>P8d)yZAGznG`SX%yvd%3$RpRnU!+++7J4A{hu+8p?8y zRZ{B>X9vCM__8IsCqI}AD+vR9IUf4$fy%4p5^b5#C)C`7l%gIQr!m!gu+lmM9gP>d za6;KUmxG-mWT-{VucJ^$$x3C8B*XUD3dlUD3qeFTz)Co>5{h9T2t$aoJiKwu!K{(N~aZ z`kYcDqnlfB$txEh-9tpSp&?T^KuH)P4m^@P5c6vQ4 zk5ZSL!sp}+bw=~}yqu|kTWP?;an;y@B5;5P7dUsCFHqMo(dML=F4NP6T+psDzBdTFOp^SDxhBTmjrQEyO7=fpvd?0rHp?TW%2 z;h>k!jRPGap^_f2BsE%etx6-rO`Y?U>a}!!Vl@H^s_J|t*n@Bw3uD}T7uzb4Kph7O zRA3oB*T7K$-N%YCe zY9r#RrjJc+;Y*CewixHODZi>lpQ3zk(BA0oSNfIdrz(N9;vm$69e$bKbmG&Lovm^q zD@7wvWaOaIti%zT=Ql#R)WUW?6D4Hy(^pBOH-yQhdwI+b%KNzra;2Qx^aN4N&r{HL zsqA_I2e!*hG`f(-;p_Q|rMCE4;xACR-Qkr6TwXx1I(WS>4xt-x$Zk_jXklNjRK9^z z>aJeV_gvwB`<0@Iiq>Xw6*7c1#HW1u!t1~)6}kWr{9te-;3h0}q1 zpoI01>y6js;ws8u#vd{Y<@H8!;)m5@J>aaD0i#lXg9)Gv+1zn0S(}%Z{Tq#PBXJwo zCf%)ivnSqUbQ?_)d$D$qDwH>S)Izcz^Hu{f>S5!y+mI9E`oT6m9jq4Hv3GN0bJ(Gl z_44*rQm0fxaiU7!X(+dC{rxH(K;D(c-5NKVB}S2V8}|q5?>!^zSpB`%1ZX@br|PW0 z_c_0*Ik~E~8;tQyPkY(>4NEr!?PMP?X1UtdesZJn3_GlSj6{?(nk)?s7hr z?>8J6uN1IxeKQ$E+fHa`tNWHC7(u74OI4~TQ4+T}3jID27z~$h$AoU2MB#z^PBNlR z{lq3OGWcCbVwJIuVb+_2pr zDjY}P9#|+pas={%g+(`&#eJ_(ejLS;zO$RzD*x%ICbMtL51DQ96NloSW?Wng^3ym5 z&GgXEmowYtXO8oil{p;CFOuLex=D?lv0tVbeK-xH;(uT_uZB)?k4bwvy$mV{iT zfVJ^k4V-D=`3>!;#J*Vd0E z5<`=A8J0#?LoHOh)VgP5)N!(i_BcpGUr-0)NZ3XfaaQhbc&syWau0(N372~s6wP%D zaxX(t^IW;Nf$aR&6AN-5gOU>lxo_mxJ&mIx_cMsYzfT-$`~HU7Ml;5y=-L#_NO^#f zI+iCE=uq1ai~@_6^RR3Apw%)!eZ)q3RvuyyT7GTNXl#xi1(K6>#;BG{q`e>yO%QQD zD{{QUQN9|MHAftvcQ`jM(d(?-k@^!1j|v&dez-v>gK6Am#Hee+NcxGZrH)f@QSq}O zq351raJ$1@arcZDQcwh^8kMRZFzD2$c~97@vh8(x!3SzB<2gI-meBDOfR@UdK(#@$ zJ+hHV(oV{G@Afz)rxrkRq|L9EaIQB@%n+qy5LQwn`z|YG1N8zzES!^y;R(AyCJjnY zTJmzb3jsYH_uSn2EDo>#g~Rda6rk3dteIBiFCB-3;Nl*vDu0>>t?-dChxPm6yl`KVrMuUk8MhAys2|`&fNxV6Xv=le&*2vh`>?NW);3jy_w#&02OWfNL736&$xJnNGmIaYG?XD}npT4};lY__$pL z8%07R+a0rRr?I=CTAKEY%y^RaRYa-sZ=?63p}@#W>By{{6%p}jIMim>V8yDqt*Vb! zW22LvG3k<|LhT#j560jDCVGmHqdV$*U@Y&3q}vIqdk!3WqK?vRoxYUlZ*zjvnu|zy zJljZ46Rgc;?r7VkpO{5RJ+2Xl3LvMx@pP*(@GwxN0eXMo8_Hj0}xZ6*=E( z*u#%lH;;3Es#8;VvXY;du&TE@FMMKC$KC95cDgpUZN`sPxi+~4BYB<|!xS^BmAyR? zW;?)81465MakW%Ynzl?}#gdhC3>-UJo|9e1u+O+>YH2l}yP6M%z@Ryd4@w3Z*&o4t z#6XLSV<#r%*2{rNB3?gBi97-ihPf~jsy49uF%rlla7pi?NMg`lRwln*E{WTIAg}ajw_0o2BMszL z4y#pr*d2#lZo9nNW6;yxLC^f-hW1q+AA~q7V=z>}YaEO{_$pG!mXw#PJvhx>NnN5X z$Tc3s4SKW*P1aVq)}y%Mt0qZNUhAL+Qr}aoB(L+>0LyR8P+qQc5FRZC#jkRca>#?& zf^&JtGbXQhXtNr0JC-0E(|LV_cJWXhWFEJXJ%q=ex-hrN8$F2INS4M0d6UDYu=;Dc zF3X!eh67=`+*6UaIA}V+CY(M*ZM(eHW4KQk738A4&B3@dfO5p$4Ho4NdAo0bh#JeM`+aFBf#0V=NXJ+2xaO~LmfN?GKy&fH4a$vzu z%KIG19WDoMl^Z-5cINZ|Zg!izKY`)Nt?D074fueEQ3kFKx5|wkoX3!)jU~HXKIp(c z?uRp(i}J4?8FV)~u^sYn4jgRk;vTt+Cnq0r@LVhC^X|E3HMdnhjCla|UdDRsr(--m z2Z$RLpNVm-2S&#*QTsXhY|P;So9MSVt25xS7drGAS6TVom`tl%J&Ua;C!ZhVf~n23 zIz!0I7skl2Rokqg7UYX#WHm%%w@8cfr7?P@gB|9&K4hRIUmm0TxL1HWX0poil`)#l zf?P$uI>v1daB7p}q}_^w+A3ckBR61C*}~l>-xy=V0QwQj5T`h4j6 zKN{DMV%F*4p*?gjD?eU_Qk9sK{}`w6NMcLpe~xpQ>60tSPsX{nZow4gr{h%6vYeIV zXX9kAGw4qbIcnBjgZ%lp&<30eb9_a9G0x*iO{<2Zgsx@&a$Ew1GxxNI@W?LjZ3s(9ALp6N93$u6-ADWv@9QA z?SjwBiZMKyxRo&*jfQCFM~uS54V~$#o<_>as+f!hz+tVk(Vk-r->a7sXm5tF?dIj= z$XJ5&?Py>`Cpv05YFO)5&&Hh*E3>Q|9SgZpafpH2iXta##@RZwB6iHwhRDk?34wS} z%*vg{a9qsTghsDzIw!|2!{Z5g_7L*C+F5?n)+<2|x7KQb^qO2Vk zK@!pT*hWio+&JCn@O(QGi37s37-%h*Wx4CP=p5D+&mO>@Vqg`y+qeXuL^k7w(n-1d zxB$*D^7-jlcfH3ri8D~xe#7oRCAP^u$0hI#a-1yG<(LJz*Er7`x~hV=%e}|hK^IL$ zpJ1F>l>3bHSSzY}fgN(+ae*34GuU@X9!8t{jq^bWgCd-BNrbI<|8W@%C5-`|pUXh- z+JSKaR)(g75_ko{xWp_T;)`c)pw?+0;PCB(5;BoRhOYGBF&q=iHtk{fLvNV?j}DYH zlH>%3d82o@X+ujjoSZny_~&IJ4YJ;me&EGpHu$t|ypmvqnC;ee*;h^;A(Ek;GQziU69B$fXxUr{QQZi{c8B*3!rf`R|DE50R&Eq z4$Z!#PKynV9PfGnYmp%h6?Ix%NW!E#Eo7wNbah%eV5ajI>a=peiTA%$rw?lw+e)%>)I-TEbc=4a?TG-?KF7Q1Oa5}%+`Hl!U zo!>>i9|BJ2cZZxOvTy%_`Ni5d-sJ$N`Nb~VUUiyZ?5XWjr}@Q}+J1FfQDQgkfI6)t zv6XhAI<1;<-30G!K*(0jxTkfoI<1;<(FAX7U^1+laog)j=631Y%C|OiL#2CMvbzRrPem%c^5&w*~2z8!p_!+HB$bHiP$zf-5N zxQ+Gq>a@h;!q$t`X=%sBu9v9Ol8y^tSE|!ej*DV1Ri`B!7s~!YotAFgID45oE!lW= z$jjB~svYkQd4;(x*`=*~$pe$=61GiVWp0Lf))S%QoH@@)mWvY~zI?Z#B0|*H(F(xn07x@l_E_woBOpUlT#MOWJn6A%bp~ zwne@lf^L_%9eg{);&xZt*v5K~IxTcOIN`nOw7~Ho(f6s-!p7r6Z&0TNjVENkU!4{* zo)P*1by~LZaL^moY1zh;us^6y%XXzA|Ef-x?aCzI{=j5ewkuot;s?52!nW~k4|Kbf zE$~$jbi1T&=X)OLc4=GWs~zZeiQB;!JM3H7Yr*3x@2Avhq2s}%pH`;@KADrxsMErp z%*$uhX+cjGa=W6mih7p9tPpdB(RKx=UiZE{c9q+2{b~K z`R)UK0}&n#C|zNSo8x|fw*xVYDBOl$~J z6wkN7iyL5jV-rc=#Boo&AO(+yF_*DfxtD@G%S#&_OIj#6*roSYxY=ysaKsc2OXIP- z&~eQmz)kQPPUOOFWi;gb-9g<)0X1kxOtFa#L)M8fH8^2Eg?;M8aoIeM%Ra!#Anw{g z*D&CpLEx5#r*M?Ei+4Lj_tMB?*M1`6t9rnfD%d{QoJX-}+!{8qN@sQ~Ba0GoL&NS;3+=Y+p7e+PQWfvY} zMw?<4m-3khMD!Q;^v%T*7i0HkmkHEuRYE~Wy6 z8`0Z>EE$**DBPWkr4j!l4US$60%48!QHIZL(mAlAygzh?!MquPZ2_#@$ARH6{+Y_= zmQ8KlagFXA8#JHN9{WYI8wnogW}>J3TGS}VAR)kgj)A{jp%TbSGa-QOmUzdQ0w~I< z1n*BNTjk5(?tV7);A<*+)%^fAWj6>B8$a=?z%A{ zgVkVLUN9EN{=x*y$LhqTgGG5vgHU@pyiaBhN)PV|!4rw5JBhl%?F7t?REBjq#L~%V z37?hZ=Wxryy?RGefC9$!DE1G981N)XoC=h1j}lEhbg0+EMYsS@1ok=1>KpYy;XXLj zFAkuX$E?0e4>(0ze2%~2Ien!baNa${@d5YvQEI<}zFQB^igJf8tT26Wk3ka1VPCRu z4=lo^eIMpymBhoZX7rKQ1~YqTUym~mCjv2$*@miSoLzLQalI}U<`QL!HnYtb+*pO~ zw~Y<+h3ecMb9{xzY^?gJc^6|gRgToTJB*v>)e~HibY+Erd2Z?)BS#7hBoCSIG7?(} zou+?1q9zEc2p3+Af}#;o6Idu>P>P&zsfWW>{frf99Zmh!mlWAC{`B?xL#%77E(BHy;7xwJlv1_Nj zZnf8M@bD;4IrT7#P|rKFWTuKeKs;}a8rnlG*mGFKp#pW#EN=>6aH8fjNY>>}ojf(O zj>-nNI&ixgchp4sohcj*!tYHmt?)iN{6aUtnbFO|sk3q7Gs~u^DjA1G>!i_4^u*FI z#CrqaMve6F$bvpJZ)ekHY~gZ_eovUAiyEE0ls-qdJG*PhkXoD2d@ruLU!V zC*3H6IT<>!xuO42s#(sAs`XI2I7O~QigAXc9|3O^*--69&bMhUm>>?d)rXf9pBo1`h*ub z`NE0pso4qCe)hCX@w9AyB9}eASUx>dp4htm{9U_u?c2Y1>;64^CxVMFm^gkNmpNNF zJPM0-sE=pHXqBbq(`uwKn3=F{@Kgluq1uCf`1TptHhjE-zK4YGo;lfM@K6eD+|R>0 z&C|-EH+EK>X4dyuW}*B}HQ3Hg<2V|sfRB&JV(k+K4vq>By8}MWKa15*7&eTBErB4g zGE%7+#-Gl-11o5X3T}WIQA5ojGbjk!E%Y9vS-{$m({K)Oj+ROq#(Sud4HzhCxB$4o z)yp(o1YG1QW*RO5F0rGe;WFSdO_?-|oM1-@=!JK?@2`h}!Ix-UcwQea-s*40Ar|*| z5=fM3T0lbc)5IwcU==DRkKq`_07eSnNv^?qcxsjy=IpRMJVrHzjd#HM4qw2g-G;3V zHKIAL!UDx?395?+_nUYUIfy(h3>EK$c&;dpD#w%?Mk^=0*$s z2qa#DGeSan&hrWsNW2DTgoLhBZ$+-*rcz{=7vV{lXj7C^vf#>Gf=zRHW;Uj#;3^!S zQ=Dp2QUwm1+Vs@+wig3HV?&ySp|7B0cR)d4LDXwVxn)UpCI7+oEY9}O_~zNz@h3y@t=q^)x176k$8guV z+lIN}|<7o;(>xn7tCowarO2x@lL6=~EgtmhlZiME=euV>EEM(7&|B`p0{ zt)((xsj|OyG1s=q-C-B%)0QdJ*rv-IK(y&u!E2Zjg_84ut0Q!|nZPv>J30rrHe$xD z|JRaBSm=MKSa<_y%qst1*#@FX&g+HCBpM=Bb$UtRu*3e)a$#e{P_)=^*dc#9R%WIe z<28!I4(l@-RuQS<2;kR54m+4H!ZRlGHltcv8gp=o;p7#B-RiTv4_r>P_5+m;+o zRl=<;WFm(yD`eH_Rupm;0w3d?=TCiMI5tCBpIAi4uBGmOP7Uy2NxK6{!-i~$3qAH3 zU8h>%iT{gl2F1S@jm-^Ls_*375DT1K{z%LpeN1bP_EF)j(mbbu5Rbs0@tNad{vP1I z4cM&q539E%PyhEp)aKu%VZ{IAur}wdeg-h=9}l8+{_$gkXZ&A5Ud_L=6BFSx{^M4A z{}5cp|E43o|BsFF^#6S2nSTVdjQ`Ib<^A6@#?$}NC{4>h0$RrZEbLuN|HsF8`hTYK zj2{s#Cd-%QH+`)4fAg~bFHxTHBO&;V`v2gaz5h>+@r?gg z<>?;@UB>^JYrTK$qm1z1hyVS`uY!NDLbF_QSNbQ9g_se39o)y`jDhjH#(0*< zIm)kr%sFE`(|?8XOg{<|pV9n(;a)!dSnL_$>Hk=qTd?{^L5}b&|Necv|MSLpyq!;; zqx@=waqbvD4dmAQu^$ImxoKgcvaPE%O)lrbHGqp8_dDAvqd}zdfW<(0-2It`Bk_j> v +#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: +*/ -- 2.39.2