Index: squid/src/http.c
===================================================================
--- squid.orig/src/http.c	2008-08-12 15:16:30.000000000 +1000
+++ squid/src/http.c	2008-08-12 15:16:40.000000000 +1000
@@ -53,9 +53,35 @@
 static void httpMakePrivate(StoreEntry *);
 static void httpMakePublic(StoreEntry *);
 static int httpCachableReply(HttpStateData *);
-static void httpMaybeRemovePublic(StoreEntry *, http_status);
+static void httpMaybeRemovePublic(StoreEntry *, HttpReply *);
 static int peer_supports_connection_pinning(HttpStateData * httpState);
 
+static int
+httpUrlHostsMatch(const char *url1, const char *url2)
+{
+    const char *host1 = strchr(url1, ':');
+    const char *host2 = strchr(url2, ':');
+
+    if (host1 && host2) {
+        do {
+            ++host1;
+            ++host2;
+        } while (*host1 == '/' && *host2 == '/');
+
+        if (!*host1) {
+            return (0);
+	}
+
+        while (*host1 && *host1 != '/' && *host1 == *host2) {
+            ++host1;
+            ++host2;
+        }
+        return (*host1 == *host2);
+    }
+
+    return (0);
+}
+
 static void
 httpStateFree(int fd, void *data)
 {
@@ -133,14 +159,38 @@
 }
 
 static void
-httpMaybeRemovePublic(StoreEntry * e, http_status status)
+httpRemovePublicByHeader(request_t *req, HttpReply *reply, http_hdr_type header)
 {
+    const char	*url, *reqUrl;
+    char	*absUrl;
+
+    reqUrl = urlCanonical(req);
+    url = httpHeaderGetStr(&reply->header, header);
+    if (url != NULL) {
+	absUrl = urlAbsolute(req, url);
+	if (absUrl != NULL) {
+	    url = absUrl;
+	}
+	if (httpUrlHostsMatch(url, reqUrl)) {
+	    storePurgeEntriesByUrl(req, url);
+	}
+	if (absUrl != NULL) {
+		xfree(absUrl);
+	}
+    }
+}
+
+static void
+httpMaybeRemovePublic(StoreEntry * e, HttpReply *reply)
+{
+    int status;
     int remove = 0;
     int forbidden = 0;
     StoreEntry *pe;
-    method_t *method_get, *method_head;
-    method_get = urlMethodGetKnownByCode(METHOD_GET);
-    method_head = urlMethodGetKnownByCode(METHOD_HEAD);
+    request_t *req;
+    const char *reqUrl;
+
+    status = reply->sline.status;
     switch (status) {
     case HTTP_OK:
     case HTTP_NON_AUTHORITATIVE_INFORMATION:
@@ -161,13 +211,11 @@
 	break;
 #endif
     default:
-#if QUESTIONABLE
 	/*
-	 * Any 2xx response should eject previously cached entities...
+	 * Any "success" response should eject previously cached entities...
 	 */
-	if (status >= 200 && status < 300)
+	if (status >= 200 && status < 400)
 	    remove = 1;
-#endif
 	break;
     }
     if (!remove && !forbidden)
@@ -188,37 +236,21 @@
      * changed.
      */
     if (e->mem_obj->request)
-	pe = storeGetPublicByRequestMethod(e->mem_obj->request, method_head);
+	pe = storeGetPublicByRequestMethodCode(e->mem_obj->request, METHOD_HEAD);
     else
-	pe = storeGetPublic(e->mem_obj->url, method_head);
+	pe = storeGetPublicByCode(e->mem_obj->url, METHOD_HEAD);
     if (pe != NULL && e != pe) {
 	storeRelease(pe);
     }
     if (forbidden)
 	return;
-    switch (e->mem_obj->method->code) {
-    case METHOD_PUT:
-    case METHOD_DELETE:
-    case METHOD_PROPPATCH:
-    case METHOD_MKCOL:
-    case METHOD_MOVE:
-    case METHOD_BMOVE:
-    case METHOD_BDELETE:
-	/*
-	 * Remove any cached GET object if it is beleived that the
-	 * object may have changed as a result of other methods
-	 */
-	if (e->mem_obj->request)
-	    pe = storeGetPublicByRequestMethod(e->mem_obj->request, method_get);
-	else
-	    pe = storeGetPublic(e->mem_obj->url, method_get);
-	if (pe != NULL) {
-	    assert(e != pe);
-	    storeRelease(pe);
-	}
-	break;
-    default:
-        break;
+    if (e->mem_obj->method->flags.purges_all && status < 400) {
+	req = e->mem_obj->request;
+	reqUrl = urlCanonical(req);
+	debug(88, 5) ("httpMaybeRemovePublic: purging due to %s %s\n", req->method->string, reqUrl);
+	storePurgeEntriesByUrl(req, reqUrl);
+	httpRemovePublicByHeader(req, reply, HDR_LOCATION);
+	httpRemovePublicByHeader(req, reply, HDR_CONTENT_LOCATION);
     }
 }
 
@@ -569,7 +601,7 @@
 	    EBIT_SET(entry->flags, ENTRY_REVALIDATE);
     }
     if (neighbors_do_private_keys && !Config.onoff.collapsed_forwarding)
-	httpMaybeRemovePublic(entry, reply->sline.status);
+	httpMaybeRemovePublic(entry, reply);
     if (httpState->flags.keepalive)
 	if (httpState->peer)
 	    httpState->peer->stats.n_keepalives_sent++;
Index: squid/src/protos.h
===================================================================
--- squid.orig/src/protos.h	2008-08-12 15:16:30.000000000 +1000
+++ squid/src/protos.h	2008-08-12 15:16:40.000000000 +1000
@@ -953,6 +953,7 @@
 extern void storeAppend(StoreEntry *, const char *, int);
 extern void storeLockObjectDebug(StoreEntry *, const char *file, const int line);
 extern void storeRelease(StoreEntry *);
+extern void storePurgeEntriesByUrl(request_t *req, const char *url);
 extern int storeUnlockObjectDebug(StoreEntry *, const char *file, const int line);
 extern const char *storeLookupUrl(const StoreEntry * e);
 #define	storeLockObject(a) storeLockObjectDebug(a, __FILE__, __LINE__);
@@ -1188,6 +1189,7 @@
 extern void urlInitialize(void);
 extern request_t *urlParse(method_t *, char *);
 extern const char *urlCanonical(request_t *);
+extern char *urlAbsolute(request_t *, const char *);
 extern char *urlRInternal(const char *host, u_short port, const char *dir, const char *name);
 extern char *urlInternal(const char *dir, const char *name);
 extern int matchDomainName(const char *host, const char *domain);
Index: squid/src/store.c
===================================================================
--- squid.orig/src/store.c	2008-08-12 15:16:30.000000000 +1000
+++ squid/src/store.c	2008-08-12 15:16:40.000000000 +1000
@@ -408,6 +408,36 @@
     return e;
 }
 
+void
+storePurgeEntriesByUrl(request_t *req, const char *url)
+{
+	int		m, get_or_head_sent;
+	method_t	*method;
+	StoreEntry	*e;
+
+	debug(20, 5) ("storePurgeEntriesByUrl: purging %s\n", url);
+	get_or_head_sent = 0;
+
+	for (m = METHOD_NONE; m < METHOD_OTHER; m++) {
+		method = urlMethodGetKnownByCode(m);
+		if (!method->flags.cachable) {
+			continue;
+		}
+		if ((m == METHOD_HEAD || m == METHOD_GET) && get_or_head_sent) {
+			continue;
+		}
+
+		e = storeGetPublic(url, method);
+		if (e == NULL) {
+			continue;
+		}
+
+		debug(20, 5) ("storePurgeEntriesByUrl: purging %s %s\n",
+		    method->string, url);
+		storeRelease(e);
+	}
+}
+
 static int
 getKeyCounter(void)
 {
Index: squid/src/url.c
===================================================================
--- squid.orig/src/url.c	2008-08-12 15:16:30.000000000 +1000
+++ squid/src/url.c	2008-08-12 15:16:40.000000000 +1000
@@ -525,6 +525,70 @@
     return (request->canonical = xstrdup(urlbuf));
 }
 
+char *
+urlAbsolute(request_t *req, const char *relUrl)
+{
+	LOCAL_ARRAY(char, portbuf, 32);
+	LOCAL_ARRAY(char, urlbuf, MAX_URL);
+	char	*path, *last_slash;
+
+	if (relUrl == NULL) {
+		return (NULL);
+	}
+	if (req->method->code == METHOD_CONNECT) {
+		return (NULL);
+	}
+	if (strchr(relUrl, ':') != NULL) {
+		return (NULL);
+	}
+
+	if (req->protocol == PROTO_URN) {
+		snprintf(urlbuf, MAX_URL, "urn:%s", strBuf(req->urlpath));
+	} else {
+		portbuf[0] = '\0';
+		if (req->port != urlDefaultPort(req->protocol)) {
+			snprintf(portbuf, 32, ":%d", req->port);
+		}
+		if (relUrl[0] == '/') {
+			snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s%s",
+			    ProtocolStr[req->protocol],
+			    req->login,
+			    *req->login ? "@" : null_string,
+			    req->host,
+			    portbuf,
+			    relUrl
+			);
+		} else {
+			path = xstrdup(strBuf(req->urlpath));
+			last_slash = strrchr(path, '/');
+			if (last_slash == NULL) {
+				snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s/%s",
+				    ProtocolStr[req->protocol],
+				    req->login,
+				    *req->login ? "@" : null_string,
+				    req->host,
+				    portbuf,
+				    relUrl
+				);
+			} else {
+				last_slash++;
+				*last_slash = '\0';
+				snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s%s%s",
+				    ProtocolStr[req->protocol],
+				    req->login,
+				    *req->login ? "@" : null_string,
+				    req->host,
+				    portbuf,
+				    path,
+				    relUrl
+				);
+			}
+			xfree(path);
+		}
+	}
+
+	return (xstrdup(urlbuf));
+}
 /*
  * Eventually the request_t strings should be String entries which
  * have in-built length. Eventually we should just take a buffer and

