=== modified file 'src/client_side.cc' --- src/client_side.cc 2011-03-09 19:02:12 +0000 +++ src/client_side.cc 2011-03-10 12:43:33 +0000 @@ -1897,48 +1897,86 @@ end = uriAndHTTPVersion + strcspn(uriAndHTTPVersion, "\r\n"); assert(end); } for (; end > uriAndHTTPVersion; end--) { if (*end == '\n' || *end == '\r') continue; if (xisspace(*end)) { if (strncasecmp(end + 1, "HTTP/", 5) == 0) return end + 1; else break; } } return NULL; } void -setLogUri(ClientHttpRequest * http, char const *uri) +setLogUri(ClientHttpRequest * http, char const *uri, bool cleanUrl) { safe_free(http->log_uri); - if (!stringHasCntl(uri)) + if (!cleanUrl) + // The uri is already clean just dump it. http->log_uri = xstrndup(uri, MAX_URL); - else - http->log_uri = xstrndup(rfc1738_escape_unescaped(uri), MAX_URL); + else { + int flags = 0; + switch (Config.uri_whitespace) { + case URI_WHITESPACE_ALLOW: + flags |= RFC1738_ESCAPE_NOSPACE; + + case URI_WHITESPACE_ENCODE: + flags |= RFC1738_ESCAPE_UNESCAPED; + http->log_uri = xstrndup(rfc1738_do_escape(uri, flags), MAX_URL); + break; + + case URI_WHITESPACE_CHOP: { + flags |= RFC1738_ESCAPE_NOSPACE; + flags |= RFC1738_ESCAPE_UNESCAPED; + http->log_uri = xstrndup(rfc1738_do_escape(uri, flags), MAX_URL); + int pos = strcspn(http->log_uri, w_space); + http->log_uri[pos] = '\0'; + } + break; + + case URI_WHITESPACE_DENY: + case URI_WHITESPACE_STRIP: + default: { + const char *t; + char *tmp_uri = static_cast(xmalloc(strlen(uri) + 1)); + char *q = tmp_uri; + t = uri; + while (*t) { + if (!xisspace(*t)) + *q++ = *t; + t++; + } + *q = '\0'; + http->log_uri = xstrndup(rfc1738_escape_unescaped(tmp_uri), MAX_URL); + xfree(tmp_uri); + } + break; + } + } } static void prepareAcceleratedURL(ConnStateData * conn, ClientHttpRequest *http, char *url, const char *req_hdr) { int vhost = conn->port->vhost; int vport = conn->port->vport; char *host; char ipbuf[MAX_IPSTRLEN]; http->flags.accel = 1; /* BUG: Squid cannot deal with '*' URLs (RFC2616 5.1.2) */ if (strncasecmp(url, "cache_object://", 15) == 0) return; /* already in good shape */ if (*url != '/') { if (conn->port->vhost) return; /* already in good shape */ @@ -2207,41 +2245,40 @@ } else if (conn->port->accel || conn->switchedToHttps()) { /* accelerator mode */ prepareAcceleratedURL(conn, http, url, req_hdr); } else if (internalCheck(url)) { /* internal URL mode */ /* prepend our name & port */ http->uri = xstrdup(internalLocalUri(NULL, url)); http->flags.accel = 1; } if (!http->uri) { /* No special rewrites have been applied above, use the * requested url. may be rewritten later, so make extra room */ int url_sz = strlen(url) + Config.appendDomainLen + 5; http->uri = (char *)xcalloc(url_sz, 1); strcpy(http->uri, url); } - setLogUri(http, http->uri); debugs(33, 5, "parseHttpRequest: Complete request received"); result->flags.parsed_ok = 1; xfree(url); return result; } int ConnStateData::getAvailableBufferLength() const { int result = in.allocatedSize - in.notYetUsed - 1; assert (result >= 0); return result; } bool ConnStateData::maybeMakeSpaceAvailable() { if (getAvailableBufferLength() < 2) { size_t newSize; if (in.allocatedSize >= Config.maxRequestBufferSize) { @@ -2378,93 +2415,101 @@ } static void clientProcessRequest(ConnStateData *conn, HttpParser *hp, ClientSocketContext *context, const HttpRequestMethod& method, HttpVersion http_ver) { ClientHttpRequest *http = context->http; HttpRequest *request = NULL; bool notedUseOfBuffer = false; bool chunked = false; bool mustReplyToOptions = false; bool unsupportedTe = false; bool expectBody = false; /* We have an initial client stream in place should it be needed */ /* setup our private context */ context->registerWithConn(); if (context->flags.parsed_ok == 0) { clientStreamNode *node = context->getClientReplyContext(); debugs(33, 1, "clientProcessRequest: Invalid Request"); + // setLogUri should called before repContext->setReplyToError + setLogUri(http, http->uri, true); clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); switch (hp->request_parse_status) { case HTTP_HEADER_TOO_LARGE: repContext->setReplyToError(ERR_TOO_BIG, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, conn->in.buf, NULL); break; case HTTP_METHOD_NOT_ALLOWED: repContext->setReplyToError(ERR_UNSUP_REQ, HTTP_METHOD_NOT_ALLOWED, method, http->uri, conn->peer, NULL, conn->in.buf, NULL); break; default: repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, conn->in.buf, NULL); } assert(context->http->out.offset == 0); context->pullData(); conn->flags.readMoreRequests = false; goto finish; } if ((request = HttpRequest::CreateFromUrlAndMethod(http->uri, method)) == NULL) { clientStreamNode *node = context->getClientReplyContext(); debugs(33, 5, "Invalid URL: " << http->uri); + // setLogUri should called before repContext->setReplyToError + setLogUri(http, http->uri, true); clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); repContext->setReplyToError(ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); conn->flags.readMoreRequests = false; goto finish; } /* RFC 2616 section 10.5.6 : handle unsupported HTTP versions cleanly. */ /* We currently only accept 0.9, 1.0, 1.1 */ if ( (http_ver.major == 0 && http_ver.minor != 9) || (http_ver.major == 1 && http_ver.minor > 1 ) || (http_ver.major > 1) ) { clientStreamNode *node = context->getClientReplyContext(); debugs(33, 5, "Unsupported HTTP version discovered. :\n" << HttpParserHdrBuf(hp)); + // setLogUri should called before repContext->setReplyToError + setLogUri(http, http->uri, true); clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); repContext->setReplyToError(ERR_UNSUP_HTTPVERSION, HTTP_HTTP_VERSION_NOT_SUPPORTED, method, http->uri, conn->peer, NULL, HttpParserHdrBuf(hp), NULL); assert(context->http->out.offset == 0); context->pullData(); conn->flags.readMoreRequests = false; goto finish; } /* compile headers */ /* we should skip request line! */ /* XXX should actually know the damned buffer size here */ if (http_ver.major >= 1 && !request->parseHeader(HttpParserHdrBuf(hp), HttpParserHdrSz(hp))) { clientStreamNode *node = context->getClientReplyContext(); debugs(33, 5, "Failed to parse request headers:\n" << HttpParserHdrBuf(hp)); + // setLogUri should called before repContext->setReplyToError + setLogUri(http, http->uri, true); clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); conn->flags.readMoreRequests = false; goto finish; } request->flags.accelerated = http->flags.accel; request->flags.ignore_cc = conn->port->ignore_cc; request->flags.no_direct = request->flags.accelerated ? !conn->port->allow_direct : 0; /** \par * If transparent or interception mode is working clone the transparent and interception flags * from the port settings to the request. */ if (Ip::Interceptor.InterceptActive()) { request->flags.intercepted = http->flags.intercepted; } === modified file 'src/client_side.h' --- src/client_side.h 2011-02-07 10:27:53 +0000 +++ src/client_side.h 2011-03-06 18:06:29 +0000 @@ -304,25 +304,25 @@ private: int connReadWasError(comm_err_t flag, int size, int xerrno); int connFinishedWithConn(int size); void clientMaybeReadData(int do_next_read); void clientAfterReadingRequests(int do_next_read); private: CBDATA_CLASS2(ConnStateData); bool transparent_; bool closing_; bool switchedToHttps_; String sslHostName; ///< Host name for SSL certificate generation AsyncCall::Pointer reader; ///< set when we are reading BodyPipe::Pointer bodyPipe; // set when we are reading request body }; /* convenience class while splitting up body handling */ /* temporary existence only - on stack use expected */ -void setLogUri(ClientHttpRequest * http, char const *uri); +void setLogUri(ClientHttpRequest * http, char const *uri, bool cleanUrl = false); const char *findTrailingHTTPVersion(const char *uriAndHTTPVersion, const char *end = NULL); #endif /* SQUID_CLIENTSIDE_H */