FreeBSD Bugzilla – Attachment 67721 Details for
Bug 99750
New port/repocopy request: www/squid26
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
file.diff
file.diff (text/plain), 329.24 KB, created by
Thomas-Martin Seck
on 2006-07-03 19:00:32 UTC
(
hide
)
Description:
file.diff
Filename:
MIME Type:
Creator:
Thomas-Martin Seck
Created:
2006-07-03 19:00:32 UTC
Size:
329.24 KB
patch
obsolete
>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@FreeBSD.org> >+# New ports collection makefile for: squid26 >+# Date created: 2006-06-01 >+# Whom: Thomas-Martin Seck <tmseck@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@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@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@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@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@SNPRINTFSOURCE = snprintf.c >- @NEED_OWN_SNPRINTF_FALSE@SNPRINTFSOURCE = >-+ >-+@NEED_OWN_STRNSTR_TRUE@STRNSTRSOURCE = strnstr.c >-+@NEED_OWN_STRNSTR_FALSE@STRNSTRSOURCE = >-+ >-+@NEED_OWN_STRCASESTR_TRUE@STRCASESTRSOURCE = strcasestr.c >-+@NEED_OWN_STRCASESTR_FALSE@STRCASESTRSOURCE = >-+ >- @NEED_OWN_MD5_TRUE@MD5SOURCE = md5.c >- @NEED_OWN_MD5_FALSE@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@am__objects_1 = >- @NEED_OWN_SNPRINTF_FALSE@am__objects_2 = >- @NEED_OWN_SNPRINTF_TRUE@am__objects_2 = snprintf.$(OBJEXT) >-+@NEED_OWN_STRNSTR_FALSE@am__objects_3 = >-+@NEED_OWN_STRNSTR_TRUE@am__objects_3 = strnstr.$(OBJEXT) >-+@NEED_OWN_STRCASESTR_TRUE@am__objects_4 = strcasestr.$(OBJEXT) >-+@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 \ >--@AMDEP_TRUE@ $(DEPDIR)/inet_ntoa.Po $(DEPDIR)/initgroups.Po \ >--@AMDEP_TRUE@ $(DEPDIR)/iso3307.Po $(DEPDIR)/md5.Po \ >--@AMDEP_TRUE@ $(DEPDIR)/ntlmauth.Po $(DEPDIR)/radix.Po \ >--@AMDEP_TRUE@ $(DEPDIR)/rfc1035.Po $(DEPDIR)/rfc1123.Po \ >--@AMDEP_TRUE@ $(DEPDIR)/rfc1738.Po $(DEPDIR)/rfc2617.Po \ >--@AMDEP_TRUE@ $(DEPDIR)/safe_inet_addr.Po $(DEPDIR)/snprintf.Po \ >--@AMDEP_TRUE@ $(DEPDIR)/splay.Po $(DEPDIR)/strerror.Po \ >--@AMDEP_TRUE@ $(DEPDIR)/stub_memaccount.Po $(DEPDIR)/tempnam.Po \ >--@AMDEP_TRUE@ $(DEPDIR)/util.Po $(DEPDIR)/uudecode.Po >-+@AMDEP_TRUE@ $(DEPDIR)/inet_ntoa.Po $(DEPDIR)/iso3307.Po \ >-+@AMDEP_TRUE@ $(DEPDIR)/md5.Po $(DEPDIR)/ntlmauth.Po \ >-+@AMDEP_TRUE@ $(DEPDIR)/radix.Po $(DEPDIR)/rfc1035.Po \ >-+@AMDEP_TRUE@ $(DEPDIR)/rfc1123.Po $(DEPDIR)/rfc1738.Po \ >-+@AMDEP_TRUE@ $(DEPDIR)/rfc2617.Po $(DEPDIR)/safe_inet_addr.Po \ >-+@AMDEP_TRUE@ $(DEPDIR)/snprintf.Po $(DEPDIR)/splay.Po \ >-+@AMDEP_TRUE@ $(DEPDIR)/strcasestr.Po $(DEPDIR)/strerror.Po \ >-+@AMDEP_TRUE@ $(DEPDIR)/strnstr.Po $(DEPDIR)/stub_memaccount.Po \ >-+@AMDEP_TRUE@ $(DEPDIR)/tempnam.Po $(DEPDIR)/util.Po \ >-+@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@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/html_quote.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/inet_ntoa.Po@am__quote@ >--@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/initgroups.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/iso3307.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/md5.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ntlmauth.Po@am__quote@ >-@@ -307,7 +321,9 @@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/safe_inet_addr.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/snprintf.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/splay.Po@am__quote@ >-+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strcasestr.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strerror.Po@am__quote@ >-+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strnstr.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/stub_memaccount.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/tempnam.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/util.Po@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@ >- >-+@USE_ICAP_TRUE@ICAPSOURCE = icap_common.c icap_reqmod.c icap_respmod.c icap_opt.c >-+@USE_ICAP_FALSE@ICAPSOURCE = >-+ >- @USE_DNSSERVER_TRUE@DNSSOURCE = dns.c >- @USE_DNSSERVER_FALSE@DNSSOURCE = dns_internal.c >- @USE_DNSSERVER_TRUE@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 = >--@USE_DELAY_POOLS_TRUE@am__objects_3 = delay_pools.$(OBJEXT) >--@USE_DELAY_POOLS_FALSE@am__objects_3 = >--@USE_DNSSERVER_FALSE@am__objects_4 = dns_internal.$(OBJEXT) >--@USE_DNSSERVER_TRUE@am__objects_4 = dns.$(OBJEXT) >--@ENABLE_HTCP_TRUE@am__objects_5 = htcp.$(OBJEXT) >--@MAKE_LEAKFINDER_FALSE@am__objects_6 = >--@MAKE_LEAKFINDER_TRUE@am__objects_6 = leakfinder.$(OBJEXT) >--@USE_SNMP_TRUE@am__objects_7 = snmp_core.$(OBJEXT) snmp_agent.$(OBJEXT) >--@USE_SNMP_FALSE@am__objects_7 = >--@ENABLE_SSL_TRUE@am__objects_8 = ssl_support.$(OBJEXT) >--@ENABLE_SSL_FALSE@am__objects_8 = >--@ENABLE_UNLINKD_FALSE@am__objects_9 = >--@ENABLE_UNLINKD_TRUE@am__objects_9 = unlinkd.$(OBJEXT) >--@ENABLE_WIN32SPECIFIC_TRUE@am__objects_10 = win32.$(OBJEXT) >--@ENABLE_WIN32SPECIFIC_FALSE@am__objects_10 = >-+@USE_DELAY_POOLS_FALSE@am__objects_5 = >-+@USE_DELAY_POOLS_TRUE@am__objects_5 = delay_pools.$(OBJEXT) >-+@USE_DNSSERVER_FALSE@am__objects_6 = dns_internal.$(OBJEXT) >-+@USE_DNSSERVER_TRUE@am__objects_6 = dns.$(OBJEXT) >-+@ENABLE_HTCP_TRUE@am__objects_7 = htcp.$(OBJEXT) >-+@USE_ICAP_TRUE@am__objects_8 = icap_common.$(OBJEXT) \ >-+@USE_ICAP_TRUE@ icap_reqmod.$(OBJEXT) icap_respmod.$(OBJEXT) \ >-+@USE_ICAP_TRUE@ icap_opt.$(OBJEXT) >-+@USE_ICAP_FALSE@am__objects_8 = >-+@MAKE_LEAKFINDER_TRUE@am__objects_9 = leakfinder.$(OBJEXT) >-+@MAKE_LEAKFINDER_FALSE@am__objects_9 = >-+@USE_SNMP_TRUE@am__objects_10 = snmp_core.$(OBJEXT) snmp_agent.$(OBJEXT) >-+@USE_SNMP_FALSE@am__objects_10 = >-+@ENABLE_SSL_FALSE@am__objects_11 = >-+@ENABLE_SSL_TRUE@am__objects_11 = ssl_support.$(OBJEXT) >-+@ENABLE_UNLINKD_TRUE@am__objects_12 = unlinkd.$(OBJEXT) >-+@ENABLE_UNLINKD_FALSE@am__objects_12 = >-+@ENABLE_WIN32SPECIFIC_FALSE@am__objects_13 = >-+@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 \ >--@AMDEP_TRUE@ $(DEPDIR)/http.Po $(DEPDIR)/icmp.Po \ >-+@AMDEP_TRUE@ $(DEPDIR)/http.Po $(DEPDIR)/icap_common.Po \ >-+@AMDEP_TRUE@ $(DEPDIR)/icap_opt.Po $(DEPDIR)/icap_reqmod.Po \ >-+@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@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/htcp.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/http.Po@am__quote@ >-+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icap_common.Po@am__quote@ >-+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icap_opt.Po@am__quote@ >-+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icap_reqmod.Po@am__quote@ >-+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icap_respmod.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icmp.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icp_v2.Po@am__quote@ >- @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/icp_v3.Po@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, "e); >-+ while (cur < eos) { >-+ new_lt = xmalloc(sizeof(logformat_token)); >-+ last_lt->next = new_lt; >-+ last_lt = new_lt; >-+ cur += accessLogGetNewLogFormatToken(new_lt, cur, "e); >-+ } >-+ 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;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 99750
: 67721