[Midnightbsd-cvs] mports: www/squid: Update to 2.6, set license

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Fri Apr 11 14:37:56 EDT 2008


Log Message:
-----------
Update to 2.6, set license

Modified Files:
--------------
    mports/www/squid:
        Makefile (r1.2 -> r1.3)
        distinfo (r1.1 -> r1.2)
    mports/www/squid/files:
        patch-src-cf.data.pre (r1.1 -> r1.2)
        pkg-deinstall.in (r1.1 -> r1.2)
        pkg-install.in (r1.1 -> r1.2)
        pkg-message.in (r1.1 -> r1.2)

Added Files:
-----------
    mports/www/squid/files:
        extra-patch-src-cf.data.pre.aufs (r1.1)
        icap-2.6-bootstrap.patch (r1.1)
        icap-2.6-core.patch (r1.1)
        patch-configure (r1.1)
        patch-helpers-negotiate_auth-squid_kerb_auth-Makefile.in (r1.1)
        patch-helpers-negotiate_auth-squid_kerb_auth-squid_kerb_auth.c (r1.1)
        patch-tools-Makefile.in (r1.1)
        squid.in (r1.1)

Removed Files:
-------------
    mports/www/squid/files:
        customlog-2.5.patch
        follow_xff-2.5.patch
        follow_xff-configure.patch
        icap-2.5-bootstrap.patch
        icap-2.5-core.patch
        squid.sh.in

-------------- next part --------------
Index: Makefile
===================================================================
RCS file: /home/cvs/mports/www/squid/Makefile,v
retrieving revision 1.2
retrieving revision 1.3
diff -L www/squid/Makefile -L www/squid/Makefile -u -r1.2 -r1.3
--- www/squid/Makefile
+++ www/squid/Makefile
@@ -3,22 +3,18 @@
 # Whom:			Adrian Chadd <adrian at FreeBSD.org>
 #
 # $MidnightBSD$
-# $FreeBSD: ports/www/squid/Makefile,v 1.192 2006/11/17 12:51:29 jmelo Exp $
+# $FreeBSD: ports/www/squid/Makefile,v 1.209 2008/04/05 00:46:55 beech Exp $
 #
 # Tunables not (yet) configurable via 'make config':
 # SQUID_{U,G}ID
 #   Which user/group Squid should run as (default: squid/squid).
 #   The user and group will be created if they do not already exist using
 #   a uid:gid of 100:100.
-#   NOTE: before version 2.5.4_6, these settings defaulted to
-#   nobody/nogroup.
-#   If you wish to keep these settings, please define SQUID_UID=nobody and
-#   SQUID_GID=nogroup in your make environment before you start the update.
-#   NOTE2:
-#   Before version 2.5.4_11 the numerical id chosen for SQUID_UID (and
-#   SQUID_GID respectively) was the first free id greater than or equal 3128.
-#   If you wish to move your squid user to id 100:100, run "make changeuser",
-#   please see the changeuser target's definition for further information.
+#   NOTE: older versions of Squid defaulted to nobody/nogroup.
+#   If you wish to run Squid as "nobody" (which is not recommended), please
+#   define SQUID_UID=nobody and SQUID_GID=nogroup in your make environment
+#   before you start the update or installation of this port.
+#
 # SQUID_LANGUAGES
 #   A list of languages for which error page files should be installed
 #   (default: all)
@@ -40,7 +36,7 @@
 #   `make SQUID_CONFIGURE_ARGS="--enable-dlmalloc --enable-truncate" install'
 #
 #   The list below may be incomplete, please see the configure script
-#   in the squid source distribution for the complete list of additional
+#   in the Squid source distribution for the complete list of additional
 #   options.
 #   Note that you probably do not need to worry about these options in most
 #   cases, they are included in case you want to experiment with them.
@@ -48,11 +44,10 @@
 #    --enable-dlmalloc
 #     Compile and use the malloc package from Doug Lea
 #    --enable-gnuregex
-#     Compile and use the supplied GNUregex routines instead of BSD regex.
+#     Compile and use the supplied GNUregex routines instead of BSD regex
+#     (not recommended).
 #    --enable-xmalloc-statistics
 #     Show malloc statistics in status page
-#    --enable-time-hack
-#     Optimize time updates to one per second rather than calling gettimeofday()
 #    --enable-cachemgr-hostname=some.hostname
 #     Set an explicit hostname in cachemgr.cgi
 #    --enable-truncate
@@ -70,39 +65,60 @@
 #    --enable-ntlm-fail-open
 #     Enable NTLM fail open, where a helper that fails one of the
 #     Authentication steps can allow Squid to still authenticate the user
-#
+#    --enable-x-accelerator-vary
+#     Enable support for the X-Accelerator-Vary HTTP header. Can be used
+#     to indicate variance within an accelerator setup. Typically used
+#     together with other code that adds custom HTTP headers to the
+#     requests.
+#    --enable-forward-log
+#     Enable experimental forward_log directive.
+#    --enable-multicast-miss
+#     Enable experimental multicast notification of cachemisses.
 
 PORTNAME=	squid
-PORTVERSION=	2.5.14
-PORTREVISION=	3
+PORTVERSION=	2.6.19
 CATEGORIES=	www
-MASTER_SITES=	http://www.squid-cache.org/%SUBDIR%/ \
-		http://www2.us.squid-cache.org/%SUBDIR%/ \
+MASTER_SITES=	ftp://ftp.squid-cache.org/pub/%SUBDIR%/ \
+		ftp://mirrors.24-7-solutions.net/pub/squid/%SUBDIR%/ \
+		ftp://ftp.belnet.be/packages/squid/pub/%SUBDIR%/ \
+		ftp://ftp.nl.uu.net/pub/unix/www/squid/%SUBDIR%/ \
+		ftp://ftp.mirrorservice.org/sites/ftp.squid-cache.org/pub/%SUBDIR%/ \
+		ftp://ftp.ntua.gr/pub/www/Squid/%SUBDIR%/ \
+		ftp://ftp.ccs.neu.edu/pub/mirrors/squid.nlanr.net/pub/%SUBDIR%/ \
+		${MASTER_SITE_RINGSERVER:S,%SUBDIR%,net/www/squid/&,} \
+		http://www.squid-cache.org/Versions/v2/2.6/ \
+		http://www3.us.squid-cache.org/Versions/v2/2.6/ \
+		http://www1.at.squid-cache.org/Versions/v2/2.6/ \
+		http://www2.nl.squid-cache.org/Versions/v2/2.6/ \
+		http://www1.ru.squid-cache.org/Versions/v2/2.6/ \
+		http://www1.uk.squid-cache.org/Versions/v2/2.6/ \
+		http://www1.jp.squid-cache.org/Versions/v2/2.6/ \
+		http://www2.tw.squid-cache.org/Versions/v2/2.6/
+MASTER_SITE_SUBDIR=	squid-2/STABLE
+DISTNAME=	squid-2.6.STABLE19
+DIST_SUBDIR=	squid2.6
+
+PATCH_SITES=	http://www.squid-cache.org/%SUBDIR%/ \
 		http://www3.us.squid-cache.org/%SUBDIR%/ \
 		http://www1.at.squid-cache.org/%SUBDIR%/ \
 		http://www2.nl.squid-cache.org/%SUBDIR%/ \
 		http://www1.ru.squid-cache.org/%SUBDIR%/ \
 		http://www1.uk.squid-cache.org/%SUBDIR%/ \
-		http://www1.gr.squid-cache.org/%SUBDIR%/ \
 		http://www1.jp.squid-cache.org/%SUBDIR%/ \
-		http://www1.tw.squid-cache.org/%SUBDIR%/
-MASTER_SITE_SUBDIR=	Versions/v2/2.5
-DISTNAME=	squid-2.5.STABLE14
-DIST_SUBDIR=	squid2.5
-
-PATCH_SITES=	${MASTER_SITES}
-PATCH_SITE_SUBDIR=	Versions/v2/2.5/bugs
-PATCHFILES=	squid-2.5.STABLE14-httpReplyDestroy.patch \
-		squid-2.5.STABLE14-hierarchy_tag.patch
+		http://www2.tw.squid-cache.org/%SUBDIR%/
+PATCH_SITE_SUBDIR=	Versions/v2/2.6/changesets
+PATCHFILES=
 PATCH_DIST_STRIP=	-p1
 
 MAINTAINER=	ports at MidnightBSD.org
 COMMENT=	HTTP Caching Proxy
+LICENSE=	gpl2
 
-CONFLICTS=	squid-2.[^5]*
+CONFLICTS=	squid-2.[^6]*
 GNU_CONFIGURE=	yes
 USE_BZIP2=	yes
 USE_PERL5=	yes
+USE_RC_SUBR=	squid
 
 SQUID_UID?=	squid
 SQUID_GID?=	squid
@@ -110,6 +126,7 @@
 MAN8=		cachemgr.cgi.8 squid.8
 docs=		QUICKSTART README RELEASENOTES.html doc/debug-sections.txt
 PORTDOCS=	${docs:T}
+PORTEXAMPLES=	passwd.sql
 SUB_FILES+=	pkg-deinstall pkg-install pkg-message
 SUB_LIST+=	SQUID_UID=${SQUID_UID} SQUID_GID=${SQUID_GID}
 
@@ -117,20 +134,19 @@
 		SQUID_SASL_AUTH "Install SASL authentication helpers" off \
 		SQUID_DELAY_POOLS "Enable delay pools" off \
 		SQUID_SNMP "Enable SNMP support" off \
-		SQUID_CARP "Enable CARP support" off \
+		SQUID_CARP "Enable CARP support" on \
 		SQUID_SSL "Enable SSL support for reverse proxies" off \
 		SQUID_PINGER "Install the icmp helper" off \
 		SQUID_DNS_HELPER "Use the old 'dnsserver' helper" off \
 		SQUID_HTCP "Enable HTCP support" off \
 		SQUID_VIA_DB "Enable forward/via database" off \
 		SQUID_CACHE_DIGESTS "Enable cache digests" off \
-		SQUID_WCCP "Enable Web Cache Coordination Protocol" on \
-		SQUID_UNDERSCORES "Allow underscores in hostnames" on \
-		SQUID_CHECK_HOSTNAME "Do hostname checking" on \
+		SQUID_WCCP "Enable Web Cache Coordination Prot. v1" on \
+		SQUID_WCCPV2 "Enable Web Cache Coordination Prot. v2" off \
 		SQUID_STRICT_HTTP "Be strictly HTTP compliant" off \
 		SQUID_IDENT "Enable ident (RFC 931) lookups" on \
+		SQUID_REFERER_LOG "Enable Referer-header logging" off \
 		SQUID_USERAGENT_LOG "Enable User-Agent-header logging" off \
-		SQUID_CUSTOM_LOG "Enable custom log format" off \
 		SQUID_ARP_ACL "Enable ACLs based on ethernet address" off \
 		SQUID_PF "Enable transparent proxying with PF" off \
 		SQUID_IPFILTER "Enable transp. proxying with IPFilter" off \
@@ -138,9 +154,9 @@
 		SQUID_ICAP "Enable ICAP client functionality" off \
 		SQUID_AUFS "Enable the aufs storage scheme" off \
 		SQUID_COSS "Enable the COSS storage scheme" off \
+		SQUID_KQUEUE "Use kqueue(2) instead of poll(2)" on \
 		SQUID_LARGEFILE "Support log and cache files >2GB" off \
-		SQUID_STACKTRACES "Create backtraces on fatal errors" off \
-		SQUID_RCNG "Install an rc.d style startup script" on
+		SQUID_STACKTRACES "Create backtraces on fatal errors" off
 
 etc_files=	squid/cachemgr.conf.default \
 		squid/mib.txt squid/mime.conf.default \
@@ -168,37 +184,46 @@
 		ERR_SOCKET_FAILURE ERR_TOO_BIG ERR_UNSUP_REQ \
 		ERR_URN_RESOLVE ERR_WRITE_ERROR ERR_ZERO_SIZE_OBJECT
 
-libexec=	cachemgr.cgi digest_pw_auth diskd ip_user_check \
+libexec=	cachemgr.cgi digest_pw_auth diskd-daemon \
+		ip_user_check \
 		msnt_auth ncsa_auth ntlm_auth \
-		pam_auth smb_auth smb_auth.sh squid_unix_group \
-		wb_auth wb_group wb_ntlmauth wbinfo_group.pl
+		pam_auth smb_auth smb_auth.sh squid_db_auth squid_session \
+		squid_unix_group wbinfo_group.pl
 .if !defined(SQUID_CONFIGURE_ARGS) || ${SQUID_CONFIGURE_ARGS:M*--disable-unlinkd*} == ""
 libexec+=	unlinkd
 .endif
 
-sbin=		RunAccel RunCache squidclient squid
+sbin=		RunCache squidclient squid
 
-CONFIGURE_ARGS=	--bindir=${PREFIX}/sbin  --sysconfdir=${PREFIX}/etc/squid \
+CONFIGURE_ARGS=	--bindir=${PREFIX}/sbin  \
+		--sbindir=${PREFIX}/sbin  \
 		--datadir=${PREFIX}/etc/squid \
 		--libexecdir=${PREFIX}/libexec/squid \
 		--localstatedir=${PREFIX}/squid \
-		--enable-removal-policies="lru heap"
+		--sysconfdir=${PREFIX}/etc/squid \
+		--enable-removal-policies="lru heap" \
+		--disable-linux-netfilter \
+		--disable-linux-tproxy \
+		--disable-epoll
 
 .include <bsd.port.pre.mk>
 
 # Authentication methods and modules:
 
-basic_auth=	NCSA PAM MSNT SMB winbind
-external_acl=	ip_user unix_group wbinfo_group winbind_group
-MAN8+=		pam_auth.8 squid_unix_group.8
+basic_auth=	DB NCSA PAM MSNT SMB
+digest_auth=	password
+external_acl=	ip_user session unix_group wbinfo_group
+MAN8+=		ncsa_auth.8 pam_auth.8 squid_db_auth.8 squid_session.8 \
+		squid_unix_group.8
 .if defined(WITH_SQUID_LDAP_AUTH)
 USE_OPENLDAP=	yes
 CFLAGS+=	-I${LOCALBASE}/include
 LDFLAGS+=	-L${LOCALBASE}/lib
 MAN8+=		squid_ldap_auth.8 squid_ldap_group.8
 basic_auth+=	LDAP
+digest_auth+=	ldap
 external_acl+=	ldap_group
-libexec+=	squid_ldap_auth squid_ldap_group
+libexec+=	digest_ldap_auth squid_ldap_auth squid_ldap_group
 .endif
 .if defined(WITH_SQUID_SASL_AUTH)
 LIB_DEPENDS+=	sasl2.2:${PORTSDIR}/security/cyrus-sasl2
@@ -214,23 +239,39 @@
 .endif
 CONFIGURE_ARGS+=	--enable-auth="basic ntlm digest" \
 			--enable-basic-auth-helpers="${basic_auth}" \
-			--enable-digest-auth-helpers="password" \
+			--enable-digest-auth-helpers="${digest_auth}" \
 			--enable-external-acl-helpers="${external_acl}" \
-			--enable-ntlm-auth-helpers="SMB winbind"
+			--enable-ntlm-auth-helpers="SMB"
+.if !defined(NO_KERBEROS) && !defined(WITHOUT_KERBEROS)
+# XXX This currently only works with heimdal from the base system,
+#     see files/patch-helpers_negotiate_auth-squid_kerb_auth_*
+CONFIGURE_ARGS+=	--enable-negotiate-auth-helpers="squid_kerb_auth"
+libexec+=	squid_kerb_auth
+.endif
 
-# Selection of storage schemes:
+# Storage schemes:
 
 storage_schemes=	ufs diskd null
 .if defined(WITH_SQUID_AUFS)
 storage_schemes+=	aufs
+.if ${OSVERSION}>=501000
+# Only document libmap.conf where it is available:
+EXTRA_PATCHES+=		${PATCHDIR}/extra-patch-src-cf.data.pre.aufs
+.endif
 # Nil aufs threads is default, set any other value via SQUID_CONFIGURE_ARGS
-CONFIGURE_ARGS+=	--enable-async-io \
-			--with-pthreads
+CONFIGURE_ARGS+=	--with-pthreads
 CFLAGS+=	${PTHREAD_CFLAGS}
 .endif
 .if defined(WITH_SQUID_COSS)
 storage_schemes+=	coss
-CONFIGURE_ARGS+=	--with-aio
+.if !defined(WITH_SQUID_AUFS)
+# use Posix AIO instead of aufs' AIO; note that you then need the kernel to
+# supply AIO support, either by loading the aio(4) module (n/a on 4.x) or by
+# adding the option VFS_AIO to your kernel configuration if you want to
+# actually use COSS storage:
+CONFIGURE_ARGS+=	--enable-coss-aio-ops
+.endif
+sbin+=		cossdump
 .endif
 CONFIGURE_ARGS+=	--enable-storeio="${storage_schemes}"
 
@@ -242,18 +283,19 @@
 .if defined(WITH_SQUID_SNMP)
 CONFIGURE_ARGS+=	--enable-snmp
 .endif
-.if defined(WITH_SQUID_CARP)
-CONFIGURE_ARGS+=	--enable-carp
+.if defined(WITHOUT_SQUID_CARP)
+CONFIGURE_ARGS+=	--disable-carp
 .endif
 .if defined(WITH_SQUID_SSL)
-# we need to .include bsd.openssl.mk manually here because USE_OPENSSL only
-# works when it is defined before bsd.port{.pre}.mk is .included and this is
-# not possible when using OPTIONS
+# we need to .include bsd.openssl.mk manually here.because USE_OPENSSL only
+# works when it is defined before bsd.port{.pre}.mk is .included.
+# This makes it currently impossible to combine this macro with OPTIONS to
+# conditionally include OpenSSL support.
 .include "${PORTSDIR}/Mk/bsd.openssl.mk"
 CONFIGURE_ARGS+=	--enable-ssl \
 			--with-openssl="${OPENSSLBASE}"
 CFLAGS+=	-I${OPENSSLINC}
-LDFLAGS+=	-L${LOCALBASE}/lib
+LDFLAGS+=	-L${OPENSSLLIB}
 .endif
 .if defined(WITH_SQUID_PINGER)
 CONFIGURE_ARGS+=	--enable-icmp
@@ -275,11 +317,8 @@
 .if defined(WITHOUT_SQUID_WCCP)
 CONFIGURE_ARGS+=	--disable-wccp
 .endif
-.if !defined(WITHOUT_SQUID_UNDERSCORES)
-CONFIGURE_ARGS+=	--enable-underscores
-.endif
-.if defined(WITHOUT_SQUID_CHECK_HOSTNAME)
-CONFIGURE_ARGS+=	--disable-hostname-checks
+.if defined(WITH_SQUID_WCCPV2)
+CONFIGURE_ARGS+=	--enable-wccpv2
 .endif
 .if defined(WITH_SQUID_STRICT_HTTP)
 CONFIGURE_ARGS+=	--disable-http-violations
@@ -287,49 +326,53 @@
 .if defined(WITHOUT_SQUID_IDENT)
 CONFIGURE_ARGS+=	--disable-ident-lookups
 .endif
+.if defined(WITH_SQUID_REFERER_LOG)
+CONFIGURE_ARGS+=	--enable-referer-log
+.endif
 .if defined(WITH_SQUID_USERAGENT_LOG)
 CONFIGURE_ARGS+=	--enable-useragent-log
 .endif
-.if defined(WITH_SQUID_CUSTOM_LOG)
-EXTRA_PATCHES+=		${PATCHDIR}/customlog-2.5.patch
-.endif
 .if defined(WITH_SQUID_ARP_ACL)
 CONFIGURE_ARGS+=	--enable-arp-acl
 .endif
 .if defined(WITH_SQUID_PF)
 CONFIGURE_ARGS+=	--enable-pf-transparent
+.if ${OSVERSION} < 502106
+IGNORE=		pf available only in FreeBSD 5.3 and newer
 .endif
+.endif
+# IPFilter-headers are not installed on FreeBSD 4 since 4.7-RELEASE,
+# they were not installed on FreeBSD 5 from 2002-03-26 (OSVERSION > 500032) to
+# 2003-06-27 (OSVERSION < 501101).
+#
+# Please see PR misc/44148 and the CVS log of src/include/Makefile for further
+# information.
 .if defined(WITH_SQUID_IPFILTER)
+.if (${OSVERSION} > 500032 && ${OSVERSION} < 501101)
+IGNORE=		the IPFilter headers are not part of the base system
+.else
 CONFIGURE_ARGS+=	--enable-ipf-transparent
 .endif
+.endif
 .if defined(WITH_SQUID_FOLLOW_XFF)
-EXTRA_PATCHES+=		${PATCHDIR}/follow_xff-2.5.patch \
-			${PATCHDIR}/follow_xff-configure.patch
 CONFIGURE_ARGS+=	--enable-follow-x-forwarded-for
 .endif
 .if defined(WITH_SQUID_ICAP)
-EXTRA_PATCHES+=		${PATCHDIR}/icap-2.5-core.patch \
-			${PATCHDIR}/icap-2.5-bootstrap.patch
+EXTRA_PATCHES+=		${PATCHDIR}/icap-2.6-bootstrap.patch \
+			${PATCHDIR}/icap-2.6-core.patch
 CONFIGURE_ARGS+=	--enable-icap-support
 error_files+=		ERR_ICAP_FAILURE
 .endif
+.if defined(WITHOUT_SQUID_KQUEUE)
+CONFIGURE_ARGS+=	--disable-kqueue
+.endif
 .if defined(WITH_SQUID_LARGEFILE)
 CONFIGURE_ARGS+=	--with-large-files --enable-large-cache-files
 .endif
 .if defined(WITH_SQUID_STACKTRACES)
 CONFIGURE_ARGS+=	--enable-stacktraces
 CFLAGS+=	-g
-STRIP=			""
-.endif
-.if !defined(WITHOUT_SQUID_RCNG)
-USE_RC_SUBR=	squid.sh
-rc_del=		rcold
-rc_state=	rcng
-.else
-SUB_FILES+=	squid.sh
-etc_files+=	rc.d/squid.sh
-rc_del=		rcng
-rc_state=	rcold
+STRIP=
 .endif
 
 # Languages:
@@ -337,11 +380,13 @@
 # If you do not define SQUID_LANGUAGES yourself, all available language files
 # will be installed; the default language will be English.
 
-SQUID_LANGUAGES?=	\
-	Azerbaijani Bulgarian Catalan Czech Danish Dutch English Estonian Finnish      \
-	French German Greek Hebrew Hungarian Italian Japanese Korean Lithuanian \
-	Polish Portuguese Romanian Russian-1251 Russian-koi8-r Serbian     \
-	Simplify_Chinese Slovak Spanish Swedish Traditional_Chinese Turkish
+SQUID_LANGUAGES?=	Armenian Azerbaijani Bulgarian Catalan Czech Danish \
+			Dutch English Estonian Finnish French German Greek \
+			Hebrew Hungarian Italian Japanese Korean Lithuanian \
+			Polish Portuguese Romanian Russian-1251 Russian-koi8-r \
+			Serbian Simplify_Chinese Slovak Spanish Swedish \
+			Traditional_Chinese Turkish Ukrainian-1251 \
+			Ukrainian-koi8-u Ukrainian-utf8
 SQUID_DEFAULT_LANG?=	English
 CONFIGURE_ARGS+=	--enable-err-languages="${SQUID_LANGUAGES}" \
 			--enable-default-err-language=${SQUID_DEFAULT_LANG}
@@ -351,7 +396,8 @@
 
 CONFIGURE_ENV+=		CFLAGS="${CFLAGS}" \
 			CPPFLAGS="${CPPFLAGS}"\
-			LDFLAGS="${LDFLAGS}"
+			LDFLAGS="${LDFLAGS}" \
+			GREP="${GREP}"
 
 PLIST_DIRS=	etc/squid/icons libexec/squid
 PLIST_FILES=	${etc_files:S,^,etc/,} ${icon_files:S,^,etc/squid/icons/,} \
@@ -364,9 +410,11 @@
 PLIST_DIRS+=	etc/squid/errors etc/squid squid/logs squid/cache squid
 
 post-patch:
-	@${REINPLACE_CMD} -e 's|-lpthread|${PTHREAD_LIBS}|g' ${WRKSRC}/configure
+	@${REINPLACE_CMD} -e 's|-lpthread|${PTHREAD_LIBS}|g' \
+	    ${WRKSRC}/configure
 	@${REINPLACE_CMD} -e 's|%%SQUID_UID%%|${SQUID_UID}|g' \
-	    -e 's|%%SQUID_GID%%|${SQUID_GID}|g' ${WRKSRC}/src/cf.data.pre
+	    -e 's|%%SQUID_GID%%|${SQUID_GID}|g' \
+	    -e 's|%%PREFIX%%|${PREFIX}|g' ${WRKSRC}/src/cf.data.pre
 	@${REINPLACE_CMD} -e 's|%%LOCALBASE%%|${LOCALBASE}|g' \
 	    ${WRKSRC}/helpers/basic_auth/SMB/Makefile.in \
 	    ${WRKSRC}/helpers/basic_auth/SMB/smb_auth.sh
@@ -375,31 +423,20 @@
 # Prevent installation of .orig files by deleting them.
 	@${FIND} ${WRKSRC} -name '*.bak' -delete
 	@${FIND} ${WRKSRC} -name '*.orig' -delete
-# create the start script:
-	@${REINPLACE_CMD} \
-	    -e '/--begin ${rc_del}/,/--end ${rc_del}/d' \
-	    -e '/--.*${rc_state}/d' ${WRKDIR}/squid.sh
-# create variable information in pkg-message:
-	@${REINPLACE_CMD} \
-	    -e '/--begin ${rc_del}/,/--end ${rc_del}/d' \
-	    -e '/--.*${rc_state}/d' ${PKGMESSAGE}
 
 pre-su-install:
 	@${SETENV} ${SCRIPTS_ENV} PKG_PREFIX=${PREFIX} \
 	    ${SH} ${PKGINSTALL} ${PKGNAME} PRE-INSTALL
 
 post-install:
-# Create cachemgr.conf.default manually since squid's install routine
-# unfortunately fails to do so:
-	${INSTALL_DATA} ${WRKSRC}/src/cachemgr.conf \
-	    ${PREFIX}/etc/squid/cachemgr.conf.default
+.if !defined(NOPORTEXAMPLES)
+	@${MKDIR} ${EXAMPLESDIR}
+	${INSTALL_DATA} ${WRKSRC}/helpers/basic_auth/DB/passwd.sql ${EXAMPLESDIR}
+.endif
 .if defined(WITH_SQUID_PINGER)
 	${CHMOD} 4510 ${PREFIX}/libexec/squid/pinger; \
 	${CHGRP} ${SQUID_GID} ${PREFIX}/libexec/squid/pinger
 .endif
-.if defined(WITHOUT_SQUID_RCNG)
-	${INSTALL_SCRIPT} ${WRKDIR}/squid.sh ${PREFIX}/etc/rc.d/
-.endif
 .if !defined(NOPORTDOCS)
 	@${MKDIR} ${DOCSDIR}
 	cd ${WRKSRC} && ${INSTALL_DATA} ${docs} ${DOCSDIR}
@@ -411,50 +448,5 @@
 	@${ECHO_CMD} ""
 	@${CAT} ${PKGMESSAGE}
 	@${ECHO_CMD} ""
-changeuser:
-# Recover from the problem that earlier versions of this port created the
-# squid pseudo-user with an id greater than 999 which is not allowed in
-# FreeBSD's ports system. The port now uses id 100:100.
-# NOTE:
-# This target assumes that SQUID_GID is the primary group of SQUID_UID. If you
-# have a different setup, do not run this target!
-.if ${SQUID_UID:L} == nobody
-	@${ECHO_CMD} "'nobody' is a system user, you do not need to execute"; \
-	${ECHO_CMD} "this target!"
-	${FALSE}
-.endif
-	@if [ `${ID} -u` -ne 0 ]; \
-	then ${ECHO_CMD} "Sorry, you must be root to use this target."; ${FALSE}; fi; \
-	current_uid=`id -u ${SQUID_UID}`; \
-	current_gid=`pw groupshow ${SQUID_GID}|cut -f 3 -d :`; \
-	${ECHO_CMD} "I will remove this user:"; \
-	${ID} -P $${current_uid}; \
-	${ECHO_CMD} "and this group:"; \
-	pw groupshow ${SQUID_GID}; \
-	${ECHO_CMD} "I will then re-create them with a user and group id of 100."; \
-	${ECHO_CMD} "Then all files and directories under ${PREFIX} and /var that"; \
-	${ECHO_CMD} "are owned by uid $${current_uid} will be chown(1)'ed."; \
-	${ECHO_CMD} "After that, all files and directories that were accessible"; \
-	${ECHO_CMD} "by group $${current_gid} will chgrp(1)'ed respectively."; \
-	${ECHO_CMD} "Note that this assumes group '${SQUID_GID}' to be the primary"; \
-	${ECHO_CMD} "group of user '${SQUID_UID}'. If you have a different setup"; \
-	${ECHO_CMD} "please abort this target now."; \
-	read -p "Press RETURN to continue or CTRL-C to abort:" dummy ; \
-	${ECHO_CMD} "OK, here we go:"; \
-	${ECHO_CMD} "deleting user $${current_uid} and his primary group..."; \
-	pw userdel -u $${current_uid}; \
-	${ECHO_CMD} "adding user ${SQUID_UID} with id 100..."; \
-	pw groupadd -n ${SQUID_GID} -g 100; \
-	pw useradd -n ${SQUID_UID} -u 100 -c "squid caching-proxy pseudo user" \
-	    -d ${PREFIX}/squid -s /sbin/nologin -h - ; \
-	${ECHO_CMD} "chown(1)'ing everything under ${PREFIX} from $${current_uid} to 100..."; \
-	${FIND} -H ${PREFIX} -user $${current_uid} -exec ${CHOWN} 100 {} \; ; \
-	${ECHO_CMD} "chgrp(1)'ing everything under ${PREFIX} from $${current_gid} to 100..."; \
-	${FIND} -H ${PREFIX} -group $${current_gid} -exec ${CHOWN} :100 {} \; ; \
-	${ECHO_CMD} "chown(1)'ing everything under /var from $${current_uid} to 100..."; \
-	${FIND} -H /var -user $${current_uid} -exec ${CHOWN} 100 {} \; ; \
-	${ECHO_CMD} "chgrp(1)'ing everything under /var from $${current_gid} to 100..."; \
-	${FIND} -H /var -group $${current_gid} -exec ${CHOWN} :100 {} \; ; \
-	${ECHO_CMD} "Finished."
 
 .include <bsd.port.post.mk>
Index: distinfo
===================================================================
RCS file: /home/cvs/mports/www/squid/distinfo,v
retrieving revision 1.1
retrieving revision 1.2
diff -L www/squid/distinfo -L www/squid/distinfo -u -r1.1 -r1.2
--- www/squid/distinfo
+++ www/squid/distinfo
@@ -1,9 +1,3 @@
-MD5 (squid2.5/squid-2.5.STABLE14.tar.bz2) = f413e0b887a5f9b2a75350243ed5564c
-SHA256 (squid2.5/squid-2.5.STABLE14.tar.bz2) = c4eaee0e5ee42f46060217df9a88d628d244c0a543feab8296e44269e57ec7bd
-SIZE (squid2.5/squid-2.5.STABLE14.tar.bz2) = 1073745
-MD5 (squid2.5/squid-2.5.STABLE14-httpReplyDestroy.patch) = 1529f8b0170e24b26353578778435bd4
-SHA256 (squid2.5/squid-2.5.STABLE14-httpReplyDestroy.patch) = 9e99132b8efb07e3465d5e33749aa450daecfa3acde73755b6a3589d09d19285
-SIZE (squid2.5/squid-2.5.STABLE14-httpReplyDestroy.patch) = 1277
-MD5 (squid2.5/squid-2.5.STABLE14-hierarchy_tag.patch) = 9abe563ca3d01dc58502737edc6f3c60
-SHA256 (squid2.5/squid-2.5.STABLE14-hierarchy_tag.patch) = 6c98f1f2351b79cfc3f956ed1c46d86c7a53aac0ba28203a33f2dadc7d1e96fe
-SIZE (squid2.5/squid-2.5.STABLE14-hierarchy_tag.patch) = 1319
+MD5 (squid2.6/squid-2.6.STABLE19.tar.bz2) = e1f355ab907369903b5e28aff0fe8386
+SHA256 (squid2.6/squid-2.6.STABLE19.tar.bz2) = 018f8f31eb40fff14f4d86bc1a40c18a0ee67d1412316de13f5975df6d2a0178
+SIZE (squid2.6/squid-2.6.STABLE19.tar.bz2) = 1324732
--- /dev/null
+++ www/squid/files/patch-helpers-negotiate_auth-squid_kerb_auth-Makefile.in
@@ -0,0 +1,19 @@
+--- helpers/negotiate_auth/squid_kerb_auth/Makefile.in.orig	Mon Jul 16 20:40:58 2007
++++ helpers/negotiate_auth/squid_kerb_auth/Makefile.in	Mon Jul 16 20:44:52 2007
+@@ -264,12 +264,12 @@
+ #-L$(top_builddir)/lib -lmiscutil $(XTRA_LIBS)
+ 
+ # HEIMDAL
+-#KERBINC = -DHEIMDAL -I/usr/include/heimdal
+-#KERBLIBS = -lgssapi -lkrb5 -lcom_err -lasn1 -lroken
++KERBINC = -DHEIMDAL -I/usr/include
++KERBLIBS = -lgssapi -lkrb5 -lcom_err -lasn1 -lroken -lcrypt -lcrypto
+ 
+ # MIT
+-KERBINC = 
+-KERBLIBS = -lgssapi_krb5 -lkrb5 -lcom_err
++#KERBINC = 
++#KERBLIBS = -lgssapi_krb5 -lkrb5 -lcom_err
+ all: all-am
+ 
+ .SUFFIXES:
--- /dev/null
+++ www/squid/files/patch-helpers-negotiate_auth-squid_kerb_auth-squid_kerb_auth.c
@@ -0,0 +1,10 @@
+--- helpers/negotiate_auth/squid_kerb_auth/squid_kerb_auth.c.orig	Mon Jul 16 21:10:10 2007
++++ helpers/negotiate_auth/squid_kerb_auth/squid_kerb_auth.c	Mon Jul 16 21:10:35 2007
+@@ -31,6 +31,7 @@
+ #include <unistd.h>
+ #include <time.h>
+ #include <sys/time.h>
++#include <sys/param.h>
+ 
+ #include "base64.h"
+ #ifndef HAVE_SPNEGO
--- www/squid/files/follow_xff-configure.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-!Simulate the autotools bootstrap of the follow-x-forwarded-for patchset.
-!
-!Beware that all line number informations in configure.log greater
-!than 2972 are offset by at least -29 (correcting all line numbers would have
-!bloated the patch by 92kB!)
---- include/autoconf.h.in.orig	Sat Jan 18 02:46:11 2003
-+++ include/autoconf.h.in	Thu Jun 24 13:19:07 2004
-@@ -291,6 +291,12 @@
- #define USE_IDENT 1
- 
- /*
-+ * Compile in support for following X-Forwarded-For headers?
-+ * Enabled by default.
-+ */
-+#define FOLLOW_X_FORWARDED_FOR 1
-+
-+/*
-  * If your system has statvfs(), and if it actually works!
-  */
- #undef HAVE_STATVFS
---- configure.orig	Thu Sep 22 10:16:26 2005
-+++ configure	Thu Sep 22 17:29:01 2005
-@@ -249,6 +249,12 @@
-                           if you build as another user who is not privileged
-                           to use the number of filedescriptors you want the
-                           resulting binary to support"
-+ac_help="$ac_help
-+  --enable-follow-x-forwarded-for
-+                          Enable support for following the X-Forwarded-For
-+                          HTTP header to try to find the IP address of the
-+                          original or indirect client when a request has
-+                          been forwarded through other proxies."
- 
- # Initialize some variables set by options.
- # The variables have the same names as the options, with
-@@ -3255,6 +3261,29 @@
- 
- fi
- 
-+
-+follow_xff=1
-+# Check whether --enable-follow-x-forwarded-for or --disable-follow-x-forwarded-for was given.
-+if test "${enable_follow_x_forwarded_for+set}" = set; then
-+  enableval="$enable_follow_x_forwarded_for"
-+   if test "$enableval" = "yes" ; then
-+    echo "follow X-Forwarded-For enabled"
-+    follow_xff=1
-+  fi
-+
-+fi
-+
-+if test $follow_xff = 1; then
-+    cat >> confdefs.h <<\EOF
-+#define FOLLOW_X_FORWARDED_FOR 1
-+EOF
-+
-+else
-+    cat >> confdefs.h <<\EOF
-+#define FOLLOW_X_FORWARDED_FOR 0
-+EOF
-+
-+fi
- 
- # Force some compilers to use ANSI features
- #
--- www/squid/files/squid.sh.in
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/bin/sh
-#
-# $FreeBSD: ports/www/squid/files/squid.sh.in,v 1.3 2006/11/04 23:03:40 miwi Exp $
-#
-# --begin rcng
-# PROVIDE: squid
-# REQUIRE: LOGIN
-# KEYWORD: shutdown
-# 
-# Note:
-# Set "squid_enable=yes" in either /etc/rc.conf, /etc/rc.conf.local or
-# /etc/rc.conf.d/squid to make this script actually do something. There
-# you can also set squid_chdir, squid_user, and squid_flags.
-#
-# Please see squid(8), rc.conf(5) and rc(8) for further details.
-#
-# --end rcng
-
-name=squid
-command=%%PREFIX%%/sbin/squid
-# --begin rcng
-extra_commands=reload
-reload_cmd="${command} ${squid_flags} -k reconfigure"
-# --end rcng
-stop_cmd="squid_stop"
-squid_chdir=${squid_chdir:-%%PREFIX%%/squid/logs}
-# --begin rcng
-squid_enable=${squid_enable:-"NO"}
-# --end rcng
-squid_flags=${squid_flags-"-D"}
-squid_user=${squid_user:-%%SQUID_UID%%}
-default_config=%%PREFIX%%/etc/squid/squid.conf
-
-# --begin rcold
-squid_stop() {
-	echo -n " ${name}"
-	${command} -k shutdown
-	while ps -xcU ${squid_user} | grep -q squid; do
-		sleep 2
-	done
-}
-
-# --end rcold
-# --begin rcng
-squid_stop() {
-	echo "Stopping ${name}."
-	${command} ${squid_flags} -k shutdown
-	run_rc_command poll
-}
-
-. %%RC_SUBR%%
-rcvar=`set_rcvar`
-load_rc_config ${name}
-
-# squid(8) will not start if ${default_config} is not present so try
-# to catch that beforehand via ${required_files} rather than make
-# squid(8) crash.
-# If you remove the default configuration file make sure to add
-# '-f /path/to/your/squid.conf' to squid_flags
-
-if [ -z "${squid_flags}" ]; then
-	required_files=${default_config}
-fi
-required_dirs=${squid_chdir}
-run_rc_command "$1"
-# --end rcng
-# --begin rcold
-case $1 in
-start)
-	if [ -x "${command}" -a \
-		\( -f "${default_config}" -o "${squid_flags}" \) ]; then
-		echo -n " ${name}"
-		(cd ${squid_chdir} && exec su -fm ${squid_user} -c \
-			"${command} ${squid_flags}")
-	fi
-	;;
-stop)
-	if [ -x "${command}" ]; then
-		${stop_cmd}
-	fi
-	;;
-*)
-	echo "usage: ${0##*/} {start|stop}" >&2
-	exit 64
-	;;
-esac
-exit 0
-# --end rcold
--- /dev/null
+++ www/squid/files/squid.in
@@ -0,0 +1,61 @@
+#!/bin/sh
+#
+# $MidnightBSD: mports/www/squid/files/squid.in,v 1.1 2008/04/11 18:37:54 laffer1 Exp $
+# $FreeBSD: ports/www/squid/files/squid.in,v 1.3 2007/08/14 02:32:11 delphij Exp $
+#
+# PROVIDE: squid
+# REQUIRE: LOGIN
+# KEYWORD: shutdown
+#
+# Note:
+# Set "squid_enable=yes" in either /etc/rc.conf, /etc/rc.conf.local or
+# /etc/rc.conf.d/squid to make this script actually do something. There
+# you can also set squid_chdir, squid_pidfile, squid_user, and squid_flags.
+#
+# Please see squid(8), rc.conf(5) and rc(8) for further details.
+#
+
+squid_checkrunning() {
+	${command} ${squid_flags} -k check 2>/dev/null
+}
+
+squid_stop() {
+	echo "Stopping ${name}."
+	${command} ${squid_flags} -k shutdown
+	run_rc_command poll
+}
+
+. %%RC_SUBR%%
+
+name=squid
+rcvar=${name}_enable
+
+command=%%PREFIX%%/sbin/squid
+extra_commands=reload
+reload_cmd="${command} ${squid_flags} -k reconfigure"
+stop_precmd="squid_checkrunning"
+stop_cmd="squid_stop"
+
+load_rc_config ${name}
+
+squid_chdir=${squid_chdir:-"%%PREFIX%%/squid/logs"}
+squid_enable=${squid_enable:-"NO"}
+squid_flags=${squid_flags-"-D"}
+squid_pidfile=${squid_pidfile:-"%%PREFIX%%/squid/logs/squid.pid"}
+squid_user=${squid_user:-%%SQUID_UID%%}
+default_config=%%PREFIX%%/etc/squid/squid.conf
+
+pidfile=${squid_pidfile}
+required_dirs=${squid_chdir}
+
+# squid(8) will not start if ${default_config} is not present so try
+# to catch that beforehand via ${required_files} rather than make
+# squid(8) crash.
+# If you remove the default configuration file make sure to add
+# '-f /path/to/your/squid.conf' to squid_flags
+
+if [ -z "${squid_flags}" ]; then
+	required_files=${default_config}
+fi
+
+run_rc_command "$1"
Index: patch-src-cf.data.pre
===================================================================
RCS file: /home/cvs/mports/www/squid/files/patch-src-cf.data.pre,v
retrieving revision 1.1
retrieving revision 1.2
diff -L www/squid/files/patch-src-cf.data.pre -L www/squid/files/patch-src-cf.data.pre -u -r1.1 -r1.2
--- www/squid/files/patch-src-cf.data.pre
+++ www/squid/files/patch-src-cf.data.pre
@@ -1,6 +1,39 @@
---- src/cf.data.pre.orig	Fri Aug 20 16:23:18 2004
-+++ src/cf.data.pre	Fri Aug 20 16:25:23 2004
-@@ -2396,12 +2396,12 @@
+--- src/cf.data.pre.orig	Tue Jun 26 01:34:57 2007
++++ src/cf.data.pre	Mon Jul 16 20:02:21 2007
+@@ -1207,6 +1207,21 @@
+ 
+ 	Note that for coss, max-size must be less than COSS_MEMBUF_SZ
+ 	(hard coded at 1 MB).
++
++	Note for FreeBSD users:
++	COSS -- like aufs -- uses async IO so if you compiled Squid without
++	support for the aufs storage type, COSS will use POSIX AIO.
++	This means that you need to add the line
++
++	options VFS_AIO
++
++	to your kernel configuration in order to use COSS.
++
++	On FreeBSD 5 and higher you can load the aio(4) module and do not
++	necessarily need to recompile your kernel.
++
++	If you compiled Squid with both support for aufs and COSS, COSS
++	will use aufs' routines and does not need special kernel support.
+ DOC_END
+ 
+ NAME: logformat
+@@ -1439,6 +1454,10 @@
+ LOC: Config.pidFilename
+ DOC_START
+ 	A filename to write the process-id to.  To disable, enter "none".
++
++	Note: If you change this setting, you need to set squid_pidfile
++	in /etc/rc.conf to reflect the new value. Please see
++	%%PREFIX%%/etc/rc.d/squid for details.
+ DOC_END
+ 
+ NAME: debug_options
+@@ -3275,12 +3294,12 @@
  
  NAME: cache_effective_user
  TYPE: string
--- /dev/null
+++ www/squid/files/icap-2.6-core.patch
@@ -0,0 +1,7056 @@
+Patch 1 of 2 to integrate the icap-2_6 branch into the FreeBSD squid port.
+
+Created by Thomas-Martin Seck <tmseck at netcologne.de>.
+
+This patch only contains the parts of the original patchset that
+actually implement the ICAP client functionality. The updates to
+the build infrastructure are omitted to avoid the need to run an
+autotools bootstrap.  Instead, we simulate said bootstrapping with
+a second patch, icap-2.6-bootstrap.patch.
+
+The complete patchset was pulled from the project's CVS repository
+at cvs.devel.squid-cache.org using
+
+cvs diff -u -b -N -kk -rZ-icap-2_6_merge_HEAD -ricap-2_6
+
+and manually adapted because of changes in the Squid code base.
+
+See http://devel.squid-cache.org/icap/ for further information
+about the ICAP client project.
+
+Patch last updated: 2007-05-17
+
+Note: ICAP client support for Squid-2 is no longer supported by
+      the Squid developers. This means that even known bugs in this
+      code will not be fixed. If you need ICAP support please try
+      Squid-3.
+
+Index: errors/Azerbaijani/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Azerbaijani/ERR_ICAP_FAILURE
+diff -N errors/Azerbaijani/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Azerbaijani/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Bulgarian/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Bulgarian/ERR_ICAP_FAILURE
+diff -N errors/Bulgarian/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Bulgarian/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Catalan/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Catalan/ERR_ICAP_FAILURE
+diff -N errors/Catalan/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Catalan/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Czech/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Czech/ERR_ICAP_FAILURE
+diff -N errors/Czech/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Czech/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Danish/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Danish/ERR_ICAP_FAILURE
+diff -N errors/Danish/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Danish/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Dutch/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Dutch/ERR_ICAP_FAILURE
+diff -N errors/Dutch/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Dutch/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/English/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/English/ERR_ICAP_FAILURE
+diff -N errors/English/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/English/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Estonian/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Estonian/ERR_ICAP_FAILURE
+diff -N errors/Estonian/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Estonian/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Finnish/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Finnish/ERR_ICAP_FAILURE
+diff -N errors/Finnish/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Finnish/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/French/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/French/ERR_ICAP_FAILURE
+diff -N errors/French/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/French/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/German/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/German/ERR_ICAP_FAILURE
+diff -N errors/German/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/German/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,33 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>FEHLER: Der angeforderte URL konnte nicht geholt werden</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>FEHLER</H1>
++<H2>Der angeforderte URL konnte nicht geholt werden</H2>
++<HR noshade size="1px">
++<P>
++Während des Versuches, den URL<BR>
++<A HREF="%U">%U</A>
++
++<BR>
++zu laden, trat der folgende Fehler auf:
++<UL>
++<LI>
++<STRONG>
++ICAP-Protokollfehler
++</STRONG>
++</UL>
++
++<P>
++<P>
++Es trat ein Problem bei der ICAP-Kommunikation auf. Mögliche Gründe:
++<UL>
++<LI>Nicht erreichbarer ICAP-Server
++<LI>Ungültige Antwort vom ICAP-Server
++
++</UL>
++</P>
++
++<P>Ihr Cache Administrator ist <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Greek/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Greek/ERR_ICAP_FAILURE
+diff -N errors/Greek/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Greek/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.12.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Hebrew/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Hebrew/ERR_ICAP_FAILURE
+diff -N errors/Hebrew/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Hebrew/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Hungarian/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Hungarian/ERR_ICAP_FAILURE
+diff -N errors/Hungarian/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Hungarian/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Italian/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Italian/ERR_ICAP_FAILURE
+diff -N errors/Italian/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Italian/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Japanese/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Japanese/ERR_ICAP_FAILURE
+diff -N errors/Japanese/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Japanese/ERR_ICAP_FAILURE	17 May 2006 17:57:59 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Korean/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Korean/ERR_ICAP_FAILURE
+diff -N errors/Korean/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Korean/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Lithuanian/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Lithuanian/ERR_ICAP_FAILURE
+diff -N errors/Lithuanian/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Lithuanian/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Polish/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Polish/ERR_ICAP_FAILURE
+diff -N errors/Polish/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Polish/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Portuguese/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Portuguese/ERR_ICAP_FAILURE
+diff -N errors/Portuguese/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Portuguese/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Romanian/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Romanian/ERR_ICAP_FAILURE
+diff -N errors/Romanian/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Romanian/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Russian-1251/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Russian-1251/ERR_ICAP_FAILURE
+diff -N errors/Russian-1251/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Russian-1251/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Russian-koi8-r/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Russian-koi8-r/ERR_ICAP_FAILURE
+diff -N errors/Russian-koi8-r/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Russian-koi8-r/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Serbian/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Serbian/ERR_ICAP_FAILURE
+diff -N errors/Serbian/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Serbian/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Simplify_Chinese/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Simplify_Chinese/ERR_ICAP_FAILURE
+diff -N errors/Simplify_Chinese/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Simplify_Chinese/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Slovak/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Slovak/ERR_ICAP_FAILURE
+diff -N errors/Slovak/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Slovak/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Spanish/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Spanish/ERR_ICAP_FAILURE
+diff -N errors/Spanish/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Spanish/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Swedish/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Swedish/ERR_ICAP_FAILURE
+diff -N errors/Swedish/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Swedish/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Traditional_Chinese/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Traditional_Chinese/ERR_ICAP_FAILURE
+diff -N errors/Traditional_Chinese/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Traditional_Chinese/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: errors/Turkish/ERR_ICAP_FAILURE
+===================================================================
+RCS file: errors/Turkish/ERR_ICAP_FAILURE
+diff -N errors/Turkish/ERR_ICAP_FAILURE
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ errors/Turkish/ERR_ICAP_FAILURE	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,31 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
++<HTML><HEAD>
++<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
++<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
++</HEAD><BODY>
++<H1>ERROR</H1>
++<H2>The requested URL could not be retrieved</H2>
++<HR noshade size="1px">
++<P>
++While attempting to retrieve the URL:
++<A HREF="%U">%U</A>
++<P>
++the following error was encountered:
++<UL>
++<LI>
++<STRONG>
++ICAP protocol error.
++</STRONG>
++</UL>
++
++<P>
++<P>
++Some aspect of the ICAP communication failed. Possible problems:
++<UL>
++<LI>ICAP server is not reachable.
++<LI>Illegal response from ICAP server.
++</UL>
++</P>
++
++<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
++
+Index: include/util.h
+===================================================================
+RCS file: /cvsroot/squid/squid/include/util.h,v
+retrieving revision 1.17
+retrieving revision 1.13.8.3
+diff -p -u -b -r1.17 -r1.13.8.3
+--- include/util.h	10 Dec 2006 13:56:25 -0000	1.17
++++ include/util.h	12 Dec 2006 22:49:41 -0000	1.13.8.3
+@@ -157,4 +157,12 @@ extern void WIN32_maperror(unsigned long
+ extern int WIN32_Close_FD_Socket(int);
+ #endif
+ 
++#ifndef HAVE_STRNSTR
++extern char *strnstr(const char *haystack, const char *needle, size_t haystacklen);
++#endif
++
++#ifndef HAVE_STRCASESTR
++extern char *strcasestr(const char *haystack, const char *needle);
++#endif
++
+ #endif /* SQUID_UTIL_H */
+Index: lib/strcasestr.c
+===================================================================
+RCS file: lib/strcasestr.c
+diff -N lib/strcasestr.c
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ lib/strcasestr.c	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,126 @@
++/* Return the offset of one string within another.
++   Copyright (C) 1994,1996,1997,1998,1999,2000 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library 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
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++/*
++ * My personal strstr() implementation that beats most other algorithms.
++ * Until someone tells me otherwise, I assume that this is the
++ * fastest implementation of strstr() in C.
++ * I deliberately chose not to comment it.  You should have at least
++ * as much fun trying to understand it, as I had to write it :-).
++ *
++ * Stephen R. van den Berg, berg at pool.informatik.rwth-aachen.de	*/
++
++/* 
++ * modified to work outside of glibc (rhorstmann, 06/04/2004)
++ */
++
++#include "config.h"
++#ifndef  HAVE_STRCASESTR
++#include <ctype.h>
++
++typedef unsigned chartype;
++
++char *
++strcasestr (phaystack, pneedle)
++     const char *phaystack;
++     const char *pneedle;
++{
++  register const unsigned char *haystack, *needle;
++  register chartype b, c;
++
++  haystack = (const unsigned char *) phaystack;
++  needle = (const unsigned char *) pneedle;
++
++  b = tolower (*needle);
++  if (b != '\0')
++    {
++      haystack--;				/* possible ANSI violation */
++      do
++	{
++	  c = *++haystack;
++	  if (c == '\0')
++	    goto ret0;
++	}
++      while (tolower (c) != (int) b);
++
++      c = tolower (*++needle);
++      if (c == '\0')
++	goto foundneedle;
++      ++needle;
++      goto jin;
++
++      for (;;)
++        {
++          register chartype a;
++	  register const unsigned char *rhaystack, *rneedle;
++
++	  do
++	    {
++	      a = *++haystack;
++	      if (a == '\0')
++		goto ret0;
++	      if (tolower (a) == (int) b)
++		break;
++	      a = *++haystack;
++	      if (a == '\0')
++		goto ret0;
++shloop:
++	      ;
++	    }
++          while (tolower (a) != (int) b);
++
++jin:	  a = *++haystack;
++	  if (a == '\0')
++	    goto ret0;
++
++	  if (tolower (a) != (int) c)
++	    goto shloop;
++
++	  rhaystack = haystack-- + 1;
++	  rneedle = needle;
++	  a = tolower (*rneedle);
++
++	  if (tolower (*rhaystack) == (int) a)
++	    do
++	      {
++		if (a == '\0')
++		  goto foundneedle;
++		++rhaystack;
++		a = tolower (*++needle);
++		if (tolower (*rhaystack) != (int) a)
++		  break;
++		if (a == '\0')
++		  goto foundneedle;
++		++rhaystack;
++		a = tolower (*++needle);
++	      }
++	    while (tolower (*rhaystack) == (int) a);
++
++	  needle = rneedle;		/* took the register-poor approach */
++
++	  if (a == '\0')
++	    break;
++        }
++    }
++foundneedle:
++  return (char*) haystack;
++ret0:
++  return 0;
++}
++#endif
+Index: lib/strnstr.c
+===================================================================
+RCS file: lib/strnstr.c
+diff -N lib/strnstr.c
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ lib/strnstr.c	17 May 2006 17:58:00 -0000	1.1.14.1
+@@ -0,0 +1,52 @@
++/*
++ *  Copyright (C) 2003 Nikos Mavroyanopoulos
++ *
++ *  This file is part of GNUTLS.
++ *
++ *  The GNUTLS library is free software; you can redistribute it and/or
++ *  modify it under the terms of the GNU Lesser General Public   
++ *  License as published by the Free Software Foundation; either 
++ *  version 2.1 of the License, or (at your option) any later version.
++ *
++ *  This library 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
++ *  Lesser General Public License for more details.
++ *
++ *  You should have received a copy of the GNU Lesser General Public
++ *  License along with this library; if not, write to the Free Software
++ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
++ *
++ */
++
++ /*
++  * DW 2003/10/17:
++  * Changed 'ssize_t' types to 'size_t'
++  */
++
++#include "config.h"
++#ifndef HAVE_STRNSTR
++#include <string.h>
++#include <util.h>
++
++char *strnstr(const char *haystack, const char *needle, size_t haystacklen)
++{
++        char *p;
++        size_t plen;
++        size_t len = strlen(needle);
++
++        if (*needle == '\0')    /* everything matches empty string */
++                return (char*) haystack;
++
++        plen = haystacklen;
++        for (p = (char*) haystack; p != NULL; p = memchr(p + 1, *needle, plen-1)) {
++                plen = haystacklen - (p - haystack);
++
++                if (plen < len) return NULL;
++
++                if (strncmp(p, needle, len) == 0)
++                        return (p);
++        }
++        return NULL;
++}
++#endif
+Index: src/MemBuf.c
+===================================================================
+RCS file: /cvsroot/squid/squid/src/MemBuf.c,v
+retrieving revision 1.11
+retrieving revision 1.9.10.4
+diff -p -u -b -r1.11 -r1.9.10.4
+--- src/MemBuf.c	16 Aug 2006 00:53:02 -0000	1.11
++++ src/MemBuf.c	21 Aug 2006 19:48:09 -0000	1.9.10.4
+@@ -341,3 +341,15 @@ memBufReport(MemBuf * mb)
+     assert(mb);
+     memBufPrintf(mb, "memBufReport is not yet implemented @?@\n");
+ }
++
++int
++memBufRead(int fd, MemBuf * mb)
++{
++    int len;
++    if (mb->capacity == mb->size)
++	memBufGrow(mb, SQUID_TCP_SO_RCVBUF);
++    len = FD_READ_METHOD(fd, mb->buf + mb->size, mb->capacity - mb->size);
++    if (len > 0)
++	mb->size += len;
++    return len;
++}
+Index: src/cache_cf.c
+===================================================================
+RCS file: /cvsroot/squid/squid/src/cache_cf.c,v
+retrieving revision 1.86
+retrieving revision 1.61.4.12
+diff -p -u -b -r1.86 -r1.61.4.12
+--- src/cache_cf.c	10 Dec 2006 05:51:43 -0000	1.86
++++ src/cache_cf.c	12 Dec 2006 22:49:42 -0000	1.61.4.12
+@@ -2389,6 +2389,587 @@ check_null_body_size_t(dlink_list bodyli
+     return bodylist.head == NULL;
+ }
+ 
++#ifdef HS_FEAT_ICAP
++
++/***************************************************
++ * prototypes
++ */
++static int icap_service_process(icap_service * s);
++static void icap_service_init(icap_service * s);
++static void icap_service_destroy(icap_service * s);
++icap_service *icap_service_lookup(char *name);
++static int icap_class_process(icap_class * c);
++static void icap_class_destroy(icap_class * c);
++static void icap_access_destroy(icap_access * a);
++static void dump_wordlist(StoreEntry * entry, const char *name, const wordlist * list);
++static void icap_class_add(icap_class * c);
++
++/***************************************************
++ * icap_service
++ */
++
++/* 
++ * example:
++ * icap_service reqmode_precache 0 icap://192.168.0.1:1344/respmod
++ */
++
++static void
++parse_icap_service_type(IcapConfig * cfg)
++{
++    char *token;
++    icap_service *A = NULL;
++    icap_service *B = NULL;
++    icap_service **T = NULL;
++
++    A = cbdataAlloc(icap_service);
++    icap_service_init(A);
++    parse_string(&A->name);
++    parse_string(&A->type_name);
++    parse_ushort(&A->bypass);
++    parse_string(&A->uri);
++    while ((token = strtok(NULL, w_space))) {
++	if (strcasecmp(token, "no-keep-alive") == 0) {
++	    A->keep_alive = 0;
++	} else {
++	    debug(3, 0) ("parse_peer: token='%s'\n", token);
++	    self_destruct();
++	}
++    }
++    debug(3, 5) ("parse_icap_service_type (line %d): %s %s %d %s\n", config_lineno, A->name, A->type_name, A->bypass, A->name);
++    if (icap_service_process(A)) {
++	/* put into linked list */
++	for (B = cfg->service_head, T = &cfg->service_head; B; T = &B->next, B = B->next);
++	*T = A;
++    } else {
++	/* clean up structure */
++	debug(3, 0) ("parse_icap_service_type (line %d): skipping %s\n", config_lineno, A->name);
++	icap_service_destroy(A);
++	cbdataFree(A);
++    }
++
++}
++
++static void
++dump_icap_service_type(StoreEntry * e, const char *name, IcapConfig cfg)
++{
++    icap_service *current_node = NULL;
++
++    if (!cfg.service_head) {
++	storeAppendPrintf(e, "%s 0\n", name);
++	return;
++    }
++    current_node = cfg.service_head;
++
++    while (current_node) {
++	storeAppendPrintf(e, "%s %s %s %d %s", name, current_node->name, current_node->type_name, current_node->bypass, current_node->uri);
++	if (current_node->keep_alive == 0) {
++	    storeAppendPrintf(e, " no-keep-alive");
++	}
++	storeAppendPrintf(e, "\n");
++	current_node = current_node->next;
++    }
++
++}
++
++static void
++free_icap_service_type(IcapConfig * cfg)
++{
++    while (cfg->service_head) {
++	icap_service *current_node = cfg->service_head;
++	cfg->service_head = current_node->next;
++	icap_service_destroy(current_node);
++	cbdataFree(current_node);
++    }
++}
++
++/* 
++ * parse the raw string and cache some parts that are needed later 
++ * returns 1 if everything was ok
++ */
++static int
++icap_service_process(icap_service * s)
++{
++    char *start, *end, *tempEnd;
++    char *tailp;
++    unsigned int len;
++    int port_in_uri, resource_in_uri = 0;
++    s->type = icapServiceToType(s->type_name);
++    if (s->type >= ICAP_SERVICE_MAX) {
++	debug(3, 0) ("icap_service_process (line %d): wrong service type %s\n", config_lineno, s->type_name);
++	return 0;
++    }
++    if (s->type == ICAP_SERVICE_REQMOD_PRECACHE)
++	s->method = ICAP_METHOD_REQMOD;
++    else if (s->type == ICAP_SERVICE_REQMOD_PRECACHE)
++	s->method = ICAP_METHOD_REQMOD;
++    else if (s->type == ICAP_SERVICE_REQMOD_POSTCACHE)
++	s->method = ICAP_METHOD_REQMOD;
++    else if (s->type == ICAP_SERVICE_RESPMOD_PRECACHE)
++	s->method = ICAP_METHOD_RESPMOD;
++    else if (s->type == ICAP_SERVICE_RESPMOD_POSTCACHE)
++	s->method = ICAP_METHOD_RESPMOD;
++    debug(3, 5) ("icap_service_process (line %d): type=%s\n", config_lineno, icapServiceToStr(s->type));
++    if (strncmp(s->uri, "icap://", 7) != 0) {
++	debug(3, 0) ("icap_service_process (line %d): wrong uri: %s\n", config_lineno, s->uri);
++	return 0;
++    }
++    start = s->uri + 7;
++    if ((end = strchr(start, ':')) != NULL) {
++	/* ok */
++	port_in_uri = 1;
++	debug(3, 5) ("icap_service_process (line %d): port given\n", config_lineno);
++    } else {
++	/* ok */
++	port_in_uri = 0;
++	debug(3, 5) ("icap_service_process (line %d): no port given\n", config_lineno);
++    }
++
++    if ((tempEnd = strchr(start, '/')) != NULL) {
++	/* ok */
++	resource_in_uri = 1;
++	debug(3, 5) ("icap_service_process (line %d): resource given\n", config_lineno);
++	if (end == '\0') {
++	    end = tempEnd;
++	}
++    } else {
++	/* ok */
++	resource_in_uri = 0;
++	debug(3, 5) ("icap_service_process (line %d): no resource given\n", config_lineno);
++    }
++
++    tempEnd = strchr(start, '\0');
++    if (end == '\0') {
++	end = tempEnd;
++    }
++    len = end - start;
++    s->hostname = xstrndup(start, len + 1);
++    s->hostname[len] = 0;
++    debug(3, 5) ("icap_service_process (line %d): hostname=%s\n", config_lineno, s->hostname);
++    start = end;
++
++    if (port_in_uri) {
++	start++;		/* skip ':' */
++	if (resource_in_uri)
++	    end = strchr(start, '/');
++	else
++	    end = strchr(start, '\0');
++	s->port = strtoul(start, &tailp, 0) % 65536;
++	if (tailp != end) {
++	    debug(3, 0) ("icap_service_process (line %d): wrong service uri (port could not be parsed): %s\n", config_lineno, s->uri);
++	    return 0;
++	}
++	debug(3, 5) ("icap_service_process (line %d): port=%d\n", config_lineno, s->port);
++	start = end;
++    } else {
++	/* no explicit ICAP port; first ask by getservbyname or default to
++	 * hardwired port 1344 per ICAP specification section 4.2 */
++	struct servent *serv = getservbyname("icap", "tcp");
++	if (serv) {
++	    s->port = htons(serv->s_port);
++	    debug(3, 5) ("icap_service_process (line %d): default port=%d getservbyname(icap,tcp)\n", config_lineno, s->port);
++	} else {
++	    s->port = 1344;
++	    debug(3, 5) ("icap_service_process (line %d): default hardwired port=%d\n", config_lineno, s->port);
++	}
++    }
++
++    if (resource_in_uri) {
++	start++;		/* skip '/' */
++	/* the rest is resource name */
++	end = strchr(start, '\0');
++	len = end - start;
++	if (len > 1024) {
++	    debug(3, 0) ("icap_service_process (line %d): long resource name (>1024), probably wrong\n", config_lineno);
++	}
++	s->resource = xstrndup(start, len + 1);
++	s->resource[len] = 0;
++	debug(3, 5) ("icap_service_process (line %d): service=%s\n", config_lineno, s->resource);
++    }
++    /* check bypass */
++    if ((s->bypass != 0) && (s->bypass != 1)) {
++	debug(3, 0) ("icap_service_process (line %d): invalid bypass value\n", config_lineno);
++	return 0;
++    }
++    return 1;
++}
++
++/*
++ * constructor
++ */
++static void
++icap_service_init(icap_service * s)
++{
++    s->type = ICAP_SERVICE_MAX;	/* means undefined */
++    s->preview = Config.icapcfg.preview_size;
++    s->opt = 0;
++    s->keep_alive = 1;
++    s->istag = StringNull;
++    s->transfer_preview = StringNull;
++    s->transfer_ignore = StringNull;
++    s->transfer_complete = StringNull;
++}
++
++/*
++ * destructor
++ * frees only strings, but don't touch the linked list
++ */
++static void
++icap_service_destroy(icap_service * s)
++{
++    xfree(s->name);
++    xfree(s->uri);
++    xfree(s->type_name);
++    xfree(s->hostname);
++    xfree(s->resource);
++    assert(s->opt == 0);	/* there should be no opt request running now */
++    stringClean(&s->istag);
++    stringClean(&s->transfer_preview);
++    stringClean(&s->transfer_ignore);
++    stringClean(&s->transfer_complete);
++}
++
++icap_service *
++icap_service_lookup(char *name)
++{
++    icap_service *iter;
++    for (iter = Config.icapcfg.service_head; iter; iter = iter->next) {
++	if (!strcmp(name, iter->name)) {
++	    return iter;
++	}
++    }
++    return NULL;
++}
++
++/***************************************************
++ * icap_service_list
++ */
++
++static void
++icap_service_list_add(icap_service_list ** isl, char *service_name)
++{
++    icap_service_list **iter;
++    icap_service_list *new;
++    icap_service *gbl_service;
++    int i;
++    int max_services;
++
++    new = memAllocate(MEM_ICAP_SERVICE_LIST);
++    /* Found all services with that name, and add to the array */
++    max_services = sizeof(new->services) / sizeof(icap_service *);
++    gbl_service = Config.icapcfg.service_head;
++    i = 0;
++    while (gbl_service && i < max_services) {
++	if (!strcmp(service_name, gbl_service->name))
++	    new->services[i++] = gbl_service;
++	gbl_service = gbl_service->next;
++    }
++    new->nservices = i;
++
++    if (*isl) {
++	iter = isl;
++	while ((*iter)->next)
++	    iter = &((*iter)->next);
++	(*iter)->next = new;
++    } else {
++	*isl = new;
++    }
++}
++
++/*
++ * free the linked list without touching references icap_service
++ */
++static void
++icap_service_list_destroy(icap_service_list * isl)
++{
++    icap_service_list *current;
++    icap_service_list *next;
++
++    current = isl;
++    while (current) {
++	next = current->next;
++	memFree(current, MEM_ICAP_SERVICE_LIST);
++	current = next;
++    }
++}
++
++/***************************************************
++ * icap_class
++ */
++static void
++parse_icap_class_type(IcapConfig * cfg)
++{
++    icap_class *s = NULL;
++
++    s = memAllocate(MEM_ICAP_CLASS);
++    parse_string(&s->name);
++    parse_wordlist(&s->services);
++
++    if (icap_class_process(s)) {
++	/* if ok, put into linked list */
++	icap_class_add(s);
++    } else {
++	/* clean up structure */
++	debug(3, 0) ("parse_icap_class_type (line %d): skipping %s\n", config_lineno, s->name);
++	icap_class_destroy(s);
++	memFree(s, MEM_ICAP_CLASS);
++    }
++}
++
++static void
++dump_icap_class_type(StoreEntry * e, const char *name, IcapConfig cfg)
++{
++    icap_class *current_node = NULL;
++    LOCAL_ARRAY(char, nom, 64);
++
++    if (!cfg.class_head) {
++	storeAppendPrintf(e, "%s 0\n", name);
++	return;
++    }
++    current_node = cfg.class_head;
++
++    while (current_node) {
++	snprintf(nom, 64, "%s %s", name, current_node->name);
++	dump_wordlist(e, nom, current_node->services);
++	current_node = current_node->next;
++    }
++}
++
++static void
++free_icap_class_type(IcapConfig * cfg)
++{
++    while (cfg->class_head) {
++	icap_class *current_node = cfg->class_head;
++	cfg->class_head = current_node->next;
++	icap_class_destroy(current_node);
++	memFree(current_node, MEM_ICAP_CLASS);
++    }
++}
++
++/*
++ * process services list, return 1, if at least one service was found
++ */
++static int
++icap_class_process(icap_class * c)
++{
++    icap_service_list *isl = NULL;
++    wordlist *iter;
++    icap_service *service;
++    /* take services list and build icap_service_list from it */
++    for (iter = c->services; iter; iter = iter->next) {
++	service = icap_service_lookup(iter->key);
++	if (service) {
++	    icap_service_list_add(&isl, iter->key);
++	} else {
++	    debug(3, 0) ("icap_class_process (line %d): skipping service %s in class %s\n", config_lineno, iter->key, c->name);
++	}
++    }
++
++    if (isl) {
++	c->isl = isl;
++	return 1;
++    }
++    return 0;
++}
++
++/*
++ * search for an icap_class in the global IcapConfig
++ * classes with hidden-flag are skipped
++ */
++static icap_class *
++icap_class_lookup(char *name)
++{
++    icap_class *iter;
++    for (iter = Config.icapcfg.class_head; iter; iter = iter->next) {
++	if ((!strcmp(name, iter->name)) && (!iter->hidden)) {
++	    return iter;
++	}
++    }
++    return NULL;
++}
++
++/*
++ * adds an icap_class to the global IcapConfig
++ */
++static void
++icap_class_add(icap_class * c)
++{
++    icap_class *cp = NULL;
++    icap_class **t = NULL;
++    IcapConfig *cfg = &Config.icapcfg;
++    if (c) {
++	for (cp = cfg->class_head, t = &cfg->class_head; cp; t = &cp->next, cp = cp->next);
++	*t = c;
++    }
++}
++
++/*
++ * free allocated memory inside icap_class
++ */
++static void
++icap_class_destroy(icap_class * c)
++{
++    xfree(c->name);
++    wordlistDestroy(&c->services);
++    icap_service_list_destroy(c->isl);
++}
++
++/***************************************************
++ * icap_access
++ */
++
++/* format: icap_access <servicename> {allow|deny} acl, ... */
++static void
++parse_icap_access_type(IcapConfig * cfg)
++{
++    icap_access *A = NULL;
++    icap_access *B = NULL;
++    icap_access **T = NULL;
++    icap_service *s = NULL;
++    icap_class *c = NULL;
++    ushort no_class = 0;
++
++    A = memAllocate(MEM_ICAP_ACCESS);
++    parse_string(&A->service_name);
++
++    /* 
++     * try to find a class with the given name first. if not found, search 
++     * the services. if a service is found, create a new hidden class with 
++     * only this service. this is for backward compatibility.
++     *
++     * the special classname All is allowed only in deny rules, because
++     * the class is not used there.
++     */
++    if (!strcmp(A->service_name, "None")) {
++	no_class = 1;
++    } else {
++	A->class = icap_class_lookup(A->service_name);
++	if (!A->class) {
++	    s = icap_service_lookup(A->service_name);
++	    if (s) {
++		c = memAllocate(MEM_ICAP_CLASS);
++		c->name = xstrdup("(hidden)");
++		c->hidden = 1;
++		wordlistAdd(&c->services, A->service_name);
++		c->isl = memAllocate(MEM_ICAP_SERVICE_LIST);
++		/* FIXME:luc: check what access do */
++		c->isl->services[0] = s;
++		c->isl->nservices = 1;
++		icap_class_add(c);
++		A->class = c;
++	    } else {
++		debug(3, 0) ("parse_icap_access_type (line %d): servicename %s not found. skipping.\n", config_lineno, A->service_name);
++		memFree(A, MEM_ICAP_ACCESS);
++		return;
++	    }
++	}
++    }
++
++    aclParseAccessLine(&(A->access));
++    debug(3, 5) ("parse_icap_access_type (line %d): %s\n", config_lineno, A->service_name);
++
++    /* check that All class is only used in deny rule */
++    if (no_class && A->access->allow) {
++	memFree(A, MEM_ICAP_ACCESS);
++	debug(3, 0) ("parse_icap_access (line %d): special class 'None' only allowed in deny rule. skipping.\n", config_lineno);
++	return;
++    }
++    if (A->access) {
++	for (B = cfg->access_head, T = &cfg->access_head; B; T = &B->next, B = B->next);
++	*T = A;
++    } else {
++	debug(3, 0) ("parse_icap_access_type (line %d): invalid line skipped\n", config_lineno);
++	memFree(A, MEM_ICAP_ACCESS);
++    }
++}
++
++static void
++dump_icap_access_type(StoreEntry * e, const char *name, IcapConfig cfg)
++{
++    icap_access *current_node = NULL;
++    LOCAL_ARRAY(char, nom, 64);
++
++    if (!cfg.access_head) {
++	storeAppendPrintf(e, "%s 0\n", name);
++	return;
++    }
++    current_node = cfg.access_head;
++
++    while (current_node) {
++	snprintf(nom, 64, "%s %s", name, current_node->service_name);
++	dump_acl_access(e, nom, current_node->access);
++	current_node = current_node->next;
++    }
++}
++
++static void
++free_icap_access_type(IcapConfig * cfg)
++{
++    while (cfg->access_head) {
++	icap_access *current_node = cfg->access_head;
++	cfg->access_head = current_node->next;
++	icap_access_destroy(current_node);
++	memFree(current_node, MEM_ICAP_ACCESS);
++    }
++}
++
++/*
++ * destructor
++ * frees everything but the linked list
++ */
++static void
++icap_access_destroy(icap_access * a)
++{
++    xfree(a->service_name);
++    aclDestroyAccessList(&a->access);
++}
++
++/***************************************************
++ * for debugging purposes only
++ */
++void
++dump_icap_config(IcapConfig * cfg)
++{
++    icap_service *s_iter;
++    icap_class *c_iter;
++    icap_access *a_iter;
++    icap_service_list *isl_iter;
++    acl_list *l;
++    debug(3, 0) ("IcapConfig: onoff        = %d\n", cfg->onoff);
++    debug(3, 0) ("IcapConfig: service_head = %d\n", (int) cfg->service_head);
++    debug(3, 0) ("IcapConfig: class_head   = %d\n", (int) cfg->class_head);
++    debug(3, 0) ("IcapConfig: access_head  = %d\n", (int) cfg->access_head);
++
++    debug(3, 0) ("IcapConfig: services =\n");
++    for (s_iter = cfg->service_head; s_iter; s_iter = s_iter->next) {
++	printf("  %s: \n", s_iter->name);
++	printf("    bypass   = %d\n", s_iter->bypass);
++	printf("    hostname = %s\n", s_iter->hostname);
++	printf("    port     = %d\n", s_iter->port);
++	printf("    resource = %s\n", s_iter->resource);
++    }
++    debug(3, 0) ("IcapConfig: classes =\n");
++    for (c_iter = cfg->class_head; c_iter; c_iter = c_iter->next) {
++	printf("  %s: \n", c_iter->name);
++	printf("    services = \n");
++	for (isl_iter = c_iter->isl; isl_iter; isl_iter = isl_iter->next) {
++	    int i;
++	    for (i = 0; i < isl_iter->nservices; i++)
++		printf("      %s\n", isl_iter->services[i]->name);
++	}
++    }
++    debug(3, 0) ("IcapConfig: access =\n");
++    for (a_iter = cfg->access_head; a_iter; a_iter = a_iter->next) {
++	printf("  service_name  = %s\n", a_iter->service_name);
++	printf("    access        = %s", a_iter->access->allow ? "allow" : "deny");
++	for (l = a_iter->access->acl_list; l != NULL; l = l->next) {
++	    printf(" %s%s",
++		l->op ? null_string : "!",
++		l->acl->name);
++	}
++	printf("\n");
++    }
++}
++#endif /* HS_FEAT_ICAP */
+ 
+ static void
+ parse_kb_size_t(squid_off_t * var)
+Index: src/cbdata.c
+===================================================================
+RCS file: /cvsroot/squid/squid/src/cbdata.c,v
+retrieving revision 1.18
+retrieving revision 1.18.8.1
+diff -p -u -b -r1.18 -r1.18.8.1
+--- src/cbdata.c	12 May 2006 22:51:56 -0000	1.18
++++ src/cbdata.c	17 May 2006 17:58:00 -0000	1.18.8.1
+@@ -179,6 +179,10 @@ cbdataInit(void)
+     CREATE_CBDATA(statefulhelper);
+     CREATE_CBDATA(helper_stateful_server);
+     CREATE_CBDATA(HttpStateData);
++#ifdef HS_FEAT_ICAP
++    CREATE_CBDATA(IcapStateData);
++    CREATE_CBDATA(icap_service);
++#endif
+     CREATE_CBDATA_FREE(peer, peerDestroy);
+     CREATE_CBDATA(ps_state);
+     CREATE_CBDATA(RemovalPolicy);
+Index: src/cf.data.pre
+===================================================================
+RCS file: /cvsroot/squid/squid/src/cf.data.pre,v
+retrieving revision 1.161
+retrieving revision 1.100.4.12
+diff -p -u -b -r1.161 -r1.100.4.12
+--- src/cf.data.pre	29 Nov 2006 00:52:57 -0000	1.161
++++ src/cf.data.pre	12 Dec 2006 22:49:42 -0000	1.100.4.12
+@@ -3189,7 +3189,6 @@ DOC_START
+ 	ensure correct results it is best to set server_persistent_connections
+ 	to off when using this directive in such configurations.
+ DOC_END
+-
+ NAME: reply_header_max_size
+ COMMENT: (KB)
+ TYPE: b_size_t
+@@ -3458,6 +3457,187 @@ DOC_START
+ DOC_END
+ 
+ COMMENT_START
++ ICAP OPTIONS
++ -----------------------------------------------------------------------------
++COMMENT_END
++
++NAME: icap_enable
++TYPE: onoff
++IFDEF: HS_FEAT_ICAP
++COMMENT: on|off
++LOC: Config.icapcfg.onoff
++DEFAULT: off
++DOC_START
++	If you want to enable the ICAP client module, set this to on.
++DOC_END
++
++NAME: icap_preview_enable
++TYPE: onoff
++IFDEF: HS_FEAT_ICAP
++COMMENT: on|off
++LOC: Config.icapcfg.preview_enable
++DEFAULT: off
++DOC_START
++	Set this to 'on' if you want to enable the ICAP preview
++	feature in Squid.
++DOC_END
++
++NAME: icap_preview_size
++TYPE: int
++IFDEF: HS_FEAT_ICAP
++LOC: Config.icapcfg.preview_size
++DEFAULT: -1
++DOC_START
++	The default size of preview data to be sent to the ICAP server.
++	-1 means no preview. This value might be overwritten on a per server
++	basis by OPTIONS requests.
++DOC_END
++
++NAME: icap_check_interval
++TYPE: int
++IFDEF: HS_FEAT_ICAP
++LOC: Config.icapcfg.check_interval
++DEFAULT: 300
++DOC_START
++        If an ICAP server does not respond, it gets marked as unreachable. Squid
++	will try again to reach it after this time.
++DOC_END
++
++NAME: icap_send_client_ip
++TYPE: onoff
++IFDEF: HS_FEAT_ICAP
++COMMENT: on|off
++LOC: Config.icapcfg.send_client_ip
++DEFAULT: off
++DOC_START
++	Allows Squid to add the "X-Client-IP" header if requested by
++	an ICAP service in it's response to OPTIONS.
++DOC_END
++
++NAME: icap_send_server_ip
++TYPE: onoff
++IFDEF: HS_FEAT_ICAP
++COMMENT: on|off
++LOC: Config.icapcfg.send_server_ip
++DEFAULT: off
++DOC_START
++	Allows Squid to add the "X-Server-IP" header if requested by
++	an ICAP service in it's response to OPTIONS.
++DOC_END
++
++NAME: icap_send_auth_user
++TYPE: onoff
++IFDEF: HS_FEAT_ICAP
++COMMENT: on|off
++LOC: Config.icapcfg.send_auth_user
++DEFAULT: off
++DOC_START
++	Allows Squid to add the "X-Authenticated-User" header if requested
++	by an ICAP service in it's response to OPTIONS.
++DOC_END
++
++NAME: icap_auth_scheme
++TYPE: string
++IFDEF: HS_FEAT_ICAP
++LOC: Config.icapcfg.auth_scheme
++DEFAULT: Local://%u
++DOC_START
++	Authentification scheme to pass to ICAP requests if
++	icap_send_auth_user is enabled. The first occurence of "%u"
++	is replaced by the authentified user name. If no "%u" is found,
++	the username is added at the end of the scheme.
++	
++	See http://www.ietf.org/internet-drafts/draft-stecher-icap-subid-00.txt,
++	section 3.4 for details on this.
++
++	Examples:
++
++	icap_auth_scheme Local://%u
++	icap_auth_scheme LDAP://ldap-server/cn=%u,dc=company,dc=com
++	icap_auth_scheme WinNT://nt-domain/%u
++	icap_auth_scheme Radius://radius-server/%u
++DOC_END
++
++NAME: icap_service
++TYPE: icap_service_type
++IFDEF: HS_FEAT_ICAP
++LOC: Config.icapcfg
++DEFAULT: none
++DOC_START
++	Defines a single ICAP service
++
++	icap_service servicename vectoring_point bypass service_url [options ...]
++
++	vectoring_point = reqmod_precache|reqmod_postcache|respmod_precache|respmod_postcache
++		This specifies at which point of request processing the ICAP
++		service should be plugged in.
++	bypass = 1|0   
++		If set to 1 and the ICAP server cannot be reached, the request will go 
++		through without being processed by an ICAP server
++	service_url = icap://servername:port/service
++
++	Options: 
++
++        no-keep-alive	To always close the connection to icap server
++        		after the transaction completes
++
++
++	Note: reqmod_precache and respmod_postcache is not yet implemented
++
++	Load-balancing and high availability:
++	You can obtain load-balancing and high availability by defining a
++	named service with different definitions.  Then, the client
++	loops through the different entities of the service providing
++	load-balancing. If an entity is marked as unreachable, the client goes
++	one step further to the next entity: you have the high-availability.
++	See the service_1 definition below
++
++Example:
++icap_service service_1 reqmod_precache 0 icap://icap1.mydomain.net:1344/reqmod
++icap_service service_1 reqmod_precache 0 icap://icap2.mydomain.net:1344/reqmod no-keep-alive
++icap_service service_2 respmod_precache 0 icap://icap3.mydomain.net:1344/respmod 
++DOC_END
++
++NAME: icap_class
++TYPE: icap_class_type
++IFDEF: HS_FEAT_ICAP
++LOC: Config.icapcfg
++DEFAULT: none
++DOC_START
++	Defines an ICAP service chain. If there are multiple services per 
++	vectoring point, they are processed in the specified order.
++
++	icap_class classname servicename...
++
++Example:
++icap_class class_1 service_1 service_2
++icap class class_2 service_1 service_3
++DOC_END
++
++NAME: icap_access
++TYPE: icap_access_type
++IFDEF: HS_FEAT_ICAP
++LOC: Config.icapcfg
++DEFAULT: none
++DOC_START
++	Redirects a request through an ICAP service class, depending
++	on given acls
++
++	icap_access classname allow|deny [!]aclname...
++
++	The icap_access statements are processed in the order they appear in
++	this configuration file. If an access list matches, the processing stops. 
++	For an "allow" rule, the specified class is used for the request. A "deny" 
++	rule simply stops processing without using the class. You can also use the 
++	special classname "None". 
++	
++	For backward compatibility, it is also possible to use services 
++	directly here.
++Example:
++icap_access class_1 allow all
++DOC_END
++
++COMMENT_START
+  MISCELLANEOUS
+  -----------------------------------------------------------------------------
+ COMMENT_END
+Index: src/cf_gen_defines
+===================================================================
+RCS file: /cvsroot/squid/squid/src/cf_gen_defines,v
+retrieving revision 1.7
+retrieving revision 1.6.8.2
+diff -p -u -b -r1.7 -r1.6.8.2
+--- src/cf_gen_defines	31 May 2006 19:51:14 -0000	1.7
++++ src/cf_gen_defines	4 Jun 2006 14:15:43 -0000	1.6.8.2
+@@ -22,6 +22,7 @@ BEGIN {
+ 	define["USE_WCCP"]="--enable-wccp"
+ 	define["USE_WCCPv2"]="--enable-wccpv2"
+ 	define["WIP_FWD_LOG"]="--enable-forward-log"
++	define["HS_FEAT_ICAP"]="--enable-icap-support"
+ }
+ /^IFDEF:/ {
+ 	if (define[$2] != "")
+Index: src/client_side.c
+===================================================================
+--- src/client_side.c.orig	Wed Mar 14 15:11:26 2007
++++ src/client_side.c	Sun Mar 18 11:16:30 2007
+@@ -109,7 +109,7 @@ static const char *const crlf = "\r\n";
+ static CWCB clientWriteComplete;
+ static CWCB clientWriteBodyComplete;
+ static PF clientReadRequest;
+-static PF connStateFree;
++PF connStateFree;
+ static PF requestTimeout;
+ static PF clientLifetimeTimeout;
+ static int clientCheckTransferDone(clientHttpRequest *);
+@@ -141,12 +141,12 @@ static void clientSetKeepaliveFlag(clien
+ static void clientPackRangeHdr(const HttpReply * rep, const HttpHdrRangeSpec * spec, String boundary, MemBuf * mb);
+ static void clientPackTermBound(String boundary, MemBuf * mb);
+ static void clientInterpretRequestHeaders(clientHttpRequest *);
+-static void clientProcessRequest(clientHttpRequest *);
++void clientProcessRequest(clientHttpRequest *);
+ static void clientProcessExpired(void *data);
+ static void clientProcessOnlyIfCachedMiss(clientHttpRequest * http);
+-static int clientCachable(clientHttpRequest * http);
+-static int clientHierarchical(clientHttpRequest * http);
+-static int clientCheckContentLength(request_t * r);
++int clientCachable(clientHttpRequest * http);
++int clientHierarchical(clientHttpRequest * http);
++int clientCheckContentLength(request_t * r);
+ static DEFER httpAcceptDefer;
+ static log_type clientProcessRequest2(clientHttpRequest * http);
+ static int clientReplyBodyTooLarge(clientHttpRequest *, squid_off_t clen);
+@@ -157,15 +157,18 @@ static void clientAccessCheck(void *data
+ static void clientAccessCheckDone(int answer, void *data);
+ static void clientAccessCheck2(void *data);
+ static void clientAccessCheckDone2(int answer, void *data);
+-static BODY_HANDLER clientReadBody;
++BODY_HANDLER clientReadBody;
+ static void clientAbortBody(request_t * req);
+ #if USE_SSL
+ static void httpsAcceptSSL(ConnStateData * connState, SSL_CTX * sslContext);
+ #endif
+ static int varyEvaluateMatch(StoreEntry * entry, request_t * request);
+ static int modifiedSince(StoreEntry *, request_t *);
+-static StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, request_flags);
++StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, request_flags);
+ static inline int clientNatLookup(ConnStateData * conn);
++#if HS_FEAT_ICAP
++static int clientIcapReqMod(clientHttpRequest * http);
++#endif
+ 
+ #if USE_IDENT
+ static void
+@@ -383,7 +386,7 @@ clientOnlyIfCached(clientHttpRequest * h
+ 	EBIT_TEST(r->cache_control->mask, CC_ONLY_IF_CACHED);
+ }
+ 
+-static StoreEntry *
++StoreEntry *
+ clientCreateStoreEntry(clientHttpRequest * h, method_t m, request_flags flags)
+ {
+     StoreEntry *e;
+@@ -640,6 +643,10 @@ clientRedirectDone(void *data, char *res
+     if (urlgroup && *urlgroup)
+ 	http->request->urlgroup = xstrdup(urlgroup);
+     clientInterpretRequestHeaders(http);
++#if HS_FEAT_ICAP
++    if (Config.icapcfg.onoff)
++	icapCheckAcl(http);
++#endif
+ #if HEADERS_LOG
+     headersLog(0, 1, request->method, request);
+ #endif
+@@ -1368,11 +1375,22 @@ httpRequestFree(void *data)
+     /* Unlink us from the clients request list */
+     dlinkDelete(&http->node, &http->conn->reqs);
+     dlinkDelete(&http->active, &ClientActiveRequests);
++#if HS_FEAT_ICAP
++    /*In the case that the upload of data breaks, we need this code here ....  */
++    if (NULL != http->icap_reqmod) {
++	if (cbdataValid(http->icap_reqmod))
++	    if (http->icap_reqmod->icap_fd > -1) {
++		comm_close(http->icap_reqmod->icap_fd);
++	    }
++	cbdataUnlock(http->icap_reqmod);
++	http->icap_reqmod = NULL;
++    }
++#endif
+     cbdataFree(http);
+ }
+ 
+ /* This is a handler normally called by comm_close() */
+-static void
++void
+ connStateFree(int fd, void *data)
+ {
+     ConnStateData *connState = data;
+@@ -1392,8 +1410,9 @@ connStateFree(int fd, void *data)
+ 	authenticateAuthUserRequestUnlock(connState->auth_user_request);
+     connState->auth_user_request = NULL;
+     authenticateOnCloseConnection(connState);
++    if (connState->in.buf)
+     memFreeBuf(connState->in.size, connState->in.buf);
+-    pconnHistCount(0, connState->nrequests);
++/*  pconnHistCount(0, connState->nrequests);*/
+     if (connState->pinning.fd >= 0)
+ 	comm_close(connState->pinning.fd);
+     cbdataFree(connState);
+@@ -1591,7 +1610,7 @@ clientSetKeepaliveFlag(clientHttpRequest
+     }
+ }
+ 
+-static int
++int
+ clientCheckContentLength(request_t * r)
+ {
+     switch (r->method) {
+@@ -1610,7 +1629,7 @@ clientCheckContentLength(request_t * r)
+     /* NOT REACHED */
+ }
+ 
+-static int
++int
+ clientCachable(clientHttpRequest * http)
+ {
+     request_t *req = http->request;
+@@ -1636,7 +1655,7 @@ clientCachable(clientHttpRequest * http)
+ }
+ 
+ /* Return true if we can query our neighbors for this object */
+-static int
++int
+ clientHierarchical(clientHttpRequest * http)
+ {
+     const char *url = http->uri;
+@@ -3302,7 +3321,7 @@ clientProcessRequest2(clientHttpRequest 
+     return LOG_TCP_HIT;
+ }
+ 
+-static void
++void
+ clientProcessRequest(clientHttpRequest * http)
+ {
+     char *url = http->uri;
+@@ -3313,6 +3332,11 @@ clientProcessRequest(clientHttpRequest *
+ 	RequestMethodStr[r->method],
+ 	url);
+     r->flags.collapsed = 0;
++#if HS_FEAT_ICAP
++    if (clientIcapReqMod(http)) {
++	return;
++    }
++#endif
+     if (r->method == METHOD_CONNECT && !http->redirect.status) {
+ 	http->log_type = LOG_TCP_MISS;
+ #if USE_SSL && SSL_CONNECT_INTERCEPT
+@@ -3808,6 +3832,20 @@ clientReadRequest(int fd, void *data)
+ 	    (long) conn->in.offset, (long) conn->in.size);
+ 	len = conn->in.size - conn->in.offset - 1;
+     }
++#if HS_FEAT_ICAP
++    /*
++     * This check exists because ICAP doesn't always work well
++     * with persistent (reused) connections.  One version of the
++     * REQMOD code creates a fake ConnStateData, which doesn't have
++     * an in.buf.  We want to make sure that the fake ConnStateData
++     * doesn't get used here.
++     */
++    if (NULL == conn->in.buf) {
++	debug(33, 1) ("clientReadRequest: FD %d aborted; conn->in.buf is NULL\n", fd);
++	comm_close(fd);
++	return;
++    }
++#endif
+     statCounter.syscalls.sock.reads++;
+     size = FD_READ_METHOD(fd, conn->in.buf + conn->in.offset, len);
+     if (size > 0) {
+@@ -3913,6 +3951,8 @@ clientReadRequest(int fd, void *data)
+ 	    dlinkAddTail(http, &http->node, &conn->reqs);
+ 	    conn->nrequests++;
+ 	    commSetTimeout(fd, Config.Timeout.lifetime, clientLifetimeTimeout, http);
++	    F->pconn.uses++;
++            F->pconn.type = 0;
+ 	    if (parser_return_code < 0) {
+ 		debug(33, 1) ("clientReadRequest: FD %d (%s:%d) Invalid Request\n", fd, fd_table[fd].ipaddr, fd_table[fd].remote_port);
+ 		err = errorCon(ERR_INVALID_REQ, HTTP_BAD_REQUEST, NULL);
+@@ -4082,7 +4122,7 @@ clientReadRequest(int fd, void *data)
+ }
+ 
+ /* file_read like function, for reading body content */
+-static void
++void
+ clientReadBody(request_t * request, char *buf, size_t size, CBCB * callback, void *cbdata)
+ {
+     ConnStateData *conn = request->body_reader_data;
+@@ -4211,7 +4251,7 @@ clientProcessBody(ConnStateData * conn)
+ }
+ 
+ /* Abort a body request */
+-static void
++void
+ clientAbortBody(request_t * request)
+ {
+     ConnStateData *conn = request->body_reader_data;
+@@ -4253,7 +4293,7 @@ requestTimeout(int fd, void *data)
+ 	 * Some data has been sent to the client, just close the FD
+ 	 */
+ 	comm_close(fd);
+-    } else if (conn->nrequests) {
++    } else if (fd_table[fd].pconn.uses) {
+ 	/*
+ 	 * assume its a persistent connection; just close it
+ 	 */
+@@ -4974,6 +5014,52 @@ varyEvaluateMatch(StoreEntry * entry, re
+ 	}
+     }
+ }
++
++#if HS_FEAT_ICAP
++static int
++clientIcapReqMod(clientHttpRequest * http)
++{
++    ErrorState *err;
++    icap_service *service;
++    if (http->flags.did_icap_reqmod)
++	return 0;
++    if (NULL == (service = icapService(ICAP_SERVICE_REQMOD_PRECACHE, http->request)))
++	return 0;
++    debug(33, 3) ("clientIcapReqMod: calling icapReqModStart for %p\n", http);
++    /*
++     * Note, we pass 'start' and 'log_addr' to ICAP so the access.log
++     * entry comes out right.  The 'clientHttpRequest' created by
++     * the ICAP side is the one that gets logged.  The first
++     * 'clientHttpRequest' does not get logged because its out.size
++     * is zero and log_type is unset.
++     */
++    http->icap_reqmod = icapReqModStart(service,
++	http->uri,
++	http->request,
++	http->conn->fd,
++	http->start,
++	http->conn->log_addr,
++	(void *) http->conn);
++    if (NULL == http->icap_reqmod) {
++	return 0;
++    } else if (-1 == (int) http->icap_reqmod) {
++	/* produce error */
++	http->icap_reqmod = NULL;
++	debug(33, 2) ("clientIcapReqMod: icap told us to send an error\n");
++	http->log_type = LOG_TCP_DENIED;
++	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, http->orig_request);
++	err->xerrno = ETIMEDOUT;
++	err->request = requestLink(http->request);
++	err->src_addr = http->conn->peer.sin_addr;
++	http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags);
++	errorAppendEntry(http->entry, err);
++	return 1;
++    }
++    cbdataLock(http->icap_reqmod);
++    http->flags.did_icap_reqmod = 1;
++    return 1;
++}
++#endif
+ 
+ /* This is a handler normally called by comm_close() */
+ static void
+Index: src/comm.c
+===================================================================
+RCS file: /cvsroot/squid/squid/src/comm.c,v
+retrieving revision 1.49
+retrieving revision 1.29.10.9
+diff -p -u -b -r1.49 -r1.29.10.9
+--- src/comm.c	23 Oct 2006 11:52:53 -0000	1.49
++++ src/comm.c	3 Nov 2006 18:47:12 -0000	1.29.10.9
+@@ -742,8 +742,8 @@ comm_close(int fd)
+     F->flags.closing = 1;
+     CommWriteStateCallbackAndFree(fd, COMM_ERR_CLOSING);
+     commCallCloseHandlers(fd);
+-    if (F->uses)		/* assume persistent connect count */
+-	pconnHistCount(1, F->uses);
++    if (F->pconn.uses)
++	pconnHistCount(F->pconn.type, F->pconn.uses);
+ #if USE_SSL
+     if (F->ssl) {
+ 	if (!F->flags.close_request) {
+Index: src/enums.h
+===================================================================
+RCS file: /cvsroot/squid/squid/src/enums.h,v
+retrieving revision 1.57
+retrieving revision 1.45.4.6
+diff -p -u -b -r1.57 -r1.45.4.6
+--- src/enums.h	30 Sep 2006 21:52:28 -0000	1.57
++++ src/enums.h	3 Nov 2006 18:47:13 -0000	1.45.4.6
+@@ -93,6 +93,7 @@ typedef enum {
+     ERR_ONLY_IF_CACHED_MISS,	/* failure to satisfy only-if-cached request */
+     ERR_TOO_BIG,
+     TCP_RESET,
++    ERR_ICAP_FAILURE,
+     ERR_INVALID_RESP,
+     ERR_MAX
+ } err_type;
+@@ -455,6 +456,9 @@ typedef enum {
+     PROTO_WHOIS,
+     PROTO_INTERNAL,
+     PROTO_HTTPS,
++#if HS_FEAT_ICAP
++    PROTO_ICAP,
++#endif
+     PROTO_MAX
+ } protocol_t;
+ 
+@@ -630,6 +634,12 @@ typedef enum {
+ #if USE_SSL
+     MEM_ACL_CERT_DATA,
+ #endif
++#if HS_FEAT_ICAP
++    MEM_ICAP_OPT_DATA,
++    MEM_ICAP_SERVICE_LIST,
++    MEM_ICAP_CLASS,
++    MEM_ICAP_ACCESS,
++#endif
+     MEM_MAX
+ } mem_type;
+ 
+@@ -730,9 +740,14 @@ typedef enum {
+     CBDATA_RemovalPolicyWalker,
+     CBDATA_RemovalPurgeWalker,
+     CBDATA_store_client,
++#ifdef HS_FEAT_ICAP
++    CBDATA_IcapStateData,
++    CBDATA_icap_service,
++#endif
+     CBDATA_FIRST_CUSTOM_TYPE = 1000
+ } cbdata_type;
+ 
++
+ /*
+  * Return codes from checkVary(request)
+  */
+@@ -781,4 +796,68 @@ typedef enum {
+     ST_OP_CREATE
+ } store_op_t;
+ 
++#if HS_FEAT_ICAP
++typedef enum {
++    ICAP_STATUS_NONE = 0,
++    ICAP_STATUS_CONTINUE = 100,
++    ICAP_STATUS_SWITCHING_PROTOCOLS = 101,
++    ICAP_STATUS_STATUS_OK = 200,
++    ICAP_CREATED = 201,
++    ICAP_STATUS_ACCEPTED = 202,
++    ICAP_STATUS_NON_AUTHORITATIVE_INFORMATION = 203,
++    ICAP_STATUS_NO_MODIFICATION_NEEDED = 204,
++    ICAP_STATUS_RESET_CONTENT = 205,
++    ICAP_STATUS_PARTIAL_CONTENT = 206,
++    ICAP_STATUS_MULTIPLE_CHOICES = 300,
++    ICAP_STATUS_MOVED_PERMANENTLY = 301,
++    ICAP_STATUS_MOVED_TEMPORARILY = 302,
++    ICAP_STATUS_SEE_OTHER = 303,
++    ICAP_STATUS_NOT_MODIFIED = 304,
++    ICAP_STATUS_USE_PROXY = 305,
++    ICAP_STATUS_BAD_REQUEST = 400,
++    ICAP_STATUS_UNAUTHORIZED = 401,
++    ICAP_STATUS_PAYMENT_REQUIRED = 402,
++    ICAP_STATUS_FORBIDDEN = 403,
++    ICAP_STATUS_SERVICE_NOT_FOUND = 404,
++    ICAP_STATUS_METHOD_NOT_ALLOWED = 405,
++    ICAP_STATUS_NOT_ACCEPTABLE = 406,
++    ICAP_STATUS_PROXY_AUTHENTICATION_REQUIRED = 407,
++    ICAP_STATUS_REQUEST_TIMEOUT = 408,
++    ICAP_STATUS_CONFLICT = 409,
++    ICAP_STATUS_GONE = 410,
++    ICAP_STATUS_LENGTH_REQUIRED = 411,
++    ICAP_STATUS_PRECONDITION_FAILED = 412,
++    ICAP_STATUS_REQUEST_ENTITY_TOO_LARGE = 413,
++    ICAP_STATUS_REQUEST_URI_TOO_LARGE = 414,
++    ICAP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415,
++    ICAP_STATUS_INTERNAL_SERVER_ERROR = 500,
++    ICAP_STATUS_NOT_IMPLEMENTED = 501,
++    ICAP_STATUS_BAD_GATEWAY = 502,
++    ICAP_STATUS_SERVICE_OVERLOADED = 503,
++    ICAP_STATUS_GATEWAY_TIMEOUT = 504,
++    ICAP_STATUS_ICAP_VERSION_NOT_SUPPORTED = 505,
++    ICAP_STATUS_INVALID_HEADER = 600
++} icap_status;
++
++/*
++ * these values are used as index in an array, so it seems to be better to 
++ * assign some numbers
++ */
++typedef enum {
++    ICAP_SERVICE_REQMOD_PRECACHE = 0,
++    ICAP_SERVICE_REQMOD_POSTCACHE = 1,
++    ICAP_SERVICE_RESPMOD_PRECACHE = 2,
++    ICAP_SERVICE_RESPMOD_POSTCACHE = 3,
++    ICAP_SERVICE_MAX = 4
++} icap_service_t;
++
++typedef enum {
++    ICAP_METHOD_NONE,
++    ICAP_METHOD_OPTION,
++    ICAP_METHOD_REQMOD,
++    ICAP_METHOD_RESPMOD
++} icap_method_t;
++
++#endif /* HS_FEAT_ICAP */
++
+ #endif /* SQUID_ENUMS_H */
+Index: src/forward.c
+===================================================================
+--- src/forward.c	Tue Apr 17 11:35:17 2007
++++ src/forward.c	Thu May 17 13:08:19 2007
+@@ -943,6 +943,8 @@ fwdCheckDeferRead(int fd, void *data)
+ void
+ fwdFail(FwdState * fwdState, ErrorState * errorState)
+ {
++    if (NULL == fwdState)
++	return;
+     debug(17, 3) ("fwdFail: %s \"%s\"\n\t%s\n",
+ 	err_type_str[errorState->type],
+ 	httpStatusString(errorState->http_status),
+@@ -981,6 +983,8 @@ fwdPeerClosed(int fd, void *data)
+ void
+ fwdUnregister(int fd, FwdState * fwdState)
+ {
++    if (NULL == fwdState)
++	return;
+     debug(17, 3) ("fwdUnregister: %s\n", storeUrl(fwdState->entry));
+     assert(fd == fwdState->server_fd);
+     assert(fd > -1);
+@@ -1000,7 +1004,10 @@ fwdUnregister(int fd, FwdState * fwdStat
+ void
+ fwdComplete(FwdState * fwdState)
+ {
+-    StoreEntry *e = fwdState->entry;
++    StoreEntry *e;
++    if (NULL == fwdState)
++	return;
++    e = fwdState->entry;
+     assert(e->store_status == STORE_PENDING);
+     debug(17, 3) ("fwdComplete: %s\n\tstatus %d\n", storeUrl(e),
+ 	e->mem_obj->reply->sline.status);
+Index: src/globals.h
+--- src/globals.h.orig	Fri Jan 19 01:19:26 2007
++++ src/globals.h	Wed Jan 24 17:15:33 2007
+@@ -171,6 +171,9 @@ extern const char *external_acl_message;
+ #if HAVE_SBRK
+ extern void *sbrk_start;	/* 0 */
+ #endif
++#if HS_FEAT_ICAP
++extern const char *icap_service_type_str[];
++#endif
+ extern int opt_send_signal;	/* -1 */
+ extern int opt_no_daemon;	/* 0 */
+ #if LINUX_TPROXY
+Index: src/http.c
+===================================================================
+RCS file: /cvsroot/squid/squid/src/http.c,v
+retrieving revision 1.58
+retrieving revision 1.28.4.13
+diff -p -u -b -r1.58 -r1.28.4.13
+--- src/http.c	24 Feb 2007 11:52:43 -0000	1.58
++++ src/http.c	27 Feb 2007 21:57:26 -0000	1.28.4.13
+@@ -47,7 +47,7 @@ static CWCB httpSendRequestEntry;
+ 
+ static PF httpReadReply;
+ static void httpSendRequest(HttpStateData *);
+-static PF httpStateFree;
++PF httpStateFree;
+ static PF httpTimeout;
+ static void httpCacheNegatively(StoreEntry *);
+ static void httpMakePrivate(StoreEntry *);
+@@ -56,11 +56,12 @@ static int httpCachableReply(HttpStateDa
+ static void httpMaybeRemovePublic(StoreEntry *, http_status);
+ static int peer_supports_connection_pinning(HttpStateData * httpState);
+ 
+-static void
++void
+ httpStateFree(int fd, void *data)
+ {
+     HttpStateData *httpState = data;
+ #if DELAY_POOLS
++    if (fd >= 0)
+     delayClearNoDelay(fd);
+ #endif
+     if (httpState == NULL)
+@@ -81,6 +82,9 @@ httpStateFree(int fd, void *data)
+     httpState->request = NULL;
+     httpState->orig_request = NULL;
+     stringClean(&httpState->chunkhdr);
++#if HS_FEAT_ICAP
++    cbdataUnlock(httpState->icap_writer);
++#endif
+     cbdataFree(httpState);
+ }
+ 
+@@ -410,7 +414,7 @@ httpMakeVaryMark(request_t * request, Ht
+ }
+ 
+ /* rewrite this later using new interfaces @?@ */
+-static size_t
++size_t
+ httpProcessReplyHeader(HttpStateData * httpState, const char *buf, int size)
+ {
+     StoreEntry *entry = httpState->entry;
+@@ -640,11 +644,25 @@ httpAppendBody(HttpStateData * httpState
+ 	    if (size > httpState->chunk_size)
+ 		size = httpState->chunk_size;
+ 	    httpState->chunk_size -= size;
++#ifdef HS_FEAT_ICAP
++	    if (httpState->icap_writer) {
++		debug(81, 5) ("calling icapRespModAddBodyData from %s:%d\n", __FILE__, __LINE__);
++		icapRespModAddBodyData(httpState->icap_writer, buf, size);
++		httpState->icap_writer->fake_content_length += size;
++	    } else
++#endif
+ 	    storeAppend(httpState->entry, buf, size);
+ 	    buf += size;
+ 	    len -= size;
+ 	} else if (httpState->chunk_size < 0) {
+ 	    /* non-chunked without content-length */
++#ifdef HS_FEAT_ICAP
++	     if (httpState->icap_writer) {
++		 debug(81, 5) ("calling icapRespModAddBodyData from %s:%d\n", __FILE__, __LINE__);
++		 icapRespModAddBodyData(httpState->icap_writer, buf, len);
++		 httpState->icap_writer->fake_content_length += len;
++	     } else
++#endif	     
+ 	    storeAppend(httpState->entry, buf, len);
+ 	    len = 0;
+ 	} else if (httpState->flags.chunked) {
+@@ -699,6 +717,15 @@ httpAppendBody(HttpStateData * httpState
+ 	    /* Don't know what to do with this data. Bail out */
+ 	    break;
+ 	}
++#if HS_FEAT_ICAP
++	if (httpState->icap_writer) {
++	    if (!httpState->icap_writer->respmod.entry) {
++		debug(11, 3) ("httpReadReply: FD: %d: icap respmod aborded!\n", fd);
++		comm_close(fd);
++		return;
++	    }
++	} else
++#endif
+ 	if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+ 	    /*
+ 	     * the above storeAppend() call could ABORT this entry,
+@@ -720,6 +747,10 @@ httpAppendBody(HttpStateData * httpState
+     if (!httpState->chunk_size && !httpState->flags.chunked)
+ 	complete = 1;
+     if (!complete && len == 0) {
++#ifdef HS_FEAT_ICAP
++    if (httpState->icap_writer)
++	icapSendRespMod(httpState->icap_writer, 0);
++#endif
+ 	/* Wait for more data or EOF condition */
+ 	if (httpState->flags.keepalive_broken) {
+ 	    commSetTimeout(fd, 10, NULL, NULL);
+@@ -779,6 +810,10 @@ httpAppendBody(HttpStateData * httpState
+      */
+     if (!entry->mem_obj->reply->keep_alive)
+ 	keep_alive = 0;
++#ifdef HS_FEAT_ICAP
++    if (httpState->icap_writer)
++	icapSendRespMod(httpState->icap_writer, 1);
++#endif
+     if (keep_alive) {
+ 	int pinned = 0;
+ #if LINUX_TPROXY
+@@ -838,6 +873,17 @@ httpReadReply(int fd, void *data)
+ #endif
+     int buffer_filled;
+ 
++#if HS_FEAT_ICAP
++    if (httpState->icap_writer) {
++	if (!httpState->icap_writer->respmod.entry) {
++	    debug(11, 3) ("httpReadReply: FD: %d: icap respmod aborded!\n", fd);
++	    comm_close(fd);
++	    return;
++	}
++	/*The folowing entry can not be marked as aborted.  
++	 * The StoreEntry icap_writer->respmod.entry used when the icap_write used...... */
++    } else
++#endif
+     if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+ 	comm_close(fd);
+ 	return;
+@@ -849,7 +895,35 @@ httpReadReply(int fd, void *data)
+     else
+ 	delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz);
+ #endif
++#if HS_FEAT_ICAP
++    if (httpState->icap_writer) {
++	IcapStateData *icap = httpState->icap_writer;
++	/*
++	 * Ok we have a received a response from the web server, so try to 
++	 * connect the icap server if it's the first attemps. If we try
++	 * to connect to the icap server, defer this request (do not read
++	 * the buffer), and defer until icapConnectOver() is not called.
++	 */
++	if (icap->flags.connect_requested == 0) {
++	    debug(81, 2) ("icapSendRespMod: Create a new connection to icap server\n");
++	    if (!icapConnect(icap, icapConnectOver)) {
++		debug(81, 2) ("icapSendRespMod: Something strange while creating a socket to icap server\n");
++		commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
++		return;
++	    }
++	    debug(81, 2) ("icapSendRespMod: new connection to icap server (using FD=%d)\n", icap->icap_fd);
++	    icap->flags.connect_requested = 1;
++	    /* Wait for more data or EOF condition */
++	    commSetTimeout(fd, httpState->flags.keepalive_broken ? 10 : Config.Timeout.read, NULL, NULL);
++	    commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
++	    return;
++	}
+ 
++       if(icap->flags.no_content == 1) {
++	 commSetDefer(fd, fwdCheckDeferRead, icap->respmod.entry);
++       }
++    }
++#endif
+     errno = 0;
+     statCounter.syscalls.sock.reads++;
+     len = FD_READ_METHOD(fd, buf, read_sz);
+@@ -868,7 +942,13 @@ httpReadReply(int fd, void *data)
+ 	IOStats.Http.read_hist[bin]++;
+ 	buf[len] = '\0';
+     }
+-    if (!httpState->reply_hdr.size && len > 0 && fd_table[fd].uses > 1) {
++#ifdef HS_FEAT_ICAP
++    if (httpState->icap_writer)
++	(void) 0;
++    else
++#endif
++
++    if (!httpState->reply_hdr.size && len > 0 && fd_table[fd].pconn.uses > 1) {
+ 	/* Skip whitespace */
+ 	while (len > 0 && xisspace(*buf))
+ 	    xmemmove(buf, buf + 1, len--);
+@@ -971,12 +1051,49 @@ httpReadReply(int fd, void *data)
+ 		commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
+ 		return;
+ 	    }
++#ifdef HS_FEAT_ICAP
++	    if (httpState->icap_writer) {
++		debug(81, 5) ("calling icapSendRespMod from %s:%d\n", __FILE__, __LINE__);
++		if (cbdataValid(httpState->icap_writer)) {
++		    icapRespModAddResponceHeaders(httpState->icap_writer, buf, done);
++		    httpState->icap_writer->fake_content_length += done;
++		}
++	    }
++#endif
+ 	}
+ 	httpAppendBody(httpState, buf + done, len - done, buffer_filled);
+ 	return;
+     }
+ }
+ 
++#ifdef HS_FEAT_ICAP
++static int
++httpReadReplyWaitForIcap(int fd, void *data)
++{
++    HttpStateData *httpState = data;
++    if (NULL == httpState->icap_writer)
++	return 0;
++    /* 
++     * Do not defer when we are not connected to the icap server.
++     * Defer when the icap server connection is not established but pending
++     * Defer when the icap server is busy (writing on the socket)
++     */
++    debug(11, 5) ("httpReadReplyWaitForIcap: FD %d, connect_requested=%d\n",
++	fd, httpState->icap_writer->flags.connect_requested);
++    if (!httpState->icap_writer->flags.connect_requested)
++	return 0;
++    debug(11, 5) ("httpReadReplyWaitForIcap: FD %d, connect_pending=%d\n",
++	fd, httpState->icap_writer->flags.connect_pending);
++    if (httpState->icap_writer->flags.connect_pending)
++	return 1;
++    debug(11, 5) ("httpReadReplyWaitForIcap: FD %d, write_pending=%d\n",
++	fd, httpState->icap_writer->flags.write_pending);
++    if (httpState->icap_writer->flags.write_pending)
++	return 1;
++    return 0;
++}
++#endif
++
+ /* This will be called when request write is complete. Schedule read of
+  * reply. */
+ static void
+@@ -1004,6 +1121,63 @@ httpSendComplete(int fd, char *bufnotuse
+ 	comm_close(fd);
+ 	return;
+     } else {
++	/* Schedule read reply. */
++#ifdef HS_FEAT_ICAP
++	if (icapService(ICAP_SERVICE_RESPMOD_PRECACHE, httpState->orig_request)) {
++	    httpState->icap_writer = icapRespModStart(
++		ICAP_SERVICE_RESPMOD_PRECACHE,
++		httpState->orig_request, httpState->entry, httpState->flags);
++	    if (-1 == (int) httpState->icap_writer) {
++		/* TODO: send error here and exit */
++		ErrorState *err;
++		httpState->icap_writer = 0;
++		err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, httpState->fwd->request);
++		err->xerrno = errno;
++		err->request = requestLink(httpState->orig_request);
++		errorAppendEntry(entry, err);
++		comm_close(fd);
++		return;
++	    } else if (httpState->icap_writer) {
++		request_flags fake_flags = httpState->orig_request->flags;
++		method_t fake_method = entry->mem_obj->method;
++		const char *fake_msg = "this is a fake entry for "
++		" response sent to an ICAP RESPMOD server";
++		cbdataLock(httpState->icap_writer);
++		/*
++		 * this httpState will give the data it reads to
++		 * the icap server, rather than put it into
++		 * a StoreEntry
++		 */
++		storeUnregisterAbort(httpState->entry);
++		storeUnlockObject(httpState->entry);
++		/*
++		 * create a bogus entry because the code assumes one is
++		 * always there.
++		 */
++		fake_flags.cachable = 0;
++		fake_flags.hierarchical = 0;	/* force private key */
++		httpState->entry = storeCreateEntry("fake", "fake", fake_flags, fake_method);
++		storeAppend(httpState->entry, fake_msg, strlen(fake_msg));
++		/*
++		 * pull a switcheroo on fwdState->entry.
++		 */
++		storeUnlockObject(httpState->fwd->entry);
++		httpState->fwd->entry = httpState->entry;
++		storeLockObject(httpState->fwd->entry);
++		/*
++		 * Note that we leave fwdState connected to httpState,
++		 * but we changed the entry.  So when fwdComplete
++		 * or whatever is called it does no harm -- its
++		 * just the fake entry.
++		 */
++	    } else {
++		/*
++		 * failed to open connection to ICAP server. 
++		 * But bypass request, so just continue here.
++		 */
++	    }
++	}
++#endif
+ 	/*
+ 	 * Set the read timeout here because it hasn't been set yet.
+ 	 * We only set the read timeout after the request has been
+@@ -1012,8 +1186,18 @@ httpSendComplete(int fd, char *bufnotuse
+ 	 * the timeout for POST/PUT requests that have very large
+ 	 * request bodies.
+ 	 */
++
++	/* removed in stable5:
++	 * commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
++	 */
+ 	commSetTimeout(fd, Config.Timeout.read, httpTimeout, httpState);
+-	commSetDefer(fd, fwdCheckDeferRead, entry);
++#ifdef HS_FEAT_ICAP
++	if (httpState->icap_writer) {
++	    debug(11, 5) ("FD %d, setting httpReadReplyWaitForIcap\n", httpState->fd);
++	    commSetDefer(httpState->fd, httpReadReplyWaitForIcap, httpState);
++	} else
++#endif
++	    commSetDefer(httpState->fd, fwdCheckDeferRead, entry);
+     }
+     httpState->flags.request_sent = 1;
+ }
+@@ -1317,8 +1501,11 @@ httpBuildRequestHeader(request_t * reque
+ 	if (!EBIT_TEST(cc->mask, CC_MAX_AGE)) {
+ 	    const char *url = entry ? storeUrl(entry) : urlCanonical(orig_request);
+ 	    httpHdrCcSetMaxAge(cc, getMaxAge(url));
++#ifndef HS_FEAT_ICAP
++	    /* Don;t bother - if  the url you want to cache is redirected? */
+ 	    if (strLen(request->urlpath))
+ 		assert(strstr(url, strBuf(request->urlpath)));
++#endif
+ 	}
+ 	/* Set no-cache if determined needed but not found */
+ 	if (orig_request->flags.nocache && !httpHeaderHas(hdr_in, HDR_PRAGMA))
+@@ -1444,6 +1631,7 @@ httpStart(FwdState * fwd)
+     int fd = fwd->server_fd;
+     HttpStateData *httpState;
+     request_t *proxy_req;
++    /* ErrorState *err; */
+     request_t *orig_req = fwd->request;
+     debug(11, 3) ("httpStart: \"%s %s\"\n",
+ 	RequestMethodStr[orig_req->method],
+@@ -1486,12 +1674,22 @@ httpStart(FwdState * fwd)
+ 	httpState->request = requestLink(orig_req);
+ 	httpState->orig_request = requestLink(orig_req);
+     }
++#ifdef HS_FEAT_ICAP
++    if (icapService(ICAP_SERVICE_REQMOD_POSTCACHE, httpState->orig_request)) {
++	httpState->icap_writer = icapRespModStart(ICAP_SERVICE_REQMOD_POSTCACHE,
++	    httpState->orig_request, httpState->entry, httpState->flags);
++	if (httpState->icap_writer) {
++	    return;
++	}
++    }
++#endif
+     /*
+      * register the handler to free HTTP state data when the FD closes
+      */
+     comm_add_close_handler(fd, httpStateFree, httpState);
+     statCounter.server.all.requests++;
+     statCounter.server.http.requests++;
++
+     httpSendRequest(httpState);
+     /*
+      * We used to set the read timeout here, but not any more.
+Index: src/icap_common.c
+===================================================================
+RCS file: src/icap_common.c
+diff -N src/icap_common.c
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ src/icap_common.c	26 May 2006 19:24:02 -0000	1.1.14.3
+@@ -0,0 +1,815 @@
++/*
++ * $Id$
++ *
++ * DEBUG: section 81    Internet Content Adaptation Protocol (ICAP) Client
++ * AUTHOR: Geetha Manjunath, Hewlett Packard Company
++ *
++ * SQUID Web Proxy Cache          http://www.squid-cache.org/
++ * ----------------------------------------------------------
++ *
++ *  Squid is the result of efforts by numerous individuals from
++ *  the Internet community; see the CONTRIBUTORS file for full
++ *  details.   Many organizations have provided support for Squid's
++ *  development; see the SPONSORS file for full details.  Squid is
++ *  Copyrighted (C) 2001 by the Regents of the University of
++ *  California; see the COPYRIGHT file for full details.  Squid
++ *  incorporates software developed and/or copyrighted by other
++ *  sources; see the CREDITS file for full details.
++ *
++ *  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, USA.
++ *
++ */
++
++/* _GNU_SOURCE is required for strcasestr */
++#define _GNU_SOURCE 1
++
++#include "squid.h"
++#include "util.h"
++
++extern PF httpStateFree;
++
++#define EXPECTED_ICAP_HEADER_LEN 256
++#define ICAP_OPTIONS_REQUEST
++
++
++void
++icapInit()
++{
++#ifdef ICAP_OPTIONS_REQUEST
++    if (Config.icapcfg.onoff) {
++	icapOptInit();
++    }
++#endif
++}
++
++void
++icapClose()
++{
++    icapOptShutdown();
++}
++
++/*
++ * search for a HTTP-like header in the buffer. 
++ * Note, buf must be 0-terminated
++ *
++ * This function is not very good.  It should probably look for
++ * header tokens only at the start of a line, not just anywhere in
++ * the buffer.
++ */
++int
++icapFindHeader(const char *buf, const char *hdr, const char **Start,
++    const char **End)
++{
++    const char *start = NULL;
++    const char *end = NULL;
++    start = strcasestr(buf, hdr);
++    if (NULL == start)
++	return 0;
++    end = start + strcspn(start, "\r\n");
++    if (start == end)
++	return 0;
++    *Start = start;
++    *End = end;
++    return 1;
++}
++
++/* 
++ * parse the contents of the encapsulated header (buffer between enc_start
++ * and enc_end) and put the result into IcapStateData
++ */
++void
++icapParseEncapsulated(IcapStateData * icap, const char *enc_start,
++    const char *enc_end)
++{
++    char *current, *end;
++
++    assert(icap);
++    assert(enc_start);
++    assert(enc_end);
++
++    current = strchr(enc_start, ':');
++    current++;
++    while (current < enc_end) {
++	while (isspace(*current))
++	    current++;
++	if (!strncmp(current, "res-hdr=", 8)) {
++	    current += 8;
++	    icap->enc.res_hdr = strtol(current, &end, 10);
++	} else if (!strncmp(current, "req-hdr=", 8)) {
++	    current += 8;
++	    icap->enc.req_hdr = strtol(current, &end, 10);
++	} else if (!strncmp(current, "null-body=", 10)) {
++	    current += 10;
++	    icap->enc.null_body = strtol(current, &end, 10);
++	} else if (!strncmp(current, "res-body=", 9)) {
++	    current += 9;
++	    icap->enc.res_body = strtol(current, &end, 10);
++	} else if (!strncmp(current, "req-body=", 9)) {
++	    current += 9;
++	    icap->enc.req_body = strtol(current, &end, 10);
++	} else if (!strncmp(current, "opt-body=", 9)) {
++	    current += 9;
++	    icap->enc.opt_body = strtol(current, &end, 10);
++	} else {
++	    /* invalid header */
++	    debug(81, 5) ("icapParseEncapsulated: error in: %s\n", current);
++	    return;
++	}
++	current = end;
++	current = strchr(current, ',');
++	if (current == NULL)
++	    break;
++	else
++	    current++;		/* skip ',' */
++    }
++    debug(81,
++	3) ("icapParseEncapsulated: res-hdr=%d, req-hdr=%d, null-body=%d, "
++	"res-body=%d, req-body=%d, opt-body=%d\n", icap->enc.res_hdr,
++	icap->enc.req_hdr, icap->enc.null_body, icap->enc.res_body,
++	icap->enc.req_body, icap->enc.opt_body);
++
++}
++
++icap_service *
++icapService(icap_service_t type, request_t * r)
++{
++    icap_service_list *isl_iter;
++    int is_iter;
++    int nb_unreachable = 0;
++    icap_service *unreachable_one = NULL;
++
++    debug(81, 8) ("icapService: type=%s\n", icapServiceToStr(type));
++    if (NULL == r) {
++	debug(81, 8) ("icapService: no request_t\n");
++	return NULL;
++    }
++    if (NULL == r->class) {
++	debug(81, 8) ("icapService: no class\n");
++	return NULL;
++    }
++    for (isl_iter = r->class->isl; isl_iter; isl_iter = isl_iter->next) {
++	/* TODO:luc: Do a round-robin, choose a random value ? 
++	 * For now, we use a simple round robin with checking is the
++	 * icap server is available */
++	is_iter = isl_iter->last_service_used;
++	do {
++	    is_iter = (is_iter + 1) % isl_iter->nservices;
++	    debug(81, 8) ("icapService: checking service %s/id=%d\n",
++		isl_iter->services[is_iter]->name, is_iter);
++	    if (type == isl_iter->services[is_iter]->type) {
++		if (!isl_iter->services[is_iter]->unreachable) {
++		    debug(81, 8) ("icapService: found service %s/id=%d\n",
++			isl_iter->services[is_iter]->name, is_iter);
++		    isl_iter->last_service_used = is_iter;
++		    return isl_iter->services[is_iter];
++		}
++		debug(81,
++		    8)
++		    ("icapService: found service %s/id=%d, but it's unreachable. I don't want to use it\n",
++		    isl_iter->services[is_iter]->name, is_iter);
++		unreachable_one = isl_iter->services[is_iter];
++		nb_unreachable++;
++		/* FIXME:luc: in response mod, if we return an NULL pointer, user can bypass
++		 * the filter, is it normal ? */
++	    }
++	} while (is_iter != isl_iter->last_service_used);
++    }
++    debug(81, 8) ("icapService: no service found\n");
++    isl_iter = r->class->isl;
++
++    if (nb_unreachable > 0) {
++	debug(81,
++	    8)
++	    ("All the services are unreachable, returning an unreachable one\n");
++	return unreachable_one;
++    } else {
++	return NULL;
++    }
++}
++
++int
++icapConnect(IcapStateData * icap, CNCB * theCallback)
++{
++    int rc;
++    icap->icap_fd = pconnPop(icap->current_service->hostname,
++	icap->current_service->port, NULL, NULL, 0);
++    if (icap->icap_fd >= 0) {
++	debug(81, 3) ("icapConnect: reused pconn FD %d\n", icap->icap_fd);
++	fd_note(icap->icap_fd, icap->current_service->uri);
++	comm_add_close_handler(icap->icap_fd, icapStateFree, icap);
++	theCallback(icap->icap_fd, 0, icap);
++	return 1;
++    }
++    icap->icap_fd = comm_open(SOCK_STREAM, 0, getOutgoingAddr(NULL), 0,
++	COMM_NONBLOCKING, icap->current_service->uri);
++    debug(81, 5) ("icapConnect: new socket, FD %d, local address %s\n",
++	icap->icap_fd, inet_ntoa(getOutgoingAddr(NULL)));
++    if (icap->icap_fd < 0) {
++	icapStateFree(-1, icap);	/* XXX test */
++	return 0;
++    }
++    icap->flags.connect_pending = 1;
++    /*
++     * Configure timeout and close handler before calling
++     * connect because commConnectStart() might get an error
++     * immediately and close the descriptor before it returns.
++     */
++    commSetTimeout(icap->icap_fd, Config.Timeout.connect,
++	icapConnectTimeout, icap);
++    comm_add_close_handler(icap->icap_fd, icapStateFree, icap);
++    /*
++     * This sucks.  commConnectStart() may fail before returning,
++     * so lets lock the data and check its validity afterwards.
++     */
++    cbdataLock(icap);
++    commConnectStart(icap->icap_fd,
++	icap->current_service->hostname,
++	icap->current_service->port, theCallback, icap);
++    rc = cbdataValid(icap);
++    cbdataUnlock(icap);
++    debug(81, 3) ("icapConnect: returning %d\n", rc);
++    return rc;
++}
++
++IcapStateData *
++icapAllocate(void)
++{
++    IcapStateData *icap;
++
++    if (!Config.icapcfg.onoff)
++	return 0;
++
++    icap = cbdataAlloc(IcapStateData);
++    icap->icap_fd = -1;
++    icap->enc.res_hdr = -1;
++    icap->enc.res_body = -1;
++    icap->enc.req_hdr = -1;
++    icap->enc.req_body = -1;
++    icap->enc.opt_body = -1;
++    icap->enc.null_body = -1;
++    icap->chunk_size = -1;
++    memBufDefInit(&icap->icap_hdr);
++
++    debug(81, 3) ("New ICAP state\n");
++    return icap;
++}
++
++void
++icapStateFree(int fd, void *data)
++{
++    IcapStateData *icap = data;
++    debug(81, 3) ("icapStateFree: FD %d, icap %p\n", fd, icap);
++    assert(icap);
++    assert(-1 == fd || fd == icap->icap_fd);
++    if (icap->respmod.entry) {
++	/*
++	 * If we got some error on this side (like ECONNRESET)
++	 * we must signal the other side(s) with a storeAbort()
++	 * call.
++	 */
++	if (icap->respmod.entry->store_status != STORE_OK)
++	    storeAbort(icap->respmod.entry);
++	storeUnlockObject(icap->respmod.entry);
++	icap->respmod.entry = NULL;
++    }
++    requestUnlink(icap->request);
++    icap->request = NULL;
++    if (!memBufIsNull(&icap->icap_hdr))
++	memBufClean(&icap->icap_hdr);
++    if (!memBufIsNull(&icap->respmod.buffer))
++	memBufClean(&icap->respmod.buffer);
++    if (!memBufIsNull(&icap->respmod.req_hdr_copy))
++	memBufClean(&icap->respmod.req_hdr_copy);
++    if (!memBufIsNull(&icap->respmod.resp_copy))
++	memBufClean(&icap->respmod.resp_copy);
++    if (!memBufIsNull(&icap->reqmod.hdr_buf))
++	memBufClean(&icap->reqmod.hdr_buf);
++    if (!memBufIsNull(&icap->reqmod.http_entity.buf))
++	memBufClean(&icap->reqmod.http_entity.buf);
++    if (!memBufIsNull(&icap->chunk_buf))
++	memBufClean(&icap->chunk_buf);
++    if (icap->httpState)
++	httpStateFree(-1, icap->httpState);
++    cbdataUnlock(icap->reqmod.client_cookie);
++    cbdataFree(icap);
++}
++
++void
++icapConnectTimeout(int fd, void *data)
++{
++    IcapStateData *icap = data;
++    debug(81, 3) ("icapConnectTimeout: FD %d, unreachable=1\n", fd);
++    assert(fd == icap->icap_fd);
++    icapOptSetUnreachable(icap->current_service);
++    comm_close(fd);
++}
++
++void
++icapReadTimeout(int fd, void *data)
++{
++    IcapStateData *icap = data;
++    assert(fd == icap->icap_fd);
++    if (icap->flags.wait_for_preview_reply || icap->flags.http_server_eof) {
++	debug(81, 3) ("icapReadTimeout: FD %d, unreachable=1\n", fd);
++	icapOptSetUnreachable(icap->current_service);
++    } else
++	debug(81, 3) ("icapReadTimeout: FD %d, still reachable\n", fd);
++    comm_close(fd);
++}
++
++icap_service_t
++icapServiceToType(const char *s)
++{
++    if (!strcmp(s, "reqmod_precache"))
++	return ICAP_SERVICE_REQMOD_PRECACHE;
++    if (!strcmp(s, "reqmod_postcache"))
++	return ICAP_SERVICE_REQMOD_POSTCACHE;
++    if (!strcmp(s, "respmod_precache"))
++	return ICAP_SERVICE_RESPMOD_PRECACHE;
++    if (!strcmp(s, "respmod_postcache"))
++	return ICAP_SERVICE_RESPMOD_POSTCACHE;
++    return ICAP_SERVICE_MAX;
++}
++
++const char *
++icapServiceToStr(const icap_service_t type)
++{
++    if (type >= 0 && type < ICAP_SERVICE_MAX)
++	return icap_service_type_str[type];
++    else
++	return "error";
++}
++
++
++/* copied from clientAclChecklistCreate */
++static aclCheck_t *
++icapAclChecklistCreate(const acl_access * acl, const clientHttpRequest * http)
++{
++    aclCheck_t *ch;
++    ConnStateData *conn = http->conn;
++    ch = aclChecklistCreate(acl, http->request, 0);
++    ch->conn = conn;
++    cbdataLock(ch->conn);
++    return ch;
++}
++
++/*
++ * check wether we do icap for a request
++ */
++int
++icapCheckAcl(clientHttpRequest * http)
++{
++    icap_access *iter;
++    aclCheck_t *icapChecklist;
++
++    for (iter = Config.icapcfg.access_head; iter; iter = iter->next) {
++	acl_access *A = iter->access;
++	icapChecklist = icapAclChecklistCreate(A, http);
++	if (aclMatchAclList(A->acl_list, icapChecklist)) {
++	    debug(81, 5) ("icapCheckAcl: match for class=%s\n",
++		iter->class->name);
++	    if (A->allow) {
++		/* allow rule, do icap and use associated class */
++		http->request->class = iter->class;
++		aclChecklistFree(icapChecklist);
++		return 1;
++	    } else {
++		/* deny rule, stop processing */
++		aclChecklistFree(icapChecklist);
++		return 0;
++	    }
++	}
++	aclChecklistFree(icapChecklist);
++    }
++    return 0;
++}
++
++/* icapLineLength
++ *
++ * returns the amount of data until lineending ( \r\n )
++ * This function is NOT tolerant of variations of \r\n.
++ */
++size_t
++icapLineLength(const char *start, int len)
++{
++    size_t lineLen = 0;
++    char *end = (char *) memchr(start, '\r', len);
++    if (NULL == end)
++	return 0;
++    end++;			/* advance to where '\n' should be */
++    lineLen = end - start + 1;
++    if (lineLen > len) {
++	debug(0, 0) ("icapLineLength: warning lineLen (%d) > len (%d)\n",
++	    lineLen, len);
++	return 0;
++    }
++    if (*end != '\n') {
++	debug(0, 0) ("icapLineLength: warning *end (%x) != '\\n'\n", *end);
++	return 0;
++    }
++    debug(81, 7) ("icapLineLength: returning %d\n", lineLen);
++    return lineLen;
++}
++
++/*
++ * return:
++ *   -1 if EOF before getting end of ICAP header
++ *    0 if we don't have the entire ICAP header yet
++ *    1 if we got the whole header
++ */
++int
++icapReadHeader(int fd, IcapStateData * icap, int *isIcap)
++{
++    int headlen = 0;
++    int len = 0;
++    int peek_sz = EXPECTED_ICAP_HEADER_LEN;
++    int read_sz = 0;
++    LOCAL_ARRAY(char, tmpbuf, SQUID_TCP_SO_RCVBUF);
++    for (;;) {
++	len = recv(fd, tmpbuf, peek_sz, MSG_PEEK);
++	debug(81, 5) ("recv(FD %d, ..., MSG_PEEK) ret %d\n", fd, len);
++	if (len < 0) {
++	    debug(81, 1) ("icapReadHeader: FD %d recv error: %s\n", fd,
++		xstrerror());
++	    return -1;
++	}
++	if (len == 0) {
++	    debug(81, 2) ("icapReadHeader: FD %d recv EOF\n", fd);
++	    return -1;
++	}
++	headlen = headersEnd(tmpbuf, len);
++	debug(81, 3) ("headlen=%d\n", headlen);
++	/*
++	 * break if we now know where the ICAP headers end
++	 */
++	if (headlen)
++	    break;
++	/*
++	 * break if we know there is no more data to read
++	 */
++	if (len < peek_sz)
++	    break;
++	/*
++	 * The ICAP header is larger than (or equal to) our read
++	 * buffer, so double it and try to peek again.
++	 */
++	peek_sz *= 2;
++	if (peek_sz >= SQUID_TCP_SO_RCVBUF) {
++	    debug(81,
++		1) ("icapReadHeader: Failed to find end of ICAP header\n");
++	    debug(81, 1) ("\twithin first %d bytes of response\n",
++		SQUID_TCP_SO_RCVBUF);
++	    debug(81, 1) ("\tpossible persistent connection bug/confusion\n");
++	    return -1;
++	}
++    }
++    /*
++     * Now actually read the data from the kernel
++     */
++    if (headlen)
++	read_sz = headlen;
++    else
++	read_sz = len;
++    len = FD_READ_METHOD(fd, tmpbuf, read_sz);
++    assert(len == read_sz);
++    fd_bytes(fd, len, FD_READ);
++    memBufAppend(&icap->icap_hdr, tmpbuf, len);
++    if (headlen) {
++	/* End of ICAP header found */
++	if (icap->icap_hdr.size < 4)
++	    *isIcap = 0;
++	else if (0 == strncmp(icap->icap_hdr.buf, "ICAP", 4))
++	    *isIcap = 1;
++	else
++	    *isIcap = 0;
++	return 1;
++    }
++    /*
++     * We don't have all the headers yet
++     */
++    return 0;
++}
++
++static int
++icapParseConnectionClose(const IcapStateData * icap, const char *s,
++    const char *e)
++{
++    char *t;
++    char *q;
++    /*
++     * s points to the start of the line "Connection: ... "
++     * e points to *after* the last character on the line
++     */
++    s += 11;			/* skip past Connection: */
++    while (s < e && isspace(*s))
++	s++;
++    if (e - s < 5)
++	return 0;
++    /*
++     * create a buffer that we can use strtok on
++     */
++    t = xmalloc(e - s + 1);
++    strncpy(t, s, e - s);
++    *(t + (e - s)) = '\0';
++    for (q = strtok(t, ","); q; q = strtok(NULL, ",")) {
++	if (0 == strcasecmp(q, "close")) {
++	    xfree(t);
++	    return 1;
++	}
++    }
++    xfree(t);
++    return 0;
++}
++
++/* returns icap status, version and subversion extracted from status line or -1 on parsing failure 
++ * The str_status pointr points to the text returned from the icap server.
++ * sline probably is NOT terminated with '\0' 
++ */
++int
++icapParseStatusLine(const char *sline, int slinesize, int *version_major,
++    int *version_minor, const char **str_status)
++{
++    char *sp, *stmp, *ep = (char *) sline + slinesize;
++    int status;
++    if (slinesize < 14)		/*The format of this line is: "ICAP/x.x xxx[ msg....]\r\n" */
++	return -1;
++
++    if (strncmp(sline, "ICAP/", 5) != 0)
++	return -1;
++    if (sscanf(sline + 5, "%d.%d", version_major, version_minor) != 2)
++	return -1;
++
++    if (!(sp = memchr(sline, ' ', slinesize)))
++	return -1;
++
++    while (sp < ep && xisspace(*++sp));
++
++    if (!xisdigit(*sp) || sp >= ep)
++	return -1;
++
++    if ((status = strtol(sp, &stmp, 10)) <= 0)
++	return -1;
++    sp = stmp;
++
++    while (sp < ep && xisspace(*++sp));
++    *str_status = sp;
++    /*Must add a test for "\r\n" end headers .... */
++    return status;
++}
++
++
++void
++icapSetKeepAlive(IcapStateData * icap, const char *hdrs)
++{
++    const char *start;
++    const char *end;
++    if (0 == icap->flags.keep_alive)
++	return;
++    if (0 == icapFindHeader(hdrs, "Connection:", &start, &end)) {
++	icap->flags.keep_alive = 1;
++	return;
++    }
++    if (icapParseConnectionClose(icap, start, end))
++	icap->flags.keep_alive = 0;
++    else
++	icap->flags.keep_alive = 1;
++}
++
++/*
++ * icapParseChunkSize
++ *
++ * Returns the offset where the next chunk starts
++ * return parameter chunk_size;
++ */
++static int
++icapParseChunkSize(const char *buf, int len, int *chunk_size)
++{
++    int chunkSize = 0;
++    char c;
++    size_t start;
++    size_t end;
++    size_t nextStart = 0;
++    debug(81, 3) ("icapParseChunkSize: buf=%p, len=%d\n", buf, len);
++    do {
++	start = nextStart;
++	debug(81, 3) ("icapParseChunkSize: start=%d\n", start);
++	if (len <= start) {
++	    /*
++	     * end of buffer, so far no lines or only empty lines,
++	     * wait for more data. read chunk size with next buffer.
++	     */
++	    *chunk_size = 0;
++	    return 0;
++	}
++	end = start + icapLineLength(buf + start, len - start);
++	nextStart = end;
++	if (end <= start) {
++	    /*
++	     * no line found, need more code here, now we are in
++	     * deep trouble, buffer stops with half a chunk size
++	     * line. For now stop here.
++	     */
++	    debug(81, 1) ("icapParseChunkSize: WARNING in mid-line, ret 0\n");
++	    *chunk_size = 0;
++	    return 0;
++	}
++	while (start < end) {
++	    if (NULL == strchr(w_space, buf[start]))
++		break;
++	    start++;
++	}
++	while (start < end) {
++	    if (NULL == strchr(w_space, buf[end - 1]))
++		break;
++	    end--;
++	}
++	/*
++	 * if now end <= start we got an empty line. The previous
++	 * chunk data should stop with a CRLF. In case that the
++	 * other end does not follow the specs and sends no CRLF
++	 * or too many empty lines, just continue till we have a
++	 * non-empty line.
++	 */
++    } while (end <= start);
++    debug(81, 3) ("icapParseChunkSize: start=%d, end=%d\n", start, end);
++
++    /* Non-empty line: Parse the chunk size */
++    while (start < end) {
++	c = buf[start++];
++	if (c >= 'a' && c <= 'f') {
++	    chunkSize = chunkSize * 16 + c - 'a' + 10;
++	} else if (c >= 'A' && c <= 'F') {
++	    chunkSize = chunkSize * 16 + c - 'A' + 10;
++	} else if (c >= '0' && c <= '9') {
++	    chunkSize = chunkSize * 16 + c - '0';
++	} else {
++	    if (!(c == ';' || c == ' ' || c == '\t')) {
++		/*Syntax error: Chunksize expected. */
++		*chunk_size = -2;	/* we are done */
++		return nextStart;
++	    }
++	    /* Next comes a chunk extension */
++	    break;
++	}
++    }
++    /*
++     * if we read a zero chunk, we reached the end. Mark this for
++     * icapPconnTransferDone
++     */
++    *chunk_size = (chunkSize > 0) ? chunkSize : -2;
++    debug(81, 3) ("icapParseChunkSize: return nextStart=%d\n", nextStart);
++    return nextStart;
++}
++
++/*
++ * icapParseChunkedBody
++ *
++ * De-chunk an HTTP entity received from the ICAP server.
++ * The 'store' function pointer is storeAppend() or memBufAppend().
++ */
++size_t
++icapParseChunkedBody(IcapStateData * icap, STRCB * store, void *store_data)
++{
++    int bufOffset = 0;
++    size_t bw = 0;
++    MemBuf *cb = &icap->chunk_buf;
++    const char *buf = cb->buf;
++    int len = cb->size;
++
++    if (icap->chunk_size == -2) {
++	debug(81, 3) ("zero end chunk reached\n");
++	return 0;
++    }
++    debug(81, 3) ("%s:%d: chunk_size=%d\n", __FILE__, __LINE__,
++	icap->chunk_size);
++    if (icap->chunk_size < 0) {
++	store(store_data, buf, len);
++	cb->size = 0;
++	return (size_t) len;
++    }
++    debug(81, 3) ("%s:%d: bufOffset=%d, len=%d\n", __FILE__, __LINE__,
++	bufOffset, len);
++    while (bufOffset < len) {
++	debug(81, 3) ("%s:%d: bufOffset=%d, len=%d\n", __FILE__, __LINE__,
++	    bufOffset, len);
++	if (icap->chunk_size == 0) {
++	    int x;
++	    x = icapParseChunkSize(buf + bufOffset,
++		len - bufOffset, &icap->chunk_size);
++	    if (x < 1) {
++		/* didn't find a valid chunk spec */
++		break;
++	    }
++	    bufOffset += x;
++	    debug(81, 3) ("got chunksize %d, new offset %d\n",
++		icap->chunk_size, bufOffset);
++	    if (icap->chunk_size == -2) {
++		debug(81, 3) ("zero end chunk reached\n");
++		break;
++	    }
++	}
++	debug(81, 3) ("%s:%d: X\n", __FILE__, __LINE__);
++	if (icap->chunk_size > 0) {
++	    if (icap->chunk_size >= len - bufOffset) {
++		store(store_data, buf + bufOffset, len - bufOffset);
++		bw += (len - bufOffset);
++		icap->chunk_size -= (len - bufOffset);
++		bufOffset = len;
++	    } else {
++		store(store_data, buf + bufOffset, icap->chunk_size);
++		bufOffset += icap->chunk_size;
++		bw += icap->chunk_size;
++		icap->chunk_size = 0;
++	    }
++	}
++    }
++    if (0 == bufOffset) {
++	(void) 0;
++    } else if (bufOffset == cb->size) {
++	cb->size = 0;
++    } else {
++	assert(bufOffset <= cb->size);
++	xmemmove(cb->buf, cb->buf + bufOffset, cb->size - bufOffset);
++	cb->size -= bufOffset;
++    }
++    return bw;
++}
++
++/*
++ *  icapAddAuthUserHeader
++ *
++ *  Builds and adds the X-Authenticated-User header to an ICAP request headers.
++ */
++void
++icapAddAuthUserHeader(MemBuf * mb, auth_user_request_t * auth_user_request)
++{
++    char *user = authenticateUserRequestUsername(auth_user_request);
++    char *authuser;
++    size_t len, userlen, schemelen, userofslen;
++    char *userofs;
++
++    if (user == NULL) {
++	debug(81, 5) ("icapAddAuthUserHeader: NULL username\n");
++	return;
++    }
++    userlen = strlen(user);
++    schemelen = strlen(Config.icapcfg.auth_scheme);
++    len = userlen + schemelen + 1;
++    authuser = xcalloc(len, 1);
++
++    if ((userofs = strstr(Config.icapcfg.auth_scheme, "%u")) == NULL) {
++	/* simply add user at end of string */
++	snprintf(authuser, len, "%s%s", Config.icapcfg.auth_scheme, user);
++    } else {
++	userofslen = userofs - Config.icapcfg.auth_scheme;
++	xmemcpy(authuser, Config.icapcfg.auth_scheme, userofslen);
++	xmemcpy(authuser + userofslen, user, userlen);
++	xmemcpy(authuser + userofslen + userlen,
++	    userofs + 2, schemelen - (userofslen + 2) + 1);
++    }
++
++    memBufPrintf(mb, "X-Authenticated-User: %s\r\n", base64_encode(authuser));
++    xfree(authuser);
++}
++
++/*
++ *  icapAddOriginIP
++ *
++ *  Builds and adds the X-Server-IP header to an ICAP request headers.
++ */
++void
++icapAddOriginIP(MemBuf * mb, const char *host)
++{
++    const ipcache_addrs *addrs;
++    struct in_addr s;
++
++    if (host == NULL) {
++	debug(81, 5) ("icapAddOriginIP: NULL host\n");
++	return;
++    }
++    addrs = ipcache_gethostbyname(host, IP_LOOKUP_IF_MISS);
++    if (addrs == NULL) {
++	/*
++	 * http://www.i-cap.org/spec/draft-stecher-icap-subid-00.txt :
++	 *
++	 * [...] If the meta information for some header is not available,
++	 * the header field MUST be omitted.
++	 */
++	debug(81, 5) ("icapAddOriginIP: can't tell IP address\n");
++	return;
++    }
++    s = addrs->in_addrs[0];
++    memBufPrintf(mb, "X-Server-IP: %s\r\n", inet_ntoa(s));
++}
+Index: src/icap_opt.c
+===================================================================
+RCS file: src/icap_opt.c
+diff -N src/icap_opt.c
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ src/icap_opt.c	17 May 2006 17:58:01 -0000	1.1.16.1
+@@ -0,0 +1,523 @@
++
++/*
++ * $Id$
++ * 
++ * DEBUG: section 81    Internet Content Adaptation Protocol (ICAP) Client OPTIONS
++ * AUTHOR: Ralf Horstmann
++ *
++ * SQUID Web Proxy Cache          http://www.squid-cache.org/
++ * ----------------------------------------------------------
++ *
++ *  Squid is the result of efforts by numerous individuals from
++ *  the Internet community; see the CONTRIBUTORS file for full
++ *  details.   Many organizations have provided support for Squid's
++ *  development; see the SPONSORS file for full details.  Squid is
++ *  Copyrighted (C) 2001 by the Regents of the University of
++ *  California; see the COPYRIGHT file for full details.  Squid
++ *  incorporates software developed and/or copyrighted by other
++ *  sources; see the CREDITS file for full details.
++ *
++ *  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, USA.
++ *
++ */
++
++#include "squid.h"
++
++/*************************************************************/
++
++/*
++ * network related functions for OPTIONS request
++ */
++static void icapOptStart(void *data);
++static void icapOptTimeout(int fd, void *data);
++static void icapOptConnectDone(int server_fd, int status, void *data);
++static void icapOptWriteComplete(int fd, char *bufnotused, size_t size, int errflag, void *data);
++static void icapOptReadReply(int fd, void *data);
++
++/*
++ * reply parsing functions
++ */
++static int icapOptParseReply(icap_service * s, IcapOptData * i);
++static void icapOptParseEntry(icap_service * s, const char *blk_start, const char *blk_end);
++static int icapIsolateLine(const char **parse_start, const char **blk_start, const char **blk_end);
++
++/*
++ * helper functions
++ */
++static void icapOptDataInit(IcapOptData * i);
++static void icapOptDataFree(IcapOptData * i);
++
++/*************************************************************/
++
++#define TIMEOUT 10
++
++void
++icapOptInit()
++{
++    icap_service *s;
++
++    /* iterate over configured services */
++    s = Config.icapcfg.service_head;
++    while (s) {
++	eventAdd("icapOptStart", icapOptStart, s, 5.0, 1);
++	s = s->next;
++    }
++}
++
++void
++icapOptShutdown()
++{
++    icap_service *s;
++
++    s = Config.icapcfg.service_head;
++    while (s) {
++	if (eventFind(icapOptStart, s)) {
++	    eventDelete(icapOptStart, s);
++	}
++	s = s->next;
++    }
++}
++
++/*
++ * mark a service as unreachable
++ */
++void
++icapOptSetUnreachable(icap_service * s)
++{
++    s->unreachable = 1;
++    debug(81, 5) ("icapOptSetUnreachable: got called for %s\n", s->uri);
++    /*
++     * if there is an options request scheduled, delete it and add
++     * it again to reset the time to the default check_interval.
++     */
++    if (eventFind(icapOptStart, s)) {
++	eventDelete(icapOptStart, s);
++	eventAdd("icapOptStart", icapOptStart, s, Config.icapcfg.check_interval, 1);
++    }
++}
++
++static void
++icapOptStart(void *data)
++{
++    icap_service *s = data;
++    int fd;
++    int ctimeout = TIMEOUT;
++    const char *host = s->hostname;
++    unsigned short port = s->port;
++    debug(81, 3) ("icapOptStart: starting OPTIONS request for %s (%s)\n", s->name, s->uri);
++    fd = comm_open(SOCK_STREAM,
++	0,
++	getOutgoingAddr(NULL),
++	0,
++	COMM_NONBLOCKING,
++	"ICAP OPTIONS connection");
++    if (fd < 0) {
++	debug(81, 4) ("icapConnectStart: %s\n", xstrerror());
++	eventAdd("icapOptStart", icapOptStart, s, Config.icapcfg.check_interval, 1);
++	return;
++    }
++    assert(s->opt == NULL);	/* if not null, another options request might be running, which should not happen */
++    s->opt = memAllocate(MEM_ICAP_OPT_DATA);
++    icapOptDataInit(s->opt);
++    cbdataLock(s);
++    commSetTimeout(fd, ctimeout, icapOptTimeout, s);
++    commConnectStart(fd, host, port, icapOptConnectDone, s);
++}
++
++static void
++icapOptTimeout(int fd, void *data)
++{
++    icap_service *s = data;
++    IcapOptData *i = s->opt;
++    int valid;
++
++    debug(81, 4) ("icapOptConnectTimeout: fd=%d, service=%s\n", fd, s->uri);
++
++    comm_close(fd);
++    valid = cbdataValid(s);
++    cbdataUnlock(s);
++    if (!valid) {
++	icapOptDataFree(i);
++	s->opt = NULL;
++	return;
++    }
++    /* try again later */
++    icapOptDataFree(i);
++    s->opt = NULL;
++    s->unreachable = 1;
++    debug(81, 3) ("icapOptConnectTimeout: unreachable=1, service=%s\n", s->uri);
++    eventAdd("icapOptStart", icapOptStart, s, Config.icapcfg.check_interval, 1);
++
++}
++
++static void
++icapOptConnectDone(int server_fd, int status, void *data)
++{
++    icap_service *s = data;
++    IcapOptData *i = s->opt;
++    MemBuf request;
++    int valid;
++
++    valid = cbdataValid(s);
++    cbdataUnlock(s);
++    if (!valid) {
++	comm_close(server_fd);
++	icapOptDataFree(i);
++	s->opt = NULL;
++	return;
++    }
++    if (status != COMM_OK) {
++	debug(81, 3) ("icapOptConnectDone: unreachable=1, service=%s\n", s->uri);
++	comm_close(server_fd);
++	icapOptDataFree(i);
++	s->opt = NULL;
++	s->unreachable = 1;
++	eventAdd("icapOptStart", icapOptStart, s, Config.icapcfg.check_interval, 1);
++	return;
++    }
++    debug(81, 3) ("icapOptConnectDone: Connection ok. Sending Options request for %s\n", s->name);
++    memBufDefInit(&request);
++    memBufPrintf(&request, "OPTIONS %s ICAP/1.0\r\n", s->uri);
++    memBufPrintf(&request, "Host: %s\r\n", s->hostname);
++    memBufPrintf(&request, "Connection: close\r\n");
++    memBufPrintf(&request, "User-Agent: ICAP-Client-Squid/1.2\r\n");
++    memBufPrintf(&request, "\r\n");
++    cbdataLock(s);
++    commSetTimeout(server_fd, TIMEOUT, icapOptTimeout, s);
++    comm_write_mbuf(server_fd, request, icapOptWriteComplete, s);
++}
++
++static void
++icapOptWriteComplete(int fd, char *bufnotused, size_t size, int errflag, void *data)
++{
++    icap_service *s = data;
++    IcapOptData *i = s->opt;
++    int valid;
++
++    valid = cbdataValid(s);
++    cbdataUnlock(s);
++    if (!valid) {
++	comm_close(fd);
++	icapOptDataFree(i);
++	s->opt = NULL;
++	return;
++    }
++    debug(81, 5) ("icapOptWriteComplete: FD %d: size %d: errflag %d.\n",
++	fd, size, errflag);
++    if (size > 0) {
++	fd_bytes(fd, size, FD_WRITE);
++	kb_incr(&statCounter.icap.all.kbytes_out, size);
++    }
++    if (errflag) {
++	/* cancel this for now */
++	debug(81, 3) ("icapOptWriteComplete: unreachable=1, service=%s\n", s->uri);
++	icapOptDataFree(i);
++	s->opt = NULL;
++	s->unreachable = 1;
++	eventAdd("icapOptStart", icapOptStart, s, Config.icapcfg.check_interval, 1);
++	comm_close(fd);
++	return;
++    }
++    cbdataLock(s);
++    commSetSelect(fd, COMM_SELECT_READ, icapOptReadReply, s, 0);
++}
++
++static void
++icapOptReadReply(int fd, void *data)
++{
++    icap_service *s = data;
++    IcapOptData *i = s->opt;
++    int size;
++    int len = i->size - i->offset - 1;
++    int valid;
++
++    valid = cbdataValid(s);
++    cbdataUnlock(s);
++    if (!valid) {
++	comm_close(fd);
++	icapOptDataFree(i);
++	s->opt = NULL;
++	return;
++    }
++    if (len == 0) {
++	/* Grow the request memory area to accomodate for a large request */
++	printf("PANIC: not enough memory\n");
++#if 0
++	i->buf = memReallocBuf(i->buf, i->size * 2, &i->size);
++	debug(81, 2) ("icapoptReadReply: growing reply buffer: offset=%ld size=%ld\n",
++	    (long) i->offset, (long) i->size);
++	len = i->size - i->offset - 1;
++#endif
++    }
++    size = FD_READ_METHOD(fd, i->buf + i->offset, len);
++    i->offset += size;
++    debug(81, 3) ("icapOptReadReply: Got %d bytes of data\n", size);
++    if (size > 0) {
++	/* do some statistics */
++	fd_bytes(fd, size, FD_READ);
++	kb_incr(&statCounter.icap.all.kbytes_in, size);
++
++	/* 
++	 * some icap servers seem to ignore the  "Connection: close" header. so 
++	 * after getting the complete option reply we close the connection 
++	 * ourself.
++	 */
++	if ((i->headlen = headersEnd(i->buf, i->offset))) {
++	    debug(81, 3) ("icapOptReadReply: EndOfResponse\n");
++	    size = 0;
++	}
++    }
++    if (size < 0) {
++	debug(81, 3) ("icapOptReadReply: FD %d: read failure: %s.\n", fd, xstrerror());
++	debug(81, 3) ("icapOptReadReply: unreachable=1, service=%s.\n", s->uri);
++	s->unreachable = 1;
++	icapOptDataFree(i);
++	s->opt = NULL;
++	eventAdd("icapOptStart", icapOptStart, s, Config.icapcfg.check_interval, 1);
++	comm_close(fd);
++    } else if (size == 0) {
++	/* no more data, now we can parse the reply */
++	debug(81, 3) ("icapOptReadReply: FD %d: connection closed\n", fd);
++	i->buf[i->offset] = '\0';	/* for string functions */
++	debug(81, 3) ("icapOptReadReply: unreachable=0, service=%s\n", s->uri);
++
++	if (!icapOptParseReply(s, i)) {
++	    debug(81, 3) ("icapOptReadReply: OPTIONS request not successful. scheduling again in %d seconds\n", Config.icapcfg.check_interval);
++	    s->unreachable = 1;
++	} else
++	    s->unreachable = 0;
++
++	if (s->options_ttl <= 0)
++	    s->options_ttl = Config.icapcfg.check_interval;
++	eventAdd("icapOptStart", icapOptStart, s, s->options_ttl, 1);
++
++	icapOptDataFree(i);
++	s->opt = NULL;
++	comm_close(fd);
++    } else {
++	/* data received */
++	/* commSetSelect(fd, Type, handler, client_data, timeout) */
++	cbdataLock(s);
++	commSetSelect(fd, COMM_SELECT_READ, icapOptReadReply, data, 0);
++    }
++}
++
++static int
++icapIsolateLine(const char **parse_start, const char **blk_start, const char **blk_end)
++{
++    int slen = strcspn(*parse_start, "\r\n");
++
++    if (!(*parse_start)[slen])	/* no crlf */
++	return 0;
++
++    if (slen == 0)		/* empty line */
++	return 0;
++
++    *blk_start = *parse_start;
++    *blk_end = *blk_start + slen;
++
++    /* set it to the beginning of next line */
++    *parse_start = *blk_end;
++    while (**parse_start == '\r')	/* CR */
++	(*parse_start)++;
++    if (**parse_start == '\n')	/* LF */
++	(*parse_start)++;
++    return 1;
++}
++
++/* process a single header entry between blk_start and blk_end */
++static void
++icapOptParseEntry(icap_service * s, const char *blk_start, const char *blk_end)
++{
++    const char *name_end = strchr(blk_start, ':');
++    const int name_len = name_end ? name_end - blk_start : 0;
++    const char *value_start = blk_start + name_len + 1;		/* skip ':' */
++    int value_len;
++    int new;
++
++    if (!name_len || name_end > blk_end) {
++	debug(81, 5) ("icapOptParseEntry: strange header. skipping\n");
++	return;
++    }
++    if (name_len > 65536) {
++	debug(81, 5) ("icapOptParseEntry: unusual long header item. skipping.\n");
++	return;
++    }
++    while (xisspace(*value_start) && value_start < blk_end) {
++	value_start++;
++    }
++    if (value_start >= blk_end) {
++	debug(81, 5) ("icapOptParseEntry: no value found\n");
++	return;
++    }
++    value_len = blk_end - value_start;
++
++
++    /* extract information */
++    if (!strncasecmp("Allow", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found Allow\n");
++	if (!strncmp("204", value_start, 3)) {
++	    s->flags.allow_204 = 1;
++	} else {
++	    debug(81, 3) ("icapOptParseEntry: Allow value unknown");
++	}
++    } else if (!strncasecmp("Connection", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found Connection\n");
++    } else if (!strncasecmp("Encapsulated", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found Encapsulated\n");
++    } else if (!strncasecmp("ISTAG", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found ISTAG\n");
++	stringClean(&s->istag);
++	stringLimitInit(&s->istag, value_start, value_len);
++    } else if (!strncasecmp("Max-Connections", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found Max-Connections\n");
++	errno = 0;
++	new = strtol(value_start, NULL, 10);
++	if (errno) {
++	    debug(81, 5) ("icapOptParseEntry: Max-Connections: could not parse value\n");
++	} else {
++	    debug(81, 5) ("icapOptParseEntry: Max-Connections: new value=%d\n", new);
++	    s->max_connections = new;
++	}
++    } else if (!strncasecmp("Methods", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found Methods\n");
++    } else if (!strncasecmp("Options-TTL", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found Options-TTL\n");
++	errno = 0;
++	new = strtol(value_start, NULL, 10);
++	if (errno) {
++	    debug(81, 5) ("icapOptParseEntry: Options-TTL: could not parse value\n");
++	} else {
++	    debug(81, 5) ("icapOptParseEntry: Options-TTL: new value=%d\n", new);
++	    s->options_ttl = new;
++	}
++    } else if (!strncasecmp("Preview", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found Preview\n");
++	errno = 0;
++	new = strtol(value_start, NULL, 10);
++	if (errno) {
++	    debug(81, 5) ("icapOptParseEntry: Preview: could not parse value\n");
++	} else {
++	    debug(81, 5) ("icapOptParseEntry: Preview: new value=%d\n", new);
++	    s->preview = new;
++	}
++    } else if (!strncasecmp("Service", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found Service\n");
++    } else if (!strncasecmp("Service-ID", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found Service-ID\n");
++    } else if (!strncasecmp("Transfer-Preview", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found Transfer-Preview\n");
++	stringClean(&s->transfer_preview);
++	stringLimitInit(&s->transfer_preview, value_start, value_len);
++    } else if (!strncasecmp("Transfer-Ignore", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found Transfer-Ignore\n");
++	stringClean(&s->transfer_ignore);
++	stringLimitInit(&s->transfer_ignore, value_start, value_len);
++    } else if (!strncasecmp("Transfer-Complete", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found Transfer-Complete\n");
++	stringClean(&s->transfer_complete);
++	stringLimitInit(&s->transfer_complete, value_start, value_len);
++    } else if (!strncasecmp("X-Include", blk_start, name_len)) {
++	debug(81, 5) ("icapOptParseEntry: found X-Include\n");
++	if (strstr(value_start, "X-Client-IP")) {
++	    debug(81, 5) ("icapOptParseEntry: X-Include: found X-Client-IP\n");
++	    s->flags.need_x_client_ip = 1;
++	}
++	if (strstr(value_start, "X-Server-IP")) {
++	    debug(81, 5) ("icapOptParseEntry: X-Include: found X-Server-IP\n");
++	    s->flags.need_x_server_ip = 1;
++	}
++	if (strstr(value_start, "X-Authenticated-User")) {
++	    debug(81, 5) ("icapOptParseEntry: X-Include: found X-Authenticated-User\n");
++	    s->flags.need_x_authenticated_user = 1;
++	}
++    } else {
++	debug(81, 5) ("icapOptParseEntry: unknown options header\n");
++    }
++}
++
++/* parse OPTIONS reply */
++static int
++icapOptParseReply(icap_service * s, IcapOptData * i)
++{
++    int version_major, version_minor;
++    const char *str_status;
++    int status;
++    const char *buf = i->buf;
++    const char *parse_start;
++    const char *head_end;
++    const char *blk_start;
++    const char *blk_end;
++
++    if ((status =
++	    icapParseStatusLine(i->buf, i->offset,
++		&version_major, &version_minor, &str_status)) < 0) {
++	debug(81, 2) ("icapOptParseReply: bad status line <%s>\n", i->buf);
++	return 0;
++    }
++    debug(81, 3) ("icapOptParseReply: got reply: <ICAP/%d.%d %d %s>\n", version_major, version_minor, status, str_status);
++
++    if (status != 200) {
++	debug(81, 3) ("icapOptParseReply: status = %d != 200\n", status);
++	return 0;
++    }
++    parse_start = buf;
++    if (i->headlen == 0)
++	i->headlen = headersEnd(parse_start, s->opt->offset);
++
++    if (!i->headlen) {
++	debug(81, 2) ("icapOptParseReply: end of headers could not be found\n");
++	return 0;
++    }
++    head_end = parse_start + i->headlen - 1;
++    while (*(head_end - 1) == '\r')
++	head_end--;
++    assert(*(head_end - 1) == '\n');
++    if (*head_end != '\r' && *head_end != '\n')
++	return 0;		/* failure */
++
++    /* skip status line */
++    if (!icapIsolateLine(&parse_start, &blk_start, &blk_end)) {
++	debug(81, 3) ("icapOptParseReply: failure in isolating status line\n");
++	return 0;
++
++    }
++    /* now we might start real parsing */
++    while (icapIsolateLine(&parse_start, &blk_start, &blk_end)) {
++	if (blk_end > head_end || blk_start > head_end || blk_start >= blk_end) {
++	    debug(81, 3) ("icapOptParseReply: header limit exceeded. finished.\n");
++	    break;
++	}
++	icapOptParseEntry(s, blk_start, blk_end);
++    }
++    return 1;
++}
++
++static void
++icapOptDataInit(IcapOptData * i)
++{
++    i->buf = memAllocBuf(HTTP_REPLY_BUF_SZ, &i->size);
++    i->offset = 0;
++    i->headlen = 0;
++}
++
++static void
++icapOptDataFree(IcapOptData * i)
++{
++    if (i) {
++	memFreeBuf(i->size, i->buf);
++	memFree(i, MEM_ICAP_OPT_DATA);
++    }
++}
+Index: src/icap_reqmod.c
+===================================================================
+RCS file: src/icap_reqmod.c
+diff -N src/icap_reqmod.c
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ src/icap_reqmod.c	31 Jan 2007 18:11:13 -0000	1.1.14.10
+@@ -0,0 +1,989 @@
++
++/*
++ * $Id$
++ *
++ * DEBUG: section 81    Internet Content Adaptation Protocol (ICAP) Client
++ * AUTHOR: Geetha Manjunath, Hewlett Packard Company
++ *
++ * SQUID Web Proxy Cache          http://www.squid-cache.org/
++ * ----------------------------------------------------------
++ *
++ *  Squid is the result of efforts by numerous individuals from
++ *  the Internet community; see the CONTRIBUTORS file for full
++ *  details.   Many organizations have provided support for Squid's
++ *  development; see the SPONSORS file for full details.  Squid is
++ *  Copyrighted (C) 2001 by the Regents of the University of
++ *  California; see the COPYRIGHT file for full details.  Squid
++ *  incorporates software developed and/or copyrighted by other
++ *  sources; see the CREDITS file for full details.
++ *
++ *  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, USA.
++ *
++ */
++
++#include "squid.h"
++
++#define ICAP_PROXY_KEEP_ALIVE 0
++
++/*
++ * These once-static functions are required to be global for ICAP
++ */
++
++PF clientReadRequest;
++PF connStateFree;
++StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, request_flags);
++int clientReadDefer(int fd, void *data);
++int clientCheckContentLength(request_t * r);
++void clientProcessRequest(clientHttpRequest *);
++int clientCachable(clientHttpRequest *);
++int clientHierarchical(clientHttpRequest *);
++void clientReadBody(request_t * request, char *buf, size_t size,
++    CBCB * callback, void *cbdata);
++static void icapReqModPassHttpBody(IcapStateData * icap, char *buf, size_t size,
++    CBCB * callback, void *cbdata);
++
++static PF icapReqModReadHttpHdrs;
++static PF icapReqModReadHttpBody;
++static CWCB icapReqModSendBodyChunk;
++static CBCB icapReqModBodyHandler;
++static BODY_HANDLER icapReqModBodyReader;
++static STRCB icapReqModMemBufAppend;
++
++#define EXPECTED_ICAP_HEADER_LEN 256
++static const char *crlf = "\r\n";
++
++/*
++ * icapExpectedHttpReqHdrSize
++ *
++ * calculate the size of the HTTP headers that we expect
++ * to read from the ICAP server.
++ */
++static int
++icapExpectedHttpReqHdrSize(IcapStateData * icap)
++{
++    if (icap->enc.req_body > -1 && icap->enc.req_hdr > -1)
++	return (icap->enc.req_body - icap->enc.req_hdr);
++    if (icap->enc.null_body > -1)
++	return icap->enc.null_body;
++    fatal("icapExpectedHttpReqHdrSize: unexpected case");
++    return 0;
++}
++
++/*
++ * icapReqModCreateClientState
++ *
++ * Creates fake client_side data structures so we can use
++ * that module to read/parse the HTTP request that we read
++ * from the ICAP server.
++ */
++static clientHttpRequest *
++icapReqModCreateClientState(IcapStateData * icap, request_t * request)
++{
++    clientHttpRequest *http;
++    if (!cbdataValid(icap->reqmod.client_cookie)) {
++	debug(81, 3) ("Whups, client cookie invalid\n");
++	icap->reqmod.client_fd = -1;
++	return NULL;
++    }
++    http = cbdataAlloc(clientHttpRequest);
++    /*
++     * use our own urlCanonicalClean here, because urlCanonicalClean
++     * may strip everything after a question-mark. As http->uri
++     * is used when doing a request to a parent proxy, we need the full
++     * url here.
++     */
++    http->uri = xstrdup(urlCanonical(icap->request));
++    http->range_iter.boundary = StringNull;
++    http->request = requestLink(request ? request : icap->request);
++    http->flags.did_icap_reqmod = 1;
++    http->start = icap->reqmod.start;
++    if (request)
++	http->http_ver = request->http_ver;
++#if ICAP_PROXY_KEEP_ALIVE
++    /*
++     * Here it is possible becouse we are using as client_cookie the original http->conn
++     * if we will keep this code we must declare an icap->conn field........
++     * Will work if pipeline_prefetch is not enabled
++     * We are using a dummy ConnStateData structure, just to free
++     * old clientHttpRequest :-( 
++     * OK,all this code is a hack and possibly must not exists in cvs ......
++     */
++
++    http->conn = icap->reqmod.client_cookie;
++    assert(http->conn->chr->next == NULL);
++    {
++	ConnStateData *dummyconn;
++	clientHttpRequest *H;
++	dummyconn = cbdataAlloc(ConnStateData);
++	dummyconn->fd = icap->reqmod.client_fd;
++	dummyconn->pinning.fd = -1;
++	H = DLINK_HEAD(conn->reqs);
++	dlinkAddTail(H, &H->node, &dummyconn->reqs);
++	H->conn = dummyconn;
++	comm_add_close_handler(dummyconn->fd, connStateFree, dummyconn);
++    }
++    http->conn->chr = http;
++#else
++    http->conn = cbdataAlloc(ConnStateData);
++    http->conn->fd = icap->reqmod.client_fd;
++    http->conn->pinning.fd = -1;
++    http->conn->in.size = 0;
++    http->conn->in.buf = NULL;
++    http->conn->log_addr = icap->reqmod.log_addr;
++    dlinkAddTail(http, &http->node, &http->conn->reqs);
++    comm_add_close_handler(http->conn->fd, connStateFree, http->conn);
++#endif
++    http->icap_reqmod = NULL;
++    return http;
++}
++
++/*
++ * icapReqModInterpretHttpRequest
++ *
++ * Interpret an HTTP request that we read from the ICAP server.
++ * Create some "fake" clientHttpRequest and ConnStateData structures
++ * so we can pass this new request off to the routines in
++ * client_side.c.
++ */
++static void
++icapReqModInterpretHttpRequest(IcapStateData * icap, request_t * request)
++{
++    clientHttpRequest *http = icapReqModCreateClientState(icap, request);
++    if (NULL == http)
++	return;
++    /*
++     * bits from clientReadRequest
++     */
++    request->content_length = httpHeaderGetSize(&request->header,
++	HDR_CONTENT_LENGTH);
++    if (!urlCheckRequest(request) ||
++	httpHeaderHas(&request->header, HDR_TRANSFER_ENCODING)) {
++	ErrorState *err;
++	err = errorCon(ERR_UNSUP_REQ, HTTP_NOT_IMPLEMENTED, request);
++	request->flags.proxy_keepalive = 0;
++	http->entry =
++	    clientCreateStoreEntry(http, request->method, null_request_flags);
++	errorAppendEntry(http->entry, err);
++	return;
++    }
++    if (!clientCheckContentLength(request)) {
++	ErrorState *err;
++	err = errorCon(ERR_INVALID_REQ, HTTP_LENGTH_REQUIRED, request);
++	http->entry =
++	    clientCreateStoreEntry(http, request->method, null_request_flags);
++	errorAppendEntry(http->entry, err);
++	return;
++    }
++    /* Do we expect a request-body? */
++    if (request->content_length > 0) {
++	debug(81, 5) ("handing request bodies in ICAP REQMOD\n");
++	if (request->body_reader_data)
++	    cbdataUnlock(request->body_reader_data);
++	request->body_reader = icapReqModBodyReader;
++	request->body_reader_data = icap;	/* XXX cbdataLock? */
++	cbdataLock(icap);	/*Yes sure ..... */
++	memBufDefInit(&icap->reqmod.http_entity.buf);
++    }
++    if (clientCachable(http))
++	request->flags.cachable = 1;
++    if (clientHierarchical(http))
++	request->flags.hierarchical = 1;
++    clientProcessRequest(http);
++}
++
++/*
++ * icapReqModParseHttpError
++ *
++ * Handle an error when parsing the new HTTP request we read
++ * from the ICAP server.
++ */
++static void
++icapReqModParseHttpError(IcapStateData * icap, const char *reason)
++{
++    debug(81, 1) ("icapReqModParseHttpError: %s\n", reason);
++}
++
++/*
++ * icapEntryError
++ *
++ * A wrapper for errorCon() and errorAppendEntry().
++ */
++static void
++icapEntryError(IcapStateData * icap, err_type et, http_status hs, int xerrno)
++{
++    ErrorState *err;
++    clientHttpRequest *http = icapReqModCreateClientState(icap, NULL);
++    if (NULL == http)
++	return;
++    http->entry = clientCreateStoreEntry(http,
++	icap->request->method, null_request_flags);
++    err = errorCon(et, hs, icap->request);
++    err->xerrno = xerrno;
++    errorAppendEntry(http->entry, err);
++}
++
++/*
++ * icapReqModParseHttpRequest
++ * 
++ * Parse the HTTP request that we read from the ICAP server.
++ * Creates and fills in the request_t structure.
++ */
++static void
++icapReqModParseHttpRequest(IcapStateData * icap)
++{
++    char *mstr;
++    char *uri;
++    char *inbuf;
++    char *t;
++    char *token;
++    char *headers;
++    method_t method;
++    request_t *request;
++    http_version_t http_ver;
++    int reqlen = icap->reqmod.hdr_buf.size;
++    int hdrlen;
++
++    /*
++     * Lazy, make a copy of the buf so I can chop it up with strtok()
++     */
++    inbuf = xcalloc(reqlen + 1, 1);
++    memcpy(inbuf, icap->reqmod.hdr_buf.buf, reqlen);
++
++    if ((mstr = strtok(inbuf, "\t ")) == NULL) {
++	debug(81, 1) ("icapReqModParseHttpRequest: Can't get request method\n");
++	icapReqModParseHttpError(icap, "error:invalid-request-method");
++	xfree(inbuf);
++	return;
++    }
++    method = urlParseMethod(mstr);
++    if (method == METHOD_NONE) {
++	debug(81, 1) ("icapReqModParseHttpRequest: Unsupported method '%s' (%d)\n",
++	    mstr, strlen(mstr));
++	icapReqModParseHttpError(icap, "error:unsupported-request-method");
++	xfree(inbuf);
++	return;
++    }
++    /* look for URL+HTTP/x.x */
++    if ((uri = strtok(NULL, "\n")) == NULL) {
++	debug(81, 1) ("icapReqModParseHttpRequest: Missing URI\n");
++	icapReqModParseHttpError(icap, "error:missing-url");
++	xfree(inbuf);
++	return;
++    }
++    while (xisspace(*uri))
++	uri++;
++    t = uri + strlen(uri);
++    assert(*t == '\0');
++    token = NULL;
++    while (t > uri) {
++	t--;
++	if (xisspace(*t) && !strncmp(t + 1, "HTTP/", 5)) {
++	    token = t + 1;
++	    break;
++	}
++    }
++    while (t > uri && xisspace(*t))
++	*(t--) = '\0';
++    debug(81, 5) ("icapReqModParseHttpRequest: URI is '%s'\n", uri);
++    if (token == NULL) {
++	debug(81, 3) ("icapReqModParseHttpRequest: Missing HTTP identifier\n");
++	icapReqModParseHttpError(icap, "error:missing-http-ident");
++	xfree(inbuf);
++	return;
++    }
++    if (sscanf(token + 5, "%d.%d", &http_ver.major, &http_ver.minor) != 2) {
++	debug(81, 3) ("icapReqModParseHttpRequest: Invalid HTTP identifier.\n");
++	icapReqModParseHttpError(icap, "error:invalid-http-ident");
++	xfree(inbuf);
++	return;
++    }
++    debug(81, 6) ("icapReqModParseHttpRequest: Client HTTP version %d.%d.\n",
++	http_ver.major, http_ver.minor);
++
++    headers = strtok(NULL, null_string);
++    hdrlen = inbuf + reqlen - headers;
++
++    if ((request = urlParse(method, uri)) == NULL) {
++	debug(81, 3) ("Invalid URL: %s at %s:%d\n", uri, __FILE__, __LINE__);
++	icapEntryError(icap, ERR_INVALID_URL, HTTP_BAD_REQUEST, 0);
++	xfree(inbuf);
++	return;
++    }
++    /* compile headers */
++    if (!httpHeaderParse(&request->header, headers, headers + hdrlen)) {
++	debug(81, 3) ("Failed to parse HTTP headers for: %s at %s:%d",
++	    uri, __FILE__, __LINE__);
++	icapEntryError(icap, ERR_INVALID_REQ, HTTP_BAD_REQUEST, 0);
++	xfree(inbuf);
++	return;
++    }
++    debug(81,
++	3)
++	("icapReqModParseHttpRequest: successfully parsed the HTTP request\n");
++    request->http_ver = http_ver;
++    request->client_addr = icap->request->client_addr;
++    request->client_port = icap->request->client_port;
++    request->my_addr = icap->request->my_addr;
++    request->my_port = icap->request->my_port;
++    request->class = icap->request->class;
++    if (icap->request->auth_user_request) {
++	/* Copy authentification info in new request */
++	request->auth_user_request = icap->request->auth_user_request;
++	authenticateAuthUserRequestLock(request->auth_user_request);
++    }
++    request->content_length = httpHeaderGetSize(&request->header,
++	HDR_CONTENT_LENGTH);
++    if (strBuf(icap->request->extacl_log))
++	request->extacl_log = stringDup(&icap->request->extacl_log);
++    if (icap->request->extacl_user)
++	request->extacl_user = xstrdup(icap->request->extacl_user);
++    if (icap->request->extacl_passwd)
++	request->extacl_passwd = xstrdup(icap->request->extacl_passwd);
++#if ICAP_PROXY_KEEP_ALIVE
++    /*
++     * Copy the proxy_keepalive flag from the original request
++     */
++    request->flags.proxy_keepalive = icap->request->flags.proxy_keepalive;
++    /*
++     * If proxy_keepalive was set for the original request, make
++     * sure that the adapated request also has the necessary headers
++     * for keepalive
++     */
++    if (request->flags.proxy_keepalive) {
++	if (!httpMsgIsPersistent(http_ver, &request->header))
++	    request->flags.proxy_keepalive = 0;
++    }
++#endif
++    icapReqModInterpretHttpRequest(icap, request);
++    xfree(inbuf);
++}
++
++/*
++ * icapReqModHandoffRespMod
++ *
++ * Handles the case where a REQMOD request results in an HTTP REPLY
++ * (instead of an ICAP REPLY that contains a new HTTP REQUEST).  We
++ * prepare the IcapStateData for passing off to the icap_reqmod
++ * code, where we have functions for reading HTTP replies in ICAP
++ * messages.
++ */
++static void
++icapReqModHandoffRespMod(IcapStateData * icap)
++{
++    extern PF icapReadReply;
++    clientHttpRequest *http = icapReqModCreateClientState(icap, NULL);
++    if (NULL == http)
++	return;
++    assert(icap->request);
++    http->entry = clientCreateStoreEntry(http,
++	icap->request->method, icap->request->flags);
++    icap->respmod.entry = http->entry;
++    storeLockObject(icap->respmod.entry);
++
++    /* icap->http_flags = ? */
++    memBufDefInit(&icap->respmod.buffer);
++    memBufDefInit(&icap->chunk_buf);
++    assert(icap->current_service);
++    icapReadReply(icap->icap_fd, icap);
++}
++
++/*
++ * icapReqModKeepAliveOrClose
++ *
++ * Called when we are done reading from the ICAP server.
++ * Either close the connection or keep it open for a future
++ * transaction.
++ */
++static void
++icapReqModKeepAliveOrClose(IcapStateData * icap)
++{
++    int fd = icap->icap_fd;
++    debug(81, 3) ("%s:%d FD %d\n", __FILE__, __LINE__, fd);
++    if (fd < 0)
++	return;
++    if (!icap->flags.keep_alive) {
++	debug(81, 3) ("%s:%d keep_alive not set, closing\n", __FILE__,
++	    __LINE__);
++	comm_close(fd);
++	return;
++    }
++    if (icap->request->content_length < 0) {
++	/* no message body */
++	debug(81, 3) ("%s:%d no message body\n", __FILE__, __LINE__);
++	if (1 != icap->reqmod.hdr_state) {
++	    /* didn't get to end of HTTP headers */
++	    debug(81, 3) ("%s:%d didnt find end of headers, closing\n",
++		__FILE__, __LINE__);
++	    comm_close(fd);
++	    return;
++	}
++    } else if (icap->reqmod.http_entity.bytes_read !=
++	icap->request->content_length) {
++	debug(81, 3) ("%s:%d bytes_read (%" PRINTF_OFF_T ") != content_length (%" PRINTF_OFF_T ")\n",
++	    __FILE__, __LINE__, icap->reqmod.http_entity.bytes_read,
++	    icap->request->content_length);
++	/* an error */
++	comm_close(fd);
++	return;
++    }
++    debug(81, 3) ("%s:%d looks good, keeping alive\n", __FILE__, __LINE__);
++    commSetDefer(fd, NULL, NULL);
++    commSetTimeout(fd, -1, NULL, NULL);
++    commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
++    comm_remove_close_handler(fd, icapStateFree, icap);
++    pconnPush(fd, icap->current_service->hostname, icap->current_service->port, NULL, NULL, 0);
++    icap->icap_fd = -1;
++    icapStateFree(-1, icap);
++}
++
++/*
++ * icapReqModReadHttpHdrs
++ *
++ * Read the HTTP reply from the ICAP server.  Uses the values
++ * from the ICAP Encapsulation header to know how many bytes
++ * to read.
++ */
++static void
++icapReqModReadHttpHdrs(int fd, void *data)
++{
++    IcapStateData *icap = data;
++    LOCAL_ARRAY(char, tmpbuf, SQUID_TCP_SO_RCVBUF);
++    int rl;
++    debug(81, 3) ("icapReqModReadHttpHdrs:\n");
++    assert(fd == icap->icap_fd);
++    assert(icap->enc.req_hdr == 0);
++    if (0 == icap->reqmod.hdr_state) {
++	int expect = icapExpectedHttpReqHdrSize(icap);
++	int so_far = icap->http_header_bytes_read_so_far;
++	int needed = expect - so_far;
++	debug(81, 3) ("expect=%d\n", expect);
++	debug(81, 3) ("so_far=%d\n", so_far);
++	debug(81, 3) ("needed=%d\n", needed);
++	assert(needed >= 0);
++	if (0 == expect) {
++	    fatalf("unexpected condition in %s:%d", __FILE__, __LINE__);
++	}
++	rl = FD_READ_METHOD(fd, tmpbuf, needed);
++	debug(81, 3) ("icapReqModReadHttpHdrs: read %d bytes\n", rl);
++	if (rl < 0) {
++	    fatalf("need to handle read error at %s:%d", __FILE__, __LINE__);
++	}
++	fd_bytes(fd, rl, FD_READ);
++	kb_incr(&statCounter.icap.all.kbytes_in, rl);
++	memBufAppend(&icap->reqmod.hdr_buf, tmpbuf, rl);
++	icap->http_header_bytes_read_so_far += rl;
++	if (rl != needed) {
++	    /* still more header data to read */
++	    commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpHdrs, icap,
++		0);
++	    return;
++	}
++	icap->reqmod.hdr_state = 1;
++    }
++    assert(1 == icap->reqmod.hdr_state);
++    debug(81, 3) ("icapReqModReadHttpHdrs: read the entire request headers\n");
++    icapReqModParseHttpRequest(icap);
++    if (-1 == icap->reqmod.client_fd) {
++	/* we detected that the original client_side went away */
++	icapReqModKeepAliveOrClose(icap);
++    } else if (icap->enc.req_body > -1) {
++	icap->chunk_size = 0;
++	memBufDefInit(&icap->chunk_buf);
++	commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpBody, icap, 0);
++    } else {
++	icapReqModKeepAliveOrClose(icap);
++    }
++}
++
++
++/*
++ * icapReqModReadIcapPart
++ *
++ * Read the ICAP reply header.
++ */
++static void
++icapReqModReadIcapPart(int fd, void *data)
++{
++    IcapStateData *icap = data;
++    int version_major, version_minor;
++    const char *str_status;
++    int x;
++    const char *start;
++    const char *end;
++    int status;
++    int isIcap = 0;
++    int directResponse = 0;
++
++    debug(81, 5) ("icapReqModReadIcapPart: FD %d httpState = %p\n", fd, data);
++    statCounter.syscalls.sock.reads++;
++
++    x = icapReadHeader(fd, icap, &isIcap);
++    if (x < 0) {
++	/* Did not find a proper ICAP response */
++	debug(81, 3) ("ICAP : Error path!\n");
++	icapEntryError(icap, ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR,
++	    errno);
++	comm_close(fd);
++	return;
++    }
++    if (x == 0) {
++	/*
++	 * Waiting for more headers.  Schedule new read hander, but
++	 * don't reset timeout.
++	 */
++	commSetSelect(fd, COMM_SELECT_READ, icapReqModReadIcapPart, icap, 0);
++	return;
++    }
++    /*
++     * Parse the ICAP header
++     */
++    assert(icap->icap_hdr.size);
++    debug(81, 3) ("Read icap header : <%s>\n", icap->icap_hdr.buf);
++    if ((status =
++	    icapParseStatusLine(icap->icap_hdr.buf, icap->icap_hdr.size,
++		&version_major, &version_minor, &str_status)) < 0) {
++	debug(81, 1) ("BAD ICAP status line <%s>\n", icap->icap_hdr.buf);
++	/* is this correct in case of ICAP protocol error? */
++	icapEntryError(icap, ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR,
++	    errno);
++	comm_close(fd);
++	return;
++    };
++    if (200 != status && 201 != status) {
++	debug(81, 1) ("Unsupported status '%d' from ICAP server\n", status);
++	icapEntryError(icap, ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR,
++	    errno);
++	comm_close(fd);
++	return;
++    }
++    icapSetKeepAlive(icap, icap->icap_hdr.buf);
++    if (icapFindHeader(icap->icap_hdr.buf, "Encapsulated:", &start, &end)) {
++	icapParseEncapsulated(icap, start, end);
++    } else {
++	debug(81,
++	    1)
++	    ("WARNING: icapReqModReadIcapPart() did not find 'Encapsulated' header\n");
++    }
++    if (icap->enc.res_hdr > -1)
++	directResponse = 1;
++    else if (icap->enc.res_body > -1)
++	directResponse = 1;
++    else
++	directResponse = 0;
++    debug(81, 3) ("icapReqModReadIcapPart: directResponse=%d\n",
++	directResponse);
++
++    /* Check whether it is a direct reply - if so over to http part */
++    if (directResponse) {
++	debug(81,
++	    3)
++	    ("icapReqModReadIcapPart: FD %d, processing HTTP response for REQMOD!\n",
++	    fd);
++	/* got the reply, no need to come here again */
++	icap->flags.wait_for_reply = 0;
++	icap->flags.got_reply = 1;
++	icapReqModHandoffRespMod(icap);
++	return;
++    }
++    memBufDefInit(&icap->reqmod.hdr_buf);
++    commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpHdrs, icap, 0);
++    return;
++}
++
++/*
++ * icapSendReqModDone
++ *
++ * Called after we've sent the ICAP request.  Checks for errors
++ * and installs the handler functions for the next step.
++ */
++static void
++icapSendReqModDone(int fd, char *bufnotused, size_t size, int errflag,
++    void *data)
++{
++    IcapStateData *icap = data;
++
++    debug(81, 5) ("icapSendReqModDone: FD %d: size %d: errflag %d.\n",
++	fd, size, errflag);
++    if (size > 0) {
++	fd_bytes(fd, size, FD_WRITE);
++	kb_incr(&statCounter.icap.all.kbytes_out, size);
++    }
++    if (errflag == COMM_ERR_CLOSING)
++	return;
++    if (errflag) {
++	debug(81, 3) ("icapSendReqModDone: unreachable=1, service=%s\n",
++	    icap->current_service->uri);
++	icapOptSetUnreachable(icap->current_service);
++	icapEntryError(icap, ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR,
++	    errno);
++	comm_close(fd);
++	return;
++    }
++    /* Schedule read reply. */
++    commSetSelect(fd, COMM_SELECT_READ, icapReqModReadIcapPart, icap, 0);
++    /*
++     * Set the read timeout here because it hasn't been set yet.
++     * We only set the read timeout after the request has been
++     * fully written to the server-side.  If we start the timeout
++     * after connection establishment, then we are likely to hit
++     * the timeout for POST/PUT requests that have very large
++     * request bodies.
++     */
++    commSetTimeout(fd, Config.Timeout.read, icapConnectTimeout, icap);
++}
++
++
++/*
++ * icapSendReqMod
++ *
++ * Send the ICAP request, including HTTP request, to the ICAP server
++ * after connection has been established.
++ */
++static void
++icapSendReqMod(int fd, int status, void *data)
++{
++    MemBuf mb;
++    MemBuf mb_hdr;
++    Packer p;
++    IcapStateData *icap = data;
++    char *client_addr;
++    int icap_fd = icap->icap_fd;
++    icap_service *service;
++    CWCB *theCallback;
++
++    debug(81, 5) ("icapSendReqMod FD %d, status %d\n", fd, status);
++    icap->flags.connect_pending = 0;
++
++    if (COMM_OK != status) {
++	debug(81, 1) ("Could not connect to ICAP server %s:%d: %s\n",
++	    icap->current_service->hostname,
++	    icap->current_service->port, xstrerror());
++	debug(81, 3) ("icapSendReqMod: unreachable=1, service=%s\n",
++	    icap->current_service->uri);
++	icapOptSetUnreachable(icap->current_service);
++	icapEntryError(icap, ERR_ICAP_FAILURE, HTTP_SERVICE_UNAVAILABLE, errno);
++	comm_close(fd);
++	return;
++    }
++    fd_table[fd].pconn.uses++;
++    fd_table[fd].pconn.type = 2;
++    if (icap->request->content_length > 0)
++	theCallback = icapReqModSendBodyChunk;
++    else
++	theCallback = icapSendReqModDone;
++
++    memBufDefInit(&mb);
++    memBufDefInit(&mb_hdr);
++    memBufPrintf(&mb_hdr, "%s %s HTTP/%d.%d\r\n",
++	RequestMethodStr[icap->request->method],
++	icap->reqmod.uri,
++	icap->request->http_ver.major, icap->request->http_ver.minor);
++    packerToMemInit(&p, &mb_hdr);
++    httpHeaderPackInto(&icap->request->header, &p);
++    packerClean(&p);
++    memBufAppend(&mb_hdr, crlf, 2);
++    service = icap->current_service;
++    assert(service);
++    client_addr = inet_ntoa(icap->request->client_addr);
++
++    memBufPrintf(&mb, "REQMOD %s ICAP/1.0\r\n", service->uri);
++    memBufPrintf(&mb, "Encapsulated: req-hdr=0");
++    /* TODO: Change the offset using 'request' if needed */
++    if (icap->request->content_length > 0)
++	memBufPrintf(&mb, ", req-body=%d", mb_hdr.size);
++    else
++	memBufPrintf(&mb, ", null-body=%d", mb_hdr.size);
++    memBufAppend(&mb, crlf, 2);
++
++    if (service->flags.need_x_client_ip && Config.icapcfg.send_client_ip)
++	memBufPrintf(&mb, "X-Client-IP: %s\r\n", client_addr);
++
++    if (service->flags.need_x_server_ip && Config.icapcfg.send_server_ip)
++	icapAddOriginIP(&mb, icap->request->host);
++
++    if ((service->flags.need_x_authenticated_user
++	    && Config.icapcfg.send_auth_user)
++	&& (icap->request->auth_user_request != NULL))
++	icapAddAuthUserHeader(&mb, icap->request->auth_user_request);
++    if (service->keep_alive) {
++	icap->flags.keep_alive = 1;
++    } else {
++	icap->flags.keep_alive = 0;
++	memBufAppend(&mb, "Connection: close\r\n", 19);
++    }
++    memBufAppend(&mb, crlf, 2);
++    memBufAppend(&mb, mb_hdr.buf, mb_hdr.size);
++    memBufClean(&mb_hdr);
++
++    debug(81, 5) ("icapSendReqMod: FD %d writing {%s}\n", icap->icap_fd,
++	mb.buf);
++    comm_write_mbuf(icap_fd, mb, theCallback, icap);
++}
++
++/*
++ * icapReqModStart
++ *
++ * Initiate an ICAP REQMOD transaction.  Create and fill in IcapStateData
++ * structure and request a TCP connection to the server.
++ */
++IcapStateData *
++icapReqModStart(icap_service * service, const char *uri, request_t * request,
++    int fd, struct timeval start, struct in_addr log_addr, void *cookie)
++{
++    IcapStateData *icap = NULL;
++
++    debug(81, 3) ("icapReqModStart: type=%d\n", (int) service->type);
++
++    switch (service->type) {
++    case ICAP_SERVICE_REQMOD_PRECACHE:
++	break;
++    default:
++	fatalf("icapReqModStart: unsupported service type '%s'\n",
++	    icap_service_type_str[service->type]);
++	break;
++    }
++
++    if (service->unreachable) {
++	if (service->bypass) {
++	    debug(81,
++		5) ("icapReqModStart: BYPASS because service unreachable: %s\n",
++		service->uri);
++	    return NULL;
++	} else {
++	    debug(81,
++		5) ("icapReqModStart: ERROR  because service unreachable: %s\n",
++		service->uri);
++	    return (IcapStateData *) - 1;
++	}
++    }
++    icap = icapAllocate();
++    if (!icap) {
++	debug(81, 3) ("icapReqModStart: icapAllocate() failed\n");
++	return NULL;
++    }
++    icap->current_service = service;
++    icap->preview_size = service->preview;
++    icap->reqmod.uri = uri;	/* XXX should be xstrdup? */
++    icap->reqmod.start = start;
++    icap->reqmod.log_addr = log_addr;
++    icap->request = requestLink(request);
++    icap->reqmod.hdr_state = 0;
++    icap->reqmod.client_fd = fd;
++    icap->reqmod.client_cookie = cookie;
++    cbdataLock(icap->reqmod.client_cookie);
++
++    if (!icapConnect(icap, icapSendReqMod))
++	return NULL;
++
++    statCounter.icap.all.requests++;
++    debug(81, 3) ("icapReqModStart: returning %p\n", icap);
++    return icap;
++}
++
++/*
++ * icapReqModSendBodyChunk
++ *
++ * A "comm_write" callback.  This is called after comm_write() does
++ * its job to let us know how things went.  If there are no errors,
++ * get another chunk of the body from client_side.
++ */
++static void
++icapReqModSendBodyChunk(int fd, char *bufnotused, size_t size, int errflag,
++    void *data)
++{
++    IcapStateData *icap = data;
++    debug(81, 3) ("icapReqModSendBodyChunk: FD %d wrote %d errflag %d.\n",
++	fd, (int) size, errflag);
++    if (errflag == COMM_ERR_CLOSING)
++	return;
++    if (errflag) {
++	icapEntryError(icap, ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR,
++	    errno);
++	comm_close(fd);
++	return;
++    }
++    clientReadBody(icap->request,
++	memAllocate(MEM_8K_BUF), 8192, icapReqModBodyHandler, icap);
++}
++
++/*
++ * icapReqModBodyHandler
++ *
++ * Called after Squid gets a chunk of the request entity from the
++ * client side.  The body is chunkified and passed to comm_write.
++ * The comm_write callback depends on whether or not this is the
++ * last chunk.
++ */
++static void
++icapReqModBodyHandler(char *buf, ssize_t size, void *data)
++{
++    IcapStateData *icap = data;
++    MemBuf mb;
++    CWCB *theCallback = icapReqModSendBodyChunk;
++    if (size < 0) {
++	debug(81, 1) ("icapReqModBodyHandler: %s\n", xstrerror());
++	memFree8K(buf);
++	return;
++    }
++    memBufDefInit(&mb);
++    debug(81, 3) ("icapReqModBodyHandler: writing chunk size %d\n", size);
++    memBufPrintf(&mb, "%x\r\n", size);
++    if (size)
++	memBufAppend(&mb, buf, size);
++    else
++	theCallback = icapSendReqModDone;
++    memBufAppend(&mb, crlf, 2);
++    memFree8K(buf);
++    comm_write_mbuf(icap->icap_fd, mb, theCallback, icap);
++}
++
++/*
++ * icapReqModReadHttpBody
++ *
++ * The read handler for the client's HTTP connection when reading
++ * message bodies.  Called by comm_select().
++ */
++static void
++icapReqModReadHttpBody(int fd, void *data)
++{
++    IcapStateData *icap = data;
++    int len;
++    debug(81, 3) ("icapReqModReadHttpBody: FD %d called\n", fd);
++    len = memBufRead(fd, &icap->chunk_buf);
++    debug(81, 3) ("icapReqModReadHttpBody: read returns %d\n", len);
++    if (len < 0) {
++	debug(81, 3) ("icapReqModReadHttpBody: FD %d %s\n", fd, xstrerror());
++	if (!ignoreErrno(errno))
++	    icap->flags.reqmod_http_entity_eof = 1;
++    } else if (0 == len) {
++	debug(81, 3) ("icapReqModReadHttpBody: FD %d EOF\n", fd);
++	icap->flags.reqmod_http_entity_eof = 1;
++    } else {
++	fd_bytes(fd, len, FD_READ);
++	kb_incr(&statCounter.icap.all.kbytes_in, len);
++	icap->reqmod.http_entity.bytes_read +=
++	    icapParseChunkedBody(icap,
++	    icapReqModMemBufAppend, &icap->reqmod.http_entity.buf);
++    }
++    if (icap->chunk_size < 0)
++	icap->flags.reqmod_http_entity_eof = 1;
++
++    if (!icap->flags.reqmod_http_entity_eof)
++	commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpBody, icap, 0);
++    /*
++     * Notify the other side if it is waiting for data from us
++     */
++    debug(81, 3) ("%s:%d http_entity.callback=%p\n", __FILE__, __LINE__,
++	icap->reqmod.http_entity.callback);
++    debug(81, 3) ("%s:%d http_entity.buf.size=%d\n", __FILE__, __LINE__,
++	icap->reqmod.http_entity.buf.size);
++    if (icap->reqmod.http_entity.callback) {
++	icapReqModPassHttpBody(icap,
++	    icap->reqmod.http_entity.callback_buf,
++	    icap->reqmod.http_entity.callback_bufsize,
++	    icap->reqmod.http_entity.callback,
++	    icap->reqmod.http_entity.callback_data);
++	icap->reqmod.http_entity.callback = NULL;
++	cbdataUnlock(icap->reqmod.http_entity.callback_data);
++    }
++}
++
++/*
++ * icapReqModPassHttpBody
++ *
++ * Called from http.c after request headers have been sent.
++ * This function feeds the http.c module chunks of the request
++ * body that were stored in the http_entity.buf MemBuf.
++ */
++static void
++icapReqModPassHttpBody(IcapStateData * icap, char *buf, size_t size,
++    CBCB * callback, void *cbdata)
++{
++    debug(81, 3) ("icapReqModPassHttpBody: called\n");
++    if (!buf) {
++	debug(81, 1) ("icapReqModPassHttpBody: FD %d called with %p, %d, %p (request aborted)\n",
++	    icap->icap_fd, buf, (int) size, cbdata);
++	comm_close(icap->icap_fd);
++	return;
++    }
++    if (!cbdataValid(cbdata)) {
++	debug(81,
++	    1)
++	    ("icapReqModPassHttpBody: FD %d callback data invalid, closing\n",
++	    icap->icap_fd);
++	comm_close(icap->icap_fd);	/*It is better to be sure that the connection will be  closed..... */
++	/*icapReqModKeepAliveOrClose(icap); */
++	return;
++    }
++    debug(81, 3) ("icapReqModPassHttpBody: entity buf size = %d\n",
++	icap->reqmod.http_entity.buf.size);
++    if (icap->reqmod.http_entity.buf.size) {
++	int copy_sz = icap->reqmod.http_entity.buf.size;
++	if (copy_sz > size)
++	    copy_sz = size;
++	xmemcpy(buf, icap->reqmod.http_entity.buf.buf, copy_sz);
++	/* XXX don't let Alex see this ugliness */
++	xmemmove(icap->reqmod.http_entity.buf.buf,
++	    icap->reqmod.http_entity.buf.buf + copy_sz,
++	    icap->reqmod.http_entity.buf.size - copy_sz);
++	icap->reqmod.http_entity.buf.size -= copy_sz;
++	debug(81, 3) ("icapReqModPassHttpBody: giving %d bytes to other side\n",
++	    copy_sz);
++	callback(buf, copy_sz, cbdata);
++	debug(81, 3) ("icapReqModPassHttpBody: entity buf size now = %d\n",
++	    icap->reqmod.http_entity.buf.size);
++	return;
++    }
++    if (icap->flags.reqmod_http_entity_eof) {
++	debug(81, 3) ("icapReqModPassHttpBody: signalling EOF\n");
++	callback(buf, 0, cbdata);
++	icapReqModKeepAliveOrClose(icap);
++	return;
++    }
++    /*
++     * We have no data for the other side at this point.  Save all
++     * these values and use them when we do have data.
++     */
++    assert(NULL == icap->reqmod.http_entity.callback);
++    icap->reqmod.http_entity.callback = callback;
++    icap->reqmod.http_entity.callback_data = cbdata;
++    icap->reqmod.http_entity.callback_buf = buf;
++    icap->reqmod.http_entity.callback_bufsize = size;
++    cbdataLock(icap->reqmod.http_entity.callback_data);
++}
++
++/*
++ * Body reader handler for use with request->body_reader function
++ * Simple a wrapper for icapReqModPassHttpBody function
++ */
++
++static void
++icapReqModBodyReader(request_t * request, char *buf, size_t size,
++    CBCB * callback, void *cbdata)
++{
++    IcapStateData *icap = request->body_reader_data;
++    icapReqModPassHttpBody(icap, buf, size, callback, cbdata);
++}
++
++/*
++ * icapReqModMemBufAppend
++ *
++ * stupid wrapper to eliminate compiler warnings
++ */
++static void
++icapReqModMemBufAppend(void *data, const char *buf, ssize_t size)
++{
++    memBufAppend(data, buf, size);
++}
+Index: src/icap_respmod.c
+===================================================================
+RCS file: src/icap_respmod.c
+diff -N src/icap_respmod.c
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ src/icap_respmod.c	31 Jan 2007 18:11:15 -0000	1.1.14.8
+@@ -0,0 +1,1018 @@
++
++/*
++ * $Id$
++ *
++ * DEBUG: section 81    Internet Content Adaptation Protocol (ICAP) Client
++ * AUTHOR: Geetha Manjunath, Hewlett Packard Company
++ *
++ * SQUID Web Proxy Cache          http://www.squid-cache.org/
++ * ----------------------------------------------------------
++ *
++ *  Squid is the result of efforts by numerous individuals from
++ *  the Internet community; see the CONTRIBUTORS file for full
++ *  details.   Many organizations have provided support for Squid's
++ *  development; see the SPONSORS file for full details.  Squid is
++ *  Copyrighted (C) 2001 by the Regents of the University of
++ *  California; see the COPYRIGHT file for full details.  Squid
++ *  incorporates software developed and/or copyrighted by other
++ *  sources; see the CREDITS file for full details.
++ *
++ *  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, USA.
++ *
++ */
++
++#include "squid.h"
++
++static CWCB icapSendRespModDone;
++static PF icapRespModGobble;
++extern PF icapReadReply;
++static PF icapRespModReadReply;
++static void icapRespModKeepAliveOrClose(IcapStateData * icap);
++static int icapReadReply2(IcapStateData * icap);
++static void icapReadReply3(IcapStateData * icap);
++
++#define EXPECTED_ICAP_HEADER_LEN 256
++const char *crlf = "\r\n";
++
++static void
++getICAPRespModString(MemBuf * mb, int o1, int o2, int o3,
++    const char *client_addr, IcapStateData * icap, const icap_service * service)
++{
++    memBufPrintf(mb, "RESPMOD %s ICAP/1.0\r\nEncapsulated:", service->uri);
++    if (o1 >= 0)
++	memBufPrintf(mb, " req-hdr=%1d", o1);
++    if (o2 >= 0)
++	memBufPrintf(mb, ", res-hdr=%1d", o2);
++    if (o3 >= 0)
++	memBufPrintf(mb, ", res-body=%1d", o3);
++    else
++	memBufPrintf(mb, ", null-body=%1d", -o3);
++    memBufPrintf(mb, crlf);
++
++    if (service->flags.need_x_client_ip && Config.icapcfg.send_client_ip) {
++	memBufPrintf(mb, "X-Client-IP: %s\r\n", client_addr);
++    }
++    if (service->flags.need_x_server_ip && Config.icapcfg.send_server_ip)
++	icapAddOriginIP(mb, icap->request->host);
++
++    if ((service->flags.need_x_authenticated_user
++	    && Config.icapcfg.send_auth_user)
++	&& (icap->request->auth_user_request != NULL)) {
++	icapAddAuthUserHeader(mb, icap->request->auth_user_request);
++    }
++#if NOT_YET_FINISHED
++    if (Config.icapcfg.trailers) {
++	memBufPrintf(mb, "X-TE: trailers\r\n");
++    }
++#endif
++}
++
++static int
++buildRespModHeader(MemBuf * mb, IcapStateData * icap)
++{
++    MemBuf mb_hdr;
++    char *client_addr;
++    int o2 = 0;
++    int o3 = 0;
++    int hlen;
++    int consumed;
++    icap_service *service;
++    HttpReply *r;
++
++    if (icap->respmod.req_hdr_copy.size > 4 && strncmp(icap->respmod.req_hdr_copy.buf, "HTTP/", 5)) {
++	debug(81, 3) ("buildRespModHeader: Non-HTTP-compliant header: '%s'\n", icap->respmod.req_hdr_copy.buf);
++	/*
++	 *Possible we can consider that we did not have http responce headers 
++	 *(maybe HTTP 0.9 protocol), lets returning -1...
++	 */
++	consumed = -1;
++	o2 = -1;
++	memBufDefInit(&mb_hdr);
++	httpBuildRequestPrefix(icap->request, icap->request,
++	    icap->respmod.entry, &mb_hdr, icap->http_flags);
++	o3 = mb_hdr.size;
++    } else {
++
++	hlen = headersEnd(icap->respmod.req_hdr_copy.buf,
++	    icap->respmod.req_hdr_copy.size);
++	debug(81, 3) ("buildRespModHeader: headersEnd = %d(%s)\n", hlen, icap->respmod.req_hdr_copy.buf);
++	if (0 == hlen)
++	    return 0;
++
++	consumed = hlen;
++	debug(81, 3) ("buildRespModHeader: consumed = %d (from %d)\n", consumed, icap->respmod.req_hdr_copy.size);
++
++
++	/*
++	 * now, truncate our req_hdr_copy at the header end.
++	 * this 'if' statement might be unncessary?
++	 */
++	if (hlen < icap->respmod.req_hdr_copy.size)
++	    icap->respmod.req_hdr_copy.size = hlen;
++
++	/* Copy request header */
++	memBufDefInit(&mb_hdr);
++	httpBuildRequestPrefix(icap->request, icap->request,
++	    icap->respmod.entry, &mb_hdr, icap->http_flags);
++	o2 = mb_hdr.size;
++
++	/* Copy response header - Append to request header mbuffer */
++	memBufAppend(&mb_hdr,
++	    icap->respmod.req_hdr_copy.buf, icap->respmod.req_hdr_copy.size);
++	o3 = mb_hdr.size;
++    }
++
++    service = icap->current_service;
++    assert(service);
++    client_addr = inet_ntoa(icap->request->client_addr);
++
++    r = httpReplyCreate();
++    httpReplyParse(r, icap->respmod.req_hdr_copy.buf,
++	icap->respmod.req_hdr_copy.size);
++    icap->respmod.res_body_sz = httpReplyBodySize(icap->request->method, r);
++    httpReplyDestroy(r);
++    if (icap->respmod.res_body_sz)
++	getICAPRespModString(mb, 0, o2, o3, client_addr, icap, service);
++    else
++	getICAPRespModString(mb, 0, o2, -o3, client_addr, icap, service);
++    if (Config.icapcfg.preview_enable)
++	if (icap->preview_size >= 0) {
++	    memBufPrintf(mb, "Preview: %d\r\n", icap->preview_size);
++	    icap->flags.preview_done = 0;
++	}
++    if (service->keep_alive) {
++	icap->flags.keep_alive = 1;
++	memBufAppend(mb, "Connection: keep-alive\r\n", 24);
++    } else {
++	icap->flags.keep_alive = 0;
++	memBufAppend(mb, "Connection: close\r\n", 19);
++    }
++    memBufAppend(mb, crlf, 2);
++    memBufAppend(mb, mb_hdr.buf, mb_hdr.size);
++    memBufClean(&mb_hdr);
++    return consumed;
++}
++
++void
++icapRespModAddResponceHeaders(IcapStateData * icap, char *buf, int len)
++{
++    if (memBufIsNull(&icap->respmod.req_hdr_copy))
++	memBufDefInit(&icap->respmod.req_hdr_copy);
++    memBufAppend(&icap->respmod.req_hdr_copy, buf, len);
++    if (len && icap->flags.copy_response) {
++	if (memBufIsNull(&icap->respmod.resp_copy))
++	    memBufDefInit(&icap->respmod.resp_copy);
++	memBufAppend(&icap->respmod.resp_copy, buf, len);
++    }
++}
++
++void
++icapRespModAddBodyData(IcapStateData * icap, char *buf, int len)
++{
++    if (icap->flags.no_content) {
++	/*
++	 * ICAP server said there are no modifications to make, so
++	 * just append this data to the StoreEntry
++	 */
++	if (icap->respmod.resp_copy.size) {
++	    /*
++	     * first copy the data that we already sent to the ICAP server
++	     */
++	    memBufAppend(&icap->chunk_buf,
++		icap->respmod.resp_copy.buf, icap->respmod.resp_copy.size);
++	    icap->respmod.resp_copy.size = 0;
++	}
++	if (len) {
++	    /*
++	     * also copy any new data from the HTTP side
++	     */
++	    memBufAppend(&icap->chunk_buf, buf, len);
++	}
++	(void) icapReadReply2(icap);
++	return;
++    }
++#if SUPPORT_ICAP_204 || ICAP_PREVIEW
++    /*
++     * make a copy of the response in case ICAP server gives us a 204
++     */
++    /*
++     * This piece of code is problematic for 204 responces outside preview.
++     * The icap->respmod.resp_copy continues to filled until we had responce
++     * If the icap server waits to gets all data before sends its responce 
++     * then we are puting all downloading object to the main system memory.
++     * My opinion is that 204 responces outside preview must be disabled .....
++     * /chtsanti
++     */
++
++    if (len && icap->flags.copy_response) {
++	if (memBufIsNull(&icap->respmod.resp_copy))
++	    memBufDefInit(&icap->respmod.resp_copy);
++	memBufAppend(&icap->respmod.resp_copy, buf, len);
++    }
++#endif
++
++    if (buf && len > 0)
++	memBufAppend(&icap->respmod.buffer, buf, len);
++}
++
++
++void
++icapSendRespMod(IcapStateData * icap, int theEnd)
++{
++    MemBuf mb;
++#if ICAP_PREVIEW
++    int size;
++    const int preview_size = icap->preview_size;
++#endif
++    if (icap->flags.no_content) {
++	return;
++    }
++    debug(81, 5) ("icapSendRespMod: FD %d, theEnd %d\n",
++	icap->icap_fd, theEnd);
++
++    /*
++     * httpReadReply is going to call us with a chunk and then
++     * right away again with an EOF if httpPconnTransferDone() is true.
++     * Since the first write is already dispatched, we'll have to 
++     * hack this in somehow.
++     */
++    if (icap->flags.write_pending) {
++	debug(81, 3) ("icapSendRespMod: oops, write_pending=1\n");
++	assert(theEnd);
++	return;
++    }
++    if (!cbdataValid(icap)) {
++	debug(81, 3) ("icapSendRespMod: failed to establish connection?\n");
++	return;
++    }
++    memBufDefInit(&mb);
++
++    if (icap->sc == 0) {
++	// http connection has been closed without sending us anything
++	if (icap->respmod.req_hdr_copy.size == 0 && theEnd == 1) {
++	    ErrorState *err;
++	    err = errorCon(ERR_INVALID_RESP, HTTP_BAD_GATEWAY, icap->request);
++	    errorAppendEntry(icap->respmod.entry, err);
++	    comm_close(icap->icap_fd);
++	    return;
++	}
++	/* No data sent yet. Start with headers */
++	icap->sc = buildRespModHeader(&mb, icap);
++	assert(icap->sc != 0);
++    }
++    if (theEnd) {
++	if (icap->respmod.res_body_sz)
++	    icap->flags.send_zero_chunk = 1;
++	icap->flags.http_server_eof = 1;
++    }
++#if ICAP_PREVIEW
++    if (preview_size < 0 || !Config.icapcfg.preview_enable)	/* preview feature off */
++	icap->flags.preview_done = 1;
++
++    if (!icap->flags.preview_done) {
++	/* preview not yet sent */
++	if (icap->respmod.buffer.size > preview_size || theEnd) {
++	    /* we got enough bytes for preview or this is the last call */
++	    /* add preview preview now */
++	    if (icap->respmod.buffer.size > 0) {
++		size = icap->respmod.buffer.size;
++		if (size > preview_size)
++		    size = preview_size;
++		memBufPrintf(&mb, "%x\r\n", size);
++		memBufAppend(&mb, icap->respmod.buffer.buf, size);
++		memBufAppend(&mb, crlf, 2);
++		icap->sc += size;
++	    }
++	    if (icap->respmod.buffer.size <= preview_size) {
++		/* content length is less than preview size+1 */
++		if (icap->respmod.res_body_sz)
++		    memBufAppend(&mb, "0; ieof\r\n\r\n", 11);
++		memBufReset(&icap->respmod.buffer);	/* will now be used for other data */
++	    } else {
++		char ch;
++		memBufAppend(&mb, "0\r\n\r\n", 5);
++		/* end of preview, wait for continue or 204 signal */
++		/* copy the extra byte and all other data to the icap buffer */
++		/* so that it can be handled next time */
++		ch = icap->respmod.buffer.buf[preview_size];
++		xmemmove(icap->respmod.buffer.buf,
++		    icap->respmod.buffer.buf + preview_size,
++		    icap->respmod.buffer.size - preview_size);
++		icap->respmod.buffer.size = icap->respmod.buffer.size - preview_size;
++		icap->respmod.buffer.buf[icap->respmod.buffer.size] = '\0';
++		debug(81,
++		    3)
++		    ("icapSendRespMod: FD %d: sending preview and keeping %d bytes in internal buf.\n",
++		    icap->icap_fd, icap->respmod.buffer.size);
++	    }
++	    icap->flags.preview_done = 1;
++	    icap->flags.wait_for_preview_reply = 1;
++	}
++    } else if (icap->flags.wait_for_preview_reply) {
++	memBufClean(&mb);
++	return;
++    } else
++#endif
++    {
++	/* after preview completed and ICAP preview response received */
++	/* there may still be some data in the buffer */
++	if (icap->respmod.buffer.size > 0) {
++	    memBufPrintf(&mb, "%x\r\n", icap->respmod.buffer.size);
++	    memBufAppend(&mb, icap->respmod.buffer.buf,
++		icap->respmod.buffer.size);
++	    memBufAppend(&mb, crlf, 2);
++	    icap->sc += icap->respmod.buffer.size;
++	    memBufReset(&icap->respmod.buffer);
++	}
++	if (icap->flags.send_zero_chunk) {
++	    /* send zero end chunk */
++	    icap->flags.send_zero_chunk = 0;
++	    icap->flags.http_server_eof = 1;
++	    memBufAppend(&mb, "0\r\n\r\n", 5);
++	}
++	/* wait for data coming from ICAP server as soon as we sent something */
++	/* but of course only until we got the response header */
++	if (!icap->flags.got_reply)
++	    icap->flags.wait_for_reply = 1;
++    }
++    commSetTimeout(icap->icap_fd, -1, NULL, NULL);
++
++    if (!mb.size) {
++	memBufClean(&mb);
++	return;
++    }
++    debug(81, 5) ("icapSendRespMod: FD %d writing {%s}\n", icap->icap_fd,
++	mb.buf);
++    icap->flags.write_pending = 1;
++    comm_write_mbuf(icap->icap_fd, mb, icapSendRespModDone, icap);
++}
++
++static void
++icapRespModReadReply(int fd, void *data)
++{
++    IcapStateData *icap = data;
++    int version_major, version_minor;
++    const char *str_status;
++    int x;
++    int status = 0;
++    int isIcap = 0;
++    int directResponse = 0;
++    ErrorState *err;
++    const char *start;
++    const char *end;
++
++    debug(81, 5) ("icapRespModReadReply: FD %d data = %p\n", fd, data);
++    statCounter.syscalls.sock.reads++;
++
++    x = icapReadHeader(fd, icap, &isIcap);
++    if (x < 0) {
++	/* Did not find a proper ICAP response */
++	debug(81, 3) ("ICAP : Error path!\n");
++	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, icap->request);
++	err->xerrno = errno;
++	errorAppendEntry(icap->respmod.entry, err);
++	comm_close(fd);
++	return;
++    }
++    if (x == 0) {
++	/*
++	 * Waiting for more headers.  Schedule new read hander, but
++	 * don't reset timeout.
++	 */
++	commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0);
++	return;
++    }
++    /*
++     * Parse the ICAP header
++     */
++    assert(icap->icap_hdr.size);
++    debug(81, 3) ("Parse icap header : <%s>\n", icap->icap_hdr.buf);
++    if ((status =
++	    icapParseStatusLine(icap->icap_hdr.buf, icap->icap_hdr.size,
++		&version_major, &version_minor, &str_status)) < 0) {
++	debug(81, 1) ("BAD ICAP status line <%s>\n", icap->icap_hdr.buf);
++	/* is this correct in case of ICAP protocol error? */
++	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, icap->request);
++	err->xerrno = errno;
++	errorAppendEntry(icap->respmod.entry, err);
++	comm_close(fd);
++	return;
++    };
++    /*  OK here we have responce. Lets stop filling the 
++     *  icap->respmod.resp_copy buffer ....
++     */
++    icap->flags.copy_response = 0;
++
++    icapSetKeepAlive(icap, icap->icap_hdr.buf);
++#if ICAP_PREVIEW
++    if (icap->flags.wait_for_preview_reply) {
++	if (100 == status) {
++	    debug(81, 5) ("icapRespModReadReply: 100 Continue received\n");
++	    icap->flags.wait_for_preview_reply = 0;
++	    /* if http_server_eof
++	     * call again icapSendRespMod to handle data that
++	     * was received while waiting for this ICAP response
++	     * else let http to call icapSendRespMod when new data arrived
++	     */
++	    if (icap->flags.http_server_eof)
++		icapSendRespMod(icap, 0);
++	    /*
++	     * reset the header to send the rest of the preview
++	     */
++	    if (!memBufIsNull(&icap->icap_hdr))
++		memBufReset(&icap->icap_hdr);
++
++	    /*We do n't need it any more ....... */
++	    if (!memBufIsNull(&icap->respmod.resp_copy))
++		memBufClean(&icap->respmod.resp_copy);
++
++	    return;
++	}
++	if (204 == status) {
++	    debug(81,
++		5) ("icapRespModReadReply: 204 No modification received\n");
++	    icap->flags.wait_for_preview_reply = 0;
++	}
++    }
++#endif /*ICAP_PREVIEW */
++
++#if SUPPORT_ICAP_204 || ICAP_PREVIEW
++    if (204 == status) {
++	debug(81, 3) ("got 204 status from ICAP server\n");
++	icapRespModKeepAliveOrClose(icap);
++
++	debug(81, 3) ("setting icap->flags.no_content\n");
++	icap->flags.no_content = 1;
++	/*
++	 * copy the response already written to the ICAP server
++	 */
++	debug(81, 3) ("copying %d bytes from resp_copy to chunk_buf\n",
++	    icap->respmod.resp_copy.size);
++	memBufAppend(&icap->chunk_buf,
++	    icap->respmod.resp_copy.buf, icap->respmod.resp_copy.size);
++	icap->respmod.resp_copy.size = 0;
++	if (icapReadReply2(icap) < 0)
++	    icapStateFree(-1, icap);
++
++	/*
++	 * XXX ideally want to clean icap->respmod.resp_copy here
++	 * XXX ideally want to "close" ICAP server connection here
++	 * OK do it....
++	 */
++	if (!memBufIsNull(&icap->respmod.resp_copy))
++	    memBufClean(&icap->respmod.resp_copy);
++	return;
++    }
++#endif
++    if (200 != status && 201 != status) {
++	debug(81, 1) ("Unsupported status '%d' from ICAP server\n", status);
++	/* Did not find a proper ICAP response */
++	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, icap->request);
++	err->xerrno = errno;
++	errorAppendEntry(icap->respmod.entry, err);
++	comm_close(fd);
++	return;
++    }
++    if (icapFindHeader(icap->icap_hdr.buf, "Encapsulated:", &start, &end)) {
++	icapParseEncapsulated(icap, start, end);
++    } else {
++	debug(81,
++	    1)
++	    ("WARNING: icapRespModReadReply() did not find 'Encapsulated' header\n");
++    }
++    if (icap->enc.res_hdr > -1)
++	directResponse = 1;
++    else if (icap->enc.res_body > -1)
++	directResponse = 1;
++    else
++	directResponse = 0;
++
++    /*
++     * "directResponse" is the normal case here.  If we don't have
++     * a response header or body, it is an error.
++     */
++    if (!directResponse) {
++	/* Did not find a proper ICAP response */
++	debug(81, 3) ("ICAP : Error path!\n");
++	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, icap->request);
++	err->xerrno = errno;
++	errorAppendEntry(icap->respmod.entry, err);
++	comm_close(fd);
++	return;
++    }
++    /* got the reply, no need to come here again */
++    icap->flags.wait_for_reply = 0;
++    icap->flags.got_reply = 1;
++    /* Next, gobble any data before the HTTP response starts */
++    if (icap->enc.res_hdr > -1)
++	icap->bytes_to_gobble = icap->enc.res_hdr;
++    commSetSelect(fd, COMM_SELECT_READ, icapRespModGobble, icap, 0);
++}
++
++
++/*
++ * Gobble up (read) some bytes until we get to the start of the body
++ */
++static void
++icapRespModGobble(int fd, void *data)
++{
++    IcapStateData *icap = data;
++    int len;
++    LOCAL_ARRAY(char, junk, SQUID_TCP_SO_RCVBUF);
++    debug(81, 3) ("icapRespModGobble: FD %d gobbling %d bytes\n", fd,
++	icap->bytes_to_gobble);
++    len = FD_READ_METHOD(fd, junk, icap->bytes_to_gobble);
++    debug(81, 3) ("icapRespModGobble: gobbled %d bytes\n", len);
++    if (len < 0) {
++	/* XXX error */
++	abort();
++    }
++    icap->bytes_to_gobble -= len;
++    if (icap->bytes_to_gobble)
++	commSetSelect(fd, COMM_SELECT_READ, icapRespModGobble, icap, 0);
++    else
++	icapReadReply(fd, icap);
++}
++
++
++static void
++icapSendRespModDone(int fd, char *bufnotused, size_t size, int errflag,
++    void *data)
++{
++    IcapStateData *icap = data;
++    ErrorState *err;
++
++    icap->flags.write_pending = 0;
++    debug(81, 5) ("icapSendRespModDone: FD %d: size %d: errflag %d.\n",
++	fd, size, errflag);
++    if (size > 0) {
++	fd_bytes(fd, size, FD_WRITE);
++	kb_incr(&statCounter.icap.all.kbytes_out, size);
++    }
++    if (errflag == COMM_ERR_CLOSING)
++	return;
++    if (errflag) {
++	if (cbdataValid(icap))
++	    err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, icap->request);
++	else
++	    err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, NULL);
++	err->xerrno = errno;
++	storeEntryReset(icap->respmod.entry);
++	errorAppendEntry(icap->respmod.entry, err);
++	comm_close(fd);
++	return;
++    }
++    if (EBIT_TEST(icap->respmod.entry->flags, ENTRY_ABORTED)) {
++	debug(81, 3) ("icapSendRespModDone: Entry Aborded\n");
++	comm_close(fd);
++	return;
++    }
++    if (icap->flags.send_zero_chunk) {
++	debug(81,
++	    3) ("icapSendRespModDone: I'm supposed to send zero chunk now\n");
++	icap->flags.send_zero_chunk = 0;
++	icapSendRespMod(icap, 1);
++	return;
++    }
++    if (icap->flags.wait_for_preview_reply || icap->flags.wait_for_reply) {
++	/* Schedule reading the ICAP response */
++	debug(81,
++	    3)
++	    ("icapSendRespModDone: FD %d: commSetSelect on read icapRespModReadReply.\n",
++	    fd);
++	commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0);
++#if 1
++	commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
++	commSetDefer(fd, fwdCheckDeferRead, icap->respmod.entry);
++#else
++	if (icap->flags.wait_for_preview_reply || icap->flags.http_server_eof) {
++	    /*
++	     * Set the read timeout only after all data has been sent
++	     * or we are waiting for a preview response
++	     * If the ICAP server does not return any data till all data
++	     * has been sent, we are likely to hit the timeout for large
++	     * HTTP bodies
++	     */
++	    commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
++	}
++#endif
++    }
++}
++
++void
++icapConnectOver(int fd, int status, void *data)
++{
++    ErrorState *err;
++    IcapStateData *icap = data;
++    debug(81, 3) ("icapConnectOver: FD %d, status=%d\n", fd, status);
++    icap->flags.connect_pending = 0;
++    if (status < 0) {
++	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, icap->request);
++	err->xerrno = errno;
++	errorAppendEntry(icap->respmod.entry, err);
++	comm_close(fd);
++	debug(81, 3) ("icapConnectOver: status < 0, unreachable=1\n");
++	icapOptSetUnreachable(icap->current_service);
++	return;
++    }
++    fd_table[fd].pconn.uses++;
++    fd_table[fd].pconn.type = 2;
++    commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0);
++}
++
++
++
++IcapStateData *
++icapRespModStart(icap_service_t type, request_t * request, StoreEntry * entry,
++    http_state_flags http_flags)
++{
++    IcapStateData *icap = NULL;
++    CNCB *theCallback = NULL;
++    icap_service *service = NULL;
++
++    debug(81, 3) ("icapRespModStart: type=%d\n", (int) type);
++    assert(type >= 0 && type < ICAP_SERVICE_MAX);
++
++    service = icapService(type, request);
++    if (!service) {
++	debug(81, 3) ("icapRespModStart: no service found\n");
++	return NULL;		/* no service found */
++    }
++    if (service->unreachable) {
++	if (service->bypass) {
++	    debug(81,
++		5)
++		("icapRespModStart: BYPASS because service unreachable: %s\n",
++		service->uri);
++	    return NULL;
++	} else {
++	    debug(81,
++		5)
++		("icapRespModStart: ERROR  because service unreachable: %s\n",
++		service->uri);
++	    return (IcapStateData *) - 1;
++	}
++    }
++    switch (type) {
++	/* TODO: When we support more than ICAP_SERVICE_RESPMOD_PRECACHE, we needs to change
++	 * this switch, because callbacks isn't keep */
++    case ICAP_SERVICE_RESPMOD_PRECACHE:
++	theCallback = icapConnectOver;
++	break;
++    default:
++	fatalf("icapRespModStart: unsupported service type '%s'\n",
++	    icap_service_type_str[type]);
++	break;
++    }
++
++    icap = icapAllocate();
++    if (!icap) {
++	debug(81, 3) ("icapRespModStart: icapAllocate() failed\n");
++	return NULL;
++    }
++    icap->request = requestLink(request);
++    icap->respmod.entry = entry;
++    if (entry)
++	storeLockObject(entry);
++    icap->http_flags = http_flags;
++    memBufDefInit(&icap->respmod.buffer);
++    memBufDefInit(&icap->chunk_buf);
++
++    icap->current_service = service;
++    icap->preview_size = service->preview;
++
++    /* 
++     * Don't create socket to the icap server now, but only for the first
++     * packet receive from the http server. This will resolve all timeout
++     * between the web server and icap server.
++     */
++    debug(81, 3) ("icapRespModStart: setting connect_requested to 0\n");
++    icap->flags.connect_requested = 0;
++
++    /*
++     * make a copy the HTTP response that we send to the ICAP server in
++     * case it turns out to be a 204
++     */
++#ifdef SUPPORT_ICAP_204
++    icap->flags.copy_response = 1;
++#elif ICAP_PREVIEW
++    if (preview_size < 0 || !Config.icapcfg.preview_enable)
++	icap->flags.copy_response = 0;
++    else
++	icap->flags.copy_response = 1;
++#else
++    icap->flags.copy_response = 0;
++#endif
++
++    statCounter.icap.all.requests++;
++    debug(81, 3) ("icapRespModStart: returning %p\n", icap);
++    return icap;
++}
++
++static int
++icapHttpReplyHdrState(IcapStateData * icap)
++{
++    assert(icap);
++    if (NULL == icap->httpState)
++	return 0;
++    return icap->httpState->reply_hdr_state;
++}
++
++static size_t
++icapProcessHttpReplyHeader(IcapStateData * icap, const char *buf, int size)
++{
++    size_t done;
++    if (NULL == icap->httpState) {
++	icap->httpState = cbdataAlloc(HttpStateData);
++	icap->httpState->request = requestLink(icap->request);
++	icap->httpState->orig_request = requestLink(icap->request);
++	icap->httpState->entry = icap->respmod.entry;
++	storeLockObject(icap->httpState->entry);	/* lock it */
++    }
++    done = httpProcessReplyHeader(icap->httpState, buf, size);
++    if (2 == icap->httpState->reply_hdr_state)
++	EBIT_CLR(icap->httpState->entry->flags, ENTRY_FWD_HDR_WAIT);
++    return done;
++}
++
++/*
++ * icapRespModKeepAliveOrClose
++ *
++ * Called when we are done reading from the ICAP server.
++ * Either close the connection or keep it open for a future
++ * transaction.
++ */
++static void
++icapRespModKeepAliveOrClose(IcapStateData * icap)
++{
++    int fd = icap->icap_fd;
++    if (fd < 0)
++	return;
++    debug(81, 3) ("%s:%d FD %d looks good, keeping alive\n", __FILE__, __LINE__,
++	fd);
++    commSetDefer(fd, NULL, NULL);
++    commSetTimeout(fd, -1, NULL, NULL);
++    commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
++    comm_remove_close_handler(fd, icapStateFree, icap);
++    icap->icap_fd = -1;
++    if (!icap->flags.keep_alive) {
++	debug(81, 3) ("%s:%d keep_alive not set, closing\n", __FILE__,
++	    __LINE__);
++	comm_close(fd);
++	return;
++    } else {
++	pconnPush(fd, icap->current_service->hostname, icap->current_service->port, NULL, NULL, 0);
++    }
++}
++
++
++
++/*
++ * copied from httpPconnTransferDone
++ *
++ */
++static int
++icapPconnTransferDone(int fd, IcapStateData * icap)
++{
++    debug(81, 3) ("icapPconnTransferDone: FD %d\n", fd);
++    /*
++     * Be careful with 204 responses.  Normally we are done when we
++     * see the zero-end chunk, but that won't happen for 204s, so we
++     * use an EOF indicator on the HTTP side instead.
++     */
++    if (icap->flags.no_content && icap->flags.http_server_eof) {
++	debug(81, 5) ("icapPconnTransferDone: no content, ret 1\n");
++	return 1;
++    }
++    if (icapHttpReplyHdrState(icap) != 2) {
++	debug(81,
++	    5) ("icapPconnTransferDone: didn't see end of HTTP hdrs, ret 0\n");
++	return 0;
++    }
++    if (icap->enc.null_body > -1) {
++	debug(81, 5) ("icapPconnTransferDone: no message body, ret 1\n");
++	return 1;
++    }
++    if (icap->chunk_size == -2) {	//AI: was != -2 ; and change content with bottom
++	/* zero end chunk reached */
++	debug(81, 5) ("icapPconnTransferDone: got zero end chunk\n");
++	return 1;
++    }
++    debug(81, 5) ("icapPconnTransferDone: didnt get zero end chunk yet\n");	//AI: change with second top condition
++
++    return 0;
++}
++
++static int
++icapExpectedHttpReplyHdrSize(IcapStateData * icap)
++{
++    if (icap->enc.res_body > -1 && icap->enc.res_hdr > -1)
++	return (icap->enc.res_body - icap->enc.res_hdr);
++    if (icap->enc.null_body > -1 && icap->enc.res_hdr > -1)
++	return icap->enc.null_body - icap->enc.res_hdr;
++    /*The case we did not get res_hdr ..... */
++    if (icap->enc.res_body > -1)
++	return icap->enc.res_body;
++    if (icap->enc.null_body > -1)
++	return icap->enc.null_body;
++    return -1;
++}
++
++/*
++ * copied from httpReadReply()
++ *
++ * by the time this is called, the ICAP headers have already
++ * been read.
++ */
++void
++icapReadReply(int fd, void *data)
++{
++    IcapStateData *icap = data;
++    StoreEntry *entry = icap->respmod.entry;
++    const request_t *request = icap->request;
++    int len;
++    debug(81, 5) ("icapReadReply: FD %d: icap %p.\n", fd, data);
++    if (icap->flags.no_content && !icap->flags.http_server_eof) {	//AI
++
++	return;
++    }
++    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
++	comm_close(fd);
++	return;
++    }
++    errno = 0;
++    statCounter.syscalls.sock.reads++;
++    len = memBufRead(fd, &icap->chunk_buf);
++    debug(81, 5) ("icapReadReply: FD %d: len %d.\n", fd, len);
++    if (len > 0) {
++	fd_bytes(fd, len, FD_READ);
++	kb_incr(&statCounter.icap.all.kbytes_in, len);
++	commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
++	if (icap->chunk_buf.size < icap->chunk_buf.capacity) {
++	    *(icap->chunk_buf.buf + icap->chunk_buf.size) = '\0';
++	    debug(81, 9) ("{%s}\n", icap->chunk_buf.buf);
++	}
++    }
++    if (len <= 0) {
++	debug(81, 2) ("icapReadReply: FD %d: read failure: %s.\n",
++	    fd, xstrerror());
++	if (ignoreErrno(errno)) {
++	    debug(81, 2) ("icapReadReply: FD %d: ignored errno\n", fd);
++	    commSetSelect(fd, COMM_SELECT_READ, icapReadReply, icap, 0);
++	} else if (entry->mem_obj->inmem_hi == 0) {
++	    ErrorState *err;
++	    debug(81, 2) ("icapReadReply: FD %d: generating error page\n", fd);
++	    err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, (request_t *) request);
++	    err->xerrno = errno;
++	    errorAppendEntry(entry, err);
++	    comm_close(fd);
++	} else {
++	    debug(81, 2) ("icapReadReply: FD %d: just calling comm_close()\n",
++		fd);
++	    comm_close(fd);
++	}
++	return;
++    }
++    if (icapReadReply2(icap) < 0)
++	comm_close(fd);
++}
++
++static int
++icapReadReply2(IcapStateData * icap)
++{
++    size_t done = 0;
++    StoreEntry *entry = icap->respmod.entry;
++    const request_t *request = icap->request;
++    debug(81, 3) ("icapReadReply2\n");
++    if (icap->chunk_buf.size == 0 && entry->mem_obj->inmem_hi == 0) {
++	ErrorState *err;
++	err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE, (request_t *) request);
++	err->xerrno = errno;
++	errorAppendEntry(entry, err);
++	icap->flags.http_server_eof = 1;
++	return -1;
++    }
++    if (icap->chunk_buf.size == 0) {
++	/* Retrieval done. */
++	if (icapHttpReplyHdrState(icap) < 2)
++	    icapProcessHttpReplyHeader(icap, icap->chunk_buf.buf,
++		icap->chunk_buf.size);
++	icap->flags.http_server_eof = 1;
++	icapReadReply3(icap);
++	return 0;
++    }
++    if (icapHttpReplyHdrState(icap) == 0) {
++	int expect = icapExpectedHttpReplyHdrSize(icap);
++	int so_far = icap->http_header_bytes_read_so_far;
++	int needed = expect - so_far;
++	debug(81, 3) ("expect=%d\n", expect);
++	debug(81, 3) ("so_far=%d\n", so_far);
++	debug(81, 3) ("needed=%d\n", needed);
++	assert(needed < 0 || needed >= 0);
++	if (0 > expect) {
++	    done = icapProcessHttpReplyHeader(icap,
++		icap->chunk_buf.buf, icap->chunk_buf.size);
++	} else if (0 == expect) {
++	    /*
++	     * this icap reply doesn't give us new HTTP headers
++	     * so we must copy them from our copy
++	     */
++	    debug(81, 1) ("WARNING: untested code at %s:%d\n", __FILE__,
++		__LINE__);
++	    if (icap->respmod.req_hdr_copy.size) {	/*For HTTP 0.9 we do not have headers */
++		storeAppend(entry,
++		    icap->respmod.req_hdr_copy.buf,
++		    icap->respmod.req_hdr_copy.size);
++	    }
++	    done = icapProcessHttpReplyHeader(icap, icap->chunk_buf.buf,
++		icap->chunk_buf.size);
++	    assert(icapHttpReplyHdrState(icap) == 2);
++	    icap->chunk_size = 0;	/*we are ready to read chunks of data now.... */
++	} else if (needed) {
++	    done = icapProcessHttpReplyHeader(icap,
++		icap->chunk_buf.buf, icap->chunk_buf.size);
++	    if (icap->chunk_buf.size >= needed) {
++		/*storeAppend not needed here, appended in httpProcessReplyHeader */
++		/*must done  = so_far - needed */
++		so_far += needed;
++		xmemmove(icap->chunk_buf.buf,
++		    icap->chunk_buf.buf + needed,
++		    icap->chunk_buf.size - needed);
++		icap->chunk_buf.size -= needed;
++		assert(icapHttpReplyHdrState(icap) == 2);
++		icap->chunk_size = 0;
++	    } else {
++		/*
++		 * We don't have the full HTTP reply headers yet, so keep
++		 * the partial reply buffered in 'chunk_buf' and wait
++		 * for more.
++		 */
++		debug(81, 3) ("We don't have full Http headers.Schedule a new read\n");
++		commSetSelect(icap->icap_fd, COMM_SELECT_READ, icapReadReply, icap, 0);
++	    }
++	}
++	icap->http_header_bytes_read_so_far = so_far;
++    }
++    debug(81, 3) ("%s:%d: icap->chunk_buf.size=%d\n", __FILE__, __LINE__,
++	(int) icap->chunk_buf.size);
++    debug(81, 3) ("%s:%d: flags.no_content=%d\n", __FILE__, __LINE__,
++	icap->flags.no_content);
++    if (icap->flags.no_content) {
++	/* data from http.c is not chunked */
++	if (!EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
++	    debug(81, 3) ("copying %d bytes from chunk_buf to entry\n",
++		icap->chunk_buf.size - done);
++	    if ((icap->chunk_buf.size - done) > 0)
++		storeAppend(entry, icap->chunk_buf.buf + done, icap->chunk_buf.size - done);
++	    icap->chunk_buf.size = 0;
++	}
++    } else if (2 == icapHttpReplyHdrState(icap)) {
++	if (icap->chunk_buf.size)
++	    icapParseChunkedBody(icap, (STRCB *) storeAppend, entry);
++    }
++    icapReadReply3(icap);
++    return 0;
++}
++
++static void
++icapReadReply3(IcapStateData * icap)
++{
++    StoreEntry *entry = icap->respmod.entry;
++    int fd = icap->icap_fd;
++    debug(81, 3) ("icapReadReply3\n");
++    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
++	debug(81, 3) ("icapReadReply3: Entry Aborded\n");
++	if (icap->flags.no_content)
++	    icapStateFree(-1, icap);
++	else
++	    comm_close(fd);
++    } else if (icapPconnTransferDone(fd, icap)) {
++	storeComplete(entry);
++	if (icap->flags.no_content)
++	    icapStateFree(-1, icap);
++	else {
++	    icapRespModKeepAliveOrClose(icap);
++	    icapStateFree(-1, icap);
++	}
++    } else if (!icap->flags.no_content) {
++	/* Wait for EOF condition */
++	commSetSelect(fd, COMM_SELECT_READ, icapReadReply, icap, 0);
++	debug(81,
++	    3)
++	    ("icapReadReply3: Going to read mode data throught icapReadReply\n");
++    } else {
++	debug(81, 3) ("icapReadReply3: Nothing\n");
++    }
++}
+Index: src/main.c
+===================================================================
+RCS file: /cvsroot/squid/squid/src/main.c,v
+retrieving revision 1.72
+retrieving revision 1.45.4.10
+diff -p -u -b -r1.72 -r1.45.4.10
+--- src/main.c	23 Oct 2006 11:52:55 -0000	1.72
++++ src/main.c	3 Nov 2006 18:47:14 -0000	1.45.4.10
+@@ -391,6 +391,9 @@ mainReconfigure(void)
+ #else
+     idnsShutdown();
+ #endif
++#ifdef HS_FEAT_ICAP
++    icapClose();
++#endif
+     redirectShutdown();
+     locationRewriteShutdown();
+     authenticateShutdown();
+@@ -422,6 +425,9 @@ mainReconfigure(void)
+ #endif
+     redirectInit();
+     locationRewriteInit();
++#ifdef HS_FEAT_ICAP
++    icapInit();
++#endif
+     authenticateInit(&Config.authConfig);
+     externalAclInit();
+ #if USE_WCCP
+@@ -573,6 +579,9 @@ mainInitialize(void)
+     redirectInit();
+     locationRewriteInit();
+     errorMapInit();
++#ifdef HS_FEAT_ICAP
++    icapInit();
++#endif
+     authenticateInit(&Config.authConfig);
+     externalAclInit();
+     useragentOpenLog();
+Index: src/mem.c
+===================================================================
+RCS file: /cvsroot/squid/squid/src/mem.c,v
+retrieving revision 1.27
+retrieving revision 1.24.4.3
+diff -p -u -b -r1.27 -r1.24.4.3
+--- src/mem.c	20 May 2006 22:50:55 -0000	1.27
++++ src/mem.c	26 May 2006 18:21:32 -0000	1.24.4.3
+@@ -353,6 +353,13 @@ memInit(void)
+     memDataInit(MEM_TLV, "storeSwapTLV", sizeof(tlv), 0);
+     memDataInit(MEM_SWAP_LOG_DATA, "storeSwapLogData", sizeof(storeSwapLogData), 0);
+ 
++#ifdef HS_FEAT_ICAP
++    memDataInit(MEM_ICAP_OPT_DATA, "IcapOptData", sizeof(IcapOptData), 0);
++    memDataInit(MEM_ICAP_SERVICE_LIST, "icap_service_list", sizeof(icap_service_list), 0);
++    memDataInit(MEM_ICAP_CLASS, "icap_class", sizeof(icap_class), 0);
++    memDataInit(MEM_ICAP_ACCESS, "icap_access", sizeof(icap_access), 0);
++#endif
++
+     /* init string pools */
+     for (i = 0; i < mem_str_pool_count; i++) {
+ 	StrPools[i].pool = memPoolCreate(StrPoolsAttrs[i].name, StrPoolsAttrs[i].obj_size);
+Index: src/mk-string-arrays.pl
+===================================================================
+--- src/mk-string-arrays.pl.orig	Fri Jan 19 01:19:26 2007
++++ src/mk-string-arrays.pl	Wed Jan 24 12:31:03 2007
+@@ -17,6 +17,7 @@ $pat{'icp_opcode'} = "icp_opcode_str";
+ $pat{'swap_log_op'} = "swap_log_op_str";
+ $pat{'lookup_t'} = "lookup_t_str";
+ $pat{'log_type'} = "log_tags";
++$pat{'icap_service_t'} = "icap_service_type_str";
+ 
+ print "#include \"squid.h\"\n";
+ 
+Index: src/pconn.c
+===================================================================
+RCS file: /cvsroot/squid/squid/src/pconn.c,v
+retrieving revision 1.10
+retrieving revision 1.9.4.2
+diff -p -u -b -r1.10 -r1.9.4.2
+--- src/pconn.c	22 May 2006 22:06:12 -0000	1.10
++++ src/pconn.c	26 May 2006 18:21:32 -0000	1.9.4.2
+@@ -46,6 +46,9 @@ struct _pconn {
+ #define PCONN_HIST_SZ (1<<16)
+ int client_pconn_hist[PCONN_HIST_SZ];
+ int server_pconn_hist[PCONN_HIST_SZ];
++#ifdef HS_FEAT_ICAP
++int icap_server_pconn_hist[PCONN_HIST_SZ];
++#endif
+ 
+ static PF pconnRead;
+ static PF pconnTimeout;
+@@ -169,6 +172,20 @@ pconnHistDump(StoreEntry * e)
+ 	    continue;
+ 	storeAppendPrintf(e, "\t%4d  %9d\n", i, server_pconn_hist[i]);
+     }
++#ifdef HS_FEAT_ICAP
++    storeAppendPrintf(e,
++	"\n"
++	"ICAP-server persistent connection counts:\n"
++	"\n"
++	"\treq/\n"
++	"\tconn      count\n"
++	"\t----  ---------\n");
++    for (i = 0; i < PCONN_HIST_SZ; i++) {
++	if (icap_server_pconn_hist[i] == 0)
++	    continue;
++	storeAppendPrintf(e, "\t%4d  %9d\n", i, icap_server_pconn_hist[i]);
++    }
++#endif
+ }
+ 
+ /* ========== PUBLIC FUNCTIONS ============================================ */
+@@ -183,6 +200,9 @@ pconnInit(void)
+     for (i = 0; i < PCONN_HIST_SZ; i++) {
+ 	client_pconn_hist[i] = 0;
+ 	server_pconn_hist[i] = 0;
++#ifdef HS_FEAT_ICAP
++	icap_server_pconn_hist[i] = 0;
++#endif
+     }
+     pconn_data_pool = memPoolCreate("pconn_data", sizeof(struct _pconn));
+     pconn_fds_pool = memPoolCreate("pconn_fds", PCONN_FDS_SZ * sizeof(int));
+@@ -265,11 +285,15 @@ pconnHistCount(int what, int i)
+ {
+     if (i >= PCONN_HIST_SZ)
+ 	i = PCONN_HIST_SZ - 1;
+-    /* what == 0 for client, 1 for server */
++    /* what == 0 for client, 1 for server, 2 for ICAP server */
+     if (what == 0)
+ 	client_pconn_hist[i]++;
+     else if (what == 1)
+ 	server_pconn_hist[i]++;
++#ifdef HS_FEAT_ICAP
++    else if (what == 2)
++	icap_server_pconn_hist[i]++;
++#endif
+     else
+ 	assert(0);
+ }
+Index: src/protos.h
+===================================================================
+RCS file: /cvsroot/squid/squid/src/protos.h,v
+retrieving revision 1.135
+retrieving revision 1.74.4.13
+diff -p -u -b -r1.135 -r1.74.4.13
+--- src/protos.h	26 Feb 2007 09:51:32 -0000	1.135
++++ src/protos.h	27 Feb 2007 21:57:36 -0000	1.74.4.13
+@@ -303,6 +303,8 @@ extern void whoisStart(FwdState *);
+ /* http.c */
+ extern int httpCachable(method_t);
+ extern void httpStart(FwdState *);
++extern void httpParseReplyHeaders(const char *, http_reply *);
++extern size_t httpProcessReplyHeader(HttpStateData *, const char *, int);
+ extern int httpBuildRequestPrefix(request_t * request,
+     request_t * orig_request,
+     StoreEntry * entry,
+@@ -626,6 +628,7 @@ extern void memBufVPrintf(MemBuf * mb, c
+ extern FREE *memBufFreeFunc(MemBuf * mb);
+ /* puts report on MemBuf _module_ usage into mb */
+ extern void memBufReport(MemBuf * mb);
++extern int memBufRead(int fd, MemBuf * mb);
+ 
+ extern char *mime_get_header(const char *mime, const char *header);
+ extern char *mime_get_header_field(const char *mime, const char *name, const char *prefix);
+@@ -1417,4 +1420,55 @@ void storeLocateVaryDone(VaryData * data
+ void storeLocateVary(StoreEntry * e, int offset, const char *vary_data, String accept_encoding, STLVCB * callback, void *cbdata);
+ void storeAddVary(const char *url, const char *log_url, const method_t method, const cache_key * key, const char *etag, const char *vary, const char *vary_headers, const char *accept_encoding);
+ 
++#ifdef HS_FEAT_ICAP
++/*
++ * icap_common.c
++ */
++void icapInit(void);
++void icapClose(void);
++void icapParseEncapsulated(IcapStateData *, const char *, const char *);
++icap_service *icapService(icap_service_t, request_t *);
++int icapConnect(IcapStateData *, CNCB *);
++IcapStateData *icapAllocate(void);
++PF icapStateFree;
++PF icapConnectTimeout;
++PF icapReadTimeout;
++icap_service_t icapServiceToType(const char *);
++const char *icapServiceToStr(const icap_service_t);
++int icapCheckAcl(clientHttpRequest *);
++size_t icapLineLength(const char *, int);
++int icapReadHeader(int, IcapStateData *, int *);
++int icapFindHeader(const char *, const char *, const char **, const char **);
++int icapParseKeepAlive(const IcapStateData *, const char *, const char *);
++void icapSetKeepAlive(IcapStateData * icap, const char *hdrs);
++size_t icapParseChunkedBody(IcapStateData *, STRCB *, void *);
++void icapAddAuthUserHeader(MemBuf *, auth_user_request_t *);
++int icapParseStatusLine(const char *, int, int *, int *, const char **);
++
++/*
++ * icap_respmod.c
++ */
++IcapStateData *icapRespModStart(icap_service_t, request_t *, StoreEntry *, http_state_flags);
++void icapSendRespMod(IcapStateData *, int);
++void icapRespModAddResponceHeaders(IcapStateData *, char *, int);
++void icapRespModAddBodyData(IcapStateData *, char *, int);
++CNCB icapConnectOver;
++
++/*
++ * icap_reqmod.c
++ */
++IcapStateData *icapReqModStart(icap_service*, const char *, request_t *, int, struct timeval, struct in_addr, void *);
++
++/* icap_opt.c */
++void icapOptInit(void);
++void icapOptShutdown(void);
++void icapOptSetUnreachable(icap_service * s);
++
++/* X-Server-IP support */
++void icapAddOriginIP(MemBuf *, const char *);
++
++/* for debugging purposes only */
++void dump_icap_config(IcapConfig * cfg);
++#endif
++
+ #endif /* SQUID_PROTOS_H */
+Index: src/squid.h
+===================================================================
+RCS file: /cvsroot/squid/squid/src/squid.h,v
+retrieving revision 1.36
+retrieving revision 1.24.8.7
+diff -p -u -b -r1.36 -r1.24.8.7
+--- src/squid.h	8 Sep 2006 19:50:59 -0000	1.36
++++ src/squid.h	26 Sep 2006 22:47:38 -0000	1.24.8.7
+@@ -38,6 +38,14 @@
+ #include "config.h"
+ 
+ /*
++ * experimental defines for ICAP
++ */
++#ifdef HS_FEAT_ICAP
++#define ICAP_PREVIEW 1
++#define SUPPORT_ICAP_204 0
++#endif
++
++/*
+  * On some systems, FD_SETSIZE is set to something lower than the
+  * actual number of files which can be opened.  IRIX is one case,
+  * NetBSD is another.  So here we increase FD_SETSIZE to our
+Index: src/stat.c
+===================================================================
+RCS file: /cvsroot/squid/squid/src/stat.c,v
+retrieving revision 1.38
+retrieving revision 1.26.8.10
+diff -p -u -b -r1.38 -r1.26.8.10
+--- src/stat.c	1 Nov 2006 21:51:29 -0000	1.38
++++ src/stat.c	3 Nov 2006 18:47:14 -0000	1.26.8.10
+@@ -804,6 +804,17 @@ statAvgDump(StoreEntry * sentry, int min
+     storeAppendPrintf(sentry, "server.other.kbytes_out = %f/sec\n",
+ 	XAVG(server.other.kbytes_out.kb));
+ 
++#ifdef HS_FEAT_ICAP
++    storeAppendPrintf(sentry, "icap.all.requests = %f/sec\n",
++	XAVG(icap.all.requests));
++    storeAppendPrintf(sentry, "icap.all.errors = %f/sec\n",
++	XAVG(icap.all.errors));
++    storeAppendPrintf(sentry, "icap.all.kbytes_in = %f/sec\n",
++	XAVG(icap.all.kbytes_in.kb));
++    storeAppendPrintf(sentry, "icap.all.kbytes_out = %f/sec\n",
++	XAVG(icap.all.kbytes_out.kb));
++#endif
++
+     storeAppendPrintf(sentry, "icp.pkts_sent = %f/sec\n",
+ 	XAVG(icp.pkts_sent));
+     storeAppendPrintf(sentry, "icp.pkts_recv = %f/sec\n",
+@@ -1188,6 +1199,17 @@ statCountersDump(StoreEntry * sentry)
+     storeAppendPrintf(sentry, "server.other.kbytes_out = %d\n",
+ 	(int) f->server.other.kbytes_out.kb);
+ 
++#if HS_FEAT_ICAP
++    storeAppendPrintf(sentry, "icap.all.requests = %d\n",
++	(int) f->icap.all.requests);
++    storeAppendPrintf(sentry, "icap.all.errors = %d\n",
++	(int) f->icap.all.errors);
++    storeAppendPrintf(sentry, "icap.all.kbytes_in = %d\n",
++	(int) f->icap.all.kbytes_in.kb);
++    storeAppendPrintf(sentry, "icap.all.kbytes_out = %d\n",
++	(int) f->icap.all.kbytes_out.kb);
++#endif
++
+     storeAppendPrintf(sentry, "icp.pkts_sent = %d\n",
+ 	f->icp.pkts_sent);
+     storeAppendPrintf(sentry, "icp.pkts_recv = %d\n",
+@@ -1488,8 +1510,6 @@ statClientRequests(StoreEntry * s)
+ 	    storeAppendPrintf(s, "\tme: %s:%d\n",
+ 		inet_ntoa(conn->me.sin_addr),
+ 		ntohs(conn->me.sin_port));
+-	    storeAppendPrintf(s, "\tnrequests: %d\n",
+-		conn->nrequests);
+ 	    storeAppendPrintf(s, "\tdefer: n %d, until %ld\n",
+ 		conn->defer.n, (long int) conn->defer.until);
+ 	}
+Index: src/store.c
+===================================================================
+RCS file: /cvsroot/squid/squid/src/store.c,v
+retrieving revision 1.39
+retrieving revision 1.21.10.10
+diff -p -u -b -r1.39 -r1.21.10.10
+--- src/store.c	10 Dec 2006 06:51:20 -0000	1.39
++++ src/store.c	12 Dec 2006 22:49:46 -0000	1.21.10.10
+@@ -1105,8 +1105,17 @@ storeAppend(StoreEntry * e, const char *
+     MemObject *mem = e->mem_obj;
+     assert(mem != NULL);
+     assert(len >= 0);
+-    assert(e->store_status == STORE_PENDING);
+     mem->refresh_timestamp = squid_curtime;
++    debug(20, 3) ("storeAppend: '%s'\n", storeKeyText(e->hash.key));
++    if (e->store_status != STORE_PENDING) {
++	/*
++	 * if we're not STORE_PENDING, then probably we got aborted
++	 * and there should be NO clients on this entry
++	 */
++	assert(EBIT_TEST(e->flags, ENTRY_ABORTED));
++	assert(e->mem_obj->nclients == 0);
++	return;
++    }
+     if (len) {
+ 	debug(20, 5) ("storeAppend: appending %d bytes for '%s'\n",
+ 	    len,
+Index: src/structs.h
+===================================================================
+RCS file: /cvsroot/squid/squid/src/structs.h,v
+retrieving revision 1.141
+retrieving revision 1.81.4.14
+diff -p -u -b -r1.141 -r1.81.4.14
+--- src/structs.h	27 Feb 2007 01:16:38 -0000	1.141
++++ src/structs.h	27 Feb 2007 21:57:44 -0000	1.81.4.14
+@@ -423,6 +423,23 @@ struct _RemovalPolicySettings {
+     wordlist *args;
+ };
+ 
++#if HS_FEAT_ICAP
++struct _IcapConfig {
++    int onoff;
++    int preview_enable;
++    icap_service *service_head;
++    icap_class *class_head;
++    icap_access *access_head;
++    int preview_size;
++    int check_interval;
++    int send_client_ip;
++    int send_server_ip;
++    int send_auth_user;
++    char *auth_scheme;
++};
++
++#endif /* HS_FEAT_ICAP */
++
+ struct _SquidConfig {
+     struct {
+ 	squid_off_t maxSize;
+@@ -805,6 +822,9 @@ struct _SquidConfig {
+ #endif
+     time_t refresh_stale_window;
+     int umask;
++#ifdef HS_FEAT_ICAP
++    IcapConfig icapcfg;
++#endif
+ };
+ 
+ struct _SquidConfig2 {
+@@ -887,6 +907,10 @@ struct _fde {
+     comm_pending write_pending;
+     squid_off_t bytes_read;
+     squid_off_t bytes_written;
++    struct {
++	int uses;
++	int type;
++    } pconn;
+     int uses;			/* ie # req's over persistent conn */
+     struct _fde_disk {
+ 	DWCB *wrt_handle;
+@@ -1094,6 +1118,131 @@ struct _http_state_flags {
+     unsigned int trailer:1;
+ };
+ 
++#ifdef HS_FEAT_ICAP
++struct _IcapStateData {
++    request_t *request;
++    http_state_flags http_flags;
++    HttpStateData *httpState;	/* needed to parse HTTP headers only */
++    int icap_fd;
++    int sc;
++    icap_service *current_service;
++    MemBuf icap_hdr;
++    struct {
++	int res_hdr;
++	int res_body;
++	int req_hdr;
++	int req_body;
++	int opt_body;
++	int null_body;
++    } enc;
++    int bytes_to_gobble;
++    int chunk_size;
++    MemBuf chunk_buf;
++    int preview_size;
++    squid_off_t fake_content_length;
++    int http_header_bytes_read_so_far;
++    struct {
++	const char *uri;	/* URI for REQMODs */
++	int client_fd;
++	struct timeval start;	/* for logging */
++	struct in_addr log_addr;	/* for logging */
++	int hdr_state;
++	MemBuf hdr_buf;
++	void *client_cookie;
++	struct {
++	    MemBuf buf;
++	    CBCB *callback;
++	    void *callback_data;
++	    char *callback_buf;
++	    size_t callback_bufsize;
++	    squid_off_t bytes_read;
++	} http_entity;
++    } reqmod;
++    struct {
++	StoreEntry *entry;
++	MemBuf buffer;
++	MemBuf req_hdr_copy;	/* XXX barf */
++	MemBuf resp_copy;	/* XXX barf^max */
++	squid_off_t res_body_sz;
++    } respmod;
++    struct {
++	unsigned int connect_requested:1;
++	unsigned int connect_pending:1;
++	unsigned int write_pending:1;
++	unsigned int keep_alive:1;
++	unsigned int http_server_eof:1;
++	unsigned int send_zero_chunk:1;
++	unsigned int got_reply:1;
++	unsigned int wait_for_reply:1;
++	unsigned int wait_for_preview_reply:1;
++	unsigned int preview_done:1;
++	unsigned int copy_response:1;
++	unsigned int no_content:1;
++	unsigned int reqmod_http_entity_eof:1;
++    } flags;
++};
++
++struct _icap_service {
++    icap_service *next;
++    char *name;			/* name to be used when referencing ths service */
++    char *uri;			/* uri of server/service to use */
++    char *type_name;		/* {req|resp}mod_{pre|post}cache */
++
++    char *hostname;
++    unsigned short int port;
++    char *resource;
++    icap_service_t type;	/* parsed type */
++    icap_method_t method;
++    ushort bypass;		/* flag: bypass allowed */
++    ushort unreachable;		/* flag: set to 1 if options request fails */
++    IcapOptData *opt;		/* temp data needed during opt request */
++    struct {
++	unsigned int allow_204:1;
++	unsigned int need_x_client_ip:1;
++	unsigned int need_x_server_ip:1;
++	unsigned int need_x_authenticated_user:1;
++    } flags;
++    int preview;
++    String istag;
++    String transfer_preview;
++    String transfer_ignore;
++    String transfer_complete;
++    int max_connections;
++    int options_ttl;
++    int keep_alive;
++};
++
++struct _icap_service_list {
++    icap_service_list *next;
++    icap_service *services[16];
++    int nservices;		/* Number of services already used */
++    int last_service_used;	/* Last services used, use to do a round robin */
++};
++
++struct _icap_class {
++    icap_class *next;
++    char *name;
++    wordlist *services;
++    icap_service_list *isl;
++    ushort hidden;		/* for unnamed classes */
++};
++
++struct _icap_access {
++    icap_access *next;
++    char *service_name;
++    icap_class *class;
++    acl_access *access;
++};
++
++struct _IcapOptData {
++    char *buf;
++    off_t offset;
++    size_t size;
++    off_t headlen;
++};
++
++#endif
++
+ struct _HttpStateData {
+     StoreEntry *entry;
+     request_t *request;
+@@ -1105,12 +1254,16 @@ struct _HttpStateData {
+     int fd;
+     http_state_flags flags;
+     FwdState *fwd;
++#ifdef HS_FEAT_ICAP
++    struct _IcapStateData *icap_writer;
++#endif
+     char *body_buf;
+     int body_buf_sz;
+     squid_off_t chunk_size;
+     String chunkhdr;
+ };
+ 
++
+ struct _icpUdpData {
+     struct sockaddr_in address;
+     void *msg;
+@@ -1219,6 +1372,7 @@ struct _clientHttpRequest {
+ 	unsigned int internal:1;
+ 	unsigned int done_copying:1;
+ 	unsigned int purging:1;
++	unsigned int did_icap_reqmod:1;
+ 	unsigned int hit:1;
+     } flags;
+     struct {
+@@ -1233,6 +1387,9 @@ struct _clientHttpRequest {
+      * zero.. [ahc]
+      */
+     char readbuf[CLIENT_SOCK_SZ];
++#if HS_FEAT_ICAP
++    IcapStateData *icap_reqmod;
++#endif
+ };
+ 
+ struct _ConnStateData {
+@@ -1901,6 +2058,9 @@ struct _request_t {
+     unsigned int done_etag:1;	/* We have done clientProcessETag on this, don't attempt it again */
+     char *urlgroup;		/* urlgroup, returned by redirectors */
+     char *peer_domain;		/* Configured peer forceddomain */
++#if HS_FEAT_ICAP
++    icap_class *class;
++#endif
+     BODY_HANDLER *body_reader;
+     void *body_reader_data;
+     String extacl_log;		/* String to be used for access.log purposes */
+@@ -2008,7 +2168,11 @@ struct _StatCounters {
+ 	    kb_t kbytes_in;
+ 	    kb_t kbytes_out;
+ 	} all , http, ftp, other;
+-    } server;
++    }
++#if HS_FEAT_ICAP
++	icap,
++#endif
++	server;
+     struct {
+ 	int pkts_sent;
+ 	int queries_sent;
+Index: src/typedefs.h
+===================================================================
+RCS file: /cvsroot/squid/squid/src/typedefs.h,v
+retrieving revision 1.41
+retrieving revision 1.32.4.8
+diff -p -u -b -r1.41 -r1.32.4.8
+--- src/typedefs.h	2 Sep 2006 14:17:45 -0000	1.41
++++ src/typedefs.h	26 Sep 2006 22:47:39 -0000	1.32.4.8
+@@ -136,6 +136,15 @@ typedef struct _HttpHeaderStat HttpHeade
+ typedef struct _HttpBody HttpBody;
+ typedef struct _HttpReply HttpReply;
+ typedef struct _HttpStateData HttpStateData;
++#ifdef HS_FEAT_ICAP
++typedef struct _IcapStateData IcapStateData;
++typedef struct _IcapConfig IcapConfig;
++typedef struct _icap_service icap_service;
++typedef struct _icap_service_list icap_service_list;
++typedef struct _icap_class icap_class;
++typedef struct _icap_access icap_access;
++typedef struct _IcapOptData IcapOptData;
++#endif
+ typedef struct _icpUdpData icpUdpData;
+ typedef struct _clientHttpRequest clientHttpRequest;
+ typedef struct _ConnStateData ConnStateData;
+Index: src/url.c
+===================================================================
+RCS file: /cvsroot/squid/squid/src/url.c,v
+retrieving revision 1.17
+retrieving revision 1.14.10.4
+diff -p -u -b -r1.17 -r1.14.10.4
+--- src/url.c	17 Jun 2006 23:51:19 -0000	1.17
++++ src/url.c	28 Jun 2006 21:12:01 -0000	1.14.10.4
+@@ -103,6 +103,9 @@ const char *ProtocolStr[] =
+     "whois",
+     "internal",
+     "https",
++#ifdef HS_FEAT_ICAP
++    "icap",
++#endif
+     "TOTAL"
+ };
+ 
+@@ -217,6 +220,10 @@ urlParseProtocol(const char *s)
+ 	return PROTO_WHOIS;
+     if (strcasecmp(s, "internal") == 0)
+ 	return PROTO_INTERNAL;
++#ifdef HS_FEAT_ICAP
++    if (strcasecmp(s, "icap") == 0)
++	return PROTO_ICAP;
++#endif
+     return PROTO_NONE;
+ }
+ 
+@@ -240,6 +247,10 @@ urlDefaultPort(protocol_t p)
+ 	return CACHE_HTTP_PORT;
+     case PROTO_WHOIS:
+ 	return 43;
++#ifdef HS_FEAT_ICAP
++    case PROTO_ICAP:
++	return 1344;
++#endif
+     default:
+ 	return 0;
+     }
Index: pkg-install.in
===================================================================
RCS file: /home/cvs/mports/www/squid/files/pkg-install.in,v
retrieving revision 1.1
retrieving revision 1.2
diff -L www/squid/files/pkg-install.in -L www/squid/files/pkg-install.in -u -r1.1 -r1.2
--- www/squid/files/pkg-install.in
+++ www/squid/files/pkg-install.in
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# $FreeBSD: ports/www/squid/files/pkg-install.in,v 1.2 2006/11/04 23:03:40 miwi Exp $
+# $FreeBSD: ports/www/squid/files/pkg-install.in,v 1.3 2007/02/07 08:42:29 pav Exp $
 #
 
 PATH=/bin:/usr/bin:/usr/sbin
@@ -16,18 +16,11 @@
 squid_group="%%SQUID_GID%%"
 squid_gid=100
 squid_uid=100
-# Try to catch the case where the $squid_user might have been created with an
-# id greater than or equal 3128. The valid exception is "nobody".
-nobody_uid=65534
-nobody_gid=65534
-squid_oldgid=3128
-squid_olduid=3128
-unset wrong_id
 case $2 in
 PRE-INSTALL)
 	echo "===> Pre-installation configuration for ${pkgname}"
 	if ! pw groupshow ${squid_group} -q >/dev/null ; then
-		echo "There is no group '${squid_group}' on this system, so I will try to create it:"
+		echo "There is no group '${squid_group}' on this system, so I will try to create it (using group id ${squid_gid}):"
 		if ! pw groupadd ${squid_group} -g ${squid_gid} -q ; then
 			echo "Failed to create group \"${squid_group}\"!" >&2
 			echo "Please create it manually." >&2
@@ -37,16 +30,11 @@
 		fi
 	else
 		echo "I will use the existing group '${squid_group}':"
-		current_gid=`pw groupshow ${squid_group}|cut -f 3 -d :`
-		if [ ${current_gid} -ge ${squid_oldgid} \
-		    -a ${current_gid} -ne ${nobody_gid} ]; then
-			wrong_id=1
-		fi	
 	fi
 	pw groupshow ${squid_group}
 
 	if ! pw usershow ${squid_user} -q >/dev/null ; then
-		echo "There is no account '${squid_user}' on this system, so I will try to create it:"
+		echo "There is no account '${squid_user}' on this system, so I will try to create it (using user id ${squid_uid}):"
 		if ! pw useradd -q -n ${squid_user} \
 		    -u ${squid_uid} -g ${squid_group} \
 	  	    -c "Squid caching-proxy pseudo user" \
@@ -60,53 +48,8 @@
 		fi
 	else
 		echo "I will use the existing user '${squid_user}':"
-		current_uid=`id -u ${squid_user}`
-		if [ ${current_uid} -ge ${squid_olduid} \
-		    -a ${current_uid} -ne ${nobody_uid} ];
-		then
-			wrong_id=1
-		fi
 	fi
 	pw usershow ${squid_user}
-	if [ "${wrong_id}" ]; then
-		echo ""
-		echo " * NOTICE *"
-		echo ""
-		echo "The Squid pseudo-user's uid and/or gid have been found"
-		echo "to be greater than or equal 3128."
-		echo ""
-		echo "This is not a problem as such, but violates the FreeBSD"
-		echo "ports' principle that a ports must not claim a uid greater"
-		echo "than 999."
-		echo ""
-		echo "Since version 2.5.4_11, the Squid user is thus created"
-		echo "with an id of ${squid_uid}:${squid_gid} while earlier versions of this"
-		echo "port used the first unused uid/gid greater than or"
-		echo "equal 3128."
-		echo ""
-		echo "If you want to change the existing Squid user's id, run"
-		echo "'make changeuser' after the installation has completed."
-		echo "If you installed this port via a package, issue the"
-		echo "following commands as root:"
-		echo ""
-		echo "pw userdel -u ${current_uid}"
-		echo "pw groupadd -n ${squid_group} -g ${squid_gid}"
-		echo "pw useradd -n ${squid_user} -u ${squid_uid} \\"
-		echo "    -c \"Squid caching-proxy pseudo user\" \\"
-		echo "    -g ${squid_group} -d ${squid_base} -s /sbin/nologin \\"
-		echo "    -h -"
-		echo "find -H ${PKG_PREFIX} -user ${current_uid} -exec chown ${squid_user} {} \\;"
-		echo "find -H ${PKG_PREFIX} -group ${current_gid} -exec chgrp ${squid_group} {} \\;"
-		echo ""
-		echo "In case you have installed third party software for Squid"
-		echo "like squidGuard, you should additionally run:"
-		echo "find -H /var -user ${current_uid} -exec chown ${squid_user} {} \\;"
-		echo "find -H /var -group ${current_gid} -exec chgrp ${squid_group} {} \\;"
-		echo ""
-		if [ -z "${PACKAGE_BUILDING}" -a -z "${BATCH}" ]; then
-			sleep 30
-		fi
-	fi
 	for dir in cache logs; do
 	if [ ! -d ${squid_base}/${dir} ]; then
 		echo "Creating ${squid_base}/${dir}..."
--- www/squid/files/customlog-2.5.patch
+++ /dev/null
@@ -1,1597 +0,0 @@
-! This patch is sourced from http://devel.squid-cache.org/customlog/
-! Modified diff paths to apply cleanly
-
-Index: src/access_log.c
-diff -u src/access_log.c:1.15.6.8 src/access_log.c:1.15.6.3.2.15
---- src/access_log.c:1.15.6.8	Tue Mar 29 18:17:46 2005
-+++ src/access_log.c	Mon May 15 03:58:22 2006
-@@ -36,9 +36,6 @@
- 
- #include "squid.h"
- 
--static void accessLogSquid(AccessLogEntry * al);
--static void accessLogCommon(AccessLogEntry * al);
--static Logfile *logfile = NULL;
- #if HEADERS_LOG
- static Logfile *headerslog = NULL;
- #endif
-@@ -234,8 +231,768 @@
-     return username_quote(name);
- }
- 
-+static char *
-+log_quoted_string(const char *str)
-+{
-+    char *out = xmalloc(strlen(str) * 2 + 1);
-+    char *p = out;
-+    while (*str) {
-+	int l = strcspn(str, "\"\\\r\n\t");
-+	memcpy(p, str, l);
-+	str += l;
-+	p += l;
-+	switch (*str) {
-+	case '\0':
-+	    break;
-+	case '\r':
-+	    *p++ = '\\';
-+	    *p++ = 'r';
-+	    str++;
-+	    break;
-+	case '\n':
-+	    *p++ = '\\';
-+	    *p++ = 'n';
-+	    str++;
-+	    break;
-+	case '\t':
-+	    *p++ = '\\';
-+	    *p++ = 't';
-+	    str++;
-+	    break;
-+	default:
-+	    *p++ = '\\';
-+	    *p++ = *str;
-+	    str++;
-+	    break;
-+	}
-+    }
-+    *p++ = '\0';
-+    return out;
-+}
-+
-+/*
-+ * Bytecodes for the configureable logformat stuff
-+ */
-+typedef enum {
-+    LFT_NONE,			/* dummy */
-+    LFT_STRING,
-+
-+    LFT_CLIENT_IP_ADDRESS,
-+    LFT_CLIENT_FQDN,
-+/*LFT_CLIENT_PORT, */
-+
-+/*LFT_SERVER_IP_ADDRESS, */
-+    LFT_SERVER_IP_OR_PEER_NAME,
-+/*LFT_SERVER_PORT, */
-+
-+    LFT_LOCAL_IP,
-+    LFT_LOCAL_PORT,
-+/*LFT_LOCAL_NAME, */
-+
-+    LFT_TIME_SECONDS_SINCE_EPOCH,
-+    LFT_TIME_SUBSECOND,
-+    LFT_TIME_LOCALTIME,
-+    LFT_TIME_GMT,
-+    LFT_TIME_TO_HANDLE_REQUEST,
-+
-+    LFT_REQUEST_HEADER,
-+    LFT_REQUEST_HEADER_ELEM,
-+    LFT_REQUEST_ALL_HEADERS,
-+
-+    LFT_REPLY_HEADER,
-+    LFT_REPLY_HEADER_ELEM,
-+    LFT_REPLY_ALL_HEADERS,
-+
-+    LFT_USER_NAME,
-+    LFT_USER_LOGIN,
-+    LFT_USER_IDENT,
-+/*LFT_USER_REALM, */
-+/*LFT_USER_SCHEME, */
-+
-+    LFT_HTTP_CODE,
-+/*LFT_HTTP_STATUS, */
-+
-+    LFT_SQUID_STATUS,
-+/*LFT_SQUID_ERROR, */
-+    LFT_SQUID_HIERARCHY,
-+
-+    LFT_MIME_TYPE,
-+
-+    LFT_REQUEST_METHOD,
-+    LFT_REQUEST_URI,
-+/*LFT_REQUEST_QUERY, * // * this is not needed. see strip_query_terms */
-+    LFT_REQUEST_VERSION,
-+
-+/*LFT_REQUEST_SIZE_TOTAL, */
-+/*LFT_REQUEST_SIZE_LINE, */
-+/*LFT_REQUEST_SIZE_HEADERS, */
-+/*LFT_REQUEST_SIZE_BODY, */
-+/*LFT_REQUEST_SIZE_BODY_NO_TE, */
-+
-+    LFT_REPLY_SIZE_TOTAL,
-+/*LFT_REPLY_SIZE_LINE, */
-+/*LFT_REPLY_SIZE_HEADERS, */
-+/*LFT_REPLY_SIZE_BODY, */
-+/*LFT_REPLY_SIZE_BODY_NO_TE, */
-+
-+#ifdef HAVE_EXTACL_LOG
-+    LFT_EXT_LOG,
-+#endif
-+
-+    LFT_PERCENT			/* special string cases for escaped chars */
-+} logformat_bcode_t;
-+
-+enum log_quote {
-+    LOG_QUOTE_NONE = 0,
-+    LOG_QUOTE_QUOTES,
-+    LOG_QUOTE_BRAKETS,
-+    LOG_QUOTE_URL,
-+    LOG_QUOTE_RAW
-+};
-+struct _logformat_token {
-+    logformat_bcode_t type;
-+    union {
-+	char *string;
-+	struct {
-+	    char *header;
-+	    char *element;
-+	    char separator;
-+	} header;
-+	char *timespec;
-+    } data;
-+    unsigned char width;
-+    unsigned char precision;
-+    enum log_quote quote:3;
-+    unsigned int left:1;
-+    unsigned int space:1;
-+    unsigned int zero:1;
-+    int divisor;
-+    logformat_token *next;	/* todo: move from linked list to array */
-+};
-+
-+struct logformat_token_table_entry {
-+    const char *config;
-+    logformat_bcode_t token_type;
-+    int options;
-+};
-+
-+struct logformat_token_table_entry logformat_token_table[] =
-+{
-+
-+    {">a", LFT_CLIENT_IP_ADDRESS},
-+/*{ ">p", LFT_CLIENT_PORT}, */
-+    {">A", LFT_CLIENT_FQDN},
-+
-+/*{ "<a", LFT_SERVER_IP_ADDRESS }, */
-+/*{ "<p", LFT_SERVER_PORT }, */
-+    {"<A", LFT_SERVER_IP_OR_PEER_NAME},
-+
-+    {"la", LFT_LOCAL_IP},
-+    {"lp", LFT_LOCAL_PORT},
-+/*{ "lA", LFT_LOCAL_NAME }, */
-+
-+    {"ts", LFT_TIME_SECONDS_SINCE_EPOCH},
-+    {"tu", LFT_TIME_SUBSECOND},
-+    {"tl", LFT_TIME_LOCALTIME},
-+    {"tg", LFT_TIME_GMT},
-+    {"tr", LFT_TIME_TO_HANDLE_REQUEST},
-+
-+    {">h", LFT_REQUEST_HEADER},
-+    {"<h", LFT_REPLY_HEADER},
-+
-+    {"un", LFT_USER_NAME},
-+    {"ul", LFT_USER_LOGIN},
-+/*{ "ur", LFT_USER_REALM }, */
-+/*{ "us", LFT_USER_SCHEME }, */
-+    {"ui", LFT_USER_IDENT},
-+
-+    {"Hs", LFT_HTTP_CODE},
-+/*{ "Ht", LFT_HTTP_STATUS }, */
-+
-+    {"Ss", LFT_SQUID_STATUS},
-+/*{ "Se", LFT_SQUID_ERROR }, */
-+    {"Sh", LFT_SQUID_HIERARCHY},
-+
-+    {"mt", LFT_MIME_TYPE},
-+
-+    {"rm", LFT_REQUEST_METHOD},
-+    {"ru", LFT_REQUEST_URI},	/* doesn't include the query-string */
-+/* { "rq", LFT_REQUEST_QUERY }, * /     / * the query-string, INCLUDING the leading ? */
-+    {">v", LFT_REQUEST_VERSION},
-+    {"rv", LFT_REQUEST_VERSION},
-+
-+/*{ ">st", LFT_REQUEST_SIZE_TOTAL }, */
-+/*{ ">sl", LFT_REQUEST_SIZE_LINE }, * / / * the request line "GET ... " */
-+/*{ ">sh", LFT_REQUEST_SIZE_HEADERS }, */
-+/*{ ">sb", LFT_REQUEST_SIZE_BODY }, */
-+/*{ ">sB", LFT_REQUEST_SIZE_BODY_NO_TE }, */
-+
-+    {"<st", LFT_REPLY_SIZE_TOTAL},
-+/*{ "<sl", LFT_REPLY_SIZE_LINE }, * /   / * the reply line (protocol, code, text) */
-+/*{ "<sh", LFT_REPLY_SIZE_HEADERS }, */
-+/*{ "<sb", LFT_REPLY_SIZE_BODY }, */
-+/*{ "<sB", LFT_REPLY_SIZE_BODY_NO_TE }, */
-+
-+#ifdef HAVE_EXTACL_LOG
-+    {"ea", LFT_EXT_LOG},
-+#endif
-+
-+    {"%", LFT_PERCENT},
-+
-+    {NULL, LFT_NONE}		/* this must be last */
-+};
-+
-+static void
-+accessLogCustom(AccessLogEntry * al, customlog * log)
-+{
-+    logformat *lf;
-+    Logfile *logfile;
-+    logformat_token *fmt;
-+    static MemBuf mb = MemBufNULL;
-+    char tmp[1024];
-+    String sb = StringNull;
-+
-+    memBufReset(&mb);
-+
-+    lf = log->logFormat;
-+    logfile = log->logfile;
-+    for (fmt = lf->format; fmt != NULL; fmt = fmt->next) {	/* for each token */
-+	const char *out = NULL;
-+	int quote = 0;
-+	long int outint = 0;
-+	int doint = 0;
-+	int dofree = 0;
-+	switch (fmt->type) {
-+	case LFT_NONE:
-+	    out = "";
-+	    break;
-+	case LFT_STRING:
-+	    out = fmt->data.string;
-+	    break;
-+	case LFT_CLIENT_IP_ADDRESS:
-+	    out = inet_ntoa(al->cache.caddr);
-+	    break;
-+
-+	case LFT_CLIENT_FQDN:
-+	    out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
-+	    if (!out)
-+		out = inet_ntoa(al->cache.caddr);
-+	    break;
-+
-+	    /* case LFT_CLIENT_PORT: */
-+
-+	    /* case LFT_SERVER_IP_ADDRESS: */
-+
-+	case LFT_SERVER_IP_OR_PEER_NAME:
-+	    out = al->hier.host;
-+	    break;
-+
-+	    /* case LFT_SERVER_PORT: */
-+
-+	case LFT_LOCAL_IP:
-+	    if (al->request)
-+		out = inet_ntoa(al->request->my_addr);
-+	    break;
-+
-+	case LFT_LOCAL_PORT:
-+	    if (al->request) {
-+		outint = al->request->my_port;
-+		doint = 1;
-+	    }
-+	    break;
-+
-+	case LFT_TIME_SECONDS_SINCE_EPOCH:
-+	    outint = current_time.tv_sec;
-+	    doint = 1;
-+	    break;
-+
-+	case LFT_TIME_SUBSECOND:
-+	    outint = current_time.tv_usec / fmt->divisor;
-+	    doint = 1;
-+	    break;
-+
-+
-+	case LFT_TIME_LOCALTIME:
-+	case LFT_TIME_GMT:
-+	    {
-+		const char *spec;
-+		struct tm *t;
-+		spec = fmt->data.timespec;
-+		if (!spec)
-+		    spec = "%d/%b/%Y:%H:%M:%S %z";
-+		if (fmt->type == LFT_TIME_LOCALTIME)
-+		    t = localtime(&squid_curtime);
-+		else
-+		    t = gmtime(&squid_curtime);
-+		strftime(tmp, sizeof(tmp), spec, t);
-+		out = tmp;
-+	    }
-+	    break;
-+
-+	case LFT_TIME_TO_HANDLE_REQUEST:
-+	    outint = al->cache.msec;
-+	    doint = 1;
-+	    break;
-+
-+	case LFT_REQUEST_HEADER:
-+	    if (al->request)
-+		sb = httpHeaderGetByName(&al->request->header, fmt->data.header.header);
-+	    out = strBuf(sb);
-+	    quote = 1;
-+	    break;
-+
-+	case LFT_REPLY_HEADER:
-+	    if (al->reply)
-+		sb = httpHeaderGetByName(&al->reply->header, fmt->data.header.header);
-+	    out = strBuf(sb);
-+	    quote = 1;
-+	    break;
-+
-+	case LFT_REQUEST_HEADER_ELEM:
-+	    if (al->request)
-+		sb = httpHeaderGetByNameListMember(&al->request->header, fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
-+	    out = strBuf(sb);
-+	    quote = 1;
-+	    break;
-+
-+	case LFT_REPLY_HEADER_ELEM:
-+	    if (al->reply)
-+		sb = httpHeaderGetByNameListMember(&al->reply->header, fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
-+	    out = strBuf(sb);
-+	    quote = 1;
-+	    break;
-+
-+	case LFT_REQUEST_ALL_HEADERS:
-+	    out = al->headers.request;
-+	    quote = 1;
-+	    break;
-+
-+	case LFT_REPLY_ALL_HEADERS:
-+	    out = al->headers.reply;
-+	    quote = 1;
-+	    break;
-+
-+	case LFT_USER_NAME:
-+	    out = accessLogFormatName(al->cache.authuser ?
-+		al->cache.authuser : al->cache.rfc931);
-+	    dofree = 1;
-+	    break;
-+
-+	case LFT_USER_LOGIN:
-+	    out = accessLogFormatName(al->cache.authuser);
-+	    dofree = 1;
-+	    break;
-+
-+	case LFT_USER_IDENT:
-+	    out = accessLogFormatName(al->cache.rfc931);
-+	    dofree = 1;
-+	    break;
-+
-+	    /* case LFT_USER_REALM: */
-+	    /* case LFT_USER_SCHEME: */
-+
-+	case LFT_HTTP_CODE:
-+	    outint = al->http.code;
-+	    doint = 1;
-+	    break;
-+
-+	    /* case LFT_HTTP_STATUS:
-+	     *           out = statusline->text;
-+	     *     quote = 1;
-+	     *     break;
-+	     */
-+
-+	case LFT_SQUID_STATUS:
-+	    out = log_tags[al->cache.code];
-+	    break;
-+
-+	    /* case LFT_SQUID_ERROR: */
-+
-+	case LFT_SQUID_HIERARCHY:
-+	    if (al->hier.ping.timedout)
-+		memBufAppend(&mb, "TIMEOUT_", 8);
-+	    out = hier_strings[al->hier.code];
-+	    break;
-+
-+	case LFT_MIME_TYPE:
-+	    out = al->http.content_type;
-+	    break;
-+
-+	case LFT_REQUEST_METHOD:
-+	    out = al->private.method_str;
-+	    break;
-+
-+	case LFT_REQUEST_URI:
-+	    out = al->url;
-+	    break;
-+
-+	case LFT_REQUEST_VERSION:
-+	    snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor);
-+	    out = tmp;
-+	    break;
-+
-+	    /*case LFT_REQUEST_SIZE_TOTAL: */
-+	    /*case LFT_REQUEST_SIZE_LINE: */
-+	    /*case LFT_REQUEST_SIZE_HEADERS: */
-+	    /*case LFT_REQUEST_SIZE_BODY: */
-+	    /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
-+
-+	case LFT_REPLY_SIZE_TOTAL:
-+	    outint = al->cache.size;
-+	    doint = 1;
-+	    break;
-+
-+	    /*case LFT_REPLY_SIZE_LINE: */
-+	    /*case LFT_REPLY_SIZE_HEADERS: */
-+	    /*case LFT_REPLY_SIZE_BODY: */
-+	    /*case LFT_REPLY_SIZE_BODY_NO_TE: */
-+
-+#ifdef HAVE_EXTACL_LOG
-+	case LFT_EXT_LOG:
-+	    if (al->request)
-+		out = strBuf(al->request->extacl_log);
-+
-+	    quote = 1;
-+	    break;
-+#endif
-+
-+	case LFT_PERCENT:
-+	    out = "%";
-+	    break;
-+	}
-+
-+	if (doint) {
-+	    snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero ? (int) fmt->width : 0, outint);
-+	    out = tmp;
-+	}
-+	if (out && *out) {
-+	    if (quote || fmt->quote != LOG_QUOTE_NONE) {
-+		char *newout = NULL;
-+		int newfree = 0;
-+		switch (fmt->quote) {
-+		case LOG_QUOTE_NONE:
-+		    newout = rfc1738_escape_unescaped(out);
-+		    break;
-+		case LOG_QUOTE_QUOTES:
-+		    newout = log_quoted_string(out);
-+		    newfree = 1;
-+		    break;
-+		case LOG_QUOTE_BRAKETS:
-+		    newout = log_quote(out);
-+		    newfree = 1;
-+		    break;
-+		case LOG_QUOTE_URL:
-+		    newout = rfc1738_escape(out);
-+		    break;
-+		case LOG_QUOTE_RAW:
-+		    break;
-+		}
-+		if (newout) {
-+		    if (dofree)
-+			safe_free(out);
-+		    out = newout;
-+		    dofree = newfree;
-+		}
-+	    }
-+	    if (fmt->width) {
-+		if (fmt->left)
-+		    memBufPrintf(&mb, "%-*s", (int) fmt->width, out);
-+		else
-+		    memBufPrintf(&mb, "%*s", (int) fmt->width, out);
-+	    } else
-+		memBufAppend(&mb, out, strlen(out));
-+	} else {
-+	    memBufAppend(&mb, "-", 1);
-+	}
-+	if (fmt->space)
-+	    memBufAppend(&mb, " ", 1);
-+	stringClean(&sb);
-+	if (dofree)
-+	    safe_free(out);
-+    }
-+    logfilePrintf(logfile, "%s\n", mb.buf);
-+}
-+
-+/* parses a single token. Returns the token length in characters,
-+ * and fills in the lt item with the token information.
-+ * def is for sure null-terminated
-+ */
-+static int
-+accessLogGetNewLogFormatToken(logformat_token * lt, char *def, enum log_quote *quote)
-+{
-+    char *cur = def;
-+    struct logformat_token_table_entry *lte;
-+    int l;
-+
-+    memset(lt, 0, sizeof(*lt));
-+    l = strcspn(cur, "%");
-+    if (l > 0) {
-+	char *cp;
-+	/* it's a string for sure, until \0 or the next % */
-+	cp = xmalloc(l + 1);
-+	xstrncpy(cp, cur, l + 1);
-+	lt->type = LFT_STRING;
-+	lt->data.string = cp;
-+	while (l > 0) {
-+	    switch (*cur) {
-+	    case '"':
-+		if (*quote == LOG_QUOTE_NONE)
-+		    *quote = LOG_QUOTE_QUOTES;
-+		else if (*quote == LOG_QUOTE_QUOTES)
-+		    *quote = LOG_QUOTE_NONE;
-+		break;
-+	    case '[':
-+		if (*quote == LOG_QUOTE_NONE)
-+		    *quote = LOG_QUOTE_BRAKETS;
-+		break;
-+	    case ']':
-+		if (*quote == LOG_QUOTE_BRAKETS)
-+		    *quote = LOG_QUOTE_NONE;
-+		break;
-+	    }
-+	    cur++;
-+	    l--;
-+	}
-+	goto done;
-+    }
-+    if (!*cur)
-+	goto done;
-+    cur++;
-+    switch (*cur) {
-+    case '"':
-+	lt->quote = LOG_QUOTE_QUOTES;
-+	cur++;
-+	break;
-+    case '\'':
-+	lt->quote = LOG_QUOTE_RAW;
-+	cur++;
-+	break;
-+    case '[':
-+	lt->quote = LOG_QUOTE_BRAKETS;
-+	cur++;
-+	break;
-+    case '#':
-+	lt->quote = LOG_QUOTE_URL;
-+	cur++;
-+	break;
-+    default:
-+	lt->quote = *quote;
-+	break;
-+    }
-+    if (*cur == '-') {
-+	lt->left = 1;
-+	cur++;
-+    }
-+    if (*cur == '0') {
-+	lt->zero = 1;
-+	cur++;
-+    }
-+    if (isdigit(*cur))
-+	lt->width = strtol(cur, &cur, 10);
-+    if (*cur == '.')
-+	lt->precision = strtol(cur + 1, &cur, 10);
-+    if (*cur == '{') {
-+	char *cp;
-+	cur++;
-+	l = strcspn(cur, "}");
-+	cp = xmalloc(l + 1);
-+	xstrncpy(cp, cur, l + 1);
-+	lt->data.string = cp;
-+	cur += l;
-+	if (*cur == '}')
-+	    cur++;
-+    }
-+    lt->type = LFT_NONE;
-+    for (lte = logformat_token_table; lte->config != NULL; lte++) {
-+	if (strncmp(lte->config, cur, strlen(lte->config)) == 0) {
-+	    lt->type = lte->token_type;
-+	    cur += strlen(lte->config);
-+	    break;
-+	}
-+    }
-+    if (lt->type == LFT_NONE) {
-+	fatalf("Can't parse configuration token: '%s'\n",
-+	    def);
-+    }
-+    if (*cur == ' ') {
-+	lt->space = 1;
-+	cur++;
-+    }
-+  done:
-+    switch (lt->type) {
-+    case LFT_REQUEST_HEADER:
-+    case LFT_REPLY_HEADER:
-+	if (lt->data.string) {
-+	    char *header = lt->data.string;
-+	    char *cp = strchr(header, ':');
-+	    if (cp) {
-+		*cp++ = '\0';
-+		if (*cp == ',' || *cp == ';' || *cp == ':')
-+		    lt->data.header.separator = *cp++;
-+		else
-+		    lt->data.header.separator = ',';
-+		lt->data.header.element = cp;
-+		lt->type = (lt->type == LFT_REQUEST_HEADER) ?
-+		    LFT_REQUEST_HEADER_ELEM :
-+		    LFT_REPLY_HEADER_ELEM;
-+	    }
-+	    lt->data.header.header = header;
-+	} else {
-+	    lt->type = (lt->type == LFT_REQUEST_HEADER) ?
-+		LFT_REQUEST_ALL_HEADERS :
-+		LFT_REPLY_ALL_HEADERS;
-+	    Config.onoff.log_mime_hdrs = 1;
-+	}
-+	break;
-+    case LFT_CLIENT_FQDN:
-+	Config.onoff.log_fqdn = 1;
-+	break;
-+    case LFT_TIME_SUBSECOND:
-+	lt->divisor = 1000;
-+	if (lt->precision) {
-+	    int i;
-+	    lt->divisor = 1000000;
-+	    for (i = lt->precision; i > 1; i--)
-+		lt->divisor /= 10;
-+	    if (!lt->divisor)
-+		lt->divisor = 0;
-+	}
-+	break;
-+    default:
-+	break;
-+    }
-+    return (cur - def);
-+}
-+
-+int
-+accessLogParseLogFormat(logformat_token ** fmt, char *def)
-+{
-+    char *cur, *eos;
-+    logformat_token *new_lt, *last_lt;
-+    enum log_quote quote = LOG_QUOTE_NONE;
-+
-+    debug(46, 1) ("accessLogParseLogFormat: got definition '%s'\n", def);
-+
-+    /* very inefficent parser, but who cares, this needs to be simple */
-+    /* First off, let's tokenize, we'll optimize in a second pass.
-+     * A token can either be a %-prefixed sequence (usually a dynamic
-+     * token but it can be an escaped sequence), or a string. */
-+    cur = def;
-+    eos = def + strlen(def);
-+    *fmt = new_lt = last_lt = xmalloc(sizeof(logformat_token));
-+    cur += accessLogGetNewLogFormatToken(new_lt, cur, &quote);
-+    while (cur < eos) {
-+	new_lt = xmalloc(sizeof(logformat_token));
-+	last_lt->next = new_lt;
-+	last_lt = new_lt;
-+	cur += accessLogGetNewLogFormatToken(new_lt, cur, &quote);
-+    }
-+    return 1;
-+}
-+
-+void
-+accessLogDumpLogFormat(StoreEntry * entry, const char *name, logformat * definitions)
-+{
-+    logformat_token *t;
-+    logformat *format;
-+    struct logformat_token_table_entry *te;
-+    debug(46, 0) ("accessLogDumpLogFormat called\n");
-+
-+    for (format = definitions; format; format = format->next) {
-+	debug(46, 0) ("Dumping logformat definition for %s\n", format->name);
-+	storeAppendPrintf(entry, "logformat %s ", format->name);
-+	for (t = format->format; t; t = t->next) {
-+	    if (t->type == LFT_STRING)
-+		storeAppendPrintf(entry, "%s", t->data.string);
-+	    else {
-+		char argbuf[256];
-+		char *arg = NULL;
-+		logformat_bcode_t type = t->type;
-+
-+		switch (type) {
-+		    /* special cases */
-+		case LFT_STRING:
-+		    break;
-+		case LFT_REQUEST_HEADER_ELEM:
-+		case LFT_REPLY_HEADER_ELEM:
-+		    if (t->data.header.separator != ',')
-+			snprintf(argbuf, sizeof(argbuf), "%s:%c%s", t->data.header.header, t->data.header.separator, t->data.header.element);
-+		    else
-+			snprintf(argbuf, sizeof(argbuf), "%s:%s", t->data.header.header, t->data.header.element);
-+
-+		    arg = argbuf;
-+		    type = (type == LFT_REQUEST_HEADER_ELEM) ?
-+			LFT_REQUEST_HEADER :
-+			LFT_REPLY_HEADER;
-+		    break;
-+
-+		case LFT_REQUEST_ALL_HEADERS:
-+		case LFT_REPLY_ALL_HEADERS:
-+		    type = (type == LFT_REQUEST_ALL_HEADERS) ?
-+			LFT_REQUEST_HEADER :
-+			LFT_REPLY_HEADER;
-+		    break;
-+
-+		default:
-+		    if (t->data.string)
-+			arg = t->data.string;
-+		    break;
-+		}
-+		storeAppend(entry, "%", 1);
-+		switch (t->quote) {
-+		case LOG_QUOTE_QUOTES:
-+		    storeAppend(entry, "\"", 1);
-+		    break;
-+		case LOG_QUOTE_BRAKETS:
-+		    storeAppend(entry, "[", 1);
-+		    break;
-+		case LOG_QUOTE_URL:
-+		    storeAppend(entry, "#", 1);
-+		    break;
-+		case LOG_QUOTE_RAW:
-+		    storeAppend(entry, "'", 1);
-+		    break;
-+		case LOG_QUOTE_NONE:
-+		    break;
-+		}
-+		if (t->left)
-+		    storeAppend(entry, "-", 1);
-+		if (t->zero)
-+		    storeAppend(entry, "0", 1);
-+		if (t->width)
-+		    storeAppendPrintf(entry, "%d", (int) t->width);
-+		if (t->precision)
-+		    storeAppendPrintf(entry, ".%d", (int) t->precision);
-+		if (arg)
-+		    storeAppendPrintf(entry, "{%s}", arg);
-+		for (te = logformat_token_table; te->config != NULL; te++) {
-+		    if (te->token_type == t->type) {
-+			storeAppendPrintf(entry, "%s", te->config);
-+			break;
-+		    }
-+		}
-+		if (t->space)
-+		    storeAppend(entry, " ", 1);
-+		assert(te->config != NULL);
-+	    }
-+	}
-+    }
-+    storeAppend(entry, "\n", 1);
-+}
-+
-+void
-+accessLogFreeLogFormat(logformat_token ** tokens)
-+{
-+    while (*tokens) {
-+	logformat_token *token = *tokens;
-+	*tokens = token->next;
-+	safe_free(token->data.string);
-+	xfree(token);
-+    }
-+}
-+
- static void
--accessLogSquid(AccessLogEntry * al)
-+accessLogSquid(AccessLogEntry * al, Logfile * logfile)
- {
-     const char *client = NULL;
-     char *user = NULL;
-@@ -261,10 +1018,19 @@
- 	al->hier.host,
- 	al->http.content_type);
-     safe_free(user);
-+    if (Config.onoff.log_mime_hdrs) {
-+	char *ereq = log_quote(al->headers.request);
-+	char *erep = log_quote(al->headers.reply);
-+	logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
-+	safe_free(ereq);
-+	safe_free(erep);
-+    } else {
-+	logfilePrintf(logfile, "\n");
-+    }
- }
- 
- static void
--accessLogCommon(AccessLogEntry * al)
-+accessLogCommon(AccessLogEntry * al, Logfile * logfile)
- {
-     const char *client = NULL;
-     char *user1 = NULL, *user2 = NULL;
-@@ -288,11 +1054,21 @@
- 	hier_strings[al->hier.code]);
-     safe_free(user1);
-     safe_free(user2);
-+    if (Config.onoff.log_mime_hdrs) {
-+	char *ereq = log_quote(al->headers.request);
-+	char *erep = log_quote(al->headers.reply);
-+	logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
-+	safe_free(ereq);
-+	safe_free(erep);
-+    } else {
-+	logfilePrintf(logfile, "\n");
-+    }
- }
- 
- void
--accessLogLog(AccessLogEntry * al)
-+accessLogLog(AccessLogEntry * al, aclCheck_t * checklist)
- {
-+    customlog *log;
-     if (LogfileStatus != LOG_ENABLE)
- 	return;
-     if (al->url == NULL)
-@@ -306,20 +1082,38 @@
-     if (al->hier.host[0] == '\0')
- 	xstrncpy(al->hier.host, dash_str, SQUIDHOSTNAMELEN);
- 
--    if (Config.onoff.common_log)
--	accessLogCommon(al);
--    else
--	accessLogSquid(al);
--    if (Config.onoff.log_mime_hdrs) {
--	char *ereq = log_quote(al->headers.request);
--	char *erep = log_quote(al->headers.reply);
--	logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
--	safe_free(ereq);
--	safe_free(erep);
--    } else {
--	logfilePrintf(logfile, "\n");
-+    for (log = Config.Log.accesslogs; log; log = log->next) {
-+	if (checklist && log->aclList && aclMatchAclList(log->aclList, checklist) != 1)
-+	    continue;
-+	switch (log->type) {
-+	case CLF_AUTO:
-+	    if (Config.onoff.common_log)
-+		accessLogCommon(al, log->logfile);
-+	    else
-+		accessLogSquid(al, log->logfile);
-+	    break;
-+	case CLF_SQUID:
-+	    accessLogSquid(al, log->logfile);
-+	    break;
-+	case CLF_COMMON:
-+	    accessLogCommon(al, log->logfile);
-+	    break;
-+	case CLF_CUSTOM:
-+	    accessLogCustom(al, log);
-+	    break;
-+	case CLF_NONE:
-+	    goto last;
-+	default:
-+	    fatalf("Unknown log format %d\n", log->type);
-+	    break;
-+	}
-+	logfileFlush(log->logfile);
-+	if (!checklist)
-+	    break;
-     }
--    logfileFlush(logfile);
-+  last:
-+    (void) 0;			/* NULL statement for label */
-+
- #if MULTICAST_MISS_STREAM
-     if (al->cache.code != LOG_TCP_MISS)
- 	(void) 0;
-@@ -346,12 +1140,15 @@
- void
- accessLogRotate(void)
- {
-+    customlog *log;
- #if FORW_VIA_DB
-     fvdbClear();
- #endif
--    if (NULL == logfile)
--	return;
--    logfileRotate(logfile);
-+    for (log = Config.Log.accesslogs; log; log = log->next) {
-+	if (log->logfile) {
-+	    logfileRotate(log->logfile);
-+	}
-+    }
- #if HEADERS_LOG
-     logfileRotate(headerslog);
- #endif
-@@ -360,10 +1157,13 @@
- void
- accessLogClose(void)
- {
--    if (NULL == logfile)
--	return;
--    logfileClose(logfile);
--    logfile = NULL;
-+    customlog *log;
-+    for (log = Config.Log.accesslogs; log; log = log->next) {
-+	if (log->logfile) {
-+	    logfileClose(log->logfile);
-+	    log->logfile = NULL;
-+	}
-+    }
- #if HEADERS_LOG
-     logfileClose(headerslog);
-     headerslog = NULL;
-@@ -383,11 +1183,14 @@
- void
- accessLogInit(void)
- {
-+    customlog *log;
-     assert(sizeof(log_tags) == (LOG_TYPE_MAX + 1) * sizeof(char *));
--    if (strcasecmp(Config.Log.access, "none") == 0)
--	return;
--    logfile = logfileOpen(Config.Log.access, MAX_URL << 1, 1);
--    LogfileStatus = LOG_ENABLE;
-+    for (log = Config.Log.accesslogs; log; log = log->next) {
-+	if (log->type == CLF_NONE)
-+	    continue;
-+	log->logfile = logfileOpen(log->filename, MAX_URL << 1, 1);
-+	LogfileStatus = LOG_ENABLE;
-+    }
- #if HEADERS_LOG
-     headerslog = logfileOpen("/usr/local/squid/logs/headers.log", MAX_URL << 1, 0);
-     assert(NULL != headerslog);
-Index: src/cache_cf.c
-diff -u src/cache_cf.c:1.38.6.29 src/cache_cf.c:1.38.6.11.4.10
---- src/cache_cf.c:1.38.6.29	Wed Oct 26 19:13:24 2005
-+++ src/cache_cf.c	Fri Mar  3 18:27:50 2006
-@@ -60,6 +60,14 @@
- static void dump_cachedir_option_readonly(StoreEntry * e, const char *option, SwapDir * sd);
- static void parse_cachedir_option_maxsize(SwapDir * sd, const char *option, const char *value, int reconfiguring);
- static void dump_cachedir_option_maxsize(StoreEntry * e, const char *option, SwapDir * sd);
-+static void parse_logformat(logformat ** logformat_definitions);
-+static void parse_access_log(customlog ** customlog_definitions);
-+static void dump_logformat(StoreEntry * entry, const char *name, logformat * definitions);
-+static void dump_access_log(StoreEntry * entry, const char *name, customlog * definitions);
-+static void free_logformat(logformat ** definitions);
-+static void free_access_log(customlog ** definitions);
-+
-+
- static struct cache_dir_option common_cachedir_options[] =
- {
-     {"read-only", parse_cachedir_option_readonly, dump_cachedir_option_readonly},
-@@ -2625,3 +2633,144 @@
- 	return t;
-     }
- }
-+
-+static void
-+parse_logformat(logformat ** logformat_definitions)
-+{
-+    logformat *nlf;
-+    char *name, *def;
-+
-+    if ((name = strtok(NULL, w_space)) == NULL)
-+	self_destruct();
-+    if ((def = strtok(NULL, "\r\n")) == NULL)
-+	self_destruct();
-+
-+    debug(3, 1) ("Logformat for '%s' is '%s'\n", name, def);
-+
-+    nlf = xcalloc(1, sizeof(logformat));
-+    nlf->name = xstrdup(name);
-+    if (!accessLogParseLogFormat(&nlf->format, def))
-+	self_destruct();
-+    nlf->next = *logformat_definitions;
-+    *logformat_definitions = nlf;
-+}
-+
-+static void
-+parse_access_log(customlog ** logs)
-+{
-+    const char *filename, *logdef_name;
-+    customlog *cl;
-+    logformat *lf;
-+
-+    cl = xcalloc(1, sizeof(*cl));
-+
-+    if ((filename = strtok(NULL, w_space)) == NULL)
-+	self_destruct();
-+
-+    if (strcmp(filename, "none") == 0) {
-+	cl->type = CLF_NONE;
-+	goto done;
-+    }
-+    if ((logdef_name = strtok(NULL, w_space)) == NULL)
-+	logdef_name = "auto";
-+
-+    debug(3, 9) ("Log definition name '%s' file '%s'\n", logdef_name, filename);
-+
-+    cl->filename = xstrdup(filename);
-+
-+    /* look for the definition pointer corresponding to this name */
-+    lf = Config.Log.logformats;
-+    while (lf != NULL) {
-+	debug(3, 9) ("Comparing against '%s'\n", lf->name);
-+	if (strcmp(lf->name, logdef_name) == 0)
-+	    break;
-+	lf = lf->next;
-+    }
-+    if (lf != NULL) {
-+	cl->type = CLF_CUSTOM;
-+	cl->logFormat = lf;
-+    } else if (strcmp(logdef_name, "auto") == 0) {
-+	cl->type = CLF_AUTO;
-+    } else if (strcmp(logdef_name, "squid") == 0) {
-+	cl->type = CLF_SQUID;
-+    } else if (strcmp(logdef_name, "common") == 0) {
-+	cl->type = CLF_COMMON;
-+    } else {
-+	debug(3, 0) ("Log format '%s' is not defined\n", logdef_name);
-+	self_destruct();
-+    }
-+
-+  done:
-+    aclParseAclList(&cl->aclList);
-+
-+    while (*logs)
-+	logs = &(*logs)->next;
-+    *logs = cl;
-+}
-+
-+static void
-+dump_logformat(StoreEntry * entry, const char *name, logformat * definitions)
-+{
-+    accessLogDumpLogFormat(entry, name, definitions);
-+}
-+
-+static void
-+dump_access_log(StoreEntry * entry, const char *name, customlog * logs)
-+{
-+    customlog *log;
-+    for (log = logs; log; log = log->next) {
-+	storeAppendPrintf(entry, "%s ", name);
-+	switch (log->type) {
-+	case CLF_CUSTOM:
-+	    storeAppendPrintf(entry, "%s %s", log->filename, log->logFormat->name);
-+	    break;
-+	case CLF_NONE:
-+	    storeAppendPrintf(entry, "none");
-+	    break;
-+	case CLF_SQUID:
-+	    storeAppendPrintf(entry, "%s squid", log->filename);
-+	    break;
-+	case CLF_COMMON:
-+	    storeAppendPrintf(entry, "%s squid", log->filename);
-+	    break;
-+	case CLF_AUTO:
-+	    if (log->aclList)
-+		storeAppendPrintf(entry, "%s auto", log->filename);
-+	    else
-+		storeAppendPrintf(entry, "%s", log->filename);
-+	    break;
-+	case CLF_UNKNOWN:
-+	    break;
-+	}
-+	if (log->aclList)
-+	    dump_acl_list(entry, log->aclList);
-+	storeAppendPrintf(entry, "\n");
-+    }
-+}
-+
-+static void
-+free_logformat(logformat ** definitions)
-+{
-+    while (*definitions) {
-+	logformat *format = *definitions;
-+	*definitions = format->next;
-+	accessLogFreeLogFormat(&format->format);
-+	xfree(format);
-+    }
-+}
-+
-+static void
-+free_access_log(customlog ** definitions)
-+{
-+    while (*definitions) {
-+	customlog *log = *definitions;
-+	*definitions = log->next;
-+
-+	log->logFormat = NULL;
-+	log->type = CLF_UNKNOWN;
-+	if (log->aclList)
-+	    aclDestroyAclList(&log->aclList);
-+	safe_free(log->filename);
-+	xfree(log);
-+    }
-+}
-Index: src/cf.data.pre
-diff -u src/cf.data.pre:1.49.2.86 src/cf.data.pre:1.49.2.40.2.18
---- src/cf.data.pre:1.49.2.86	Sat Feb 25 19:13:57 2006
-+++ src/cf.data.pre	Fri Mar  3 18:27:50 2006
-@@ -834,16 +834,97 @@
- 	(hard coded at 1 MB).
- DOC_END
- 
--
--NAME: cache_access_log
--TYPE: string
--DEFAULT: @DEFAULT_ACCESS_LOG@
--LOC: Config.Log.access
-+NAME: logformat
-+TYPE: logformat
-+LOC: Config.Log.logformats
-+DEFAULT: none
- DOC_START
--	Logs the client request activity.  Contains an entry for
--	every HTTP and ICP queries received. To disable, enter "none".
--DOC_END
-+	Usage:
-+
-+	logformat <name> <format specification>
-+
-+	Defines an access log format.
-+
-+	The <format specification> is a string with embedded % format codes
-+	
-+	% format codes all follow the same basic structure where all but
-+	the formatcode is optional. Output strings are automatically escaped
-+	as required according to their context and the output format
-+	modifiers are usually not needed, but can be specified if an explicit
-+	output format is desired.
-+
-+		% ["|[|'|#] [-] [[0]width] [{argument}] formatcode
-+	
-+		"	output in quoted string format
-+		[	output in squid text log format as used by log_mime_hdrs
-+		#	output in URL quoted format
-+		'	output as-is
-+
-+		-	left aligned
-+		width	field width. If starting with 0 then the
-+			output is zero padded
-+		{arg}	argument such as header name etc
-+
-+	Format codes:
-+
-+		>a	Client source IP address
-+		>A	Client FQDN
-+		<A	Server IP address or peer name
-+		la	Local IP address (http_port)
-+		lp	Local port number (http_port)
-+		ts	Seconds since epoch
-+		tu	subsecond time (milliseconds)
-+		tl	Local time. Optional strftime format argument
-+			default %d/%b/%Y:%H:%M:%S %z
-+		tg	GMT time. Optional strftime format argument
-+			default %d/%b/%Y:%H:%M:%S %z
-+		tr	Response time (milliseconds)
-+		>h	Request header. Optional header name argument
-+			on the format header[:[separator]element]
-+		<h	Reply header. Optional header name argument
-+			as for >h
-+		un	User name
-+		ul	User login
-+		ui	User ident
-+		Hs	HTTP status code
-+		Ss	Squid request status (TCP_MISS etc)
-+		Sh	Squid hierarchy status (DEFAULT_PARENT etc)
-+		mt	MIME content type
-+		rm	Request method (GET/POST etc)
-+		ru	Request URL
-+		rv	Request protocol version
-+		ea	Log string returned by external acl
-+		<st	Reply size including HTTP headers
-+		%	a literal % character
-+
-+logformat squid  %ts.%03tu %6tr %>a %Ss/%03Hs %<st %rm %ru %un %Sh/%<A %mt
-+logformat squidmime  %ts.%03tu %6tr %>a %Ss/%03Hs %<st %rm %ru %un %Sh/%<A %mt [%>h] [%<h]
-+logformat common %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %Hs %<st %Ss:%Sh
-+logformat combined %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %Hs %<st "%{Referer}>h" "%{User-Agent}>h" %Ss:%Sh
-+DOC_END
-+
-+NAME: access_log cache_access_log
-+TYPE: access_log
-+LOC: Config.Log.accesslogs
-+DEFAULT: none
-+DOC_START
-+  These files log client request activities. Has a line every HTTP or
-+  ICP request. The format is:
-+  access_log <filepath> [<logformat name> [acl acl ...]]
-+
-+  Will log to the specified file using the specified format (which
-+  must be defined in a logformat directive) those entries which match
-+  ALL the acl's specified (which must be defined in acl clauses).
-+  If no acl is specified, all requests will be logged to this file.
-+  
-+  To disable logging of a request use the filepath "none", in which case
-+  a logformat name should not be specified.
- 
-+  To log the request via syslog specify a filepath of "syslog"
-+NOCOMMENT_START
-+access_log @DEFAULT_ACCESS_LOG@ squid
-+NOCOMMENT_END
-+DOC_END
- 
- NAME: cache_log
- TYPE: string
-@@ -2440,6 +2521,17 @@
- 	no limit imposed.
- DOC_END
- 
-+NAME: log_access
-+TYPE: acl_access
-+LOC: Config.accessList.log
-+DEFAULT: none
-+COMMENT: allow|deny acl acl...
-+DOC_START
-+        This options allows you to control which requests gets logged
-+	to access.log (see cache_access_log directive). Requests denied
-+	for logging will also not be accounted for in performance counters.
-+DOC_END
-+
- COMMENT_START
-  ADMINISTRATIVE PARAMETERS
-  -----------------------------------------------------------------------------
-Index: src/client_side.c
-diff -u src/client_side.c:1.47.2.76 src/client_side.c:1.47.2.31.2.15
---- src/client_side.c:1.47.2.76	Fri Mar 10 19:16:31 2006
-+++ src/client_side.c	Mon Apr 24 08:22:33 2006
-@@ -871,14 +871,18 @@
- 	http->al.cache.code = http->log_type;
- 	http->al.cache.msec = tvSubMsec(http->start, current_time);
- 	if (request) {
--	    Packer p;
--	    MemBuf mb;
--	    memBufDefInit(&mb);
--	    packerToMemInit(&p, &mb);
--	    httpHeaderPackInto(&request->header, &p);
-+	    if (Config.onoff.log_mime_hdrs) {
-+		Packer p;
-+		MemBuf mb;
-+		memBufDefInit(&mb);
-+		packerToMemInit(&p, &mb);
-+		httpHeaderPackInto(&request->header, &p);
-+		http->al.headers.request = xstrdup(mb.buf);
-+		packerClean(&p);
-+		memBufClean(&mb);
-+	    }
- 	    http->al.http.method = request->method;
- 	    http->al.http.version = request->http_ver;
--	    http->al.headers.request = xstrdup(mb.buf);
- 	    http->al.hier = request->hier;
- 	    if (request->auth_user_request) {
- 		if (authenticateUserRequestUsername(request->auth_user_request))
-@@ -888,12 +892,17 @@
- 	    }
- 	    if (conn->rfc931[0])
- 		http->al.cache.rfc931 = conn->rfc931;
--	    packerClean(&p);
--	    memBufClean(&mb);
- 	}
--	accessLogLog(&http->al);
--	clientUpdateCounters(http);
--	clientdbUpdate(conn->peer.sin_addr, http->log_type, PROTO_HTTP, http->out.size);
-+	http->al.request = request;
-+	if (!http->acl_checklist)
-+	    http->acl_checklist = clientAclChecklistCreate(Config.accessList.http, http);
-+	http->acl_checklist->reply = http->reply;
-+	if (!Config.accessList.log || aclCheckFast(Config.accessList.log, http->acl_checklist)) {
-+	    http->al.reply = http->reply;
-+	    accessLogLog(&http->al, http->acl_checklist);
-+	    clientUpdateCounters(http);
-+	    clientdbUpdate(conn->peer.sin_addr, http->log_type, PROTO_HTTP, http->out.size);
-+	}
-     }
-     if (http->acl_checklist)
- 	aclChecklistFree(http->acl_checklist);
-@@ -904,6 +913,7 @@
-     safe_free(http->al.headers.request);
-     safe_free(http->al.headers.reply);
-     safe_free(http->al.cache.authuser);
-+    http->al.request = NULL;
-     safe_free(http->redirect.location);
-     stringClean(&http->range_iter.boundary);
-     if ((e = http->entry)) {
-Index: src/icp_v2.c
-diff -u src/icp_v2.c:1.5 src/icp_v2.c:1.5.60.1
---- src/icp_v2.c:1.5	Fri May  4 06:39:12 2001
-+++ src/icp_v2.c	Sat Jun 21 05:45:26 2003
-@@ -63,7 +63,7 @@
-     al.cache.size = len;
-     al.cache.code = logcode;
-     al.cache.msec = delay;
--    accessLogLog(&al);
-+    accessLogLog(&al, NULL);
- }
- 
- void
-Index: src/logfile.c
-diff -u src/logfile.c:1.5.38.3 src/logfile.c:1.5.38.3.4.4
---- src/logfile.c:1.5.38.3	Mon Jan 20 19:15:11 2003
-+++ src/logfile.c	Sun May 21 16:56:52 2006
-@@ -36,36 +36,127 @@
- 
- static void logfileWriteWrapper(Logfile * lf, const void *buf, size_t len);
- 
-+#if HAVE_SYSLOG
-+typedef struct {
-+    const char *name;
-+    int value;
-+}syslog_symbol_t;
-+
-+static int 
-+syslog_ntoa(const char *s)
-+{
-+#define syslog_symbol(a) #a, a
-+    static syslog_symbol_t symbols[] =
-+    {
-+#ifdef LOG_AUTHPRIV
-+	{syslog_symbol(LOG_AUTHPRIV)},
-+#endif
-+#ifdef LOG_DAEMON
-+	{syslog_symbol(LOG_DAEMON)},
-+#endif
-+#ifdef LOG_LOCAL0
-+	{syslog_symbol(LOG_LOCAL0)},
-+#endif
-+#ifdef LOG_LOCAL1
-+	{syslog_symbol(LOG_LOCAL1)},
-+#endif
-+#ifdef LOG_LOCAL2
-+	{syslog_symbol(LOG_LOCAL2)},
-+#endif
-+#ifdef LOG_LOCAL3
-+	{syslog_symbol(LOG_LOCAL3)},
-+#endif
-+#ifdef LOG_LOCAL4
-+	{syslog_symbol(LOG_LOCAL4)},
-+#endif
-+#ifdef LOG_LOCAL5
-+	{syslog_symbol(LOG_LOCAL5)},
-+#endif
-+#ifdef LOG_LOCAL6
-+	{syslog_symbol(LOG_LOCAL6)},
-+#endif
-+#ifdef LOG_LOCAL7
-+	{syslog_symbol(LOG_LOCAL7)},
-+#endif
-+#ifdef LOG_USER
-+	{syslog_symbol(LOG_USER)},
-+#endif
-+#ifdef LOG_ERR
-+	{syslog_symbol(LOG_ERR)},
-+#endif
-+#ifdef LOG_WARNING
-+	{syslog_symbol(LOG_WARNING)},
-+#endif
-+#ifdef LOG_NOTICE
-+	{syslog_symbol(LOG_NOTICE)},
-+#endif
-+#ifdef LOG_INFO
-+	{syslog_symbol(LOG_INFO)},
-+#endif
-+#ifdef LOG_DEBUG
-+	{syslog_symbol(LOG_DEBUG)},
-+#endif
-+	{NULL, 0}
-+    };
-+    syslog_symbol_t *p;
-+
-+    for (p = symbols; p->name != NULL; ++p)
-+	if (!strcmp(s, p->name) || !strcmp(s, p->name + 4))
-+	    return p->value;
-+    return 0;
-+}
-+
-+#define PRIORITY_MASK (LOG_ERR | LOG_WARNING | LOG_NOTICE | LOG_INFO | LOG_DEBUG)
-+#endif /* HAVE_SYSLOG */
-+
- Logfile *
- logfileOpen(const char *path, size_t bufsz, int fatal_flag)
- {
--    int fd;
--    Logfile *lf;
--    fd = file_open(path, O_WRONLY | O_CREAT | O_TEXT);
--    if (DISK_ERROR == fd) {
--	if (ENOENT == errno && fatal_flag) {
--	    fatalf("Cannot open '%s' because\n"
--		"\tthe parent directory does not exist.\n"
--		"\tPlease create the directory.\n", path);
--	} else if (EACCES == errno && fatal_flag) {
--	    fatalf("Cannot open '%s' for writing.\n"
--		"\tThe parent directory must be writeable by the\n"
--		"\tuser '%s', which is the cache_effective_user\n"
--		"\tset in squid.conf.", path, Config.effectiveUser);
--	} else {
--	    debug(50, 1) ("logfileOpen: %s: %s\n", path, xstrerror());
--	    return NULL;
-+    Logfile *lf = xcalloc(1, sizeof(*lf));
-+    xstrncpy(lf->path, path, MAXPATHLEN);
-+#if HAVE_SYSLOG
-+    if (strcmp(path, "syslog") == 0 || strncmp(path, "syslog:", 7) == 0) {
-+	lf->flags.syslog = 1;
-+	lf->fd = -1;
-+	if (path[6] != '\0') {
-+	    const char *priority = path + 7;
-+	    char *facility = strchr(priority, '|');
-+	    if (facility) {
-+		*facility++ = '\0';
-+		lf->syslog_priority |= syslog_ntoa(facility);
-+	    }
-+	    lf->syslog_priority |= syslog_ntoa(priority);
-+	}
-+	if ((lf->syslog_priority & PRIORITY_MASK) == 0)
-+	    lf->syslog_priority |= LOG_INFO;
-+    } else
-+#endif
-+    {
-+	int fd = file_open(path, O_WRONLY | O_CREAT | O_TEXT);
-+	if (DISK_ERROR == fd) {
-+	    if (ENOENT == errno && fatal_flag) {
-+		fatalf("Cannot open '%s' because\n"
-+		    "\tthe parent directory does not exist.\n"
-+		    "\tPlease create the directory.\n", path);
-+	    } else if (EACCES == errno && fatal_flag) {
-+		fatalf("Cannot open '%s' for writing.\n"
-+		    "\tThe parent directory must be writeable by the\n"
-+		    "\tuser '%s', which is the cache_effective_user\n"
-+		    "\tset in squid.conf.", path, Config.effectiveUser);
-+	    } else {
-+		debug(50, 1) ("logfileOpen: %s: %s\n", path, xstrerror());
-+		safe_free(lf);
-+		return NULL;
-+	    }
-+	}
-+	lf->fd = fd;
-+	if (bufsz > 0) {
-+	    lf->buf = xmalloc(bufsz);
-+	    lf->bufsz = bufsz;
- 	}
-     }
--    lf = xcalloc(1, sizeof(*lf));
--    lf->fd = fd;
-     if (fatal_flag)
- 	lf->flags.fatal = 1;
--    xstrncpy(lf->path, path, MAXPATHLEN);
--    if (bufsz > 0) {
--	lf->buf = xmalloc(bufsz);
--	lf->bufsz = bufsz;
--    }
-     return lf;
- }
- 
-@@ -73,7 +164,8 @@
- logfileClose(Logfile * lf)
- {
-     logfileFlush(lf);
--    file_close(lf->fd);
-+    if (lf->fd >= 0)
-+	file_close(lf->fd);
-     if (lf->buf)
- 	xfree(lf->buf);
-     xfree(lf);
-@@ -89,6 +181,8 @@
-     char from[MAXPATHLEN];
-     char to[MAXPATHLEN];
-     assert(lf->path);
-+    if (lf->flags.syslog)
-+	return;
- #ifdef S_ISREG
-     if (stat(lf->path, &sb) == 0)
- 	if (S_ISREG(sb.st_mode) == 0)
-@@ -120,6 +214,12 @@
- void
- logfileWrite(Logfile * lf, void *buf, size_t len)
- {
-+#if HAVE_SYSLOG
-+    if (lf->flags.syslog) {
-+	syslog(lf->syslog_priority, "%s", (char *) buf);
-+	return;
-+    }
-+#endif
-     if (0 == lf->bufsz) {
- 	/* buffering disabled */
- 	logfileWriteWrapper(lf, buf, len);
-Index: src/protos.h
-diff -u src/protos.h:1.41.6.34 src/protos.h:1.41.6.14.2.10
---- src/protos.h:1.41.6.34	Sat Feb 25 19:13:57 2006
-+++ src/protos.h	Fri Mar  3 18:27:52 2006
-@@ -34,11 +34,14 @@
- #ifndef SQUID_PROTOS_H
- #define SQUID_PROTOS_H
- 
--extern void accessLogLog(AccessLogEntry *);
-+extern void accessLogLog(AccessLogEntry *, aclCheck_t * checklist);
- extern void accessLogRotate(void);
- extern void accessLogClose(void);
- extern void accessLogInit(void);
- extern const char *accessLogTime(time_t);
-+extern int accessLogParseLogFormat(logformat_token ** fmt, char *def);
-+extern void accessLogDumpLogFormat(StoreEntry * entry, const char *name, logformat * definitions);
-+extern void accessLogFreeLogFormat(logformat_token ** fmt);
- extern void hierarchyNote(HierarchyLogEntry *, hier_code, const char *);
- #if FORW_VIA_DB
- extern void fvdbCountVia(const char *key);
-Index: src/structs.h
-diff -u src/structs.h:1.48.2.46 src/structs.h:1.48.2.11.2.14
---- src/structs.h:1.48.2.46	Fri Mar 10 19:16:31 2006
-+++ src/structs.h	Mon Apr 24 08:22:34 2006
-@@ -465,7 +465,6 @@
-     char *as_whois_server;
-     struct {
- 	char *log;
--	char *access;
- 	char *store;
- 	char *swap;
- #if USE_USERAGENT_LOG
-@@ -477,6 +476,8 @@
- #if WIP_FWD_LOG
- 	char *forward;
- #endif
-+	logformat *logformats;
-+	customlog *accesslogs;
- 	int rotateNumber;
-     } Log;
-     char *adminEmail;
-@@ -623,6 +624,7 @@
- 	acl_access *AlwaysDirect;
- 	acl_access *ASlists;
- 	acl_access *noCache;
-+	acl_access *log;
- #if SQUID_SNMP
- 	acl_access *snmp;
- #endif
-@@ -1061,6 +1063,8 @@
- 	const char *method_str;
-     } private;
-     HierarchyLogEntry hier;
-+    HttpReply *reply;
-+    request_t *request;
- };
- 
- struct _clientHttpRequest {
-@@ -2210,8 +2214,32 @@
-     size_t bufsz;
-     ssize_t offset;
-     struct {
--	unsigned int fatal:1;
-+	unsigned int fatal;
-+	unsigned int syslog;
-     } flags;
-+    int syslog_priority;
-+};
-+
-+struct _logformat {
-+    char *name;
-+    logformat_token *format;
-+    logformat *next;
-+};
-+
-+struct _customlog {
-+    char *filename;
-+    acl_list *aclList;
-+    logformat *logFormat;
-+    Logfile *logfile;
-+    customlog *next;
-+    enum {
-+	CLF_UNKNOWN,
-+	CLF_AUTO,
-+	CLF_CUSTOM,
-+	CLF_SQUID,
-+	CLF_COMMON,
-+	CLF_NONE
-+    } type;
- };
- 
- struct cache_dir_option {
-Index: src/typedefs.h
-diff -u src/typedefs.h:1.25.6.8 src/typedefs.h:1.25.6.2.2.6
---- src/typedefs.h:1.25.6.8	Sat Mar 26 18:16:17 2005
-+++ src/typedefs.h	Thu May 26 21:34:16 2005
-@@ -209,6 +209,9 @@
- typedef struct _storerepl_entry storerepl_entry_t;
- typedef struct _diskd_queue diskd_queue;
- typedef struct _Logfile Logfile;
-+typedef struct _logformat_token logformat_token;
-+typedef struct _logformat logformat;
-+typedef struct _customlog customlog;
- typedef struct _RemovalPolicy RemovalPolicy;
- typedef struct _RemovalPolicyWalker RemovalPolicyWalker;
- typedef struct _RemovalPurgeWalker RemovalPurgeWalker;
--- /dev/null
+++ www/squid/files/extra-patch-src-cf.data.pre.aufs
@@ -0,0 +1,20 @@
+--- src/cf.data.pre.orig	Wed Nov  1 15:12:02 2006
++++ src/cf.data.pre	Wed Nov  1 15:12:17 2006
+@@ -1097,6 +1100,17 @@
+ 
+ 	see argument descriptions under ufs above
+ 
++	Note:
++	By default, FreeBSD uses the pthread(3) M:N threading library.
++	You can, however, map the thread library to the 1:1 libthr(3)
++	implementation by inserting the following lines into
++	/etc/libmap.conf and see whether this performs better on your
++	system:
++
++	[%%PREFIX%%/sbin/squid]
++	libpthread.so.1	libthr.so.1
++	libpthread.so.2	libthr.so.2
++
+ 	The diskd store type:
+ 
+ 	"diskd" uses the same storage format as "ufs", utilizing a
--- /dev/null
+++ www/squid/files/icap-2.6-bootstrap.patch
@@ -0,0 +1,490 @@
+Patch 2 of 2 to integrate the icap-2_6 branch into the FreeBSD squid port.
+
+Created by Thomas-Martin Seck <tmseck at netcologne.de>.
+
+This patch simulates the autotools bootstrap necessary after applying the
+ICAP patchset.
+
+Please see icap-2.6-core.patch for further information.
+
+Patch last updated: 2008-04-02
+
+--- configure.orig	2008-04-02 22:26:33.000000000 +0200
++++ configure	2008-04-02 22:26:34.000000000 +0200
+@@ -728,6 +728,8 @@
+ ENABLE_PINGER_FALSE
+ USE_DELAY_POOLS_TRUE
+ USE_DELAY_POOLS_FALSE
++USE_ICAP_TRUE
++USE_ICAP_FALSE
+ USE_SNMP_TRUE
+ USE_SNMP_FALSE
+ SNMPLIB
+@@ -794,6 +796,10 @@
+ USE_DEVPOLL_FALSE
+ NEED_OWN_SNPRINTF_TRUE
+ NEED_OWN_SNPRINTF_FALSE
++NEED_OWN_STRNSTR_TRUE
++NEED_OWN_STRNSTR_FALSE
++NEED_OWN_STRCASESTR_TRUE
++NEED_OWN_STRCASESTR_FALSE
+ NEED_OWN_STRSEP_TRUE
+ NEED_OWN_STRSEP_FALSE
+ REGEXLIB
+@@ -1427,6 +1433,7 @@
+ 			  to build your custom policy
+   --enable-icmp           Enable ICMP pinging
+   --enable-delay-pools    Enable delay pools to limit bandwidth usage
++  --enable-icap-support   	   Enable ICAP client capability
+   --enable-useragent-log  Enable logging of User-Agent header
+   --enable-referer-log    Enable logging of Referer header
+   --disable-wccp          Disable Web Cache Coordination V1 Protocol
+@@ -2349,7 +2356,7 @@
+ 
+ # Define the identity of the package.
+  PACKAGE='squid'
+- VERSION='2.6.STABLE19'
++ VERSION='2.6.STABLE19+ICAP'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -4543,6 +4550,40 @@
+ 
+ 
+ 
++
++if false; then
++  USE_ICAP_TRUE=
++  USE_ICAP_FALSE='#'
++else
++  USE_ICAP_TRUE='#'
++  USE_ICAP_FALSE=
++fi
++
++# Check whether --enable-icap-support was given.
++if test "${enable_icap_support+set}" = set; then
++  enableval=$enable_icap_support;  if test "$enableval" = "yes" ; then
++    echo "ICAP support enabled"
++
++cat >>confdefs.h <<\_ACEOF
++#define HS_FEAT_ICAP 1
++_ACEOF
++
++
++
++if true; then
++  USE_ICAP_TRUE=
++  USE_ICAP_FALSE='#'
++else
++  USE_ICAP_TRUE='#'
++  USE_ICAP_FALSE=
++fi
++
++  fi
++
++fi
++
++
++
+ # Check whether --enable-useragent-log was given.
+ if test "${enable_useragent_log+set}" = set; then
+   enableval=$enable_useragent_log;  if test "$enableval" = "yes" ; then
+@@ -24506,6 +24547,8 @@
+ 	srand48 \
+ 	srandom \
+ 	statfs \
++	strnstr \
++	strcasestr \
+ 	strsep \
+ 	strtoll \
+ 	sysconf \
+@@ -25211,6 +25254,52 @@
+ 
+ 
+ if false; then
++  NEED_OWN_STRNSTR_TRUE=
++  NEED_OWN_STRNSTR_FALSE='#'
++else
++  NEED_OWN_STRNSTR_TRUE='#'
++  NEED_OWN_STRNSTR_FALSE=
++fi
++
++if test "$ac_cv_func_strnstr" = "no" || test "$ac_cv_func_vstrnstr" = "no" ; then
++
++
++if true; then
++  NEED_OWN_STRNSTR_TRUE=
++  NEED_OWN_STRNSTR_FALSE='#'
++else
++  NEED_OWN_STRNSTR_TRUE='#'
++  NEED_OWN_STRNSTR_FALSE=
++fi
++
++fi
++
++
++
++if false; then
++  NEED_OWN_STRCASESTR_TRUE=
++  NEED_OWN_STRCASESTR_FALSE='#'
++else
++  NEED_OWN_STRCASESTR_TRUE='#'
++  NEED_OWN_STRCASESTR_FALSE=
++fi
++
++if test "$ac_cv_func_strcasestr" = "no" || test "$ac_cv_func_vstrcasestr" = "no"; then
++
++
++if true; then
++  NEED_OWN_STRCASESTR_TRUE=
++  NEED_OWN_STRCASESTR_FALSE='#'
++else
++  NEED_OWN_STRCASESTR_TRUE='#'
++  NEED_OWN_STRCASESTR_FALSE=
++fi
++
++fi
++
++
++
++if false; then
+   NEED_OWN_STRSEP_TRUE=
+   NEED_OWN_STRSEP_FALSE='#'
+ else
+@@ -26801,6 +26890,20 @@
+ Usually this means the macro was only invoked conditionally." >&2;}
+    { (exit 1); exit 1; }; }
+ fi
++if test -z "${USE_ICAP_TRUE}" && test -z "${USE_ICAP_FALSE}"; then
++  { { echo "$as_me:$LINENO: error: conditional \"USE_ICAP\" was never defined.
++Usually this means the macro was only invoked conditionally." >&5
++echo "$as_me: error: conditional \"USE_ICAP\" was never defined.
++Usually this means the macro was only invoked conditionally." >&2;}
++   { (exit 1); exit 1; }; }
++fi
++if test -z "${USE_ICAP_TRUE}" && test -z "${USE_ICAP_FALSE}"; then
++  { { echo "$as_me:$LINENO: error: conditional \"USE_ICAP\" was never defined.
++Usually this means the macro was only invoked conditionally." >&5
++echo "$as_me: error: conditional \"USE_ICAP\" was never defined.
++Usually this means the macro was only invoked conditionally." >&2;}
++   { (exit 1); exit 1; }; }
++fi
+ if test -z "${USE_SNMP_TRUE}" && test -z "${USE_SNMP_FALSE}"; then
+   { { echo "$as_me:$LINENO: error: conditional \"USE_SNMP\" was never defined.
+ Usually this means the macro was only invoked conditionally." >&5
+@@ -26962,6 +27065,34 @@
+ Usually this means the macro was only invoked conditionally." >&2;}
+    { (exit 1); exit 1; }; }
+ fi
++if test -z "${NEED_OWN_STRNSTR_TRUE}" && test -z "${NEED_OWN_STRNSTR_FALSE}"; then
++  { { echo "$as_me:$LINENO: error: conditional \"NEED_OWN_STRNSTR\" was never defined.
++Usually this means the macro was only invoked conditionally." >&5
++echo "$as_me: error: conditional \"NEED_OWN_STRNSTR\" was never defined.
++Usually this means the macro was only invoked conditionally." >&2;}
++   { (exit 1); exit 1; }; }
++fi
++if test -z "${NEED_OWN_STRNSTR_TRUE}" && test -z "${NEED_OWN_STRNSTR_FALSE}"; then
++  { { echo "$as_me:$LINENO: error: conditional \"NEED_OWN_STRNSTR\" was never defined.
++Usually this means the macro was only invoked conditionally." >&5
++echo "$as_me: error: conditional \"NEED_OWN_STRNSTR\" was never defined.
++Usually this means the macro was only invoked conditionally." >&2;}
++   { (exit 1); exit 1; }; }
++fi
++if test -z "${NEED_OWN_STRCASESTR_TRUE}" && test -z "${NEED_OWN_STRCASESTR_FALSE}"; then
++  { { echo "$as_me:$LINENO: error: conditional \"NEED_OWN_STRCASESTR\" was never defined.
++Usually this means the macro was only invoked conditionally." >&5
++echo "$as_me: error: conditional \"NEED_OWN_STRCASESTR\" was never defined.
++Usually this means the macro was only invoked conditionally." >&2;}
++   { (exit 1); exit 1; }; }
++fi
++if test -z "${NEED_OWN_STRCASESTR_TRUE}" && test -z "${NEED_OWN_STRCASESTR_FALSE}"; then
++  { { echo "$as_me:$LINENO: error: conditional \"NEED_OWN_STRCASESTR\" was never defined.
++Usually this means the macro was only invoked conditionally." >&5
++echo "$as_me: error: conditional \"NEED_OWN_STRCASESTR\" was never defined.
++Usually this means the macro was only invoked conditionally." >&2;}
++   { (exit 1); exit 1; }; }
++fi
+ if test -z "${NEED_OWN_STRSEP_TRUE}" && test -z "${NEED_OWN_STRSEP_FALSE}"; then
+   { { echo "$as_me:$LINENO: error: conditional \"NEED_OWN_STRSEP\" was never defined.
+ Usually this means the macro was only invoked conditionally." >&5
+@@ -27708,6 +27839,8 @@
+ ENABLE_PINGER_FALSE!$ENABLE_PINGER_FALSE$ac_delim
+ USE_DELAY_POOLS_TRUE!$USE_DELAY_POOLS_TRUE$ac_delim
+ USE_DELAY_POOLS_FALSE!$USE_DELAY_POOLS_FALSE$ac_delim
++USE_ICAP_TRUE!$USE_ICAP_TRUE$ac_delim
++USE_ICAP_FALSE!$USE_ICAP_FALSE$ac_delim
+ USE_SNMP_TRUE!$USE_SNMP_TRUE$ac_delim
+ USE_SNMP_FALSE!$USE_SNMP_FALSE$ac_delim
+ SNMPLIB!$SNMPLIB$ac_delim
+@@ -27774,6 +27907,10 @@
+ USE_DEVPOLL_FALSE!$USE_DEVPOLL_FALSE$ac_delim
+ NEED_OWN_SNPRINTF_TRUE!$NEED_OWN_SNPRINTF_TRUE$ac_delim
+ NEED_OWN_SNPRINTF_FALSE!$NEED_OWN_SNPRINTF_FALSE$ac_delim
++NEED_OWN_STRNSTR_TRUE!$NEED_OWN_STRNSTR_TRUE$ac_delim
++NEED_OWN_STRNSTR_FALSE!$NEED_OWN_STRNSTR_FALSE$ac_delim
++NEED_OWN_STRCASESTR_TRUE!$NEED_OWN_STRCASESTR_TRUE$ac_delim
++NEED_OWN_STRCASESTR_FALSE!$NEED_OWN_STRCASESTR_FALSE$ac_delim
+ NEED_OWN_STRSEP_TRUE!$NEED_OWN_STRSEP_TRUE$ac_delim
+ NEED_OWN_STRSEP_FALSE!$NEED_OWN_STRSEP_FALSE$ac_delim
+ REGEXLIB!$REGEXLIB$ac_delim
+@@ -27784,7 +27921,7 @@
+ LTLIBOBJS!$LTLIBOBJS$ac_delim
+ _ACEOF
+ 
+-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 89; then
++  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 95; then
+     break
+   elif $ac_last_try; then
+     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+--- include/autoconf.h.in.orig	Sat Jun 23 23:51:56 2007
++++ include/autoconf.h.in	Mon Jul 16 22:21:25 2007
+@@ -457,6 +457,9 @@
+ /* Define to 1 if you have the <stdlib.h> header file. */
+ #undef HAVE_STDLIB_H
+ 
++/* Define to 1 if you have the `strcasestr' function. */
++#undef HAVE_STRCASESTR
++
+ /* Define to 1 if you have the `strerror' function. */
+ #undef HAVE_STRERROR
+ 
+@@ -466,6 +469,9 @@
+ /* Define to 1 if you have the <string.h> header file. */
+ #undef HAVE_STRING_H
+ 
++/* Define to 1 if you have the `strnstr' function. */
++#undef HAVE_STRNSTR
++
+ /* Define to 1 if you have the `strsep' function. */
+ #undef HAVE_STRSEP
+ 
+@@ -596,6 +602,9 @@
+ 
+ /* Some systems support __va_copy */
+ #undef HAVE___VA_COPY
++
++/* Content filtering via ICAP servers. */
++#undef HS_FEAT_ICAP
+ 
+ /* By default (for now anyway) Squid includes options which allows the cache
+    administrator to violate the HTTP protocol specification in terms of cache
+--- lib/Makefile.in.orig	Sat Jun 23 02:14:55 2007
++++ lib/Makefile.in	Mon Jul 16 22:21:39 2007
+@@ -62,20 +62,23 @@
+ am__libmiscutil_a_SOURCES_DIST = Array.c base64.c getfullhostname.c \
+ 	hash.c heap.c html_quote.c iso3307.c md5.c radix.c rfc1035.c \
+ 	rfc1123.c rfc1738.c rfc2617.c safe_inet_addr.c snprintf.c \
+-	splay.c Stack.c strsep.c stub_memaccount.c util.c uudecode.c \
+-	win32lib.c
++	splay.c Stack.c strnstr.c strcasestr.c strsep.c \
++	stub_memaccount.c util.c uudecode.c win32lib.c
+ @NEED_OWN_MD5_TRUE at am__objects_1 = md5.$(OBJEXT)
+ @NEED_OWN_SNPRINTF_TRUE at am__objects_2 = snprintf.$(OBJEXT)
+- at NEED_OWN_STRSEP_TRUE@am__objects_3 = strsep.$(OBJEXT)
+- at ENABLE_MINGW32SPECIFIC_TRUE@am__objects_4 = win32lib.$(OBJEXT)
++ at NEED_OWN_STRNSTR_TRUE@am__objects_3 = strnstr.$(OBJEXT)
++ at NEED_OWN_STRCASESTR_TRUE@am__objects_4 = strcasestr.$(OBJEXT)
++ at NEED_OWN_STRSEP_TRUE@am__objects_5 = strsep.$(OBJEXT)
++ at ENABLE_MINGW32SPECIFIC_TRUE@am__objects_6 = win32lib.$(OBJEXT)
+ am_libmiscutil_a_OBJECTS = Array.$(OBJEXT) base64.$(OBJEXT) \
+ 	getfullhostname.$(OBJEXT) hash.$(OBJEXT) heap.$(OBJEXT) \
+ 	html_quote.$(OBJEXT) iso3307.$(OBJEXT) $(am__objects_1) \
+ 	radix.$(OBJEXT) rfc1035.$(OBJEXT) rfc1123.$(OBJEXT) \
+ 	rfc1738.$(OBJEXT) rfc2617.$(OBJEXT) safe_inet_addr.$(OBJEXT) \
+ 	$(am__objects_2) splay.$(OBJEXT) Stack.$(OBJEXT) \
+-	$(am__objects_3) stub_memaccount.$(OBJEXT) util.$(OBJEXT) \
+-	uudecode.$(OBJEXT) $(am__objects_4)
++	$(am__objects_3) $(am__objects_4) $(am__objects_5) \
++	stub_memaccount.$(OBJEXT) util.$(OBJEXT) uudecode.$(OBJEXT) \
++	$(am__objects_6)
+ libmiscutil_a_OBJECTS = $(am_libmiscutil_a_OBJECTS)
+ libntlmauth_a_AR = $(AR) $(ARFLAGS)
+ libntlmauth_a_DEPENDENCIES = @LIBOBJS@
+@@ -189,6 +192,10 @@
+ NEED_OWN_MD5_TRUE = @NEED_OWN_MD5_TRUE@
+ NEED_OWN_SNPRINTF_FALSE = @NEED_OWN_SNPRINTF_FALSE@
+ NEED_OWN_SNPRINTF_TRUE = @NEED_OWN_SNPRINTF_TRUE@
++NEED_OWN_STRCASESTR_FALSE = @NEED_OWN_STRCASESTR_FALSE@
++NEED_OWN_STRCASESTR_TRUE = @NEED_OWN_STRCASESTR_TRUE@
++NEED_OWN_STRNSTR_FALSE = @NEED_OWN_STRNSTR_FALSE@
++NEED_OWN_STRNSTR_TRUE = @NEED_OWN_STRNSTR_TRUE@
+ NEED_OWN_STRSEP_FALSE = @NEED_OWN_STRSEP_FALSE@
+ NEED_OWN_STRSEP_TRUE = @NEED_OWN_STRSEP_TRUE@
+ NEGOTIATE_AUTH_HELPERS = @NEGOTIATE_AUTH_HELPERS@
+@@ -230,6 +237,8 @@
+ USE_DNSSERVER_TRUE = @USE_DNSSERVER_TRUE@
+ USE_EPOLL_FALSE = @USE_EPOLL_FALSE@
+ USE_EPOLL_TRUE = @USE_EPOLL_TRUE@
++USE_ICAP_FALSE = @USE_ICAP_FALSE@
++USE_ICAP_TRUE = @USE_ICAP_TRUE@
+ USE_KQUEUE_FALSE = @USE_KQUEUE_FALSE@
+ USE_KQUEUE_TRUE = @USE_KQUEUE_TRUE@
+ USE_POLL_FALSE = @USE_POLL_FALSE@
+@@ -287,6 +296,10 @@
+ target_alias = @target_alias@
+ @NEED_OWN_SNPRINTF_FALSE at SNPRINTFSOURCE = 
+ @NEED_OWN_SNPRINTF_TRUE at SNPRINTFSOURCE = snprintf.c
++ at NEED_OWN_STRNSTR_FALSE@STRNSTRSOURCE = 
++ at NEED_OWN_STRNSTR_TRUE@STRNSTRSOURCE = strnstr.c
++ at NEED_OWN_STRCASESTR_FALSE@STRCASESTRSOURCE = 
++ at NEED_OWN_STRCASESTR_TRUE@STRCASESTRSOURCE = strcasestr.c
+ @NEED_OWN_STRSEP_FALSE at STRSEPSOURCE = 
+ @NEED_OWN_STRSEP_TRUE at STRSEPSOURCE = strsep.c
+ @NEED_OWN_MD5_FALSE at MD5SOURCE = 
+@@ -331,6 +344,8 @@
+ 	$(SNPRINTFSOURCE) \
+ 	splay.c \
+ 	Stack.c \
++	$(STRNSTRSOURCE) \
++	$(STRCASESTRSOURCE) \
+ 	$(STRSEPSOURCE) \
+ 	stub_memaccount.c \
+ 	util.c \
+@@ -446,6 +461,8 @@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/snprintf.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/splay.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/sspwin32.Po at am__quote@
++ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/strcasestr.Po at am__quote@
++ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/strnstr.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/strsep.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/stub_memaccount.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/util.Po at am__quote@
+--- src/Makefile.in.orig	Sat Jun 23 02:14:56 2007
++++ src/Makefile.in	Mon Jul 16 22:21:33 2007
+@@ -91,14 +91,15 @@
+ 	globals.h gopher.c helper.c htcp.c http.c HttpStatusLine.c \
+ 	HttpHdrCc.c HttpHdrRange.c HttpHdrContRange.c HttpHeader.c \
+ 	HttpHeaderTools.c HttpBody.c HttpMsg.c HttpReply.c \
+-	HttpRequest.c icmp.c icp_v2.c icp_v3.c ident.c internal.c \
+-	ipc.c ipc_win32.c ipcache.c leakfinder.c locrewrite.c \
+-	logfile.c main.c mem.c MemPool.c MemBuf.c mime.c multicast.c \
+-	neighbors.c net_db.c Packer.c pconn.c peer_digest.c \
+-	peer_monitor.c peer_select.c peer_sourcehash.c peer_userhash.c \
+-	protos.h redirect.c referer.c refresh.c send-announce.c \
+-	snmp_core.c snmp_agent.c squid.h ssl.c ssl_support.c stat.c \
+-	StatHist.c String.c stmem.c store.c store_io.c store_client.c \
++	HttpRequest.c icap_common.c icap_reqmod.c icap_respmod.c \
++	icap_opt.c icmp.c icp_v2.c icp_v3.c ident.c internal.c ipc.c \
++	ipc_win32.c ipcache.c leakfinder.c locrewrite.c logfile.c \
++	main.c mem.c MemPool.c MemBuf.c mime.c multicast.c neighbors.c \
++	net_db.c Packer.c pconn.c peer_digest.c peer_monitor.c \
++	peer_select.c peer_sourcehash.c peer_userhash.c protos.h \
++	redirect.c referer.c refresh.c send-announce.c snmp_core.c \
++	snmp_agent.c squid.h ssl.c ssl_support.c stat.c StatHist.c \
++	String.c stmem.c store.c store_io.c store_client.c \
+ 	store_digest.c store_dir.c store_key_md5.c store_log.c \
+ 	store_rebuild.c store_swapin.c store_swapmeta.c \
+ 	store_swapout.c structs.h tools.c typedefs.h unlinkd.c url.c \
+@@ -115,14 +116,17 @@
+ @USE_DNSSERVER_FALSE at am__objects_3 = dns_internal.$(OBJEXT)
+ @USE_DNSSERVER_TRUE at am__objects_3 = dns.$(OBJEXT)
+ @ENABLE_HTCP_TRUE at am__objects_4 = htcp.$(OBJEXT)
+- at ENABLE_MINGW32SPECIFIC_FALSE@am__objects_5 = ipc.$(OBJEXT)
+- at ENABLE_MINGW32SPECIFIC_TRUE@am__objects_5 = ipc_win32.$(OBJEXT)
+- at MAKE_LEAKFINDER_TRUE@am__objects_6 = leakfinder.$(OBJEXT)
+- at USE_SNMP_TRUE@am__objects_7 = snmp_core.$(OBJEXT) \
++ at USE_ICAP_TRUE@am__objects_5 = icap_common.$(OBJEXT) \
++ at USE_ICAP_TRUE@	icap_reqmod.$(OBJEXT) icap_respmod.$(OBJEXT) \
++ at USE_ICAP_TRUE@	icap_opt.$(OBJEXT)
++ at ENABLE_MINGW32SPECIFIC_FALSE@am__objects_6 = ipc.$(OBJEXT)
++ at ENABLE_MINGW32SPECIFIC_TRUE@am__objects_6 = ipc_win32.$(OBJEXT)
++ at MAKE_LEAKFINDER_TRUE@am__objects_7 = leakfinder.$(OBJEXT)
++ at USE_SNMP_TRUE@am__objects_8 = snmp_core.$(OBJEXT) \
+ @USE_SNMP_TRUE@	snmp_agent.$(OBJEXT)
+- at ENABLE_SSL_TRUE@am__objects_8 = ssl_support.$(OBJEXT)
+- at ENABLE_UNLINKD_TRUE@am__objects_9 = unlinkd.$(OBJEXT)
+- at ENABLE_WIN32SPECIFIC_TRUE@am__objects_10 = win32.$(OBJEXT)
++ at ENABLE_SSL_TRUE@am__objects_9 = ssl_support.$(OBJEXT)
++ at ENABLE_UNLINKD_TRUE@am__objects_10 = unlinkd.$(OBJEXT)
++ at ENABLE_WIN32SPECIFIC_TRUE@am__objects_11 = win32.$(OBJEXT)
+ am_squid_OBJECTS = access_log.$(OBJEXT) acl.$(OBJEXT) asn.$(OBJEXT) \
+ 	authenticate.$(OBJEXT) cache_cf.$(OBJEXT) \
+ 	CacheDigest.$(OBJEXT) cache_manager.$(OBJEXT) carp.$(OBJEXT) \
+@@ -137,27 +141,27 @@
+ 	HttpHdrRange.$(OBJEXT) HttpHdrContRange.$(OBJEXT) \
+ 	HttpHeader.$(OBJEXT) HttpHeaderTools.$(OBJEXT) \
+ 	HttpBody.$(OBJEXT) HttpMsg.$(OBJEXT) HttpReply.$(OBJEXT) \
+-	HttpRequest.$(OBJEXT) icmp.$(OBJEXT) icp_v2.$(OBJEXT) \
+-	icp_v3.$(OBJEXT) ident.$(OBJEXT) internal.$(OBJEXT) \
+-	$(am__objects_5) ipcache.$(OBJEXT) $(am__objects_6) \
+-	locrewrite.$(OBJEXT) logfile.$(OBJEXT) main.$(OBJEXT) \
+-	mem.$(OBJEXT) MemPool.$(OBJEXT) MemBuf.$(OBJEXT) \
+-	mime.$(OBJEXT) multicast.$(OBJEXT) neighbors.$(OBJEXT) \
+-	net_db.$(OBJEXT) Packer.$(OBJEXT) pconn.$(OBJEXT) \
+-	peer_digest.$(OBJEXT) peer_monitor.$(OBJEXT) \
++	HttpRequest.$(OBJEXT) $(am__objects_5) icmp.$(OBJEXT) \
++	icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) ident.$(OBJEXT) \
++	internal.$(OBJEXT) $(am__objects_6) ipcache.$(OBJEXT) \
++	$(am__objects_7) locrewrite.$(OBJEXT) logfile.$(OBJEXT) \
++	main.$(OBJEXT) mem.$(OBJEXT) MemPool.$(OBJEXT) \
++	MemBuf.$(OBJEXT) mime.$(OBJEXT) multicast.$(OBJEXT) \
++	neighbors.$(OBJEXT) net_db.$(OBJEXT) Packer.$(OBJEXT) \
++	pconn.$(OBJEXT) peer_digest.$(OBJEXT) peer_monitor.$(OBJEXT) \
+ 	peer_select.$(OBJEXT) peer_sourcehash.$(OBJEXT) \
+ 	peer_userhash.$(OBJEXT) redirect.$(OBJEXT) referer.$(OBJEXT) \
+-	refresh.$(OBJEXT) send-announce.$(OBJEXT) $(am__objects_7) \
+-	ssl.$(OBJEXT) $(am__objects_8) stat.$(OBJEXT) \
++	refresh.$(OBJEXT) send-announce.$(OBJEXT) $(am__objects_8) \
++	ssl.$(OBJEXT) $(am__objects_9) stat.$(OBJEXT) \
+ 	StatHist.$(OBJEXT) String.$(OBJEXT) stmem.$(OBJEXT) \
+ 	store.$(OBJEXT) store_io.$(OBJEXT) store_client.$(OBJEXT) \
+ 	store_digest.$(OBJEXT) store_dir.$(OBJEXT) \
+ 	store_key_md5.$(OBJEXT) store_log.$(OBJEXT) \
+ 	store_rebuild.$(OBJEXT) store_swapin.$(OBJEXT) \
+ 	store_swapmeta.$(OBJEXT) store_swapout.$(OBJEXT) \
+-	tools.$(OBJEXT) $(am__objects_9) url.$(OBJEXT) urn.$(OBJEXT) \
++	tools.$(OBJEXT) $(am__objects_10) url.$(OBJEXT) urn.$(OBJEXT) \
+ 	useragent.$(OBJEXT) wais.$(OBJEXT) wccp.$(OBJEXT) \
+-	wccp2.$(OBJEXT) whois.$(OBJEXT) $(am__objects_10)
++	wccp2.$(OBJEXT) whois.$(OBJEXT) $(am__objects_11)
+ nodist_squid_OBJECTS = repl_modules.$(OBJEXT) auth_modules.$(OBJEXT) \
+ 	store_modules.$(OBJEXT) globals.$(OBJEXT) \
+ 	string_arrays.$(OBJEXT)
+@@ -282,6 +286,10 @@
+ NEED_OWN_MD5_TRUE = @NEED_OWN_MD5_TRUE@
+ NEED_OWN_SNPRINTF_FALSE = @NEED_OWN_SNPRINTF_FALSE@
+ NEED_OWN_SNPRINTF_TRUE = @NEED_OWN_SNPRINTF_TRUE@
++NEED_OWN_STRCASESTR_FALSE = @NEED_OWN_STRCASESTR_FALSE@
++NEED_OWN_STRCASESTR_TRUE = @NEED_OWN_STRCASESTR_TRUE@
++NEED_OWN_STRNSTR_FALSE = @NEED_OWN_STRNSTR_FALSE@
++NEED_OWN_STRNSTR_TRUE = @NEED_OWN_STRNSTR_TRUE@
+ NEED_OWN_STRSEP_FALSE = @NEED_OWN_STRSEP_FALSE@
+ NEED_OWN_STRSEP_TRUE = @NEED_OWN_STRSEP_TRUE@
+ NEGOTIATE_AUTH_HELPERS = @NEGOTIATE_AUTH_HELPERS@
+@@ -323,6 +331,8 @@
+ USE_DNSSERVER_TRUE = @USE_DNSSERVER_TRUE@
+ USE_EPOLL_FALSE = @USE_EPOLL_FALSE@
+ USE_EPOLL_TRUE = @USE_EPOLL_TRUE@
++USE_ICAP_FALSE = @USE_ICAP_FALSE@
++USE_ICAP_TRUE = @USE_ICAP_TRUE@
+ USE_KQUEUE_FALSE = @USE_KQUEUE_FALSE@
+ USE_KQUEUE_TRUE = @USE_KQUEUE_TRUE@
+ USE_POLL_FALSE = @USE_POLL_FALSE@
+@@ -378,6 +388,8 @@
+ sharedstatedir = @sharedstatedir@
+ sysconfdir = @sysconfdir@
+ target_alias = @target_alias@
++ at USE_ICAP_FALSE@ICAPSOURCE = 
++ at USE_ICAP_TRUE@ICAPSOURCE = icap_common.c icap_reqmod.c icap_respmod.c icap_opt.c
+ @USE_DNSSERVER_FALSE at DNSSOURCE = dns_internal.c
+ @USE_DNSSERVER_TRUE at DNSSOURCE = dns.c
+ @USE_DNSSERVER_FALSE at DNSSERVER = 
+@@ -483,6 +495,7 @@
+ 	HttpMsg.c \
+ 	HttpReply.c \
+ 	HttpRequest.c \
++	$(ICAPSOURCE) \
+ 	icmp.c \
+ 	icp_v2.c \
+ 	icp_v3.c \
+@@ -802,6 +815,10 @@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/helper.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/htcp.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/http.Po at am__quote@
++ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/icap_common.Po at am__quote@
++ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/icap_opt.Po at am__quote@
++ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/icap_reqmod.Po at am__quote@
++ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/icap_respmod.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/icmp.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/icp_v2.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/icp_v3.Po at am__quote@
--- www/squid/files/follow_xff-2.5.patch
+++ /dev/null
@@ -1,411 +0,0 @@
-! This is a reduced part of the original follow-XFF patchset from
-! devel.squid-cache.org for use with the FreeBSD squid-2.5 port.
-Index: src/acl.c
---- src/acl.c	13 May 2003 02:14:12 -0000	1.43.2.16
-+++ src/acl.c	23 Nov 2003 14:20:12 -0000
-@@ -2001,6 +2001,11 @@
-     cbdataLock(A);
-     if (request != NULL) {
- 	checklist->request = requestLink(request);
-+#if FOLLOW_X_FORWARDED_FOR
-+	if (Config.onoff.acl_uses_indirect_client) {
-+	    checklist->src_addr = request->indirect_client_addr;
-+	} else
-+#endif /* FOLLOW_X_FORWARDED_FOR */
- 	checklist->src_addr = request->client_addr;
- 	checklist->my_addr = request->my_addr;
- 	checklist->my_port = request->my_port;
-Index: src/cf.data.pre
---- src/cf.data.pre	7 Nov 2003 03:14:30 -0000	1.49.2.46
-+++ src/cf.data.pre	23 Nov 2003 14:20:17 -0000
-@@ -2065,6 +2065,92 @@
- NOCOMMENT_END
- DOC_END
- 
-+NAME: follow_x_forwarded_for
-+TYPE: acl_access
-+IFDEF: FOLLOW_X_FORWARDED_FOR
-+LOC: Config.accessList.followXFF
-+DEFAULT: none
-+DEFAULT_IF_NONE: deny all
-+DOC_START
-+	Allowing or Denying the X-Forwarded-For header to be followed to
-+	find the original source of a request.
-+
-+	Requests may pass through a chain of several other proxies
-+	before reaching us.  The X-Forwarded-For header will contain a
-+	comma-separated list of the IP addresses in the chain, with the
-+	rightmost address being the most recent.
-+
-+	If a request reaches us from a source that is allowed by this
-+	configuration item, then we consult the X-Forwarded-For header
-+	to see where that host received the request from.  If the
-+	X-Forwarded-For header contains multiple addresses, and if
-+	acl_uses_indirect_client is on, then we continue backtracking
-+	until we reach an address for which we are not allowed to
-+	follow the X-Forwarded-For header, or until we reach the first
-+	address in the list.  (If acl_uses_indirect_client is off, then
-+	it's impossible to backtrack through more than one level of
-+	X-Forwarded-For addresses.)
-+
-+	The end result of this process is an IP address that we will
-+	refer to as the indirect client address.  This address may
-+	be treated as the client address for access control, delay
-+	pools and logging, depending on the acl_uses_indirect_client,
-+	delay_pool_uses_indirect_client and log_uses_indirect_client
-+	options.
-+
-+	SECURITY CONSIDERATIONS:
-+
-+		Any host for which we follow the X-Forwarded-For header
-+		can place incorrect information in the header, and Squid
-+		will use the incorrect information as if it were the
-+		source address of the request.  This may enable remote
-+		hosts to bypass any access control restrictions that are
-+		based on the client's source addresses.
-+
-+	For example:
-+
-+		acl localhost src 127.0.0.1
-+		acl my_other_proxy srcdomain .proxy.example.com
-+		follow_x_forwarded_for allow localhost
-+		follow_x_forwarded_for allow my_other_proxy
-+DOC_END
-+
-+NAME: acl_uses_indirect_client
-+COMMENT: on|off
-+TYPE: onoff
-+IFDEF: FOLLOW_X_FORWARDED_FOR
-+DEFAULT: on
-+LOC: Config.onoff.acl_uses_indirect_client
-+DOC_START
-+	Controls whether the indirect client address
-+	(see follow_x_forwarded_for) is used instead of the
-+	direct client address in acl matching.
-+DOC_END
-+
-+NAME: delay_pool_uses_indirect_client
-+COMMENT: on|off
-+TYPE: onoff
-+IFDEF: FOLLOW_X_FORWARDED_FOR && DELAY_POOLS
-+DEFAULT: on
-+LOC: Config.onoff.delay_pool_uses_indirect_client
-+DOC_START
-+	Controls whether the indirect client address
-+	(see follow_x_forwarded_for) is used instead of the
-+	direct client address in delay pools.
-+DOC_END
-+
-+NAME: log_uses_indirect_client
-+COMMENT: on|off
-+TYPE: onoff
-+IFDEF: FOLLOW_X_FORWARDED_FOR
-+DEFAULT: on
-+LOC: Config.onoff.log_uses_indirect_client
-+DOC_START
-+	Controls whether the indirect client address
-+	(see follow_x_forwarded_for) is used instead of the
-+	direct client address in the access log.
-+DOC_END
-+
- NAME: http_access
- TYPE: acl_access
- LOC: Config.accessList.http
-Index: src/client_side.c
---- src/client_side.c	2 Sep 2003 02:13:45 -0000	1.47.2.39
-+++ src/client_side.c	23 Nov 2003 14:20:22 -0000
-@@ -109,6 +109,11 @@
- #if USE_IDENT
- static IDCB clientIdentDone;
- #endif
-+#if FOLLOW_X_FORWARDED_FOR
-+static void clientFollowXForwardedForStart(void *data);
-+static void clientFollowXForwardedForNext(void *data);
-+static void clientFollowXForwardedForDone(int answer, void *data);
-+#endif /* FOLLOW_X_FORWARDED_FOR */
- static int clientOnlyIfCached(clientHttpRequest * http);
- static STCB clientSendMoreData;
- static STCB clientCacheHit;
-@@ -177,10 +182,179 @@
-     return ch;
- }
- 
-+#if FOLLOW_X_FORWARDED_FOR
-+/*
-+ * clientFollowXForwardedForStart() copies the X-Forwarded-For
-+ * header into x_forwarded_for_iterator and passes control to
-+ * clientFollowXForwardedForNext().
-+ *
-+ * clientFollowXForwardedForNext() checks the indirect_client_addr
-+ * against the followXFF ACL and passes the result to
-+ * clientFollowXForwardedForDone().
-+ *
-+ * clientFollowXForwardedForDone() either grabs the next address
-+ * from the tail of x_forwarded_for_iterator and loops back to
-+ * clientFollowXForwardedForNext(), or cleans up and passes control to
-+ * clientAccessCheck().
-+ */
-+
-+static void
-+clientFollowXForwardedForStart(void *data)
-+{
-+    clientHttpRequest *http = data;
-+    request_t *request = http->request;
-+    if (Config.accessList.followXFF
-+	&& httpHeaderHas(&request->header, HDR_X_FORWARDED_FOR))
-+    {
-+	request->x_forwarded_for_iterator = httpHeaderGetList(
-+			&request->header, HDR_X_FORWARDED_FOR);
-+	debug(33, 5) ("clientFollowXForwardedForStart: indirect_client_addr=%s XFF='%s'\n",
-+			inet_ntoa(request->indirect_client_addr),
-+			strBuf(request->x_forwarded_for_iterator));
-+	clientFollowXForwardedForNext(http);
-+    } else {
-+	/* not configured to follow X-Forwarded-For, or nothing to follow */
-+	debug(33, 5) ("clientFollowXForwardedForStart: nothing to do\n");
-+	clientFollowXForwardedForDone(-1, http);
-+    }
-+}
-+
-+static void
-+clientFollowXForwardedForNext(void *data)
-+{
-+    clientHttpRequest *http = data;
-+    request_t *request = http->request;
-+    debug(33, 5) ("clientFollowXForwardedForNext: indirect_client_addr=%s XFF='%s'\n",
-+		    inet_ntoa(request->indirect_client_addr),
-+		    strBuf(request->x_forwarded_for_iterator));
-+    if (strLen(request->x_forwarded_for_iterator) != 0) {
-+	/* check the acl to see whether to believe the X-Forwarded-For header */
-+	http->acl_checklist = clientAclChecklistCreate(
-+			Config.accessList.followXFF, http);
-+	aclNBCheck(http->acl_checklist, clientFollowXForwardedForDone, http);
-+    } else {
-+	/* nothing left to follow */
-+	debug(33, 5) ("clientFollowXForwardedForNext: nothing more to do\n");
-+	clientFollowXForwardedForDone(-1, http);
-+    }
-+}
-+
-+static void
-+clientFollowXForwardedForDone(int answer, void *data)
-+{
-+    clientHttpRequest *http = data;
-+    request_t *request = http->request;
-+    /*
-+     * answer should be be ACCESS_ALLOWED or ACCESS_DENIED if we are
-+     * called as a result of ACL checks, or -1 if we are called when
-+     * there's nothing left to do.
-+     */
-+    if (answer == ACCESS_ALLOWED) {
-+	/*
-+	 * The IP address currently in request->indirect_client_addr
-+	 * is trusted to use X-Forwarded-For.  Remove the last
-+	 * comma-delimited element from x_forwarded_for_iterator and use
-+	 * it to to replace indirect_client_addr, then repeat the cycle.
-+	 */
-+	const char *p;
-+	const char *asciiaddr;
-+	int l;
-+	struct in_addr addr;
-+	debug(33, 5) ("clientFollowXForwardedForDone: indirect_client_addr=%s is trusted\n",
-+			inet_ntoa(request->indirect_client_addr));
-+	p = strBuf(request->x_forwarded_for_iterator);
-+	l = strLen(request->x_forwarded_for_iterator);
-+
-+	/*
-+	 * XXX x_forwarded_for_iterator should really be a list of
-+	 * IP addresses, but it's a String instead.  We have to
-+	 * walk backwards through the String, biting off the last
-+	 * comma-delimited part each time.  As long as the data is in
-+	 * a String, we should probably implement and use a variant of
-+	 * strListGetItem() that walks backwards instead of forwards
-+	 * through a comma-separated list.  But we don't even do that;
-+	 * we just do the work in-line here.
-+	 */
-+	/* skip trailing space and commas */
-+	while (l > 0 && (p[l-1] == ',' || xisspace(p[l-1])))
-+	    l--;
-+	strCut(request->x_forwarded_for_iterator, l);
-+	/* look for start of last item in list */
-+	while (l > 0 && ! (p[l-1] == ',' || xisspace(p[l-1])))
-+	    l--;
-+	asciiaddr = p+l;
-+	if (inet_aton(asciiaddr, &addr) == 0) {
-+	    /* the address is not well formed; do not use it */
-+	    debug(33, 3) ("clientFollowXForwardedForDone: malformed address '%s'\n",
-+			    asciiaddr);
-+	    goto done;
-+	}
-+	debug(33, 3) ("clientFollowXForwardedForDone: changing indirect_client_addr from %s to '%s'\n",
-+		    inet_ntoa(request->indirect_client_addr),
-+		    asciiaddr);
-+	request->indirect_client_addr = addr;
-+	strCut(request->x_forwarded_for_iterator, l);
-+	if (! Config.onoff.acl_uses_indirect_client) {
-+	    /*
-+	     * If acl_uses_indirect_client is off, then it's impossible
-+	     * to follow more than one level of X-Forwarded-For.
-+	     */
-+	    goto done;
-+	}
-+	clientFollowXForwardedForNext(http);
-+	return;
-+    } else if (answer == ACCESS_DENIED) {
-+	debug(33, 5) ("clientFollowXForwardedForDone: indirect_client_addr=%s not trusted\n",
-+			inet_ntoa(request->indirect_client_addr));
-+    } else {
-+	debug(33, 5) ("clientFollowXForwardedForDone: indirect_client_addr=%s nothing more to do\n",
-+			inet_ntoa(request->indirect_client_addr));
-+    }
-+done:
-+    /* clean up, and pass control to clientAccessCheck */
-+    debug(33, 6) ("clientFollowXForwardedForDone: cleanup\n");
-+    if (Config.onoff.log_uses_indirect_client) {
-+	/*
-+	 * Ensure that the access log shows the indirect client
-+	 * instead of the direct client.
-+	 */
-+	ConnStateData *conn = http->conn;
-+	conn->log_addr = request->indirect_client_addr;
-+	conn->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr;
-+	debug(33, 3) ("clientFollowXForwardedForDone: setting log_addr=%s\n",
-+			inet_ntoa(conn->log_addr));
-+    }
-+    stringClean(&request->x_forwarded_for_iterator);
-+    request->flags.done_follow_x_forwarded_for = 1;
-+    http->acl_checklist = NULL; /* XXX do we need to aclChecklistFree() ? */
-+    clientAccessCheck(http);
-+}
-+#endif /* FOLLOW_X_FORWARDED_FOR */
-+
- void
- clientAccessCheck(void *data)
- {
-     clientHttpRequest *http = data;
-+#if FOLLOW_X_FORWARDED_FOR
-+    if (! http->request->flags.done_follow_x_forwarded_for
-+        && httpHeaderHas(&http->request->header, HDR_X_FORWARDED_FOR))
-+    {
-+	/*
-+	 * There's an X-ForwardedFor header and we haven't yet tried
-+	 * to follow it to find the indirect_client_addr.  Follow it now.
-+	 * clientFollowXForwardedForDone() will eventually pass control
-+	 * back to us.
-+	 *
-+	 * XXX perhaps our caller should have called
-+	 *     clientFollowXForwardedForStart instead.  Then we wouldn't
-+	 *     need to do this little dance transferring control over
-+	 *     there and then back here, and we wouldn't need the
-+	 *     done_follow_x_forwarded_for flag.
-+	 */
-+	clientFollowXForwardedForStart(data);
-+	return;
-+    }
-+#endif /* FOLLOW_X_FORWARDED_FOR */
-     if (checkAccelOnly(http)) {
- 	/* deny proxy requests in accel_only mode */
- 	debug(33, 1) ("clientAccessCheck: proxy request denied in accel_only mode\n");
-@@ -325,6 +499,9 @@
- 	new_request->http_ver = old_request->http_ver;
- 	httpHeaderAppend(&new_request->header, &old_request->header);
- 	new_request->client_addr = old_request->client_addr;
-+#if FOLLOW_X_FORWARDED_FOR
-+	new_request->indirect_client_addr = old_request->indirect_client_addr;
-+#endif /* FOLLOW_X_FORWARDED_FOR */
- 	new_request->my_addr = old_request->my_addr;
- 	new_request->my_port = old_request->my_port;
- 	new_request->flags.redirected = 1;
-@@ -3051,6 +3228,9 @@
- 	    safe_free(http->log_uri);
- 	    http->log_uri = xstrdup(urlCanonicalClean(request));
- 	    request->client_addr = conn->peer.sin_addr;
-+#if FOLLOW_X_FORWARDED_FOR
-+	    request->indirect_client_addr = request->client_addr;
-+#endif /* FOLLOW_X_FORWARDED_FOR */
- 	    request->my_addr = conn->me.sin_addr;
- 	    request->my_port = ntohs(conn->me.sin_port);
- 	    request->http_ver = http->http_ver;
-Index: src/delay_pools.c
---- src/delay_pools.c	19 Jun 2003 02:13:57 -0000	1.5.54.6
-+++ src/delay_pools.c	23 Nov 2003 14:20:23 -0000
-@@ -318,6 +318,11 @@
-     r = http->request;
- 
-     memset(&ch, '\0', sizeof(ch));
-+#if FOLLOW_X_FORWARDED_FOR
-+    if (Config.onoff.delay_pool_uses_indirect_client) {
-+	ch.src_addr = r->indirect_client_addr;
-+    } else
-+#endif /* FOLLOW_X_FORWARDED_FOR */
-     ch.src_addr = r->client_addr;
-     ch.my_addr = r->my_addr;
-     ch.my_port = r->my_port;
-*** src/structs.h.orig	Sun Jun 26 12:45:58 2005
---- src/structs.h	Sun Jun 26 12:48:45 2005
-***************
-*** 610,615 ****
---- 610,620 ----
-  	int accel_uses_host_header;
-  	int accel_no_pmtu_disc;
-  	int global_internal_static;
-+ #if FOLLOW_X_FORWARDED_FOR
-+ 	int acl_uses_indirect_client;
-+ 	int delay_pool_uses_indirect_client;
-+ 	int log_uses_indirect_client;
-+ #endif /* FOLLOW_X_FORWARDED_FOR */
-      } onoff;
-      acl *aclList;
-      struct {
-***************
-*** 631,636 ****
---- 636,644 ----
-  	acl_access *reply;
-  	acl_address *outgoing_address;
-  	acl_tos *outgoing_tos;
-+ #if FOLLOW_X_FORWARDED_FOR
-+ 	acl_access *followXFF;
-+ #endif /* FOLLOW_X_FORWARDED_FOR */
-      } accessList;
-      acl_deny_info_list *denyInfoList;
-      struct _authConfig {
-***************
-*** 1623,1628 ****
---- 1631,1641 ----
-      unsigned int body_sent:1;
-      unsigned int reset_tcp:1;
-      unsigned int must_keepalive:1;
-+ #if FOLLOW_X_FORWARDED_FOR
-+     /* XXX this flag could be eliminated;
-+      * see comments in clientAccessCheck */
-+     unsigned int done_follow_x_forwarded_for;
-+ #endif /* FOLLOW_X_FORWARDED_FOR */
-  };
-  
-  struct _link_list {
-***************
-*** 1666,1671 ****
---- 1679,1687 ----
-      int max_forwards;
-      /* these in_addr's could probably be sockaddr_in's */
-      struct in_addr client_addr;
-+ #if FOLLOW_X_FORWARDED_FOR
-+     struct in_addr indirect_client_addr; /* after following X-Forwarded-For */
-+ #endif /* FOLLOW_X_FORWARDED_FOR */
-      struct in_addr my_addr;
-      unsigned short my_port;
-      HttpHeader header;
-***************
-*** 1677,1682 ****
---- 1693,1703 ----
-      const char *vary_headers;	/* Used when varying entities are detected. Changes how the store key is calculated */
-      BODY_HANDLER *body_reader;
-      void *body_reader_data;
-+ #if FOLLOW_X_FORWARDED_FOR
-+     /* XXX a list of IP addresses would be a better data structure
-+      * than this String */
-+     String x_forwarded_for_iterator;
-+ #endif /* FOLLOW_X_FORWARDED_FOR */
-  };
-  
-  struct _cachemgr_passwd {
--- www/squid/files/icap-2.5-bootstrap.patch
+++ /dev/null
@@ -1,422 +0,0 @@
-Patch 2 of 2 to integrate the icap-2_5 branch into the FreeBSD squid port.
-
-Created by Thomas-Martin Seck <tmseck at netcologne.de>.
-
-This patch simulates the autotools bootstrap necessary after applying the
-ICAP patchset.
-
-Please see icap-2.5-core.patch for further information.
-
-Patch last updated: 2005-12-17
-
---- configure.orig	Sat Oct 22 11:56:01 2005
-+++ configure	Sat Dec 17 17:45:21 2005
-@@ -70,6 +70,8 @@
- ac_help="$ac_help
-   --enable-delay-pools    Enable delay pools to limit bandwidth usage"
- ac_help="$ac_help
-+  --enable-icap-support   	   Enable iCAP client capability"
-+ac_help="$ac_help
-   --enable-useragent-log  Enable logging of User-Agent header"
- ac_help="$ac_help
-   --enable-referer-log    Enable logging of Referer header"
-@@ -2170,6 +2172,38 @@
- 
- 
- 
-+
-+if false; then
-+  USE_ICAP_TRUE=
-+  USE_ICAP_FALSE='#'
-+else
-+  USE_ICAP_TRUE='#'
-+  USE_ICAP_FALSE=
-+fi
-+# Check whether --enable-icap-support or --disable-icap-support was given.
-+if test "${enable_icap_support+set}" = set; then
-+  enableval="$enable_icap_support"
-+   if test "$enableval" = "yes" ; then
-+    echo "ICAP support enabled"
-+    cat >> confdefs.h <<\EOF
-+#define HS_FEAT_ICAP 1
-+EOF
-+
-+    
-+
-+if true; then
-+  USE_ICAP_TRUE=
-+  USE_ICAP_FALSE='#'
-+else
-+  USE_ICAP_TRUE='#'
-+  USE_ICAP_FALSE=
-+fi
-+  fi
-+
-+fi
-+
-+
-+
- # Check whether --enable-useragent-log or --disable-useragent-log was given.
- if test "${enable_useragent_log+set}" = set; then
-   enableval="$enable_useragent_log"
-@@ -7428,14 +7462,14 @@
-         fi
-     ;;
-     esac
--    echo $ac_n "checking for main in -lpthread""... $ac_c" 1>&6
--echo "configure:7433: checking for main in -lpthread" >&5
-+    echo $ac_n "checking for main in -pthread""... $ac_c" 1>&6
-+echo "configure:7433: checking for main in -pthread" >&5
- ac_lib_var=`echo pthread'_'main | sed 'y%./+-%__p_%'`
- if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
-   echo $ac_n "(cached) $ac_c" 1>&6
- else
-   ac_save_LIBS="$LIBS"
--LIBS="-lpthread  $LIBS"
-+LIBS="-pthread  $LIBS"
- cat > conftest.$ac_ext <<EOF
- #line 7441 "configure"
- #include "confdefs.h"
-@@ -7465,7 +7499,7 @@
- #define $ac_tr_lib 1
- EOF
- 
--  LIBS="-lpthread $LIBS"
-+  LIBS="-pthread $LIBS"
- 
- else
-   echo "$ac_t""no" 1>&6
-@@ -7769,6 +7803,8 @@
- 	srand48 \
- 	srandom \
- 	statfs \
-+	strnstr \
-+	strcasestr \
- 	strtoll \
- 	sysconf \
- 	syslog \
-@@ -7898,6 +7934,50 @@
- fi
- fi
- 
-+
-+if false; then
-+  NEED_OWN_STRNSTR_TRUE=
-+  NEED_OWN_STRNSTR_FALSE='#'
-+else
-+  NEED_OWN_STRNSTR_TRUE='#'
-+  NEED_OWN_STRNSTR_FALSE=
-+fi
-+if test "$ac_cv_func_strnstr" = "no" || test "$ac_cv_func_vstrnstr" = "no" ; then
-+  
-+
-+if true; then
-+  NEED_OWN_STRNSTR_TRUE=
-+  NEED_OWN_STRNSTR_FALSE='#'
-+else
-+  NEED_OWN_STRNSTR_TRUE='#'
-+  NEED_OWN_STRNSTR_FALSE=
-+fi
-+fi
-+
-+
-+
-+if false; then
-+  NEED_OWN_STRCASESTR_TRUE=
-+  NEED_OWN_STRCASESTR_FALSE='#'
-+else
-+  NEED_OWN_STRCASESTR_TRUE='#'
-+  NEED_OWN_STRCASESTR_FALSE=
-+fi
-+if test "$ac_cv_func_strcasestr" = "no" || test "$ac_cv_func_vstrcasestr" = "no"; then
-+  
-+
-+if true; then
-+  NEED_OWN_STRCASESTR_TRUE=
-+  NEED_OWN_STRCASESTR_FALSE='#'
-+else
-+  NEED_OWN_STRCASESTR_TRUE='#'
-+  NEED_OWN_STRCASESTR_FALSE=
-+fi
-+fi
-+
-+
-+
-+
- echo $ac_n "checking if va_copy is implemented""... $ac_c" 1>&6
- echo "configure:7903: checking if va_copy is implemented" >&5
- if eval "test \"`echo '$''{'ac_cv_func_va_copy'+set}'`\" = set"; then
-@@ -9072,6 +9152,8 @@
- s%@ENABLE_PINGER_FALSE@%$ENABLE_PINGER_FALSE%g
- s%@USE_DELAY_POOLS_TRUE@%$USE_DELAY_POOLS_TRUE%g
- s%@USE_DELAY_POOLS_FALSE@%$USE_DELAY_POOLS_FALSE%g
-+s%@USE_ICAP_TRUE@%$USE_ICAP_TRUE%g
-+s%@USE_ICAP_FALSE@%$USE_ICAP_FALSE%g
- s%@USE_SNMP_TRUE@%$USE_SNMP_TRUE%g
- s%@USE_SNMP_FALSE@%$USE_SNMP_FALSE%g
- s%@SNMPLIB@%$SNMPLIB%g
-@@ -9118,6 +9200,10 @@
- s%@LIB_LBER@%$LIB_LBER%g
- s%@NEED_OWN_SNPRINTF_TRUE@%$NEED_OWN_SNPRINTF_TRUE%g
- s%@NEED_OWN_SNPRINTF_FALSE@%$NEED_OWN_SNPRINTF_FALSE%g
-+s%@NEED_OWN_STRNSTR_TRUE@%$NEED_OWN_STRNSTR_TRUE%g
-+s%@NEED_OWN_STRNSTR_FALSE@%$NEED_OWN_STRNSTR_FALSE%g
-+s%@NEED_OWN_STRCASESTR_TRUE@%$NEED_OWN_STRCASESTR_TRUE%g
-+s%@NEED_OWN_STRCASESTR_FALSE@%$NEED_OWN_STRCASESTR_FALSE%g
- s%@REGEXLIB@%$REGEXLIB%g
- s%@LIBREGEX@%$LIBREGEX%g
- s%@LIBOBJS@%$LIBOBJS%g
---- include/autoconf.h.in.orig	Tue Sep 13 02:12:34 2005
-+++ include/autoconf.h.in	Sat Dec 17 17:45:21 2005
-@@ -124,6 +124,11 @@
-  */
- #undef DELAY_POOLS
- 
-+/* 
-+ * ICAP - Internet Content Adaptation Protocol
-+ */
-+#undef HS_FEAT_ICAP
-+
- /*
-  * If you want to log User-Agent request header values, define this.
-  * By default, they are written to useragent.log in the Squid log
-@@ -574,6 +579,12 @@
- 
- /* Define if you have the statfs function.  */
- #undef HAVE_STATFS
-+
-+/* Define if you have the strcasestr function. */
-+#undef HAVE_STRCASESTR
-+
-+/* Define if you have the strnstr function. */
-+#undef HAVE_STRNSTR
- 
- /* Define if you have the strerror function.  */
- #undef HAVE_STRERROR
---- lib/Makefile.in.orig	Wed Sep 28 22:57:20 2005
-+++ lib/Makefile.in	Sat Dec 17 17:45:21 2005
-@@ -123,6 +123,13 @@
- 
- @NEED_OWN_SNPRINTF_TRUE at SNPRINTFSOURCE = snprintf.c
- @NEED_OWN_SNPRINTF_FALSE at SNPRINTFSOURCE = 
-+
-+ at NEED_OWN_STRNSTR_TRUE@STRNSTRSOURCE = strnstr.c
-+ at NEED_OWN_STRNSTR_FALSE@STRNSTRSOURCE = 
-+
-+ at NEED_OWN_STRCASESTR_TRUE@STRCASESTRSOURCE = strcasestr.c
-+ at NEED_OWN_STRCASESTR_FALSE@STRCASESTRSOURCE = 
-+
- @NEED_OWN_MD5_TRUE at MD5SOURCE = md5.c
- @NEED_OWN_MD5_FALSE at MD5SOURCE = 
- 
-@@ -158,6 +165,8 @@
- 	$(SNPRINTFSOURCE) \
- 	splay.c \
- 	Stack.c \
-+	$(STRNSTRSOURCE) \
-+	$(STRCASESTRSOURCE) \
- 	stub_memaccount.c \
- 	util.c \
- 	uudecode.c
-@@ -196,13 +205,18 @@
- @NEED_OWN_MD5_FALSE at am__objects_1 =
- @NEED_OWN_SNPRINTF_FALSE at am__objects_2 =
- @NEED_OWN_SNPRINTF_TRUE at am__objects_2 = snprintf.$(OBJEXT)
-+ at NEED_OWN_STRNSTR_FALSE@am__objects_3 =
-+ at NEED_OWN_STRNSTR_TRUE@am__objects_3 = strnstr.$(OBJEXT)
-+ at NEED_OWN_STRCASESTR_TRUE@am__objects_4 = strcasestr.$(OBJEXT)
-+ at NEED_OWN_STRCASESTR_FALSE@am__objects_4 =
- am_libmiscutil_a_OBJECTS = Array.$(OBJEXT) base64.$(OBJEXT) \
- 	getfullhostname.$(OBJEXT) hash.$(OBJEXT) heap.$(OBJEXT) \
- 	html_quote.$(OBJEXT) iso3307.$(OBJEXT) $(am__objects_1) \
- 	radix.$(OBJEXT) rfc1035.$(OBJEXT) rfc1123.$(OBJEXT) \
- 	rfc1738.$(OBJEXT) rfc2617.$(OBJEXT) safe_inet_addr.$(OBJEXT) \
- 	$(am__objects_2) splay.$(OBJEXT) Stack.$(OBJEXT) \
--	stub_memaccount.$(OBJEXT) util.$(OBJEXT) uudecode.$(OBJEXT)
-+	$(am__objects_3) $(am__objects_4) stub_memaccount.$(OBJEXT) \
-+	util.$(OBJEXT) uudecode.$(OBJEXT)
- libmiscutil_a_OBJECTS = $(am_libmiscutil_a_OBJECTS)
- libntlmauth_a_AR = $(AR) cru
- libntlmauth_a_DEPENDENCIES = @LIBOBJS@
-@@ -224,15 +238,16 @@
- @AMDEP_TRUE@	$(DEPDIR)/dlmalloc.Po $(DEPDIR)/drand48.Po \
- @AMDEP_TRUE@	$(DEPDIR)/getfullhostname.Po $(DEPDIR)/hash.Po \
- @AMDEP_TRUE@	$(DEPDIR)/heap.Po $(DEPDIR)/html_quote.Po \
-- at AMDEP_TRUE@	$(DEPDIR)/inet_ntoa.Po $(DEPDIR)/initgroups.Po \
-- at AMDEP_TRUE@	$(DEPDIR)/iso3307.Po $(DEPDIR)/md5.Po \
-- at AMDEP_TRUE@	$(DEPDIR)/ntlmauth.Po $(DEPDIR)/radix.Po \
-- at AMDEP_TRUE@	$(DEPDIR)/rfc1035.Po $(DEPDIR)/rfc1123.Po \
-- at AMDEP_TRUE@	$(DEPDIR)/rfc1738.Po $(DEPDIR)/rfc2617.Po \
-- at AMDEP_TRUE@	$(DEPDIR)/safe_inet_addr.Po $(DEPDIR)/snprintf.Po \
-- at AMDEP_TRUE@	$(DEPDIR)/splay.Po $(DEPDIR)/strerror.Po \
-- at AMDEP_TRUE@	$(DEPDIR)/stub_memaccount.Po $(DEPDIR)/tempnam.Po \
-- at AMDEP_TRUE@	$(DEPDIR)/util.Po $(DEPDIR)/uudecode.Po
-+ at AMDEP_TRUE@	$(DEPDIR)/inet_ntoa.Po $(DEPDIR)/iso3307.Po \
-+ at AMDEP_TRUE@	$(DEPDIR)/md5.Po $(DEPDIR)/ntlmauth.Po \
-+ at AMDEP_TRUE@	$(DEPDIR)/radix.Po $(DEPDIR)/rfc1035.Po \
-+ at AMDEP_TRUE@	$(DEPDIR)/rfc1123.Po $(DEPDIR)/rfc1738.Po \
-+ at AMDEP_TRUE@	$(DEPDIR)/rfc2617.Po $(DEPDIR)/safe_inet_addr.Po \
-+ at AMDEP_TRUE@	$(DEPDIR)/snprintf.Po $(DEPDIR)/splay.Po \
-+ at AMDEP_TRUE@	$(DEPDIR)/strcasestr.Po $(DEPDIR)/strerror.Po \
-+ at AMDEP_TRUE@	$(DEPDIR)/strnstr.Po $(DEPDIR)/stub_memaccount.Po \
-+ at AMDEP_TRUE@	$(DEPDIR)/tempnam.Po $(DEPDIR)/util.Po \
-+ at AMDEP_TRUE@	$(DEPDIR)/uudecode.Po
- COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- 	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
- CCLD = $(CC)
-@@ -241,8 +256,8 @@
- DIST_SOURCES = $(libdlmalloc_a_SOURCES) $(libmiscutil_a_SOURCES) \
- 	$(EXTRA_libmiscutil_a_SOURCES) $(libntlmauth_a_SOURCES) \
- 	$(libregex_a_SOURCES)
--DIST_COMMON = Makefile.am Makefile.in drand48.c inet_ntoa.c \
--	initgroups.c strerror.c tempnam.c
-+DIST_COMMON = Makefile.am Makefile.in drand48.c inet_ntoa.c strerror.c \
-+	tempnam.c
- SOURCES = $(libdlmalloc_a_SOURCES) $(libmiscutil_a_SOURCES) $(EXTRA_libmiscutil_a_SOURCES) $(libntlmauth_a_SOURCES) $(libregex_a_SOURCES)
- 
- all: all-am
-@@ -295,7 +310,6 @@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/heap.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/html_quote.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/inet_ntoa.Po at am__quote@
-- at AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/initgroups.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/iso3307.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/md5.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ntlmauth.Po at am__quote@
-@@ -307,7 +321,9 @@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/safe_inet_addr.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/snprintf.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/splay.Po at am__quote@
-+ at AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strcasestr.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strerror.Po at am__quote@
-+ at AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strnstr.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/stub_memaccount.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/tempnam.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/util.Po at am__quote@
---- src/Makefile.in.orig	Wed Sep 28 22:57:21 2005
-+++ src/Makefile.in	Sat Dec 17 17:45:21 2005
-@@ -125,6 +125,9 @@
- install_sh = @install_sh@
- makesnmplib = @makesnmplib@
- 
-+ at USE_ICAP_TRUE@ICAPSOURCE = icap_common.c icap_reqmod.c icap_respmod.c icap_opt.c
-+ at USE_ICAP_FALSE@ICAPSOURCE = 
-+
- @USE_DNSSERVER_TRUE at DNSSOURCE = dns.c
- @USE_DNSSERVER_FALSE at DNSSOURCE = dns_internal.c
- @USE_DNSSERVER_TRUE at DNSSERVER = dnsserver
-@@ -249,6 +252,7 @@
- 	HttpMsg.c \
- 	HttpReply.c \
- 	HttpRequest.c \
-+	$(ICAPSOURCE) \
- 	icmp.c \
- 	icp_v2.c \
- 	icp_v3.c \
-@@ -468,54 +472,58 @@
- pinger_LDADD = $(LDADD)
- pinger_DEPENDENCIES =
- pinger_LDFLAGS =
-- at USE_DELAY_POOLS_TRUE@am__objects_3 = delay_pools.$(OBJEXT)
-- at USE_DELAY_POOLS_FALSE@am__objects_3 =
-- at USE_DNSSERVER_FALSE@am__objects_4 = dns_internal.$(OBJEXT)
-- at USE_DNSSERVER_TRUE@am__objects_4 = dns.$(OBJEXT)
-- at ENABLE_HTCP_TRUE@am__objects_5 = htcp.$(OBJEXT)
-- at MAKE_LEAKFINDER_FALSE@am__objects_6 =
-- at MAKE_LEAKFINDER_TRUE@am__objects_6 = leakfinder.$(OBJEXT)
-- at USE_SNMP_TRUE@am__objects_7 = snmp_core.$(OBJEXT) snmp_agent.$(OBJEXT)
-- at USE_SNMP_FALSE@am__objects_7 =
-- at ENABLE_SSL_TRUE@am__objects_8 = ssl_support.$(OBJEXT)
-- at ENABLE_SSL_FALSE@am__objects_8 =
-- at ENABLE_UNLINKD_FALSE@am__objects_9 =
-- at ENABLE_UNLINKD_TRUE@am__objects_9 = unlinkd.$(OBJEXT)
-- at ENABLE_WIN32SPECIFIC_TRUE@am__objects_10 = win32.$(OBJEXT)
-- at ENABLE_WIN32SPECIFIC_FALSE@am__objects_10 =
-+ at USE_DELAY_POOLS_FALSE@am__objects_5 =
-+ at USE_DELAY_POOLS_TRUE@am__objects_5 = delay_pools.$(OBJEXT)
-+ at USE_DNSSERVER_FALSE@am__objects_6 = dns_internal.$(OBJEXT)
-+ at USE_DNSSERVER_TRUE@am__objects_6 = dns.$(OBJEXT)
-+ at ENABLE_HTCP_TRUE@am__objects_7 = htcp.$(OBJEXT)
-+ at USE_ICAP_TRUE@am__objects_8 = icap_common.$(OBJEXT) \
-+ at USE_ICAP_TRUE@	icap_reqmod.$(OBJEXT) icap_respmod.$(OBJEXT) \
-+ at USE_ICAP_TRUE@	icap_opt.$(OBJEXT)
-+ at USE_ICAP_FALSE@am__objects_8 =
-+ at MAKE_LEAKFINDER_TRUE@am__objects_9 = leakfinder.$(OBJEXT)
-+ at MAKE_LEAKFINDER_FALSE@am__objects_9 =
-+ at USE_SNMP_TRUE@am__objects_10 = snmp_core.$(OBJEXT) snmp_agent.$(OBJEXT)
-+ at USE_SNMP_FALSE@am__objects_10 =
-+ at ENABLE_SSL_FALSE@am__objects_11 =
-+ at ENABLE_SSL_TRUE@am__objects_11 = ssl_support.$(OBJEXT)
-+ at ENABLE_UNLINKD_TRUE@am__objects_12 = unlinkd.$(OBJEXT)
-+ at ENABLE_UNLINKD_FALSE@am__objects_12 =
-+ at ENABLE_WIN32SPECIFIC_FALSE@am__objects_13 =
-+ at ENABLE_WIN32SPECIFIC_TRUE@am__objects_13 = win32.$(OBJEXT)
- am_squid_OBJECTS = access_log.$(OBJEXT) acl.$(OBJEXT) asn.$(OBJEXT) \
- 	authenticate.$(OBJEXT) cache_cf.$(OBJEXT) CacheDigest.$(OBJEXT) \
- 	cache_manager.$(OBJEXT) carp.$(OBJEXT) cbdata.$(OBJEXT) \
- 	client_db.$(OBJEXT) client_side.$(OBJEXT) comm.$(OBJEXT) \
--	comm_select.$(OBJEXT) debug.$(OBJEXT) $(am__objects_3) \
--	disk.$(OBJEXT) $(am__objects_4) errorpage.$(OBJEXT) \
-+	comm_select.$(OBJEXT) debug.$(OBJEXT) $(am__objects_5) \
-+	disk.$(OBJEXT) $(am__objects_6) errorpage.$(OBJEXT) \
- 	ETag.$(OBJEXT) event.$(OBJEXT) external_acl.$(OBJEXT) \
- 	fd.$(OBJEXT) filemap.$(OBJEXT) forward.$(OBJEXT) \
- 	fqdncache.$(OBJEXT) ftp.$(OBJEXT) gopher.$(OBJEXT) \
--	helper.$(OBJEXT) $(am__objects_5) http.$(OBJEXT) \
-+	helper.$(OBJEXT) $(am__objects_7) http.$(OBJEXT) \
- 	HttpStatusLine.$(OBJEXT) HttpHdrCc.$(OBJEXT) \
- 	HttpHdrRange.$(OBJEXT) HttpHdrContRange.$(OBJEXT) \
- 	HttpHeader.$(OBJEXT) HttpHeaderTools.$(OBJEXT) \
- 	HttpBody.$(OBJEXT) HttpMsg.$(OBJEXT) HttpReply.$(OBJEXT) \
--	HttpRequest.$(OBJEXT) icmp.$(OBJEXT) icp_v2.$(OBJEXT) \
--	icp_v3.$(OBJEXT) ident.$(OBJEXT) internal.$(OBJEXT) \
--	ipc.$(OBJEXT) ipcache.$(OBJEXT) $(am__objects_6) \
--	logfile.$(OBJEXT) main.$(OBJEXT) mem.$(OBJEXT) \
-+	HttpRequest.$(OBJEXT) $(am__objects_8) icmp.$(OBJEXT) \
-+	icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) ident.$(OBJEXT) \
-+	internal.$(OBJEXT) ipc.$(OBJEXT) ipcache.$(OBJEXT) \
-+	$(am__objects_9) logfile.$(OBJEXT) main.$(OBJEXT) mem.$(OBJEXT) \
- 	MemPool.$(OBJEXT) MemBuf.$(OBJEXT) mime.$(OBJEXT) \
- 	multicast.$(OBJEXT) neighbors.$(OBJEXT) net_db.$(OBJEXT) \
- 	Packer.$(OBJEXT) pconn.$(OBJEXT) peer_digest.$(OBJEXT) \
- 	peer_select.$(OBJEXT) redirect.$(OBJEXT) referer.$(OBJEXT) \
--	refresh.$(OBJEXT) send-announce.$(OBJEXT) $(am__objects_7) \
--	ssl.$(OBJEXT) $(am__objects_8) stat.$(OBJEXT) \
-+	refresh.$(OBJEXT) send-announce.$(OBJEXT) $(am__objects_10) \
-+	ssl.$(OBJEXT) $(am__objects_11) stat.$(OBJEXT) \
- 	StatHist.$(OBJEXT) String.$(OBJEXT) stmem.$(OBJEXT) \
- 	store.$(OBJEXT) store_io.$(OBJEXT) store_client.$(OBJEXT) \
- 	store_digest.$(OBJEXT) store_dir.$(OBJEXT) \
- 	store_key_md5.$(OBJEXT) store_log.$(OBJEXT) \
- 	store_rebuild.$(OBJEXT) store_swapin.$(OBJEXT) \
- 	store_swapmeta.$(OBJEXT) store_swapout.$(OBJEXT) \
--	tools.$(OBJEXT) $(am__objects_9) url.$(OBJEXT) urn.$(OBJEXT) \
-+	tools.$(OBJEXT) $(am__objects_12) url.$(OBJEXT) urn.$(OBJEXT) \
- 	useragent.$(OBJEXT) wais.$(OBJEXT) wccp.$(OBJEXT) \
--	whois.$(OBJEXT) $(am__objects_10)
-+	whois.$(OBJEXT) $(am__objects_13)
- nodist_squid_OBJECTS = repl_modules.$(OBJEXT) auth_modules.$(OBJEXT) \
- 	store_modules.$(OBJEXT) globals.$(OBJEXT) \
- 	string_arrays.$(OBJEXT)
-@@ -563,7 +571,9 @@
- @AMDEP_TRUE@	$(DEPDIR)/fqdncache.Po $(DEPDIR)/ftp.Po \
- @AMDEP_TRUE@	$(DEPDIR)/globals.Po $(DEPDIR)/gopher.Po \
- @AMDEP_TRUE@	$(DEPDIR)/helper.Po $(DEPDIR)/htcp.Po \
-- at AMDEP_TRUE@	$(DEPDIR)/http.Po $(DEPDIR)/icmp.Po \
-+ at AMDEP_TRUE@	$(DEPDIR)/http.Po $(DEPDIR)/icap_common.Po \
-+ at AMDEP_TRUE@	$(DEPDIR)/icap_opt.Po $(DEPDIR)/icap_reqmod.Po \
-+ at AMDEP_TRUE@	$(DEPDIR)/icap_respmod.Po $(DEPDIR)/icmp.Po \
- @AMDEP_TRUE@	$(DEPDIR)/icp_v2.Po $(DEPDIR)/icp_v3.Po \
- @AMDEP_TRUE@	$(DEPDIR)/ident.Po $(DEPDIR)/internal.Po \
- @AMDEP_TRUE@	$(DEPDIR)/ipc.Po $(DEPDIR)/ipcache.Po \
-@@ -777,6 +787,10 @@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/helper.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/htcp.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/http.Po at am__quote@
-+ at AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icap_common.Po at am__quote@
-+ at AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icap_opt.Po at am__quote@
-+ at AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icap_reqmod.Po at am__quote@
-+ at AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icap_respmod.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icmp.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icp_v2.Po at am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icp_v3.Po at am__quote@
Index: pkg-deinstall.in
===================================================================
RCS file: /home/cvs/mports/www/squid/files/pkg-deinstall.in,v
retrieving revision 1.1
retrieving revision 1.2
diff -L www/squid/files/pkg-deinstall.in -L www/squid/files/pkg-deinstall.in -u -r1.1 -r1.2
--- www/squid/files/pkg-deinstall.in
+++ www/squid/files/pkg-deinstall.in
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# $FreeBSD: ports/www/squid/files/pkg-deinstall.in,v 1.2 2006/11/04 23:03:40 miwi Exp $
+# $FreeBSD: ports/www/squid/files/pkg-deinstall.in,v 1.3 2007/02/07 08:42:29 pav Exp $
 #
 
 PATH=/bin:/usr/bin:/usr/sbin
@@ -21,12 +21,11 @@
 	echo "     To remove the '%%SQUID_UID%%' user and the '%%SQUID_GID%%' group which were"
 	echo "     created by a default installation of this package, run"
 	echo ""
-	echo "     pw userdel -r -n %%SQUID_UID%% -u 100"
-	echo ""
+	echo "     pw userdel -n %%SQUID_UID%% -u 100"
 	if  [ -d ${PKG_PREFIX}/squid -o -d ${PKG_PREFIX}/etc/squid ] ; then
 		echo ""
-		echo "     To ease updates, the cache and log directories and"
-		echo "     all configuration files modified by you were preserved."
+		echo "     In order to ease updates the cache and log directories"
+		echo "     and all configuration files modified by you were preserved."
 		echo ""
 		echo "     Please remove them manually if you do not want to use"
 	       	echo "     Squid any longer."
--- www/squid/files/icap-2.5-core.patch
+++ /dev/null
@@ -1,7137 +0,0 @@
-Patch 1 of 2 to integrate the icap-2_5 branch into the FreeBSD squid port.
-
-Created by Thomas-Martin Seck <tmseck at netcologne.de>.
-
-This patch only contains the parts of the original patchset that
-actually implement the ICAP client functionality. The updates to
-the build infrastructure are omitted to avoid the need to run an
-autotools bootstrap.  Instead, we simulate said bootstrapping with
-a second patch, icap-2.5-bootstrap.patch.
-
-The patchset was pulled from the project's CVS repository
-at cvs.devel.squid-cache.org using
-
-cvs diff -u -b -N -kk -rs2_5 -ricap-2_5
-
-See also
-<http://devel.squid-cache.org/cgi-bin/diff2/icap-2_5.patch?s2_5>
-for the "official" auto-generated patchset.
-
-See http://devel.squid-cache.org/icap/ for further information
-about the ICAP client project.
-
-Patch last updated: 2006-06-01
-
-Index: errors/Azerbaijani/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Azerbaijani/ERR_ICAP_FAILURE
-diff -N errors/Azerbaijani/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Azerbaijani/ERR_ICAP_FAILURE	8 Dec 2003 12:30:56 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Bulgarian/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Bulgarian/ERR_ICAP_FAILURE
-diff -N errors/Bulgarian/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Bulgarian/ERR_ICAP_FAILURE	8 Dec 2003 12:30:56 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Catalan/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Catalan/ERR_ICAP_FAILURE
-diff -N errors/Catalan/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Catalan/ERR_ICAP_FAILURE	8 Dec 2003 12:30:57 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Czech/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Czech/ERR_ICAP_FAILURE
-diff -N errors/Czech/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Czech/ERR_ICAP_FAILURE	8 Dec 2003 12:30:57 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Danish/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Danish/ERR_ICAP_FAILURE
-diff -N errors/Danish/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Danish/ERR_ICAP_FAILURE	8 Dec 2003 12:30:57 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Dutch/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Dutch/ERR_ICAP_FAILURE
-diff -N errors/Dutch/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Dutch/ERR_ICAP_FAILURE	8 Dec 2003 12:30:57 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/English/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/English/ERR_ICAP_FAILURE
-diff -N errors/English/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/English/ERR_ICAP_FAILURE	8 Dec 2003 12:30:57 -0000	1.1.2.2
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Estonian/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Estonian/ERR_ICAP_FAILURE
-diff -N errors/Estonian/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Estonian/ERR_ICAP_FAILURE	8 Dec 2003 12:30:58 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Finnish/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Finnish/ERR_ICAP_FAILURE
-diff -N errors/Finnish/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Finnish/ERR_ICAP_FAILURE	8 Dec 2003 12:30:58 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/French/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/French/ERR_ICAP_FAILURE
-diff -N errors/French/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/French/ERR_ICAP_FAILURE	8 Dec 2003 12:30:58 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/German/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/German/ERR_ICAP_FAILURE
-diff -N errors/German/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/German/ERR_ICAP_FAILURE	23 Mar 2004 08:20:05 -0000	1.1.2.2
-@@ -0,0 +1,33 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>FEHLER: Der angeforderte URL konnte nicht geholt werden</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>FEHLER</H1>
-+<H2>Der angeforderte URL konnte nicht geholt werden</H2>
-+<HR noshade size="1px">
-+<P>
-+Während des Versuches, den URL<BR>
-+<A HREF="%U">%U</A>
-+
-+<BR>
-+zu laden, trat der folgende Fehler auf:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP-Protokollfehler
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Es trat ein Problem bei der ICAP-Kommunikation auf. Mögliche Gründe:
-+<UL>
-+<LI>Nicht erreichbarer ICAP-Server
-+<LI>Ungültige Antwort vom ICAP-Server
-+
-+</UL>
-+</P>
-+
-+<P>Ihr Cache Administrator ist <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Greek/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Greek/ERR_ICAP_FAILURE
-diff -N errors/Greek/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Greek/ERR_ICAP_FAILURE	24 Sep 2005 10:31:00 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Hebrew/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Hebrew/ERR_ICAP_FAILURE
-diff -N errors/Hebrew/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Hebrew/ERR_ICAP_FAILURE	8 Dec 2003 12:30:59 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Hungarian/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Hungarian/ERR_ICAP_FAILURE
-diff -N errors/Hungarian/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Hungarian/ERR_ICAP_FAILURE	8 Dec 2003 12:30:59 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Italian/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Italian/ERR_ICAP_FAILURE
-diff -N errors/Italian/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Italian/ERR_ICAP_FAILURE	8 Dec 2003 12:31:00 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Japanese/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Japanese/ERR_ICAP_FAILURE
-diff -N errors/Japanese/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Japanese/ERR_ICAP_FAILURE	8 Dec 2003 12:31:00 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Korean/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Korean/ERR_ICAP_FAILURE
-diff -N errors/Korean/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Korean/ERR_ICAP_FAILURE	8 Dec 2003 12:31:00 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Lithuanian/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Lithuanian/ERR_ICAP_FAILURE
-diff -N errors/Lithuanian/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Lithuanian/ERR_ICAP_FAILURE	8 Dec 2003 12:31:00 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Polish/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Polish/ERR_ICAP_FAILURE
-diff -N errors/Polish/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Polish/ERR_ICAP_FAILURE	8 Dec 2003 12:31:00 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Portuguese/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Portuguese/ERR_ICAP_FAILURE
-diff -N errors/Portuguese/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Portuguese/ERR_ICAP_FAILURE	8 Dec 2003 12:31:01 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Romanian/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Romanian/ERR_ICAP_FAILURE
-diff -N errors/Romanian/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Romanian/ERR_ICAP_FAILURE	8 Dec 2003 12:31:01 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Russian-1251/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Russian-1251/ERR_ICAP_FAILURE
-diff -N errors/Russian-1251/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Russian-1251/ERR_ICAP_FAILURE	8 Dec 2003 12:31:02 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Russian-koi8-r/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Russian-koi8-r/ERR_ICAP_FAILURE
-diff -N errors/Russian-koi8-r/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Russian-koi8-r/ERR_ICAP_FAILURE	8 Dec 2003 12:31:02 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Serbian/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Serbian/ERR_ICAP_FAILURE
-diff -N errors/Serbian/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Serbian/ERR_ICAP_FAILURE	8 Dec 2003 12:31:02 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Simplify_Chinese/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Simplify_Chinese/ERR_ICAP_FAILURE
-diff -N errors/Simplify_Chinese/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Simplify_Chinese/ERR_ICAP_FAILURE	8 Dec 2003 12:31:02 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Slovak/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Slovak/ERR_ICAP_FAILURE
-diff -N errors/Slovak/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Slovak/ERR_ICAP_FAILURE	8 Dec 2003 12:31:03 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Spanish/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Spanish/ERR_ICAP_FAILURE
-diff -N errors/Spanish/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Spanish/ERR_ICAP_FAILURE	8 Dec 2003 12:31:03 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Swedish/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Swedish/ERR_ICAP_FAILURE
-diff -N errors/Swedish/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Swedish/ERR_ICAP_FAILURE	8 Dec 2003 12:31:03 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Traditional_Chinese/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Traditional_Chinese/ERR_ICAP_FAILURE
-diff -N errors/Traditional_Chinese/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Traditional_Chinese/ERR_ICAP_FAILURE	8 Dec 2003 12:31:03 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: errors/Turkish/ERR_ICAP_FAILURE
-===================================================================
-RCS file: errors/Turkish/ERR_ICAP_FAILURE
-diff -N errors/Turkish/ERR_ICAP_FAILURE
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ errors/Turkish/ERR_ICAP_FAILURE	8 Dec 2003 12:31:04 -0000	1.1.2.1
-@@ -0,0 +1,31 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-+<HTML><HEAD>
-+<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
-+<STYLE type="text/css"><!--BODY{background-color:#ffffff; font-family:verdana,sans-serif}--></STYLE>
-+</HEAD><BODY>
-+<H1>ERROR</H1>
-+<H2>The requested URL could not be retrieved</H2>
-+<HR noshade size="1px">
-+<P>
-+While attempting to retrieve the URL:
-+<A HREF="%U">%U</A>
-+<P>
-+the following error was encountered:
-+<UL>
-+<LI>
-+<STRONG>
-+ICAP protocol error.
-+</STRONG>
-+</UL>
-+
-+<P>
-+<P>
-+Some aspect of the ICAP communication failed. Possible problems:
-+<UL>
-+<LI>ICAP server is not reachable.
-+<LI>Illegal response from ICAP server.
-+</UL>
-+</P>
-+
-+<P>Your cache administrator is <A HREF="mailto:%w">%w</A>. 
-+
-Index: include/util.h
-===================================================================
-RCS file: /cvsroot/squid/squid/include/util.h,v
-retrieving revision 1.10.6.1
-retrieving revision 1.10.30.3
-diff -p -u -b -r1.10.6.1 -r1.10.30.3
---- include/util.h	12 May 2006 16:51:32 -0000	1.10.6.1
-+++ include/util.h	16 May 2006 17:56:57 -0000	1.10.30.3
-@@ -123,4 +123,12 @@ double drand48(void);
-  */
- int statMemoryAccounted(void);
- 
-+#ifndef HAVE_STRNSTR
-+extern char *strnstr(const char *haystack, const char *needle, size_t haystacklen);
-+#endif
-+
-+#ifndef HAVE_STRCASESTR
-+extern char *strcasestr(const char *haystack, const char *needle);
-+#endif
-+
- #endif /* SQUID_UTIL_H */
-Index: lib/strcasestr.c
-===================================================================
-RCS file: lib/strcasestr.c
-diff -N lib/strcasestr.c
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ lib/strcasestr.c	6 Apr 2004 13:04:38 -0000	1.1.2.1
-@@ -0,0 +1,126 @@
-+/* Return the offset of one string within another.
-+   Copyright (C) 1994,1996,1997,1998,1999,2000 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library 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
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, write to the Free
-+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+   02111-1307 USA.  */
-+
-+/*
-+ * My personal strstr() implementation that beats most other algorithms.
-+ * Until someone tells me otherwise, I assume that this is the
-+ * fastest implementation of strstr() in C.
-+ * I deliberately chose not to comment it.  You should have at least
-+ * as much fun trying to understand it, as I had to write it :-).
-+ *
-+ * Stephen R. van den Berg, berg at pool.informatik.rwth-aachen.de	*/
-+
-+/* 
-+ * modified to work outside of glibc (rhorstmann, 06/04/2004)
-+ */
-+
-+#include "config.h"
-+#ifndef  HAVE_STRCASESTR
-+#include <ctype.h>
-+
-+typedef unsigned chartype;
-+
-+char *
-+strcasestr (phaystack, pneedle)
-+     const char *phaystack;
-+     const char *pneedle;
-+{
-+  register const unsigned char *haystack, *needle;
-+  register chartype b, c;
-+
-+  haystack = (const unsigned char *) phaystack;
-+  needle = (const unsigned char *) pneedle;
-+
-+  b = tolower (*needle);
-+  if (b != '\0')
-+    {
-+      haystack--;				/* possible ANSI violation */
-+      do
-+	{
-+	  c = *++haystack;
-+	  if (c == '\0')
-+	    goto ret0;
-+	}
-+      while (tolower (c) != (int) b);
-+
-+      c = tolower (*++needle);
-+      if (c == '\0')
-+	goto foundneedle;
-+      ++needle;
-+      goto jin;
-+
-+      for (;;)
-+        {
-+          register chartype a;
-+	  register const unsigned char *rhaystack, *rneedle;
-+
-+	  do
-+	    {
-+	      a = *++haystack;
-+	      if (a == '\0')
-+		goto ret0;
-+	      if (tolower (a) == (int) b)
-+		break;
-+	      a = *++haystack;
-+	      if (a == '\0')
-+		goto ret0;
-+shloop:
-+	      ;
-+	    }
-+          while (tolower (a) != (int) b);
-+
-+jin:	  a = *++haystack;
-+	  if (a == '\0')
-+	    goto ret0;
-+
-+	  if (tolower (a) != (int) c)
-+	    goto shloop;
-+
-+	  rhaystack = haystack-- + 1;
-+	  rneedle = needle;
-+	  a = tolower (*rneedle);
-+
-+	  if (tolower (*rhaystack) == (int) a)
-+	    do
-+	      {
-+		if (a == '\0')
-+		  goto foundneedle;
-+		++rhaystack;
-+		a = tolower (*++needle);
-+		if (tolower (*rhaystack) != (int) a)
-+		  break;
-+		if (a == '\0')
-+		  goto foundneedle;
-+		++rhaystack;
-+		a = tolower (*++needle);
-+	      }
-+	    while (tolower (*rhaystack) == (int) a);
-+
-+	  needle = rneedle;		/* took the register-poor approach */
-+
-+	  if (a == '\0')
-+	    break;
-+        }
-+    }
-+foundneedle:
-+  return (char*) haystack;
-+ret0:
-+  return 0;
-+}
-+#endif
-Index: lib/strnstr.c
-===================================================================
-RCS file: lib/strnstr.c
-diff -N lib/strnstr.c
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ lib/strnstr.c	16 May 2005 20:52:40 -0000	1.1.2.2
-@@ -0,0 +1,52 @@
-+/*
-+ *  Copyright (C) 2003 Nikos Mavroyanopoulos
-+ *
-+ *  This file is part of GNUTLS.
-+ *
-+ *  The GNUTLS library is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU Lesser General Public   
-+ *  License as published by the Free Software Foundation; either 
-+ *  version 2.1 of the License, or (at your option) any later version.
-+ *
-+ *  This library 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
-+ *  Lesser General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU Lesser General Public
-+ *  License along with this library; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
-+ *
-+ */
-+
-+ /*
-+  * DW 2003/10/17:
-+  * Changed 'ssize_t' types to 'size_t'
-+  */
-+
-+#include "config.h"
-+#ifndef HAVE_STRNSTR
-+#include <string.h>
-+#include <util.h>
-+
-+char *strnstr(const char *haystack, const char *needle, size_t haystacklen)
-+{
-+        char *p;
-+        size_t plen;
-+        size_t len = strlen(needle);
-+
-+        if (*needle == '\0')    /* everything matches empty string */
-+                return (char*) haystack;
-+
-+        plen = haystacklen;
-+        for (p = (char*) haystack; p != NULL; p = memchr(p + 1, *needle, plen-1)) {
-+                plen = haystacklen - (p - haystack);
-+
-+                if (plen < len) return NULL;
-+
-+                if (strncmp(p, needle, len) == 0)
-+                        return (p);
-+        }
-+        return NULL;
-+}
-+#endif
-Index: src/MemBuf.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/MemBuf.c,v
-retrieving revision 1.5.30.3
-retrieving revision 1.5.44.8
-diff -p -u -b -r1.5.30.3 -r1.5.44.8
---- src/MemBuf.c	26 Mar 2005 03:15:54 -0000	1.5.30.3
-+++ src/MemBuf.c	28 Mar 2005 18:02:04 -0000	1.5.44.8
-@@ -386,3 +386,15 @@ memBufReport(MemBuf * mb)
-     assert(mb);
-     memBufPrintf(mb, "memBufReport is not yet implemented @?@\n");
- }
-+
-+int
-+memBufRead(int fd, MemBuf * mb)
-+{
-+    int len;
-+    if (mb->capacity == mb->size)
-+	memBufGrow(mb, SQUID_TCP_SO_RCVBUF);
-+    len = FD_READ_METHOD(fd, mb->buf + mb->size, mb->capacity - mb->size);
-+    if (len)
-+	mb->size += len;
-+    return len;
-+}
-Index: src/cache_cf.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/cache_cf.c,v
-retrieving revision 1.38.6.29
-retrieving revision 1.38.6.11.2.22
-diff -p -u -b -r1.38.6.29 -r1.38.6.11.2.22
---- src/cache_cf.c	27 Oct 2005 02:13:24 -0000	1.38.6.29
-+++ src/cache_cf.c	23 Nov 2005 20:38:56 -0000	1.38.6.11.2.22
-@@ -2198,6 +2198,587 @@ check_null_body_size_t(dlink_list bodyli
-     return bodylist.head == NULL;
- }
- 
-+#ifdef HS_FEAT_ICAP
-+
-+/***************************************************
-+ * prototypes
-+ */
-+static int icap_service_process(icap_service * s);
-+static void icap_service_init(icap_service * s);
-+static void icap_service_destroy(icap_service * s);
-+icap_service *icap_service_lookup(char *name);
-+static int icap_class_process(icap_class * c);
-+static void icap_class_destroy(icap_class * c);
-+static void icap_access_destroy(icap_access * a);
-+static void dump_wordlist(StoreEntry * entry, const char *name, wordlist * list);
-+static void icap_class_add(icap_class * c);
-+
-+/***************************************************
-+ * icap_service
-+ */
-+
-+/* 
-+ * example:
-+ * icap_service reqmode_precache 0 icap://192.168.0.1:1344/respmod
-+ */
-+
-+static void
-+parse_icap_service_type(IcapConfig * cfg)
-+{
-+    char *token;
-+    icap_service *A = NULL;
-+    icap_service *B = NULL;
-+    icap_service **T = NULL;
-+
-+    A = cbdataAlloc(icap_service);
-+    icap_service_init(A);
-+    parse_string(&A->name);
-+    parse_string(&A->type_name);
-+    parse_ushort(&A->bypass);
-+    parse_string(&A->uri);
-+    while ((token = strtok(NULL, w_space))) {
-+	if (strcasecmp(token, "no-keep-alive") == 0) {
-+	    A->keep_alive = 0;
-+	} else {
-+	    debug(3, 0) ("parse_peer: token='%s'\n", token);
-+	    self_destruct();
-+	}
-+    }
-+    debug(3, 5) ("parse_icap_service_type (line %d): %s %s %d %s\n", config_lineno, A->name, A->type_name, A->bypass, A->name);
-+    if (icap_service_process(A)) {
-+	/* put into linked list */
-+	for (B = cfg->service_head, T = &cfg->service_head; B; T = &B->next, B = B->next);
-+	*T = A;
-+    } else {
-+	/* clean up structure */
-+	debug(3, 0) ("parse_icap_service_type (line %d): skipping %s\n", config_lineno, A->name);
-+	icap_service_destroy(A);
-+	cbdataFree(A);
-+    }
-+
-+}
-+
-+static void
-+dump_icap_service_type(StoreEntry * e, const char *name, IcapConfig cfg)
-+{
-+    icap_service *current_node = NULL;
-+
-+    if (!cfg.service_head) {
-+	storeAppendPrintf(e, "%s 0\n", name);
-+	return;
-+    }
-+    current_node = cfg.service_head;
-+
-+    while (current_node) {
-+	storeAppendPrintf(e, "%s %s %s %d %s", name, current_node->name, current_node->type_name, current_node->bypass, current_node->uri);
-+	if (current_node->keep_alive == 0) {
-+	    storeAppendPrintf(e, " no-keep-alive");
-+	}
-+	storeAppendPrintf(e, "\n");
-+	current_node = current_node->next;
-+    }
-+
-+}
-+
-+static void
-+free_icap_service_type(IcapConfig * cfg)
-+{
-+    while (cfg->service_head) {
-+	icap_service *current_node = cfg->service_head;
-+	cfg->service_head = current_node->next;
-+	icap_service_destroy(current_node);
-+	cbdataFree(current_node);
-+    }
-+}
-+
-+/* 
-+ * parse the raw string and cache some parts that are needed later 
-+ * returns 1 if everything was ok
-+ */
-+static int
-+icap_service_process(icap_service * s)
-+{
-+    char *start, *end, *tempEnd;
-+    char *tailp;
-+    unsigned int len;
-+    int port_in_uri, resource_in_uri = 0;
-+    s->type = icapServiceToType(s->type_name);
-+    if (s->type >= ICAP_SERVICE_MAX) {
-+	debug(3, 0) ("icap_service_process (line %d): wrong service type %s\n", config_lineno, s->type_name);
-+	return 0;
-+    }
-+    if (s->type == ICAP_SERVICE_REQMOD_PRECACHE)
-+	s->method = ICAP_METHOD_REQMOD;
-+    else if (s->type == ICAP_SERVICE_REQMOD_PRECACHE)
-+	s->method = ICAP_METHOD_REQMOD;
-+    else if (s->type == ICAP_SERVICE_REQMOD_POSTCACHE)
-+	s->method = ICAP_METHOD_REQMOD;
-+    else if (s->type == ICAP_SERVICE_RESPMOD_PRECACHE)
-+	s->method = ICAP_METHOD_RESPMOD;
-+    else if (s->type == ICAP_SERVICE_RESPMOD_POSTCACHE)
-+	s->method = ICAP_METHOD_RESPMOD;
-+    debug(3, 5) ("icap_service_process (line %d): type=%s\n", config_lineno, icapServiceToStr(s->type));
-+    if (strncmp(s->uri, "icap://", 7) != 0) {
-+	debug(3, 0) ("icap_service_process (line %d): wrong uri: %s\n", config_lineno, s->uri);
-+	return 0;
-+    }
-+    start = s->uri + 7;
-+    if ((end = strchr(start, ':')) != NULL) {
-+	/* ok */
-+	port_in_uri = 1;
-+	debug(3, 5) ("icap_service_process (line %d): port given\n", config_lineno);
-+    } else {
-+	/* ok */
-+	port_in_uri = 0;
-+	debug(3, 5) ("icap_service_process (line %d): no port given\n", config_lineno);
-+    }
-+
-+    if ((tempEnd = strchr(start, '/')) != NULL) {
-+	/* ok */
-+	resource_in_uri = 1;
-+	debug(3, 5) ("icap_service_process (line %d): resource given\n", config_lineno);
-+	if (end == '\0') {
-+	    end = tempEnd;
-+	}
-+    } else {
-+	/* ok */
-+	resource_in_uri = 0;
-+	debug(3, 5) ("icap_service_process (line %d): no resource given\n", config_lineno);
-+    }
-+
-+    tempEnd = strchr(start, '\0');
-+    if (end == '\0') {
-+	end = tempEnd;
-+    }
-+    len = end - start;
-+    s->hostname = xstrndup(start, len + 1);
-+    s->hostname[len] = 0;
-+    debug(3, 5) ("icap_service_process (line %d): hostname=%s\n", config_lineno, s->hostname);
-+    start = end;
-+
-+    if (port_in_uri) {
-+	start++;		/* skip ':' */
-+	if (resource_in_uri)
-+	    end = strchr(start, '/');
-+	else
-+	    end = strchr(start, '\0');
-+	s->port = strtoul(start, &tailp, 0) % 65536;
-+	if (tailp != end) {
-+	    debug(3, 0) ("icap_service_process (line %d): wrong service uri (port could not be parsed): %s\n", config_lineno, s->uri);
-+	    return 0;
-+	}
-+	debug(3, 5) ("icap_service_process (line %d): port=%d\n", config_lineno, s->port);
-+	start = end;
-+    } else {
-+	/* no explicit ICAP port; first ask by getservbyname or default to
-+	 * hardwired port 1344 per ICAP specification section 4.2 */
-+	struct servent *serv = getservbyname("icap", "tcp");
-+	if (serv) {
-+	    s->port = htons(serv->s_port);
-+	    debug(3, 5) ("icap_service_process (line %d): default port=%d getservbyname(icap,tcp)\n", config_lineno, s->port);
-+	} else {
-+	    s->port = 1344;
-+	    debug(3, 5) ("icap_service_process (line %d): default hardwired port=%d\n", config_lineno, s->port);
-+	}
-+    }
-+
-+    if (resource_in_uri) {
-+	start++;		/* skip '/' */
-+	/* the rest is resource name */
-+	end = strchr(start, '\0');
-+	len = end - start;
-+	if (len > 1024) {
-+	    debug(3, 0) ("icap_service_process (line %d): long resource name (>1024), probably wrong\n", config_lineno);
-+	}
-+	s->resource = xstrndup(start, len + 1);
-+	s->resource[len] = 0;
-+	debug(3, 5) ("icap_service_process (line %d): service=%s\n", config_lineno, s->resource);
-+    }
-+    /* check bypass */
-+    if ((s->bypass != 0) && (s->bypass != 1)) {
-+	debug(3, 0) ("icap_service_process (line %d): invalid bypass value\n", config_lineno);
-+	return 0;
-+    }
-+    return 1;
-+}
-+
-+/*
-+ * constructor
-+ */
-+static void
-+icap_service_init(icap_service * s)
-+{
-+    s->type = ICAP_SERVICE_MAX;	/* means undefined */
-+    s->preview = Config.icapcfg.preview_size;
-+    s->opt = 0;
-+    s->keep_alive = 1;
-+    s->istag = StringNull;
-+    s->transfer_preview = StringNull;
-+    s->transfer_ignore = StringNull;
-+    s->transfer_complete = StringNull;
-+}
-+
-+/*
-+ * destructor
-+ * frees only strings, but don't touch the linked list
-+ */
-+static void
-+icap_service_destroy(icap_service * s)
-+{
-+    xfree(s->name);
-+    xfree(s->uri);
-+    xfree(s->type_name);
-+    xfree(s->hostname);
-+    xfree(s->resource);
-+    assert(s->opt == 0);	/* there should be no opt request running now */
-+    stringClean(&s->istag);
-+    stringClean(&s->transfer_preview);
-+    stringClean(&s->transfer_ignore);
-+    stringClean(&s->transfer_complete);
-+}
-+
-+icap_service *
-+icap_service_lookup(char *name)
-+{
-+    icap_service *iter;
-+    for (iter = Config.icapcfg.service_head; iter; iter = iter->next) {
-+	if (!strcmp(name, iter->name)) {
-+	    return iter;
-+	}
-+    }
-+    return NULL;
-+}
-+
-+/***************************************************
-+ * icap_service_list
-+ */
-+
-+static void
-+icap_service_list_add(icap_service_list ** isl, char *service_name)
-+{
-+    icap_service_list **iter;
-+    icap_service_list *new;
-+    icap_service *gbl_service;
-+    int i;
-+    int max_services;
-+
-+    new = memAllocate(MEM_ICAP_SERVICE_LIST);
-+    /* Found all services with that name, and add to the array */
-+    max_services = sizeof(new->services) / sizeof(icap_service *);
-+    gbl_service = Config.icapcfg.service_head;
-+    i = 0;
-+    while (gbl_service && i < max_services) {
-+	if (!strcmp(service_name, gbl_service->name))
-+	    new->services[i++] = gbl_service;
-+	gbl_service = gbl_service->next;
-+    }
-+    new->nservices = i;
-+
-+    if (*isl) {
-+	iter = isl;
-+	while ((*iter)->next)
-+	    iter = &((*iter)->next);
-+	(*iter)->next = new;
-+    } else {
-+	*isl = new;
-+    }
-+}
-+
-+/*
-+ * free the linked list without touching references icap_service
-+ */
-+static void
-+icap_service_list_destroy(icap_service_list * isl)
-+{
-+    icap_service_list *current;
-+    icap_service_list *next;
-+
-+    current = isl;
-+    while (current) {
-+	next = current->next;
-+	memFree(current, MEM_ICAP_SERVICE_LIST);
-+	current = next;
-+    }
-+}
-+
-+/***************************************************
-+ * icap_class
-+ */
-+static void
-+parse_icap_class_type(IcapConfig * cfg)
-+{
-+    icap_class *s = NULL;
-+
-+    s = memAllocate(MEM_ICAP_CLASS);
-+    parse_string(&s->name);
-+    parse_wordlist(&s->services);
-+
-+    if (icap_class_process(s)) {
-+	/* if ok, put into linked list */
-+	icap_class_add(s);
-+    } else {
-+	/* clean up structure */
-+	debug(3, 0) ("parse_icap_class_type (line %d): skipping %s\n", config_lineno, s->name);
-+	icap_class_destroy(s);
-+	memFree(s, MEM_ICAP_CLASS);
-+    }
-+}
-+
-+static void
-+dump_icap_class_type(StoreEntry * e, const char *name, IcapConfig cfg)
-+{
-+    icap_class *current_node = NULL;
-+    LOCAL_ARRAY(char, nom, 64);
-+
-+    if (!cfg.class_head) {
-+	storeAppendPrintf(e, "%s 0\n", name);
-+	return;
-+    }
-+    current_node = cfg.class_head;
-+
-+    while (current_node) {
-+	snprintf(nom, 64, "%s %s", name, current_node->name);
-+	dump_wordlist(e, nom, current_node->services);
-+	current_node = current_node->next;
-+    }
-+}
-+
-+static void
-+free_icap_class_type(IcapConfig * cfg)
-+{
-+    while (cfg->class_head) {
-+	icap_class *current_node = cfg->class_head;
-+	cfg->class_head = current_node->next;
-+	icap_class_destroy(current_node);
-+	memFree(current_node, MEM_ICAP_CLASS);
-+    }
-+}
-+
-+/*
-+ * process services list, return 1, if at least one service was found
-+ */
-+static int
-+icap_class_process(icap_class * c)
-+{
-+    icap_service_list *isl = NULL;
-+    wordlist *iter;
-+    icap_service *service;
-+    /* take services list and build icap_service_list from it */
-+    for (iter = c->services; iter; iter = iter->next) {
-+	service = icap_service_lookup(iter->key);
-+	if (service) {
-+	    icap_service_list_add(&isl, iter->key);
-+	} else {
-+	    debug(3, 0) ("icap_class_process (line %d): skipping service %s in class %s\n", config_lineno, iter->key, c->name);
-+	}
-+    }
-+
-+    if (isl) {
-+	c->isl = isl;
-+	return 1;
-+    }
-+    return 0;
-+}
-+
-+/*
-+ * search for an icap_class in the global IcapConfig
-+ * classes with hidden-flag are skipped
-+ */
-+static icap_class *
-+icap_class_lookup(char *name)
-+{
-+    icap_class *iter;
-+    for (iter = Config.icapcfg.class_head; iter; iter = iter->next) {
-+	if ((!strcmp(name, iter->name)) && (!iter->hidden)) {
-+	    return iter;
-+	}
-+    }
-+    return NULL;
-+}
-+
-+/*
-+ * adds an icap_class to the global IcapConfig
-+ */
-+static void
-+icap_class_add(icap_class * c)
-+{
-+    icap_class *cp = NULL;
-+    icap_class **t = NULL;
-+    IcapConfig *cfg = &Config.icapcfg;
-+    if (c) {
-+	for (cp = cfg->class_head, t = &cfg->class_head; cp; t = &cp->next, cp = cp->next);
-+	*t = c;
-+    }
-+}
-+
-+/*
-+ * free allocated memory inside icap_class
-+ */
-+static void
-+icap_class_destroy(icap_class * c)
-+{
-+    xfree(c->name);
-+    wordlistDestroy(&c->services);
-+    icap_service_list_destroy(c->isl);
-+}
-+
-+/***************************************************
-+ * icap_access
-+ */
-+
-+/* format: icap_access <servicename> {allow|deny} acl, ... */
-+static void
-+parse_icap_access_type(IcapConfig * cfg)
-+{
-+    icap_access *A = NULL;
-+    icap_access *B = NULL;
-+    icap_access **T = NULL;
-+    icap_service *s = NULL;
-+    icap_class *c = NULL;
-+    ushort no_class = 0;
-+
-+    A = memAllocate(MEM_ICAP_ACCESS);
-+    parse_string(&A->service_name);
-+
-+    /* 
-+     * try to find a class with the given name first. if not found, search 
-+     * the services. if a service is found, create a new hidden class with 
-+     * only this service. this is for backward compatibility.
-+     *
-+     * the special classname All is allowed only in deny rules, because
-+     * the class is not used there.
-+     */
-+    if (!strcmp(A->service_name, "None")) {
-+	no_class = 1;
-+    } else {
-+	A->class = icap_class_lookup(A->service_name);
-+	if (!A->class) {
-+	    s = icap_service_lookup(A->service_name);
-+	    if (s) {
-+		c = memAllocate(MEM_ICAP_CLASS);
-+		c->name = xstrdup("(hidden)");
-+		c->hidden = 1;
-+		wordlistAdd(&c->services, A->service_name);
-+		c->isl = memAllocate(MEM_ICAP_SERVICE_LIST);
-+		/* FIXME:luc: check what access do */
-+		c->isl->services[0] = s;
-+		c->isl->nservices = 1;
-+		icap_class_add(c);
-+		A->class = c;
-+	    } else {
-+		debug(3, 0) ("parse_icap_access_type (line %d): servicename %s not found. skipping.\n", config_lineno, A->service_name);
-+		memFree(A, MEM_ICAP_ACCESS);
-+		return;
-+	    }
-+	}
-+    }
-+
-+    aclParseAccessLine(&(A->access));
-+    debug(3, 5) ("parse_icap_access_type (line %d): %s\n", config_lineno, A->service_name);
-+
-+    /* check that All class is only used in deny rule */
-+    if (no_class && A->access->allow) {
-+	memFree(A, MEM_ICAP_ACCESS);
-+	debug(3, 0) ("parse_icap_access (line %d): special class 'None' only allowed in deny rule. skipping.\n", config_lineno);
-+	return;
-+    }
-+    if (A->access) {
-+	for (B = cfg->access_head, T = &cfg->access_head; B; T = &B->next, B = B->next);
-+	*T = A;
-+    } else {
-+	debug(3, 0) ("parse_icap_access_type (line %d): invalid line skipped\n", config_lineno);
-+	memFree(A, MEM_ICAP_ACCESS);
-+    }
-+}
-+
-+static void
-+dump_icap_access_type(StoreEntry * e, const char *name, IcapConfig cfg)
-+{
-+    icap_access *current_node = NULL;
-+    LOCAL_ARRAY(char, nom, 64);
-+
-+    if (!cfg.access_head) {
-+	storeAppendPrintf(e, "%s 0\n", name);
-+	return;
-+    }
-+    current_node = cfg.access_head;
-+
-+    while (current_node) {
-+	snprintf(nom, 64, "%s %s", name, current_node->service_name);
-+	dump_acl_access(e, nom, current_node->access);
-+	current_node = current_node->next;
-+    }
-+}
-+
-+static void
-+free_icap_access_type(IcapConfig * cfg)
-+{
-+    while (cfg->access_head) {
-+	icap_access *current_node = cfg->access_head;
-+	cfg->access_head = current_node->next;
-+	icap_access_destroy(current_node);
-+	memFree(current_node, MEM_ICAP_ACCESS);
-+    }
-+}
-+
-+/*
-+ * destructor
-+ * frees everything but the linked list
-+ */
-+static void
-+icap_access_destroy(icap_access * a)
-+{
-+    xfree(a->service_name);
-+    aclDestroyAccessList(&a->access);
-+}
-+
-+/***************************************************
-+ * for debugging purposes only
-+ */
-+void
-+dump_icap_config(IcapConfig * cfg)
-+{
-+    icap_service *s_iter;
-+    icap_class *c_iter;
-+    icap_access *a_iter;
-+    icap_service_list *isl_iter;
-+    acl_list *l;
-+    debug(3, 0) ("IcapConfig: onoff        = %d\n", cfg->onoff);
-+    debug(3, 0) ("IcapConfig: service_head = %d\n", (int) cfg->service_head);
-+    debug(3, 0) ("IcapConfig: class_head   = %d\n", (int) cfg->class_head);
-+    debug(3, 0) ("IcapConfig: access_head  = %d\n", (int) cfg->access_head);
-+
-+    debug(3, 0) ("IcapConfig: services =\n");
-+    for (s_iter = cfg->service_head; s_iter; s_iter = s_iter->next) {
-+	printf("  %s: \n", s_iter->name);
-+	printf("    bypass   = %d\n", s_iter->bypass);
-+	printf("    hostname = %s\n", s_iter->hostname);
-+	printf("    port     = %d\n", s_iter->port);
-+	printf("    resource = %s\n", s_iter->resource);
-+    }
-+    debug(3, 0) ("IcapConfig: classes =\n");
-+    for (c_iter = cfg->class_head; c_iter; c_iter = c_iter->next) {
-+	printf("  %s: \n", c_iter->name);
-+	printf("    services = \n");
-+	for (isl_iter = c_iter->isl; isl_iter; isl_iter = isl_iter->next) {
-+	    int i;
-+	    for (i = 0; i < isl_iter->nservices; i++)
-+		printf("      %s\n", isl_iter->services[i]->name);
-+	}
-+    }
-+    debug(3, 0) ("IcapConfig: access =\n");
-+    for (a_iter = cfg->access_head; a_iter; a_iter = a_iter->next) {
-+	printf("  service_name  = %s\n", a_iter->service_name);
-+	printf("    access        = %s", a_iter->access->allow ? "allow" : "deny");
-+	for (l = a_iter->access->acl_list; l != NULL; l = l->next) {
-+	    printf(" %s%s",
-+		l->op ? null_string : "!",
-+		l->acl->name);
-+	}
-+	printf("\n");
-+    }
-+}
-+#endif /* HS_FEAT_ICAP */
- 
- static void
- parse_kb_size_t(squid_off_t * var)
-Index: src/cbdata.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/cbdata.c,v
-retrieving revision 1.14.6.1
-retrieving revision 1.14.32.2
-diff -p -u -b -r1.14.6.1 -r1.14.32.2
---- src/cbdata.c	17 Jul 2003 02:13:28 -0000	1.14.6.1
-+++ src/cbdata.c	14 Sep 2003 01:36:26 -0000	1.14.32.2
-@@ -144,6 +144,10 @@ cbdataInit(void)
-     CREATE_CBDATA(statefulhelper);
-     CREATE_CBDATA(helper_stateful_server);
-     CREATE_CBDATA(HttpStateData);
-+#ifdef HS_FEAT_ICAP
-+    CREATE_CBDATA(IcapStateData);
-+    CREATE_CBDATA(icap_service);
-+#endif
-     CREATE_CBDATA_FREE(peer, peerDestroy);
-     CREATE_CBDATA(ps_state);
-     CREATE_CBDATA(RemovalPolicy);
-Index: src/cf.data.pre
-===================================================================
-RCS file: /cvsroot/squid/squid/src/cf.data.pre,v
-retrieving revision 1.49.2.86
-retrieving revision 1.49.2.33.2.34
-diff -p -u -b -r1.49.2.86 -r1.49.2.33.2.34
---- src/cf.data.pre	26 Feb 2006 03:13:57 -0000	1.49.2.86
-+++ src/cf.data.pre	16 May 2006 17:56:57 -0000	1.49.2.33.2.34
-@@ -2397,7 +2397,6 @@ DOC_START
- 	ensure correct results it is best to set server_persisten_connections
- 	to off when using this directive in such configurations.
- DOC_END
--
- NAME: reply_header_max_size
- COMMENT: (KB)
- TYPE: b_size_t
-@@ -2716,6 +2715,187 @@ DOC_START
- DOC_END
- 
- COMMENT_START
-+ ICAP OPTIONS
-+ -----------------------------------------------------------------------------
-+COMMENT_END
-+
-+NAME: icap_enable
-+TYPE: onoff
-+IFDEF: HS_FEAT_ICAP
-+COMMENT: on|off
-+LOC: Config.icapcfg.onoff
-+DEFAULT: off
-+DOC_START
-+	If you want to enable the ICAP client module, set this to on.
-+DOC_END
-+
-+NAME: icap_preview_enable
-+TYPE: onoff
-+IFDEF: HS_FEAT_ICAP
-+COMMENT: on|off
-+LOC: Config.icapcfg.preview_enable
-+DEFAULT: off
-+DOC_START
-+	Set this to 'on' if you want to enable the ICAP preview
-+	feature in Squid.
-+DOC_END
-+
-+NAME: icap_preview_size
-+TYPE: int
-+IFDEF: HS_FEAT_ICAP
-+LOC: Config.icapcfg.preview_size
-+DEFAULT: -1
-+DOC_START
-+	The default size of preview data to be sent to the ICAP server.
-+	-1 means no preview. This value might be overwritten on a per server
-+	basis by OPTIONS requests.
-+DOC_END
-+
-+NAME: icap_check_interval
-+TYPE: int
-+IFDEF: HS_FEAT_ICAP
-+LOC: Config.icapcfg.check_interval
-+DEFAULT: 300
-+DOC_START
-+        If an ICAP server does not respond, it gets marked as unreachable. Squid
-+	will try again to reach it after this time.
-+DOC_END
-+
-+NAME: icap_send_client_ip
-+TYPE: onoff
-+IFDEF: HS_FEAT_ICAP
-+COMMENT: on|off
-+LOC: Config.icapcfg.send_client_ip
-+DEFAULT: off
-+DOC_START
-+	Allows Squid to add the "X-Client-IP" header if requested by
-+	an ICAP service in it's response to OPTIONS.
-+DOC_END
-+
-+NAME: icap_send_server_ip
-+TYPE: onoff
-+IFDEF: HS_FEAT_ICAP
-+COMMENT: on|off
-+LOC: Config.icapcfg.send_server_ip
-+DEFAULT: off
-+DOC_START
-+	Allows Squid to add the "X-Server-IP" header if requested by
-+	an ICAP service in it's response to OPTIONS.
-+DOC_END
-+
-+NAME: icap_send_auth_user
-+TYPE: onoff
-+IFDEF: HS_FEAT_ICAP
-+COMMENT: on|off
-+LOC: Config.icapcfg.send_auth_user
-+DEFAULT: off
-+DOC_START
-+	Allows Squid to add the "X-Authenticated-User" header if requested
-+	by an ICAP service in it's response to OPTIONS.
-+DOC_END
-+
-+NAME: icap_auth_scheme
-+TYPE: string
-+IFDEF: HS_FEAT_ICAP
-+LOC: Config.icapcfg.auth_scheme
-+DEFAULT: Local://%u
-+DOC_START
-+	Authentification scheme to pass to ICAP requests if
-+	icap_send_auth_user is enabled. The first occurence of "%u"
-+	is replaced by the authentified user name. If no "%u" is found,
-+	the username is added at the end of the scheme.
-+	
-+	See http://www.ietf.org/internet-drafts/draft-stecher-icap-subid-00.txt,
-+	section 3.4 for details on this.
-+
-+	Examples:
-+
-+	icap_auth_scheme Local://%u
-+	icap_auth_scheme LDAP://ldap-server/cn=%u,dc=company,dc=com
-+	icap_auth_scheme WinNT://nt-domain/%u
-+	icap_auth_scheme Radius://radius-server/%u
-+DOC_END
-+
-+NAME: icap_service
-+TYPE: icap_service_type
-+IFDEF: HS_FEAT_ICAP
-+LOC: Config.icapcfg
-+DEFAULT: none
-+DOC_START
-+	Defines a single ICAP service
-+
-+	icap_service servicename vectoring_point bypass service_url [options ...]
-+
-+	vectoring_point = reqmod_precache|reqmod_postcache|respmod_precache|respmod_postcache
-+		This specifies at which point of request processing the ICAP
-+		service should be plugged in.
-+	bypass = 1|0   
-+		If set to 1 and the ICAP server cannot be reached, the request will go 
-+		through without being processed by an ICAP server
-+	service_url = icap://servername:port/service
-+
-+	Options: 
-+
-+        no-keep-alive	To always close the connection to icap server
-+        		after the transaction completes
-+
-+
-+	Note: reqmod_precache and respmod_postcache is not yet implemented
-+
-+	Load-balancing and high availability:
-+	You can obtain load-balancing and high availability by defining a
-+	named service with different definitions.  Then, the client
-+	loops through the different entities of the service providing
-+	load-balancing. If an entity is marked as unreachable, the client goes
-+	one step further to the next entity: you have the high-availability.
-+	See the service_1 definition below
-+
-+Example:
-+icap_service service_1 reqmod_precache 0 icap://icap1.mydomain.net:1344/reqmod
-+icap_service service_1 reqmod_precache 0 icap://icap2.mydomain.net:1344/reqmod no-keep-alive
-+icap_service service_2 respmod_precache 0 icap://icap3.mydomain.net:1344/respmod 
-+DOC_END
-+
-+NAME: icap_class
-+TYPE: icap_class_type
-+IFDEF: HS_FEAT_ICAP
-+LOC: Config.icapcfg
-+DEFAULT: none
-+DOC_START
-+	Defines an ICAP service chain. If there are multiple services per 
-+	vectoring point, they are processed in the specified order.
-+
-+	icap_class classname servicename...
-+
-+Example:
-+icap_class class_1 service_1 service_2
-+icap class class_2 service_1 service_3
-+DOC_END
-+
-+NAME: icap_access
-+TYPE: icap_access_type
-+IFDEF: HS_FEAT_ICAP
-+LOC: Config.icapcfg
-+DEFAULT: none
-+DOC_START
-+	Redirects a request through an ICAP service class, depending
-+	on given acls
-+
-+	icap_access classname allow|deny [!]aclname...
-+
-+	The icap_access statements are processed in the order they appear in
-+	this configuration file. If an access list matches, the processing stops. 
-+	For an "allow" rule, the specified class is used for the request. A "deny" 
-+	rule simply stops processing without using the class. You can also use the 
-+	special classname "None". 
-+	
-+	For backward compatibility, it is also possible to use services 
-+	directly here.
-+Example:
-+icap_access class_1 allow all
-+DOC_END
-+
-+COMMENT_START
-  MISCELLANEOUS
-  -----------------------------------------------------------------------------
- COMMENT_END
-Index: src/cf_gen_defines
-===================================================================
-RCS file: /cvsroot/squid/squid/src/cf_gen_defines,v
-retrieving revision 1.5
-retrieving revision 1.5.48.3
-diff -p -u -b -r1.5 -r1.5.48.3
---- src/cf_gen_defines	3 Dec 2001 08:03:21 -0000	1.5
-+++ src/cf_gen_defines	13 Mar 2005 17:58:44 -0000	1.5.48.3
-@@ -18,12 +18,13 @@ BEGIN {
- 	define["USE_UNLINKD"]="--enable-unlinkd"
- 	define["USE_USERAGENT_LOG"]="--enable-useragent-log"
- 	define["USE_WCCP"]="--enable-wccp"
-+	define["HS_FEAT_ICAP"]="--enable-icap-support"
- }
- /^IFDEF:/ {
- 	if (define[$2] != "")
--	    DEFINE=define[$2]
-+	    DEFINE = define[$2]
- 	else  
--	    DEFINE="-D" $2
-+	    DEFINE = "-D" $2
- 	print "{\"" $2 "\", \"" DEFINE "\", "
- 	print "#if " $2
- 	print "1"
-Index: src/client_side.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/client_side.c,v
-retrieving revision 1.47.2.76
-retrieving revision 1.47.2.28.2.41
-diff -p -u -b -r1.47.2.76 -r1.47.2.28.2.41
---- src/client_side.c	11 Mar 2006 03:16:31 -0000	1.47.2.76
-+++ src/client_side.c	16 May 2006 17:56:58 -0000	1.47.2.28.2.41
-@@ -109,7 +109,7 @@ static const char *const crlf = "\r\n";
- static CWCB clientWriteComplete;
- static CWCB clientWriteBodyComplete;
- static PF clientReadRequest;
--static PF connStateFree;
-+PF connStateFree;
- static PF requestTimeout;
- static PF clientLifetimeTimeout;
- static int clientCheckTransferDone(clientHttpRequest *);
-@@ -136,20 +136,23 @@ static void clientSetKeepaliveFlag(clien
- static void clientPackRangeHdr(const HttpReply * rep, const HttpHdrRangeSpec * spec, String boundary, MemBuf * mb);
- static void clientPackTermBound(String boundary, MemBuf * mb);
- static void clientInterpretRequestHeaders(clientHttpRequest *);
--static void clientProcessRequest(clientHttpRequest *);
-+void clientProcessRequest(clientHttpRequest *);
- static void clientProcessExpired(void *data);
- static void clientProcessOnlyIfCachedMiss(clientHttpRequest * http);
--static int clientCachable(clientHttpRequest * http);
--static int clientHierarchical(clientHttpRequest * http);
--static int clientCheckContentLength(request_t * r);
-+int clientCachable(clientHttpRequest * http);
-+int clientHierarchical(clientHttpRequest * http);
-+int clientCheckContentLength(request_t * r);
- static DEFER httpAcceptDefer;
- static log_type clientProcessRequest2(clientHttpRequest * http);
- static int clientReplyBodyTooLarge(clientHttpRequest *, squid_off_t clen);
- static int clientRequestBodyTooLarge(squid_off_t clen);
- static void clientProcessBody(ConnStateData * conn);
- static void clientEatRequestBody(clientHttpRequest *);
--static BODY_HANDLER clientReadBody;
-+BODY_HANDLER clientReadBody;
- static void clientAbortBody(request_t * req);
-+#if HS_FEAT_ICAP
-+static int clientIcapReqMod(clientHttpRequest * http);
-+#endif
- 
- static int
- checkAccelOnly(clientHttpRequest * http)
-@@ -392,6 +395,10 @@ clientRedirectDone(void *data, char *res
- 	http->request = requestLink(new_request);
-     }
-     clientInterpretRequestHeaders(http);
-+#if HS_FEAT_ICAP
-+    if (Config.icapcfg.onoff)
-+	icapCheckAcl(http);
-+#endif
- #if HEADERS_LOG
-     headersLog(0, 1, request->method, request);
- #endif
-@@ -936,11 +943,22 @@ httpRequestFree(void *data)
-     *H = http->next;
-     http->next = NULL;
-     dlinkDelete(&http->active, &ClientActiveRequests);
-+#if HS_FEAT_ICAP
-+    /*In the case that the upload of data breaks, we need this code here ....  */
-+    if (NULL != http->icap_reqmod) {
-+	if (cbdataValid(http->icap_reqmod))
-+	    if (http->icap_reqmod->icap_fd > -1) {
-+		comm_close(http->icap_reqmod->icap_fd);
-+	    }
-+	cbdataUnlock(http->icap_reqmod);
-+	http->icap_reqmod = NULL;
-+    }
-+#endif
-     cbdataFree(http);
- }
- 
- /* This is a handler normally called by comm_close() */
--static void
-+void
- connStateFree(int fd, void *data)
- {
-     ConnStateData *connState = data;
-@@ -963,7 +981,6 @@ connStateFree(int fd, void *data)
-     } else
- 	safe_free(connState->in.buf);
-     /* XXX account connState->in.buf */
--    pconnHistCount(0, connState->nrequests);
-     cbdataFree(connState);
- #ifdef _SQUID_LINUX_
-     /* prevent those nasty RST packets */
-@@ -1108,7 +1125,7 @@ clientSetKeepaliveFlag(clientHttpRequest
-     }
- }
- 
--static int
-+int
- clientCheckContentLength(request_t * r)
- {
-     switch (r->method) {
-@@ -1127,7 +1144,7 @@ clientCheckContentLength(request_t * r)
-     /* NOT REACHED */
- }
- 
--static int
-+int
- clientCachable(clientHttpRequest * http)
- {
-     request_t *req = http->request;
-@@ -1153,7 +1170,7 @@ clientCachable(clientHttpRequest * http)
- }
- 
- /* Return true if we can query our neighbors for this object */
--static int
-+int
- clientHierarchical(clientHttpRequest * http)
- {
-     const char *url = http->uri;
-@@ -2447,7 +2464,7 @@ clientProcessRequest2(clientHttpRequest 
-     return LOG_TCP_HIT;
- }
- 
--static void
-+void
- clientProcessRequest(clientHttpRequest * http)
- {
-     char *url = http->uri;
-@@ -2457,6 +2474,11 @@ clientProcessRequest(clientHttpRequest *
-     debug(33, 4) ("clientProcessRequest: %s '%s'\n",
- 	RequestMethodStr[r->method],
- 	url);
-+#if HS_FEAT_ICAP
-+    if (clientIcapReqMod(http)) {
-+	return;
-+    }
-+#endif
-     if (r->method == METHOD_CONNECT && !http->redirect.status) {
- 	http->log_type = LOG_TCP_MISS;
- 	sslStart(http, &http->out.size, &http->al.http.code);
-@@ -3001,6 +3023,20 @@ clientReadRequest(int fd, void *data)
- 	    (long) conn->in.offset, (long) conn->in.size);
- 	len = conn->in.size - conn->in.offset - 1;
-     }
-+#if HS_FEAT_ICAP
-+    /*
-+     * This check exists because ICAP doesn't always work well
-+     * with persistent (reused) connections.  One version of the
-+     * REQMOD code creates a fake ConnStateData, which doesn't have
-+     * an in.buf.  We want to make sure that the fake ConnStateData
-+     * doesn't get used here.
-+     */
-+    if (NULL == conn->in.buf) {
-+	debug(33, 1) ("clientReadRequest: FD %d aborted; conn->in.buf is NULL\n", fd);
-+	comm_close(fd);
-+	return;
-+    }
-+#endif
-     statCounter.syscalls.sock.reads++;
-     size = FD_READ_METHOD(fd, conn->in.buf + conn->in.offset, len);
-     if (size > 0) {
-@@ -3104,7 +3140,8 @@ clientReadRequest(int fd, void *data)
- 	    /* add to the client request queue */
- 	    for (H = &conn->chr; *H; H = &(*H)->next);
- 	    *H = http;
--	    conn->nrequests++;
-+	    F->pconn.uses++;
-+	    F->pconn.type = 0;
- 	    /*
- 	     * I wanted to lock 'http' here since its callback data for 
- 	     * clientLifetimeTimeout(), but there's no logical place to
-@@ -3274,7 +3311,7 @@ clientReadRequest(int fd, void *data)
- }
- 
- /* file_read like function, for reading body content */
--static void
-+void
- clientReadBody(request_t * request, char *buf, size_t size, CBCB * callback, void *cbdata)
- {
-     ConnStateData *conn = request->body_reader_data;
-@@ -3398,7 +3435,7 @@ clientProcessBody(ConnStateData * conn)
- }
- 
- /* Abort a body request */
--static void
-+void
- clientAbortBody(request_t * request)
- {
-     ConnStateData *conn = request->body_reader_data;
-@@ -3440,7 +3477,7 @@ requestTimeout(int fd, void *data)
- 	 * Some data has been sent to the client, just close the FD
- 	 */
- 	comm_close(fd);
--    } else if (conn->nrequests) {
-+    } else if (fd_table[fd].pconn.uses) {
- 	/*
- 	 * assume its a persistent connection; just close it
- 	 */
-@@ -3956,3 +3993,49 @@ varyEvaluateMatch(StoreEntry * entry, re
- 	}
-     }
- }
-+
-+#if HS_FEAT_ICAP
-+static int
-+clientIcapReqMod(clientHttpRequest * http)
-+{
-+    ErrorState *err;
-+    icap_service *service;
-+    if (http->flags.did_icap_reqmod)
-+	return 0;
-+    if (NULL == (service = icapService(ICAP_SERVICE_REQMOD_PRECACHE, http->request)))
-+	return 0;
-+    debug(33, 3) ("clientIcapReqMod: calling icapReqModStart for %p\n", http);
-+    /*
-+     * Note, we pass 'start' and 'log_addr' to ICAP so the access.log
-+     * entry comes out right.  The 'clientHttpRequest' created by
-+     * the ICAP side is the one that gets logged.  The first
-+     * 'clientHttpRequest' does not get logged because its out.size
-+     * is zero and log_type is unset.
-+     */
-+    http->icap_reqmod = icapReqModStart(service,
-+	http->uri,
-+	http->request,
-+	http->conn->fd,
-+	http->start,
-+	http->conn->log_addr,
-+	(void *) http->conn);
-+    if (NULL == http->icap_reqmod) {
-+	return 0;
-+    } else if (-1 == (int) http->icap_reqmod) {
-+	/* produce error */
-+	http->icap_reqmod = NULL;
-+	debug(33, 2) ("clientIcapReqMod: icap told us to send an error\n");
-+	http->log_type = LOG_TCP_DENIED;
-+	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
-+	err->xerrno = ETIMEDOUT;
-+	err->request = requestLink(http->request);
-+	err->src_addr = http->conn->peer.sin_addr;
-+	http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags);
-+	errorAppendEntry(http->entry, err);
-+	return 1;
-+    }
-+    cbdataLock(http->icap_reqmod);
-+    http->flags.did_icap_reqmod = 1;
-+    return 1;
-+}
-+#endif
-Index: src/comm.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/comm.c,v
-retrieving revision 1.18.6.6
-retrieving revision 1.18.6.2.12.9
-diff -p -u -b -r1.18.6.6 -r1.18.6.2.12.9
---- src/comm.c	11 Sep 2005 02:13:22 -0000	1.18.6.6
-+++ src/comm.c	23 Nov 2005 20:33:06 -0000	1.18.6.2.12.9
-@@ -653,8 +653,8 @@ comm_close(int fd)
- #endif
-     CommWriteStateCallbackAndFree(fd, COMM_ERR_CLOSING);
-     commCallCloseHandlers(fd);
--    if (F->uses)		/* assume persistent connect count */
--	pconnHistCount(1, F->uses);
-+    if (F->pconn.uses)
-+	pconnHistCount(F->pconn.type, F->pconn.uses);
- #if USE_SSL
-     if (F->ssl) {
- 	SSL_free(F->ssl);
-Index: src/enums.h
-===================================================================
-RCS file: /cvsroot/squid/squid/src/enums.h,v
-retrieving revision 1.29.2.18
-retrieving revision 1.29.2.8.2.17
-diff -p -u -b -r1.29.2.18 -r1.29.2.8.2.17
---- src/enums.h	12 Nov 2005 03:13:48 -0000	1.29.2.18
-+++ src/enums.h	23 Nov 2005 20:38:56 -0000	1.29.2.8.2.17
-@@ -93,6 +93,7 @@ typedef enum {
-     ERR_ONLY_IF_CACHED_MISS,	/* failure to satisfy only-if-cached request */
-     ERR_TOO_BIG,
-     TCP_RESET,
-+    ERR_ICAP_FAILURE,
-     ERR_INVALID_RESP,
-     ERR_MAX
- } err_type;
-@@ -438,6 +439,9 @@ typedef enum {
-     PROTO_WHOIS,
-     PROTO_INTERNAL,
-     PROTO_HTTPS,
-+#if HS_FEAT_ICAP
-+    PROTO_ICAP,
-+#endif
-     PROTO_MAX
- } protocol_t;
- 
-@@ -610,6 +614,12 @@ typedef enum {
-     MEM_TLV,
-     MEM_SWAP_LOG_DATA,
-     MEM_CLIENT_REQ_BUF,
-+#if HS_FEAT_ICAP
-+    MEM_ICAP_OPT_DATA,
-+    MEM_ICAP_SERVICE_LIST,
-+    MEM_ICAP_CLASS,
-+    MEM_ICAP_ACCESS,
-+#endif
-     MEM_MAX
- } mem_type;
- 
-@@ -709,9 +719,14 @@ typedef enum {
-     CBDATA_RemovalPolicyWalker,
-     CBDATA_RemovalPurgeWalker,
-     CBDATA_store_client,
-+#ifdef HS_FEAT_ICAP
-+    CBDATA_IcapStateData,
-+    CBDATA_icap_service,
-+#endif
-     CBDATA_FIRST_CUSTOM_TYPE = 1000
- } cbdata_type;
- 
-+
- /*
-  * Return codes from checkVary(request)
-  */
-@@ -742,4 +757,68 @@ enum {
- 
- #endif
- 
-+#if HS_FEAT_ICAP
-+typedef enum {
-+    ICAP_STATUS_NONE = 0,
-+    ICAP_STATUS_CONTINUE = 100,
-+    ICAP_STATUS_SWITCHING_PROTOCOLS = 101,
-+    ICAP_STATUS_STATUS_OK = 200,
-+    ICAP_CREATED = 201,
-+    ICAP_STATUS_ACCEPTED = 202,
-+    ICAP_STATUS_NON_AUTHORITATIVE_INFORMATION = 203,
-+    ICAP_STATUS_NO_MODIFICATION_NEEDED = 204,
-+    ICAP_STATUS_RESET_CONTENT = 205,
-+    ICAP_STATUS_PARTIAL_CONTENT = 206,
-+    ICAP_STATUS_MULTIPLE_CHOICES = 300,
-+    ICAP_STATUS_MOVED_PERMANENTLY = 301,
-+    ICAP_STATUS_MOVED_TEMPORARILY = 302,
-+    ICAP_STATUS_SEE_OTHER = 303,
-+    ICAP_STATUS_NOT_MODIFIED = 304,
-+    ICAP_STATUS_USE_PROXY = 305,
-+    ICAP_STATUS_BAD_REQUEST = 400,
-+    ICAP_STATUS_UNAUTHORIZED = 401,
-+    ICAP_STATUS_PAYMENT_REQUIRED = 402,
-+    ICAP_STATUS_FORBIDDEN = 403,
-+    ICAP_STATUS_SERVICE_NOT_FOUND = 404,
-+    ICAP_STATUS_METHOD_NOT_ALLOWED = 405,
-+    ICAP_STATUS_NOT_ACCEPTABLE = 406,
-+    ICAP_STATUS_PROXY_AUTHENTICATION_REQUIRED = 407,
-+    ICAP_STATUS_REQUEST_TIMEOUT = 408,
-+    ICAP_STATUS_CONFLICT = 409,
-+    ICAP_STATUS_GONE = 410,
-+    ICAP_STATUS_LENGTH_REQUIRED = 411,
-+    ICAP_STATUS_PRECONDITION_FAILED = 412,
-+    ICAP_STATUS_REQUEST_ENTITY_TOO_LARGE = 413,
-+    ICAP_STATUS_REQUEST_URI_TOO_LARGE = 414,
-+    ICAP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415,
-+    ICAP_STATUS_INTERNAL_SERVER_ERROR = 500,
-+    ICAP_STATUS_NOT_IMPLEMENTED = 501,
-+    ICAP_STATUS_BAD_GATEWAY = 502,
-+    ICAP_STATUS_SERVICE_OVERLOADED = 503,
-+    ICAP_STATUS_GATEWAY_TIMEOUT = 504,
-+    ICAP_STATUS_ICAP_VERSION_NOT_SUPPORTED = 505,
-+    ICAP_STATUS_INVALID_HEADER = 600
-+} icap_status;
-+
-+/*
-+ * these values are used as index in an array, so it seems to be better to 
-+ * assign some numbers
-+ */
-+typedef enum {
-+    ICAP_SERVICE_REQMOD_PRECACHE = 0,
-+    ICAP_SERVICE_REQMOD_POSTCACHE = 1,
-+    ICAP_SERVICE_RESPMOD_PRECACHE = 2,
-+    ICAP_SERVICE_RESPMOD_POSTCACHE = 3,
-+    ICAP_SERVICE_MAX = 4
-+} icap_service_t;
-+
-+typedef enum {
-+    ICAP_METHOD_NONE,
-+    ICAP_METHOD_OPTION,
-+    ICAP_METHOD_REQMOD,
-+    ICAP_METHOD_RESPMOD
-+} icap_method_t;
-+
-+#endif /* HS_FEAT_ICAP */
-+
- #endif /* SQUID_ENUMS_H */
-Index: src/forward.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/forward.c,v
-retrieving revision 1.13.6.16
-retrieving revision 1.13.6.3.2.16
-diff -p -u -b -r1.13.6.16 -r1.13.6.3.2.16
---- src/forward.c	11 Mar 2006 03:16:31 -0000	1.13.6.16
-+++ src/forward.c	16 May 2006 17:56:58 -0000	1.13.6.3.2.16
-@@ -251,7 +251,8 @@ fwdConnectDone(int server_fd, int status
-     } else {
- 	debug(17, 3) ("fwdConnectDone: FD %d: '%s'\n", server_fd, storeUrl(fwdState->entry));
- 	fd_note(server_fd, storeUrl(fwdState->entry));
--	fd_table[server_fd].uses++;
-+	fd_table[server_fd].pconn.uses++;
-+	fd_table[server_fd].pconn.type = 1;
- 	if (fs->peer)
- 	    peerConnectSucceded(fs->peer);
- 	fwdDispatch(fwdState);
-@@ -700,6 +701,8 @@ fwdCheckDeferRead(int fd, void *data)
- void
- fwdFail(FwdState * fwdState, ErrorState * errorState)
- {
-+    if (NULL == fwdState)
-+	return;
-     debug(17, 3) ("fwdFail: %s \"%s\"\n\t%s\n",
- 	err_type_str[errorState->type],
- 	httpStatusString(errorState->http_status),
-@@ -738,6 +741,8 @@ fwdPeerClosed(int fd, void *data)
- void
- fwdUnregister(int fd, FwdState * fwdState)
- {
-+    if (NULL == fwdState)
-+	return;
-     debug(17, 3) ("fwdUnregister: %s\n", storeUrl(fwdState->entry));
-     assert(fd == fwdState->server_fd);
-     assert(fd > -1);
-@@ -754,7 +759,10 @@ fwdUnregister(int fd, FwdState * fwdStat
- void
- fwdComplete(FwdState * fwdState)
- {
--    StoreEntry *e = fwdState->entry;
-+    StoreEntry *e;
-+    if (NULL == fwdState)
-+	return;
-+    e = fwdState->entry;
-     assert(e->store_status == STORE_PENDING);
-     debug(17, 3) ("fwdComplete: %s\n\tstatus %d\n", storeUrl(e),
- 	e->mem_obj->reply->sline.status);
-Index: src/globals.h
-===================================================================
-RCS file: /cvsroot/squid/squid/src/globals.h,v
-retrieving revision 1.14.6.7
-retrieving revision 1.14.6.3.2.5
-diff -p -u -b -r1.14.6.7 -r1.14.6.3.2.5
---- src/globals.h	14 Jun 2005 02:15:00 -0000	1.14.6.7
-+++ src/globals.h	12 Sep 2005 18:34:41 -0000	1.14.6.3.2.5
-@@ -165,6 +165,9 @@ extern char *WIN32_OS_string;	/* NULL */
- #if HAVE_SBRK
- extern void *sbrk_start;	/* 0 */
- #endif
-+#if HS_FEAT_ICAP
-+extern char *icap_service_type_str[];
-+#endif
- extern int opt_send_signal;	/* -1 */
- extern int opt_no_daemon;	/* 0 */
- 
-Index: src/http.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/http.c,v
-retrieving revision 1.17.6.32
-retrieving revision 1.17.6.3.6.40
-diff -p -u -b -r1.17.6.32 -r1.17.6.3.6.40
---- src/http.c	19 Oct 2005 02:13:21 -0000	1.17.6.32
-+++ src/http.c	17 Feb 2006 12:45:21 -0000	1.17.6.3.6.40
-@@ -47,7 +47,7 @@ static CWCB httpSendRequestEntry;
- 
- static PF httpReadReply;
- static void httpSendRequest(HttpStateData *);
--static PF httpStateFree;
-+PF httpStateFree;
- static PF httpTimeout;
- static void httpCacheNegatively(StoreEntry *);
- static void httpMakePrivate(StoreEntry *);
-@@ -55,11 +55,12 @@ static void httpMakePublic(StoreEntry *)
- static int httpCachableReply(HttpStateData *);
- static void httpMaybeRemovePublic(StoreEntry *, http_status);
- 
--static void
-+void
- httpStateFree(int fd, void *data)
- {
-     HttpStateData *httpState = data;
- #if DELAY_POOLS
-+    if (fd >= 0)
-     delayClearNoDelay(fd);
- #endif
-     if (httpState == NULL)
-@@ -79,6 +80,9 @@ httpStateFree(int fd, void *data)
-     requestUnlink(httpState->orig_request);
-     httpState->request = NULL;
-     httpState->orig_request = NULL;
-+#if HS_FEAT_ICAP
-+    cbdataUnlock(httpState->icap_writer);
-+#endif
-     cbdataFree(httpState);
- }
- 
-@@ -392,7 +396,7 @@ httpMakeVaryMark(request_t * request, Ht
- }
- 
- /* rewrite this later using new interfaces @?@ */
--static void
-+void
- httpProcessReplyHeader(HttpStateData * httpState, const char *buf, int size)
- {
-     StoreEntry *entry = httpState->entry;
-@@ -527,24 +531,35 @@ httpPconnTransferDone(HttpStateData * ht
-     MemObject *mem = httpState->entry->mem_obj;
-     HttpReply *reply = mem->reply;
-     squid_off_t clen;
-+    squid_off_t content_bytes_read;
-     debug(11, 3) ("httpPconnTransferDone: FD %d\n", httpState->fd);
-     debug(11, 5) ("httpPconnTransferDone: content_length=%" PRINTF_OFF_T "\n",
- 	reply->content_length);
-     /* If we haven't seen the end of reply headers, we are not done */
--    if (httpState->reply_hdr_state < 2)
-+    if (httpState->reply_hdr_state < 2) {
-+	debug(11, 3) ("httpPconnTransferDone: reply_hdr_state=%d, returning 0\n",
-+	    httpState->reply_hdr_state);
- 	return 0;
-+    }
-     clen = httpReplyBodySize(httpState->request->method, reply);
-+#ifdef HS_FEAT_ICAP
-+    if (httpState->icap_writer) {
-+	content_bytes_read = httpState->icap_writer->fake_content_length;
-+	debug(11, 3) ("using fake conten length %" PRINTF_OFF_T "\n", content_bytes_read);
-+    } else
-+#endif
-+	content_bytes_read = mem->inmem_hi;
-     /* If the body size is unknown we must wait for EOF */
-     if (clen < 0)
- 	return 0;
-     /* Barf if we got more than we asked for */
--    if (mem->inmem_hi > clen + reply->hdr_sz)
-+    if (content_bytes_read > clen + reply->hdr_sz)
- 	return -1;
-     /* If there is no message body, we can be persistent */
-     if (0 == clen)
- 	return 1;
-     /* If the body size is known, we must wait until we've gotten all of it.  */
--    if (mem->inmem_hi < clen + reply->hdr_sz)
-+    if (content_bytes_read < clen + reply->hdr_sz)
- 	return 0;
-     /* We got it all */
-     return 1;
-@@ -568,6 +583,17 @@ httpReadReply(int fd, void *data)
-     delay_id delay_id;
- #endif
- 
-+#if HS_FEAT_ICAP
-+    if (httpState->icap_writer) {
-+	if (!httpState->icap_writer->respmod.entry) {
-+	    debug(11, 3) ("httpReadReply: FD: %d: icap respmod aborded!\n", fd);
-+	    comm_close(fd);
-+	    return;
-+	}
-+	/*The folowing entry can not be marked as aborted.  
-+	 * The StoreEntry icap_writer->respmod.entry used when the icap_write used...... */
-+    } else
-+#endif
-     if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
- 	comm_close(fd);
- 	return;
-@@ -579,6 +605,37 @@ httpReadReply(int fd, void *data)
-     else
- 	delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz);
- #endif
-+
-+#if HS_FEAT_ICAP
-+    if (httpState->icap_writer) {
-+	IcapStateData *icap = httpState->icap_writer;
-+	/*
-+	 * Ok we have a received a response from the web server, so try to 
-+	 * connect the icap server if it's the first attemps. If we try
-+	 * to connect to the icap server, defer this request (do not read
-+	 * the buffer), and defer until icapConnectOver() is not called.
-+	 */
-+	if (icap->flags.connect_requested == 0) {
-+	    debug(81, 2) ("icapSendRespMod: Create a new connection to icap server\n");
-+	    if (!icapConnect(icap, icapConnectOver)) {
-+		debug(81, 2) ("icapSendRespMod: Something strange while creating a socket to icap server\n");
-+		commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
-+		return;
-+	    }
-+	    debug(81, 2) ("icapSendRespMod: new connection to icap server (using FD=%d)\n", icap->icap_fd);
-+	    icap->flags.connect_requested = 1;
-+	    /* Wait for more data or EOF condition */
-+	    commSetTimeout(fd, httpState->flags.keepalive_broken ? 10 : Config.Timeout.read, NULL, NULL);
-+	    commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
-+	    return;
-+	}
-+
-+       if(icap->flags.no_content == 1) {
-+	 commSetDefer(fd, fwdCheckDeferRead, icap->respmod.entry);
-+       }
-+    }
-+#endif
-+
-     errno = 0;
-     statCounter.syscalls.sock.reads++;
-     len = FD_READ_METHOD(fd, buf, read_sz);
-@@ -595,7 +652,13 @@ httpReadReply(int fd, void *data)
- 	    clen >>= 1;
- 	IOStats.Http.read_hist[bin]++;
-     }
--    if (!httpState->reply_hdr.size && len > 0 && fd_table[fd].uses > 1) {
-+#ifdef HS_FEAT_ICAP
-+    if (httpState->icap_writer)
-+	(void) 0;
-+    else
-+#endif
-+
-+    if (!httpState->reply_hdr.size && len > 0 && fd_table[fd].pconn.uses > 1) {
- 	/* Skip whitespace */
- 	while (len > 0 && xisspace(*buf))
- 	    xmemmove(buf, buf + 1, len--);
-@@ -625,6 +688,12 @@ httpReadReply(int fd, void *data)
-     } else if (len == 0) {
- 	/* Connection closed; retrieval done. */
- 	httpState->eof = 1;
-+#ifdef HS_FEAT_ICAP
-+	if (httpState->icap_writer && cbdataValid(httpState->icap_writer)) {
-+	    debug(81, 3) ("httpReadReply: EOF for ICAP writer\n");
-+	    icapSendRespMod(httpState->icap_writer, buf, len, 1);
-+	}
-+#endif
- 	if (httpState->reply_hdr_state < 2)
- 	    /*
- 	     * Yes Henrik, there is a point to doing this.  When we
-@@ -677,7 +746,28 @@ httpReadReply(int fd, void *data)
- 		    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
- 	    }
- 	}
-+#ifdef HS_FEAT_ICAP
-+	if (httpState->icap_writer) {
-+	    debug(81, 5) ("calling icapSendRespMod from %s:%d\n", __FILE__, __LINE__);
-+	    if (cbdataValid(httpState->icap_writer)) {
-+		icapSendRespMod(httpState->icap_writer, buf, len, 0);
-+		httpState->icap_writer->fake_content_length += len;
-+	    }
-+	} else
-+#endif
- 	storeAppend(entry, buf, len);
-+
-+
-+	debug(11, 5) ("httpReadReply: after storeAppend FD %d read %d\n", fd, len);
-+#if HS_FEAT_ICAP
-+	if (httpState->icap_writer) {
-+	    if (!httpState->icap_writer->respmod.entry) {
-+		debug(11, 3) ("httpReadReply: FD: %d: icap respmod aborded!\n", fd);
-+		comm_close(fd);
-+		return;
-+	    }
-+	} else
-+#endif
- 	if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
- 	    /*
- 	     * the above storeAppend() call could ABORT this entry,
-@@ -724,10 +814,21 @@ httpReadReply(int fd, void *data)
- 			    ("httpReadReply: Excess data from \"%s %s\"\n",
- 			    RequestMethodStr[httpState->orig_request->method],
- 			    storeUrl(entry));
-+#ifdef HS_FEAT_ICAP
-+			if (httpState->icap_writer) {
-+			    debug(81, 5) ("calling icapSendRespMod from %s:%d\n", __FILE__, __LINE__);
-+			    icapSendRespMod(httpState->icap_writer, buf, len, 0);
-+			    httpState->icap_writer->fake_content_length += len;
-+			} else
-+#endif
- 			storeAppend(entry, buf, len);
- 			keep_alive = 0;
- 		    }
- 		}
-+#ifdef HS_FEAT_ICAP
-+		if (httpState->icap_writer)
-+		    icapSendRespMod(httpState->icap_writer, NULL, 0, 1);
-+#endif
- 		if (keep_alive) {
- 		    /* yes we have to clear all these! */
- 		    commSetDefer(fd, NULL, NULL);
-@@ -766,6 +867,10 @@ httpReadReply(int fd, void *data)
- 		("httpReadReply: Excess data from \"%s %s\"\n",
- 		RequestMethodStr[httpState->orig_request->method],
- 		storeUrl(entry));
-+#ifdef HS_FEAT_ICAP
-+	    if (httpState->icap_writer)
-+		icapSendRespMod(httpState->icap_writer, NULL, 0, 1);
-+#endif
- 	    fwdComplete(httpState->fwd);
- 	    comm_close(fd);
- 	    return;
-@@ -776,6 +881,34 @@ httpReadReply(int fd, void *data)
-     }
- }
- 
-+#ifdef HS_FEAT_ICAP
-+static int
-+httpReadReplyWaitForIcap(int fd, void *data)
-+{
-+    HttpStateData *httpState = data;
-+    if (NULL == httpState->icap_writer)
-+	return 0;
-+    /* 
-+     * Do not defer when we are not connected to the icap server.
-+     * Defer when the icap server connection is not established but pending
-+     * Defer when the icap server is busy (writing on the socket)
-+     */
-+    debug(11, 5) ("httpReadReplyWaitForIcap: FD %d, connect_requested=%d\n",
-+	fd, httpState->icap_writer->flags.connect_requested);
-+    if (!httpState->icap_writer->flags.connect_requested)
-+	return 0;
-+    debug(11, 5) ("httpReadReplyWaitForIcap: FD %d, connect_pending=%d\n",
-+	fd, httpState->icap_writer->flags.connect_pending);
-+    if (httpState->icap_writer->flags.connect_pending)
-+	return 1;
-+    debug(11, 5) ("httpReadReplyWaitForIcap: FD %d, write_pending=%d\n",
-+	fd, httpState->icap_writer->flags.write_pending);
-+    if (httpState->icap_writer->flags.write_pending)
-+	return 1;
-+    return 0;
-+}
-+#endif
-+
- /* This will be called when request write is complete. Schedule read of
-  * reply. */
- static void
-@@ -803,6 +936,63 @@ httpSendComplete(int fd, char *bufnotuse
- 	comm_close(fd);
- 	return;
-     } else {
-+	/* Schedule read reply. */
-+#ifdef HS_FEAT_ICAP
-+	if (icapService(ICAP_SERVICE_RESPMOD_PRECACHE, httpState->orig_request)) {
-+	    httpState->icap_writer = icapRespModStart(
-+		ICAP_SERVICE_RESPMOD_PRECACHE,
-+		httpState->orig_request, httpState->entry, httpState->flags);
-+	    if (-1 == (int) httpState->icap_writer) {
-+		/* TODO: send error here and exit */
-+		ErrorState *err;
-+		httpState->icap_writer = 0;
-+		err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
-+		err->xerrno = errno;
-+		err->request = requestLink(httpState->orig_request);
-+		errorAppendEntry(entry, err);
-+		comm_close(fd);
-+		return;
-+	    } else if (httpState->icap_writer) {
-+		request_flags fake_flags = httpState->orig_request->flags;
-+		method_t fake_method = entry->mem_obj->method;
-+		const char *fake_msg = "this is a fake entry for "
-+		" response sent to an ICAP RESPMOD server";
-+		cbdataLock(httpState->icap_writer);
-+		/*
-+		 * this httpState will give the data it reads to
-+		 * the icap server, rather than put it into
-+		 * a StoreEntry
-+		 */
-+		storeUnlockObject(httpState->entry);
-+		storeUnregisterAbort(httpState->entry);
-+		/*
-+		 * create a bogus entry because the code assumes one is
-+		 * always there.
-+		 */
-+		fake_flags.cachable = 0;
-+		fake_flags.hierarchical = 0;	/* force private key */
-+		httpState->entry = storeCreateEntry("fake", "fake", fake_flags, fake_method);
-+		storeAppend(httpState->entry, fake_msg, strlen(fake_msg));
-+		/*
-+		 * pull a switcheroo on fwdState->entry.
-+		 */
-+		storeUnlockObject(httpState->fwd->entry);
-+		httpState->fwd->entry = httpState->entry;
-+		storeLockObject(httpState->fwd->entry);
-+		/*
-+		 * Note that we leave fwdState connected to httpState,
-+		 * but we changed the entry.  So when fwdComplete
-+		 * or whatever is called it does no harm -- its
-+		 * just the fake entry.
-+		 */
-+	    } else {
-+		/*
-+		 * failed to open connection to ICAP server. 
-+		 * But bypass request, so just continue here.
-+		 */
-+	    }
-+	}
-+#endif
- 	/*
- 	 * Set the read timeout here because it hasn't been set yet.
- 	 * We only set the read timeout after the request has been
-@@ -811,8 +1001,18 @@ httpSendComplete(int fd, char *bufnotuse
- 	 * the timeout for POST/PUT requests that have very large
- 	 * request bodies.
- 	 */
-+
-+	/* removed in stable5:
-+	 * commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
-+	 */
- 	commSetTimeout(fd, Config.Timeout.read, httpTimeout, httpState);
--	commSetDefer(fd, fwdCheckDeferRead, entry);
-+#ifdef HS_FEAT_ICAP
-+	if (httpState->icap_writer) {
-+	    debug(11, 5) ("FD %d, setting httpReadReplyWaitForIcap\n", httpState->fd);
-+	    commSetDefer(httpState->fd, httpReadReplyWaitForIcap, httpState);
-+	} else
-+#endif
-+	    commSetDefer(httpState->fd, fwdCheckDeferRead, entry);
-     }
-     httpState->flags.request_sent = 1;
- }
-@@ -1010,8 +1210,11 @@ httpBuildRequestHeader(request_t * reque
- 	if (!EBIT_TEST(cc->mask, CC_MAX_AGE)) {
- 	    const char *url = entry ? storeUrl(entry) : urlCanonical(orig_request);
- 	    httpHdrCcSetMaxAge(cc, getMaxAge(url));
-+#ifndef HS_FEAT_ICAP
-+	    /* Don;t bother - if  the url you want to cache is redirected? */
- 	    if (strLen(request->urlpath))
- 		assert(strstr(url, strBuf(request->urlpath)));
-+#endif
- 	}
- 	/* Set no-cache if determined needed but not found */
- 	if (orig_request->flags.nocache && !httpHeaderHas(hdr_in, HDR_PRAGMA))
-@@ -1119,6 +1322,7 @@ httpStart(FwdState * fwd)
-     int fd = fwd->server_fd;
-     HttpStateData *httpState;
-     request_t *proxy_req;
-+    /* ErrorState *err; */
-     request_t *orig_req = fwd->request;
-     debug(11, 3) ("httpStart: \"%s %s\"\n",
- 	RequestMethodStr[orig_req->method],
-@@ -1156,12 +1360,22 @@ httpStart(FwdState * fwd)
- 	httpState->request = requestLink(orig_req);
- 	httpState->orig_request = requestLink(orig_req);
-     }
-+#ifdef HS_FEAT_ICAP
-+    if (icapService(ICAP_SERVICE_REQMOD_POSTCACHE, httpState->orig_request)) {
-+	httpState->icap_writer = icapRespModStart(ICAP_SERVICE_REQMOD_POSTCACHE,
-+	    httpState->orig_request, httpState->entry, httpState->flags);
-+	if (httpState->icap_writer) {
-+	    return;
-+	}
-+    }
-+#endif
-     /*
-      * register the handler to free HTTP state data when the FD closes
-      */
-     comm_add_close_handler(fd, httpStateFree, httpState);
-     statCounter.server.all.requests++;
-     statCounter.server.http.requests++;
-+
-     httpSendRequest(httpState);
-     /*
-      * We used to set the read timeout here, but not any more.
-Index: src/icap_common.c
-===================================================================
-RCS file: src/icap_common.c
-diff -N src/icap_common.c
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ src/icap_common.c	16 Feb 2006 17:21:45 -0000	1.1.2.40
-@@ -0,0 +1,817 @@
-+/*
-+ * $Id$
-+ *
-+ * DEBUG: section 81    Internet Content Adaptation Protocol (ICAP) Client
-+ * AUTHOR: Geetha Manjunath, Hewlett Packard Company
-+ *
-+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
-+ * ----------------------------------------------------------
-+ *
-+ *  Squid is the result of efforts by numerous individuals from
-+ *  the Internet community; see the CONTRIBUTORS file for full
-+ *  details.   Many organizations have provided support for Squid's
-+ *  development; see the SPONSORS file for full details.  Squid is
-+ *  Copyrighted (C) 2001 by the Regents of the University of
-+ *  California; see the COPYRIGHT file for full details.  Squid
-+ *  incorporates software developed and/or copyrighted by other
-+ *  sources; see the CREDITS file for full details.
-+ *
-+ *  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, USA.
-+ *
-+ */
-+
-+/* _GNU_SOURCE is required for strcasestr */
-+#define _GNU_SOURCE 1
-+
-+#include "squid.h"
-+#include "util.h"
-+
-+extern PF httpStateFree;
-+
-+#define EXPECTED_ICAP_HEADER_LEN 256
-+#define ICAP_OPTIONS_REQUEST
-+
-+
-+void
-+icapInit()
-+{
-+#ifdef ICAP_OPTIONS_REQUEST
-+    if (Config.icapcfg.onoff) {
-+	icapOptInit();
-+    }
-+#endif
-+}
-+
-+void
-+icapClose()
-+{
-+    icapOptShutdown();
-+}
-+
-+/*
-+ * search for a HTTP-like header in the buffer. 
-+ * Note, buf must be 0-terminated
-+ *
-+ * This function is not very good.  It should probably look for
-+ * header tokens only at the start of a line, not just anywhere in
-+ * the buffer.
-+ */
-+int
-+icapFindHeader(const char *buf, const char *hdr, const char **Start,
-+    const char **End)
-+{
-+    const char *start = NULL;
-+    const char *end = NULL;
-+    start = strcasestr(buf, hdr);
-+    if (NULL == start)
-+	return 0;
-+    end = start + strcspn(start, "\r\n");
-+    if (start == end)
-+	return 0;
-+    *Start = start;
-+    *End = end;
-+    return 1;
-+}
-+
-+/* 
-+ * parse the contents of the encapsulated header (buffer between enc_start
-+ * and enc_end) and put the result into IcapStateData
-+ */
-+void
-+icapParseEncapsulated(IcapStateData * icap, const char *enc_start,
-+    const char *enc_end)
-+{
-+    char *current, *end;
-+
-+    assert(icap);
-+    assert(enc_start);
-+    assert(enc_end);
-+
-+    current = strchr(enc_start, ':');
-+    current++;
-+    while (current < enc_end) {
-+	while (isspace(*current))
-+	    current++;
-+	if (!strncmp(current, "res-hdr=", 8)) {
-+	    current += 8;
-+	    icap->enc.res_hdr = strtol(current, &end, 10);
-+	} else if (!strncmp(current, "req-hdr=", 8)) {
-+	    current += 8;
-+	    icap->enc.req_hdr = strtol(current, &end, 10);
-+	} else if (!strncmp(current, "null-body=", 10)) {
-+	    current += 10;
-+	    icap->enc.null_body = strtol(current, &end, 10);
-+	} else if (!strncmp(current, "res-body=", 9)) {
-+	    current += 9;
-+	    icap->enc.res_body = strtol(current, &end, 10);
-+	} else if (!strncmp(current, "req-body=", 9)) {
-+	    current += 9;
-+	    icap->enc.req_body = strtol(current, &end, 10);
-+	} else if (!strncmp(current, "opt-body=", 9)) {
-+	    current += 9;
-+	    icap->enc.opt_body = strtol(current, &end, 10);
-+	} else {
-+	    /* invalid header */
-+	    debug(81, 5) ("icapParseEncapsulated: error in: %s\n", current);
-+	    return;
-+	}
-+	current = end;
-+	current = strchr(current, ',');
-+	if (current == NULL)
-+	    break;
-+	else
-+	    current++;		/* skip ',' */
-+    }
-+    debug(81,
-+	3) ("icapParseEncapsulated: res-hdr=%d, req-hdr=%d, null-body=%d, "
-+	"res-body=%d, req-body=%d, opt-body=%d\n", icap->enc.res_hdr,
-+	icap->enc.req_hdr, icap->enc.null_body, icap->enc.res_body,
-+	icap->enc.req_body, icap->enc.opt_body);
-+
-+}
-+
-+icap_service *
-+icapService(icap_service_t type, request_t * r)
-+{
-+    icap_service_list *isl_iter;
-+    int is_iter;
-+    int nb_unreachable = 0;
-+    icap_service *unreachable_one = NULL;
-+
-+    debug(81, 8) ("icapService: type=%s\n", icapServiceToStr(type));
-+    if (NULL == r) {
-+	debug(81, 8) ("icapService: no request_t\n");
-+	return NULL;
-+    }
-+    if (NULL == r->class) {
-+	debug(81, 8) ("icapService: no class\n");
-+	return NULL;
-+    }
-+    for (isl_iter = r->class->isl; isl_iter; isl_iter = isl_iter->next) {
-+	/* TODO:luc: Do a round-robin, choose a random value ? 
-+	 * For now, we use a simple round robin with checking is the
-+	 * icap server is available */
-+	is_iter = isl_iter->last_service_used;
-+	do {
-+	    is_iter = (is_iter + 1) % isl_iter->nservices;
-+	    debug(81, 8) ("icapService: checking service %s/id=%d\n",
-+		isl_iter->services[is_iter]->name, is_iter);
-+	    if (type == isl_iter->services[is_iter]->type) {
-+		if (!isl_iter->services[is_iter]->unreachable) {
-+		    debug(81, 8) ("icapService: found service %s/id=%d\n",
-+			isl_iter->services[is_iter]->name, is_iter);
-+		    isl_iter->last_service_used = is_iter;
-+		    return isl_iter->services[is_iter];
-+		}
-+		debug(81,
-+		    8)
-+		    ("icapService: found service %s/id=%d, but it's unreachable. I don't want to use it\n",
-+		    isl_iter->services[is_iter]->name, is_iter);
-+		unreachable_one = isl_iter->services[is_iter];
-+		nb_unreachable++;
-+		/* FIXME:luc: in response mod, if we return an NULL pointer, user can bypass
-+		 * the filter, is it normal ? */
-+	    }
-+	} while (is_iter != isl_iter->last_service_used);
-+    }
-+    debug(81, 8) ("icapService: no service found\n");
-+    isl_iter = r->class->isl;
-+
-+    if (nb_unreachable > 0) {
-+	debug(81,
-+	    8)
-+	    ("All the services are unreachable, returning an unreachable one\n");
-+	return unreachable_one;
-+    } else {
-+	return NULL;
-+    }
-+}
-+
-+int
-+icapConnect(IcapStateData * icap, CNCB * theCallback)
-+{
-+    int rc;
-+    icap->icap_fd = pconnPop(icap->current_service->hostname,
-+	icap->current_service->port);
-+    if (icap->icap_fd >= 0) {
-+	debug(81, 3) ("icapConnect: reused pconn FD %d\n", icap->icap_fd);
-+	fd_note(icap->icap_fd, icap->current_service->uri);
-+	comm_add_close_handler(icap->icap_fd, icapStateFree, icap);
-+	theCallback(icap->icap_fd, 0, icap);
-+	return 1;
-+    }
-+    icap->icap_fd = comm_open(SOCK_STREAM, 0, getOutgoingAddr(NULL), 0,
-+	COMM_NONBLOCKING, icap->current_service->uri);
-+    debug(81, 5) ("icapConnect: new socket, FD %d, local address %s\n",
-+	icap->icap_fd, inet_ntoa(getOutgoingAddr(NULL)));
-+    if (icap->icap_fd < 0) {
-+	icapStateFree(-1, icap);	/* XXX test */
-+	return 0;
-+    }
-+    icap->flags.connect_pending = 1;
-+    /*
-+     * Configure timeout and close handler before calling
-+     * connect because commConnectStart() might get an error
-+     * immediately and close the descriptor before it returns.
-+     */
-+    commSetTimeout(icap->icap_fd, Config.Timeout.connect,
-+	icapConnectTimeout, icap);
-+    comm_add_close_handler(icap->icap_fd, icapStateFree, icap);
-+    /*
-+     * This sucks.  commConnectStart() may fail before returning,
-+     * so lets lock the data and check its validity afterwards.
-+     */
-+    cbdataLock(icap);
-+    commConnectStart(icap->icap_fd,
-+	icap->current_service->hostname,
-+	icap->current_service->port, theCallback, icap);
-+    rc = cbdataValid(icap);
-+    cbdataUnlock(icap);
-+    debug(81, 3) ("icapConnect: returning %d\n", rc);
-+    return rc;
-+}
-+
-+IcapStateData *
-+icapAllocate(void)
-+{
-+    IcapStateData *icap;
-+
-+    if (!Config.icapcfg.onoff)
-+	return 0;
-+
-+    icap = cbdataAlloc(IcapStateData);
-+    icap->icap_fd = -1;
-+    icap->enc.res_hdr = -1;
-+    icap->enc.res_body = -1;
-+    icap->enc.req_hdr = -1;
-+    icap->enc.req_body = -1;
-+    icap->enc.opt_body = -1;
-+    icap->enc.null_body = -1;
-+    icap->chunk_size = -1;
-+    memBufDefInit(&icap->icap_hdr);
-+
-+    debug(81, 3) ("New ICAP state\n");
-+    return icap;
-+}
-+
-+void
-+icapStateFree(int fd, void *data)
-+{
-+    IcapStateData *icap = data;
-+    debug(81, 3) ("icapStateFree: FD %d, icap %p\n", fd, icap);
-+    assert(icap);
-+    assert(-1 == fd || fd == icap->icap_fd);
-+    if (icap->respmod.entry) {
-+	/*
-+	 * If we got some error on this side (like ECONNRESET)
-+	 * we must signal the other side(s) with a storeAbort()
-+	 * call.
-+	 */
-+	if (icap->respmod.entry->store_status != STORE_OK)
-+	    storeAbort(icap->respmod.entry);
-+	storeUnlockObject(icap->respmod.entry);
-+	icap->respmod.entry = NULL;
-+    }
-+    requestUnlink(icap->request);
-+    icap->request = NULL;
-+    if (!memBufIsNull(&icap->icap_hdr))
-+	memBufClean(&icap->icap_hdr);
-+    if (!memBufIsNull(&icap->respmod.buffer))
-+	memBufClean(&icap->respmod.buffer);
-+    if (!memBufIsNull(&icap->respmod.req_hdr_copy))
-+	memBufClean(&icap->respmod.req_hdr_copy);
-+    if (!memBufIsNull(&icap->respmod.resp_copy))
-+	memBufClean(&icap->respmod.resp_copy);
-+    if (!memBufIsNull(&icap->reqmod.hdr_buf))
-+	memBufClean(&icap->reqmod.hdr_buf);
-+    if (!memBufIsNull(&icap->reqmod.http_entity.buf))
-+	memBufClean(&icap->reqmod.http_entity.buf);
-+    if (!memBufIsNull(&icap->chunk_buf))
-+	memBufClean(&icap->chunk_buf);
-+    if (icap->httpState)
-+	httpStateFree(-1, icap->httpState);
-+    cbdataUnlock(icap->reqmod.client_cookie);
-+    cbdataFree(icap);
-+}
-+
-+void
-+icapConnectTimeout(int fd, void *data)
-+{
-+    IcapStateData *icap = data;
-+    debug(81, 3) ("icapConnectTimeout: FD %d, unreachable=1\n", fd);
-+    assert(fd == icap->icap_fd);
-+    icapOptSetUnreachable(icap->current_service);
-+    comm_close(fd);
-+}
-+
-+void
-+icapReadTimeout(int fd, void *data)
-+{
-+    IcapStateData *icap = data;
-+    assert(fd == icap->icap_fd);
-+    if (icap->flags.wait_for_preview_reply || icap->flags.http_server_eof) {
-+	debug(81, 3) ("icapReadTimeout: FD %d, unreachable=1\n", fd);
-+	icapOptSetUnreachable(icap->current_service);
-+    } else
-+	debug(81, 3) ("icapReadTimeout: FD %d, still reachable\n", fd);
-+    comm_close(fd);
-+}
-+
-+icap_service_t
-+icapServiceToType(const char *s)
-+{
-+    if (!strcmp(s, "reqmod_precache"))
-+	return ICAP_SERVICE_REQMOD_PRECACHE;
-+    if (!strcmp(s, "reqmod_postcache"))
-+	return ICAP_SERVICE_REQMOD_POSTCACHE;
-+    if (!strcmp(s, "respmod_precache"))
-+	return ICAP_SERVICE_RESPMOD_PRECACHE;
-+    if (!strcmp(s, "respmod_postcache"))
-+	return ICAP_SERVICE_RESPMOD_POSTCACHE;
-+    return ICAP_SERVICE_MAX;
-+}
-+
-+const char *
-+icapServiceToStr(const icap_service_t type)
-+{
-+    if (type >= 0 && type < ICAP_SERVICE_MAX)
-+	return icap_service_type_str[type];
-+    else
-+	return "error";
-+}
-+
-+
-+/* copied from clientAclChecklistCreate */
-+static aclCheck_t *
-+icapAclChecklistCreate(const acl_access * acl, const clientHttpRequest * http)
-+{
-+    aclCheck_t *ch;
-+    ConnStateData *conn = http->conn;
-+    ch = aclChecklistCreate(acl, http->request, 0);
-+    ch->conn = conn;
-+    cbdataLock(ch->conn);
-+    return ch;
-+}
-+
-+/*
-+ * check wether we do icap for a request
-+ */
-+int
-+icapCheckAcl(clientHttpRequest * http)
-+{
-+    icap_access *iter;
-+    aclCheck_t *icapChecklist;
-+
-+    for (iter = Config.icapcfg.access_head; iter; iter = iter->next) {
-+	acl_access *A = iter->access;
-+	icapChecklist = icapAclChecklistCreate(A, http);
-+	if (aclMatchAclList(A->acl_list, icapChecklist)) {
-+	    debug(81, 5) ("icapCheckAcl: match for class=%s\n",
-+		iter->class->name);
-+	    if (A->allow) {
-+		/* allow rule, do icap and use associated class */
-+		http->request->class = iter->class;
-+		aclChecklistFree(icapChecklist);
-+		return 1;
-+	    } else {
-+		/* deny rule, stop processing */
-+		aclChecklistFree(icapChecklist);
-+		return 0;
-+	    }
-+	}
-+	aclChecklistFree(icapChecklist);
-+    }
-+    return 0;
-+}
-+
-+/* icapLineLength
-+ *
-+ * returns the amount of data until lineending ( \r\n )
-+ * This function is NOT tolerant of variations of \r\n.
-+ */
-+size_t
-+icapLineLength(const char *start, int len)
-+{
-+    size_t lineLen = 0;
-+    char *end = (char *) memchr(start, '\r', len);
-+    if (NULL == end)
-+	return 0;
-+    end++;			/* advance to where '\n' should be */
-+    lineLen = end - start + 1;
-+    if (lineLen > len) {
-+	debug(0, 0) ("icapLineLength: warning lineLen (%d) > len (%d)\n",
-+	    lineLen, len);
-+	return 0;
-+    }
-+    if (*end != '\n') {
-+	debug(0, 0) ("icapLineLength: warning *end (%x) != '\\n'\n", *end);
-+	return 0;
-+    }
-+    debug(81, 7) ("icapLineLength: returning %d\n", lineLen);
-+    return lineLen;
-+}
-+
-+/*
-+ * return:
-+ *   -1 if EOF before getting end of ICAP header
-+ *    0 if we don't have the entire ICAP header yet
-+ *    1 if we got the whole header
-+ */
-+int
-+icapReadHeader(int fd, IcapStateData * icap, int *isIcap)
-+{
-+    int headlen = 0;
-+    int len = 0;
-+    int peek_sz = EXPECTED_ICAP_HEADER_LEN;
-+    int read_sz = 0;
-+    LOCAL_ARRAY(char, tmpbuf, SQUID_TCP_SO_RCVBUF);
-+    for (;;) {
-+	len = recv(fd, tmpbuf, peek_sz, MSG_PEEK);
-+	debug(81, 5) ("recv(FD %d, ..., MSG_PEEK) ret %d\n", fd, len);
-+	if (len < 0) {
-+	    debug(81, 1) ("icapReadHeader: FD %d recv error: %s\n", fd,
-+		xstrerror());
-+	    return -1;
-+	}
-+	if (len == 0) {
-+	    debug(81, 2) ("icapReadHeader: FD %d recv EOF\n", fd);
-+	    return -1;
-+	}
-+	headlen = headersEnd(tmpbuf, len);
-+	debug(81, 3) ("headlen=%d\n", headlen);
-+	/*
-+	 * break if we now know where the ICAP headers end
-+	 */
-+	if (headlen)
-+	    break;
-+	/*
-+	 * break if we know there is no more data to read
-+	 */
-+	if (len < peek_sz)
-+	    break;
-+	/*
-+	 * The ICAP header is larger than (or equal to) our read
-+	 * buffer, so double it and try to peek again.
-+	 */
-+	peek_sz *= 2;
-+	if (peek_sz >= SQUID_TCP_SO_RCVBUF) {
-+	    debug(81,
-+		1) ("icapReadHeader: Failed to find end of ICAP header\n");
-+	    debug(81, 1) ("\twithin first %d bytes of response\n",
-+		SQUID_TCP_SO_RCVBUF);
-+	    debug(81, 1) ("\tpossible persistent connection bug/confusion\n");
-+	    return -1;
-+	}
-+    }
-+    /*
-+     * Now actually read the data from the kernel
-+     */
-+    if (headlen)
-+	read_sz = headlen;
-+    else
-+	read_sz = len;
-+    len = FD_READ_METHOD(fd, tmpbuf, read_sz);
-+    assert(len == read_sz);
-+    fd_bytes(fd, len, FD_READ);
-+    memBufAppend(&icap->icap_hdr, tmpbuf, len);
-+    if (headlen) {
-+	/* End of ICAP header found */
-+	if (icap->icap_hdr.size < 4)
-+	    *isIcap = 0;
-+	else if (0 == strncmp(icap->icap_hdr.buf, "ICAP", 4))
-+	    *isIcap = 1;
-+	else
-+	    *isIcap = 0;
-+	return 1;
-+    }
-+    /*
-+     * We don't have all the headers yet
-+     */
-+    return 0;
-+}
-+
-+static int
-+icapParseConnectionClose(const IcapStateData * icap, const char *s,
-+    const char *e)
-+{
-+    char *t;
-+    char *q;
-+    /*
-+     * s points to the start of the line "Connection: ... "
-+     * e points to *after* the last character on the line
-+     */
-+    s += 11;			/* skip past Connection: */
-+    while (s < e && isspace(*s))
-+	s++;
-+    if (e - s < 5)
-+	return 0;
-+    /*
-+     * create a buffer that we can use strtok on
-+     */
-+    t = xmalloc(e - s + 1);
-+    strncpy(t, s, e - s);
-+    *(t + (e - s)) = '\0';
-+    for (q = strtok(t, ","); q; q = strtok(NULL, ",")) {
-+	if (0 == strcasecmp(q, "close")) {
-+	    xfree(t);
-+	    return 1;
-+	}
-+    }
-+    xfree(t);
-+    return 0;
-+}
-+
-+/* returns icap status, version and subversion extracted from status line or -1 on parsing failure 
-+ * The str_status pointr points to the text returned from the icap server.
-+ * sline probably is NOT terminated with '\0' 
-+ */
-+int
-+icapParseStatusLine(const char *sline, int slinesize, int *version_major,
-+    int *version_minor, const char **str_status)
-+{
-+    char *sp, *stmp, *ep = (char *) sline + slinesize;
-+    int status;
-+    if (slinesize < 14)		/*The format of this line is: "ICAP/x.x xxx[ msg....]\r\n" */
-+	return -1;
-+
-+    if (strncmp(sline, "ICAP/", 5) != 0)
-+	return -1;
-+    if (sscanf(sline + 5, "%d.%d", version_major, version_minor) != 2)
-+	return -1;
-+
-+    if (!(sp = memchr(sline, ' ', slinesize)))
-+	return -1;
-+
-+    while (sp < ep && xisspace(*++sp));
-+
-+    if (!xisdigit(*sp) || sp >= ep)
-+	return -1;
-+
-+    if ((status = strtol(sp, &stmp, 10)) <= 0)
-+	return -1;
-+    sp = stmp;
-+
-+    while (sp < ep && xisspace(*++sp));
-+    *str_status = sp;
-+    /*Must add a test for "\r\n" end headers .... */
-+    return status;
-+}
-+
-+
-+void
-+icapSetKeepAlive(IcapStateData * icap, const char *hdrs)
-+{
-+    const char *start;
-+    const char *end;
-+    if (0 == icap->flags.keep_alive)
-+	return;
-+    if (0 == icapFindHeader(hdrs, "Connection:", &start, &end)) {
-+	icap->flags.keep_alive = 1;
-+	return;
-+    }
-+    if (icapParseConnectionClose(icap, start, end))
-+	icap->flags.keep_alive = 0;
-+    else
-+	icap->flags.keep_alive = 1;
-+}
-+
-+/*
-+ * icapParseChunkSize
-+ *
-+ * Returns the offset where the next chunk starts
-+ * return parameter chunk_size;
-+ */
-+static int
-+icapParseChunkSize(const char *buf, int len, int *chunk_size)
-+{
-+    int chunkSize = 0;
-+    char c;
-+    size_t start;
-+    size_t end;
-+    size_t nextStart = 0;
-+    debug(81, 3) ("icapParseChunkSize: buf=%p, len=%d\n", buf, len);
-+    do {
-+	start = nextStart;
-+	debug(81, 3) ("icapParseChunkSize: start=%d\n", start);
-+	if (len <= start) {
-+	    /*
-+	     * end of buffer, so far no lines or only empty lines,
-+	     * wait for more data. read chunk size with next buffer.
-+	     */
-+	    *chunk_size = 0;
-+	    return 0;
-+	}
-+	end = start + icapLineLength(buf + start, len - start);
-+	nextStart = end;
-+	if (end <= start) {
-+	    /*
-+	     * no line found, need more code here, now we are in
-+	     * deep trouble, buffer stops with half a chunk size
-+	     * line. For now stop here.
-+	     */
-+	    debug(81, 1) ("icapParseChunkSize: WARNING in mid-line, ret 0\n");
-+	    *chunk_size = 0;
-+	    return 0;
-+	}
-+	while (start < end) {
-+	    if (NULL == strchr(w_space, buf[start]))
-+		break;
-+	    start++;
-+	}
-+	while (start < end) {
-+	    if (NULL == strchr(w_space, buf[end - 1]))
-+		break;
-+	    end--;
-+	}
-+	/*
-+	 * if now end <= start we got an empty line. The previous
-+	 * chunk data should stop with a CRLF. In case that the
-+	 * other end does not follow the specs and sends no CRLF
-+	 * or too many empty lines, just continue till we have a
-+	 * non-empty line.
-+	 */
-+    } while (end <= start);
-+    debug(81, 3) ("icapParseChunkSize: start=%d, end=%d\n", start, end);
-+
-+    /* Non-empty line: Parse the chunk size */
-+    while (start < end) {
-+	c = buf[start++];
-+	if (c >= 'a' && c <= 'f') {
-+	    chunkSize = chunkSize * 16 + c - 'a' + 10;
-+	} else if (c >= 'A' && c <= 'F') {
-+	    chunkSize = chunkSize * 16 + c - 'A' + 10;
-+	} else if (c >= '0' && c <= '9') {
-+	    chunkSize = chunkSize * 16 + c - '0';
-+	} else {
-+	    if (!(c == ';' || c == ' ' || c == '\t')) {
-+		/*Syntax error: Chunksize expected. */
-+		*chunk_size = -2;	/* we are done */
-+		return nextStart;
-+	    }
-+	    /* Next comes a chunk extension */
-+	    break;
-+	}
-+    }
-+    /*
-+     * if we read a zero chunk, we reached the end. Mark this for
-+     * icapPconnTransferDone
-+     */
-+    *chunk_size = (chunkSize > 0) ? chunkSize : -2;
-+    debug(81, 3) ("icapParseChunkSize: return nextStart=%d\n", nextStart);
-+    return nextStart;
-+}
-+
-+/*
-+ * icapParseChunkedBody
-+ *
-+ * De-chunk an HTTP entity received from the ICAP server.
-+ * The 'store' function pointer is storeAppend() or memBufAppend().
-+ */
-+size_t
-+icapParseChunkedBody(IcapStateData * icap, STRCB * store, void *store_data)
-+{
-+    int bufOffset = 0;
-+    size_t bw = 0;
-+    MemBuf *cb = &icap->chunk_buf;
-+    const char *buf = cb->buf;
-+    int len = cb->size;
-+
-+    if (icap->chunk_size == -2) {
-+	debug(81, 3) ("zero end chunk reached\n");
-+	return 0;
-+    }
-+    debug(81, 3) ("%s:%d: chunk_size=%d\n", __FILE__, __LINE__,
-+	icap->chunk_size);
-+    if (icap->chunk_size < 0) {
-+	store(store_data, buf, len);
-+	cb->size = 0;
-+	return (size_t) len;
-+    }
-+    debug(81, 3) ("%s:%d: bufOffset=%d, len=%d\n", __FILE__, __LINE__,
-+	bufOffset, len);
-+    while (bufOffset < len) {
-+	debug(81, 3) ("%s:%d: bufOffset=%d, len=%d\n", __FILE__, __LINE__,
-+	    bufOffset, len);
-+	if (icap->chunk_size == 0) {
-+	    int x;
-+	    x = icapParseChunkSize(buf + bufOffset,
-+		len - bufOffset, &icap->chunk_size);
-+	    if (x < 1) {
-+		/* didn't find a valid chunk spec */
-+		break;
-+	    }
-+	    bufOffset += x;
-+	    debug(81, 3) ("got chunksize %d, new offset %d\n",
-+		icap->chunk_size, bufOffset);
-+	    if (icap->chunk_size == -2) {
-+		debug(81, 3) ("zero end chunk reached\n");
-+		break;
-+	    }
-+	}
-+	debug(81, 3) ("%s:%d: X\n", __FILE__, __LINE__);
-+	if (icap->chunk_size > 0) {
-+	    if (icap->chunk_size >= len - bufOffset) {
-+		store(store_data, buf + bufOffset, len - bufOffset);
-+		bw += (len - bufOffset);
-+		icap->chunk_size -= (len - bufOffset);
-+		bufOffset = len;
-+	    } else {
-+		store(store_data, buf + bufOffset, icap->chunk_size);
-+		bufOffset += icap->chunk_size;
-+		bw += icap->chunk_size;
-+		icap->chunk_size = 0;
-+	    }
-+	}
-+    }
-+    if (0 == bufOffset) {
-+	(void) 0;
-+    } else if (bufOffset == cb->size) {
-+	cb->size = 0;
-+    } else {
-+	assert(bufOffset <= cb->size);
-+	xmemmove(cb->buf, cb->buf + bufOffset, cb->size - bufOffset);
-+	cb->size -= bufOffset;
-+    }
-+    return bw;
-+}
-+
-+/*
-+ *  icapAddAuthUserHeader
-+ *
-+ *  Builds and adds the X-Authenticated-User header to an ICAP request headers.
-+ */
-+void
-+icapAddAuthUserHeader(MemBuf * mb, auth_user_request_t * auth_user_request)
-+{
-+    char *user = authenticateUserRequestUsername(auth_user_request);
-+    char *authuser;
-+    size_t len, userlen, schemelen, userofslen;
-+    char *userofs;
-+
-+    if (user == NULL) {
-+	debug(81, 5) ("icapAddAuthUserHeader: NULL username\n");
-+	return;
-+    }
-+    userlen = strlen(user);
-+    schemelen = strlen(Config.icapcfg.auth_scheme);
-+    len = userlen + schemelen + 1;
-+    authuser = xcalloc(len, 1);
-+
-+    if ((userofs = strstr(Config.icapcfg.auth_scheme, "%u")) == NULL) {
-+	/* simply add user at end of string */
-+	snprintf(authuser, len, "%s%s", Config.icapcfg.auth_scheme, user);
-+    } else {
-+	userofslen = userofs - Config.icapcfg.auth_scheme;
-+	xmemcpy(authuser, Config.icapcfg.auth_scheme, userofslen);
-+	xmemcpy(authuser + userofslen, user, userlen);
-+	xmemcpy(authuser + userofslen + userlen,
-+	    userofs + 2, schemelen - (userofslen + 2) + 1);
-+    }
-+
-+    memBufPrintf(mb, "X-Authenticated-User: %s\r\n", base64_encode(authuser));
-+    xfree(authuser);
-+}
-+
-+/*
-+ *  icapAddOriginIP
-+ *
-+ *  Builds and adds the X-Server-IP header to an ICAP request headers.
-+ */
-+void
-+icapAddOriginIP(MemBuf *mb, const char *host)
-+{
-+  const ipcache_addrs *addrs;
-+  struct in_addr s;
-+
-+  if (host == NULL) {
-+    debug(81, 5)("icapAddOriginIP: NULL host\n");
-+    return;
-+  }
-+    
-+  addrs = ipcache_gethostbyname(host, IP_LOOKUP_IF_MISS);
-+  if (addrs == NULL) {
-+    /*
-+     * http://www.i-cap.org/spec/draft-stecher-icap-subid-00.txt :
-+     *
-+     * [...] If the meta information for some header is not available,
-+     * the header field MUST be omitted.
-+     */
-+    debug(81, 5)("icapAddOriginIP: can't tell IP address\n");
-+    return;
-+  }
-+
-+  s = addrs->in_addrs[0];
-+  memBufPrintf(mb, "X-Server-IP: %s\r\n", inet_ntoa(s));
-+}
-Index: src/icap_opt.c
-===================================================================
-RCS file: src/icap_opt.c
-diff -N src/icap_opt.c
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ src/icap_opt.c	16 Feb 2006 17:21:45 -0000	1.1.2.18
-@@ -0,0 +1,523 @@
-+
-+/*
-+ * $Id$
-+ * 
-+ * DEBUG: section 81    Internet Content Adaptation Protocol (ICAP) Client OPTIONS
-+ * AUTHOR: Ralf Horstmann
-+ *
-+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
-+ * ----------------------------------------------------------
-+ *
-+ *  Squid is the result of efforts by numerous individuals from
-+ *  the Internet community; see the CONTRIBUTORS file for full
-+ *  details.   Many organizations have provided support for Squid's
-+ *  development; see the SPONSORS file for full details.  Squid is
-+ *  Copyrighted (C) 2001 by the Regents of the University of
-+ *  California; see the COPYRIGHT file for full details.  Squid
-+ *  incorporates software developed and/or copyrighted by other
-+ *  sources; see the CREDITS file for full details.
-+ *
-+ *  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, USA.
-+ *
-+ */
-+
-+#include "squid.h"
-+
-+/*************************************************************/
-+
-+/*
-+ * network related functions for OPTIONS request
-+ */
-+static void icapOptStart(void *data);
-+static void icapOptTimeout(int fd, void *data);
-+static void icapOptConnectDone(int server_fd, int status, void *data);
-+static void icapOptWriteComplete(int fd, char *bufnotused, size_t size, int errflag, void *data);
-+static void icapOptReadReply(int fd, void *data);
-+
-+/*
-+ * reply parsing functions
-+ */
-+static int icapOptParseReply(icap_service * s, IcapOptData * i);
-+static void icapOptParseEntry(icap_service * s, const char *blk_start, const char *blk_end);
-+static int icapIsolateLine(const char **parse_start, const char **blk_start, const char **blk_end);
-+
-+/*
-+ * helper functions
-+ */
-+static void icapOptDataInit(IcapOptData * i);
-+static void icapOptDataFree(IcapOptData * i);
-+
-+/*************************************************************/
-+
-+#define TIMEOUT 10
-+
-+void
-+icapOptInit()
-+{
-+    icap_service *s;
-+
-+    /* iterate over configured services */
-+    s = Config.icapcfg.service_head;
-+    while (s) {
-+	eventAdd("icapOptStart", icapOptStart, s, 5.0, 1);
-+	s = s->next;
-+    }
-+}
-+
-+void
-+icapOptShutdown()
-+{
-+    icap_service *s;
-+
-+    s = Config.icapcfg.service_head;
-+    while (s) {
-+	if (eventFind(icapOptStart, s)) {
-+	    eventDelete(icapOptStart, s);
-+	}
-+	s = s->next;
-+    }
-+}
-+
-+/*
-+ * mark a service as unreachable
-+ */
-+void
-+icapOptSetUnreachable(icap_service * s)
-+{
-+    s->unreachable = 1;
-+    debug(81, 5) ("icapOptSetUnreachable: got called for %s\n", s->uri);
-+    /*
-+     * if there is an options request scheduled, delete it and add
-+     * it again to reset the time to the default check_interval.
-+     */
-+    if (eventFind(icapOptStart, s)) {
-+	eventDelete(icapOptStart, s);
-+	eventAdd("icapOptStart", icapOptStart, s, Config.icapcfg.check_interval, 1);
-+    }
-+}
-+
-+static void
-+icapOptStart(void *data)
-+{
-+    icap_service *s = data;
-+    int fd;
-+    int ctimeout = TIMEOUT;
-+    const char *host = s->hostname;
-+    unsigned short port = s->port;
-+    debug(81, 3) ("icapOptStart: starting OPTIONS request for %s (%s)\n", s->name, s->uri);
-+    fd = comm_open(SOCK_STREAM,
-+	0,
-+	getOutgoingAddr(NULL),
-+	0,
-+	COMM_NONBLOCKING,
-+	"ICAP OPTIONS connection");
-+    if (fd < 0) {
-+	debug(81, 4) ("icapConnectStart: %s\n", xstrerror());
-+	eventAdd("icapOptStart", icapOptStart, s, Config.icapcfg.check_interval, 1);
-+	return;
-+    }
-+    assert(s->opt == NULL);	/* if not null, another options request might be running, which should not happen */
-+    s->opt = memAllocate(MEM_ICAP_OPT_DATA);
-+    icapOptDataInit(s->opt);
-+    cbdataLock(s);
-+    commSetTimeout(fd, ctimeout, icapOptTimeout, s);
-+    commConnectStart(fd, host, port, icapOptConnectDone, s);
-+}
-+
-+static void
-+icapOptTimeout(int fd, void *data)
-+{
-+    icap_service *s = data;
-+    IcapOptData *i = s->opt;
-+    int valid;
-+
-+    debug(81, 4) ("icapOptConnectTimeout: fd=%d, service=%s\n", fd, s->uri);
-+
-+    comm_close(fd);
-+    valid = cbdataValid(s);
-+    cbdataUnlock(s);
-+    if (!valid) {
-+	icapOptDataFree(i);
-+	s->opt = NULL;
-+	return;
-+    }
-+    /* try again later */
-+    icapOptDataFree(i);
-+    s->opt = NULL;
-+    s->unreachable = 1;
-+    debug(81, 3) ("icapOptConnectTimeout: unreachable=1, service=%s\n", s->uri);
-+    eventAdd("icapOptStart", icapOptStart, s, Config.icapcfg.check_interval, 1);
-+
-+}
-+
-+static void
-+icapOptConnectDone(int server_fd, int status, void *data)
-+{
-+    icap_service *s = data;
-+    IcapOptData *i = s->opt;
-+    MemBuf request;
-+    int valid;
-+
-+    valid = cbdataValid(s);
-+    cbdataUnlock(s);
-+    if (!valid) {
-+	comm_close(server_fd);
-+	icapOptDataFree(i);
-+	s->opt = NULL;
-+	return;
-+    }
-+    if (status != COMM_OK) {
-+	debug(81, 3) ("icapOptConnectDone: unreachable=1, service=%s\n", s->uri);
-+	comm_close(server_fd);
-+	icapOptDataFree(i);
-+	s->opt = NULL;
-+	s->unreachable = 1;
-+	eventAdd("icapOptStart", icapOptStart, s, Config.icapcfg.check_interval, 1);
-+	return;
-+    }
-+    debug(81, 3) ("icapOptConnectDone: Connection ok. Sending Options request for %s\n", s->name);
-+    memBufDefInit(&request);
-+    memBufPrintf(&request, "OPTIONS %s ICAP/1.0\r\n", s->uri);
-+    memBufPrintf(&request, "Host: %s\r\n", s->hostname);
-+    memBufPrintf(&request, "Connection: close\r\n");
-+    memBufPrintf(&request, "User-Agent: ICAP-Client-Squid/1.2\r\n");
-+    memBufPrintf(&request, "\r\n");
-+    cbdataLock(s);
-+    commSetTimeout(server_fd, TIMEOUT, icapOptTimeout, s);
-+    comm_write_mbuf(server_fd, request, icapOptWriteComplete, s);
-+}
-+
-+static void
-+icapOptWriteComplete(int fd, char *bufnotused, size_t size, int errflag, void *data)
-+{
-+    icap_service *s = data;
-+    IcapOptData *i = s->opt;
-+    int valid;
-+
-+    valid = cbdataValid(s);
-+    cbdataUnlock(s);
-+    if (!valid) {
-+	comm_close(fd);
-+	icapOptDataFree(i);
-+	s->opt = NULL;
-+	return;
-+    }
-+    debug(81, 5) ("icapOptWriteComplete: FD %d: size %d: errflag %d.\n",
-+	fd, size, errflag);
-+    if (size > 0) {
-+	fd_bytes(fd, size, FD_WRITE);
-+	kb_incr(&statCounter.icap.all.kbytes_out, size);
-+    }
-+    if (errflag) {
-+	/* cancel this for now */
-+	debug(81, 3) ("icapOptWriteComplete: unreachable=1, service=%s\n", s->uri);
-+	icapOptDataFree(i);
-+	s->opt = NULL;
-+	s->unreachable = 1;
-+	eventAdd("icapOptStart", icapOptStart, s, Config.icapcfg.check_interval, 1);
-+	comm_close(fd);
-+	return;
-+    }
-+    cbdataLock(s);
-+    commSetSelect(fd, COMM_SELECT_READ, icapOptReadReply, s, 0);
-+}
-+
-+static void
-+icapOptReadReply(int fd, void *data)
-+{
-+    icap_service *s = data;
-+    IcapOptData *i = s->opt;
-+    int size;
-+    int len = i->size - i->offset - 1;
-+    int valid;
-+
-+    valid = cbdataValid(s);
-+    cbdataUnlock(s);
-+    if (!valid) {
-+	comm_close(fd);
-+	icapOptDataFree(i);
-+	s->opt = NULL;
-+	return;
-+    }
-+    if (len == 0) {
-+	/* Grow the request memory area to accomodate for a large request */
-+	printf("PANIC: not enough memory\n");
-+#if 0
-+	i->buf = memReallocBuf(i->buf, i->size * 2, &i->size);
-+	debug(81, 2) ("icapoptReadReply: growing reply buffer: offset=%ld size=%ld\n",
-+	    (long) i->offset, (long) i->size);
-+	len = i->size - i->offset - 1;
-+#endif
-+    }
-+    size = FD_READ_METHOD(fd, i->buf + i->offset, len);
-+    i->offset += size;
-+    debug(81, 3) ("icapOptReadReply: Got %d bytes of data\n", size);
-+    if (size > 0) {
-+	/* do some statistics */
-+	fd_bytes(fd, size, FD_READ);
-+	kb_incr(&statCounter.icap.all.kbytes_in, size);
-+
-+	/* 
-+	 * some icap servers seem to ignore the  "Connection: close" header. so 
-+	 * after getting the complete option reply we close the connection 
-+	 * ourself.
-+	 */
-+	if ((i->headlen = headersEnd(i->buf, i->offset))) {
-+	    debug(81, 3) ("icapOptReadReply: EndOfResponse\n");
-+	    size = 0;
-+	}
-+    }
-+    if (size < 0) {
-+	debug(81, 3) ("icapOptReadReply: FD %d: read failure: %s.\n", fd, xstrerror());
-+	debug(81, 3) ("icapOptReadReply: unreachable=1, service=%s.\n", s->uri);
-+	s->unreachable = 1;
-+	icapOptDataFree(i);
-+	s->opt = NULL;
-+	eventAdd("icapOptStart", icapOptStart, s, Config.icapcfg.check_interval, 1);
-+	comm_close(fd);
-+    } else if (size == 0) {
-+	/* no more data, now we can parse the reply */
-+	debug(81, 3) ("icapOptReadReply: FD %d: connection closed\n", fd);
-+	i->buf[i->offset] = '\0';	/* for string functions */
-+	debug(81, 3) ("icapOptReadReply: unreachable=0, service=%s\n", s->uri);
-+
-+	if (!icapOptParseReply(s, i)) {
-+	    debug(81, 3) ("icapOptReadReply: OPTIONS request not successful. scheduling again in %d seconds\n", Config.icapcfg.check_interval);
-+	    s->unreachable = 1;
-+	} else
-+	    s->unreachable = 0;
-+
-+	if (s->options_ttl <= 0)
-+	    s->options_ttl = Config.icapcfg.check_interval;
-+	eventAdd("icapOptStart", icapOptStart, s, s->options_ttl, 1);
-+
-+	icapOptDataFree(i);
-+	s->opt = NULL;
-+	comm_close(fd);
-+    } else {
-+	/* data received */
-+	/* commSetSelect(fd, Type, handler, client_data, timeout) */
-+	cbdataLock(s);
-+	commSetSelect(fd, COMM_SELECT_READ, icapOptReadReply, data, 0);
-+    }
-+}
-+
-+static int
-+icapIsolateLine(const char **parse_start, const char **blk_start, const char **blk_end)
-+{
-+    int slen = strcspn(*parse_start, "\r\n");
-+
-+    if (!(*parse_start)[slen])	/* no crlf */
-+	return 0;
-+
-+    if (slen == 0)		/* empty line */
-+	return 0;
-+
-+    *blk_start = *parse_start;
-+    *blk_end = *blk_start + slen;
-+
-+    /* set it to the beginning of next line */
-+    *parse_start = *blk_end;
-+    while (**parse_start == '\r')	/* CR */
-+	(*parse_start)++;
-+    if (**parse_start == '\n')	/* LF */
-+	(*parse_start)++;
-+    return 1;
-+}
-+
-+/* process a single header entry between blk_start and blk_end */
-+static void
-+icapOptParseEntry(icap_service * s, const char *blk_start, const char *blk_end)
-+{
-+    const char *name_end = strchr(blk_start, ':');
-+    const int name_len = name_end ? name_end - blk_start : 0;
-+    const char *value_start = blk_start + name_len + 1;		/* skip ':' */
-+    int value_len;
-+    int new;
-+
-+    if (!name_len || name_end > blk_end) {
-+	debug(81, 5) ("icapOptParseEntry: strange header. skipping\n");
-+	return;
-+    }
-+    if (name_len > 65536) {
-+	debug(81, 5) ("icapOptParseEntry: unusual long header item. skipping.\n");
-+	return;
-+    }
-+    while (xisspace(*value_start) && value_start < blk_end) {
-+	value_start++;
-+    }
-+    if (value_start >= blk_end) {
-+	debug(81, 5) ("icapOptParseEntry: no value found\n");
-+	return;
-+    }
-+    value_len = blk_end - value_start;
-+
-+
-+    /* extract information */
-+    if (!strncasecmp("Allow", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found Allow\n");
-+	if (!strncmp("204", value_start, 3)) {
-+	    s->flags.allow_204 = 1;
-+	} else {
-+	    debug(81, 3) ("icapOptParseEntry: Allow value unknown");
-+	}
-+    } else if (!strncasecmp("Connection", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found Connection\n");
-+    } else if (!strncasecmp("Encapsulated", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found Encapsulated\n");
-+    } else if (!strncasecmp("ISTAG", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found ISTAG\n");
-+	stringClean(&s->istag);
-+	stringLimitInit(&s->istag, value_start, value_len);
-+    } else if (!strncasecmp("Max-Connections", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found Max-Connections\n");
-+	errno = 0;
-+	new = strtol(value_start, NULL, 10);
-+	if (errno) {
-+	    debug(81, 5) ("icapOptParseEntry: Max-Connections: could not parse value\n");
-+	} else {
-+	    debug(81, 5) ("icapOptParseEntry: Max-Connections: new value=%d\n", new);
-+	    s->max_connections = new;
-+	}
-+    } else if (!strncasecmp("Methods", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found Methods\n");
-+    } else if (!strncasecmp("Options-TTL", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found Options-TTL\n");
-+	errno = 0;
-+	new = strtol(value_start, NULL, 10);
-+	if (errno) {
-+	    debug(81, 5) ("icapOptParseEntry: Options-TTL: could not parse value\n");
-+	} else {
-+	    debug(81, 5) ("icapOptParseEntry: Options-TTL: new value=%d\n", new);
-+	    s->options_ttl = new;
-+	}
-+    } else if (!strncasecmp("Preview", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found Preview\n");
-+	errno = 0;
-+	new = strtol(value_start, NULL, 10);
-+	if (errno) {
-+	    debug(81, 5) ("icapOptParseEntry: Preview: could not parse value\n");
-+	} else {
-+	    debug(81, 5) ("icapOptParseEntry: Preview: new value=%d\n", new);
-+	    s->preview = new;
-+	}
-+    } else if (!strncasecmp("Service", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found Service\n");
-+    } else if (!strncasecmp("Service-ID", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found Service-ID\n");
-+    } else if (!strncasecmp("Transfer-Preview", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found Transfer-Preview\n");
-+	stringClean(&s->transfer_preview);
-+	stringLimitInit(&s->transfer_preview, value_start, value_len);
-+    } else if (!strncasecmp("Transfer-Ignore", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found Transfer-Ignore\n");
-+	stringClean(&s->transfer_ignore);
-+	stringLimitInit(&s->transfer_ignore, value_start, value_len);
-+    } else if (!strncasecmp("Transfer-Complete", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found Transfer-Complete\n");
-+	stringClean(&s->transfer_complete);
-+	stringLimitInit(&s->transfer_complete, value_start, value_len);
-+    } else if (!strncasecmp("X-Include", blk_start, name_len)) {
-+	debug(81, 5) ("icapOptParseEntry: found X-Include\n");
-+	if (strstr(value_start, "X-Client-IP")) {
-+	    debug(81, 5) ("icapOptParseEntry: X-Include: found X-Client-IP\n");
-+	    s->flags.need_x_client_ip = 1;
-+	}
-+	if (strstr(value_start, "X-Server-IP")) {
-+	    debug(81, 5) ("icapOptParseEntry: X-Include: found X-Server-IP\n");
-+	    s->flags.need_x_server_ip = 1;
-+	}
-+	if (strstr(value_start, "X-Authenticated-User")) {
-+	    debug(81, 5) ("icapOptParseEntry: X-Include: found X-Authenticated-User\n");
-+	    s->flags.need_x_authenticated_user = 1;
-+	}
-+    } else {
-+	debug(81, 5) ("icapOptParseEntry: unknown options header\n");
-+    }
-+}
-+
-+/* parse OPTIONS reply */
-+static int
-+icapOptParseReply(icap_service * s, IcapOptData * i)
-+{
-+    int version_major, version_minor;
-+    const char *str_status;
-+    int status;
-+    const char *buf = i->buf;
-+    const char *parse_start;
-+    const char *head_end;
-+    const char *blk_start;
-+    const char *blk_end;
-+
-+    if ((status =
-+	    icapParseStatusLine(i->buf, i->offset,
-+		&version_major, &version_minor, &str_status)) < 0) {
-+	debug(81, 2) ("icapOptParseReply: bad status line <%s>\n", i->buf);
-+	return 0;
-+    }
-+    debug(81, 3) ("icapOptParseReply: got reply: <ICAP/%d.%d %d %s>\n", version_major, version_minor, status, str_status);
-+
-+    if (status != 200) {
-+	debug(81, 3) ("icapOptParseReply: status = %d != 200\n", status);
-+	return 0;
-+    }
-+    parse_start = buf;
-+    if (i->headlen == 0)
-+	i->headlen = headersEnd(parse_start, s->opt->offset);
-+
-+    if (!i->headlen) {
-+	debug(81, 2) ("icapOptParseReply: end of headers could not be found\n");
-+	return 0;
-+    }
-+    head_end = parse_start + i->headlen - 1;
-+    while (*(head_end - 1) == '\r')
-+	head_end--;
-+    assert(*(head_end - 1) == '\n');
-+    if (*head_end != '\r' && *head_end != '\n')
-+	return 0;		/* failure */
-+
-+    /* skip status line */
-+    if (!icapIsolateLine(&parse_start, &blk_start, &blk_end)) {
-+	debug(81, 3) ("icapOptParseReply: failure in isolating status line\n");
-+	return 0;
-+
-+    }
-+    /* now we might start real parsing */
-+    while (icapIsolateLine(&parse_start, &blk_start, &blk_end)) {
-+	if (blk_end > head_end || blk_start > head_end || blk_start >= blk_end) {
-+	    debug(81, 3) ("icapOptParseReply: header limit exceeded. finished.\n");
-+	    break;
-+	}
-+	icapOptParseEntry(s, blk_start, blk_end);
-+    }
-+    return 1;
-+}
-+
-+static void
-+icapOptDataInit(IcapOptData * i)
-+{
-+    i->buf = memAllocBuf(HTTP_REPLY_BUF_SZ, &i->size);
-+    i->offset = 0;
-+    i->headlen = 0;
-+}
-+
-+static void
-+icapOptDataFree(IcapOptData * i)
-+{
-+    if (i) {
-+	memFreeBuf(i->size, i->buf);
-+	memFree(i, MEM_ICAP_OPT_DATA);
-+    }
-+}
-Index: src/icap_reqmod.c
-===================================================================
-RCS file: src/icap_reqmod.c
-diff -N src/icap_reqmod.c
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ src/icap_reqmod.c	17 Feb 2006 12:50:52 -0000	1.1.2.60
-@@ -0,0 +1,981 @@
-+
-+/*
-+ * $Id$
-+ *
-+ * DEBUG: section 81    Internet Content Adaptation Protocol (ICAP) Client
-+ * AUTHOR: Geetha Manjunath, Hewlett Packard Company
-+ *
-+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
-+ * ----------------------------------------------------------
-+ *
-+ *  Squid is the result of efforts by numerous individuals from
-+ *  the Internet community; see the CONTRIBUTORS file for full
-+ *  details.   Many organizations have provided support for Squid's
-+ *  development; see the SPONSORS file for full details.  Squid is
-+ *  Copyrighted (C) 2001 by the Regents of the University of
-+ *  California; see the COPYRIGHT file for full details.  Squid
-+ *  incorporates software developed and/or copyrighted by other
-+ *  sources; see the CREDITS file for full details.
-+ *
-+ *  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, USA.
-+ *
-+ */
-+
-+#include "squid.h"
-+
-+#define ICAP_PROXY_KEEP_ALIVE 0
-+
-+/*
-+ * These once-static functions are required to be global for ICAP
-+ */
-+
-+PF clientReadRequest;
-+PF connStateFree;
-+int clientReadDefer(int fd, void *data);
-+int clientCheckContentLength(request_t * r);
-+void clientProcessRequest(clientHttpRequest *);
-+int clientCachable(clientHttpRequest *);
-+int clientHierarchical(clientHttpRequest *);
-+void clientReadBody(request_t * request, char *buf, size_t size,
-+    CBCB * callback, void *cbdata);
-+static void icapReqModPassHttpBody(IcapStateData * icap, char *buf, size_t size,
-+    CBCB * callback, void *cbdata);
-+
-+static PF icapReqModReadHttpHdrs;
-+static PF icapReqModReadHttpBody;
-+static CWCB icapReqModSendBodyChunk;
-+static CBCB icapReqModBodyHandler;
-+static BODY_HANDLER icapReqModBodyReader;
-+static STRCB icapReqModMemBufAppend;
-+
-+#define EXPECTED_ICAP_HEADER_LEN 256
-+static const char *crlf = "\r\n";
-+
-+/*
-+ * icapExpectedHttpReqHdrSize
-+ *
-+ * calculate the size of the HTTP headers that we expect
-+ * to read from the ICAP server.
-+ */
-+static int
-+icapExpectedHttpReqHdrSize(IcapStateData * icap)
-+{
-+    if (icap->enc.req_body > -1 && icap->enc.req_hdr > -1)
-+	return (icap->enc.req_body - icap->enc.req_hdr);
-+    if (icap->enc.null_body > -1)
-+	return icap->enc.null_body;
-+    fatal("icapExpectedHttpReqHdrSize: unexpected case");
-+    return 0;
-+}
-+
-+/*
-+ * icapReqModCreateClientState
-+ *
-+ * Creates fake client_side data structures so we can use
-+ * that module to read/parse the HTTP request that we read
-+ * from the ICAP server.
-+ */
-+static clientHttpRequest *
-+icapReqModCreateClientState(IcapStateData * icap, request_t * request)
-+{
-+    clientHttpRequest *http;
-+    if (!cbdataValid(icap->reqmod.client_cookie)) {
-+	debug(81, 3) ("Whups, client cookie invalid\n");
-+	icap->reqmod.client_fd = -1;
-+	return NULL;
-+    }
-+    http = cbdataAlloc(clientHttpRequest);
-+    /*
-+     * use our own urlCanonicalClean here, because urlCanonicalClean
-+     * may strip everything after a question-mark. As http->uri
-+     * is used when doing a request to a parent proxy, we need the full
-+     * url here.
-+     */
-+    http->uri = xstrdup(urlCanonical(icap->request));
-+    http->log_uri = xstrndup(http->uri, MAX_URL);
-+    http->range_iter.boundary = StringNull;
-+    http->request = requestLink(request ? request : icap->request);
-+    http->flags.did_icap_reqmod = 1;
-+    http->start = icap->reqmod.start;
-+#if ICAP_PROXY_KEEP_ALIVE
-+    /*
-+     * Here it is possible becouse we are using as client_cookie the original http->conn
-+     * if we will keep this code we must declare an icap->conn field........
-+     * Will work if pipeline_prefetch is not enabled
-+     * We are using a dummy ConnStateData structure, just to free
-+     * old clientHttpRequest :-( 
-+     * OK,all this code is a hack and possibly must not exists in cvs ......
-+     */
-+
-+    http->conn = icap->reqmod.client_cookie;
-+    assert(http->conn->chr->next == NULL);
-+    {
-+	ConnStateData *dummyconn;
-+	dummyconn = cbdataAlloc(ConnStateData);
-+	dummyconn->fd = icap->reqmod.client_fd;
-+	dummyconn->chr = http->conn->chr;
-+	dummyconn->chr->conn = dummyconn;
-+	comm_add_close_handler(dummyconn->fd, connStateFree, dummyconn);
-+    }
-+
-+    http->conn->chr = http;
-+
-+#else
-+    http->conn = cbdataAlloc(ConnStateData);
-+    http->conn->fd = icap->reqmod.client_fd;
-+    http->conn->in.size = 0;
-+    http->conn->in.buf = NULL;
-+    http->conn->log_addr = icap->reqmod.log_addr;
-+    http->conn->chr = http;
-+    comm_add_close_handler(http->conn->fd, connStateFree, http->conn);
-+#endif
-+    http->icap_reqmod = NULL;
-+    return http;
-+}
-+
-+/*
-+ * icapReqModInterpretHttpRequest
-+ *
-+ * Interpret an HTTP request that we read from the ICAP server.
-+ * Create some "fake" clientHttpRequest and ConnStateData structures
-+ * so we can pass this new request off to the routines in
-+ * client_side.c.
-+ */
-+static void
-+icapReqModInterpretHttpRequest(IcapStateData * icap, request_t * request)
-+{
-+    clientHttpRequest *http = icapReqModCreateClientState(icap, request);
-+    if (NULL == http)
-+	return;
-+    /*
-+     * bits from clientReadRequest
-+     */
-+    request->content_length = httpHeaderGetSize(&request->header,
-+	HDR_CONTENT_LENGTH);
-+    if (!urlCheckRequest(request) ||
-+	httpHeaderHas(&request->header, HDR_TRANSFER_ENCODING)) {
-+	ErrorState *err;
-+	err = errorCon(ERR_UNSUP_REQ, HTTP_NOT_IMPLEMENTED);
-+	err->request = requestLink(request);
-+	request->flags.proxy_keepalive = 0;
-+	http->entry =
-+	    clientCreateStoreEntry(http, request->method, null_request_flags);
-+	errorAppendEntry(http->entry, err);
-+	return;
-+    }
-+    if (!clientCheckContentLength(request)) {
-+	ErrorState *err;
-+	err = errorCon(ERR_INVALID_REQ, HTTP_LENGTH_REQUIRED);
-+	err->request = requestLink(request);
-+	http->entry =
-+	    clientCreateStoreEntry(http, request->method, null_request_flags);
-+	errorAppendEntry(http->entry, err);
-+	return;
-+    }
-+    /* Do we expect a request-body? */
-+    if (request->content_length > 0) {
-+	debug(81, 5) ("handing request bodies in ICAP REQMOD\n");
-+	if (request->body_reader_data)
-+	    cbdataUnlock(request->body_reader_data);
-+	request->body_reader = icapReqModBodyReader;
-+	request->body_reader_data = icap;	/* XXX cbdataLock? */
-+	cbdataLock(icap);	/*Yes sure ..... */
-+	memBufDefInit(&icap->reqmod.http_entity.buf);
-+    }
-+    if (clientCachable(http))
-+	request->flags.cachable = 1;
-+    if (clientHierarchical(http))
-+	request->flags.hierarchical = 1;
-+    clientProcessRequest(http);
-+}
-+
-+/*
-+ * icapReqModParseHttpError
-+ *
-+ * Handle an error when parsing the new HTTP request we read
-+ * from the ICAP server.
-+ */
-+static void
-+icapReqModParseHttpError(IcapStateData * icap, const char *reason)
-+{
-+    debug(81, 1) ("icapReqModParseHttpError: %s\n", reason);
-+}
-+
-+/*
-+ * icapEntryError
-+ *
-+ * A wrapper for errorCon() and errorAppendEntry().
-+ */
-+static void
-+icapEntryError(IcapStateData * icap, err_type et, http_status hs, int xerrno)
-+{
-+    ErrorState *err;
-+    clientHttpRequest *http = icapReqModCreateClientState(icap, NULL);
-+    if (NULL == http)
-+	return;
-+    http->entry = clientCreateStoreEntry(http,
-+	icap->request->method, null_request_flags);
-+    err = errorCon(et, hs);
-+    err->xerrno = xerrno;
-+    err->request = requestLink(icap->request);
-+    errorAppendEntry(http->entry, err);
-+}
-+
-+/*
-+ * icapReqModParseHttpRequest
-+ * 
-+ * Parse the HTTP request that we read from the ICAP server.
-+ * Creates and fills in the request_t structure.
-+ */
-+static void
-+icapReqModParseHttpRequest(IcapStateData * icap)
-+{
-+    char *mstr;
-+    char *uri;
-+    char *inbuf;
-+    char *t;
-+    char *token;
-+    char *headers;
-+    method_t method;
-+    request_t *request;
-+    http_version_t http_ver;
-+    int reqlen = icap->reqmod.hdr_buf.size;
-+    int hdrlen;
-+
-+    /*
-+     * Lazy, make a copy of the buf so I can chop it up with strtok()
-+     */
-+    inbuf = xcalloc(reqlen + 1, 1);
-+    memcpy(inbuf, icap->reqmod.hdr_buf.buf, reqlen);
-+
-+    if ((mstr = strtok(inbuf, "\t ")) == NULL) {
-+	debug(81, 1) ("icapReqModParseHttpRequest: Can't get request method\n");
-+	icapReqModParseHttpError(icap, "error:invalid-request-method");
-+	xfree(inbuf);
-+	return;
-+    }
-+    method = urlParseMethod(mstr);
-+    if (method == METHOD_NONE) {
-+	debug(81, 1) ("icapReqModParseHttpRequest: Unsupported method '%s'\n",
-+	    mstr);
-+	icapReqModParseHttpError(icap, "error:unsupported-request-method");
-+	xfree(inbuf);
-+	return;
-+    }
-+    /* look for URL+HTTP/x.x */
-+    if ((uri = strtok(NULL, "\n")) == NULL) {
-+	debug(81, 1) ("icapReqModParseHttpRequest: Missing URI\n");
-+	icapReqModParseHttpError(icap, "error:missing-url");
-+	xfree(inbuf);
-+	return;
-+    }
-+    while (xisspace(*uri))
-+	uri++;
-+    t = uri + strlen(uri);
-+    assert(*t == '\0');
-+    token = NULL;
-+    while (t > uri) {
-+	t--;
-+	if (xisspace(*t) && !strncmp(t + 1, "HTTP/", 5)) {
-+	    token = t + 1;
-+	    break;
-+	}
-+    }
-+    while (t > uri && xisspace(*t))
-+	*(t--) = '\0';
-+    debug(81, 5) ("icapReqModParseHttpRequest: URI is '%s'\n", uri);
-+    if (token == NULL) {
-+	debug(81, 3) ("icapReqModParseHttpRequest: Missing HTTP identifier\n");
-+	icapReqModParseHttpError(icap, "error:missing-http-ident");
-+	xfree(inbuf);
-+	return;
-+    }
-+    if (sscanf(token + 5, "%d.%d", &http_ver.major, &http_ver.minor) != 2) {
-+	debug(81, 3) ("icapReqModParseHttpRequest: Invalid HTTP identifier.\n");
-+	icapReqModParseHttpError(icap, "error:invalid-http-ident");
-+	xfree(inbuf);
-+	return;
-+    }
-+    debug(81, 6) ("icapReqModParseHttpRequest: Client HTTP version %d.%d.\n",
-+	http_ver.major, http_ver.minor);
-+
-+    headers = strtok(NULL, null_string);
-+    hdrlen = inbuf + reqlen - headers;
-+
-+    if ((request = urlParse(method, uri)) == NULL) {
-+	debug(81, 3) ("Invalid URL: %s at %s:%d\n", uri, __FILE__, __LINE__);
-+	icapEntryError(icap, ERR_INVALID_URL, HTTP_BAD_REQUEST, 0);
-+	xfree(inbuf);
-+	return;
-+    }
-+    /* compile headers */
-+    if (!httpHeaderParse(&request->header, headers, headers + hdrlen)) {
-+	debug(81, 3) ("Failed to parse HTTP headers for: %s at %s:%d",
-+	    uri, __FILE__, __LINE__);
-+	icapEntryError(icap, ERR_INVALID_REQ, HTTP_BAD_REQUEST, 0);
-+	xfree(inbuf);
-+	return;
-+    }
-+    debug(81,
-+	3)
-+	("icapReqModParseHttpRequest: successfully parsed the HTTP request\n");
-+    request->http_ver = http_ver;
-+    request->client_addr = icap->request->client_addr;
-+    request->my_addr = icap->request->my_addr;
-+    request->my_port = icap->request->my_port;
-+    request->class = icap->request->class;
-+    if (icap->request->auth_user_request != NULL) {
-+	/* Copy authentification info in new request */
-+	request->auth_user_request = icap->request->auth_user_request;
-+	authenticateAuthUserRequestLock(request->auth_user_request);
-+    }
-+#if ICAP_PROXY_KEEP_ALIVE
-+    /*
-+     * Copy the proxy_keepalive flag from the original request
-+     */
-+    request->flags.proxy_keepalive = icap->request->flags.proxy_keepalive;
-+    /*
-+     * If proxy_keepalive was set for the original request, make
-+     * sure that the adapated request also has the necessary headers
-+     * for keepalive
-+     */
-+    if (request->flags.proxy_keepalive) {
-+	if (!httpMsgIsPersistent(http_ver, &request->header))
-+	    request->flags.proxy_keepalive = 0;
-+    }
-+#endif
-+    icapReqModInterpretHttpRequest(icap, request);
-+    xfree(inbuf);
-+}
-+
-+/*
-+ * icapReqModHandoffRespMod
-+ *
-+ * Handles the case where a REQMOD request results in an HTTP REPLY
-+ * (instead of an ICAP REPLY that contains a new HTTP REQUEST).  We
-+ * prepare the IcapStateData for passing off to the icap_reqmod
-+ * code, where we have functions for reading HTTP replies in ICAP
-+ * messages.
-+ */
-+static void
-+icapReqModHandoffRespMod(IcapStateData * icap)
-+{
-+    extern PF icapReadReply;
-+    clientHttpRequest *http = icapReqModCreateClientState(icap, NULL);
-+    if (NULL == http)
-+	return;
-+    assert(icap->request);
-+
-+    http->entry = clientCreateStoreEntry(http,
-+	icap->request->method, icap->request->flags);
-+    icap->respmod.entry = http->entry;
-+    storeLockObject(icap->respmod.entry);
-+
-+    /* icap->http_flags = ? */
-+    memBufDefInit(&icap->respmod.buffer);
-+    memBufDefInit(&icap->chunk_buf);
-+    assert(icap->current_service);
-+    icapReadReply(icap->icap_fd, icap);
-+}
-+
-+/*
-+ * icapReqModKeepAliveOrClose
-+ *
-+ * Called when we are done reading from the ICAP server.
-+ * Either close the connection or keep it open for a future
-+ * transaction.
-+ */
-+static void
-+icapReqModKeepAliveOrClose(IcapStateData * icap)
-+{
-+    int fd = icap->icap_fd;
-+    debug(81, 3) ("%s:%d FD %d\n", __FILE__, __LINE__, fd);
-+    if (fd < 0)
-+	return;
-+    if (!icap->flags.keep_alive) {
-+	debug(81, 3) ("%s:%d keep_alive not set, closing\n", __FILE__,
-+	    __LINE__);
-+	comm_close(fd);
-+	return;
-+    }
-+    if (icap->request->content_length < 0) {
-+	/* no message body */
-+	debug(81, 3) ("%s:%d no message body\n", __FILE__, __LINE__);
-+	if (1 != icap->reqmod.hdr_state) {
-+	    /* didn't get to end of HTTP headers */
-+	    debug(81, 3) ("%s:%d didnt find end of headers, closing\n",
-+		__FILE__, __LINE__);
-+	    comm_close(fd);
-+	    return;
-+	}
-+    } else if (icap->reqmod.http_entity.bytes_read !=
-+	icap->request->content_length) {
-+	debug(81, 3) ("%s:%d bytes_read (%" PRINTF_OFF_T ") != content_length (%" PRINTF_OFF_T ")\n",
-+	    __FILE__, __LINE__, icap->reqmod.http_entity.bytes_read,
-+	    icap->request->content_length);
-+	/* an error */
-+	comm_close(fd);
-+	return;
-+    }
-+    debug(81, 3) ("%s:%d looks good, keeping alive\n", __FILE__, __LINE__);
-+    commSetDefer(fd, NULL, NULL);
-+    commSetTimeout(fd, -1, NULL, NULL);
-+    commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
-+    comm_remove_close_handler(fd, icapStateFree, icap);
-+    pconnPush(fd, icap->current_service->hostname, icap->current_service->port);
-+    icap->icap_fd = -1;
-+    icapStateFree(-1, icap);
-+}
-+
-+/*
-+ * icapReqModReadHttpHdrs
-+ *
-+ * Read the HTTP reply from the ICAP server.  Uses the values
-+ * from the ICAP Encapsulation header to know how many bytes
-+ * to read.
-+ */
-+static void
-+icapReqModReadHttpHdrs(int fd, void *data)
-+{
-+    IcapStateData *icap = data;
-+    LOCAL_ARRAY(char, tmpbuf, SQUID_TCP_SO_RCVBUF);
-+    int rl;
-+    debug(81, 3) ("icapReqModReadHttpHdrs:\n");
-+    assert(fd == icap->icap_fd);
-+    assert(icap->enc.req_hdr == 0);
-+    if (0 == icap->reqmod.hdr_state) {
-+	int expect = icapExpectedHttpReqHdrSize(icap);
-+	int so_far = icap->http_header_bytes_read_so_far;
-+	int needed = expect - so_far;
-+	debug(81, 3) ("expect=%d\n", expect);
-+	debug(81, 3) ("so_far=%d\n", so_far);
-+	debug(81, 3) ("needed=%d\n", needed);
-+	assert(needed >= 0);
-+	if (0 == expect) {
-+	    fatalf("unexpected condition in %s:%d", __FILE__, __LINE__);
-+	}
-+	rl = FD_READ_METHOD(fd, tmpbuf, needed);
-+	debug(81, 3) ("icapReqModReadHttpHdrs: read %d bytes\n", rl);
-+	if (rl < 0) {
-+	    fatalf("need to handle read error at %s:%d", __FILE__, __LINE__);
-+	}
-+	fd_bytes(fd, rl, FD_READ);
-+	kb_incr(&statCounter.icap.all.kbytes_in, rl);
-+	memBufAppend(&icap->reqmod.hdr_buf, tmpbuf, rl);
-+	icap->http_header_bytes_read_so_far += rl;
-+	if (rl != needed) {
-+	    /* still more header data to read */
-+	    commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpHdrs, icap,
-+		0);
-+	    return;
-+	}
-+	icap->reqmod.hdr_state = 1;
-+    }
-+    assert(1 == icap->reqmod.hdr_state);
-+    debug(81, 3) ("icapReqModReadHttpHdrs: read the entire request headers\n");
-+    icapReqModParseHttpRequest(icap);
-+    if (-1 == icap->reqmod.client_fd) {
-+	/* we detected that the original client_side went away */
-+	icapReqModKeepAliveOrClose(icap);
-+    } else if (icap->enc.req_body > -1) {
-+	icap->chunk_size = 0;
-+	memBufDefInit(&icap->chunk_buf);
-+	commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpBody, icap, 0);
-+    } else {
-+	icapReqModKeepAliveOrClose(icap);
-+    }
-+}
-+
-+
-+/*
-+ * icapReqModReadIcapPart
-+ *
-+ * Read the ICAP reply header.
-+ */
-+static void
-+icapReqModReadIcapPart(int fd, void *data)
-+{
-+    IcapStateData *icap = data;
-+    int version_major, version_minor;
-+    const char *str_status;
-+    int x;
-+    const char *start;
-+    const char *end;
-+    int status;
-+    int isIcap = 0;
-+    int directResponse = 0;
-+
-+    debug(81, 5) ("icapReqModReadIcapPart: FD %d httpState = %p\n", fd, data);
-+    statCounter.syscalls.sock.reads++;
-+
-+    x = icapReadHeader(fd, icap, &isIcap);
-+    if (x < 0) {
-+	/* Did not find a proper ICAP response */
-+	debug(81, 3) ("ICAP : Error path!\n");
-+	icapEntryError(icap, ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR,
-+	    errno);
-+	comm_close(fd);
-+	return;
-+    }
-+    if (x == 0) {
-+	/*
-+	 * Waiting for more headers.  Schedule new read hander, but
-+	 * don't reset timeout.
-+	 */
-+	commSetSelect(fd, COMM_SELECT_READ, icapReqModReadIcapPart, icap, 0);
-+	return;
-+    }
-+    /*
-+     * Parse the ICAP header
-+     */
-+    assert(icap->icap_hdr.size);
-+    debug(81, 3) ("Read icap header : <%s>\n", icap->icap_hdr.buf);
-+    if ((status =
-+	    icapParseStatusLine(icap->icap_hdr.buf, icap->icap_hdr.size,
-+		&version_major, &version_minor, &str_status)) < 0) {
-+	debug(81, 1) ("BAD ICAP status line <%s>\n", icap->icap_hdr.buf);
-+	/* is this correct in case of ICAP protocol error? */
-+	icapEntryError(icap, ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR,
-+	    errno);
-+	comm_close(fd);
-+	return;
-+    };
-+    if (200 != status && 201 != status) {
-+	debug(81, 1) ("Unsupported status '%d' from ICAP server\n", status);
-+	icapEntryError(icap, ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR,
-+	    errno);
-+	comm_close(fd);
-+	return;
-+    }
-+    icapSetKeepAlive(icap, icap->icap_hdr.buf);
-+    if (icapFindHeader(icap->icap_hdr.buf, "Encapsulated:", &start, &end)) {
-+	icapParseEncapsulated(icap, start, end);
-+    } else {
-+	debug(81,
-+	    1)
-+	    ("WARNING: icapReqModReadIcapPart() did not find 'Encapsulated' header\n");
-+    }
-+    if (icap->enc.res_hdr > -1)
-+	directResponse = 1;
-+    else if (icap->enc.res_body > -1)
-+	directResponse = 1;
-+    else
-+	directResponse = 0;
-+    debug(81, 3) ("icapReqModReadIcapPart: directResponse=%d\n",
-+	directResponse);
-+
-+    /* Check whether it is a direct reply - if so over to http part */
-+    if (directResponse) {
-+	debug(81,
-+	    3)
-+	    ("icapReqModReadIcapPart: FD %d, processing HTTP response for REQMOD!\n",
-+	    fd);
-+	/* got the reply, no need to come here again */
-+	icap->flags.wait_for_reply = 0;
-+	icap->flags.got_reply = 1;
-+	icapReqModHandoffRespMod(icap);
-+	return;
-+    }
-+    memBufDefInit(&icap->reqmod.hdr_buf);
-+    commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpHdrs, icap, 0);
-+    return;
-+}
-+
-+/*
-+ * icapSendReqModDone
-+ *
-+ * Called after we've sent the ICAP request.  Checks for errors
-+ * and installs the handler functions for the next step.
-+ */
-+static void
-+icapSendReqModDone(int fd, char *bufnotused, size_t size, int errflag,
-+    void *data)
-+{
-+    IcapStateData *icap = data;
-+
-+    debug(81, 5) ("icapSendReqModDone: FD %d: size %d: errflag %d.\n",
-+	fd, size, errflag);
-+    if (size > 0) {
-+	fd_bytes(fd, size, FD_WRITE);
-+	kb_incr(&statCounter.icap.all.kbytes_out, size);
-+    }
-+    if (errflag == COMM_ERR_CLOSING)
-+	return;
-+    if (errflag) {
-+	debug(81, 3) ("icapSendReqModDone: unreachable=1, service=%s\n",
-+	    icap->current_service->uri);
-+	icapOptSetUnreachable(icap->current_service);
-+	icapEntryError(icap, ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR,
-+	    errno);
-+	comm_close(fd);
-+	return;
-+    }
-+    /* Schedule read reply. */
-+    commSetSelect(fd, COMM_SELECT_READ, icapReqModReadIcapPart, icap, 0);
-+    /*
-+     * Set the read timeout here because it hasn't been set yet.
-+     * We only set the read timeout after the request has been
-+     * fully written to the server-side.  If we start the timeout
-+     * after connection establishment, then we are likely to hit
-+     * the timeout for POST/PUT requests that have very large
-+     * request bodies.
-+     */
-+    commSetTimeout(fd, Config.Timeout.read, icapConnectTimeout, icap);
-+}
-+
-+
-+/*
-+ * icapSendReqMod
-+ *
-+ * Send the ICAP request, including HTTP request, to the ICAP server
-+ * after connection has been established.
-+ */
-+static void
-+icapSendReqMod(int fd, int status, void *data)
-+{
-+    MemBuf mb;
-+    MemBuf mb_hdr;
-+    Packer p;
-+    IcapStateData *icap = data;
-+    char *client_addr;
-+    int icap_fd = icap->icap_fd;
-+    icap_service *service;
-+    CWCB *theCallback;
-+
-+    debug(81, 5) ("icapSendReqMod FD %d, status %d\n", fd, status);
-+    icap->flags.connect_pending = 0;
-+
-+    if (COMM_OK != status) {
-+	debug(81, 1) ("Could not connect to ICAP server %s:%d: %s\n",
-+	    icap->current_service->hostname,
-+	    icap->current_service->port, xstrerror());
-+	debug(81, 3) ("icapSendReqMod: unreachable=1, service=%s\n",
-+	    icap->current_service->uri);
-+	icapOptSetUnreachable(icap->current_service);
-+	icapEntryError(icap, ERR_ICAP_FAILURE, HTTP_SERVICE_UNAVAILABLE, errno);
-+	comm_close(fd);
-+	return;
-+    }
-+    fd_table[fd].pconn.uses++;
-+    fd_table[fd].pconn.type = 2;
-+    if (icap->request->content_length > 0)
-+	theCallback = icapReqModSendBodyChunk;
-+    else
-+	theCallback = icapSendReqModDone;
-+
-+    memBufDefInit(&mb);
-+    memBufDefInit(&mb_hdr);
-+    memBufPrintf(&mb_hdr, "%s %s HTTP/%d.%d\r\n",
-+	RequestMethodStr[icap->request->method],
-+	icap->reqmod.uri,
-+	icap->request->http_ver.major, icap->request->http_ver.minor);
-+    packerToMemInit(&p, &mb_hdr);
-+    httpHeaderPackInto(&icap->request->header, &p);
-+    packerClean(&p);
-+    memBufAppend(&mb_hdr, crlf, 2);
-+    service = icap->current_service;
-+    assert(service);
-+    client_addr = inet_ntoa(icap->request->client_addr);
-+
-+    memBufPrintf(&mb, "REQMOD %s ICAP/1.0\r\n", service->uri);
-+    memBufPrintf(&mb, "Encapsulated: req-hdr=0");
-+    /* TODO: Change the offset using 'request' if needed */
-+    if (icap->request->content_length > 0)
-+	memBufPrintf(&mb, ", req-body=%d", mb_hdr.size);
-+    else
-+	memBufPrintf(&mb, ", null-body=%d", mb_hdr.size);
-+    memBufAppend(&mb, crlf, 2);
-+
-+    if (service->flags.need_x_client_ip && Config.icapcfg.send_client_ip)
-+	memBufPrintf(&mb, "X-Client-IP: %s\r\n", client_addr);
-+
-+    if (service->flags.need_x_server_ip && Config.icapcfg.send_server_ip)
-+        icapAddOriginIP(&mb, icap->request->host);
-+
-+    if ((service->flags.need_x_authenticated_user
-+	    && Config.icapcfg.send_auth_user)
-+	&& (icap->request->auth_user_request != NULL))
-+	icapAddAuthUserHeader(&mb, icap->request->auth_user_request);
-+    if (service->keep_alive) {
-+	icap->flags.keep_alive = 1;
-+    } else {
-+	icap->flags.keep_alive = 0;
-+	memBufAppend(&mb, "Connection: close\r\n", 19);
-+    }
-+    memBufAppend(&mb, crlf, 2);
-+    memBufAppend(&mb, mb_hdr.buf, mb_hdr.size);
-+    memBufClean(&mb_hdr);
-+
-+    debug(81, 5) ("icapSendReqMod: FD %d writing {%s}\n", icap->icap_fd,
-+	mb.buf);
-+    comm_write_mbuf(icap_fd, mb, theCallback, icap);
-+}
-+
-+/*
-+ * icapReqModStart
-+ *
-+ * Initiate an ICAP REQMOD transaction.  Create and fill in IcapStateData
-+ * structure and request a TCP connection to the server.
-+ */
-+IcapStateData *
-+icapReqModStart(icap_service *service, const char *uri, request_t * request,
-+    int fd, struct timeval start, struct in_addr log_addr, void *cookie)
-+{
-+    IcapStateData *icap = NULL;
-+
-+    debug(81, 3) ("icapReqModStart: type=%d\n", (int) service->type);
-+
-+    switch (service->type) {
-+    case ICAP_SERVICE_REQMOD_PRECACHE:
-+	break;
-+    default:
-+	fatalf("icapReqModStart: unsupported service type '%s'\n",
-+	    icap_service_type_str[service->type]);
-+	break;
-+    }
-+
-+    if (service->unreachable) {
-+	if (service->bypass) {
-+	    debug(81,
-+		5) ("icapReqModStart: BYPASS because service unreachable: %s\n",
-+		service->uri);
-+	    return NULL;
-+	} else {
-+	    debug(81,
-+		5) ("icapReqModStart: ERROR  because service unreachable: %s\n",
-+		service->uri);
-+	    return (IcapStateData *) - 1;
-+	}
-+    }
-+    icap = icapAllocate();
-+    if (!icap) {
-+	debug(81, 3) ("icapReqModStart: icapAllocate() failed\n");
-+	return NULL;
-+    }
-+    icap->current_service = service;
-+    icap->preview_size = service->preview;
-+    icap->reqmod.uri = uri;	/* XXX should be xstrdup? */
-+    icap->reqmod.start = start;
-+    icap->reqmod.log_addr = log_addr;
-+    icap->request = requestLink(request);
-+    icap->reqmod.hdr_state = 0;
-+    icap->reqmod.client_fd = fd;
-+    icap->reqmod.client_cookie = cookie;
-+    cbdataLock(icap->reqmod.client_cookie);
-+
-+    if (!icapConnect(icap, icapSendReqMod))
-+	return NULL;
-+
-+    statCounter.icap.all.requests++;
-+    debug(81, 3) ("icapReqModStart: returning %p\n", icap);
-+    return icap;
-+}
-+
-+/*
-+ * icapReqModSendBodyChunk
-+ *
-+ * A "comm_write" callback.  This is called after comm_write() does
-+ * its job to let us know how things went.  If there are no errors,
-+ * get another chunk of the body from client_side.
-+ */
-+static void
-+icapReqModSendBodyChunk(int fd, char *bufnotused, size_t size, int errflag,
-+    void *data)
-+{
-+    IcapStateData *icap = data;
-+    debug(81, 3) ("icapReqModSendBodyChunk: FD %d wrote %d errflag %d.\n",
-+	fd, (int) size, errflag);
-+    if (errflag == COMM_ERR_CLOSING)
-+	return;
-+    if (errflag) {
-+	icapEntryError(icap, ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR,
-+	    errno);
-+	comm_close(fd);
-+	return;
-+    }
-+    clientReadBody(icap->request,
-+	memAllocate(MEM_8K_BUF), 8192, icapReqModBodyHandler, icap);
-+}
-+
-+/*
-+ * icapReqModBodyHandler
-+ *
-+ * Called after Squid gets a chunk of the request entity from the
-+ * client side.  The body is chunkified and passed to comm_write.
-+ * The comm_write callback depends on whether or not this is the
-+ * last chunk.
-+ */
-+static void
-+icapReqModBodyHandler(char *buf, ssize_t size, void *data)
-+{
-+    IcapStateData *icap = data;
-+    MemBuf mb;
-+    CWCB *theCallback = icapReqModSendBodyChunk;
-+    if (size < 0) {
-+	debug(81, 1) ("icapReqModBodyHandler: %s\n", xstrerror());
-+	memFree8K(buf);
-+	return;
-+    }
-+    memBufDefInit(&mb);
-+    debug(81, 3) ("icapReqModBodyHandler: writing chunk size %d\n", size);
-+    memBufPrintf(&mb, "%x\r\n", size);
-+    if (size)
-+	memBufAppend(&mb, buf, size);
-+    else
-+	theCallback = icapSendReqModDone;
-+    memBufAppend(&mb, crlf, 2);
-+    memFree8K(buf);
-+    comm_write_mbuf(icap->icap_fd, mb, theCallback, icap);
-+}
-+
-+/*
-+ * icapReqModReadHttpBody
-+ *
-+ * The read handler for the client's HTTP connection when reading
-+ * message bodies.  Called by comm_select().
-+ */
-+static void
-+icapReqModReadHttpBody(int fd, void *data)
-+{
-+    IcapStateData *icap = data;
-+    int len;
-+    debug(81, 3) ("icapReqModReadHttpBody: FD %d called\n", fd);
-+    len = memBufRead(fd, &icap->chunk_buf);
-+    debug(81, 3) ("icapReqModReadHttpBody: read returns %d\n", len);
-+    if (len < 0) {
-+	debug(81, 3) ("icapReqModReadHttpBody: FD %d %s\n", fd, xstrerror());
-+	if (!ignoreErrno(errno))
-+	    icap->flags.reqmod_http_entity_eof = 1;
-+    } else if (0 == len) {
-+	debug(81, 3) ("icapReqModReadHttpBody: FD %d EOF\n", fd);
-+	icap->flags.reqmod_http_entity_eof = 1;
-+    } else {
-+	fd_bytes(fd, len, FD_READ);
-+	kb_incr(&statCounter.icap.all.kbytes_in, len);
-+	icap->reqmod.http_entity.bytes_read +=
-+	    icapParseChunkedBody(icap,
-+	    icapReqModMemBufAppend, &icap->reqmod.http_entity.buf);
-+    }
-+    if (icap->reqmod.http_entity.bytes_read >= icap->request->content_length)
-+	icap->flags.reqmod_http_entity_eof = 1;
-+
-+    if (!icap->flags.reqmod_http_entity_eof)
-+	commSetSelect(fd, COMM_SELECT_READ, icapReqModReadHttpBody, icap, 0);
-+    /*
-+     * Notify the other side if it is waiting for data from us
-+     */
-+    debug(81, 3) ("%s:%d http_entity.callback=%p\n", __FILE__, __LINE__,
-+	icap->reqmod.http_entity.callback);
-+    debug(81, 3) ("%s:%d http_entity.buf.size=%d\n", __FILE__, __LINE__,
-+	icap->reqmod.http_entity.buf.size);
-+    if (icap->reqmod.http_entity.callback && icap->reqmod.http_entity.buf.size) {
-+	icapReqModPassHttpBody(icap,
-+	    icap->reqmod.http_entity.callback_buf,
-+	    icap->reqmod.http_entity.callback_bufsize,
-+	    icap->reqmod.http_entity.callback,
-+	    icap->reqmod.http_entity.callback_data);
-+	icap->reqmod.http_entity.callback = NULL;
-+	cbdataUnlock(icap->reqmod.http_entity.callback_data);
-+
-+    }
-+}
-+
-+/*
-+ * icapReqModPassHttpBody
-+ *
-+ * Called from http.c after request headers have been sent.
-+ * This function feeds the http.c module chunks of the request
-+ * body that were stored in the http_entity.buf MemBuf.
-+ */
-+static void
-+icapReqModPassHttpBody(IcapStateData * icap, char *buf, size_t size,
-+    CBCB * callback, void *cbdata)
-+{
-+    debug(81, 3) ("icapReqModPassHttpBody: called\n");
-+    if (!buf) {
-+	debug(81, 1) ("icapReqModPassHttpBody: FD %d called with %p, %d, %p (request aborted)\n",
-+	    icap->icap_fd, buf, (int) size, cbdata);
-+	comm_close(icap->icap_fd);
-+	return;
-+    }
-+    if (!cbdataValid(cbdata)) {
-+	debug(81,
-+	    1)
-+	    ("icapReqModPassHttpBody: FD %d callback data invalid, closing\n",
-+	    icap->icap_fd);
-+	comm_close(icap->icap_fd);	/*It is better to be sure that the connection will be  closed..... */
-+	/*icapReqModKeepAliveOrClose(icap); */
-+	return;
-+    }
-+    debug(81, 3) ("icapReqModPassHttpBody: entity buf size = %d\n",
-+	icap->reqmod.http_entity.buf.size);
-+    if (icap->reqmod.http_entity.buf.size) {
-+	int copy_sz = icap->reqmod.http_entity.buf.size;
-+	if (copy_sz > size)
-+	    copy_sz = size;
-+	xmemcpy(buf, icap->reqmod.http_entity.buf.buf, copy_sz);
-+	/* XXX don't let Alex see this ugliness */
-+	xmemmove(icap->reqmod.http_entity.buf.buf,
-+	    icap->reqmod.http_entity.buf.buf + copy_sz,
-+	    icap->reqmod.http_entity.buf.size - copy_sz);
-+	icap->reqmod.http_entity.buf.size -= copy_sz;
-+	debug(81, 3) ("icapReqModPassHttpBody: giving %d bytes to other side\n",
-+	    copy_sz);
-+	callback(buf, copy_sz, cbdata);
-+	debug(81, 3) ("icapReqModPassHttpBody: entity buf size now = %d\n",
-+	    icap->reqmod.http_entity.buf.size);
-+	return;
-+    }
-+    if (icap->flags.reqmod_http_entity_eof) {
-+	debug(81, 3) ("icapReqModPassHttpBody: signalling EOF\n");
-+	callback(buf, 0, cbdata);
-+	icapReqModKeepAliveOrClose(icap);
-+	return;
-+    }
-+    /*
-+     * We have no data for the other side at this point.  Save all
-+     * these values and use them when we do have data.
-+     */
-+    assert(NULL == icap->reqmod.http_entity.callback);
-+    icap->reqmod.http_entity.callback = callback;
-+    icap->reqmod.http_entity.callback_data = cbdata;
-+    icap->reqmod.http_entity.callback_buf = buf;
-+    icap->reqmod.http_entity.callback_bufsize = size;
-+    cbdataLock(icap->reqmod.http_entity.callback_data);
-+}
-+
-+/*
-+ * Body reader handler for use with request->body_reader function
-+ * Simple a wrapper for icapReqModPassHttpBody function
-+ */
-+
-+static void
-+icapReqModBodyReader(request_t * request, char *buf, size_t size,
-+    CBCB * callback, void *cbdata)
-+{
-+    IcapStateData *icap = request->body_reader_data;
-+    icapReqModPassHttpBody(icap, buf, size, callback, cbdata);
-+}
-+
-+/*
-+ * icapReqModMemBufAppend
-+ *
-+ * stupid wrapper to eliminate compiler warnings
-+ */
-+static void
-+icapReqModMemBufAppend(void *data, const char *buf, ssize_t size)
-+{
-+    memBufAppend(data, buf, size);
-+}
-Index: src/icap_respmod.c
-===================================================================
-RCS file: src/icap_respmod.c
-diff -N src/icap_respmod.c
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ src/icap_respmod.c	25 May 2006 16:04:55 -0000	1.1.2.65
-@@ -0,0 +1,1055 @@
-+
-+/*
-+ * $Id$
-+ *
-+ * DEBUG: section 81    Internet Content Adaptation Protocol (ICAP) Client
-+ * AUTHOR: Geetha Manjunath, Hewlett Packard Company
-+ *
-+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
-+ * ----------------------------------------------------------
-+ *
-+ *  Squid is the result of efforts by numerous individuals from
-+ *  the Internet community; see the CONTRIBUTORS file for full
-+ *  details.   Many organizations have provided support for Squid's
-+ *  development; see the SPONSORS file for full details.  Squid is
-+ *  Copyrighted (C) 2001 by the Regents of the University of
-+ *  California; see the COPYRIGHT file for full details.  Squid
-+ *  incorporates software developed and/or copyrighted by other
-+ *  sources; see the CREDITS file for full details.
-+ *
-+ *  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, USA.
-+ *
-+ */
-+
-+#include "squid.h"
-+
-+static CWCB icapSendRespModDone;
-+static PF icapRespModGobble;
-+extern PF icapReadReply;
-+static PF icapRespModReadReply;
-+static int icapReadReply2(IcapStateData * icap);
-+static void icapReadReply3(IcapStateData * icap);
-+
-+#define EXPECTED_ICAP_HEADER_LEN 256
-+const char *crlf = "\r\n";
-+
-+static void
-+getICAPRespModString(MemBuf * mb, int o1, int o2, int o3,
-+    const char *client_addr, IcapStateData * icap, const icap_service * service)
-+{
-+    memBufPrintf(mb, "RESPMOD %s ICAP/1.0\r\nEncapsulated:", service->uri);
-+    if (o1 >= 0)
-+	memBufPrintf(mb, " req-hdr=%1d", o1);
-+    if (o2 >= 0)
-+	memBufPrintf(mb, ", res-hdr=%1d", o2);
-+    if (o3 >= 0)
-+	memBufPrintf(mb, ", res-body=%1d", o3);
-+    else
-+	memBufPrintf(mb, ", null-body=%1d", -o3);
-+    memBufPrintf(mb, crlf);
-+
-+    if (service->flags.need_x_client_ip && Config.icapcfg.send_client_ip) {
-+	memBufPrintf(mb, "X-Client-IP: %s\r\n", client_addr);
-+    }
-+
-+    if (service->flags.need_x_server_ip && Config.icapcfg.send_server_ip)
-+        icapAddOriginIP(mb, icap->request->host);
-+
-+    if ((service->flags.need_x_authenticated_user
-+	    && Config.icapcfg.send_auth_user)
-+	&& (icap->request->auth_user_request != NULL)) {
-+	icapAddAuthUserHeader(mb, icap->request->auth_user_request);
-+    }
-+#if NOT_YET_FINISHED
-+    if (Config.icapcfg.trailers) {
-+	memBufPrintf(mb, "X-TE: trailers\r\n");
-+    }
-+#endif
-+}
-+
-+static int
-+buildRespModHeader(MemBuf * mb, IcapStateData * icap, char *buf,
-+    ssize_t len, int theEnd)
-+{
-+    MemBuf mb_hdr;
-+    char *client_addr;
-+    int o2 = 0;
-+    int o3 = 0;
-+    int hlen;
-+    int consumed;
-+    icap_service *service;
-+    HttpReply *r;
-+
-+    if (memBufIsNull(&icap->respmod.req_hdr_copy))
-+	memBufDefInit(&icap->respmod.req_hdr_copy);
-+
-+    memBufAppend(&icap->respmod.req_hdr_copy, buf, len);
-+
-+    if (icap->respmod.req_hdr_copy.size > 4 && strncmp(icap->respmod.req_hdr_copy.buf, "HTTP/", 5)) {
-+	debug(81, 3) ("buildRespModHeader: Non-HTTP-compliant header: '%s'\n", buf);
-+	/*
-+	 *Possible we can consider that we did not have http responce headers 
-+	 *(maybe HTTP 0.9 protocol), lets returning -1...
-+	 */
-+	consumed = -1;
-+	o2 = -1;
-+	memBufDefInit(&mb_hdr);
-+	httpBuildRequestPrefix(icap->request, icap->request,
-+			       icap->respmod.entry, &mb_hdr, icap->http_flags);
-+	o3 = mb_hdr.size;
-+    } else {
-+
-+	hlen = headersEnd(icap->respmod.req_hdr_copy.buf,
-+	    icap->respmod.req_hdr_copy.size);
-+	debug(81, 3) ("buildRespModHeader: headersEnd = %d(%s)\n", hlen, buf);
-+	if (0 == hlen)
-+	    return 0;
-+
-+	/*
-+	 * calc how many bytes from this 'buf' went towards the
-+	 * reply header.
-+	 */
-+	consumed = hlen - (icap->respmod.req_hdr_copy.size - len);
-+	debug(81, 3) ("buildRespModHeader: consumed = %d\n", consumed);
-+
-+
-+	/*
-+	 * now, truncate our req_hdr_copy at the header end.
-+	 * this 'if' statement might be unncessary?
-+	 */
-+	if (hlen < icap->respmod.req_hdr_copy.size)
-+	    icap->respmod.req_hdr_copy.size = hlen;
-+
-+	/* Copy request header */
-+	memBufDefInit(&mb_hdr);
-+	httpBuildRequestPrefix(icap->request, icap->request,
-+	    icap->respmod.entry, &mb_hdr, icap->http_flags);
-+	o2 = mb_hdr.size;
-+
-+    	/* Copy response header - Append to request header mbuffer */
-+	memBufAppend(&mb_hdr,
-+		     icap->respmod.req_hdr_copy.buf, icap->respmod.req_hdr_copy.size);
-+	o3 = mb_hdr.size;
-+    }
-+
-+    service = icap->current_service;
-+    assert(service);
-+    client_addr = inet_ntoa(icap->request->client_addr);
-+
-+    r = httpReplyCreate();
-+    httpReplyParse(r, icap->respmod.req_hdr_copy.buf,
-+	icap->respmod.req_hdr_copy.size);
-+    icap->respmod.res_body_sz = httpReplyBodySize(icap->request->method, r);
-+    httpReplyDestroy(r);
-+    if (icap->respmod.res_body_sz)
-+	getICAPRespModString(mb, 0, o2, o3, client_addr, icap, service);
-+    else
-+	getICAPRespModString(mb, 0, o2, -o3, client_addr, icap, service);
-+    if (Config.icapcfg.preview_enable)
-+	if (icap->preview_size >= 0) {
-+	    memBufPrintf(mb, "Preview: %d\r\n", icap->preview_size);
-+	    icap->flags.preview_done = 0;
-+	}
-+    if (service->keep_alive) {
-+	icap->flags.keep_alive = 1;
-+	memBufAppend(mb, "Connection: keep-alive\r\n", 24);
-+    } else {
-+	icap->flags.keep_alive = 0;
-+	memBufAppend(mb, "Connection: close\r\n", 19);
-+    }
-+    memBufAppend(mb, crlf, 2);
-+    memBufAppend(mb, mb_hdr.buf, mb_hdr.size);
-+    memBufClean(&mb_hdr);
-+
-+
-+    return consumed;
-+}
-+
-+
-+void
-+icapSendRespMod(IcapStateData * icap, char *buf, int len, int theEnd)
-+{
-+    MemBuf mb;
-+#if ICAP_PREVIEW
-+    int size;
-+    const int preview_size = icap->preview_size;
-+#endif
-+    debug(81, 5) ("icapSendRespMod: FD %d, len %d, theEnd %d\n",
-+	icap->icap_fd, len, theEnd);
-+
-+    if (icap->flags.no_content) {
-+	/*
-+	 * ICAP server said there are no modifications to make, so
-+	 * just append this data to the StoreEntry
-+	 */
-+	if (icap->respmod.resp_copy.size) {
-+	    /*
-+	     * first copy the data that we already sent to the ICAP server
-+	     */
-+	    memBufAppend(&icap->chunk_buf,
-+		icap->respmod.resp_copy.buf, icap->respmod.resp_copy.size);
-+	    icap->respmod.resp_copy.size = 0;
-+	}
-+	debug(81, 5) ("icapSendRepMod: len=%d theEnd=%d write_pending=%d\n",
-+	    len, theEnd, icap->flags.write_pending);
-+	if (len) {
-+	    /*
-+	     * also copy any new data from the HTTP side
-+	     */
-+	    memBufAppend(&icap->chunk_buf, buf, len);
-+	}
-+	(void) icapReadReply2(icap);
-+	return;
-+    }
-+    if (theEnd) {
-+	if (icap->respmod.res_body_sz)
-+	    icap->flags.send_zero_chunk = 1;
-+	icap->flags.http_server_eof = 1;
-+    }
-+    /*
-+     * httpReadReply is going to call us with a chunk and then
-+     * right away again with an EOF if httpPconnTransferDone() is true.
-+     * Since the first write is already dispatched, we'll have to 
-+     * hack this in somehow.
-+     */
-+    if (icap->flags.write_pending) {
-+	debug(81, 3) ("icapSendRespMod: oops, write_pending=1\n");
-+	assert(theEnd);
-+	assert(len == 0);
-+	return;
-+    }
-+    if (!cbdataValid(icap)) {
-+	debug(81, 3) ("icapSendRespMod: failed to establish connection?\n");
-+	return;
-+    }
-+    memBufDefInit(&mb);
-+
-+#if SUPPORT_ICAP_204 || ICAP_PREVIEW
-+    /*
-+     * make a copy of the response in case ICAP server gives us a 204
-+     */
-+    /*
-+     * This piece of code is problematic for 204 responces outside preview.
-+     * The icap->respmod.resp_copy continues to filled until we had responce
-+     * If the icap server waits to gets all data before sends its responce 
-+     * then we are puting all downloading object to the main system memory.
-+     * My opinion is that 204 responces outside preview must be disabled .....
-+     * /chtsanti
-+     */
-+
-+    if (len && icap->flags.copy_response) {
-+	if (memBufIsNull(&icap->respmod.resp_copy))
-+	    memBufDefInit(&icap->respmod.resp_copy);
-+	memBufAppend(&icap->respmod.resp_copy, buf, len);
-+    }
-+#endif
-+
-+    if (icap->sc == 0) {
-+        // http connection has been closed without sending us anything
-+        if(len == 0 && theEnd == 1) {
-+	    ErrorState *err;
-+	    err = errorCon(ERR_INVALID_RESP, HTTP_BAD_GATEWAY);
-+	    err->request = requestLink(icap->request);
-+	    errorAppendEntry(icap->respmod.entry, err);
-+	    comm_close(icap->icap_fd);
-+	    return;
-+        }
-+
-+	/* No data sent yet. Start with headers */
-+	if ((icap->sc = buildRespModHeader(&mb, icap, buf, len, theEnd)) > 0) {
-+	    buf += icap->sc;
-+	    len -= icap->sc;
-+	}
-+	/*
-+	 * Then we do not have http responce headers. All data (previous and those in buf)
-+	 * now are exist to icap->respmod.req_hdr_copy. Lets get them back.......
-+	 */
-+	if (icap->sc < 0) {
-+	    memBufAppend(&icap->respmod.buffer,
-+		icap->respmod.req_hdr_copy.buf,
-+		icap->respmod.req_hdr_copy.size);
-+	    icap->sc = icap->respmod.req_hdr_copy.size;
-+	    icap->respmod.req_hdr_copy.size = 0;
-+	    buf = NULL;
-+	    len = 0;
-+	}
-+    }
-+    if (0 == icap->sc) {
-+	/* check again; bail if we're not ready to send ICAP/HTTP hdrs */
-+	debug(81, 5) ("icapSendRespMod: dont have full HTTP response hdrs\n");
-+	memBufClean(&mb);
-+	return;
-+    }
-+#if ICAP_PREVIEW
-+    if (preview_size < 0 || !Config.icapcfg.preview_enable)	/* preview feature off */
-+	icap->flags.preview_done = 1;
-+
-+    if (!icap->flags.preview_done) {
-+	/* preview not yet sent */
-+	if (icap->sc > 0 && icap->respmod.buffer.size <= preview_size
-+	    && len > 0) {
-+	    /* Try to collect at least preview_size+1 bytes */
-+	    /* By collecting one more byte than needed for preview we know best */
-+	    /* whether we have to send the ieof chunk extension */
-+	    size = icap->respmod.buffer.size + len;
-+	    if (size > preview_size + 1)
-+		size = preview_size + 1;
-+	    size -= icap->respmod.buffer.size;
-+	    debug(81,
-+		3)
-+		("icapSendRespMod: FD %d: copy %d more bytes to preview buffer.\n",
-+		icap->icap_fd, size);
-+	    memBufAppend(&icap->respmod.buffer, buf, size);
-+	    buf = ((char *) buf) + size;
-+	    len -= size;
-+	}
-+	if (icap->respmod.buffer.size > preview_size || theEnd) {
-+	    /* we got enough bytes for preview or this is the last call */
-+	    /* add preview preview now */
-+	    if (icap->respmod.buffer.size > 0) {
-+		size = icap->respmod.buffer.size;
-+		if (size > preview_size)
-+		    size = preview_size;
-+		memBufPrintf(&mb, "%x\r\n", size);
-+		memBufAppend(&mb, icap->respmod.buffer.buf, size);
-+		memBufAppend(&mb, crlf, 2);
-+		icap->sc += size;
-+	    }
-+	    if (icap->respmod.buffer.size <= preview_size) {
-+		/* content length is less than preview size+1 */
-+		if (icap->respmod.res_body_sz)
-+		    memBufAppend(&mb, "0; ieof\r\n\r\n", 11);
-+		memBufReset(&icap->respmod.buffer);	/* will now be used for other data */
-+	    } else {
-+		char ch;
-+		memBufAppend(&mb, "0\r\n\r\n", 5);
-+		/* end of preview, wait for continue or 204 signal */
-+		/* copy the extra byte and all other data to the icap buffer */
-+		/* so that it can be handled next time */
-+		ch = icap->respmod.buffer.buf[preview_size];
-+		memBufReset(&icap->respmod.buffer);	/* will now be used for other data */
-+		memBufAppend(&icap->respmod.buffer, &ch, 1);
-+		debug(81,
-+		    3)
-+		    ("icapSendRespMod: FD %d: sending preview and keeping %d bytes in internal buf.\n",
-+		    icap->icap_fd, len + 1);
-+		if (len > 0)
-+		    memBufAppend(&icap->respmod.buffer, buf, len);
-+	    }
-+	    icap->flags.preview_done = 1;
-+	    icap->flags.wait_for_preview_reply = 1;
-+	}
-+    } else if (icap->flags.wait_for_preview_reply) {
-+	/* received new data while waiting for preview response */
-+	/* add data to internal buffer and send later */
-+	debug(81,
-+	    3)
-+	    ("icapSendRespMod: FD %d: add %d more bytes to internal buf while waiting for preview-response.\n",
-+	    icap->icap_fd, len);
-+	if (len > 0)
-+	    memBufAppend(&icap->respmod.buffer, buf, len);
-+	/* do not send any data now while waiting for preview response */
-+	/* but prepare for read more data on the HTTP connection */
-+	memBufClean(&mb);
-+	return;
-+    } else
-+#endif
-+    {
-+	/* after preview completed and ICAP preview response received */
-+	/* there may still be some data in the buffer */
-+	if (icap->respmod.buffer.size > 0) {
-+	    memBufPrintf(&mb, "%x\r\n", icap->respmod.buffer.size);
-+	    memBufAppend(&mb, icap->respmod.buffer.buf,
-+		icap->respmod.buffer.size);
-+	    memBufAppend(&mb, crlf, 2);
-+	    icap->sc += icap->respmod.buffer.size;
-+	    memBufReset(&icap->respmod.buffer);
-+	}
-+	if (len > 0) {
-+	    memBufPrintf(&mb, "%x\r\n", len);
-+	    memBufAppend(&mb, buf, len);
-+	    memBufAppend(&mb, crlf, 2);
-+	    icap->sc += len;
-+	}
-+	if (icap->flags.send_zero_chunk) {
-+	    /* send zero end chunk */
-+	    icap->flags.send_zero_chunk = 0;
-+	    icap->flags.http_server_eof = 1;
-+	    memBufAppend(&mb, "0\r\n\r\n", 5);
-+	}
-+	/* wait for data coming from ICAP server as soon as we sent something */
-+	/* but of course only until we got the response header */
-+	if (!icap->flags.got_reply)
-+	    icap->flags.wait_for_reply = 1;
-+    }
-+    commSetTimeout(icap->icap_fd, -1, NULL, NULL);
-+
-+    if (!mb.size) {
-+	memBufClean(&mb);
-+	return;
-+    }
-+    debug(81, 5) ("icapSendRespMod: FD %d writing {%s}\n", icap->icap_fd,
-+	mb.buf);
-+    icap->flags.write_pending = 1;
-+    comm_write_mbuf(icap->icap_fd, mb, icapSendRespModDone, icap);
-+}
-+
-+static void
-+icapRespModReadReply(int fd, void *data)
-+{
-+    IcapStateData *icap = data;
-+    int version_major, version_minor;
-+    const char *str_status;
-+    int x;
-+    int status = 0;
-+    int isIcap = 0;
-+    int directResponse = 0;
-+    ErrorState *err;
-+    const char *start;
-+    const char *end;
-+
-+    debug(81, 5) ("icapRespModReadReply: FD %d data = %p\n", fd, data);
-+    statCounter.syscalls.sock.reads++;
-+
-+    x = icapReadHeader(fd, icap, &isIcap);
-+    if (x < 0) {
-+	/* Did not find a proper ICAP response */
-+	debug(81, 3) ("ICAP : Error path!\n");
-+	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
-+	err->request = requestLink(icap->request);
-+	err->xerrno = errno;
-+	errorAppendEntry(icap->respmod.entry, err);
-+	comm_close(fd);
-+	return;
-+    }
-+    if (x == 0) {
-+	/*
-+	 * Waiting for more headers.  Schedule new read hander, but
-+	 * don't reset timeout.
-+	 */
-+	commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0);
-+	return;
-+    }
-+    /*
-+     * Parse the ICAP header
-+     */
-+    assert(icap->icap_hdr.size);
-+    debug(81, 3) ("Parse icap header : <%s>\n", icap->icap_hdr.buf);
-+    if ((status =
-+	    icapParseStatusLine(icap->icap_hdr.buf, icap->icap_hdr.size,
-+		&version_major, &version_minor, &str_status)) < 0) {
-+	debug(81, 1) ("BAD ICAP status line <%s>\n", icap->icap_hdr.buf);
-+	/* is this correct in case of ICAP protocol error? */
-+	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
-+	err->request = requestLink(icap->request);
-+	err->xerrno = errno;
-+	errorAppendEntry(icap->respmod.entry, err);
-+	comm_close(fd);
-+	return;
-+    };
-+    /*  OK here we have responce. Lets stop filling the 
-+     *  icap->respmod.resp_copy buffer ....
-+     */
-+    icap->flags.copy_response = 0;
-+
-+    icapSetKeepAlive(icap, icap->icap_hdr.buf);
-+#if ICAP_PREVIEW
-+    if (icap->flags.wait_for_preview_reply) {
-+	if (100 == status) {
-+	    debug(81, 5) ("icapRespModReadReply: 100 Continue received\n");
-+	    icap->flags.wait_for_preview_reply = 0;
-+	    /* if http_server_eof
-+	     * call again icapSendRespMod to handle data that
-+	     * was received while waiting for this ICAP response
-+	     * else let http to call icapSendRespMod when new data arrived
-+	     */
-+	    if (icap->flags.http_server_eof)
-+		icapSendRespMod(icap, NULL, 0, 0);
-+	    /*
-+	     * reset the header to send the rest of the preview
-+	     */
-+	    if (!memBufIsNull(&icap->icap_hdr))
-+		memBufReset(&icap->icap_hdr);
-+
-+	    /*We do n't need it any more ....... */
-+	    if (!memBufIsNull(&icap->respmod.resp_copy))
-+		memBufClean(&icap->respmod.resp_copy);
-+
-+	    return;
-+	}
-+	if (204 == status) {
-+	    debug(81,
-+		5) ("icapRespModReadReply: 204 No modification received\n");
-+	    icap->flags.wait_for_preview_reply = 0;
-+	}
-+    }
-+#endif /*ICAP_PREVIEW */
-+
-+#if SUPPORT_ICAP_204 || ICAP_PREVIEW
-+    if (204 == status) {
-+	debug(81, 3) ("got 204 status from ICAP server\n");
-+	debug(81, 3) ("setting icap->flags.no_content\n");
-+	icap->flags.no_content = 1;
-+	/*
-+	 * copy the response already written to the ICAP server
-+	 */
-+	debug(81, 3) ("copying %d bytes from resp_copy to chunk_buf\n",
-+	    icap->respmod.resp_copy.size);
-+	memBufAppend(&icap->chunk_buf,
-+	    icap->respmod.resp_copy.buf, icap->respmod.resp_copy.size);
-+	icap->respmod.resp_copy.size = 0;
-+	if (icapReadReply2(icap) < 0)
-+	    comm_close(fd);
-+	/*
-+	 * XXX ideally want to clean icap->respmod.resp_copy here
-+	 * XXX ideally want to "close" ICAP server connection here
-+	 * OK do it....
-+	 */
-+	if (!memBufIsNull(&icap->respmod.resp_copy))
-+	    memBufClean(&icap->respmod.resp_copy);
-+	return;
-+    }
-+#endif
-+    if (200 != status && 201 != status) {
-+	debug(81, 1) ("Unsupported status '%d' from ICAP server\n", status);
-+	/* Did not find a proper ICAP response */
-+	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
-+	err->request = requestLink(icap->request);
-+	err->xerrno = errno;
-+	errorAppendEntry(icap->respmod.entry, err);
-+	comm_close(fd);
-+	return;
-+    }
-+    if (icapFindHeader(icap->icap_hdr.buf, "Encapsulated:", &start, &end)) {
-+	icapParseEncapsulated(icap, start, end);
-+    } else {
-+	debug(81,
-+	    1)
-+	    ("WARNING: icapRespModReadReply() did not find 'Encapsulated' header\n");
-+    }
-+    if (icap->enc.res_hdr > -1)
-+	directResponse = 1;
-+    else if (icap->enc.res_body > -1)
-+	directResponse = 1;
-+    else
-+	directResponse = 0;
-+
-+    /*
-+     * "directResponse" is the normal case here.  If we don't have
-+     * a response header or body, it is an error.
-+     */
-+    if (!directResponse) {
-+	/* Did not find a proper ICAP response */
-+	debug(81, 3) ("ICAP : Error path!\n");
-+	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
-+	err->request = requestLink(icap->request);
-+	err->xerrno = errno;
-+	errorAppendEntry(icap->respmod.entry, err);
-+	comm_close(fd);
-+	return;
-+    }
-+    /* got the reply, no need to come here again */
-+    icap->flags.wait_for_reply = 0;
-+    icap->flags.got_reply = 1;
-+    /* Next, gobble any data before the HTTP response starts */
-+    if (icap->enc.res_hdr > -1)
-+	icap->bytes_to_gobble = icap->enc.res_hdr;
-+    commSetSelect(fd, COMM_SELECT_READ, icapRespModGobble, icap, 0);
-+}
-+
-+
-+/*
-+ * Gobble up (read) some bytes until we get to the start of the body
-+ */
-+static void
-+icapRespModGobble(int fd, void *data)
-+{
-+    IcapStateData *icap = data;
-+    int len;
-+    LOCAL_ARRAY(char, junk, SQUID_TCP_SO_RCVBUF);
-+    debug(81, 3) ("icapRespModGobble: FD %d gobbling %d bytes\n", fd,
-+	icap->bytes_to_gobble);
-+    len = FD_READ_METHOD(fd, junk, icap->bytes_to_gobble);
-+    debug(81, 3) ("icapRespModGobble: gobbled %d bytes\n", len);
-+    if (len < 0) {
-+	/* XXX error */
-+	abort();
-+    }
-+    icap->bytes_to_gobble -= len;
-+    if (icap->bytes_to_gobble)
-+	commSetSelect(fd, COMM_SELECT_READ, icapRespModGobble, icap, 0);
-+    else
-+	icapReadReply(fd, icap);
-+}
-+
-+
-+static void
-+icapSendRespModDone(int fd, char *bufnotused, size_t size, int errflag,
-+    void *data)
-+{
-+    IcapStateData *icap = data;
-+    ErrorState *err;
-+
-+    icap->flags.write_pending = 0;
-+    debug(81, 5) ("icapSendRespModDone: FD %d: size %d: errflag %d.\n",
-+	fd, size, errflag);
-+    if (size > 0) {
-+	fd_bytes(fd, size, FD_WRITE);
-+	kb_incr(&statCounter.icap.all.kbytes_out, size);
-+    }
-+    if (errflag == COMM_ERR_CLOSING)
-+	return;
-+    if (errflag) {
-+	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
-+	err->xerrno = errno;
-+	if (cbdataValid(icap))
-+	    err->request = requestLink(icap->request);
-+	storeEntryReset(icap->respmod.entry);
-+	errorAppendEntry(icap->respmod.entry, err);
-+	comm_close(fd);
-+	return;
-+    }
-+    if (EBIT_TEST(icap->respmod.entry->flags, ENTRY_ABORTED)) {
-+	debug(81, 3) ("icapSendRespModDone: Entry Aborded\n");
-+	comm_close(fd);
-+	return;
-+    }
-+    if (icap->flags.send_zero_chunk) {
-+	debug(81,
-+	    3) ("icapSendRespModDone: I'm supposed to send zero chunk now\n");
-+	icap->flags.send_zero_chunk = 0;
-+	icapSendRespMod(icap, NULL, 0, 1);
-+	return;
-+    }
-+    if (icap->flags.wait_for_preview_reply || icap->flags.wait_for_reply) {
-+	/* Schedule reading the ICAP response */
-+	debug(81,
-+	    3)
-+	    ("icapSendRespModDone: FD %d: commSetSelect on read icapRespModReadReply.\n",
-+	    fd);
-+	commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0);
-+#if 1
-+	commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
-+	commSetDefer(fd, fwdCheckDeferRead, icap->respmod.entry);
-+#else
-+	if (icap->flags.wait_for_preview_reply || icap->flags.http_server_eof) {
-+	    /*
-+	     * Set the read timeout only after all data has been sent
-+	     * or we are waiting for a preview response
-+	     * If the ICAP server does not return any data till all data
-+	     * has been sent, we are likely to hit the timeout for large
-+	     * HTTP bodies
-+	     */
-+	    commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
-+	}
-+#endif
-+    }
-+}
-+
-+void
-+icapConnectOver(int fd, int status, void *data)
-+{
-+    ErrorState *err;
-+    IcapStateData *icap = data;
-+    debug(81, 3) ("icapConnectOver: FD %d, status=%d\n", fd, status);
-+    icap->flags.connect_pending = 0;
-+    if (status < 0) {
-+	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
-+	err->xerrno = errno;
-+	err->request = requestLink(icap->request);
-+	errorAppendEntry(icap->respmod.entry, err);
-+	comm_close(fd);
-+	debug(81, 3) ("icapConnectOver: status < 0, unreachable=1\n");
-+	icapOptSetUnreachable(icap->current_service);
-+	return;
-+    }
-+    fd_table[fd].pconn.uses++;
-+    fd_table[fd].pconn.type = 2;
-+    commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0);
-+}
-+
-+
-+
-+IcapStateData *
-+icapRespModStart(icap_service_t type, request_t * request, StoreEntry * entry,
-+    http_state_flags http_flags)
-+{
-+    IcapStateData *icap = NULL;
-+    CNCB *theCallback = NULL;
-+    icap_service *service = NULL;
-+
-+    debug(81, 3) ("icapRespModStart: type=%d\n", (int) type);
-+    assert(type >= 0 && type < ICAP_SERVICE_MAX);
-+
-+    service = icapService(type, request);
-+    if (!service) {
-+	debug(81, 3) ("icapRespModStart: no service found\n");
-+	return NULL;		/* no service found */
-+    }
-+    if (service->unreachable) {
-+	if (service->bypass) {
-+	    debug(81,
-+		5)
-+		("icapRespModStart: BYPASS because service unreachable: %s\n",
-+		service->uri);
-+	    return NULL;
-+	} else {
-+	    debug(81,
-+		5)
-+		("icapRespModStart: ERROR  because service unreachable: %s\n",
-+		service->uri);
-+	    return (IcapStateData *) - 1;
-+	}
-+    }
-+    switch (type) {
-+	/* TODO: When we support more than ICAP_SERVICE_RESPMOD_PRECACHE, we needs to change
-+	 * this switch, because callbacks isn't keep */
-+    case ICAP_SERVICE_RESPMOD_PRECACHE:
-+	theCallback = icapConnectOver;
-+	break;
-+    default:
-+	fatalf("icapRespModStart: unsupported service type '%s'\n",
-+	    icap_service_type_str[type]);
-+	break;
-+    }
-+
-+    icap = icapAllocate();
-+    if (!icap) {
-+	debug(81, 3) ("icapRespModStart: icapAllocate() failed\n");
-+	return NULL;
-+    }
-+    icap->request = requestLink(request);
-+    icap->respmod.entry = entry;
-+    if (entry)
-+	storeLockObject(entry);
-+    icap->http_flags = http_flags;
-+    memBufDefInit(&icap->respmod.buffer);
-+    memBufDefInit(&icap->chunk_buf);
-+
-+    icap->current_service = service;
-+    icap->preview_size = service->preview;
-+
-+    /* 
-+     * Don't create socket to the icap server now, but only for the first
-+     * packet receive from the http server. This will resolve all timeout
-+     * between the web server and icap server.
-+     */
-+    debug(81, 3) ("icapRespModStart: setting connect_requested to 0\n");
-+    icap->flags.connect_requested = 0;
-+
-+    /*
-+     * make a copy the HTTP response that we send to the ICAP server in
-+     * case it turns out to be a 204
-+     */
-+#ifdef SUPPORT_ICAP_204
-+    icap->flags.copy_response = 1;
-+#elif ICAP_PREVIEW
-+    if (preview_size < 0 || !Config.icapcfg.preview_enable)
-+	icap->flags.copy_response = 0;
-+    else
-+	icap->flags.copy_response = 1;
-+#else
-+    icap->flags.copy_response = 0;
-+#endif
-+
-+    statCounter.icap.all.requests++;
-+    debug(81, 3) ("icapRespModStart: returning %p\n", icap);
-+    return icap;
-+}
-+
-+static int
-+icapHttpReplyHdrState(IcapStateData * icap)
-+{
-+    assert(icap);
-+    if (NULL == icap->httpState)
-+	return 0;
-+    return icap->httpState->reply_hdr_state;
-+}
-+
-+static void
-+icapProcessHttpReplyHeader(IcapStateData * icap, const char *buf, int size)
-+{
-+    if (NULL == icap->httpState) {
-+	icap->httpState = cbdataAlloc(HttpStateData);
-+	icap->httpState->request = requestLink(icap->request);
-+	icap->httpState->orig_request = requestLink(icap->request);
-+	icap->httpState->entry = icap->respmod.entry;
-+	storeLockObject(icap->httpState->entry);	/* lock it */
-+    }
-+    httpProcessReplyHeader(icap->httpState, buf, size);
-+    if (2 == icap->httpState->reply_hdr_state)
-+	EBIT_CLR(icap->httpState->entry->flags, ENTRY_FWD_HDR_WAIT);
-+}
-+
-+/*
-+ * icapRespModKeepAliveOrClose
-+ *
-+ * Called when we are done reading from the ICAP server.
-+ * Either close the connection or keep it open for a future
-+ * transaction.
-+ */
-+static void
-+icapRespModKeepAliveOrClose(IcapStateData * icap)
-+{
-+    int fd = icap->icap_fd;
-+    if (fd < 0)
-+	return;
-+    if (!icap->flags.keep_alive) {
-+	debug(81, 3) ("%s:%d keep_alive not set, closing\n", __FILE__,
-+	    __LINE__);
-+	comm_close(fd);
-+	return;
-+    }
-+    debug(81, 3) ("%s:%d FD %d looks good, keeping alive\n", __FILE__, __LINE__,
-+	fd);
-+    commSetDefer(fd, NULL, NULL);
-+    commSetTimeout(fd, -1, NULL, NULL);
-+    commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
-+    comm_remove_close_handler(fd, icapStateFree, icap);
-+    pconnPush(fd, icap->current_service->hostname, icap->current_service->port);
-+    icap->icap_fd = -1;
-+    icapStateFree(-1, icap);
-+}
-+
-+
-+
-+/*
-+ * copied from httpPconnTransferDone
-+ *
-+ */
-+static int
-+icapPconnTransferDone(int fd, IcapStateData * icap)
-+{
-+    debug(81, 3) ("icapPconnTransferDone: FD %d\n", fd);
-+    /*
-+     * Be careful with 204 responses.  Normally we are done when we
-+     * see the zero-end chunk, but that won't happen for 204s, so we
-+     * use an EOF indicator on the HTTP side instead.
-+     */
-+    if (icap->flags.no_content && icap->flags.http_server_eof) {
-+	debug(81, 5) ("icapPconnTransferDone: no content, ret 1\n");
-+	return 1;
-+    }
-+    if (icapHttpReplyHdrState(icap) != 2) {
-+	debug(81,
-+	    5) ("icapPconnTransferDone: didn't see end of HTTP hdrs, ret 0\n");
-+	return 0;
-+    }
-+    if (icap->enc.null_body > -1) {
-+	debug(81, 5) ("icapPconnTransferDone: no message body, ret 1\n");
-+	return 1;
-+    }
-+    if (icap->chunk_size == -2) {	//AI: was != -2 ; and change content with bottom
-+	/* zero end chunk reached */
-+	debug(81, 5) ("icapPconnTransferDone: got zero end chunk\n");
-+	return 1;
-+    }
-+    debug(81, 5) ("icapPconnTransferDone: didnt get zero end chunk yet\n");	//AI: change with second top condition
-+
-+    return 0;
-+}
-+
-+static int
-+icapExpectedHttpReplyHdrSize(IcapStateData * icap)
-+{
-+    if (icap->enc.res_body > -1 && icap->enc.res_hdr > -1)
-+	return (icap->enc.res_body - icap->enc.res_hdr);
-+    if (icap->enc.null_body > -1 && icap->enc.res_hdr > -1)
-+	return icap->enc.null_body - icap->enc.res_hdr;
-+    /*The case we did not get res_hdr ..... */
-+    if (icap->enc.res_body > -1)
-+	return icap->enc.res_body;
-+    if (icap->enc.null_body > -1)
-+	return icap->enc.null_body;
-+    return -1;
-+}
-+
-+/*
-+ * copied from httpReadReply()
-+ *
-+ * by the time this is called, the ICAP headers have already
-+ * been read.
-+ */
-+void
-+icapReadReply(int fd, void *data)
-+{
-+    IcapStateData *icap = data;
-+    StoreEntry *entry = icap->respmod.entry;
-+    const request_t *request = icap->request;
-+    int len;
-+    debug(81, 5) ("icapReadReply: FD %d: icap %p.\n", fd, data);
-+    if (icap->flags.no_content && !icap->flags.http_server_eof) {	//AI
-+
-+	return;
-+    }
-+    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
-+	comm_close(fd);
-+	return;
-+    }
-+    errno = 0;
-+    statCounter.syscalls.sock.reads++;
-+    len = memBufRead(fd, &icap->chunk_buf);
-+    debug(81, 5) ("icapReadReply: FD %d: len %d.\n", fd, len);
-+    if (len > 0) {
-+	fd_bytes(fd, len, FD_READ);
-+	kb_incr(&statCounter.icap.all.kbytes_in, len);
-+	commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
-+	if (icap->chunk_buf.size < icap->chunk_buf.capacity) {
-+	    *(icap->chunk_buf.buf + icap->chunk_buf.size) = '\0';
-+	    debug(81, 9) ("{%s}\n", icap->chunk_buf.buf);
-+	}
-+    }
-+    if (len <= 0) {
-+	debug(81, 2) ("icapReadReply: FD %d: read failure: %s.\n",
-+	    fd, xstrerror());
-+	if (ignoreErrno(errno)) {
-+	    debug(81, 2) ("icapReadReply: FD %d: ignored errno\n", fd);
-+	    commSetSelect(fd, COMM_SELECT_READ, icapReadReply, icap, 0);
-+	} else if (entry->mem_obj->inmem_hi == 0) {
-+	    ErrorState *err;
-+	    debug(81, 2) ("icapReadReply: FD %d: generating error page\n", fd);
-+	    err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
-+	    err->request = requestLink((request_t *) request);
-+	    err->xerrno = errno;
-+	    errorAppendEntry(entry, err);
-+	    comm_close(fd);
-+	} else {
-+	    debug(81, 2) ("icapReadReply: FD %d: just calling comm_close()\n",
-+		fd);
-+	    comm_close(fd);
-+	}
-+	return;
-+    }
-+    if (icapReadReply2(icap) < 0)
-+	comm_close(fd);
-+}
-+
-+static int
-+icapReadReply2(IcapStateData * icap)
-+{
-+    StoreEntry *entry = icap->respmod.entry;
-+    const request_t *request = icap->request;
-+    debug(81, 3) ("icapReadReply2\n");
-+    if (icap->chunk_buf.size == 0 && entry->mem_obj->inmem_hi == 0) {
-+	ErrorState *err;
-+	err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);
-+	err->xerrno = errno;
-+	err->request = requestLink((request_t *) request);
-+	errorAppendEntry(entry, err);
-+	icap->flags.http_server_eof = 1;
-+	return -1;
-+    }
-+    if (icap->chunk_buf.size == 0) {
-+	/* Retrieval done. */
-+	if (icapHttpReplyHdrState(icap) < 2)
-+	    icapProcessHttpReplyHeader(icap, icap->chunk_buf.buf,
-+		icap->chunk_buf.size);
-+	icap->flags.http_server_eof = 1;
-+	icapReadReply3(icap);
-+	return 0;
-+    }
-+    if (icapHttpReplyHdrState(icap) == 0) {
-+	int expect = icapExpectedHttpReplyHdrSize(icap);
-+	int so_far = icap->http_header_bytes_read_so_far;
-+	int needed = expect - so_far;
-+	debug(81, 3) ("expect=%d\n", expect);
-+	debug(81, 3) ("so_far=%d\n", so_far);
-+	debug(81, 3) ("needed=%d\n", needed);
-+	assert(needed < 0 || needed >= 0);
-+	if (0 > expect) {
-+	    icapProcessHttpReplyHeader(icap,
-+		icap->chunk_buf.buf, icap->chunk_buf.size);
-+	} else if (0 == expect) {
-+	    /*
-+	     * this icap reply doesn't give us new HTTP headers
-+	     * so we must copy them from our copy
-+	     */
-+	    debug(81, 1) ("WARNING: untested code at %s:%d\n", __FILE__,
-+		__LINE__);
-+	    if (icap->respmod.req_hdr_copy.size) {	/*For HTTP 0.9 we do not have headers */
-+		storeAppend(entry,
-+		    icap->respmod.req_hdr_copy.buf,
-+		    icap->respmod.req_hdr_copy.size);
-+	    }
-+	    icapProcessHttpReplyHeader(icap, icap->chunk_buf.buf,
-+		icap->chunk_buf.size);
-+	    assert(icapHttpReplyHdrState(icap) == 2);
-+	    icap->chunk_size = 0;	/*we are ready to read chunks of data now.... */
-+	} else if (needed) {
-+	    icapProcessHttpReplyHeader(icap,
-+		icap->chunk_buf.buf, icap->chunk_buf.size);
-+	    if (icap->chunk_buf.size >= needed) {
-+		storeAppend(entry, icap->chunk_buf.buf, needed);
-+		so_far += needed;
-+		xmemmove(icap->chunk_buf.buf,
-+		    icap->chunk_buf.buf + needed,
-+		    icap->chunk_buf.size - needed);
-+		icap->chunk_buf.size -= needed;
-+		assert(icapHttpReplyHdrState(icap) == 2);
-+		icap->chunk_size = 0;
-+	    } else {
-+		/*
-+		 * We don't have the full HTTP reply headers yet, so keep
-+		 * the partial reply buffered in 'chunk_buf' and wait
-+		 * for more.
-+		 */
-+		debug(81, 3) ("We don't have full Http headers.Schedule a new read\n");
-+		commSetSelect(icap->icap_fd, COMM_SELECT_READ, icapReadReply, icap, 0);
-+	    }
-+	}
-+	icap->http_header_bytes_read_so_far = so_far;
-+    }
-+    debug(81, 3) ("%s:%d: icap->chunk_buf.size=%d\n", __FILE__, __LINE__,
-+	(int) icap->chunk_buf.size);
-+    debug(81, 3) ("%s:%d: flags.no_content=%d\n", __FILE__, __LINE__,
-+	icap->flags.no_content);
-+    if (icap->flags.no_content) {
-+	/* data from http.c is not chunked */
-+	if (!EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
-+	    debug(81, 3) ("copying %d bytes from chunk_buf to entry\n",
-+		icap->chunk_buf.size);
-+	    storeAppend(entry, icap->chunk_buf.buf, icap->chunk_buf.size);
-+	    icap->chunk_buf.size = 0;
-+	}
-+    } else if (2 == icapHttpReplyHdrState(icap)) {
-+	if (icap->chunk_buf.size)
-+	    icapParseChunkedBody(icap, (STRCB *) storeAppend, entry);
-+    }
-+    icapReadReply3(icap);
-+    return 0;
-+}
-+
-+static void
-+icapReadReply3(IcapStateData * icap)
-+{
-+    StoreEntry *entry = icap->respmod.entry;
-+    int fd = icap->icap_fd;
-+    debug(81, 3) ("icapReadReply3\n");
-+    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
-+	debug(81, 3) ("icapReadReply3: Entry Aborded\n");
-+	comm_close(fd);
-+    } else if (icapPconnTransferDone(fd, icap)) {
-+	storeComplete(entry);
-+	icapRespModKeepAliveOrClose(icap);
-+    } else if (!icap->flags.no_content) {
-+	/* Wait for EOF condition */
-+	commSetSelect(fd, COMM_SELECT_READ, icapReadReply, icap, 0);
-+	debug(81,
-+	    3)
-+	    ("icapReadReply3: Going to read mode data throught icapReadReply\n");
-+    } else {
-+	debug(81, 3) ("icapReadReply3: Nothing\n");
-+    }
-+}
-Index: src/main.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/main.c,v
-retrieving revision 1.28.6.25
-retrieving revision 1.28.6.8.2.11
-diff -p -u -b -r1.28.6.25 -r1.28.6.8.2.11
---- src/main.c	28 Jun 2005 02:16:51 -0000	1.28.6.25
-+++ src/main.c	12 Sep 2005 18:34:41 -0000	1.28.6.8.2.11
-@@ -350,6 +350,9 @@ mainReconfigure(void)
- #else
-     idnsShutdown();
- #endif
-+#ifdef HS_FEAT_ICAP
-+    icapClose();
-+#endif
-     redirectShutdown();
-     authenticateShutdown();
-     externalAclShutdown();
-@@ -378,6 +381,9 @@ mainReconfigure(void)
-     idnsInit();
- #endif
-     redirectInit();
-+#ifdef HS_FEAT_ICAP
-+    icapInit();
-+#endif
-     authenticateInit(&Config.authConfig);
-     externalAclInit();
- #if USE_WCCP
-@@ -507,6 +513,9 @@ mainInitialize(void)
-     idnsInit();
- #endif
-     redirectInit();
-+#ifdef HS_FEAT_ICAP
-+    icapInit();
-+#endif
-     authenticateInit(&Config.authConfig);
-     externalAclInit();
-     useragentOpenLog();
-Index: src/mem.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/mem.c,v
-retrieving revision 1.13
-retrieving revision 1.13.28.2
-diff -p -u -b -r1.13 -r1.13.28.2
---- src/mem.c	7 Sep 2001 23:55:49 -0000	1.13
-+++ src/mem.c	27 Jun 2003 01:15:18 -0000	1.13.28.2
-@@ -243,6 +243,13 @@ memInit(void)
-     memDataInit(MEM_CLIENT_REQ_BUF, "clientRequestBuffer", CLIENT_REQ_BUF_SZ, 0);
-     memDataInit(MEM_SWAP_LOG_DATA, "storeSwapLogData", sizeof(storeSwapLogData), 0);
- 
-+#ifdef HS_FEAT_ICAP
-+    memDataInit(MEM_ICAP_OPT_DATA, "IcapOptData", sizeof(IcapOptData), 0);
-+    memDataInit(MEM_ICAP_SERVICE_LIST, "icap_service_list", sizeof(icap_service_list), 0);
-+    memDataInit(MEM_ICAP_CLASS, "icap_class", sizeof(icap_class), 0);
-+    memDataInit(MEM_ICAP_ACCESS, "icap_access", sizeof(icap_access), 0);
-+#endif
-+
-     /* init string pools */
-     for (i = 0; i < mem_str_pool_count; i++) {
- 	StrPools[i].pool = memPoolCreate(StrPoolsAttrs[i].name, StrPoolsAttrs[i].obj_size);
-Index: src/mk-string-arrays.pl
-===================================================================
-RCS file: /cvsroot/squid/squid/src/mk-string-arrays.pl,v
-retrieving revision 1.2
-retrieving revision 1.2.140.1
-diff -p -u -b -r1.2 -r1.2.140.1
---- src/mk-string-arrays.pl	23 Oct 2000 15:04:21 -0000	1.2
-+++ src/mk-string-arrays.pl	4 Apr 2003 16:55:44 -0000	1.2.140.1
-@@ -16,6 +16,7 @@ $pat{'err_type'} = "err_type_str";
- $pat{'icp_opcode'} = "icp_opcode_str";
- $pat{'swap_log_op'} = "swap_log_op_str";
- $pat{'lookup_t'} = "lookup_t_str";
-+$pat{'icap_service_t'} = "icap_service_type_str";
- 
- $state = 0;	# start state
- while (<>) {
-Index: src/pconn.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/pconn.c,v
-retrieving revision 1.6.38.2
-retrieving revision 1.6.60.2
-diff -p -u -b -r1.6.38.2 -r1.6.60.2
---- src/pconn.c	16 Dec 2003 03:13:59 -0000	1.6.38.2
-+++ src/pconn.c	23 Nov 2005 20:33:07 -0000	1.6.60.2
-@@ -46,6 +46,9 @@ struct _pconn {
- #define PCONN_HIST_SZ (1<<16)
- int client_pconn_hist[PCONN_HIST_SZ];
- int server_pconn_hist[PCONN_HIST_SZ];
-+#ifdef HS_FEAT_ICAP
-+int icap_server_pconn_hist[PCONN_HIST_SZ];
-+#endif
- 
- static PF pconnRead;
- static PF pconnTimeout;
-@@ -159,6 +162,20 @@ pconnHistDump(StoreEntry * e)
- 	    continue;
- 	storeAppendPrintf(e, "\t%4d  %9d\n", i, server_pconn_hist[i]);
-     }
-+#ifdef HS_FEAT_ICAP
-+    storeAppendPrintf(e,
-+	"\n"
-+	"ICAP-server persistent connection counts:\n"
-+	"\n"
-+	"\treq/\n"
-+	"\tconn      count\n"
-+	"\t----  ---------\n");
-+    for (i = 0; i < PCONN_HIST_SZ; i++) {
-+	if (icap_server_pconn_hist[i] == 0)
-+	    continue;
-+	storeAppendPrintf(e, "\t%4d  %9d\n", i, icap_server_pconn_hist[i]);
-+    }
-+#endif
- }
- 
- /* ========== PUBLIC FUNCTIONS ============================================ */
-@@ -173,6 +190,9 @@ pconnInit(void)
-     for (i = 0; i < PCONN_HIST_SZ; i++) {
- 	client_pconn_hist[i] = 0;
- 	server_pconn_hist[i] = 0;
-+#ifdef HS_FEAT_ICAP
-+	icap_server_pconn_hist[i] = 0;
-+#endif
-     }
-     pconn_data_pool = memPoolCreate("pconn_data", sizeof(struct _pconn));
-     pconn_fds_pool = memPoolCreate("pconn_fds", PCONN_FDS_SZ * sizeof(int));
-@@ -248,11 +268,15 @@ pconnHistCount(int what, int i)
- {
-     if (i >= PCONN_HIST_SZ)
- 	i = PCONN_HIST_SZ - 1;
--    /* what == 0 for client, 1 for server */
-+    /* what == 0 for client, 1 for server, 2 for ICAP server */
-     if (what == 0)
- 	client_pconn_hist[i]++;
-     else if (what == 1)
- 	server_pconn_hist[i]++;
-+#ifdef HS_FEAT_ICAP
-+    else if (what == 2)
-+	icap_server_pconn_hist[i]++;
-+#endif
-     else
- 	assert(0);
- }
-Index: src/protos.h
-===================================================================
-RCS file: /cvsroot/squid/squid/src/protos.h,v
-retrieving revision 1.41.6.34
-retrieving revision 1.41.6.13.2.39
-diff -p -u -b -r1.41.6.34 -r1.41.6.13.2.39
---- src/protos.h	26 Feb 2006 03:13:57 -0000	1.41.6.34
-+++ src/protos.h	16 May 2006 17:56:59 -0000	1.41.6.13.2.39
-@@ -292,6 +292,8 @@ extern void whoisStart(FwdState *);
- /* http.c */
- extern int httpCachable(method_t);
- extern void httpStart(FwdState *);
-+extern void httpParseReplyHeaders(const char *, http_reply *);
-+extern void httpProcessReplyHeader(HttpStateData *, const char *, int);
- extern int httpBuildRequestPrefix(request_t * request,
-     request_t * orig_request,
-     StoreEntry * entry,
-@@ -614,6 +616,7 @@ extern void memBufVPrintf(MemBuf * mb, c
- extern FREE *memBufFreeFunc(MemBuf * mb);
- /* puts report on MemBuf _module_ usage into mb */
- extern void memBufReport(MemBuf * mb);
-+extern int memBufRead(int fd, MemBuf * mb);
- 
- extern char *mime_get_header(const char *mime, const char *header);
- extern char *mime_get_header_field(const char *mime, const char *name, const char *prefix);
-@@ -1341,4 +1344,53 @@ extern void externalAclShutdown(void);
- extern int externalAclRequiresAuth(void *acl_data);
- extern char *strtokFile(void);
- 
-+#ifdef HS_FEAT_ICAP
-+/*
-+ * icap_common.c
-+ */
-+void icapInit(void);
-+void icapClose(void);
-+void icapParseEncapsulated(IcapStateData *, const char *, const char *);
-+icap_service *icapService(icap_service_t, request_t *);
-+int icapConnect(IcapStateData *, CNCB *);
-+IcapStateData *icapAllocate(void);
-+PF icapStateFree;
-+PF icapConnectTimeout;
-+PF icapReadTimeout;
-+icap_service_t icapServiceToType(const char *);
-+const char *icapServiceToStr(const icap_service_t);
-+int icapCheckAcl(clientHttpRequest *);
-+size_t icapLineLength(const char *, int);
-+int icapReadHeader(int, IcapStateData *, int *);
-+int icapFindHeader(const char *, const char *, const char **, const char **);
-+int icapParseKeepAlive(const IcapStateData *, const char *, const char *);
-+void icapSetKeepAlive(IcapStateData * icap, const char *hdrs);
-+size_t icapParseChunkedBody(IcapStateData *, STRCB *, void *);
-+void icapAddAuthUserHeader(MemBuf *, auth_user_request_t *);
-+int icapParseStatusLine(const char *, int, int *, int *, const char **);
-+
-+/*
-+ * icap_respmod.c
-+ */
-+IcapStateData *icapRespModStart(icap_service_t, request_t *, StoreEntry *, http_state_flags);
-+void icapSendRespMod(IcapStateData *, char *, int, int);
-+CNCB icapConnectOver;
-+
-+/*
-+ * icap_reqmod.c
-+ */
-+IcapStateData *icapReqModStart(icap_service*, const char *, request_t *, int, struct timeval, struct in_addr, void *);
-+
-+/* icap_opt.c */
-+void icapOptInit(void);
-+void icapOptShutdown(void);
-+void icapOptSetUnreachable(icap_service * s);
-+
-+/* X-Server-IP support */
-+void icapAddOriginIP(MemBuf *, const char *);
-+
-+/* for debugging purposes only */
-+void dump_icap_config(IcapConfig * cfg);
-+#endif
-+
- #endif /* SQUID_PROTOS_H */
-Index: src/squid.h
-===================================================================
-RCS file: /cvsroot/squid/squid/src/squid.h,v
-retrieving revision 1.13.6.9
-retrieving revision 1.13.6.6.2.12
-diff -p -u -b -r1.13.6.9 -r1.13.6.6.2.12
---- src/squid.h	11 Mar 2006 03:16:31 -0000	1.13.6.9
-+++ src/squid.h	16 May 2006 17:56:59 -0000	1.13.6.6.2.12
-@@ -38,6 +38,14 @@
- #include "config.h"
- 
- /*
-+ * experimental defines for ICAP
-+ */
-+#ifdef HS_FEAT_ICAP
-+#define ICAP_PREVIEW 1
-+#define SUPPORT_ICAP_204 0
-+#endif
-+
-+/*
-  * On some systems, FD_SETSIZE is set to something lower than the
-  * actual number of files which can be opened.  IRIX is one case,
-  * NetBSD is another.  So here we increase FD_SETSIZE to our
-Index: src/stat.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/stat.c,v
-retrieving revision 1.13.6.14
-retrieving revision 1.13.6.7.2.7
-diff -p -u -b -r1.13.6.14 -r1.13.6.7.2.7
---- src/stat.c	30 Mar 2005 02:17:46 -0000	1.13.6.14
-+++ src/stat.c	23 Nov 2005 20:33:07 -0000	1.13.6.7.2.7
-@@ -775,6 +775,17 @@ statAvgDump(StoreEntry * sentry, int min
-     storeAppendPrintf(sentry, "server.other.kbytes_out = %f/sec\n",
- 	XAVG(server.other.kbytes_out.kb));
- 
-+#ifdef HS_FEAT_ICAP
-+    storeAppendPrintf(sentry, "icap.all.requests = %f/sec\n",
-+	XAVG(icap.all.requests));
-+    storeAppendPrintf(sentry, "icap.all.errors = %f/sec\n",
-+	XAVG(icap.all.errors));
-+    storeAppendPrintf(sentry, "icap.all.kbytes_in = %f/sec\n",
-+	XAVG(icap.all.kbytes_in.kb));
-+    storeAppendPrintf(sentry, "icap.all.kbytes_out = %f/sec\n",
-+	XAVG(icap.all.kbytes_out.kb));
-+#endif
-+
-     storeAppendPrintf(sentry, "icp.pkts_sent = %f/sec\n",
- 	XAVG(icp.pkts_sent));
-     storeAppendPrintf(sentry, "icp.pkts_recv = %f/sec\n",
-@@ -1160,6 +1171,17 @@ statCountersDump(StoreEntry * sentry)
-     storeAppendPrintf(sentry, "server.other.kbytes_out = %d\n",
- 	(int) f->server.other.kbytes_out.kb);
- 
-+#if HS_FEAT_ICAP
-+    storeAppendPrintf(sentry, "icap.all.requests = %d\n",
-+	(int) f->icap.all.requests);
-+    storeAppendPrintf(sentry, "icap.all.errors = %d\n",
-+	(int) f->icap.all.errors);
-+    storeAppendPrintf(sentry, "icap.all.kbytes_in = %d\n",
-+	(int) f->icap.all.kbytes_in.kb);
-+    storeAppendPrintf(sentry, "icap.all.kbytes_out = %d\n",
-+	(int) f->icap.all.kbytes_out.kb);
-+#endif
-+
-     storeAppendPrintf(sentry, "icp.pkts_sent = %d\n",
- 	f->icp.pkts_sent);
-     storeAppendPrintf(sentry, "icp.pkts_recv = %d\n",
-@@ -1459,8 +1481,6 @@ statClientRequests(StoreEntry * s)
- 	    storeAppendPrintf(s, "\tme: %s:%d\n",
- 		inet_ntoa(conn->me.sin_addr),
- 		ntohs(conn->me.sin_port));
--	    storeAppendPrintf(s, "\tnrequests: %d\n",
--		conn->nrequests);
- 	    storeAppendPrintf(s, "\tdefer: n %d, until %ld\n",
- 		conn->defer.n, (long int) conn->defer.until);
- 	}
-Index: src/store.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/store.c,v
-retrieving revision 1.16.6.9
-retrieving revision 1.16.6.2.2.8
-diff -p -u -b -r1.16.6.9 -r1.16.6.2.2.8
---- src/store.c	2 Sep 2005 02:13:43 -0000	1.16.6.9
-+++ src/store.c	12 Sep 2005 18:34:41 -0000	1.16.6.2.2.8
-@@ -520,7 +520,16 @@ storeAppend(StoreEntry * e, const char *
-     MemObject *mem = e->mem_obj;
-     assert(mem != NULL);
-     assert(len >= 0);
--    assert(e->store_status == STORE_PENDING);
-+    debug(20, 3) ("storeAppend: '%s'\n", storeKeyText(e->hash.key));
-+    if (e->store_status != STORE_PENDING) {
-+	/*
-+	 * if we're not STORE_PENDING, then probably we got aborted
-+	 * and there should be NO clients on this entry
-+	 */
-+	assert(EBIT_TEST(e->flags, ENTRY_ABORTED));
-+	assert(e->mem_obj->nclients == 0);
-+	return;
-+    }
-     if (len) {
- 	debug(20, 5) ("storeAppend: appending %d bytes for '%s'\n",
- 	    len,
-Index: src/structs.h
-===================================================================
-RCS file: /cvsroot/squid/squid/src/structs.h,v
-retrieving revision 1.48.2.46
-retrieving revision 1.48.2.9.2.50
-diff -p -u -b -r1.48.2.46 -r1.48.2.9.2.50
---- src/structs.h	11 Mar 2006 03:16:31 -0000	1.48.2.46
-+++ src/structs.h	16 May 2006 17:56:59 -0000	1.48.2.9.2.50
-@@ -384,6 +384,23 @@ struct _RemovalPolicySettings {
-     wordlist *args;
- };
- 
-+#if HS_FEAT_ICAP
-+struct _IcapConfig {
-+    int onoff;
-+    int preview_enable;
-+    icap_service *service_head;
-+    icap_class *class_head;
-+    icap_access *access_head;
-+    int preview_size;
-+    int check_interval;
-+    int send_client_ip;
-+    int send_server_ip;
-+    int send_auth_user;
-+    char *auth_scheme;
-+};
-+
-+#endif /* HS_FEAT_ICAP */
-+
- struct _SquidConfig {
-     struct {
- 	squid_off_t maxSize;
-@@ -715,6 +732,9 @@ struct _SquidConfig {
-     char *store_dir_select_algorithm;
-     int sleep_after_fork;	/* microseconds */
-     external_acl *externalAclHelperList;
-+#ifdef HS_FEAT_ICAP
-+    IcapConfig icapcfg;
-+#endif
- };
- 
- struct _SquidConfig2 {
-@@ -788,7 +808,10 @@ struct _fde {
-     } flags;
-     squid_off_t bytes_read;
-     squid_off_t bytes_written;
--    int uses;			/* ie # req's over persistent conn */
-+    struct {
-+	int uses;
-+	int type;
-+    } pconn;
-     struct _fde_disk {
- 	DWCB *wrt_handle;
- 	void *wrt_handle_data;
-@@ -983,6 +1006,131 @@ struct _http_state_flags {
-     unsigned int request_sent:1;
- };
- 
-+#ifdef HS_FEAT_ICAP
-+struct _IcapStateData {
-+    request_t *request;
-+    http_state_flags http_flags;
-+    HttpStateData *httpState;	/* needed to parse HTTP headers only */
-+    int icap_fd;
-+    int sc;
-+    icap_service *current_service;
-+    MemBuf icap_hdr;
-+    struct {
-+	int res_hdr;
-+	int res_body;
-+	int req_hdr;
-+	int req_body;
-+	int opt_body;
-+	int null_body;
-+    } enc;
-+    int bytes_to_gobble;
-+    int chunk_size;
-+    MemBuf chunk_buf;
-+    int preview_size;
-+    squid_off_t fake_content_length;
-+    int http_header_bytes_read_so_far;
-+    struct {
-+	const char *uri;	/* URI for REQMODs */
-+	int client_fd;
-+	struct timeval start;	/* for logging */
-+	struct in_addr log_addr;	/* for logging */
-+	int hdr_state;
-+	MemBuf hdr_buf;
-+	void *client_cookie;
-+	struct {
-+	    MemBuf buf;
-+	    CBCB *callback;
-+	    void *callback_data;
-+	    char *callback_buf;
-+	    size_t callback_bufsize;
-+	    squid_off_t bytes_read;
-+	} http_entity;
-+    } reqmod;
-+    struct {
-+	StoreEntry *entry;
-+	MemBuf buffer;
-+	MemBuf req_hdr_copy;	/* XXX barf */
-+	MemBuf resp_copy;	/* XXX barf^max */
-+	squid_off_t res_body_sz;
-+    } respmod;
-+    struct {
-+	unsigned int connect_requested:1;
-+	unsigned int connect_pending:1;
-+	unsigned int write_pending:1;
-+	unsigned int keep_alive:1;
-+	unsigned int http_server_eof:1;
-+	unsigned int send_zero_chunk:1;
-+	unsigned int got_reply:1;
-+	unsigned int wait_for_reply:1;
-+	unsigned int wait_for_preview_reply:1;
-+	unsigned int preview_done:1;
-+	unsigned int copy_response:1;
-+	unsigned int no_content:1;
-+	unsigned int reqmod_http_entity_eof:1;
-+    } flags;
-+};
-+
-+struct _icap_service {
-+    icap_service *next;
-+    char *name;			/* name to be used when referencing ths service */
-+    char *uri;			/* uri of server/service to use */
-+    char *type_name;		/* {req|resp}mod_{pre|post}cache */
-+
-+    char *hostname;
-+    unsigned short int port;
-+    char *resource;
-+    icap_service_t type;	/* parsed type */
-+    icap_method_t method;
-+    ushort bypass;		/* flag: bypass allowed */
-+    ushort unreachable;		/* flag: set to 1 if options request fails */
-+    IcapOptData *opt;		/* temp data needed during opt request */
-+    struct {
-+	unsigned int allow_204:1;
-+	unsigned int need_x_client_ip:1;
-+	unsigned int need_x_server_ip:1;
-+	unsigned int need_x_authenticated_user:1;
-+    } flags;
-+    int preview;
-+    String istag;
-+    String transfer_preview;
-+    String transfer_ignore;
-+    String transfer_complete;
-+    int max_connections;
-+    int options_ttl;
-+    int keep_alive;
-+};
-+
-+struct _icap_service_list {
-+    icap_service_list *next;
-+    icap_service *services[16];
-+    int nservices;		/* Number of services already used */
-+    int last_service_used;	/* Last services used, use to do a round robin */
-+};
-+
-+struct _icap_class {
-+    icap_class *next;
-+    char *name;
-+    wordlist *services;
-+    icap_service_list *isl;
-+    ushort hidden;		/* for unnamed classes */
-+};
-+
-+struct _icap_access {
-+    icap_access *next;
-+    char *service_name;
-+    icap_class *class;
-+    acl_access *access;
-+};
-+
-+struct _IcapOptData {
-+    char *buf;
-+    off_t offset;
-+    size_t size;
-+    off_t headlen;
-+};
-+
-+#endif
-+
- struct _HttpStateData {
-     StoreEntry *entry;
-     request_t *request;
-@@ -994,10 +1142,14 @@ struct _HttpStateData {
-     int fd;
-     http_state_flags flags;
-     FwdState *fwd;
-+#ifdef HS_FEAT_ICAP
-+    struct _IcapStateData *icap_writer;
-+#endif
-     char *body_buf;
-     int body_buf_sz;
- };
- 
-+
- struct _icpUdpData {
-     struct sockaddr_in address;
-     void *msg;
-@@ -1099,6 +1251,7 @@ struct _clientHttpRequest {
- 	unsigned int internal:1;
- 	unsigned int done_copying:1;
- 	unsigned int purging:1;
-+	unsigned int did_icap_reqmod:1;
- 	unsigned int hit:1;
-     } flags;
-     struct {
-@@ -1107,6 +1260,9 @@ struct _clientHttpRequest {
-     } redirect;
-     dlink_node active;
-     squid_off_t maxBodySize;
-+#if HS_FEAT_ICAP
-+    IcapStateData *icap_reqmod;
-+#endif
- };
- 
- struct _ConnStateData {
-@@ -1134,7 +1290,6 @@ struct _ConnStateData {
-     struct sockaddr_in me;
-     struct in_addr log_addr;
-     char rfc931[USER_IDENT_SZ];
--    int nrequests;
-     struct {
- 	int n;
- 	time_t until;
-@@ -1685,6 +1840,9 @@ struct _request_t {
-     char *peer_login;		/* Configured peer login:password */
-     time_t lastmod;		/* Used on refreshes */
-     const char *vary_headers;	/* Used when varying entities are detected. Changes how the store key is calculated */
-+#if HS_FEAT_ICAP
-+    icap_class *class;
-+#endif
-     BODY_HANDLER *body_reader;
-     void *body_reader_data;
- };
-@@ -1790,7 +1948,11 @@ struct _StatCounters {
- 	    kb_t kbytes_in;
- 	    kb_t kbytes_out;
- 	} all , http, ftp, other;
--    } server;
-+    }
-+#if HS_FEAT_ICAP
-+	icap,
-+#endif
-+	server;
-     struct {
- 	int pkts_sent;
- 	int queries_sent;
-Index: src/typedefs.h
-===================================================================
-RCS file: /cvsroot/squid/squid/src/typedefs.h,v
-retrieving revision 1.25.6.8
-retrieving revision 1.25.6.1.6.13
-diff -p -u -b -r1.25.6.8 -r1.25.6.1.6.13
---- src/typedefs.h	27 Mar 2005 02:16:17 -0000	1.25.6.8
-+++ src/typedefs.h	28 Mar 2005 18:05:08 -0000	1.25.6.1.6.13
-@@ -131,6 +131,15 @@ typedef struct _HttpHeaderStat HttpHeade
- typedef struct _HttpBody HttpBody;
- typedef struct _HttpReply HttpReply;
- typedef struct _HttpStateData HttpStateData;
-+#ifdef HS_FEAT_ICAP
-+typedef struct _IcapStateData IcapStateData;
-+typedef struct _IcapConfig IcapConfig;
-+typedef struct _icap_service icap_service;
-+typedef struct _icap_service_list icap_service_list;
-+typedef struct _icap_class icap_class;
-+typedef struct _icap_access icap_access;
-+typedef struct _IcapOptData IcapOptData;
-+#endif
- typedef struct _icpUdpData icpUdpData;
- typedef struct _clientHttpRequest clientHttpRequest;
- typedef struct _ConnStateData ConnStateData;
-Index: src/url.c
-===================================================================
-RCS file: /cvsroot/squid/squid/src/url.c,v
-retrieving revision 1.7.6.7
-retrieving revision 1.7.6.5.2.3
-diff -p -u -b -r1.7.6.7 -r1.7.6.5.2.3
---- src/url.c	11 Mar 2006 03:16:31 -0000	1.7.6.7
-+++ src/url.c	16 May 2006 17:56:59 -0000	1.7.6.5.2.3
-@@ -103,6 +103,9 @@ const char *ProtocolStr[] =
-     "whois",
-     "internal",
-     "https",
-+#ifdef HS_FEAT_ICAP
-+    "icap",
-+#endif
-     "TOTAL"
- };
- 
-@@ -221,6 +224,10 @@ urlParseProtocol(const char *s)
- 	return PROTO_WHOIS;
-     if (strcasecmp(s, "internal") == 0)
- 	return PROTO_INTERNAL;
-+#ifdef HS_FEAT_ICAP
-+    if (strcasecmp(s, "icap") == 0)
-+	return PROTO_ICAP;
-+#endif
-     return PROTO_NONE;
- }
- 
-@@ -244,6 +251,10 @@ urlDefaultPort(protocol_t p)
- 	return CACHE_HTTP_PORT;
-     case PROTO_WHOIS:
- 	return 43;
-+#ifdef HS_FEAT_ICAP
-+    case PROTO_ICAP:
-+	return 1344;
-+#endif
-     default:
- 	return 0;
-     }
--- /dev/null
+++ www/squid/files/patch-configure
@@ -0,0 +1,19 @@
+Patch for Squid bug 2203:
+
+--with-maxfd inadvertently unsets LDFLAGS.
+--- configure.orig	2008-04-02 21:51:54.000000000 +0200
++++ configure	2008-04-02 21:55:28.000000000 +0200
+@@ -25795,11 +25795,12 @@
+ 
+ fi
+ 
++TLDFLAGS="$LDFLAGS"
++
+ if test -z "$SQUID_MAXFD"; then
+ 
+ { echo "$as_me:$LINENO: checking Maximum number of filedescriptors we can open" >&5
+ echo $ECHO_N "checking Maximum number of filedescriptors we can open... $ECHO_C" >&6; }
+-TLDFLAGS="$LDFLAGS"
+ case $host in
+ i386-unknown-freebsd*)
+     if echo "$LDFLAGS" | grep -q pthread; then
Index: pkg-message.in
===================================================================
RCS file: /home/cvs/mports/www/squid/files/pkg-message.in,v
retrieving revision 1.1
retrieving revision 1.2
diff -L www/squid/files/pkg-message.in -L www/squid/files/pkg-message.in -u -r1.1 -r1.2
--- www/squid/files/pkg-message.in
+++ www/squid/files/pkg-message.in
@@ -1,24 +1,31 @@
      o You can find the configuration files for this package in the
        directory %%PREFIX%%/etc/squid.
-     
+
      o A cache directory has been created in %%PREFIX%%/squid/cache.
        Log files will be written to %%PREFIX%%/squid/logs.
-     
+
        Note:
        You must initialize new cache directories before you can start
-       Squid.  Do this by running "squid -z" as 'root' or '%%SQUID_UID%%'.
+       squid.  Do this by running "squid -z" as 'root' or '%%SQUID_UID%%'.
        If your cache directories are already initialized (e.g. after an
-       upgrade of Squid) you do not need to initialize them again.
+       upgrade of squid) you do not need to initialize them again.
 
      o The default configuration will deny everyone access to the
        proxy service. Edit the "http_access" directives in
        %%PREFIX%%/etc/squid/squid.conf to suit your needs.
---begin rcng
 
      Please note that the Squid start script is an rc.d style script.
-     This means that Squid will not start automatically at boot time.
+     This means that Squid will not start automatically at boot
+     time unless it is explicitly enabled.
 
      To enable Squid, set squid_enable=yes in either
      /etc/rc.conf, /etc/rc.conf.local or /etc/rc.conf.d/squid
      Please see %%PREFIX%%/etc/rc.d/squid(.sh) for further details.
---end rcng
+
+     Note:
+     If you just updated your Squid installation from 2.5 or earlier,
+     make sure to check your Squid configuration against the 2.6 default
+     configuration file %%PREFIX%%/etc/squid/squid.conf.default.
+
+     Additionally, you should check your configuration by calling
+     'squid -f /path/to/squid.conf -k parse' before starting Squid.
--- /dev/null
+++ www/squid/files/patch-tools-Makefile.in
@@ -0,0 +1,11 @@
+--- tools/Makefile.in.orig	Sun May 14 18:30:04 2006
++++ tools/Makefile.in	Sun May 14 18:31:02 2006
+@@ -297,7 +297,7 @@
+ EXTRA_DIST = \
+ 	cachemgr.conf
+ 
+-DEFAULT_CACHEMGR_CONFIG = $(sysconfdir)/cachemgr.conf
++DEFAULT_CACHEMGR_CONFIG = $(sysconfdir)/cachemgr.conf.default
+ 
+ # Don't automatically uninstall config files
+ #	@if test -f $(DESTDIR)$(DEFAULT_CONFIG_FILE) ; then \


More information about the Midnightbsd-cvs mailing list