=== modified file 'src/HttpReply.cc' --- src/HttpReply.cc 2009-08-22 10:43:54 +0000 +++ src/HttpReply.cc 2009-11-01 10:17:45 +0000 @@ -458,24 +458,33 @@ return false; } + int pos; // catch missing or mismatched protocol identifier - if (protoPrefix.cmp(buf->content(), protoPrefix.size()) != 0) { - debugs(58, 3, "HttpReply::sanityCheckStartLine: missing protocol prefix (" << protoPrefix << ") in '" << buf->content() << "'"); - *error = HTTP_INVALID_HEADER; - return false; + // allow special-case for ICY protocol (non-HTTP identifier) in response to faked HTTP request. + if (strncmp(buf->content(), "ICY", 3) == 0) { + protoPrefix = "ICY"; + pos = protoPrefix.psize(); } - - // catch missing or negative status value (negative '-' is not a digit) - int pos = protoPrefix.psize(); - - // skip arbitrary number of digits and a dot in the verion portion - while ( pos <= buf->contentSize() && (*(buf->content()+pos) == '.' || xisdigit(*(buf->content()+pos)) ) ) ++pos; - - // catch missing version info - if (pos == protoPrefix.psize()) { - debugs(58, 3, "HttpReply::sanityCheckStartLine: missing protocol version numbers (ie. " << protoPrefix << "/1.0) in '" << buf->content() << "'"); - *error = HTTP_INVALID_HEADER; - return false; + else { + + if (protoPrefix.cmp(buf->content(), protoPrefix.size()) != 0) { + debugs(58, 3, "HttpReply::sanityCheckStartLine: missing protocol prefix (" << protoPrefix << ") in '" << buf->content() << "'"); + *error = HTTP_INVALID_HEADER; + return false; + } + + // catch missing or negative status value (negative '-' is not a digit) + pos = protoPrefix.psize(); + + // skip arbitrary number of digits and a dot in the verion portion + while ( pos <= buf->contentSize() && (*(buf->content()+pos) == '.' || xisdigit(*(buf->content()+pos)) ) ) ++pos; + + // catch missing version info + if (pos == protoPrefix.psize()) { + debugs(58, 3, "HttpReply::sanityCheckStartLine: missing protocol version numbers (ie. " << protoPrefix << "/1.0) in '" << buf->content() << "'"); + *error = HTTP_INVALID_HEADER; + return false; + } } // skip arbitrary number of spaces... === modified file 'src/HttpStatusLine.cc' --- src/HttpStatusLine.cc 2009-09-16 09:53:46 +0000 +++ src/HttpStatusLine.cc 2009-11-01 11:06:47 +0000 @@ -39,6 +39,7 @@ /* local constants */ /* AYJ: see bug 2469 - RFC2616 confirms stating 'SP characters' plural! */ const char *HttpStatusLineFormat = "HTTP/%d.%d %3d %s\r\n"; +const char *IcyStatusLineFormat = "ICY %3d %s\r\n"; void httpStatusLineInit(HttpStatusLine * sline) @@ -59,17 +60,31 @@ httpStatusLineSet(HttpStatusLine * sline, HttpVersion version, http_status status, const char *reason) { assert(sline); + sline->protocol = PROTO_HTTP; sline->version = version; sline->status = status; /* Note: no xstrdup for 'reason', assumes constant 'reasons' */ sline->reason = reason; } -/** write HTTP version and status structures into a Packer buffer for output as HTTP status line. */ +/** + * Write HTTP version and status structures into a Packer buffer for output as HTTP status line. + * Special exemption made for ICY response status lines. + */ void httpStatusLinePackInto(const HttpStatusLine * sline, Packer * p) { assert(sline && p); + + /* handle ICY protocol status line specially. Pass on the bad format. */ + if (sline->protocol == PROTO_ICY) { + debugs(57, 9, "packing sline " << sline << " using " << p << ":"); + debugs(57, 9, "FORMAT=" << IcyStatusLineFormat ); + debugs(57, 9, "ICY " << sline->status << " " << (sline->reason ? sline->reason : httpStatusString(sline->status)) ); + packerPrintf(p, IcyStatusLineFormat, sline->status, httpStatusLineReason(sline)); + return; + } + debugs(57, 9, "packing sline " << sline << " using " << p << ":"); debugs(57, 9, "FORMAT=" << HttpStatusLineFormat ); debugs(57, 9, "HTTP/" << sline->version.major << "." << sline->version.minor << @@ -91,17 +106,24 @@ // XXX: HttpMsg::parse() has a similar check but is using // casesensitive comparison (which is required by HTTP errata?) - if (protoPrefix.caseCmp(start, protoPrefix.size()) != 0) - return 0; - - start += protoPrefix.size(); - - if (!xisdigit(*start)) - return 0; - - if (sscanf(start, "%d.%d", &sline->version.major, &sline->version.minor) != 2) { - debugs(57, 7, "httpStatusLineParse: Invalid HTTP identifier."); - } + if (protoPrefix.cmp("ICY", 3) == 0) { + debugs(57, 3, "httpStatusLineParse: Invalid HTTP identifier. Detected ICY protocol istead."); + sline->protocol = PROTO_ICY; + start += protoPrefix.size(); + } + else if (protoPrefix.caseCmp(start, protoPrefix.size()) != 0) { + + start += protoPrefix.size(); + + if (!xisdigit(*start)) + return 0; + + if (sscanf(start, "%d.%d", &sline->version.major, &sline->version.minor) != 2) { + debugs(57, 7, "httpStatusLineParse: Invalid HTTP identifier."); + } + } + else + return 0; if (!(start = strchr(start, ' '))) return 0; === modified file 'src/HttpStatusLine.h' --- src/HttpStatusLine.h 2009-01-21 03:47:47 +0000 +++ src/HttpStatusLine.h 2009-11-01 08:20:01 +0000 @@ -39,20 +39,32 @@ /* for SQUIDCEXTERN */ #include "config.h" -/* for http_status */ +/* for http_status and protocol_t */ #include "enums.h" -/* for class variables */ #include "HttpVersion.h" +#include "SquidString.h" +/** + * Holds the values parsed from an HTTP reply status line. + * + * For example: HTTP/1.1 200 Okay + */ class HttpStatusLine { - public: /* public, read only */ - HttpVersion version; - const char *reason; /**< points to a _constant_ string (default or supplied), never free()d */ - http_status status; + + /** + * By rights protocol name should be a constant "HTTP", with no need for this field to exist. + * However there are protocols which violate HTTP by sending their wn custom formats + * back with other protocol names (ICY streaming format being the current major problem) + */ + protocol_t protocol; + + HttpVersion version; ///< breakdown of protocol version labels: 0.9 1.0 1.1 + http_status status; ///< status code. ie 200 404 + const char *reason; ///< points to a _constant_ string (default or supplied), never free()d */ }; /* init/clean */ === modified file 'src/URLScheme.cc' --- src/URLScheme.cc 2009-01-21 03:47:47 +0000 +++ src/URLScheme.cc 2009-11-01 11:25:59 +0000 @@ -52,6 +52,6 @@ "whois", "internal", "https", + "icy", "TOTAL" }; - === modified file 'src/client_side_reply.cc' --- src/client_side_reply.cc 2009-09-18 20:40:02 +0000 +++ src/client_side_reply.cc 2009-11-01 10:40:59 +0000 @@ -1440,8 +1440,10 @@ reply = HTTPMSGLOCK(rep); - /* enforce 1.0 reply version */ - reply->sline.version = HttpVersion(1,0); + if (reply->sline.protocol == PROTO_HTTP) { + /* enforce 1.0 reply version (but only on real HTTP traffic) */ + reply->sline.version = HttpVersion(1,0); + } /* do header conversions */ buildReplyHeader(); === modified file 'src/enums.h' --- src/enums.h 2009-08-23 05:13:09 +0000 +++ src/enums.h 2009-11-01 08:18:48 +0000 @@ -152,6 +152,7 @@ PROTO_WHOIS, PROTO_INTERNAL, PROTO_HTTPS, + PROTO_ICY, PROTO_MAX } protocol_t;