Index: squid/src/HttpReply.c
===================================================================
--- squid.orig/src/HttpReply.c	2008-08-12 14:59:36.383037000 +1000
+++ squid/src/HttpReply.c	2008-08-12 15:16:29.000000000 +1000
@@ -474,13 +474,14 @@
  * Returns the body size of a HTTP response
  */
 squid_off_t
-httpReplyBodySize(method_t method, const HttpReply * reply)
+httpReplyBodySize(method_t *method, const HttpReply * reply)
 {
     if (reply->sline.version.major < 1)
 	return -1;
-    else if (METHOD_HEAD == method)
-	return 0;
-    else if (reply->sline.status == HTTP_OK)
+    else if (method != NULL) {
+	if (method->code == METHOD_HEAD)
+		return 0;
+    } else if (reply->sline.status == HTTP_OK)
 	(void) 0;		/* common case, continue */
     else if (reply->sline.status == HTTP_NO_CONTENT)
 	return 0;
Index: squid/src/HttpRequest.c
===================================================================
--- squid.orig/src/HttpRequest.c	2008-08-12 14:59:36.383189000 +1000
+++ squid/src/HttpRequest.c	2008-08-12 15:16:29.000000000 +1000
@@ -36,7 +36,7 @@
 #include "squid.h"
 
 request_t *
-requestCreate(method_t method, protocol_t protocol, const char *urlpath)
+requestCreate(method_t *method, protocol_t protocol, const char *urlpath)
 {
     request_t *req = memAllocate(MEM_REQUEST_T);
     req->method = method;
@@ -85,6 +85,7 @@
     if (req->pinned_connection)
 	cbdataUnlock(req->pinned_connection);
     req->pinned_connection = NULL;
+    urlMethodFree(req->method);
     memFree(req, MEM_REQUEST_T);
 }
 
@@ -114,7 +115,7 @@
     assert(req && p);
     /* pack request-line */
     packerPrintf(p, "%s %s HTTP/%d.%d\r\n",
-	RequestMethods[req->method].str, strBuf(req->urlpath), req->http_ver.major, req->http_ver.minor);
+	req->method->string, strBuf(req->urlpath), req->http_ver.major, req->http_ver.minor);
     /* headers */
     httpHeaderPackInto(&req->header, p);
     /* trailer */
@@ -134,7 +135,7 @@
     packerPrintf(p, "\n");
     /* pack request-line */
     packerPrintf(p, "%s %s HTTP/%d.%d\r\n",
-	RequestMethods[req->method].str, urlCanonical(req), req->http_ver.major, req->http_ver.minor);
+	req->method->string, urlCanonical(req), req->http_ver.major, req->http_ver.minor);
     /* headers */
     httpHeaderPackInto(&req->header, p);
     /* trailer */
@@ -154,7 +155,7 @@
 
 #if UNUSED_CODE
 void
-httpRequestSetHeaders(request_t * req, method_t method, const char *uri, const char *header_str)
+httpRequestSetHeaders(request_t * req, method_t *method, const char *uri, const char *header_str)
 {
     assert(req && uri && header_str);
     assert(!req->header.len);
@@ -168,7 +169,7 @@
 httpRequestPrefixLen(const request_t * req)
 {
     assert(req);
-    return RequestMethods[req->method].len + 1 +
+    return strlen(req->method->string) + 1 +
 	strLen(req->urlpath) + 1 +
 	4 + 1 + 3 + 2 +
 	req->header.len + 2;
Index: squid/src/access_log.c
===================================================================
--- squid.orig/src/access_log.c	2008-08-12 15:16:24.000000000 +1000
+++ squid/src/access_log.c	2008-08-12 15:16:29.000000000 +1000
@@ -1156,7 +1156,7 @@
     if (al->icp.opcode)
 	al->private.method_str = icp_opcode_str[al->icp.opcode];
     else
-	al->private.method_str = RequestMethods[al->http.method].str;
+	al->private.method_str = al->http.method->string;
     if (al->hier.host[0] == '\0')
 	xstrncpy(al->hier.host, dash_str, SQUIDHOSTNAMELEN);
 
@@ -1198,7 +1198,7 @@
 #if MULTICAST_MISS_STREAM
     if (al->cache.code != LOG_TCP_MISS)
 	(void) 0;
-    else if (al->http.method != METHOD_GET)
+    else if (al->http.method->code != METHOD_GET)
 	(void) 0;
     else if (mcast_miss_fd < 0)
 	(void) 0;
@@ -1443,12 +1443,12 @@
 
 #if HEADERS_LOG
 void
-headersLog(int cs, int pq, method_t m, void *data)
+headersLog(int cs, int pq, method_t *m, void *data)
 {
     HttpReply *rep;
     request_t *req;
     unsigned short magic = 0;
-    unsigned char M = (unsigned char) m;
+    unsigned char M = (unsigned char) m->code;
     unsigned short S;
     char *hmask;
     int ccmask = 0;
Index: squid/src/acl.c
===================================================================
--- squid.orig/src/acl.c	2008-08-12 14:59:36.383348000 +1000
+++ squid/src/acl.c	2008-08-12 15:16:29.000000000 +1000
@@ -42,7 +42,6 @@
 static void aclParseIntlist(void *curlist);
 static void aclParseWordList(void *curlist);
 static void aclParseProtoList(void *curlist);
-static void aclParseMethodList(void *curlist);
 static void aclParseTimeSpec(void *curlist);
 static void aclParsePortRange(void *curlist);
 static void aclDestroyTimeList(acl_time_data * data);
@@ -82,7 +81,6 @@
 static wordlist *aclDumpIntlistList(intlist * data);
 static wordlist *aclDumpIntRangeList(intrange * data);
 static wordlist *aclDumpProtoList(intlist * data);
-static wordlist *aclDumpMethodList(intlist * data);
 static SPLAYCMP aclIpAddrNetworkCompare;
 static SPLAYCMP aclIpNetworkCompare;
 static SPLAYCMP aclHostDomainCompare;
@@ -383,23 +381,6 @@
 }
 
 static void
-aclParseMethodList(void *curlist)
-{
-    intlist **Tail;
-    intlist *q = NULL;
-    char *t = NULL;
-    for (Tail = curlist; *Tail; Tail = &((*Tail)->next));
-    while ((t = strtokFile())) {
-	q = memAllocate(MEM_INTLIST);
-	q->i = (int) urlParseMethod(t, strlen(t));
-	if (q->i == METHOD_NONE)
-	    self_destruct();
-	*(Tail) = q;
-	Tail = &q->next;
-    }
-}
-
-static void
 aclParseType(void *current)
 {
     acl_request_type **p = current;
@@ -1060,7 +1041,7 @@
 	aclParseProtoList(&A->data);
 	break;
     case ACL_METHOD:
-	aclParseMethodList(&A->data);
+	aclParseWordList(&A->data);
 	break;
     case ACL_PROXY_AUTH:
 	if (authenticateSchemeCount() == 0) {
@@ -1696,6 +1677,19 @@
 }
 
 static int
+aclMatchWordListInsensitive(wordlist * w, const char *word)
+{
+    debug(28, 3) ("aclMatchWordListInsensitive: looking for '%s'\n", word);
+    while (w != NULL) {
+	debug(28, 3) ("aclMatchWordListInsensitive: checking '%s'\n", w->key);
+	if (!strcasecmp(w->key, word))
+	    return 1;
+	w = w->next;
+    }
+    return 0;
+}
+
+static int
 aclMatchType(acl_request_type * type, request_t * request)
 {
     if (type->accelerated && request->flags.accelerated)
@@ -1944,7 +1938,7 @@
 	return aclMatchInteger(ae->data, r->protocol);
 	/* NOTREACHED */
     case ACL_METHOD:
-	return aclMatchInteger(ae->data, r->method);
+	return aclMatchWordListInsensitive(ae->data, r->method->string);
 	/* NOTREACHED */
     case ACL_BROWSER:
 	browser = httpHeaderGetStr(&checklist->request->header, HDR_USER_AGENT);
@@ -2057,8 +2051,8 @@
 	}
 	/* NOTREACHED */
     case ACL_HIER_CODE:
-	return aclMatchWordList(ae->data, hier_strings[checklist->request->hier.code]);
-	/* NOTREACHED */
+         return aclMatchWordList(ae->data, hier_strings[checklist->request->hier.code]);
+         /* NOTREACHED */
     case ACL_NONE:
     case ACL_ENUM_MAX:
 	break;
@@ -2533,11 +2527,6 @@
 	case ACL_SRC_DOMAIN:
 	    splay_destroy(a->data, xfree);
 	    break;
-#if SQUID_SNMP
-	case ACL_SNMP_COMMUNITY:
-	    wordlistDestroy((wordlist **) (void *) &a->data);
-	    break;
-#endif
 #if USE_IDENT
 	case ACL_IDENT:
 	    aclFreeUserData(a->data);
@@ -2574,7 +2563,6 @@
 	    aclDestroyHeader(a->data);
 	    break;
 	case ACL_PROTO:
-	case ACL_METHOD:
 	case ACL_SRC_ASN:
 	case ACL_DST_ASN:
 #if SRC_RTT_NOT_YET_FINISHED
@@ -2590,16 +2578,18 @@
 	case ACL_MY_PORT:
 	    aclDestroyIntRange(a->data);
 	    break;
+#if SQUID_SNMP
+	case ACL_SNMP_COMMUNITY:
+#endif
+	case ACL_METHOD:
 	case ACL_MY_PORT_NAME:
+	case ACL_URLGROUP:
+	case ACL_HIER_CODE:
 	    wordlistDestroy((wordlist **) (void *) &a->data);
 	    break;
 	case ACL_EXTERNAL:
 	    aclDestroyExternal(&a->data);
 	    break;
-	case ACL_URLGROUP:
-	case ACL_HIER_CODE:
-	    wordlistDestroy((wordlist **) (void *) &a->data);
-	    break;
 #if USE_SSL
 	case ACL_USER_CERT:
 	case ACL_CA_CERT:
@@ -2954,17 +2944,6 @@
 }
 
 static wordlist *
-aclDumpMethodList(intlist * data)
-{
-    wordlist *W = NULL;
-    while (data != NULL) {
-	wordlistAdd(&W, RequestMethods[data->i].str);
-	data = data->next;
-    }
-    return W;
-}
-
-static wordlist *
 aclDumpType(acl_request_type * type)
 {
     wordlist *W = NULL;
@@ -3033,7 +3012,7 @@
     case ACL_PROTO:
 	return aclDumpProtoList(a->data);
     case ACL_METHOD:
-	return aclDumpMethodList(a->data);
+	return wordlistDup(a->data);
 #if USE_ARP_ACL
     case ACL_SRC_ARP:
 	return aclDumpArpList(a->data);
@@ -3074,7 +3053,7 @@
 	for (b = a->acl_list; b; b = b->next) {
 	    if (ACL_METHOD != b->acl->type)
 		continue;
-	    if (aclMatchInteger(b->acl->data, METHOD_PURGE))
+	    if (aclMatchWordList(b->acl->data, "PURGE"))
 		return 1;
 	}
     }
Index: squid/src/asn.c
===================================================================
--- squid.orig/src/asn.c	2008-08-12 14:59:36.383433000 +1000
+++ squid/src/asn.c	2008-08-12 15:16:29.000000000 +1000
@@ -195,15 +195,17 @@
     StoreEntry *e;
     request_t *req;
     ASState *asState;
+    method_t *method_get;
+    method_get = urlMethodGetKnownByCode(METHOD_GET);
     asState = cbdataAlloc(ASState);
     debug(53, 3) ("asnCacheStart: AS %d\n", as);
     snprintf(asres, 4096, "whois://%s/!gAS%d", Config.as_whois_server, as);
     asState->as_number = as;
-    req = urlParse(METHOD_GET, asres);
+    req = urlParse(method_get, asres);
     assert(NULL != req);
     asState->request = requestLink(req);
-    if ((e = storeGetPublic(asres, METHOD_GET)) == NULL) {
-	e = storeCreateEntry(asres, null_request_flags, METHOD_GET);
+    if ((e = storeGetPublic(asres, method_get)) == NULL) {
+	e = storeCreateEntry(asres, null_request_flags, method_get);
 	asState->sc = storeClientRegister(e, asState);
 	fwdStart(-1, e, asState->request);
     } else {
Index: squid/src/cf.data.pre
===================================================================
--- squid.orig/src/cf.data.pre	2008-08-12 15:16:24.000000000 +1000
+++ squid/src/cf.data.pre	2008-08-12 15:16:29.000000000 +1000
@@ -3456,15 +3456,6 @@
 	objects not intended for caching to get cached.
 DOC_END
 
-NAME: extension_methods
-TYPE: extension_method
-LOC: RequestMethods
-DEFAULT: none
-DOC_START
-	Squid only knows about standardized HTTP request methods.
-	You can add up to 20 additional "extension" methods here.
-DOC_END
-
 NAME: request_entities
 TYPE: onoff
 LOC: Config.onoff.request_entities
Index: squid/src/client_side.c
===================================================================
--- squid.orig/src/client_side.c	2008-08-12 15:16:24.000000000 +1000
+++ squid/src/client_side.c	2008-08-12 15:16:30.000000000 +1000
@@ -120,7 +120,7 @@
 static void clientProcessHit(clientHttpRequest * http);
 static void clientBuildReplyHeader(clientHttpRequest * http, HttpReply * rep);
 static clientHttpRequest *parseHttpRequestAbort(ConnStateData * conn, const char *uri);
-static clientHttpRequest *parseHttpRequest(ConnStateData *, HttpMsgBuf *, method_t *, int *);
+static clientHttpRequest *parseHttpRequest(ConnStateData *, HttpMsgBuf *, method_t **, int *);
 
 static void clientCheckNoCache(clientHttpRequest *);
 static void clientCheckNoCacheDone(int answer, void *data);
@@ -165,7 +165,7 @@
 #endif
 static int varyEvaluateMatch(StoreEntry * entry, request_t * request);
 static int modifiedSince(StoreEntry *, request_t *);
-static StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, request_flags);
+static StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t *, request_flags);
 static inline int clientNatLookup(ConnStateData * conn);
 
 #if USE_IDENT
@@ -385,7 +385,7 @@
 }
 
 static StoreEntry *
-clientCreateStoreEntry(clientHttpRequest * h, method_t m, request_flags flags)
+clientCreateStoreEntry(clientHttpRequest * h, method_t *m, request_flags flags)
 {
     StoreEntry *e;
     /*
@@ -432,7 +432,7 @@
     ErrorState *err = NULL;
     char *proxy_auth_msg = NULL;
     debug(33, 2) ("The request %s %s is %s, because it matched '%s'\n",
-	RequestMethods[http->request->method].str, http->uri,
+	http->request->method->string, http->uri,
 	answer == ACCESS_ALLOWED ? "ALLOWED" : "DENIED",
 	AclMatchedName ? AclMatchedName : "NO ACL's");
     proxy_auth_msg = authenticateAuthUserRequestMessage(http->conn->auth_user_request ? http->conn->auth_user_request : http->request->auth_user_request);
@@ -497,7 +497,7 @@
     ErrorState *err = NULL;
     char *proxy_auth_msg = NULL;
     debug(33, 2) ("The request %s %s is %s, because it matched '%s'\n",
-	RequestMethods[http->request->method].str, http->uri,
+	http->request->method->string, http->uri,
 	answer == ACCESS_ALLOWED ? "ALLOWED" : "DENIED",
 	AclMatchedName ? AclMatchedName : "NO ACL's");
     proxy_auth_msg = authenticateAuthUserRequestMessage(http->conn->auth_user_request ? http->conn->auth_user_request : http->request->auth_user_request);
@@ -978,6 +978,7 @@
     ErrorState *err = NULL;
     HttpReply *r;
     http_status status = HTTP_NOT_FOUND;
+    method_t *method_get = NULL, *method_head = NULL;
     debug(33, 3) ("Config2.onoff.enable_purge = %d\n", Config2.onoff.enable_purge);
     if (!Config2.onoff.enable_purge) {
 	http->log_type = LOG_TCP_DENIED;
@@ -989,12 +990,16 @@
     /* Release both IP cache */
     ipcacheInvalidate(http->request->host);
 
+    method_get = urlMethodGetKnownByCode(METHOD_GET);
+    method_head = urlMethodGetKnownByCode(METHOD_HEAD);
+
     if (!http->flags.purging) {
 	/* Try to find a base entry */
 	http->flags.purging = 1;
-	entry = storeGetPublicByRequestMethod(http->request, METHOD_GET);
-	if (!entry)
-	    entry = storeGetPublicByRequestMethod(http->request, METHOD_HEAD);
+	entry = storeGetPublicByRequestMethod(http->request, method_get);
+	if (!entry) {
+	    entry = storeGetPublicByRequestMethod(http->request, method_head);
+	}
 	if (entry) {
 	    if (EBIT_TEST(entry->flags, ENTRY_SPECIAL)) {
 		http->log_type = LOG_TCP_DENIED;
@@ -1018,14 +1023,14 @@
     }
     http->log_type = LOG_TCP_MISS;
     /* Release the cached URI */
-    entry = storeGetPublicByRequestMethod(http->request, METHOD_GET);
+    entry = storeGetPublicByRequestMethod(http->request, method_get);
     if (entry) {
 	debug(33, 4) ("clientPurgeRequest: GET '%s'\n",
 	    storeUrl(entry));
 	storeRelease(entry);
 	status = HTTP_OK;
     }
-    entry = storeGetPublicByRequestMethod(http->request, METHOD_HEAD);
+    entry = storeGetPublicByRequestMethod(http->request, method_head);
     if (entry) {
 	debug(33, 4) ("clientPurgeRequest: HEAD '%s'\n",
 	    storeUrl(entry));
@@ -1034,14 +1039,14 @@
     }
     /* And for Vary, release the base URI if none of the headers was included in the request */
     if (http->request->vary_headers && !strstr(http->request->vary_headers, "=")) {
-	entry = storeGetPublic(urlCanonical(http->request), METHOD_GET);
+	entry = storeGetPublic(urlCanonical(http->request), method_get);
 	if (entry) {
 	    debug(33, 4) ("clientPurgeRequest: Vary GET '%s'\n",
 		storeUrl(entry));
 	    storeRelease(entry);
 	    status = HTTP_OK;
 	}
-	entry = storeGetPublic(urlCanonical(http->request), METHOD_HEAD);
+	entry = storeGetPublic(urlCanonical(http->request), method_head);
 	if (entry) {
 	    debug(33, 4) ("clientPurgeRequest: Vary HEAD '%s'\n",
 		storeUrl(entry));
@@ -1360,7 +1365,7 @@
 	request->flags.no_connection_auth = 1;
 
     /* ignore range header in non-GETs */
-    if (request->method == METHOD_GET) {
+    if (request->method->code == METHOD_GET) {
 	request->range = httpHeaderGetRange(req_hdr);
 	if (request->range)
 	    request->flags.range = 1;
@@ -1450,7 +1455,7 @@
 	stringClean(&s);
     }
 #endif
-    if (request->method == METHOD_TRACE) {
+    if (request->method->code == METHOD_TRACE) {
 	request->max_forwards = httpHeaderGetInt(req_hdr, HDR_MAX_FORWARDS);
     }
     if (clientCachable(http))
@@ -1480,7 +1485,7 @@
     debug(33, 3) ("clientSetKeepaliveFlag: http_ver = %d.%d\n",
 	request->http_ver.major, request->http_ver.minor);
     debug(33, 3) ("clientSetKeepaliveFlag: method = %s\n",
-	RequestMethods[request->method].str);
+	request->method->string);
     {
 	http_version_t http_ver;
 	if (http->conn->port->http11)
@@ -1495,11 +1500,7 @@
 static int
 clientCheckContentLength(request_t * r)
 {
-    switch (r->method) {
-    case METHOD_PUT:
-    case METHOD_POST:
-	/* PUT/POST requires a request entity */
-	return (r->content_length >= 0);
+    switch (r->method->code) {
     case METHOD_GET:
     case METHOD_HEAD:
 	/* We do not want to see a request entity on GET/HEAD requests */
@@ -1515,19 +1516,21 @@
 clientCachable(clientHttpRequest * http)
 {
     request_t *req = http->request;
-    method_t method = req->method;
+    method_t *method = req->method;
     if (req->flags.loopdetect)
 	return 0;
     if (req->protocol == PROTO_HTTP)
 	return httpCachable(method);
     /* FTP is always cachable */
-    if (method == METHOD_CONNECT)
+    if (method->code == METHOD_OTHER)
+	return 0;
+    if (method->code == METHOD_CONNECT)
 	return 0;
-    if (method == METHOD_TRACE)
+    if (method->code == METHOD_TRACE)
 	return 0;
-    if (method == METHOD_PUT)
+    if (method->code == METHOD_PUT)
 	return 0;
-    if (method == METHOD_POST)
+    if (method->code == METHOD_POST)
 	return 0;		/* XXX POST may be cached sometimes.. ignored for now */
     if (req->protocol == PROTO_GOPHER)
 	return gopherCachable(req);
@@ -1542,7 +1545,7 @@
 {
     const char *url = http->uri;
     request_t *request = http->request;
-    method_t method = request->method;
+    method_t *method = request->method;
     const wordlist *p = NULL;
 
     /* IMS needs a private key, so we can use the hierarchy for IMS only
@@ -1551,9 +1554,9 @@
 	return 0;
     if (request->flags.auth)
 	return 0;
-    if (method == METHOD_TRACE)
+    if (method->code == METHOD_TRACE)
 	return 1;
-    if (method != METHOD_GET)
+    if (method->code != METHOD_GET)
 	return 0;
     /* scan hierarchy_stoplist */
     for (p = Config.hierarchy_stoplist; p; p = p->next)
@@ -2313,7 +2316,7 @@
 	clientProcessMiss(http);
 	return;
     }
-    if (r->method == METHOD_PURGE) {
+    if (r->method->code == METHOD_PURGE) {
 	http->entry = NULL;
 	storeClientUnregister(http->sc, e, http);
 	http->sc = NULL;
@@ -3020,7 +3023,7 @@
 {
     clientHttpRequest *http = data;
     debug(33, 2) ("The reply for %s %s is %s, because it matched '%s'\n",
-	RequestMethods[http->request->method].str, http->uri,
+	http->request->method->string, http->uri,
 	answer ? "ALLOWED" : "DENIED",
 	AclMatchedName ? AclMatchedName : "NO ACL's");
     if (answer != ACCESS_ALLOWED) {
@@ -3093,9 +3096,11 @@
     MemBuf mb;
     /* reset range iterator */
     http->range_iter.pos = HttpHdrRangeInitPos;
-    if (http->request->method == METHOD_HEAD) {
-	/* do not forward body for HEAD replies */
-	http->flags.done_copying = 1;
+    if (http->request->method != NULL) {
+	    if (http->request->method->code == METHOD_HEAD) {
+		/* do not forward body for HEAD replies */
+		http->flags.done_copying = 1;
+	    }
     }
     /* init mb; put status line and headers  */
     if (http->http_ver.major >= 1)
@@ -3114,7 +3119,8 @@
     /* append body if any */
     if (http->request->range) {
 	/* Only GET requests should have ranges */
-	assert(http->request->method == METHOD_GET);
+	assert(http->request->method != NULL);
+	assert(http->request->method->code == METHOD_GET);
 	/* clientPackMoreRanges() updates http->out.offset */
 	/* force the end of the transfer if we are done */
 	if (!clientPackMoreRanges(http, "", 0, &mb))
@@ -3192,7 +3198,7 @@
 	/* NULL because clientWriteBodyComplete frees it */
 	return;
     }
-    if (http->request->method == METHOD_HEAD) {
+    if (http->request->method->code == METHOD_HEAD) {
 	/*
 	 * If we are here, then store_status == STORE_OK and it
 	 * seems we have a HEAD repsponse which is missing the
@@ -3212,7 +3218,7 @@
     memBufDefInit(&mb);
     if (http->request->range) {
 	/* Only GET requests should have ranges */
-	assert(http->request->method == METHOD_GET);
+	assert(http->request->method->code == METHOD_GET);
 	/* clientPackMoreRanges() updates http->out.offset */
 	/* force the end of the transfer if we are done */
 	if (!clientPackMoreRanges(http, buf, size, &mb))
@@ -3291,7 +3297,7 @@
 	 * execution will resume after the operation completes.
 	 */
 	/* if it was a pipelined CONNECT kick it alive here */
-	if (http->request->method == METHOD_CONNECT)
+	if (http->request->method->code == METHOD_CONNECT)
 	    clientCheckFollowXForwardedFor(http);
     } else {
 	debug(33, 2) ("clientKeepaliveNextRequest: FD %d Sending next\n",
@@ -3423,7 +3429,7 @@
     ErrorState *err = NULL;
     http->flags.hit = 0;
     debug(33, 4) ("clientProcessOnlyIfCachedMiss: '%s %s'\n",
-	RequestMethods[r->method].str, url);
+	r->method->string, url);
     http->al.http.code = HTTP_GATEWAY_TIMEOUT;
     err = errorCon(ERR_ONLY_IF_CACHED_MISS, HTTP_GATEWAY_TIMEOUT, http->orig_request);
     if (http->entry) {
@@ -3572,9 +3578,7 @@
     char *url = http->uri;
     request_t *r = http->request;
     HttpReply *rep;
-    debug(33, 4) ("clientProcessRequest: %s '%s'\n",
-	RequestMethods[r->method].str,
-	url);
+    debug(33, 4) ("clientProcessRequest: %s '%s'\n", r->method->string, url);
     r->flags.collapsed = 0;
     if (httpHeaderHas(&r->header, HDR_EXPECT)) {
 	int ignore = 0;
@@ -3592,7 +3596,7 @@
 	    return;
 	}
     }
-    if (r->method == METHOD_CONNECT && !http->redirect.status) {
+    if (r->method->code == METHOD_CONNECT && !http->redirect.status) {
 	http->log_type = LOG_TCP_MISS;
 #if USE_SSL && SSL_CONNECT_INTERCEPT
 	if (Config.Sockaddr.https) {
@@ -3604,10 +3608,10 @@
 #endif
 	    sslStart(http, &http->out.size, &http->al.http.code);
 	return;
-    } else if (r->method == METHOD_PURGE) {
+    } else if (r->method->code == METHOD_PURGE) {
 	clientPurgeRequest(http);
 	return;
-    } else if (r->method == METHOD_TRACE) {
+    } else if (r->method->code == METHOD_TRACE) {
 	if (r->max_forwards == 0) {
 	    http->log_type = LOG_TCP_HIT;
 	    http->entry = clientCreateStoreEntry(http, r->method, null_request_flags);
@@ -3659,8 +3663,7 @@
     char *url = http->uri;
     request_t *r = http->request;
     ErrorState *err = NULL;
-    debug(33, 4) ("clientProcessMiss: '%s %s'\n",
-	RequestMethods[r->method].str, url);
+    debug(33, 4) ("clientProcessMiss: '%s %s'\n", r->method->string, url);
     http->flags.hit = 0;
     r->flags.collapsed = 0;
     /*
@@ -3681,7 +3684,7 @@
 	storeUnlockObject(http->entry);
 	http->entry = NULL;
     }
-    if (r->method == METHOD_PURGE) {
+    if (r->method->code == METHOD_PURGE) {
 	clientPurgeRequest(http);
 	return;
     }
@@ -3718,7 +3721,7 @@
 	return;
     }
     http->entry = clientCreateStoreEntry(http, r->method, r->flags);
-    if (Config.onoff.collapsed_forwarding && r->flags.cachable && !r->flags.need_validation && (r->method == METHOD_GET || r->method == METHOD_HEAD)) {
+    if (Config.onoff.collapsed_forwarding && r->flags.cachable && !r->flags.need_validation && (r->method->code == METHOD_GET || r->method->code == METHOD_HEAD)) {
 	http->entry->mem_obj->refresh_timestamp = squid_curtime;
 	/* Set the vary object state */
 	safe_free(http->entry->mem_obj->vary_headers);
@@ -3757,7 +3760,7 @@
  *    a clientHttpRequest structure on success
  */
 static clientHttpRequest *
-parseHttpRequest(ConnStateData * conn, HttpMsgBuf * hmsg, method_t * method_p, int *status)
+parseHttpRequest(ConnStateData * conn, HttpMsgBuf * hmsg, method_t **method_p, int *status)
 {
     LOCAL_ARRAY(char, urlbuf, MAX_URL);
     char *url = urlbuf;
@@ -3766,13 +3769,13 @@
     size_t header_sz;		/* size of headers, not including first line */
     size_t prefix_sz;		/* size of whole request (req-line + headers) */
     size_t req_sz;
-    method_t method;
+    method_t *method;
     clientHttpRequest *http = NULL;
     char *t;
     int ret;
 
     /* pre-set these values to make aborting simpler */
-    *method_p = METHOD_NONE;
+    *method_p = NULL;
     *status = -1;
 
     /* Parse the request line */
@@ -3803,14 +3806,13 @@
 	debug(33, 5) ("parseHttpRequest: Too large request\n");
 	return parseHttpRequestAbort(conn, "error:request-too-large");
     }
-    /* Look for request method */
-    method = urlParseMethod(hmsg->buf + hmsg->m_start, hmsg->m_len);
+    /* Wrap the request method */
+    method = urlMethodGet(hmsg->buf + hmsg->m_start, hmsg->m_len);
 
-    if (method == METHOD_NONE) {
-	debug(33, 1) ("parseHttpRequest: Unsupported method '%.*s'\n", hmsg->m_len, hmsg->buf + hmsg->m_start);
-	return parseHttpRequestAbort(conn, "error:unsupported-request-method");
+    debug(33, 5) ("parseHttpRequest: Method is '%s'\n", method->string);
+    if (method->code == METHOD_OTHER) {
+	debug(33, 5) ("parseHttpRequest: Unknown method, continuing regardless");
     }
-    debug(33, 5) ("parseHttpRequest: Method is '%s'\n", RequestMethods[method].str);
     *method_p = method;
 
     /* Make sure URL fits inside MAX_URL */
@@ -3856,7 +3858,7 @@
 #endif
 
     /* handle "accelerated" objects (and internal) */
-    if (method == METHOD_CONNECT) {
+    if (method->code == METHOD_CONNECT) {
 	if (http_ver.major < 1) {
 	    debug(33, 1) ("parseHttpRequest: Invalid HTTP version\n");
 	    goto invalid_request;
@@ -4018,7 +4020,7 @@
     int nrequests;
     dlink_node *n;
     clientHttpRequest *http = NULL;
-    method_t method;
+    method_t *method;
     ErrorState *err = NULL;
     int parser_return_code = 0;
     request_t *request = NULL;
@@ -4165,13 +4167,12 @@
 	    if (clientRequestBodyTooLarge(http, request)) {
 		err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE, request);
 		http->log_type = LOG_TCP_DENIED;
-		http->entry = clientCreateStoreEntry(http,
-		    METHOD_NONE, null_request_flags);
+		http->entry = clientCreateStoreEntry(http, urlMethodGetKnownByCode(METHOD_NONE), null_request_flags);
 		errorAppendEntry(http->entry, err);
 		return -1;
 	    }
 	}
-	if (request->method == METHOD_CONNECT) {
+	if (request->method->code == METHOD_CONNECT) {
 	    /* Stop reading requests... */
 	    commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
 	    if (!DLINK_ISEMPTY(conn->reqs) && DLINK_HEAD(conn->reqs) == http)
@@ -4203,7 +4204,7 @@
 	    /* add to the client request queue */
 	    dlinkAddTail(http, &http->node, &conn->reqs);
 	    http->log_type = LOG_TCP_DENIED;
-	    http->entry = clientCreateStoreEntry(http, METHOD_NONE, null_request_flags);
+	    http->entry = clientCreateStoreEntry(http, NULL, null_request_flags);
 	    errorAppendEntry(http->entry, err);
 	    return -1;
 	}
@@ -4953,7 +4954,7 @@
 	sending = SENDING_HDRSONLY;
     else if (reply->sline.status < HTTP_OK)
 	sending = SENDING_HDRSONLY;
-    else if (http->request->method == METHOD_HEAD)
+    else if (http->request->method->code == METHOD_HEAD)
 	sending = SENDING_HDRSONLY;
     else
 	sending = SENDING_BODY;
Index: squid/src/enums.h
===================================================================
--- squid.orig/src/enums.h	2008-08-12 14:59:36.383655000 +1000
+++ squid/src/enums.h	2008-08-12 15:16:30.000000000 +1000
@@ -394,7 +394,7 @@
     STORE_DISK_CLIENT
 } store_client_t;
 
-enum {
+typedef enum {
     METHOD_NONE,		/* 000 */
     METHOD_GET,			/* 001 */
     METHOD_POST,		/* 010 */
@@ -425,30 +425,8 @@
     METHOD_MKACTIVITY,
     METHOD_CHECKOUT,
     METHOD_MERGE,
-    /* Extension methods must be last, Add any new methods before this line */
-    METHOD_EXT00,
-    METHOD_EXT01,
-    METHOD_EXT02,
-    METHOD_EXT03,
-    METHOD_EXT04,
-    METHOD_EXT05,
-    METHOD_EXT06,
-    METHOD_EXT07,
-    METHOD_EXT08,
-    METHOD_EXT09,
-    METHOD_EXT10,
-    METHOD_EXT11,
-    METHOD_EXT12,
-    METHOD_EXT13,
-    METHOD_EXT14,
-    METHOD_EXT15,
-    METHOD_EXT16,
-    METHOD_EXT17,
-    METHOD_EXT18,
-    METHOD_EXT19,
-    METHOD_ENUM_END
-};
-typedef unsigned int method_t;
+    METHOD_OTHER,
+} method_code_t;
 
 typedef enum {
     PROTO_NONE,
Index: squid/src/errormap.c
===================================================================
--- squid.orig/src/errormap.c	2008-08-12 14:59:36.383737000 +1000
+++ squid/src/errormap.c	2008-08-12 15:16:30.000000000 +1000
@@ -169,7 +169,7 @@
     errorUrl = getErrorMap(map, status, squid_error, aclname);
     if (!errorUrl)
 	return 0;
-    req = urlParse(METHOD_GET, (char *) errorUrl);
+    req = urlParse(urlMethodGetKnownByCode(METHOD_GET), (char *) errorUrl);
     if (!req) {
 	debug(0, 0) ("errorMapStart: Invalid error URL '%s'\n", errorUrl);
 	return 0;
Index: squid/src/errorpage.c
===================================================================
--- squid.orig/src/errorpage.c	2008-08-12 14:59:36.383810000 +1000
+++ squid/src/errorpage.c	2008-08-12 15:16:30.000000000 +1000
@@ -526,7 +526,7 @@
 	p = authenticateAuthUserRequestMessage(err->auth_user_request) ? authenticateAuthUserRequestMessage(err->auth_user_request) : "[not available]";
 	break;
     case 'M':
-	p = r ? RequestMethods[r->method].str : "[unknown method]";
+	p = r ? r->method->string : "[unknown method]";
 	break;
     case 'o':
 	p = external_acl_message;
@@ -547,7 +547,7 @@
 	if (NULL != r) {
 	    Packer p;
 	    memBufPrintf(&mb, "%s %s HTTP/%d.%d\n",
-		RequestMethods[r->method].str,
+		r->method->string,
 		strLen(r->urlpath) ? strBuf(r->urlpath) : "/",
 		r->http_ver.major, r->http_ver.minor);
 	    packerToMemInit(&p, &mb);
Index: squid/src/external_acl.c
===================================================================
--- squid.orig/src/external_acl.c	2008-08-12 14:59:36.383886000 +1000
+++ squid/src/external_acl.c	2008-08-12 15:16:30.000000000 +1000
@@ -673,7 +673,7 @@
 	    str = strBuf(request->urlpath);
 	    break;
 	case EXT_ACL_METHOD:
-	    str = RequestMethods[request->method].str;
+	    str = request->method->string;
 	    break;
 	case EXT_ACL_HEADER:
 	    sb = httpHeaderGetByName(&request->header, format->header);
Index: squid/src/forward.c
===================================================================
--- squid.orig/src/forward.c	2008-08-12 14:59:36.383962000 +1000
+++ squid/src/forward.c	2008-08-12 15:16:30.000000000 +1000
@@ -160,7 +160,7 @@
 	return 0;
 
     /* RFC2616 9.1 Safe and Idempotent Methods */
-    switch (fwdState->request->method) {
+    switch (fwdState->request->method->code) {
 	/* 9.1.1 Safe Methods */
     case METHOD_GET:
     case METHOD_HEAD:
@@ -759,9 +759,7 @@
     int server_fd = fwdState->server_fd;
     FwdServer *fs = fwdState->servers;
     debug(17, 3) ("fwdDispatch: FD %d: Fetching '%s %s'\n",
-	fwdState->client_fd,
-	RequestMethods[request->method].str,
-	storeUrl(entry));
+	fwdState->client_fd, request->method->string, storeUrl(entry));
     /*
      * Assert that server_fd is set.  This is to guarantee that fwdState
      * is attached to something and will be deallocated when server_fd
@@ -1242,8 +1240,7 @@
     logfilePrintf(logfile, "%9d.%03d %03d %s %s\n",
 	(int) current_time.tv_sec,
 	(int) current_time.tv_usec / 1000,
-	fwdState->last_status,
-	RequestMethods[fwdState->request->method].str,
+	fwdState->last_status, fwdState->request->method->string,
 	fwdState->request->canonical);
 }
 
Index: squid/src/ftp.c
===================================================================
--- squid.orig/src/ftp.c	2008-08-12 14:59:36.384033000 +1000
+++ squid/src/ftp.c	2008-08-12 15:16:30.000000000 +1000
@@ -1121,7 +1121,7 @@
     ftpState->flags.rest_supported = 1;
     ftpState->fwd = fwd;
     comm_add_close_handler(fd, ftpStateFree, ftpState);
-    if (ftpState->request->method == METHOD_PUT)
+    if (ftpState->request->method->code == METHOD_PUT)
 	ftpState->flags.put = 1;
     if (!ftpCheckAuth(ftpState, &request->header)) {
 	/* This request is not fully authenticated */
@@ -1731,7 +1731,7 @@
     int fd;
     struct sockaddr_in addr;
     socklen_t addr_len;
-    if (ftpState->request->method == METHOD_HEAD && (ftpState->flags.isdir || ftpState->size != -1)) {
+    if (ftpState->request->method->code == METHOD_HEAD && (ftpState->flags.isdir || ftpState->size != -1)) {
 	/* Terminate here for HEAD requests */
 	ftpAppendSuccessHeader(ftpState);
 	storeTimestampsSet(ftpState->entry);
Index: squid/src/globals.h
===================================================================
--- squid.orig/src/globals.h	2008-08-12 14:59:36.384116000 +1000
+++ squid/src/globals.h	2008-08-12 15:16:30.000000000 +1000
@@ -48,8 +48,6 @@
 extern char config_input_line[BUFSIZ];
 extern const char *AclMatchedName;	/* NULL */
 extern const char *DefaultConfigFile;	/* DEFAULT_CONFIG_FILE */
-extern rms_t RequestMethods[];
-extern const char *RequestMethodStr[];
 extern const char *ProtocolStr[];
 extern const char *cfg_filename;	/* NULL */
 extern const char *const appname;	/* "squid" */
Index: squid/src/htcp.c
===================================================================
--- squid.orig/src/htcp.c	2008-08-12 14:59:36.384192000 +1000
+++ squid/src/htcp.c	2008-08-12 15:16:30.000000000 +1000
@@ -479,7 +479,7 @@
 htcpUnpackSpecifier(char *buf, int sz)
 {
     htcpSpecifier *s = memPoolAlloc(htcpSpecifierPool);
-    method_t method;
+    method_t *method;
 
     /* Find length of METHOD */
     u_short l = ntohs(*(u_short *) buf);
@@ -553,8 +553,11 @@
     /*
      * Parse the request
      */
-    method = urlParseMethod(s->method, strlen(s->method));
-    s->request = urlParse(method == METHOD_NONE ? METHOD_GET : method, s->uri);
+    method = urlMethodGetKnown(s->method, strlen(s->method));
+    if (method == NULL) {
+        method = urlMethodGetKnownByCode(METHOD_GET);
+    }
+    s->request = urlParse(method, s->uri);
     return s;
 }
 
@@ -1178,7 +1181,7 @@
     stuff.f1 = 1;
     stuff.response = 0;
     stuff.msg_id = ++msg_id_counter;
-    stuff.S.method = (char *) RequestMethods[req->method].str;
+    stuff.S.method = (char *) req->method->string;
     stuff.S.uri = (char *) storeUrl(e);
     stuff.S.version = vbuf;
     httpBuildRequestHeader(req, req, e, &hdr, flags);
Index: squid/src/http.c
===================================================================
--- squid.orig/src/http.c	2008-08-12 14:59:36.384273000 +1000
+++ squid/src/http.c	2008-08-12 15:16:53.243538000 +1000
@@ -85,13 +85,10 @@
 }
 
 int
-httpCachable(method_t method)
+httpCachable(method_t *method)
 {
-    /* GET and HEAD are cachable. Others are not. */
-    if (method != METHOD_GET && method != METHOD_HEAD)
-	return 0;
-    /* else cachable */
-    return 1;
+
+    return (method->flags.cachable);
 }
 
 static void
@@ -141,6 +138,9 @@
     int remove = 0;
     int forbidden = 0;
     StoreEntry *pe;
+    method_t *method_get, *method_head;
+    method_get = urlMethodGetKnownByCode(METHOD_GET);
+    method_head = urlMethodGetKnownByCode(METHOD_HEAD);
     switch (status) {
     case HTTP_OK:
     case HTTP_NON_AUTHORITATIVE_INFORMATION:
@@ -188,15 +188,15 @@
      * changed.
      */
     if (e->mem_obj->request)
-	pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_HEAD);
+	pe = storeGetPublicByRequestMethod(e->mem_obj->request, method_head);
     else
-	pe = storeGetPublic(e->mem_obj->url, METHOD_HEAD);
+	pe = storeGetPublic(e->mem_obj->url, method_head);
     if (pe != NULL && e != pe) {
 	storeRelease(pe);
     }
     if (forbidden)
 	return;
-    switch (e->mem_obj->method) {
+    switch (e->mem_obj->method->code) {
     case METHOD_PUT:
     case METHOD_DELETE:
     case METHOD_PROPPATCH:
@@ -209,14 +209,16 @@
 	 * object may have changed as a result of other methods
 	 */
 	if (e->mem_obj->request)
-	    pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_GET);
+	    pe = storeGetPublicByRequestMethod(e->mem_obj->request, method_get);
 	else
-	    pe = storeGetPublic(e->mem_obj->url, METHOD_GET);
+	    pe = storeGetPublic(e->mem_obj->url, method_get);
 	if (pe != NULL) {
 	    assert(e != pe);
 	    storeRelease(pe);
 	}
 	break;
+    default:
+        break;
     }
 }
 
@@ -229,7 +231,7 @@
     const char *v;
 #if HTTP_VIOLATIONS
     const refresh_t *R = NULL;
-    /* This strange looking define first looks up the frefresh pattern
+    /* This strange looking define first looks up the refresh pattern
      * and then checks if the specified flag is set. The main purpose
      * of this is to simplify the refresh pattern lookup
      */
@@ -772,7 +774,7 @@
     if (len > 0) {
 	debug(11, Config.onoff.relaxed_header_parser <= 0 || keep_alive ? 1 : 2)
 	    ("httpReadReply: Excess data from \"%s %s\"\n",
-	    RequestMethods[orig_request->method].str,
+	    orig_request->method->string,
 	    storeUrl(entry));
 	comm_close(fd);
 	return;
@@ -793,7 +795,7 @@
      */
     if (!httpState->flags.request_sent) {
 	debug(11, 1) ("httpAppendBody: Request not yet fully sent \"%s %s\"\n",
-	    RequestMethods[orig_request->method].str,
+	    orig_request->method->string,
 	    storeUrl(entry));
 	keep_alive = 0;
     }
@@ -1180,7 +1182,7 @@
 		    httpHeaderAddClone(hdr_out, e);
 	    break;
 	case HDR_MAX_FORWARDS:
-	    if (orig_request->method == METHOD_TRACE) {
+	    if (orig_request->method->code == METHOD_TRACE) {
 		/* sacrificing efficiency over clarity, etc. */
 		const int hops = httpHeaderGetInt(hdr_in, HDR_MAX_FORWARDS);
 		if (hops > 0)
@@ -1398,8 +1400,7 @@
     http_state_flags flags)
 {
     const int offset = mb->size;
-    memBufPrintf(mb, "%s %s HTTP/1.%d\r\n",
-	RequestMethods[request->method].str,
+    memBufPrintf(mb, "%s %s HTTP/1.%d\r\n", request->method->string,
 	strLen(request->urlpath) ? strBuf(request->urlpath) : "/",
 	flags.http11);
     /* build and pack headers */
@@ -1491,8 +1492,7 @@
     HttpStateData *httpState;
     request_t *proxy_req;
     request_t *orig_req = fwd->request;
-    debug(11, 3) ("httpStart: \"%s %s\"\n",
-	RequestMethods[orig_req->method].str,
+    debug(11, 3) ("httpStart: \"%s %s\"\n", orig_req->method->string,
 	storeUrl(fwd->entry));
     httpState = cbdataAlloc(HttpStateData);
     storeLockObject(fwd->entry);
Index: squid/src/icp_v2.c
===================================================================
--- squid.orig/src/icp_v2.c	2008-08-12 14:59:36.384346000 +1000
+++ squid/src/icp_v2.c	2008-08-12 15:16:30.000000000 +1000
@@ -193,7 +193,9 @@
     u_num32 flags = 0;
     int rtt = 0;
     int hops = 0;
+    method_t *method_get;
     xmemcpy(&header, buf, sizeof(icp_common_t));
+    method_get = urlMethodGetKnownByCode(METHOD_GET);
     /*
      * Only these fields need to be converted
      */
@@ -218,7 +220,7 @@
 	    icpUdpSend(fd, &from, reply, LOG_UDP_INVALID, 0);
 	    break;
 	}
-	if ((icp_request = urlParse(METHOD_GET, url)) == NULL) {
+	if ((icp_request = urlParse(method_get, url)) == NULL) {
 	    reply = icpCreateMessage(ICP_ERR, 0, url, header.reqnum, 0);
 	    icpUdpSend(fd, &from, reply, LOG_UDP_INVALID, 0);
 	    break;
@@ -251,7 +253,7 @@
 		flags |= ICP_FLAG_SRC_RTT;
 	}
 	/* The peer is allowed to use this cache */
-	entry = storeGetPublic(url, METHOD_GET);
+	entry = storeGetPublic(url, method_get);
 	debug(12, 5) ("icpHandleIcpV2: OPCODE %s\n", icp_opcode_str[header.opcode]);
 	if (icpCheckUdpHit(entry, icp_request)) {
 	    reply = icpCreateMessage(ICP_HIT, flags, url, header.reqnum, src_rtt);
@@ -560,5 +562,5 @@
 {
     if (neighbors_do_private_keys && reqnum)
 	return queried_keys[reqnum & N_QUERIED_KEYS_MASK];
-    return storeKeyPublic(url, METHOD_GET);
+    return storeKeyPublic(url, urlMethodGetKnownByCode(METHOD_GET));
 }
Index: squid/src/icp_v3.c
===================================================================
--- squid.orig/src/icp_v3.c	2008-08-12 14:59:36.384418000 +1000
+++ squid/src/icp_v3.c	2008-08-12 15:16:30.000000000 +1000
@@ -47,7 +47,9 @@
     request_t *icp_request = NULL;
     int allow = 0;
     aclCheck_t checklist;
+    method_t *method_get;
     xmemcpy(&header, buf, sizeof(icp_common_t));
+    method_get = urlMethodGetKnownByCode(METHOD_GET);
     /*
      * Only these fields need to be converted
      */
@@ -72,7 +74,7 @@
 	    icpUdpSend(fd, &from, reply, LOG_UDP_INVALID, 0);
 	    break;
 	}
-	if ((icp_request = urlParse(METHOD_GET, url)) == NULL) {
+	if ((icp_request = urlParse(method_get, url)) == NULL) {
 	    reply = icpCreateMessage(ICP_ERR, 0, url, header.reqnum, 0);
 	    icpUdpSend(fd, &from, reply, LOG_UDP_INVALID, 0);
 	    break;
@@ -98,7 +100,7 @@
 	    break;
 	}
 	/* The peer is allowed to use this cache */
-	entry = storeGetPublic(url, METHOD_GET);
+	entry = storeGetPublic(url, method_get);
 	debug(12, 5) ("icpHandleIcpV3: OPCODE %s\n",
 	    icp_opcode_str[header.opcode]);
 	if (icpCheckUdpHit(entry, icp_request)) {
Index: squid/src/mime.c
===================================================================
--- squid.orig/src/mime.c	2008-08-12 14:59:36.384490000 +1000
+++ squid/src/mime.c	2008-08-12 15:16:30.000000000 +1000
@@ -407,11 +407,13 @@
     const char *type = mimeGetContentType(icon);
     HttpReply *reply;
     request_t *r;
+    method_t *method_get;
     if (type == NULL)
 	fatal("Unknown icon format while reading mime.conf\n");
+    method_get = urlMethodGetKnownByCode(METHOD_GET);
     buf = internalStoreUri("/squid-internal-static/icons/", icon);
     xstrncpy(url, buf, MAX_URL);
-    if (storeGetPublic(url, METHOD_GET))
+    if (storeGetPublic(url, method_get))
 	return;
     snprintf(path, MAXPATHLEN, "%s/%s", Config.icons.directory, icon);
     fd = file_open(path, O_RDONLY | O_BINARY);
@@ -426,12 +428,12 @@
     }
     flags = null_request_flags;
     flags.cachable = 1;
-    e = storeCreateEntry(url, flags, METHOD_GET);
+    e = storeCreateEntry(url, flags, method_get);
     assert(e != NULL);
     EBIT_SET(e->flags, ENTRY_SPECIAL);
     storeSetPublicKey(e);
     storeBuffer(e);
-    r = urlParse(METHOD_GET, url);
+    r = urlParse(method_get, url);
     if (NULL == r)
 	fatal("mimeLoadIcon: cannot parse internal URL");
     e->mem_obj->request = requestLink(r);
Index: squid/src/neighbors.c
===================================================================
--- squid.orig/src/neighbors.c	2008-08-12 14:59:36.384564000 +1000
+++ squid/src/neighbors.c	2008-08-12 15:16:30.000000000 +1000
@@ -1207,13 +1207,15 @@
     MemObject *mem;
     icp_common_t *query;
     int reqnum;
+    method_t *method_get;
     LOCAL_ARRAY(char, url, MAX_URL);
     assert(p->type == PEER_MULTICAST);
+    method_get = urlMethodGetKnownByCode(METHOD_GET);
     p->mcast.flags.count_event_pending = 0;
     snprintf(url, MAX_URL, "http://%s/", inet_ntoa(p->in_addr.sin_addr));
-    fake = storeCreateEntry(url, null_request_flags, METHOD_GET);
+    fake = storeCreateEntry(url, null_request_flags, method_get);
     psstate = cbdataAlloc(ps_state);
-    psstate->request = requestLink(urlParse(METHOD_GET, url));
+    psstate->request = requestLink(urlParse(method_get, url));
     psstate->entry = fake;
     psstate->callback = NULL;
     psstate->callback_data = p;
Index: squid/src/net_db.c
===================================================================
--- squid.orig/src/net_db.c	2008-08-12 14:59:36.384636000 +1000
+++ squid/src/net_db.c	2008-08-12 15:16:30.000000000 +1000
@@ -978,6 +978,7 @@
     peer *p = data;
     char *uri;
     netdbExchangeState *ex;
+    method_t *method_get;
     CBDATA_INIT_TYPE(netdbExchangeState);
     ex = cbdataAlloc(netdbExchangeState);
     cbdataLock(p);
@@ -985,7 +986,8 @@
     uri = internalRemoteUri(p->host, p->http_port, "/squid-internal-dynamic/", "netdb");
     debug(38, 3) ("netdbExchangeStart: Requesting '%s'\n", uri);
     assert(NULL != uri);
-    ex->r = urlParse(METHOD_GET, uri);
+    method_get = urlMethodGetKnownByCode(METHOD_GET);
+    ex->r = urlParse(method_get, uri);
     if (NULL == ex->r) {
 	debug(38, 1) ("netdbExchangeStart: Bad URI %s\n", uri);
 	return;
@@ -993,7 +995,7 @@
     requestLink(ex->r);
     assert(NULL != ex->r);
     httpBuildVersion(&ex->r->http_ver, 1, 0);
-    ex->e = storeCreateEntry(uri, null_request_flags, METHOD_GET);
+    ex->e = storeCreateEntry(uri, null_request_flags, method_get);
     assert(NULL != ex->e);
     ex->sc = storeClientRegister(ex->e, ex);
     storeClientRef(ex->sc, ex->e, ex->seen, ex->used, SM_PAGE_SIZE,
Index: squid/src/peer_digest.c
===================================================================
--- squid.orig/src/peer_digest.c	2008-08-12 15:16:24.000000000 +1000
+++ squid/src/peer_digest.c	2008-08-12 15:16:30.000000000 +1000
@@ -285,7 +285,7 @@
 	url = internalRemoteUri(p->host, p->http_port,
 	    "/squid-internal-periodic/", StoreDigestFileName);
 
-    req = urlParse(METHOD_GET, url);
+    req = urlParse(urlMethodGetKnownByCode(METHOD_GET), url);
     assert(req);
     key = storeKeyPublicByRequest(req);
     debug(72, 2) ("peerDigestRequest: %s key: %s\n", url, storeKeyText(key));
Index: squid/src/peer_monitor.c
===================================================================
--- squid.orig/src/peer_monitor.c	2008-08-12 14:59:36.384780000 +1000
+++ squid/src/peer_monitor.c	2008-08-12 15:16:30.000000000 +1000
@@ -151,7 +151,7 @@
 	cbdataFree(pm);
 	return;
     }
-    req = urlParse(METHOD_GET, url);
+    req = urlParse(urlMethodGetKnownByCode(METHOD_GET), url);
     if (!req) {
 	debug(DBG, 1) ("peerMonitorRequest: Failed to parse URL '%s' for cache_peer %s\n", url, pm->peer->name);
 	cbdataFree(pm);
Index: squid/src/peer_select.c
===================================================================
--- squid.orig/src/peer_select.c	2008-08-12 14:59:36.384860000 +1000
+++ squid/src/peer_select.c	2008-08-12 15:16:30.000000000 +1000
@@ -139,7 +139,7 @@
     if (entry)
 	debug(44, 3) ("peerSelect: %s\n", storeUrl(entry));
     else
-	debug(44, 3) ("peerSelect: %s\n", RequestMethods[request->method].str);
+	debug(44, 3) ("peerSelect: %s\n", request->method->string);
     psstate = cbdataAlloc(ps_state);
     psstate->request = requestLink(request);
     psstate->entry = entry;
@@ -238,8 +238,7 @@
 {
     StoreEntry *entry = ps->entry;
     request_t *request = ps->request;
-    debug(44, 3) ("peerSelectFoo: '%s %s'\n",
-	RequestMethods[request->method].str,
+    debug(44, 3) ("peerSelectFoo: '%s %s'\n", request->method->string,
 	request->host);
     if (ps->direct == DIRECT_UNKNOWN) {
 	if (ps->always_direct == 0 && Config.accessList.AlwaysDirect) {
@@ -459,8 +458,7 @@
     peer *p;
     request_t *request = ps->request;
     hier_code code = HIER_NONE;
-    debug(44, 3) ("peerGetSomeParent: %s %s\n",
-	RequestMethods[request->method].str,
+    debug(44, 3) ("peerGetSomeParent: %s %s\n", request->method->string,
 	request->host);
     if (ps->direct == DIRECT_YES)
 	return;
Index: squid/src/protos.h
===================================================================
--- squid.orig/src/protos.h	2008-08-12 15:16:24.000000000 +1000
+++ squid/src/protos.h	2008-08-12 15:16:53.243684000 +1000
@@ -48,7 +48,7 @@
 extern void fvdbCountForw(const char *key);
 #endif
 #if HEADERS_LOG
-extern void headersLog(int cs, int pq, method_t m, void *data);
+extern void headersLog(int cs, int pq, method_t *m, void *data);
 #endif
 char *log_quote(const char *header);
 
@@ -324,7 +324,7 @@
 extern void whoisStart(FwdState *);
 
 /* http.c */
-extern int httpCachable(method_t);
+extern int httpCachable(method_t *);
 extern void httpStart(FwdState *);
 extern int httpBuildRequestPrefix(request_t * request,
     request_t * orig_request,
@@ -528,12 +528,12 @@
 extern time_t httpReplyExpires(const HttpReply * rep);
 extern int httpReplyHasCc(const HttpReply * rep, http_hdr_cc_type type);
 extern void httpRedirectReply(HttpReply *, http_status, const char *);
-extern squid_off_t httpReplyBodySize(method_t, const HttpReply *);
-extern squid_off_t httpDelayBodySize(method_t, const HttpReply *);
+extern squid_off_t httpReplyBodySize(method_t *, const HttpReply *);
+extern squid_off_t httpDelayBodySize(method_t *, const HttpReply *);
 extern HttpReply *httpReplyClone(HttpReply * src);
 
 /* Http Request */
-extern request_t *requestCreate(method_t, protocol_t, const char *urlpath);
+extern request_t *requestCreate(method_t *, protocol_t, const char *urlpath);
 extern void requestDestroy(request_t *);
 extern request_t *requestLink(request_t *);
 extern void requestUnlink(request_t *);
@@ -938,10 +938,12 @@
 extern StoreEntry *new_StoreEntry(int, const char *);
 extern void storeEntrySetStoreUrl(StoreEntry * e, const char *store_url);
 extern StoreEntry *storeGet(const cache_key *);
-extern StoreEntry *storeGetPublic(const char *uri, const method_t method);
+extern StoreEntry *storeGetPublic(const char *uri, const method_t *method);
+extern StoreEntry *storeGetPublicByCode(const char *uri, const method_code_t code);
 extern StoreEntry *storeGetPublicByRequest(request_t * request);
-extern StoreEntry *storeGetPublicByRequestMethod(request_t * request, const method_t method);
-extern StoreEntry *storeCreateEntry(const char *, request_flags, method_t);
+extern StoreEntry *storeGetPublicByRequestMethod(request_t * request, const method_t *method);
+extern StoreEntry *storeGetPublicByRequestMethodCode(request_t * request, const method_code_t code);
+extern StoreEntry *storeCreateEntry(const char *, request_flags, method_t *);
 extern void storeSetPublicKey(StoreEntry *);
 extern void storeComplete(StoreEntry *);
 extern void storeRequestFailed(StoreEntry *, ErrorState * err);
@@ -1035,10 +1037,10 @@
 extern void storeKeyFree(const cache_key *);
 extern const cache_key *storeKeyScan(const char *);
 extern const char *storeKeyText(const cache_key *);
-extern const cache_key *storeKeyPublic(const char *, const method_t);
+extern const cache_key *storeKeyPublic(const char *, const method_t *);
 extern const cache_key *storeKeyPublicByRequest(request_t *);
-extern const cache_key *storeKeyPublicByRequestMethod(request_t *, const method_t);
-extern const cache_key *storeKeyPrivate(const char *, method_t, int);
+extern const cache_key *storeKeyPublicByRequestMethod(request_t *, const method_t *);
+extern const cache_key *storeKeyPrivate(const char *, method_t *, int);
 extern int storeKeyHashBuckets(int);
 extern int storeKeyNull(const cache_key *);
 extern void storeKeyInit(void);
@@ -1178,9 +1180,13 @@
 extern char *url_convert_hex(char *org_url, int allocate);
 extern char *url_escape(const char *url);
 extern protocol_t urlParseProtocol(const char *);
-extern method_t urlParseMethod(const char *, int len);
+extern method_t *urlMethodGet(const char *, int len);
+extern method_t *urlMethodGetKnown(const char *, int len);
+extern method_t *urlMethodGetKnownByCode(method_code_t);
+extern method_t *urlMethodDup(method_t *);
+extern void urlMethodFree(method_t *);
 extern void urlInitialize(void);
-extern request_t *urlParse(method_t, char *);
+extern request_t *urlParse(method_t *, char *);
 extern const char *urlCanonical(request_t *);
 extern char *urlRInternal(const char *host, u_short port, const char *dir, const char *name);
 extern char *urlInternal(const char *dir, const char *name);
@@ -1189,9 +1195,6 @@
 extern int urlDefaultPort(protocol_t p);
 extern char *urlCanonicalClean(const request_t *);
 extern char *urlHostname(const char *url);
-extern void parse_extension_method(rms_t(*foo)[]);
-extern void free_extension_method(rms_t(*foo)[]);
-extern void dump_extension_method(StoreEntry * entry, const char *name, rms_t * methods);
 
 extern void useragentOpenLog(void);
 extern void useragentRotateLog(void);
@@ -1480,7 +1483,7 @@
 /* ETag support */
 void storeLocateVaryDone(VaryData * data);
 void storeLocateVary(StoreEntry * e, int offset, const char *vary_data, String accept_encoding, STLVCB * callback, void *cbdata);
-void storeAddVary(const char *url, const method_t method, const cache_key * key, const char *etag, const char *vary, const char *vary_headers, const char *accept_encoding);
+void storeAddVary(const char *url, method_t *method, const cache_key * key, const char *etag, const char *vary, const char *vary_headers, const char *accept_encoding);
 
 rewritetoken *rewriteURLCompile(const char *urlfmt);
 char *internalRedirectProcessURL(clientHttpRequest * req, rewritetoken * head);
Index: squid/src/redirect.c
===================================================================
--- squid.orig/src/redirect.c	2008-08-12 14:59:36.385012000 +1000
+++ squid/src/redirect.c	2008-08-12 15:16:30.000000000 +1000
@@ -126,7 +126,7 @@
 #endif
     if (!r->client_ident)
 	r->client_ident = dash_str;
-    r->method_s = RequestMethods[http->request->method].str;
+    r->method_s = http->request->method->string;
     r->handler = handler;
     r->data = data;
     cbdataLock(r->data);
@@ -421,7 +421,7 @@
 	    str = req->request->extacl_user;
 	    break;
 	case RFT_METHOD:
-	    str = RequestMethods[req->request->method].str;
+	    str = req->request->method->string;
 	    break;
 	case RFT_PROTOCOL:
 	    str = ProtocolStr[req->request->protocol];
Index: squid/src/ssl.c
===================================================================
--- squid.orig/src/ssl.c	2008-08-12 15:16:24.000000000 +1000
+++ squid/src/ssl.c	2008-08-12 15:16:30.000000000 +1000
@@ -516,8 +516,7 @@
 	    return;
 	}
     }
-    debug(26, 3) ("sslStart: '%s %s'\n",
-	RequestMethods[request->method].str, url);
+    debug(26, 3) ("sslStart: '%s %s'\n", request->method->string, url);
     statCounter.server.all.requests++;
     statCounter.server.other.requests++;
     outgoing = getOutgoingAddr(request);
Index: squid/src/stat.c
===================================================================
--- squid.orig/src/stat.c	2008-08-12 15:16:24.000000000 +1000
+++ squid/src/stat.c	2008-08-12 15:16:30.000000000 +1000
@@ -249,8 +249,7 @@
     memBufPrintf(mb, "KEY %s\n", storeKeyText(e->hash.key));
     /* XXX should this url be escaped? */
     if (mem)
-	memBufPrintf(mb, "\t%s %s\n",
-	    RequestMethods[mem->method].str, mem->url);
+	memBufPrintf(mb, "\t%s %s\n", mem->method->string, mem->url);
     if (mem && mem->store_url)
 	memBufPrintf(mb, "\tStore lookup URL: %s\n", mem->store_url);
     memBufPrintf(mb, "\t%s\n", describeStatuses(e));
Index: squid/src/store.c
===================================================================
--- squid.orig/src/store.c	2008-08-12 15:16:24.000000000 +1000
+++ squid/src/store.c	2008-08-12 15:16:53.243813000 +1000
@@ -172,6 +172,7 @@
     assert(mem->chksum == url_checksum(mem->url));
 #endif
     e->mem_obj = NULL;
+    urlMethodFree(mem->method);
     if (!shutting_down)
 	assert(mem->swapout.sio == NULL);
     stmemFree(&mem->data_hdr);
@@ -347,18 +348,32 @@
 StoreEntry *
 storeGet(const cache_key * key)
 {
-    debug(20, 3) ("storeGet: looking up %s\n", storeKeyText(key));
-    return (StoreEntry *) hash_lookup(store_table, key);
+    StoreEntry *e = (StoreEntry *) hash_lookup(store_table, key);
+    debug(20, 3) ("storeGet: %s -> %p\n", storeKeyText(key), e);
+    return e;
 }
 
 StoreEntry *
-storeGetPublic(const char *uri, const method_t method)
+storeGetPublic(const char *uri, const method_t *method)
 {
     return storeGet(storeKeyPublic(uri, method));
 }
 
 StoreEntry *
-storeGetPublicByRequestMethod(request_t * req, const method_t method)
+storeGetPublicByCode(const char *uri, const method_code_t code)
+{
+	method_t	*method;
+
+	method = urlMethodGetKnownByCode(code);
+	if (method == NULL) {
+		return (NULL);
+	}
+
+	return storeGetPublic(uri, method);
+}
+
+StoreEntry *
+storeGetPublicByRequestMethod(request_t * req, const method_t *method)
 {
     if (req->vary) {
 	/* Varying objects... */
@@ -371,12 +386,25 @@
 }
 
 StoreEntry *
+storeGetPublicByRequestMethodCode(request_t * req, const method_code_t code)
+{
+	method_t	*method;
+
+	method = urlMethodGetKnownByCode(code);
+	if (method == NULL) {
+		return (NULL);
+	}
+
+	return storeGetPublicByRequestMethod(req, method);
+}
+
+StoreEntry *
 storeGetPublicByRequest(request_t * req)
 {
     StoreEntry *e = storeGetPublicByRequestMethod(req, req->method);
-    if (e == NULL && req->method == METHOD_HEAD)
+    if (e == NULL && req->method->code == METHOD_HEAD)
 	/* We can generate a HEAD reply from a cached GET object */
-	e = storeGetPublicByRequestMethod(req, METHOD_GET);
+	e = storeGetPublicByRequestMethodCode(req, METHOD_GET);
     return e;
 }
 
@@ -405,7 +433,7 @@
 	mem->id = getKeyCounter();
 	newkey = storeKeyPrivate(mem->url, mem->method, mem->id);
     } else {
-	newkey = storeKeyPrivate("JUNK", METHOD_NONE, getKeyCounter());
+	newkey = storeKeyPrivate("JUNK", NULL, getKeyCounter());
     }
     assert(hash_lookup(store_table, newkey) == NULL);
     EBIT_SET(e->flags, KEY_PRIVATE);
@@ -720,7 +748,7 @@
  * At leas one of key or etag must be specified, preferably both.
  */
 void
-storeAddVary(const char *url, const method_t method, const cache_key * key, const char *etag, const char *vary, const char *vary_headers, const char *accept_encoding)
+storeAddVary(const char *url, method_t *method, const cache_key * key, const char *etag, const char *vary, const char *vary_headers, const char *accept_encoding)
 {
     AddVaryState *state;
     request_flags flags = null_request_flags;
@@ -1094,7 +1122,7 @@
 }
 
 StoreEntry *
-storeCreateEntry(const char *url, request_flags flags, method_t method)
+storeCreateEntry(const char *url, request_flags flags, method_t *method)
 {
     StoreEntry *e = NULL;
     MemObject *mem = NULL;
@@ -1103,7 +1131,7 @@
     e = new_StoreEntry(STORE_ENTRY_WITH_MEMOBJ, url);
     e->lock_count = 1;		/* Note lock here w/o calling storeLock() */
     mem = e->mem_obj;
-    mem->method = method;
+    mem->method = urlMethodDup(method);
     if (neighbors_do_private_keys || !flags.hierarchical)
 	storeSetPrivateKey(e);
     else
Index: squid/src/store_digest.c
===================================================================
--- squid.orig/src/store_digest.c	2008-08-12 14:59:36.385308000 +1000
+++ squid/src/store_digest.c	2008-08-12 15:16:30.000000000 +1000
@@ -338,8 +338,10 @@
     request_flags flags;
     char *url;
     StoreEntry *e;
+    method_t *method_get;
 
     assert(store_digest);
+    method_get = urlMethodGetKnownByCode(METHOD_GET);
     /* prevent overlapping if rewrite schedule is too tight */
     if (sd_state.rewrite_lock) {
 	debug(71, 1) ("storeDigestRewriteStart: overlap detected, consider increasing rewrite period\n");
@@ -350,12 +352,12 @@
     url = internalStoreUri("/squid-internal-periodic/", StoreDigestFileName);
     flags = null_request_flags;
     flags.cachable = 1;
-    e = storeCreateEntry(url, flags, METHOD_GET);
+    e = storeCreateEntry(url, flags, method_get);
     assert(e);
     sd_state.rewrite_lock = cbdataAlloc(generic_cbdata);
     sd_state.rewrite_lock->data = e;
     debug(71, 3) ("storeDigestRewriteStart: url: %s key: %s\n", url, storeKeyText(e->hash.key));
-    e->mem_obj->request = requestLink(urlParse(METHOD_GET, url));
+    e->mem_obj->request = requestLink(urlParse(method_get, url));
     /* wait for rebuild (if any) to finish */
     if (sd_state.rebuild_lock) {
 	debug(71, 2) ("storeDigestRewriteStart: waiting for rebuild to finish.\n");
Index: squid/src/store_key_md5.c
===================================================================
--- squid.orig/src/store_key_md5.c	2008-08-12 14:59:36.385379000 +1000
+++ squid/src/store_key_md5.c	2008-08-12 15:16:30.000000000 +1000
@@ -92,27 +92,36 @@
 }
 
 const cache_key *
-storeKeyPrivate(const char *url, method_t method, int id)
+storeKeyPrivate(const char *url, method_t *method, int id)
 {
     static cache_key digest[SQUID_MD5_DIGEST_LENGTH];
+    int zero = 0;
     SQUID_MD5_CTX M;
     assert(id > 0);
-    debug(20, 3) ("storeKeyPrivate: %s %s\n",
-	RequestMethods[method].str, url);
+    debug(20, 3) ("storeKeyPrivate: %s %s\n", method->string, url);
     SQUID_MD5Init(&M);
     SQUID_MD5Update(&M, (unsigned char *) &id, sizeof(id));
-    SQUID_MD5Update(&M, (unsigned char *) &method, sizeof(method));
+    if (method == NULL) {
+        SQUID_MD5Update(&M, (unsigned char *)&zero, sizeof(int));
+    } else {
+        SQUID_MD5Update(&M, (unsigned char *) &method->code, sizeof(method->code));
+    }
     SQUID_MD5Update(&M, (unsigned char *) url, strlen(url));
     SQUID_MD5Final(digest, &M);
     return digest;
 }
 
 const cache_key *
-storeKeyPublic(const char *url, const method_t method)
+storeKeyPublic(const char *url, const method_t *method)
 {
     static cache_key digest[SQUID_MD5_DIGEST_LENGTH];
-    unsigned char m = (unsigned char) method;
+    unsigned char m;
     SQUID_MD5_CTX M;
+    if (method == NULL) {
+	m = 0;
+    } else {
+        m = (unsigned char) method->code;
+    }
     SQUID_MD5Init(&M);
     SQUID_MD5Update(&M, &m, sizeof(m));
     SQUID_MD5Update(&M, (unsigned char *) url, strlen(url));
@@ -127,13 +136,19 @@
 }
 
 const cache_key *
-storeKeyPublicByRequestMethod(request_t * request, const method_t method)
+storeKeyPublicByRequestMethod(request_t * request, const method_t *method)
 {
     static cache_key digest[SQUID_MD5_DIGEST_LENGTH];
-    unsigned char m = (unsigned char) method;
+    unsigned char m;
     const char *url;
     SQUID_MD5_CTX M;
 
+    if (method == NULL) {
+	m = 0;
+    } else {
+        m = (unsigned char) method->code;
+    }
+
     if (request->store_url) {
 	url = request->store_url;
     } else {
Index: squid/src/store_log.c
===================================================================
--- squid.orig/src/store_log.c	2008-08-12 14:59:36.385456000 +1000
+++ squid/src/store_log.c	2008-08-12 15:16:30.000000000 +1000
@@ -79,7 +79,7 @@
 	    strLen(reply->content_type) ? strBuf(reply->content_type) : "unknown",
 	    reply->content_length,
 	    mem->inmem_hi - mem->reply->hdr_sz,
-	    RequestMethods[mem->method].str,
+	    mem->method->string,
 	    rfc1738_escape_unescaped(mem->url));
 	logfileLineEnd(storelog);
     } else {
Index: squid/src/store_rewrite.c
===================================================================
--- squid.orig/src/store_rewrite.c	2008-08-12 14:59:36.385528000 +1000
+++ squid/src/store_rewrite.c	2008-08-12 15:16:30.000000000 +1000
@@ -126,7 +126,7 @@
 #endif
     if (!r->client_ident)
 	r->client_ident = dash_str;
-    r->method_s = RequestMethods[http->request->method].str;
+    r->method_s = http->request->method->string;
     r->handler = handler;
     r->data = data;
     cbdataLock(r->data);
Index: squid/src/structs.h
===================================================================
--- squid.orig/src/structs.h	2008-08-12 15:16:24.000000000 +1000
+++ squid/src/structs.h	2008-08-12 15:16:30.000000000 +1000
@@ -1206,10 +1206,19 @@
     struct timeval store_complete_stop;
 };
 
+struct _method_t {
+	method_code_t	code;
+	char *		string;
+	struct {
+		unsigned int	cachable:1;
+		unsigned int	purges_all:1;
+	} flags;
+};
+
 struct _AccessLogEntry {
     const char *url;
     struct {
-	method_t method;
+	method_t *method;
 	int code;
 	const char *content_type;
 	http_version_t version;
@@ -1755,7 +1764,7 @@
 
 /* This structure can be freed while object is purged out from memory */
 struct _MemObject {
-    method_t method;
+    method_t *method;
     char *url;
     const char *store_url;
     mem_hdr data_hdr;
@@ -1940,7 +1949,7 @@
 };
 
 struct _request_t {
-    method_t method;
+    method_t *method;
     protocol_t protocol;
     char login[MAX_LOGIN_SZ];
     char host[SQUIDHOSTNAMELEN + 1];
@@ -2613,12 +2622,6 @@
     int v_maj, v_min;
 };
 
-/* request method str stuff; should probably be a String type.. */
-struct rms {
-    char *str;
-    int len;
-};
-
 struct _rewritetoken {
     rewrite_token_type type;
     const char *str;
Index: squid/src/typedefs.h
===================================================================
--- squid.orig/src/typedefs.h	2008-08-12 14:59:36.385679000 +1000
+++ squid/src/typedefs.h	2008-08-12 15:16:30.000000000 +1000
@@ -185,6 +185,7 @@
 typedef struct _header_mangler header_mangler;
 typedef struct _body_size body_size;
 typedef struct _delay_body_size delay_body_size;
+typedef struct _method_t method_t;
 typedef struct _request_t request_t;
 typedef struct _AccessLogEntry AccessLogEntry;
 typedef struct _cachemgr_passwd cachemgr_passwd;
@@ -424,8 +425,6 @@
 
 typedef struct _HttpMsgBuf HttpMsgBuf;
 
-typedef struct rms rms_t;
-
 typedef void LOGLINESTART(Logfile *);
 typedef void LOGWRITE(Logfile *, const char *, size_t len);
 typedef void LOGLINEEND(Logfile *);
Index: squid/src/url.c
===================================================================
--- squid.orig/src/url.c	2008-08-12 14:59:36.385759000 +1000
+++ squid/src/url.c	2008-08-12 15:16:53.243985000 +1000
@@ -35,59 +35,47 @@
 
 #include "squid.h"
 
-rms_t RequestMethods[] =
-{
-    {(char *) "NONE", 4},
-    {(char *) "GET", 3},
-    {(char *) "POST", 4},
-    {(char *) "PUT", 3},
-    {(char *) "HEAD", 4},
-    {(char *) "CONNECT", 7},
-    {(char *) "TRACE", 5},
-    {(char *) "PURGE", 5},
-    {(char *) "OPTIONS", 7},
-    {(char *) "DELETE", 6},
-    {(char *) "PROPFIND", 8},
-    {(char *) "PROPPATCH", 9},
-    {(char *) "MKCOL", 5},
-    {(char *) "COPY", 4},
-    {(char *) "MOVE", 4},
-    {(char *) "LOCK", 4},
-    {(char *) "UNLOCK", 6},
-    {(char *) "BMOVE", 5},
-    {(char *) "BDELETE", 7},
-    {(char *) "BPROPFIND", 9},
-    {(char *) "BPROPPATCH", 10},
-    {(char *) "BCOPY", 5},
-    {(char *) "SEARCH", 6},
-    {(char *) "SUBSCRIBE", 9},
-    {(char *) "UNSUBSCRIBE", 11},
-    {(char *) "POLL", 4},
-    {(char *) "REPORT", 6},
-    {(char *) "MKACTIVITY", 10},
-    {(char *) "CHECKOUT", 8},
-    {(char *) "MERGE", 5},
-    {(char *) "%EXT00", 6},
-    {(char *) "%EXT01", 6},
-    {(char *) "%EXT02", 6},
-    {(char *) "%EXT03", 6},
-    {(char *) "%EXT04", 6},
-    {(char *) "%EXT05", 6},
-    {(char *) "%EXT06", 6},
-    {(char *) "%EXT07", 6},
-    {(char *) "%EXT08", 6},
-    {(char *) "%EXT09", 6},
-    {(char *) "%EXT10", 6},
-    {(char *) "%EXT11", 6},
-    {(char *) "%EXT12", 6},
-    {(char *) "%EXT13", 6},
-    {(char *) "%EXT14", 6},
-    {(char *) "%EXT15", 6},
-    {(char *) "%EXT16", 6},
-    {(char *) "%EXT17", 6},
-    {(char *) "%EXT18", 6},
-    {(char *) "%EXT19", 6},
-    {(char *) "ERROR", 5},
+struct rms {
+	method_t	method;
+	int		string_len;
+};
+
+/*
+ * It is currently VERY, VERY IMPORTANT that these be in order of their
+ * definition in the method_code_t enum.
+ */
+static struct rms request_methods[] = {
+	{ { METHOD_NONE, "NONE", { .cachable=0, .purges_all=0 } }, 4 },
+	{ { METHOD_GET, "GET", { .cachable=1, .purges_all=0 } }, 3 },
+	{ { METHOD_POST, "POST", { .cachable=0, .purges_all=1 } }, 4 },
+	{ { METHOD_PUT, "PUT", { .cachable=0, .purges_all=1 } }, 3 },
+	{ { METHOD_HEAD, "HEAD", { .cachable=1, .purges_all=0 } }, 4 },
+	{ { METHOD_CONNECT, "CONNECT", { .cachable=0, .purges_all=0 } }, 7 },
+	{ { METHOD_TRACE, "TRACE", { .cachable=0, .purges_all=0 } }, 5 },
+	{ { METHOD_PURGE, "PURGE", { .cachable=0, .purges_all=1 } }, 5 },
+	{ { METHOD_OPTIONS, "OPTIONS", { .cachable=0, .purges_all=0 } }, 7 },
+	{ { METHOD_DELETE, "DELETE", { .cachable=0, .purges_all=1 } }, 6 },
+	{ { METHOD_PROPFIND, "PROPFIND", { .cachable=0, .purges_all=0 } }, 8 },
+	{ { METHOD_PROPPATCH, "PROPPATCH", { .cachable=0, .purges_all=1 } }, 9 },
+	{ { METHOD_MKCOL, "MKCOL", { .cachable=0, .purges_all=1 } }, 5 },
+	{ { METHOD_COPY, "COPY", { .cachable=0, .purges_all=0 } }, 4 },
+	{ { METHOD_MOVE, "MOVE", { .cachable=0, .purges_all=1 } }, 4 },
+	{ { METHOD_LOCK, "LOCK", { .cachable=0, .purges_all=0 } }, 4 },
+	{ { METHOD_UNLOCK, "UNLOCK", { .cachable=0, .purges_all=0 } }, 6 },
+	{ { METHOD_BMOVE, "BMOVE", { .cachable=0, .purges_all=1 } }, 5 },
+	{ { METHOD_BDELETE, "BDELETE", { .cachable=0, .purges_all=1 } }, 7 },
+	{ { METHOD_BPROPFIND, "BPROPFIND", { .cachable=0, .purges_all=0 } }, 9 },
+	{ { METHOD_BPROPPATCH, "BPROPPATCH", { .cachable=0, .purges_all=0 } }, 10 },
+	{ { METHOD_BCOPY, "BCOPY", { .cachable=0, .purges_all=0 } }, 5 },
+	{ { METHOD_SEARCH, "SEARCH", { .cachable=0, .purges_all=0 } }, 6 },
+	{ { METHOD_SUBSCRIBE, "SUBSCRIBE", { .cachable=0, .purges_all=0 } }, 9 },
+	{ { METHOD_UNSUBSCRIBE, "UNSUBSCRIBE", { .cachable=0, .purges_all=0 } }, 11 },
+	{ { METHOD_POLL, "POLL", { .cachable=0, .purges_all=0 } }, 4 },
+	{ { METHOD_REPORT, "REPORT", { .cachable=0, .purges_all=0 } }, 6 },
+	{ { METHOD_MKACTIVITY, "MKACTIVITY", { .cachable=0, .purges_all=0 } }, 10 },
+	{ { METHOD_CHECKOUT, "CHECKOUT", { .cachable=0, .purges_all=0 } }, 8 },
+	{ { METHOD_MERGE, "MERGE", { .cachable=0, .purges_all=0 } }, 5 },
+	{ { METHOD_OTHER, NULL, { .cachable=0, .purges_all=0 } }, 0 },
 };
 
 const char *ProtocolStr[] =
@@ -109,7 +97,7 @@
     "TOTAL"
 };
 
-static request_t *urnParse(method_t method, char *urn);
+static request_t *urnParse(method_t *method, char *urn);
 static const char valid_hostname_chars_u[] =
 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 "abcdefghijklmnopqrstuvwxyz"
@@ -177,24 +165,105 @@
     /* more cases? */
 }
 
-method_t
-urlParseMethod(const char *s, int len)
+method_t *
+urlMethodGetKnown(const char *s, int len)
 {
-    method_t method = METHOD_NONE;
-    /*
-     * This check for '%' makes sure that we don't
-     * match one of the extension method placeholders,
-     * which have the form %EXT[0-9][0-9]
-     */
-    if (*s == '%')
-	return METHOD_NONE;
-    for (method++; method < METHOD_ENUM_END; method++) {
-	if (len == RequestMethods[method].len && 0 == strncasecmp(s, RequestMethods[method].str, len))
-	    return method;
-    }
-    return METHOD_NONE;
+	struct rms	*rms;
+
+	for (rms = request_methods; rms->string_len != 0; rms++) {
+		if (len != rms->string_len) {
+			continue;
+		}
+		if (strncasecmp(s, rms->method.string, len) == 0) {
+			return (&rms->method);
+		}
+	}
+
+	return (NULL);
 }
 
+method_t *
+urlMethodGet(const char *s, int len)
+{
+	method_t	*method;
+
+	method = urlMethodGetKnown(s, len);
+	if (method != NULL) {
+		return (method);
+	}
+
+	method = xmalloc(sizeof(method_t));
+	if (method == NULL) {
+		return (NULL);
+	}
+
+	method->code = METHOD_OTHER;
+	method->string = xmalloc((len + 1) * sizeof(char));
+	if (method->string == NULL) {
+		xfree(method);
+		return (NULL);
+	}
+	method->string = strncpy(method->string, s, len);
+	method->string[len] = '\0';
+	method->flags.cachable = 0;
+	method->flags.purges_all = 1;
+
+	return (method);
+}
+
+method_t *
+urlMethodGetKnownByCode(method_code_t code) {
+	if (code < 0 || code >= METHOD_OTHER) {
+		return (NULL);
+	}
+	return (&request_methods[code].method);
+}
+
+method_t *
+urlMethodDup(method_t *orig)
+{
+	method_t	*method;
+
+	if (orig == NULL) {
+		return (NULL);
+	}
+
+	if (orig->code != METHOD_OTHER) {
+		return (orig);
+	}
+
+	method = xmalloc(sizeof(method_t));
+	if (method == NULL) {
+		return (NULL);
+	}
+
+	method->code = orig->code;
+	method->string = xstrdup(orig->string);
+	if (method->string == NULL) {
+		xfree(method);
+		return (NULL);
+	}
+	method->flags.cachable = orig->flags.cachable;
+	method->flags.purges_all = orig->flags.purges_all;
+
+	return (method);
+}
+
+void
+urlMethodFree(method_t *method)
+{
+
+	if (method == NULL) {
+		return;
+	}
+
+	if (method->code != METHOD_OTHER) {
+		return;
+	}
+
+	xfree(method->string);
+	xfree(method);
+}
 
 protocol_t
 urlParseProtocol(const char *s)
@@ -256,7 +325,7 @@
  * being "end of host with implied path of /".
  */
 request_t *
-urlParse(method_t method, char *url)
+urlParse(method_t *method, char *url)
 {
     LOCAL_ARRAY(char, proto, MAX_URL);
     LOCAL_ARRAY(char, login, MAX_URL);
@@ -279,7 +348,7 @@
 	debug(23, 1) ("urlParse: URL too large (%d bytes)\n", l);
 	return NULL;
     }
-    if (method == METHOD_CONNECT) {
+    if (method->code == METHOD_CONNECT) {
 	port = CONNECT_PORT;
 	if (sscanf(url, "%[^:]:%d", host, &port) < 1)
 	    return NULL;
@@ -419,7 +488,7 @@
 }
 
 static request_t *
-urnParse(method_t method, char *urn)
+urnParse(method_t *method, char *urn)
 {
     debug(50, 5) ("urnParse: %s\n", urn);
     return requestCreate(method, PROTO_URN, urn + 4);
@@ -435,7 +504,7 @@
     if (request->protocol == PROTO_URN) {
 	snprintf(urlbuf, MAX_URL, "urn:%s", strBuf(request->urlpath));
     } else {
-	switch (request->method) {
+	switch (request->method->code) {
 	case METHOD_CONNECT:
 	    snprintf(urlbuf, MAX_URL, "%s:%d", request->host, request->port);
 	    break;
@@ -475,7 +544,7 @@
     if (request->protocol == PROTO_URN) {
 	snprintf(buf, MAX_URL, "urn:%s", strBuf(request->urlpath));
     } else {
-	switch (request->method) {
+	switch (request->method->code) {
 	case METHOD_CONNECT:
 	    snprintf(buf, MAX_URL, "%s:%d", request->host, request->port);
 	    break;
@@ -626,11 +695,11 @@
 {
     int rc = 0;
     /* protocol "independent" methods */
-    if (r->method == METHOD_CONNECT)
+    if (r->method->code == METHOD_CONNECT)
 	return 1;
-    if (r->method == METHOD_TRACE)
+    if (r->method->code == METHOD_TRACE)
 	return 1;
-    if (r->method == METHOD_PURGE)
+    if (r->method->code == METHOD_PURGE)
 	return 1;
     /* does method match the protocol? */
     switch (r->protocol) {
@@ -641,14 +710,14 @@
 	rc = 1;
 	break;
     case PROTO_FTP:
-	if (r->method == METHOD_PUT)
+	if (r->method->code == METHOD_PUT)
 	    rc = 1;
     case PROTO_GOPHER:
     case PROTO_WAIS:
     case PROTO_WHOIS:
-	if (r->method == METHOD_GET)
+	if (r->method->code == METHOD_GET)
 	    rc = 1;
-	else if (r->method == METHOD_HEAD)
+	else if (r->method->code == METHOD_HEAD)
 	    rc = 1;
 	break;
     case PROTO_HTTPS:
@@ -699,61 +768,3 @@
     }
     return host;
 }
-
-static void
-urlExtMethodAdd(const char *mstr)
-{
-    method_t method = 0;
-    for (method++; method < METHOD_ENUM_END; method++) {
-	if (0 == strcmp(mstr, RequestMethods[method].str)) {
-	    debug(23, 2) ("Extension method '%s' already exists\n", mstr);
-	    return;
-	}
-	if (0 != strncmp("%EXT", RequestMethods[method].str, 4))
-	    continue;
-	/* Don't free statically allocated "%EXTnn" string */
-	if (0 == strncmp("%EXT_", RequestMethods[method].str, 5))
-	    safe_free(RequestMethods[method].str);
-	RequestMethods[method].str = xstrdup(mstr);
-	RequestMethods[method].len = strlen(mstr);
-	debug(23, 1) ("Extension method '%s' added, enum=%d\n", mstr, (int) method);
-	return;
-    }
-    debug(23, 1) ("WARNING: Could not add new extension method '%s' due to lack of array space\n", mstr);
-}
-
-void
-parse_extension_method(rms_t(*foo)[])
-{
-    char *token;
-    char *t = strtok(NULL, "");
-    while ((token = strwordtok(NULL, &t))) {
-	urlExtMethodAdd(token);
-    }
-}
-
-void
-free_extension_method(rms_t(*foo)[])
-{
-    method_t method;
-    for (method = METHOD_EXT00; method < METHOD_ENUM_END; method++) {
-	if (RequestMethods[method].str[0] != '%') {
-	    char buf[32];
-	    snprintf(buf, sizeof(buf), "%%EXT_%02d", method - METHOD_EXT00);
-	    safe_free(RequestMethods[method].str);
-	    RequestMethods[method].str = xstrdup(buf);
-	    RequestMethods[method].len = strlen(buf);
-	}
-    }
-}
-
-void
-dump_extension_method(StoreEntry * entry, const char *name, rms_t * methods)
-{
-    method_t method;
-    for (method = METHOD_EXT00; method < METHOD_ENUM_END; method++) {
-	if (RequestMethods[method].str[0] != '%') {
-	    storeAppendPrintf(entry, "%s %s\n", name, RequestMethods[method].str);
-	}
-    }
-}
Index: squid/src/urn.c
===================================================================
--- squid.orig/src/urn.c	2008-08-12 14:59:36.385865000 +1000
+++ squid/src/urn.c	2008-08-12 15:16:30.000000000 +1000
@@ -56,12 +56,12 @@
 } url_entry;
 
 static STNCB urnHandleReply;
-static url_entry *urnParseReply(const char *inbuf, method_t);
+static url_entry *urnParseReply(const char *inbuf, method_t *);
 static const char *const crlf = "\r\n";
 static QS url_entry_sort;
 
 static url_entry *
-urnFindMinRtt(url_entry * urls, method_t m, int *rtt_ret)
+urnFindMinRtt(url_entry * urls, method_t *m, int *rtt_ret)
 {
     int min_rtt = 0;
     url_entry *u = NULL;
@@ -106,8 +106,10 @@
     UrnState *urnState;
     StoreEntry *urlres_e;
     ErrorState *err;
+    method_t *method_get;
     debug(52, 3) ("urnStart: '%s'\n", storeUrl(e));
     CBDATA_INIT_TYPE(UrnState);
+    method_get = urlMethodGetKnownByCode(METHOD_GET);
     urnState = cbdataAlloc(UrnState);
     urnState->entry = e;
     urnState->request = requestLink(r);
@@ -127,7 +129,7 @@
     }
     snprintf(urlres, 4096, "http://%s/uri-res/N2L?urn:%s", host, strBuf(r->urlpath));
     safe_free(host);
-    urlres_r = urlParse(METHOD_GET, urlres);
+    urlres_r = urlParse(method_get, urlres);
     if (urlres_r == NULL) {
 	debug(52, 3) ("urnStart: Bad uri-res URL %s\n", urlres);
 	err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND, r);
@@ -136,8 +138,8 @@
 	return;
     }
     httpHeaderPutStr(&urlres_r->header, HDR_ACCEPT, "text/plain");
-    if ((urlres_e = storeGetPublic(urlres, METHOD_GET)) == NULL) {
-	urlres_e = storeCreateEntry(urlres, null_request_flags, METHOD_GET);
+    if ((urlres_e = storeGetPublic(urlres, method_get)) == NULL) {
+	urlres_e = storeCreateEntry(urlres, null_request_flags, method_get);
 	urnState->sc = storeClientRegister(urlres_e, urnState);
 	fwdStart(-1, urlres_e, urlres_r);
     } else {
@@ -303,7 +305,7 @@
 }
 
 static url_entry *
-urnParseReply(const char *inbuf, method_t m)
+urnParseReply(const char *inbuf, method_t *m)
 {
     char *buf = xstrdup(inbuf);
     char *token;

