ports/99750: New port/repocopy request: www/squid26

Thomas-Martin Seck tmseck at netcologne.de
Mon Jul 3 18:01:01 UTC 2006


>Number:         99750
>Category:       ports
>Synopsis:       New port/repocopy request: www/squid26
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jul 03 18:00:32 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Thomas-Martin Seck
>Release:        FreeBSD 6.1-STABLE i386
>Organization:
a private site in Germany
>Environment:
FreeBSD ports collection as of July 3, 2006.

	
>Description:
The squid developers have just released 2.6.STABLE1 as the new
stable Squid release. I would like to keep www/squid at 2.5 for now
because of the large amount of changes between 2.5 and 2.6 and
introduce 2.6 as www/squid26. As I understand it, it is preferred
to repocopy www/squid to www/squid26 and then update it via a patch.
Since this patch is quite impressive (see below), I can also submit
a shar archive of the new port if needed to have it added from
scratch. If the preamble in the Makefile needs to be unchanged, feel free
to revert my changes there.

Functional changes:

New OPTIONS:
- WITH_/WITHOUT_SQUID_KQUEUE: use kqueue(2) support (defaults to yes)
- WITH_/WITHOUT_SQUID_WCCPV2: enable WCCPv2 support (defaults to no)
- WITH_/WITHOUT_SQUID_REFERER_LOG: enable referer-header logging (default no)
- make WITH_DEBUG a synonym for WITH_SQUID_STACKTRACES

Removed OPTIONS:
- WITH_SQUID_CUSTOM_LOG: the code is now part of mainline squid and can
  be configured via squid.conf
- WITH_/WITHOUT_SQUID_UNDERSCORES: no longer configurable
- WITH_/WITHOUT_SQUID_CHECK_HOSTNAME: no longer configurable
- WITH_/WITHOUT_SQUID_RCNG: the start script is now rc.d only

Changed default:

- CARP support is enabled by default in squid 2.6 and needs to be
  explicitly disabled defining WITHOUT_SQUID_CARP

Port infrastructural changes:
- no longer check for invalid user/group id; this problem should no longer
  be an issue (if it ever was one, but you never know) and remove the
  'changeuser:' target
- use files/squid.in instead of files/squid.sh.in as template
- remove ancient information about Harvest from pkg-descr, tighten COMMENT
- add some HTTP mirror sites taken from
  <http://www.squid-cache.org/Mirrors/http-mirrors.html> as additional
  PATCH_SITES (thanks to Robert Backhaus for the initial submission)
- ICAP support is not yet available, the squid-devel CVS is not synchronized
  with mainline squid as I write this so mark WITH_SQUID_ICAP as IGNORE for
  now. I'll add the necessary patches ASAP.
- spell "squid" as "Squid" when referring to the project as this seems to be
  the spelling the Squid project prefers
- some cosmetic changes in macro definitions

Removed files:

files/customlog-2.5.patch
files/follow_xff-2.5.patch
files/follow_xff--configure.patch
files/icap-2.5-bootstrap.patch
files/icap-2.5-core.patch
files/squid.sh.in

New files:

files/patch-tools-Makefile.in
files/squid.in


	
>How-To-Repeat:
	
>Fix:
Copy www/squid to www/squid26 and apply this patch to www/squid26:

Index: Makefile
===================================================================
--- Makefile	(.../www/squid)	(revision 934)
+++ Makefile	(.../local/squid26)	(revision 934)
@@ -1,23 +1,19 @@
-# New ports collection makefile for:	squid24
-# Date created:		Tue Mar 27 14:56:08 CEST 2001
-# Whom:			Adrian Chadd <adrian at FreeBSD.org>
+# New ports collection makefile for:	squid26
+# Date created:		2006-06-01
+# Whom:			Thomas-Martin Seck <tmseck at netcologne.de>
 #
-# $FreeBSD: ports/www/squid/Makefile,v 1.188 2006/06/05 22:00:46 jmelo Exp $
+# $FreeBSD$
 #
 # Tunables not (yet) configurable via 'make config':
 # SQUID_{U,G}ID
-#   Which user/group squid should run as (default: squid/squid).
+#   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)
@@ -39,7 +35,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.
@@ -47,11 +43,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
@@ -68,15 +63,23 @@
 #     of filedescriptors the resulting binary is expected to support.
 #    --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
-#
+#     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-auth-on-acceleration
+#     Enable authentication in accelerators.
+#    --enable-forward-log
+#     Enable experimental forward_log directive.
+#    --enable-multicast-miss
+#     Enable experimental multicast notification of cachemisses.
 
 PORTNAME=	squid
-PORTVERSION=	2.5.14
-PORTREVISION=	1
+PORTVERSION=	2.6.1
 CATEGORIES=	www
-MASTER_SITES=	\
-		ftp://ftp.squid-cache.org/pub/%SUBDIR%/ \
+MASTER_SITES=	ftp://ftp.squid-cache.org/pub/%SUBDIR%/ \
 		ftp://archive.progeny.com/squid/%SUBDIR%/ \
 		ftp://mirrors.24-7-solutions.net/pub/squid/%SUBDIR%/ \
 		ftp://sunsite.auc.dk/pub/infosystems/squid/%SUBDIR%/ \
@@ -86,20 +89,32 @@
 		ftp://ftp.ccs.neu.edu/pub/mirrors/squid.nlanr.net/pub/%SUBDIR%/ \
 		${MASTER_SITE_RINGSERVER:S,%SUBDIR%,net/www/squid/&,}
 MASTER_SITE_SUBDIR=	squid-2/STABLE
-DISTNAME=	squid-2.5.STABLE14
-DIST_SUBDIR=	squid2.5
+DISTNAME=	squid-2.6.STABLE1
+DIST_SUBDIR=	squid2.6
 
-PATCH_SITES=	http://www.squid-cache.org/Versions/v2/2.5/bugs/
-PATCHFILES=	squid-2.5.STABLE14-httpReplyDestroy.patch
+PATCH_SITES=	http://www.squid-cache.org/%SUBDIR%/ \
+		http://www2.us.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.jp.squid-cache.org/%SUBDIR%/ \
+		http://www1.tw.squid-cache.org/%SUBDIR%/
+PATCH_SITE_SUBDIR=	Versions/v2/2.6/bugs
+PATCHFILES=
 PATCH_DIST_STRIP=	-p1
 
 MAINTAINER=	tmseck at netcologne.de
-COMMENT=	The successful WWW proxy cache and accelerator
+COMMENT=	HTTP Caching Proxy
 
-CONFLICTS=	squid-2.[^5]*
+LATEST_LINK=	squid26
+
+CONFLICTS=	squid-2.[^6]*
 GNU_CONFIGURE=	yes
 USE_BZIP2=	yes
 USE_PERL5=	yes
+USE_RC_SUBR=	squid
 
 SQUID_UID?=	squid
 SQUID_GID?=	squid
@@ -114,20 +129,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 \
@@ -135,9 +149,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 \
@@ -165,37 +179,44 @@
 		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_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=	NCSA PAM MSNT SMB
+digest_auth=	password
+external_acl=	ip_user session unix_group wbinfo_group
+MAN8+=		ncsa_auth.8 pam_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
@@ -211,11 +232,11 @@
 .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"
 
-# Selection of storage schemes:
+# Storage schemes:
 
 storage_schemes=	ufs diskd null
 .if defined(WITH_SQUID_AUFS)
@@ -227,7 +248,7 @@
 .endif
 .if defined(WITH_SQUID_COSS)
 storage_schemes+=	coss
-CONFIGURE_ARGS+=	--with-aio
+CONFIGURE_ARGS+=	--enable-coss-aio-ops
 .endif
 CONFIGURE_ARGS+=	--enable-storeio="${storage_schemes}"
 
@@ -239,13 +260,14 @@
 .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}"
@@ -272,24 +294,21 @@
 .if defined(WITHOUT_SQUID_WCCP)
 CONFIGURE_ARGS+=	--disable-wccp
 .endif
-.if !defined(WITHOUT_SQUID_UNDERSCORES)
-CONFIGURE_ARGS+=	--enable-underscores
+.if defined(WITH_SQUID_WCCPV2)
+CONFIGURE_ARGS+=	--enable-wccpv2
 .endif
-.if defined(WITHOUT_SQUID_CHECK_HOSTNAME)
-CONFIGURE_ARGS+=	--disable-hostname-checks
-.endif
 .if defined(WITH_SQUID_STRICT_HTTP)
 CONFIGURE_ARGS+=	--disable-http-violations
 .endif
 .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
@@ -313,45 +332,39 @@
 .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
-CONFIGURE_ARGS+=	--enable-icap-support
-error_files+=		ERR_ICAP_FAILURE
+IGNORE=		patches for ICAP support are not yet updated
+EXTRA_PATCHES+=	
+#CONFIGURE_ARGS+=	--enable-icap-support
+#error_files+=		ERR_ICAP_FAILURE
 .endif
+.if !defined(WITHOUT_SQUID_KQUEUE)
+CONFIGURE_ARGS+=	--enable-kqueue
+.else
+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)
+.if defined(WITH_SQUID_STACKTRACES) || defined(WITH_DEBUG)
 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
-.endif
 
 # Languages:
 #
 # 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?=	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_DEFAULT_LANG?=	English
 CONFIGURE_ARGS+=	--enable-err-languages="${SQUID_LANGUAGES}" \
 			--enable-default-err-language=${SQUID_DEFAULT_LANG}
@@ -385,31 +398,16 @@
 # 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(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}
@@ -421,50 +419,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
===================================================================
--- distinfo	(.../www/squid)	(revision 934)
+++ distinfo	(.../local/squid26)	(revision 934)
@@ -1,6 +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.6/squid-2.6.STABLE1.tar.bz2) = d6bb23a67b0475cca11d4af8d574d054
+SHA256 (squid2.6/squid-2.6.STABLE1.tar.bz2) = a9efea26f1c3966dff69f80c271a73562afed5c65929d69dab713308dd402ba9
+SIZE (squid2.6/squid-2.6.STABLE1.tar.bz2) = 1212556
Index: pkg-descr
===================================================================
--- pkg-descr	(.../www/squid)	(revision 934)
+++ pkg-descr	(.../local/squid26)	(revision 934)
@@ -1,15 +1,10 @@
-This is the Squid Internet Object Cache developed by the National
-Laboratory for Applied Networking Research (NLANR) and Internet
-volunteers.  This software is freely available for anyone to use.
+Squid is a high-performance proxy caching server for web clients,
+supporting FTP, gopher, and HTTP data objects. Unlike traditional
+caching software, Squid handles all requests in a single, non-blocking,
+I/O-driven process.
 
-This software is based on the Harvest Object Cache developed by
-the University of Colorado and the University of Southern California.
-The Harvest home page is http://harvest.cs.colorado.edu/.
+Squid supports SSL, extensive access controls, and full request logging.
+By using the lightweight Internet Cache Protocol, Squid caches can be
+arranged in a hierarchy or mesh for additional bandwidth savings.
 
-ARPA funding for the Harvest project has ended, the squid project has
-continued development of the cache where Harvest finished.
-
-This port provides many configuration options, most of which are
-available via 'make config'.
-
 WWW: http://www.squid-cache.org/
Index: files/pkg-deinstall.in
===================================================================
--- files/pkg-deinstall.in	(.../www/squid)	(revision 934)
+++ files/pkg-deinstall.in	(.../local/squid26)	(revision 934)
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# $FreeBSD: ports/www/squid/files/pkg-deinstall.in,v 1.1 2006/03/18 17:11:13 pav Exp $
+# $FreeBSD$
 #
 
 PATH=/bin:/usr/bin:/usr/sbin
@@ -16,20 +16,19 @@
 	echo "===> post-deinstallation information for $1:"
 	echo ""
 	echo "     Note:"
-	echo "     squid related user accounts and groups were not removed."
+	echo "     Squid related user accounts and groups were not removed."
 	echo ""
 	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."
+	       	echo "     Squid any longer."
 	fi
 	echo ""
 	;;
Index: files/pkg-message.in
===================================================================
--- files/pkg-message.in	(.../www/squid)	(revision 934)
+++ files/pkg-message.in	(.../local/squid26)	(revision 934)
@@ -1,9 +1,9 @@
      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%%'.
@@ -13,12 +13,19 @@
      o The default configuration will deny everyone access to the
        proxy service. Edit the "http_access" directives in
        %%PREFIX%%/etc/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.
+     Please note that the Squid start script is an rc.d style script.
+     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
+     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.
Index: files/pkg-install.in
===================================================================
--- files/pkg-install.in	(.../www/squid)	(revision 934)
+++ files/pkg-install.in	(.../local/squid26)	(revision 934)
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# $FreeBSD: ports/www/squid/files/pkg-install.in,v 1.1 2006/03/18 17:11:13 pav Exp $
+# $FreeBSD$
 #
 
 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}..."
Index: files/squid.in
===================================================================
--- files/squid.in	(.../www/squid)	(revision 0)
+++ files/squid.in	(.../local/squid26)	(revision 934)
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# $FreeBSD$
+#
+# 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.
+#
+
+squid_stop() {
+	${command} -k shutdown
+	run_rc_command poll
+}
+
+. %%RC_SUBR%%
+
+name=squid
+rcvar=${name}_enable
+
+command=%%PREFIX%%/sbin/squid
+extra_commands=reload
+reload_cmd="${command} -k reconfigure"
+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_user=${squid_user:-%%SQUID_UID%%}
+default_config=%%PREFIX%%/etc/squid/squid.conf
+
+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: files/patch-tools-Makefile.in
===================================================================
--- files/patch-tools-Makefile.in	(.../www/squid)	(revision 0)
+++ files/patch-tools-Makefile.in	(.../local/squid26)	(revision 934)
@@ -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 \
Index: files/squid.sh.in
===================================================================
--- files/squid.sh.in	(.../www/squid)	(revision 934)
+++ files/squid.sh.in	(.../local/squid26)	(revision 934)
@@ -1,87 +0,0 @@
-#!/bin/sh
-#
-# $FreeBSD: ports/www/squid/files/squid.sh.in,v 1.1 2006/03/18 17:11:13 pav 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} -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() {
-	${command} -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
Index: files/follow_xff-configure.patch
===================================================================
--- files/follow_xff-configure.patch	(.../www/squid)	(revision 934)
+++ files/follow_xff-configure.patch	(.../local/squid26)	(revision 934)
@@ -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
- #
Index: files/icap-2.5-core.patch
===================================================================
--- files/icap-2.5-core.patch	(.../www/squid)	(revision 934)
+++ files/icap-2.5-core.patch	(.../local/squid26)	(revision 934)
@@ -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;
-     }
Index: files/follow_xff-2.5.patch
===================================================================
--- files/follow_xff-2.5.patch	(.../www/squid)	(revision 934)
+++ files/follow_xff-2.5.patch	(.../local/squid26)	(revision 934)
@@ -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 {
Index: files/icap-2.5-bootstrap.patch
===================================================================
--- files/icap-2.5-bootstrap.patch	(.../www/squid)	(revision 934)
+++ files/icap-2.5-bootstrap.patch	(.../local/squid26)	(revision 934)
@@ -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: files/customlog-2.5.patch
===================================================================
--- files/customlog-2.5.patch	(.../www/squid)	(revision 934)
+++ files/customlog-2.5.patch	(.../local/squid26)	(revision 934)
@@ -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;
	

>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-ports-bugs mailing list