http://lists.stargirl.org/pipermail/btpd-users/2007-June/000250.html

On Wed, June 27, 2007 10:27, Richard Nyberg said:
> On Tue, June 26, 2007 12:29, barone rosso said:
>> the tracker is Macnbits, http://beta.macnbits.com/home.php , a BNBT
>> tracker based. I have the same problem with all torrents relased by
>> this tracker.
>>
> This tracker almost manages to talk HTTP, but not quite. As specified
> in RFC 2616, the line endings in HTTP is encoded with CRLF. This
> tracker only sends LF.
>
> Quoted from http://tools.ietf.org/html/rfc2616 section 3.7.1:
> "a bare CR or LF MUST NOT be substituted for CRLF within any of
>  the HTTP control structures (such as header fields and multipart
>  boundaries)."
>
> You should talk to the tracker admins and try to get them to fix it.
>
> Nevertheless, this is probably a common error - curl deals with it -
> so one should perhaps make btpd parse it as well.

Please try the attached patch. It should tolerate both types of
new lines.

        -Richard

Index: misc/http_client.c
===================================================================
--- misc/http_client.c	(revision 357)
+++ misc/http_client.c	(working copy)
@@ -132,11 +132,24 @@
     http_free(req);
 }
 
+static char *
+strnl(char *str, int *nlsize)
+{
+    char *nl = strchr(str, '\n');
+    if (nl != NULL && nl > str && *(nl - 1) == '\r') {
+        *nlsize = 2;
+        return nl - 1;
+    } else {
+        *nlsize = 1;
+        return nl;
+    }
+}
+
 static int
 headers_parse(struct http_req *req, char *buf, char *end)
 {
-    int code, majv, minv;
-    char *cur, *crlf;
+    int code, majv, minv, nlsize;
+    char *cur, *nl;
     char name[128], value[872];
     struct http_response res;
 
@@ -151,12 +164,12 @@
     if (req->cancel)
         return 1;
 
-    cur = strstr(buf, "\r\n") + 2;
-    crlf = strstr(cur, "\r\n");
+    cur = strchr(buf, '\n') + 1;
+    nl = strnl(cur, &nlsize);
     while (cur < end) {
         int i;
         char *colon = strchr(cur, ':');
-        if (colon == NULL || colon > crlf)
+        if (colon == NULL || colon > nl)
             return 0;
         snprintf(name, sizeof(name), "%.*s", (int)(colon - cur), cur);
 
@@ -165,15 +178,15 @@
     val_loop:
         while (isblank(*cur))
             cur++;
-        while (cur < crlf) {
+        while (cur < nl) {
             if (i < sizeof(value) - 1) {
                 value[i] = *cur;
                 i++;
             }
             cur++;
         }
-        cur += 2;
-        crlf = strstr(cur, "\r\n");
+        cur += nlsize;
+        nl = strnl(cur, &nlsize);
         if (isblank(*cur)) {
             if (i < sizeof(value) - 1) {
                 value[i] = ' ';
@@ -222,7 +235,11 @@
     case PS_HEAD:
         if (len == 0)
             goto error;
-        if ((end = evbuffer_find(req->buf, "\r\n\r\n", 4)) == NULL) {
+        if ((end = evbuffer_find(req->buf, "\r\n\r\n", 4)) != NULL)
+            dlen = 4;
+        else if ((end = evbuffer_find(req->buf, "\n\n", 2)) != NULL)
+            dlen = 2;
+        else {
             if (req->buf->off < (1 << 15))
                 return 1;
             else
@@ -235,7 +252,7 @@
             goto error;
         if (req->cancel)
             goto cancel;
-        evbuffer_drain(req->buf, end - (char *)req->buf->buffer + 4);
+        evbuffer_drain(req->buf, end - (char *)req->buf->buffer + dlen);
         goto again;
     case PS_CHUNK_SIZE:
         assert(req->chunked);
