Index: cache_cf.c
===================================================================
RCS file: /cvsroot/squid/squid/src/cache_cf.c,v
retrieving revision 1.506
diff -u -r1.506 cache_cf.c
--- cache_cf.c	14 Aug 2008 19:59:14 -0000	1.506
+++ cache_cf.c	27 Aug 2008 06:33:21 -0000
@@ -1853,6 +1853,22 @@
 	} else if (!strcasecmp(token, "htcp-oldsquid")) {
 	    p->options.htcp = 1;
 	    p->options.htcp_oldsquid = 1;
+	} else if (!strcasecmp(token, "htcp-no-clr")) {
+	    if (p->options.htcp_only_clr)
+		fatalf("parse_peer: can't set htcp-no-clr and htcp-only-clr simultaneously");
+	    p->options.htcp = 1;
+	    p->options.htcp_no_clr = 1;
+	} else if (!strcasecmp(token, "htcp-no-purge-clr")) {
+	    p->options.htcp = 1;
+	    p->options.htcp_no_purge_clr = 1;
+	} else if (!strcasecmp(token, "htcp-only-clr")) {
+	    if (p->options.htcp_no_clr)
+		fatalf("parse_peer: can't set htcp-no-clr and htcp-only-clr simultaneously");
+	    p->options.htcp = 1;
+	    p->options.htcp_only_clr = 1;
+	} else if (!strcasecmp(token, "htcp-forward-clr")) {
+	    p->options.htcp = 1;
+	    p->options.htcp_forward_clr = 1;
 #endif
 	} else if (!strcasecmp(token, "no-netdb-exchange")) {
 	    p->options.no_netdb_exchange = 1;
Index: cf.data.pre
===================================================================
RCS file: /cvsroot/squid/squid/src/cf.data.pre,v
retrieving revision 1.493
diff -u -r1.493 cf.data.pre
--- cf.data.pre	27 Aug 2008 00:33:24 -0000	1.493
+++ cf.data.pre	27 Aug 2008 06:33:21 -0000
@@ -1513,6 +1513,10 @@
 		     max-conn=n
 		     htcp
 		     htcp-oldsquid
+		     htcp-no-clr
+		     htcp-no-purge-clr
+		     htcp-only-clr
+		     htcp-forward-clr
 		     originserver
 		     userhash
 		     sourcehash
@@ -1655,7 +1659,21 @@
 		     use 'htcp-oldsquid' to send HTCP to old Squid versions
 		     You must also allow this Squid htcp_access and
 		     http_access in the peer Squid configuration.
-
+		
+		     use 'htcp-no-clr' to send HTCP to the neighbor but without
+		     sending any CLR requests.  This cannot be used with
+		     htcp-only-clr.
+		
+		     use 'htcp-no-purge-clr' to send HTCP to the neighbor
+		     including CLRs but only when they do not result from
+		     PURGE requests.
+		
+		     use 'htcp-only-clr' to send HTCP to the neighbor but ONLY
+		     CLR requests.  This cannot be used with htcp-no-clr.
+		
+		     use 'htcp-forward-clr' to forward any HTCP CLR requests
+		     this proxy receives to the peer.
+		
 		     'originserver' causes this parent peer to be contacted as
 		     a origin server. Meant to be used in accelerator setups.
 
Index: client_side.c
===================================================================
RCS file: /cvsroot/squid/squid/src/client_side.c,v
retrieving revision 1.787
diff -u -r1.787 client_side.c
--- client_side.c	17 Aug 2008 22:02:00 -0000	1.787
+++ client_side.c	27 Aug 2008 06:33:22 -0000
@@ -1027,6 +1027,9 @@
     if (entry) {
 	debug(33, 4) ("clientPurgeRequest: GET '%s'\n",
 	    storeUrl(entry));
+#if USE_HTCP
+        neighborsHtcpClear(entry, NULL, http->request, method_get, HTCP_CLR_PURGE);
+#endif
 	storeRelease(entry);
 	status = HTTP_OK;
     }
@@ -1034,6 +1037,9 @@
     if (entry) {
 	debug(33, 4) ("clientPurgeRequest: HEAD '%s'\n",
 	    storeUrl(entry));
+#if USE_HTCP
+        neighborsHtcpClear(entry, NULL, http->request, method_head, HTCP_CLR_PURGE);
+#endif
 	storeRelease(entry);
 	status = HTTP_OK;
     }
@@ -1043,6 +1049,9 @@
 	if (entry) {
 	    debug(33, 4) ("clientPurgeRequest: Vary GET '%s'\n",
 		storeUrl(entry));
+#if USE_HTCP
+            neighborsHtcpClear(entry, NULL, http->request, method_get, HTCP_CLR_PURGE);
+#endif
 	    storeRelease(entry);
 	    status = HTTP_OK;
 	}
@@ -1050,6 +1059,9 @@
 	if (entry) {
 	    debug(33, 4) ("clientPurgeRequest: Vary HEAD '%s'\n",
 		storeUrl(entry));
+#if USE_HTCP
+            neighborsHtcpClear(entry, NULL, http->request, method_head, HTCP_CLR_PURGE);
+#endif
 	    storeRelease(entry);
 	    status = HTTP_OK;
 	}
Index: enums.h
===================================================================
RCS file: /cvsroot/squid/squid/src/enums.h,v
retrieving revision 1.253
diff -u -r1.253 enums.h
--- enums.h	17 Aug 2008 22:02:00 -0000	1.253
+++ enums.h	27 Aug 2008 06:33:22 -0000
@@ -807,4 +807,13 @@
     FORWARDED_FOR_TRUNCATE
 } forwarded_for_mode;
 
+#if USE_HTCP
+
+enum htcp_clr_reason {
+    HTCP_CLR_PURGE,
+    HTCP_CLR_INVALIDATION,
+};
+
+#endif
+
 #endif /* SQUID_ENUMS_H */
Index: htcp.c
===================================================================
RCS file: /cvsroot/squid/squid/src/htcp.c,v
retrieving revision 1.58
diff -u -r1.58 htcp.c
--- htcp.c	15 Aug 2008 04:56:00 -0000	1.58
+++ htcp.c	27 Aug 2008 06:33:22 -0000
@@ -129,6 +129,7 @@
     int rr;
     int f1;
     int response;
+    int reason;
     u_num32 msg_id;
     htcpSpecifier S;
     htcpDetail D;
@@ -196,7 +197,6 @@
 static void htcpFreeSpecifier(htcpSpecifier * s);
 static void htcpFreeDetail(htcpDetail * s);
 static void htcpHandle(char *buf, int sz, struct sockaddr_in *from);
-static void htcpHandleData(char *buf, int sz, struct sockaddr_in *from);
 static void htcpHandleMon(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
 static void htcpHandleNop(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
 static void htcpHandleSet(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
@@ -207,6 +207,7 @@
 static void htcpHandleTstRequest(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from);
 static void htcpHandleTstResponse(htcpDataHeader *, char *, int, struct sockaddr_in *);
 static StoreEntry *htcpCheckHit(const htcpSpecifier *);
+static void htcpForwardClr(char *buf, int sz);
 
 static int old_squid_format = 0;
 
@@ -339,6 +340,25 @@
 }
 
 static ssize_t
+htcpBuildClrOpData(char *buf, size_t buflen, htcpStuff * stuff)
+{
+    u_short reason;
+    
+    switch (stuff->rr) {
+    case RR_REQUEST:
+	debug(31, 3) ("htcpBuildClrOpData: RR_REQUEST\n");
+	reason = htons((u_short)stuff->reason);
+	xmemcpy(buf, &reason, 2);
+	return htcpBuildSpecifier(buf + 2, buflen - 2, stuff) + 2;
+    case RR_RESPONSE:
+        break;
+    default:
+	fatal_dump("htcpBuildClrOpData: bad RR value");
+    }
+    return 0;
+}
+
+static ssize_t
 htcpBuildOpData(char *buf, size_t buflen, htcpStuff * stuff)
 {
     ssize_t off = 0;
@@ -349,7 +369,7 @@
 	off = htcpBuildTstOpData(buf + off, buflen, stuff);
 	break;
     case HTCP_CLR:
-	/* nothing to be done */
+        off = htcpBuildClrOpData(buf + off, buflen, stuff);
 	break;
     default:
 	assert(0);
@@ -982,18 +1002,70 @@
 }
 
 static void
-htcpHandleData(char *buf, int sz, struct sockaddr_in *from)
+htcpForwardClr(char *buf, int sz)
+{
+	peer *p;
+	int i;
+	
+	for (i = 0, p = Config.peers; i < Config.npeers; i++, p = p->next) {
+		if (!p->options.htcp) {
+			continue;
+		}
+		if (!p->options.htcp_forward_clr) {
+			continue;
+		}
+		
+		htcpSend(buf, sz, &p->in_addr);
+	}
+}
+
+static void
+htcpHandle(char *buf, int sz, struct sockaddr_in *from)
 {
+    htcpHeader htcpHdr;
     htcpDataHeader hdr;
-    if (sz < sizeof(htcpDataHeader)) {
-	debug(31, 1) ("htcpHandleData: msg size less than htcpDataHeader size\n");
+    char *hbuf;
+    int hsz;
+
+    if (sz < sizeof(htcpHeader)) {
+	debug(31, 1) ("htcpHandle: msg size less than htcpHeader size\n");
+	return;
+    }
+    htcpHexdump("htcpHandle", buf, sz);
+    xmemcpy(&htcpHdr, buf, sizeof(htcpHeader));
+    htcpHdr.length = ntohs(htcpHdr.length);
+    if (htcpHdr.minor == 0)
+	old_squid_format = 1;
+    else
+	old_squid_format = 0;
+    debug(31, 3) ("htcpHandle: htcpHdr.length = %d\n", (int) htcpHdr.length);
+    debug(31, 3) ("htcpHandle: htcpHdr.major = %d\n", (int) htcpHdr.major);
+    debug(31, 3) ("htcpHandle: htcpHdr.minor = %d\n", (int) htcpHdr.minor);
+    if (sz != htcpHdr.length) {
+	debug(31, 1) ("htcpHandle: sz/%d != htcpHdr.length/%d from %s:%d\n",
+	    sz, htcpHdr.length,
+	    inet_ntoa(from->sin_addr), (int) ntohs(from->sin_port));
+	return;
+    }
+    if (htcpHdr.major != 0) {
+	debug(31, 1) ("htcpHandle: Unknown major version %d from %s:%d\n",
+	    htcpHdr.major,
+	    inet_ntoa(from->sin_addr), (int) ntohs(from->sin_port));
+	return;
+    }
+
+    hbuf = buf + sizeof(htcpHeader);
+    hsz = sz - sizeof(htcpHeader);
+
+    if (hsz < sizeof(htcpDataHeader)) {
+	debug(31, 1) ("htcpHandle: msg size less than htcpDataHeader size\n");
 	return;
     }
     if (!old_squid_format) {
-	xmemcpy(&hdr, buf, sizeof(hdr));
+	xmemcpy(&hdr, hbuf, sizeof(hdr));
     } else {
 	htcpDataHeaderSquid hdrSquid;
-	xmemcpy(&hdrSquid, buf, sizeof(hdrSquid));
+	xmemcpy(&hdrSquid, hbuf, sizeof(hdrSquid));
 	hdr.length = hdrSquid.length;
 	hdr.opcode = hdrSquid.opcode;
 	hdr.response = hdrSquid.response;
@@ -1004,48 +1076,49 @@
     }
     hdr.length = ntohs(hdr.length);
     hdr.msg_id = ntohl(hdr.msg_id);
-    debug(31, 3) ("htcpHandleData: sz = %d\n", sz);
-    debug(31, 3) ("htcpHandleData: length = %d\n", (int) hdr.length);
+    debug(31, 3) ("htcpHandle: hsz = %d\n", hsz);
+    debug(31, 3) ("htcpHandle: length = %d\n", (int) hdr.length);
     if (hdr.opcode >= HTCP_END) {
-	debug(31, 1) ("htcpHandleData: client %s, opcode %d out of range\n",
+	debug(31, 1) ("htcpHandle: client %s, opcode %d out of range\n",
 	    inet_ntoa(from->sin_addr),
 	    (int) hdr.opcode);
 	return;
     }
-    debug(31, 3) ("htcpHandleData: opcode = %d %s\n",
+    debug(31, 3) ("htcpHandle: opcode = %d %s\n",
 	(int) hdr.opcode, htcpOpcodeStr[hdr.opcode]);
-    debug(31, 3) ("htcpHandleData: response = %d\n", (int) hdr.response);
-    debug(31, 3) ("htcpHandleData: F1 = %d\n", (int) hdr.F1);
-    debug(31, 3) ("htcpHandleData: RR = %d\n", (int) hdr.RR);
-    debug(31, 3) ("htcpHandleData: msg_id = %d\n", (int) hdr.msg_id);
-    if (sz < hdr.length) {
-	debug(31, 1) ("htcpHandleData: sz < hdr.length\n");
+    debug(31, 3) ("htcpHandle: response = %d\n", (int) hdr.response);
+    debug(31, 3) ("htcpHandle: F1 = %d\n", (int) hdr.F1);
+    debug(31, 3) ("htcpHandle: RR = %d\n", (int) hdr.RR);
+    debug(31, 3) ("htcpHandle: msg_id = %d\n", (int) hdr.msg_id);
+    if (hsz < hdr.length) {
+	debug(31, 1) ("htcpHandle: hsz < hdr.length\n");
 	return;
     }
     /*
      * set sz = hdr.length so we ignore any AUTH fields following
      * the DATA.
      */
-    sz = (int) hdr.length;
-    buf += sizeof(htcpDataHeader);
-    sz -= sizeof(htcpDataHeader);
-    debug(31, 3) ("htcpHandleData: sz = %d\n", sz);
-    htcpHexdump("htcpHandleData", buf, sz);
+    hsz = (int) hdr.length;
+    hbuf += sizeof(htcpDataHeader);
+    hsz -= sizeof(htcpDataHeader);
+    debug(31, 3) ("htcpHandle: hsz = %d\n", hsz);
+    htcpHexdump("htcpHandle", hbuf, hsz);
     switch (hdr.opcode) {
     case HTCP_NOP:
-	htcpHandleNop(&hdr, buf, sz, from);
+	htcpHandleNop(&hdr, hbuf, hsz, from);
 	break;
     case HTCP_TST:
-	htcpHandleTst(&hdr, buf, sz, from);
+	htcpHandleTst(&hdr, hbuf, hsz, from);
 	break;
     case HTCP_MON:
-	htcpHandleMon(&hdr, buf, sz, from);
+	htcpHandleMon(&hdr, hbuf, hsz, from);
 	break;
     case HTCP_SET:
-	htcpHandleSet(&hdr, buf, sz, from);
+	htcpHandleSet(&hdr, hbuf, hsz, from);
 	break;
     case HTCP_CLR:
-	htcpHandleClr(&hdr, buf, sz, from);
+	htcpHandleClr(&hdr, hbuf, hsz, from);
+	htcpForwardClr(buf, sz);
 	break;
     default:
 	return;
@@ -1053,41 +1126,6 @@
 }
 
 static void
-htcpHandle(char *buf, int sz, struct sockaddr_in *from)
-{
-    htcpHeader htcpHdr;
-    if (sz < sizeof(htcpHeader)) {
-	debug(31, 1) ("htcpHandle: msg size less than htcpHeader size\n");
-	return;
-    }
-    htcpHexdump("htcpHandle", buf, sz);
-    xmemcpy(&htcpHdr, buf, sizeof(htcpHeader));
-    htcpHdr.length = ntohs(htcpHdr.length);
-    if (htcpHdr.minor == 0)
-	old_squid_format = 1;
-    else
-	old_squid_format = 0;
-    debug(31, 3) ("htcpHandle: htcpHdr.length = %d\n", (int) htcpHdr.length);
-    debug(31, 3) ("htcpHandle: htcpHdr.major = %d\n", (int) htcpHdr.major);
-    debug(31, 3) ("htcpHandle: htcpHdr.minor = %d\n", (int) htcpHdr.minor);
-    if (sz != htcpHdr.length) {
-	debug(31, 1) ("htcpHandle: sz/%d != htcpHdr.length/%d from %s:%d\n",
-	    sz, htcpHdr.length,
-	    inet_ntoa(from->sin_addr), (int) ntohs(from->sin_port));
-	return;
-    }
-    if (htcpHdr.major != 0) {
-	debug(31, 1) ("htcpHandle: Unknown major version %d from %s:%d\n",
-	    htcpHdr.major,
-	    inet_ntoa(from->sin_addr), (int) ntohs(from->sin_port));
-	return;
-    }
-    buf += sizeof(htcpHeader);
-    sz -= sizeof(htcpHeader);
-    htcpHandleData(buf, sz, from);
-}
-
-static void
 htcpRecv(int fd, void *data)
 {
     static char buf[8192];
@@ -1205,6 +1243,71 @@
     debug(31, 3) ("htcpQuery: key (%p) %s\n", save_key, storeKeyText(save_key));
 }
 
+void
+htcpClear(StoreEntry * e, const char *uri, request_t * req, method_t *method, peer * p, htcp_clr_reason reason)
+{
+    static char pkt[8192];
+    ssize_t pktlen;
+    char vbuf[32];
+    htcpStuff stuff;
+    HttpHeader hdr;
+    Packer pa;
+    MemBuf mb;
+    http_state_flags flags;
+
+    if (htcpInSocket < 0)
+	return;
+
+    old_squid_format = p->options.htcp_oldsquid;
+    memset(&flags, '\0', sizeof(flags));
+    snprintf(vbuf, sizeof(vbuf), "%d/%d",
+	req->http_ver.major, req->http_ver.minor);
+    stuff.op = HTCP_CLR;
+    stuff.rr = RR_REQUEST;
+    stuff.f1 = 0;
+    stuff.response = 0;
+    stuff.msg_id = ++msg_id_counter;
+    switch (reason) {
+    case HTCP_CLR_INVALIDATION:
+        stuff.reason = 1;
+        break;
+    default:
+        stuff.reason = 0;
+        break;
+    }
+    stuff.S.method = (char *) method->string;
+    if (e == NULL || e->mem_obj == NULL) {
+	if (uri == NULL) {
+	    return;
+	}
+        stuff.S.uri = xstrdup(uri);
+    } else {
+        stuff.S.uri = (char *) storeUrl(e);
+    }
+    stuff.S.version = vbuf;
+    if (reason != HTCP_CLR_INVALIDATION) {
+	httpBuildRequestHeader(req, req, e, &hdr, flags);
+	memBufDefInit(&mb);
+	packerToMemInit(&pa, &mb);
+	httpHeaderPackInto(&hdr, &pa);
+	httpHeaderClean(&hdr);
+	packerClean(&pa);
+	stuff.S.req_hdrs = mb.buf;
+    }
+    pktlen = htcpBuildPacket(pkt, sizeof(pkt), &stuff);
+    if (reason != HTCP_CLR_INVALIDATION) {
+    	memBufClean(&mb);
+    }
+    if (e == NULL) {
+        xfree(stuff.S.uri);
+    }
+    if (!pktlen) {
+	debug(31, 1) ("htcpQuery: htcpBuildPacket() failed\n");
+	return;
+    }
+    htcpSend(pkt, (int) pktlen, &p->in_addr);
+}
+
 /*  
  * htcpSocketShutdown only closes the 'in' socket if it is
  * different than the 'out' socket.
Index: http.c
===================================================================
RCS file: /cvsroot/squid/squid/src/http.c,v
retrieving revision 1.449
diff -u -r1.449 http.c
--- http.c	17 Aug 2008 22:02:00 -0000	1.449
+++ http.c	27 Aug 2008 06:33:22 -0000
@@ -238,6 +238,9 @@
     else
 	pe = storeGetPublicByCode(e->mem_obj->url, METHOD_HEAD);
     if (pe != NULL && e != pe) {
+#if USE_HTCP
+	neighborsHtcpClear(e, NULL, e->mem_obj->request, urlMethodGetKnownByCode(METHOD_HEAD), HTCP_CLR_INVALIDATION);
+#endif
 	storeRelease(pe);
     }
     if (forbidden)
Index: neighbors.c
===================================================================
RCS file: /cvsroot/squid/squid/src/neighbors.c,v
retrieving revision 1.330
diff -u -r1.330 neighbors.c
--- neighbors.c	15 Aug 2008 04:56:00 -0000	1.330
+++ neighbors.c	27 Aug 2008 06:33:22 -0000
@@ -478,7 +478,7 @@
 	debug(15, 3) ("neighborsUdpPing: reqnum = %d\n", reqnum);
 
 #if USE_HTCP
-	if (p->options.htcp) {
+	if (p->options.htcp && !p->options.htcp_only_clr) {
 	    debug(15, 3) ("neighborsUdpPing: sending HTCP query\n");
 	    htcpQuery(entry, request, p);
 	} else
@@ -1327,8 +1327,18 @@
     if (p->options.sourcehash)
 	storeAppendPrintf(sentry, " sourcehash");
 #if USE_HTCP
-    if (p->options.htcp)
+    if (p->options.htcp) {
 	storeAppendPrintf(sentry, " htcp");
+	
+	if (p->options.htcp_oldsquid)
+	    storeAppendPrintf(sentry, " htcp-oldsquid");
+	if (p->options.htcp_no_clr)
+	    storeAppendPrintf(sentry, " htcp-no-clr");
+	if (p->options.htcp_no_purge_clr)
+	    storeAppendPrintf(sentry, " htcp-no-purge-clr");
+	if (p->options.htcp_only_clr)
+	    storeAppendPrintf(sentry, " htcp-only-clr");
+    }
 #endif
     if (p->options.no_netdb_exchange)
 	storeAppendPrintf(sentry, " no-netdb-exchange");
@@ -1513,4 +1523,28 @@
     debug(15, 3) ("neighborsHtcpReply: e = %p\n", e);
     mem->ping_reply_callback(p, ntype, PROTO_HTCP, htcp, mem->ircb_data);
 }
+
+void
+neighborsHtcpClear(StoreEntry *e, const char *uri, request_t *req, method_t *method, htcp_clr_reason reason)
+{
+	peer	*p;
+	int	i;
+	
+	debug(15, 1) ("neighborsHtcpClear: clear reason: %d\n", reason);
+	for (i = 0, p = Config.peers; i++ < Config.npeers; p = p->next) {
+		if (!p->options.htcp) {
+			continue;
+		}
+		if (p->options.htcp_no_clr) {
+			continue;
+		}
+		if (p->options.htcp_no_purge_clr && reason == HTCP_CLR_PURGE) {
+			continue;
+		}
+		
+		debug(15, 1) ("neighborsHtcpClear: sending CLR to %s:%d\n", inet_ntoa(p->in_addr.sin_addr), ntohs(p->in_addr.sin_port));
+		htcpClear(e, uri, req, method, p, reason);
+	}
+}
+
 #endif
Index: protos.h
===================================================================
RCS file: /cvsroot/squid/squid/src/protos.h,v
retrieving revision 1.567
diff -u -r1.567 protos.h
--- protos.h	15 Aug 2008 05:08:00 -0000	1.567
+++ protos.h	27 Aug 2008 06:33:22 -0000
@@ -688,6 +688,9 @@
 extern void neighborsUdpAck(const cache_key *, icp_common_t *, const struct sockaddr_in *);
 extern void neighborAdd(const char *, const char *, int, int, int, int, int);
 extern void neighbors_init(void);
+#if USE_HTCP
+extern void neighborsHtcpClear(StoreEntry *, const char *, request_t *, method_t *, htcp_clr_reason);
+#endif
 extern peer *peerFindByName(const char *);
 extern peer *peerFindByNameAndPort(const char *, unsigned short);
 extern peer *getDefaultParent(request_t * request);
@@ -1257,6 +1260,7 @@
 #if USE_HTCP
 extern void htcpInit(void);
 extern void htcpQuery(StoreEntry * e, request_t * req, peer * p);
+extern void htcpClear(StoreEntry * e, const char *uri, request_t * req, method_t *, peer * p, htcp_clr_reason reason);
 extern void htcpSocketShutdown(void);
 extern void htcpSocketClose(void);
 #endif
Index: store.c
===================================================================
RCS file: /cvsroot/squid/squid/src/store.c,v
retrieving revision 1.596
diff -u -r1.596 store.c
--- store.c	15 Aug 2008 05:08:00 -0000	1.596
+++ store.c	27 Aug 2008 06:33:23 -0000
@@ -426,10 +426,28 @@
 	}
 	e = storeGetPublic(url, method);
 	if (e == NULL) {
+#if USE_HTCP
+            if (m == METHOD_HEAD) {
+                method = urlMethodGetKnownByCode(METHOD_GET);
+            }
+            neighborsHtcpClear(NULL, url, req, method, HTCP_CLR_INVALIDATION);
+            if (m == METHOD_GET || m == METHOD_HEAD) {
+                get_or_head_sent = 1;
+            }
+#endif
 	    continue;
 	}
 	debug(20, 5) ("storePurgeEntriesByUrl: purging %s %s\n",
 	    method->string, url);
+#if USE_HTCP
+        if (m == METHOD_HEAD) {
+            method = urlMethodGetKnownByCode(METHOD_GET);
+        }
+        neighborsHtcpClear(e, url, req, method, HTCP_CLR_INVALIDATION);
+        if (m == METHOD_GET || m == METHOD_HEAD) {
+            get_or_head_sent = 1;
+        }
+#endif
 	storeRelease(e);
     }
 }
Index: structs.h
===================================================================
RCS file: /cvsroot/squid/squid/src/structs.h,v
retrieving revision 1.567
diff -u -r1.567 structs.h
--- structs.h	17 Aug 2008 22:02:00 -0000	1.567
+++ structs.h	27 Aug 2008 06:33:23 -0000
@@ -1506,6 +1506,10 @@
 #if USE_HTCP
 	unsigned int htcp:1;
 	unsigned int htcp_oldsquid:1;
+	unsigned int htcp_no_clr:1;
+	unsigned int htcp_no_purge_clr:1;
+	unsigned int htcp_only_clr:1;
+	unsigned int htcp_forward_clr:1;
 #endif
 	unsigned int no_netdb_exchange:1;
 #if DELAY_POOLS
Index: typedefs.h
===================================================================
RCS file: /cvsroot/squid/squid/src/typedefs.h,v
retrieving revision 1.164
diff -u -r1.164 typedefs.h
--- typedefs.h	15 Aug 2008 04:56:01 -0000	1.164
+++ typedefs.h	27 Aug 2008 06:33:23 -0000
@@ -434,4 +434,11 @@
 
 typedef void REFRESHCHECK(void *data, int fresh, const char *log);
 typedef struct _refresh_check_helper refresh_check_helper;
+
+#if USE_HTCP
+
+typedef enum htcp_clr_reason htcp_clr_reason;
+
+#endif
+
 #endif /* SQUID_TYPEDEFS_H */
