From: Amos Jeffries Date: Mon, 17 Feb 2014 10:49:37 +0000 (-0800) Subject: Merge from trunk X-Git-Tag: merge-candidate-3-v1~506^2~53 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=00589b8e290a3a688bd445ade43854687a59deb7;p=thirdparty%2Fsquid.git Merge from trunk --- 00589b8e290a3a688bd445ade43854687a59deb7 diff --cc src/HttpHeader.cc index f84a017290,de002db6bc..fd25dc34c1 --- a/src/HttpHeader.cc +++ b/src/HttpHeader.cc @@@ -545,12 -550,11 +550,12 @@@ HttpHeader::reset( } int -HttpHeader::parse(const char *header_start, const char *header_end) +HttpHeader::parse(const char *header_start, size_t hdrLen) { const char *field_ptr = header_start; + const char *header_end = header_start + hdrLen; // XXX: remove HttpHeaderEntry *e, *e2; - bool warnOnError = (Config.onoff.relaxed_header_parser <= 0 ? DBG_IMPORTANT : 2); + int warnOnError = (Config.onoff.relaxed_header_parser <= 0 ? DBG_IMPORTANT : 2); PROF_start(HttpHeaderParse); diff --cc src/Makefile.am index 9b8b1ee4c9,c0568c1ead..b0e3b0ef0c --- a/src/Makefile.am +++ b/src/Makefile.am @@@ -640,9 -643,7 +639,8 @@@ squid_LDADD = $(REGEXLIB) \ $(ADAPTATION_LIBS) \ $(ESI_LIBS) \ - $(SSL_LIBS) \ $(SNMP_LIBS) \ + parser/libsquid-parser.la \ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ diff --cc src/client_side.cc index d5f7f501e3,fad7390cca..179e75e819 --- a/src/client_side.cc +++ b/src/client_side.cc @@@ -2173,11 -2160,11 +2163,11 @@@ prepareTransparentURL(ConnStateData * c /* BUG: Squid cannot deal with '*' URLs (RFC2616 5.1.2) */ - if ((host = mime_get_header(req_hdr, "Host")) != NULL) { - int url_sz = strlen(url) + 32 + Config.appendDomainLen + + if (const char *host = hp.getHeaderField("Host")) { + const int url_sz = hp.requestUri().length() + 32 + Config.appendDomainLen + strlen(host); http->uri = (char *)xcalloc(url_sz, 1); - snprintf(http->uri, url_sz, "%s://%s%s", URLScheme(conn->port->transport.protocol).const_str(), host, SBuf(hp.requestUri()).c_str()); - snprintf(http->uri, url_sz, "%s://%s%s", AnyP::UriScheme(conn->port->transport.protocol).c_str(), host, url); ++ snprintf(http->uri, url_sz, "%s://%s%s", AnyP::UriScheme(conn->port->transport.protocol).c_str(), host, SBuf(hp.requestUri()).c_str()); debugs(33, 5, "TRANSPARENT HOST REWRITE: '" << http->uri <<"'"); } else { /* Put the local socket IP address as the hostname. */ @@@ -2185,8 -2172,8 +2175,8 @@@ http->uri = (char *)xcalloc(url_sz, 1); http->getConn()->clientConnection->local.toHostStr(ipbuf,MAX_IPSTRLEN); snprintf(http->uri, url_sz, "%s://%s:%d%s", - URLScheme(http->getConn()->port->transport.protocol).const_str(), + AnyP::UriScheme(http->getConn()->port->transport.protocol).c_str(), - ipbuf, http->getConn()->clientConnection->local.port(), url); + ipbuf, http->getConn()->clientConnection->local.port(), SBuf(hp.requestUri()).c_str()); debugs(33, 5, "TRANSPARENT REWRITE: '" << http->uri << "'"); } } diff --cc src/http/Http1Parser.h index 62de09c898,0000000000..86439e440a mode 100644,000000..100644 --- a/src/http/Http1Parser.h +++ b/src/http/Http1Parser.h @@@ -1,161 -1,0 +1,161 @@@ +#ifndef _SQUID_SRC_HTTP_ONEREQUESTPARSER_H +#define _SQUID_SRC_HTTP_ONEREQUESTPARSER_H + +#include "base/RefCount.h" +#include "http/forward.h" +#include "http/ProtocolVersion.h" +#include "http/RequestMethod.h" +#include "http/StatusCode.h" +#include "SBuf.h" + +namespace Http { +namespace One { + +// Parser states +#define HTTP_PARSE_NONE 0 // nothing. completely unset state. +#define HTTP_PARSE_NEW 1 // initialized, but nothing usefully parsed yet. +#define HTTP_PARSE_FIRST 2 // have parsed request first line +#define HTTP_PARSE_MIME 3 // have located end of mime header block +#define HTTP_PARSE_DONE 99 // have done with parsing so far + +/** HTTP protocol parser. + * - * Works on a raw character I/O buffer and separates the content into ++ * Works on a raw character I/O buffer and tokenizes the content into + * either an error state or HTTP procotol major sections: + * + * \item first-line (request-line / simple-request / status-line) + * \item mime-header block + */ +class Parser : public RefCountable +{ +public: + Parser() { clear(); } + + /** Initialize a new parser. + * Presenting it a buffer to work on and the current length of available data. + * NOTE: This is *not* the buffer size, just the parse-able data length. + * The parse routines may be called again later with more data. + */ + Parser(const char *aBuf, int len) { reset(aBuf,len); } + + /// Set this parser back to a default state. + /// Will DROP any reference to a buffer (does not free). + virtual void clear(); + + /// Reset the parser for use on a new buffer. + void reset(const char *aBuf, int len); + + /** Adjust parser state to account for a buffer shift of n bytes. + * + * The leftmost n bytes bytes have been dropped and all other + * bytes shifted left n positions. + */ + virtual void noteBufferShift(int64_t n) = 0; + + /** Whether the parser is already done processing the buffer. + * Use to determine between incomplete data and errors results + * from the parse. + */ + bool isDone() const {return completedState_==HTTP_PARSE_DONE;} + + /// number of bytes in buffer before the message + virtual int64_t messageOffset() const = 0; + + /// size in bytes of the first line including CRLF terminator + virtual int64_t firstLineSize() const = 0; + + /// size in bytes of the message headers including CRLF terminator(s) + /// but excluding first-line bytes + int64_t headerBlockSize() const {return mimeHeaderBlock_.length();} + + /// size in bytes of HTTP message block, includes first-line and mime headers + /// excludes any body/entity/payload bytes + /// excludes any garbage prefix before the first-line + int64_t messageHeaderSize() const {return firstLineSize() + headerBlockSize();} + + /// buffer containing HTTP mime headers, excluding message first-line. + const char *rawHeaderBuf() {return mimeHeaderBlock_.c_str();} + + /// attempt to parse a message from the buffer + virtual bool parse() = 0; + + /// the protocol label for this message + const AnyP::ProtocolVersion & messageProtocol() const {return msgProtocol_;} + + /** + * \return A pointer to a field-value of the first matching field-name, or NULL. + */ + char *getHeaderField(const char *name); + +public: + const char *buf; + int bufsiz; + +protected: + /// what stage the parser is currently up to + uint8_t completedState_; + + /// what protocol label has been found in the first line + AnyP::ProtocolVersion msgProtocol_; + + /// byte offset for non-parsed region of the buffer + size_t parseOffset_; + + /// buffer holding the mime headers + SBuf mimeHeaderBlock_; +}; + +/** HTTP protocol request parser. + * + * Works on a raw character I/O buffer and tokenizes the content into + * either an error state or, an HTTP procotol request major segments: + * + * \item Request Line (method, URL, protocol, version) + * \item Mime header block + */ +class RequestParser : public Http1::Parser +{ +public: + /* Http::One::Parser API */ + RequestParser() : Parser() {} + RequestParser(const char *aBuf, int len) : Parser(aBuf, len) {} + virtual void clear(); + virtual void noteBufferShift(int64_t n); + virtual int64_t messageOffset() const {return req.start;} + virtual int64_t firstLineSize() const {return req.end - req.start + 1;} + virtual bool parse(); + + /// the HTTP method if this is a request message + const HttpRequestMethod & method() const {return method_;} + + /// the request-line URI if this is a request message, or an empty string. + const SBuf &requestUri() const {return uri_;} + + /** HTTP status code to be used on the invalid-request error page + * Http::scNone indicates incomplete parse, Http::scOkay indicates no error. + */ + Http::StatusCode request_parse_status; + +private: + bool skipGarbageLines(); + int parseRequestFirstLine(); + + /// Offsets for pieces of the (HTTP request) Request-Line as per RFC 2616 + struct request_offsets { + int start, end; + int m_start, m_end; // method + int u_start, u_end; // url + int v_start, v_end; // version (full text) + } req; + + /// what request method has been found on the first line + HttpRequestMethod method_; + + /// raw copy of the origina client reqeust-line URI field + SBuf uri_; +}; + +} // namespace One +} // namespace Http + +#endif /* _SQUID_SRC_HTTP_HTTP1PARSER_H */