=== 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;
 


