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;