It turned out to be much easier than I thought -- actually a darcs
merge did the thing completely automatically, I only needed to
manually add a chapter to the documentation.

You can get the code from the stable darcs tree, or from the attached
patch.  Please let me know how it goes.

(Tom, if you decide to apply this to the Debian package, please make
sure you version it as 0.9.7, not 0.9.8 -- there's another thing I
might want to include in 0.9.8.)

                                        Juliusz

Fri Jan 14 02:14:07 CET 2005  Juliusz Chroboczek <[EMAIL PROTECTED]>
  * Move the lax parser docs to a more logical place.

Fri Jan 14 02:07:27 CET 2005  Juliusz Chroboczek <[EMAIL PROTECTED]>
  * Document the lax HTTP parser.

Mon Sep  6 01:33:52 CEST 2004  Juliusz Chroboczek <[EMAIL PROTECTED]>
  * Implement lax HTTP parsing.

diff -rN -u polipo-stable-0.9-old/CHANGES polipo-stable-0.9-new/CHANGES
--- polipo-stable-0.9-old/CHANGES       2005-01-14 02:15:19.000000000 +0100
+++ polipo-stable-0.9-new/CHANGES       2005-01-14 02:07:00.000000000 +0100
@@ -1,3 +1,7 @@
+Polipo 0.9.8 (unreleased):
+
+        Backported the lax HTTP parser from the head branch.
+
 27 December 2004: Polipo 0.9.7:
 
         Fixed a possible crash when tunnelling.
diff -rN -u polipo-stable-0.9-old/http_parse.c 
polipo-stable-0.9-new/http_parse.c
--- polipo-stable-0.9-old/http_parse.c  2005-01-14 02:15:19.000000000 +0100
+++ polipo-stable-0.9-new/http_parse.c  2005-01-14 02:02:06.000000000 +0100
@@ -41,6 +41,7 @@
     atomXPolipoBodyOffset;
 
 int censorReferer = 0;
+int laxHttpParser = 1;
 
 static AtomListPtr censoredHeaders;
 
@@ -55,6 +56,8 @@
     }
     CONFIG_VARIABLE(censoredHeaders, CONFIG_ATOM_LIST_LOWER,
                     "Headers to censor.");
+    CONFIG_VARIABLE(laxHttpParser, CONFIG_BOOLEAN,
+                    "Ignore unknown HTTP headers.");
 }
 
 void
@@ -499,6 +502,8 @@
     return i;
 }
 
+/* Returned *name_start_return is -1 at end of headers, -2 if the line
+   couldn't be parsed. */
 static int
 parseHeaderLine(const char *restrict buf, int start,
                 int *name_start_return, int *name_end_return,
@@ -518,16 +523,33 @@
 
     i = getNextToken(buf, start, &name_start, &name_end);
     if(i < 0 || buf[i] != ':')
-        return -1;
+        goto syntax;
 
     i = getHeaderValue(buf, i + 2, &value_start, &value_end);
-    if(i < 0) return -1;
+    if(i < 0)
+        goto syntax;
 
     *name_start_return = name_start;
     *name_end_return = name_end;
     *value_start_return = value_start;
     *value_end_return = value_end;
     return i;
+
+ syntax:
+    i = start;
+    while(1) {
+        if(buf[i] == '\n') {
+            i++;
+            break;
+        }
+        if(buf[i] == '\r' && buf[i + 1] == '\n') {
+            i += 2;
+            break;
+        }
+        i++;
+    }
+    *name_start_return = -2;
+    return i;
 }
 
 int
@@ -750,16 +772,19 @@
     i = start;
 
     while(1) {
-        i = parseHeaderLine(buf, i, 
+        i = parseHeaderLine(buf, i,
                             &name_start, &name_end, &value_start, &value_end);
         if(i < 0) {
-            do_log(L_ERROR, "Couldn't find end of header line\n");
+            do_log(L_ERROR, "Couldn't find end of header line.\n");
             goto fail;
         }
 
-        if(name_start < 0)
+        if(name_start == -1)
             break;
 
+        if(name_start < 0)
+            continue;
+
         /* It's not worthwile to intern the name -- it will only be
            compared once. */
         
@@ -806,13 +831,21 @@
         i = parseHeaderLine(buf, i, 
                             &name_start, &name_end, &value_start, &value_end);
         if(i < 0) {
-            do_log(L_ERROR, "Couldn't find end of header line\n");
+            do_log(L_ERROR, "Couldn't find end of header line.\n");
             goto fail;
         }
 
-        if(name_start < 0)
+        if(name_start == -1)
             break;
 
+        if(name_start < 0) {
+            do_log(L_WARN, "Couldn't parse header line.\n");
+            if(laxHttpParser)
+                continue;
+            else
+                goto fail;
+        }
+
         name = internAtomLowerN(buf + name_start, name_end - name_start);
         
         if(name == atomProxyConnection) {
diff -rN -u polipo-stable-0.9-old/polipo.texi polipo-stable-0.9-new/polipo.texi
--- polipo-stable-0.9-old/polipo.texi   2005-01-14 02:15:19.000000000 +0100
+++ polipo-stable-0.9-new/polipo.texi   2005-01-14 02:13:07.000000000 +0100
@@ -691,6 +691,7 @@
 @menu
 * Client connections::          Speaking to clients
 * Contacting servers::          Contacting servers.
+* Tuning the HTTP parser::      
 * Censoring headers::           Censoring headers.
 * Offline browsing::            Browsing with poor connectivity.
 * Server statistics::           Polipo keeps statistics about servers.
@@ -807,7 +808,7 @@
 and its optional integrity guarantees are impossible to implement
 without significantly impairing latency.}.
 
[EMAIL PROTECTED] Contacting servers, Censoring headers, Client connections, 
Network
[EMAIL PROTECTED] Contacting servers, Tuning the HTTP parser, Client 
connections, Network
 @section Contacting servers
 
 @cindex multiple addresses
@@ -842,7 +843,19 @@
 @samp{80-86, 1024-65535}.  Set this variable to @samp{1-65535} if your
 clients (and the web pages they consult!) are fully trusted.
 
[EMAIL PROTECTED] Censoring headers, Offline browsing, Contacting servers, 
Network
[EMAIL PROTECTED] Tuning the HTTP parser, Censoring headers, Contacting 
servers, Network
[EMAIL PROTECTED] Tuning the HTTP parser
+
[EMAIL PROTECTED] laxHttpParser
+
+As a number of HTTP servers and CGI scripts serve incorrect HTTP
+headers, Polipo uses a @emph{lax} parser by default, meaning that
+incorrect HTTP headers will be ignored (with a warning).  If the
+variable @code{laxHttpParser} is not set, Polipo will use a
[EMAIL PROTECTED] parser, and refuse to serve an instance unless it could
+parse all the headers.
+
[EMAIL PROTECTED] Censoring headers, Offline browsing, Tuning the HTTP parser, 
Network
 @section Censoring headers
 @cindex privacy
 @cindex anonymity

Reply via email to