Add REQUEST_BODYmaster
authorMichael Maier <mmaier@micha.(none)>
Tue, 19 Jun 2012 22:47:53 +0000 (20 00:47 +0200)
committerMichael Maier <mmaier@micha.(none)>
Tue, 19 Jun 2012 22:47:53 +0000 (20 00:47 +0200)
AUTHORS
LICENSE
README
examples/formtest.php [new file with mode: 0644]
examples/hello_world.php
examples/hello_world_forks.php
examples/return_vars.php [new file with mode: 0644]
http11_parser.c
http11_parser.h
http11_parser.rl [new file with mode: 0644]
mistral.c

diff --git a/AUTHORS b/AUTHORS
index b6b1afa..60e4796 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,2 +1,2 @@
-Michael Maier <maier@b2host.de>
+Michael Maier <michael@feel3.de>
 Stefan de Konink <stefan@konink.de>
diff --git a/LICENSE b/LICENSE
dissimilarity index 100%
index f6584f4..fb6d90b 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -1 +1,166 @@
-The license debate has not yet been started. So for now the license will be LGPL.
+GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
+
diff --git a/README b/README
index e7454d6..b21da5d 100644 (file)
--- a/README
+++ b/README
@@ -53,4 +53,4 @@ Stefan de Konink & Michael Maier, 2010-05-13
 Information request
 -------------------
 Dutch/English  -- Stefan (stefan@konink.de)
-German/English -- Michael (maier@b2host.de)
+German/English -- Michael (michael@feel3.de)
diff --git a/examples/formtest.php b/examples/formtest.php
new file mode 100644 (file)
index 0000000..ea8352a
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+function my_cool_callback($requests) {
+    $requests['HTTP_CONNECTION'] = isset($requests['HTTP_CONNECTION']) ? $requests['HTTP_CONNECTION'] : 'close';
+
+    $output = '<form method="post" enctype="multipart/form-data"><input type="text" name="test_txt_fld" /><input type="hidden" name="test_hdn_fld" value="foobar" /><input type="file" name="testfile" /><input type="submit" /></form>';
+    $output .= nl2br(print_r($requests, true));
+
+    $answer = array('status_code' => '200 OK',
+                'connection' => $requests['HTTP_CONNECTION'],
+                'content-type' => 'text/html',
+                'content-length' => strlen($output),
+                'body' => $output);
+    return $answer;
+}
+
+$port = 8081;
+
+# Bind Webserver on all ips with the port, timeout > 0 == keep-alive
+mistral_init('0.0.0.0', $port, 2);
+
+# Setup callback function which gets called after each client request
+mistral_register_callback("my_cool_callback");
+
+echo "Mistral Listening on port $port\n";
+
+# Start serving
+mistral_start();
dissimilarity index 62%
index 1564e09..86593ab 100644 (file)
@@ -1,16 +1,19 @@
-<?php
-function my_cool_callback($requests) {
-       /* Takes as argument: status_code, body, and all other headers. The above, string based still works too. */
-
-       return array('status_code' => '200 OK', 'connection' => 'close', 'content-type' => 'text/plain', 'body' => print_r($requests, true));
-}
-
-# Bind Webserver on all ips with port 8081, timeout > 0 == keep-alive
-mistral_init('0.0.0.0', 8081, 0);
-
-# Setup callback function which gets called after each client request
-mistral_register_callback("my_cool_callback");
-
-# Start serving
-mistral_start();
-?>
+<?php
+function my_cool_callback($requests) {
+    /* Takes as argument: status_code, body, and all other headers. The above, string based still works too. */
+    return array('status_code' => '200 OK', 'connection' => 'close', 'content-type' => 'text/plain', 'body' => 'Hello World!');
+}
+
+$port = 8081;
+
+# Bind Webserver on every ip with the port, timeout > 0 == keep-alive
+mistral_init('0.0.0.0', $port, 0);
+
+# Setup callback function which gets called after each client request
+mistral_register_callback("my_cool_callback");
+
+echo "Mistral Listening on port $port\n";
+
+# Start serving
+mistral_start();
+
index 9571cbe..c0dbca4 100644 (file)
@@ -2,7 +2,7 @@
 function my_cool_callback($requests) {
     $requests['HTTP_CONNECTION'] = isset($requests['HTTP_CONNECTION']) ? $requests['HTTP_CONNECTION'] : 'close';
 
-    $output = "Hello World!";
+    $output = "Hello World! PID: " . getMyPid();
     $answer = array('status_code' => '200 OK',
                 'connection' => $requests['HTTP_CONNECTION'],
                 'content-type' => 'text/html',
@@ -11,6 +11,7 @@ function my_cool_callback($requests) {
     return $answer;
 }
 
+$cntChildren = 0;
 $maxChildren = 4;
 $startport = 8080;
 while( $cntChildren < $maxChildren ) {
@@ -23,7 +24,7 @@ while( $cntChildren < $maxChildren ) {
     } elseif($pid) {
         // Parent process
     } else {
-        echo 'Spawn Child [' . getMyPid() . '] Port ' . $startport . "\n";
+        echo '[' . getMyPid() . '] Child process listening on port ' . $startport . "\n";
         mistral_init('0.0.0.0', $startport, 5);
         mistral_register_callback('my_cool_callback');
         mistral_start();
@@ -33,4 +34,4 @@ while( $cntChildren < $maxChildren ) {
 while(true) {
     sleep(1);
 }
-?>
+
diff --git a/examples/return_vars.php b/examples/return_vars.php
new file mode 100644 (file)
index 0000000..db0c6bd
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+function my_cool_callback($requests) {
+    $requests['HTTP_CONNECTION'] = isset($requests['HTTP_CONNECTION']) ? $requests['HTTP_CONNECTION'] : 'close';
+
+    $output = print_r($requests, true);
+
+    $answer = array('status_code' => '200 OK',
+                'connection' => $requests['HTTP_CONNECTION'],
+                'content-type' => 'text/plain',
+                'content-length' => strlen($output),
+                'body' => $output);
+    return $answer;
+}
+
+$port = 8081;
+
+# Bind Webserver on all ips with port 8081, timeout > 0 == keep-alive
+mistral_init('0.0.0.0', $port, 2);
+
+# Setup callback function which gets called after each client request
+mistral_register_callback("my_cool_callback");
+
+echo "Mistral Listening on port $port\n";
+
+# Start serving
+mistral_start();
dissimilarity index 80%
index 870dda4..a14238e 100644 (file)
-
-#line 1 "http11_parser.rl"
-/**
- *
- * Copyright (c) 2010, Zed A. Shaw and Mongrel2 Project Contributors.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * 
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- * 
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- * 
- *     * Neither the name of the Mongrel2 Project, Zed A. Shaw, nor the names
- *       of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written
- *       permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "http11_parser.h"
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-
-#define LEN(AT, FPC) (FPC - buffer - parser->AT)
-#define MARK(M,FPC) (parser->M = (FPC) - buffer)
-#define PTR_TO(F) (buffer + parser->F)
-
-/** Machine **/
-
-
-#line 165 "http11_parser.rl"
-
-
-/** Data **/
-
-#line 57 "http11_parser.c"
-static const int http_parser_start = 1;
-static const int http_parser_first_final = 60;
-static const int http_parser_error = 0;
-
-static const int http_parser_en_main = 1;
-
-
-#line 169 "http11_parser.rl"
-
-static int apply_element(http_parser *parser, int type, const char *begin, const char *end, int max_length)
-{
-  int len = (int)(end-begin);
-  if(len > max_length) {
-    return(0);
-  }
-  if(parser->on_element)
-    parser->on_element(parser->data, type, begin, len);
-  return(1);
-}
-
-
-
-int http_parser_init(http_parser *parser) {
-  int cs = 0;
-  
-#line 83 "http11_parser.c"
-       {
-       cs = http_parser_start;
-       }
-
-#line 186 "http11_parser.rl"
-  parser->cs = cs;
-  parser->body_start = 0;
-  parser->content_len = 0;
-  parser->mark = 0;
-  parser->nread = 0;
-  parser->field_len = 0;
-  parser->field_start = 0;
-
-  return(1);
-}
-
-/** exec **/
-size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len, size_t off)  
-{
-  if(len == 0) return 0;
-
-  const char *p, *pe;
-  int cs = parser->cs;
-
-  assert(off <= len && "offset past end of buffer");
-
-  p = buffer+off;
-  pe = buffer+len;
-
-  assert(pe - p == (int)len - (int)off && "pointers aren't same distance");
-
-  
-#line 116 "http11_parser.c"
-       {
-       if ( p == pe )
-               goto _test_eof;
-       switch ( cs )
-       {
-case 1:
-       switch( (*p) ) {
-               case 36: goto tr0;
-               case 95: goto tr0;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto tr0;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto tr0;
-       } else
-               goto tr0;
-       goto st0;
-st0:
-cs = 0;
-       goto _out;
-tr0:
-#line 52 "http11_parser.rl"
-       {MARK(mark, p); }
-       goto st2;
-st2:
-       if ( ++p == pe )
-               goto _test_eof2;
-case 2:
-#line 147 "http11_parser.c"
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st41;
-               case 95: goto st41;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st41;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st41;
-       } else
-               goto st41;
-       goto st0;
-tr2:
-#line 94 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_METHOD, PTR_TO(mark), p, 1024))
-      {p++; cs = 3; goto _out;}
-  }
-       goto st3;
-st3:
-       if ( ++p == pe )
-               goto _test_eof3;
-case 3:
-#line 173 "http11_parser.c"
-       switch( (*p) ) {
-               case 42: goto tr4;
-               case 47: goto tr5;
-               case 104: goto tr6;
-       }
-       goto st0;
-tr4:
-#line 52 "http11_parser.rl"
-       {MARK(mark, p); }
-       goto st4;
-st4:
-       if ( ++p == pe )
-               goto _test_eof4;
-case 4:
-#line 188 "http11_parser.c"
-       switch( (*p) ) {
-               case 32: goto tr7;
-               case 35: goto tr8;
-       }
-       goto st0;
-tr7:
-#line 99 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_URI, PTR_TO(mark), p, 12*1024))
-      {p++; cs = 5; goto _out;}
-  }
-       goto st5;
-tr33:
-#line 52 "http11_parser.rl"
-       {MARK(mark, p); }
-#line 79 "http11_parser.rl"
-       {
-    if(!apply_element(parser, FRAGMENT, PTR_TO(mark), p, 10*1024))
-      {p++; cs = 5; goto _out;}
-  }
-       goto st5;
-tr36:
-#line 79 "http11_parser.rl"
-       {
-    if(!apply_element(parser, FRAGMENT, PTR_TO(mark), p, 10*1024))
-      {p++; cs = 5; goto _out;}
-  }
-       goto st5;
-tr40:
-#line 89 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_PATH, PTR_TO(mark), p, 1024))
-      {p++; cs = 5; goto _out;}
-  }
-#line 99 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_URI, PTR_TO(mark), p, 12*1024))
-      {p++; cs = 5; goto _out;}
-  }
-       goto st5;
-tr51:
-#line 104 "http11_parser.rl"
-       {MARK(query_start, p); }
-#line 106 "http11_parser.rl"
-       {
-    if(!apply_element(parser, QUERY_STRING, PTR_TO(query_start), p, 10*1024))
-      {p++; cs = 5; goto _out;}
-  }
-#line 99 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_URI, PTR_TO(mark), p, 12*1024))
-      {p++; cs = 5; goto _out;}
-  }
-       goto st5;
-tr55:
-#line 106 "http11_parser.rl"
-       {
-    if(!apply_element(parser, QUERY_STRING, PTR_TO(query_start), p, 10*1024))
-      {p++; cs = 5; goto _out;}
-  }
-#line 99 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_URI, PTR_TO(mark), p, 12*1024))
-      {p++; cs = 5; goto _out;}
-  }
-       goto st5;
-st5:
-       if ( ++p == pe )
-               goto _test_eof5;
-case 5:
-#line 259 "http11_parser.c"
-       if ( (*p) == 72 )
-               goto tr9;
-       goto st0;
-tr9:
-#line 52 "http11_parser.rl"
-       {MARK(mark, p); }
-       goto st6;
-st6:
-       if ( ++p == pe )
-               goto _test_eof6;
-case 6:
-#line 271 "http11_parser.c"
-       if ( (*p) == 84 )
-               goto st7;
-       goto st0;
-st7:
-       if ( ++p == pe )
-               goto _test_eof7;
-case 7:
-       if ( (*p) == 84 )
-               goto st8;
-       goto st0;
-st8:
-       if ( ++p == pe )
-               goto _test_eof8;
-case 8:
-       if ( (*p) == 80 )
-               goto st9;
-       goto st0;
-st9:
-       if ( ++p == pe )
-               goto _test_eof9;
-case 9:
-       if ( (*p) == 47 )
-               goto st10;
-       goto st0;
-st10:
-       if ( ++p == pe )
-               goto _test_eof10;
-case 10:
-       if ( (*p) == 49 )
-               goto st11;
-       goto st0;
-st11:
-       if ( ++p == pe )
-               goto _test_eof11;
-case 11:
-       if ( (*p) == 46 )
-               goto st12;
-       goto st0;
-st12:
-       if ( ++p == pe )
-               goto _test_eof12;
-case 12:
-       if ( 48 <= (*p) && (*p) <= 49 )
-               goto st13;
-       goto st0;
-st13:
-       if ( ++p == pe )
-               goto _test_eof13;
-case 13:
-       switch( (*p) ) {
-               case 10: goto tr17;
-               case 13: goto tr18;
-       }
-       goto st0;
-tr17:
-#line 84 "http11_parser.rl"
-       {
-    if(!apply_element(parser, HTTP_VERSION, PTR_TO(mark), p, 10))
-      {p++; cs = 14; goto _out;}
-  }
-       goto st14;
-tr25:
-#line 60 "http11_parser.rl"
-       { MARK(mark, p); }
-#line 62 "http11_parser.rl"
-       {
-    if(parser->http_field != NULL) {
-      parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
-    }
-  }
-       goto st14;
-tr29:
-#line 62 "http11_parser.rl"
-       {
-    if(parser->http_field != NULL) {
-      parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
-    }
-  }
-       goto st14;
-st14:
-       if ( ++p == pe )
-               goto _test_eof14;
-case 14:
-#line 355 "http11_parser.c"
-       switch( (*p) ) {
-               case 10: goto tr19;
-               case 13: goto st15;
-               case 33: goto tr21;
-               case 124: goto tr21;
-               case 126: goto tr21;
-       }
-       if ( (*p) < 45 ) {
-               if ( (*p) > 39 ) {
-                       if ( 42 <= (*p) && (*p) <= 43 )
-                               goto tr21;
-               } else if ( (*p) >= 35 )
-                       goto tr21;
-       } else if ( (*p) > 46 ) {
-               if ( (*p) < 65 ) {
-                       if ( 48 <= (*p) && (*p) <= 57 )
-                               goto tr21;
-               } else if ( (*p) > 90 ) {
-                       if ( 94 <= (*p) && (*p) <= 122 )
-                               goto tr21;
-               } else
-                       goto tr21;
-       } else
-               goto tr21;
-       goto st0;
-tr19:
-#line 111 "http11_parser.rl"
-       {
-    parser->body_start = p - buffer + 1;    
-    {p++; cs = 60; goto _out;}
-  }
-       goto st60;
-st60:
-       if ( ++p == pe )
-               goto _test_eof60;
-case 60:
-#line 392 "http11_parser.c"
-       goto st0;
-st15:
-       if ( ++p == pe )
-               goto _test_eof15;
-case 15:
-       if ( (*p) == 10 )
-               goto tr19;
-       goto st0;
-tr21:
-#line 55 "http11_parser.rl"
-       { MARK(field_start, p); }
-       goto st16;
-st16:
-       if ( ++p == pe )
-               goto _test_eof16;
-case 16:
-#line 409 "http11_parser.c"
-       switch( (*p) ) {
-               case 33: goto st16;
-               case 58: goto tr23;
-               case 124: goto st16;
-               case 126: goto st16;
-       }
-       if ( (*p) < 45 ) {
-               if ( (*p) > 39 ) {
-                       if ( 42 <= (*p) && (*p) <= 43 )
-                               goto st16;
-               } else if ( (*p) >= 35 )
-                       goto st16;
-       } else if ( (*p) > 46 ) {
-               if ( (*p) < 65 ) {
-                       if ( 48 <= (*p) && (*p) <= 57 )
-                               goto st16;
-               } else if ( (*p) > 90 ) {
-                       if ( 94 <= (*p) && (*p) <= 122 )
-                               goto st16;
-               } else
-                       goto st16;
-       } else
-               goto st16;
-       goto st0;
-tr23:
-#line 56 "http11_parser.rl"
-       { 
-    parser->field_len = LEN(field_start, p);
-  }
-       goto st17;
-tr27:
-#line 60 "http11_parser.rl"
-       { MARK(mark, p); }
-       goto st17;
-st17:
-       if ( ++p == pe )
-               goto _test_eof17;
-case 17:
-#line 448 "http11_parser.c"
-       switch( (*p) ) {
-               case 10: goto tr25;
-               case 13: goto tr26;
-               case 32: goto tr27;
-       }
-       goto tr24;
-tr24:
-#line 60 "http11_parser.rl"
-       { MARK(mark, p); }
-       goto st18;
-st18:
-       if ( ++p == pe )
-               goto _test_eof18;
-case 18:
-#line 463 "http11_parser.c"
-       switch( (*p) ) {
-               case 10: goto tr29;
-               case 13: goto tr30;
-       }
-       goto st18;
-tr18:
-#line 84 "http11_parser.rl"
-       {
-    if(!apply_element(parser, HTTP_VERSION, PTR_TO(mark), p, 10))
-      {p++; cs = 19; goto _out;}
-  }
-       goto st19;
-tr26:
-#line 60 "http11_parser.rl"
-       { MARK(mark, p); }
-#line 62 "http11_parser.rl"
-       {
-    if(parser->http_field != NULL) {
-      parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
-    }
-  }
-       goto st19;
-tr30:
-#line 62 "http11_parser.rl"
-       {
-    if(parser->http_field != NULL) {
-      parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
-    }
-  }
-       goto st19;
-st19:
-       if ( ++p == pe )
-               goto _test_eof19;
-case 19:
-#line 498 "http11_parser.c"
-       if ( (*p) == 10 )
-               goto st14;
-       goto st0;
-tr8:
-#line 99 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_URI, PTR_TO(mark), p, 12*1024))
-      {p++; cs = 20; goto _out;}
-  }
-       goto st20;
-tr41:
-#line 89 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_PATH, PTR_TO(mark), p, 1024))
-      {p++; cs = 20; goto _out;}
-  }
-#line 99 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_URI, PTR_TO(mark), p, 12*1024))
-      {p++; cs = 20; goto _out;}
-  }
-       goto st20;
-tr52:
-#line 104 "http11_parser.rl"
-       {MARK(query_start, p); }
-#line 106 "http11_parser.rl"
-       {
-    if(!apply_element(parser, QUERY_STRING, PTR_TO(query_start), p, 10*1024))
-      {p++; cs = 20; goto _out;}
-  }
-#line 99 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_URI, PTR_TO(mark), p, 12*1024))
-      {p++; cs = 20; goto _out;}
-  }
-       goto st20;
-tr56:
-#line 106 "http11_parser.rl"
-       {
-    if(!apply_element(parser, QUERY_STRING, PTR_TO(query_start), p, 10*1024))
-      {p++; cs = 20; goto _out;}
-  }
-#line 99 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_URI, PTR_TO(mark), p, 12*1024))
-      {p++; cs = 20; goto _out;}
-  }
-       goto st20;
-st20:
-       if ( ++p == pe )
-               goto _test_eof20;
-case 20:
-#line 551 "http11_parser.c"
-       switch( (*p) ) {
-               case 32: goto tr33;
-               case 37: goto tr34;
-               case 60: goto st0;
-               case 62: goto st0;
-               case 127: goto st0;
-       }
-       if ( (*p) > 31 ) {
-               if ( 34 <= (*p) && (*p) <= 35 )
-                       goto st0;
-       } else if ( (*p) >= 0 )
-               goto st0;
-       goto tr32;
-tr32:
-#line 52 "http11_parser.rl"
-       {MARK(mark, p); }
-       goto st21;
-st21:
-       if ( ++p == pe )
-               goto _test_eof21;
-case 21:
-#line 573 "http11_parser.c"
-       switch( (*p) ) {
-               case 32: goto tr36;
-               case 37: goto st22;
-               case 60: goto st0;
-               case 62: goto st0;
-               case 127: goto st0;
-       }
-       if ( (*p) > 31 ) {
-               if ( 34 <= (*p) && (*p) <= 35 )
-                       goto st0;
-       } else if ( (*p) >= 0 )
-               goto st0;
-       goto st21;
-tr34:
-#line 52 "http11_parser.rl"
-       {MARK(mark, p); }
-       goto st22;
-st22:
-       if ( ++p == pe )
-               goto _test_eof22;
-case 22:
-#line 595 "http11_parser.c"
-       if ( (*p) < 65 ) {
-               if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st23;
-       } else if ( (*p) > 70 ) {
-               if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st23;
-       } else
-               goto st23;
-       goto st0;
-st23:
-       if ( ++p == pe )
-               goto _test_eof23;
-case 23:
-       if ( (*p) < 65 ) {
-               if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st21;
-       } else if ( (*p) > 70 ) {
-               if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st21;
-       } else
-               goto st21;
-       goto st0;
-tr5:
-#line 52 "http11_parser.rl"
-       {MARK(mark, p); }
-       goto st24;
-st24:
-       if ( ++p == pe )
-               goto _test_eof24;
-case 24:
-#line 626 "http11_parser.c"
-       switch( (*p) ) {
-               case 32: goto tr40;
-               case 34: goto st0;
-               case 35: goto tr41;
-               case 37: goto st25;
-               case 59: goto tr43;
-               case 60: goto st0;
-               case 62: goto st0;
-               case 63: goto tr44;
-               case 127: goto st0;
-       }
-       if ( 0 <= (*p) && (*p) <= 31 )
-               goto st0;
-       goto st24;
-st25:
-       if ( ++p == pe )
-               goto _test_eof25;
-case 25:
-       if ( (*p) < 65 ) {
-               if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st26;
-       } else if ( (*p) > 70 ) {
-               if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st26;
-       } else
-               goto st26;
-       goto st0;
-st26:
-       if ( ++p == pe )
-               goto _test_eof26;
-case 26:
-       if ( (*p) < 65 ) {
-               if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st24;
-       } else if ( (*p) > 70 ) {
-               if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st24;
-       } else
-               goto st24;
-       goto st0;
-tr43:
-#line 89 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_PATH, PTR_TO(mark), p, 1024))
-      {p++; cs = 27; goto _out;}
-  }
-       goto st27;
-st27:
-       if ( ++p == pe )
-               goto _test_eof27;
-case 27:
-#line 678 "http11_parser.c"
-       switch( (*p) ) {
-               case 32: goto tr7;
-               case 34: goto st0;
-               case 35: goto tr8;
-               case 37: goto st28;
-               case 60: goto st0;
-               case 62: goto st0;
-               case 63: goto st30;
-               case 127: goto st0;
-       }
-       if ( 0 <= (*p) && (*p) <= 31 )
-               goto st0;
-       goto st27;
-st28:
-       if ( ++p == pe )
-               goto _test_eof28;
-case 28:
-       if ( (*p) < 65 ) {
-               if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st29;
-       } else if ( (*p) > 70 ) {
-               if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st29;
-       } else
-               goto st29;
-       goto st0;
-st29:
-       if ( ++p == pe )
-               goto _test_eof29;
-case 29:
-       if ( (*p) < 65 ) {
-               if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st27;
-       } else if ( (*p) > 70 ) {
-               if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st27;
-       } else
-               goto st27;
-       goto st0;
-tr44:
-#line 89 "http11_parser.rl"
-       {
-    if(!apply_element(parser, REQUEST_PATH, PTR_TO(mark), p, 1024))
-      {p++; cs = 30; goto _out;}
-  }
-       goto st30;
-st30:
-       if ( ++p == pe )
-               goto _test_eof30;
-case 30:
-#line 729 "http11_parser.c"
-       switch( (*p) ) {
-               case 32: goto tr51;
-               case 34: goto st0;
-               case 35: goto tr52;
-               case 37: goto tr53;
-               case 60: goto st0;
-               case 62: goto st0;
-               case 127: goto st0;
-       }
-       if ( 0 <= (*p) && (*p) <= 31 )
-               goto st0;
-       goto tr50;
-tr50:
-#line 104 "http11_parser.rl"
-       {MARK(query_start, p); }
-       goto st31;
-st31:
-       if ( ++p == pe )
-               goto _test_eof31;
-case 31:
-#line 750 "http11_parser.c"
-       switch( (*p) ) {
-               case 32: goto tr55;
-               case 34: goto st0;
-               case 35: goto tr56;
-               case 37: goto st32;
-               case 60: goto st0;
-               case 62: goto st0;
-               case 127: goto st0;
-       }
-       if ( 0 <= (*p) && (*p) <= 31 )
-               goto st0;
-       goto st31;
-tr53:
-#line 104 "http11_parser.rl"
-       {MARK(query_start, p); }
-       goto st32;
-st32:
-       if ( ++p == pe )
-               goto _test_eof32;
-case 32:
-#line 771 "http11_parser.c"
-       if ( (*p) < 65 ) {
-               if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st33;
-       } else if ( (*p) > 70 ) {
-               if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st33;
-       } else
-               goto st33;
-       goto st0;
-st33:
-       if ( ++p == pe )
-               goto _test_eof33;
-case 33:
-       if ( (*p) < 65 ) {
-               if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st31;
-       } else if ( (*p) > 70 ) {
-               if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st31;
-       } else
-               goto st31;
-       goto st0;
-tr6:
-#line 52 "http11_parser.rl"
-       {MARK(mark, p); }
-       goto st34;
-st34:
-       if ( ++p == pe )
-               goto _test_eof34;
-case 34:
-#line 802 "http11_parser.c"
-       if ( (*p) == 116 )
-               goto st35;
-       goto st0;
-st35:
-       if ( ++p == pe )
-               goto _test_eof35;
-case 35:
-       if ( (*p) == 116 )
-               goto st36;
-       goto st0;
-st36:
-       if ( ++p == pe )
-               goto _test_eof36;
-case 36:
-       if ( (*p) == 112 )
-               goto st37;
-       goto st0;
-st37:
-       if ( ++p == pe )
-               goto _test_eof37;
-case 37:
-       if ( (*p) == 58 )
-               goto st38;
-       goto st0;
-st38:
-       if ( ++p == pe )
-               goto _test_eof38;
-case 38:
-       switch( (*p) ) {
-               case 32: goto tr7;
-               case 34: goto st0;
-               case 35: goto tr8;
-               case 37: goto st39;
-               case 60: goto st0;
-               case 62: goto st0;
-               case 127: goto st0;
-       }
-       if ( 0 <= (*p) && (*p) <= 31 )
-               goto st0;
-       goto st38;
-st39:
-       if ( ++p == pe )
-               goto _test_eof39;
-case 39:
-       if ( (*p) < 65 ) {
-               if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st40;
-       } else if ( (*p) > 70 ) {
-               if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st40;
-       } else
-               goto st40;
-       goto st0;
-st40:
-       if ( ++p == pe )
-               goto _test_eof40;
-case 40:
-       if ( (*p) < 65 ) {
-               if ( 48 <= (*p) && (*p) <= 57 )
-                       goto st38;
-       } else if ( (*p) > 70 ) {
-               if ( 97 <= (*p) && (*p) <= 102 )
-                       goto st38;
-       } else
-               goto st38;
-       goto st0;
-st41:
-       if ( ++p == pe )
-               goto _test_eof41;
-case 41:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st42;
-               case 95: goto st42;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st42;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st42;
-       } else
-               goto st42;
-       goto st0;
-st42:
-       if ( ++p == pe )
-               goto _test_eof42;
-case 42:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st43;
-               case 95: goto st43;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st43;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st43;
-       } else
-               goto st43;
-       goto st0;
-st43:
-       if ( ++p == pe )
-               goto _test_eof43;
-case 43:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st44;
-               case 95: goto st44;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st44;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st44;
-       } else
-               goto st44;
-       goto st0;
-st44:
-       if ( ++p == pe )
-               goto _test_eof44;
-case 44:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st45;
-               case 95: goto st45;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st45;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st45;
-       } else
-               goto st45;
-       goto st0;
-st45:
-       if ( ++p == pe )
-               goto _test_eof45;
-case 45:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st46;
-               case 95: goto st46;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st46;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st46;
-       } else
-               goto st46;
-       goto st0;
-st46:
-       if ( ++p == pe )
-               goto _test_eof46;
-case 46:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st47;
-               case 95: goto st47;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st47;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st47;
-       } else
-               goto st47;
-       goto st0;
-st47:
-       if ( ++p == pe )
-               goto _test_eof47;
-case 47:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st48;
-               case 95: goto st48;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st48;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st48;
-       } else
-               goto st48;
-       goto st0;
-st48:
-       if ( ++p == pe )
-               goto _test_eof48;
-case 48:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st49;
-               case 95: goto st49;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st49;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st49;
-       } else
-               goto st49;
-       goto st0;
-st49:
-       if ( ++p == pe )
-               goto _test_eof49;
-case 49:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st50;
-               case 95: goto st50;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st50;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st50;
-       } else
-               goto st50;
-       goto st0;
-st50:
-       if ( ++p == pe )
-               goto _test_eof50;
-case 50:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st51;
-               case 95: goto st51;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st51;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st51;
-       } else
-               goto st51;
-       goto st0;
-st51:
-       if ( ++p == pe )
-               goto _test_eof51;
-case 51:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st52;
-               case 95: goto st52;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st52;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st52;
-       } else
-               goto st52;
-       goto st0;
-st52:
-       if ( ++p == pe )
-               goto _test_eof52;
-case 52:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st53;
-               case 95: goto st53;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st53;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st53;
-       } else
-               goto st53;
-       goto st0;
-st53:
-       if ( ++p == pe )
-               goto _test_eof53;
-case 53:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st54;
-               case 95: goto st54;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st54;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st54;
-       } else
-               goto st54;
-       goto st0;
-st54:
-       if ( ++p == pe )
-               goto _test_eof54;
-case 54:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st55;
-               case 95: goto st55;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st55;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st55;
-       } else
-               goto st55;
-       goto st0;
-st55:
-       if ( ++p == pe )
-               goto _test_eof55;
-case 55:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st56;
-               case 95: goto st56;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st56;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st56;
-       } else
-               goto st56;
-       goto st0;
-st56:
-       if ( ++p == pe )
-               goto _test_eof56;
-case 56:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st57;
-               case 95: goto st57;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st57;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st57;
-       } else
-               goto st57;
-       goto st0;
-st57:
-       if ( ++p == pe )
-               goto _test_eof57;
-case 57:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st58;
-               case 95: goto st58;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st58;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st58;
-       } else
-               goto st58;
-       goto st0;
-st58:
-       if ( ++p == pe )
-               goto _test_eof58;
-case 58:
-       switch( (*p) ) {
-               case 32: goto tr2;
-               case 36: goto st59;
-               case 95: goto st59;
-       }
-       if ( (*p) < 48 ) {
-               if ( 45 <= (*p) && (*p) <= 46 )
-                       goto st59;
-       } else if ( (*p) > 57 ) {
-               if ( 65 <= (*p) && (*p) <= 90 )
-                       goto st59;
-       } else
-               goto st59;
-       goto st0;
-st59:
-       if ( ++p == pe )
-               goto _test_eof59;
-case 59:
-       if ( (*p) == 32 )
-               goto tr2;
-       goto st0;
-       }
-       _test_eof2: cs = 2; goto _test_eof; 
-       _test_eof3: cs = 3; goto _test_eof; 
-       _test_eof4: cs = 4; goto _test_eof; 
-       _test_eof5: cs = 5; goto _test_eof; 
-       _test_eof6: cs = 6; goto _test_eof; 
-       _test_eof7: cs = 7; goto _test_eof; 
-       _test_eof8: cs = 8; goto _test_eof; 
-       _test_eof9: cs = 9; goto _test_eof; 
-       _test_eof10: cs = 10; goto _test_eof; 
-       _test_eof11: cs = 11; goto _test_eof; 
-       _test_eof12: cs = 12; goto _test_eof; 
-       _test_eof13: cs = 13; goto _test_eof; 
-       _test_eof14: cs = 14; goto _test_eof; 
-       _test_eof60: cs = 60; goto _test_eof; 
-       _test_eof15: cs = 15; goto _test_eof; 
-       _test_eof16: cs = 16; goto _test_eof; 
-       _test_eof17: cs = 17; goto _test_eof; 
-       _test_eof18: cs = 18; goto _test_eof; 
-       _test_eof19: cs = 19; goto _test_eof; 
-       _test_eof20: cs = 20; goto _test_eof; 
-       _test_eof21: cs = 21; goto _test_eof; 
-       _test_eof22: cs = 22; goto _test_eof; 
-       _test_eof23: cs = 23; goto _test_eof; 
-       _test_eof24: cs = 24; goto _test_eof; 
-       _test_eof25: cs = 25; goto _test_eof; 
-       _test_eof26: cs = 26; goto _test_eof; 
-       _test_eof27: cs = 27; goto _test_eof; 
-       _test_eof28: cs = 28; goto _test_eof; 
-       _test_eof29: cs = 29; goto _test_eof; 
-       _test_eof30: cs = 30; goto _test_eof; 
-       _test_eof31: cs = 31; goto _test_eof; 
-       _test_eof32: cs = 32; goto _test_eof; 
-       _test_eof33: cs = 33; goto _test_eof; 
-       _test_eof34: cs = 34; goto _test_eof; 
-       _test_eof35: cs = 35; goto _test_eof; 
-       _test_eof36: cs = 36; goto _test_eof; 
-       _test_eof37: cs = 37; goto _test_eof; 
-       _test_eof38: cs = 38; goto _test_eof; 
-       _test_eof39: cs = 39; goto _test_eof; 
-       _test_eof40: cs = 40; goto _test_eof; 
-       _test_eof41: cs = 41; goto _test_eof; 
-       _test_eof42: cs = 42; goto _test_eof; 
-       _test_eof43: cs = 43; goto _test_eof; 
-       _test_eof44: cs = 44; goto _test_eof; 
-       _test_eof45: cs = 45; goto _test_eof; 
-       _test_eof46: cs = 46; goto _test_eof; 
-       _test_eof47: cs = 47; goto _test_eof; 
-       _test_eof48: cs = 48; goto _test_eof; 
-       _test_eof49: cs = 49; goto _test_eof; 
-       _test_eof50: cs = 50; goto _test_eof; 
-       _test_eof51: cs = 51; goto _test_eof; 
-       _test_eof52: cs = 52; goto _test_eof; 
-       _test_eof53: cs = 53; goto _test_eof; 
-       _test_eof54: cs = 54; goto _test_eof; 
-       _test_eof55: cs = 55; goto _test_eof; 
-       _test_eof56: cs = 56; goto _test_eof; 
-       _test_eof57: cs = 57; goto _test_eof; 
-       _test_eof58: cs = 58; goto _test_eof; 
-       _test_eof59: cs = 59; goto _test_eof; 
-
-       _test_eof: {}
-       _out: {}
-       }
-
-#line 213 "http11_parser.rl"
-
-  assert(p <= pe && "Buffer overflow after parsing.");
-
-  if (!http_parser_has_error(parser)) {
-      parser->cs = cs;
-  }
-
-  parser->nread += p - (buffer + off);
-
-  assert(parser->nread <= len && "nread longer than length");
-  assert(parser->body_start <= len && "body starts after buffer end");
-  assert(parser->mark < len && "mark is after buffer end");
-  assert(parser->field_len <= len && "field has length longer than whole buffer");
-  assert(parser->field_start < len && "field starts after buffer end");
-
-  return(parser->nread);
-}
-
-int http_parser_finish(http_parser *parser)
-{
-  if (http_parser_has_error(parser) ) {
-    return -1;
-  } else if (http_parser_is_finished(parser) ) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-int http_parser_has_error(http_parser *parser) {
-  return parser->cs == http_parser_error;
-}
-
-int http_parser_is_finished(http_parser *parser) {
-  return parser->cs >= http_parser_first_final;
-}
+
+#line 1 "http11_parser.rl"
+/**
+ *
+ * Copyright (c) 2010, Zed A. Shaw and Mongrel2 Project Contributors.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ * 
+ *     * Neither the name of the Mongrel2 Project, Zed A. Shaw, nor the names
+ *       of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written
+ *       permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "http11_parser.h"
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#define LEN(AT, FPC) (FPC - buffer - parser->AT)
+#define MARK(M,FPC) (parser->M = (FPC) - buffer)
+#define PTR_TO(F) (buffer + parser->F)
+
+/** Machine **/
+
+
+#line 161 "http11_parser.rl"
+
+
+/** Data **/
+
+#line 57 "http11_parser.c"
+static const char _http_parser_actions[] = {
+       0, 1, 0, 1, 1, 1, 2, 1, 
+       3, 1, 4, 1, 5, 1, 6, 1, 
+       7, 1, 8, 1, 9, 1, 10, 1, 
+       12, 2, 0, 5, 2, 3, 4, 2, 
+       7, 9, 2, 11, 9, 3, 10, 11, 
+       9
+};
+
+static const short _http_parser_key_offsets[] = {
+       0, 0, 8, 17, 20, 22, 23, 24, 
+       25, 26, 27, 28, 29, 31, 33, 50, 
+       51, 67, 70, 72, 73, 82, 91, 97, 
+       103, 114, 120, 126, 136, 142, 148, 157, 
+       166, 172, 178, 179, 180, 181, 182, 191, 
+       197, 203, 212, 221, 230, 239, 248, 257, 
+       266, 275, 284, 293, 302, 311, 320, 329, 
+       338, 347, 356, 365, 366
+};
+
+static const char _http_parser_trans_keys[] = {
+       36, 95, 45, 46, 48, 57, 65, 90, 
+       32, 36, 95, 45, 46, 48, 57, 65, 
+       90, 42, 47, 104, 32, 35, 72, 84, 
+       84, 80, 47, 49, 46, 48, 49, 10, 
+       13, 10, 13, 33, 124, 126, 35, 39, 
+       42, 43, 45, 46, 48, 57, 65, 90, 
+       94, 122, 10, 33, 58, 124, 126, 35, 
+       39, 42, 43, 45, 46, 48, 57, 65, 
+       90, 94, 122, 10, 13, 32, 10, 13, 
+       10, 32, 37, 60, 62, 127, 0, 31, 
+       34, 35, 32, 37, 60, 62, 127, 0, 
+       31, 34, 35, 48, 57, 65, 70, 97, 
+       102, 48, 57, 65, 70, 97, 102, 32, 
+       34, 35, 37, 59, 60, 62, 63, 127, 
+       0, 31, 48, 57, 65, 70, 97, 102, 
+       48, 57, 65, 70, 97, 102, 32, 34, 
+       35, 37, 60, 62, 63, 127, 0, 31, 
+       48, 57, 65, 70, 97, 102, 48, 57, 
+       65, 70, 97, 102, 32, 34, 35, 37, 
+       60, 62, 127, 0, 31, 32, 34, 35, 
+       37, 60, 62, 127, 0, 31, 48, 57, 
+       65, 70, 97, 102, 48, 57, 65, 70, 
+       97, 102, 116, 116, 112, 58, 32, 34, 
+       35, 37, 60, 62, 127, 0, 31, 48, 
+       57, 65, 70, 97, 102, 48, 57, 65, 
+       70, 97, 102, 32, 36, 95, 45, 46, 
+       48, 57, 65, 90, 32, 36, 95, 45, 
+       46, 48, 57, 65, 90, 32, 36, 95, 
+       45, 46, 48, 57, 65, 90, 32, 36, 
+       95, 45, 46, 48, 57, 65, 90, 32, 
+       36, 95, 45, 46, 48, 57, 65, 90, 
+       32, 36, 95, 45, 46, 48, 57, 65, 
+       90, 32, 36, 95, 45, 46, 48, 57, 
+       65, 90, 32, 36, 95, 45, 46, 48, 
+       57, 65, 90, 32, 36, 95, 45, 46, 
+       48, 57, 65, 90, 32, 36, 95, 45, 
+       46, 48, 57, 65, 90, 32, 36, 95, 
+       45, 46, 48, 57, 65, 90, 32, 36, 
+       95, 45, 46, 48, 57, 65, 90, 32, 
+       36, 95, 45, 46, 48, 57, 65, 90, 
+       32, 36, 95, 45, 46, 48, 57, 65, 
+       90, 32, 36, 95, 45, 46, 48, 57, 
+       65, 90, 32, 36, 95, 45, 46, 48, 
+       57, 65, 90, 32, 36, 95, 45, 46, 
+       48, 57, 65, 90, 32, 36, 95, 45, 
+       46, 48, 57, 65, 90, 32, 0
+};
+
+static const char _http_parser_single_lengths[] = {
+       0, 2, 3, 3, 2, 1, 1, 1, 
+       1, 1, 1, 1, 0, 2, 5, 1, 
+       4, 3, 2, 1, 5, 5, 0, 0, 
+       9, 0, 0, 8, 0, 0, 7, 7, 
+       0, 0, 1, 1, 1, 1, 7, 0, 
+       0, 3, 3, 3, 3, 3, 3, 3, 
+       3, 3, 3, 3, 3, 3, 3, 3, 
+       3, 3, 3, 1, 0
+};
+
+static const char _http_parser_range_lengths[] = {
+       0, 3, 3, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 1, 0, 6, 0, 
+       6, 0, 0, 0, 2, 2, 3, 3, 
+       1, 3, 3, 1, 3, 3, 1, 1, 
+       3, 3, 0, 0, 0, 0, 1, 3, 
+       3, 3, 3, 3, 3, 3, 3, 3, 
+       3, 3, 3, 3, 3, 3, 3, 3, 
+       3, 3, 3, 0, 0
+};
+
+static const short _http_parser_index_offsets[] = {
+       0, 0, 6, 13, 17, 20, 22, 24, 
+       26, 28, 30, 32, 34, 36, 39, 51, 
+       53, 64, 68, 71, 73, 81, 89, 93, 
+       97, 108, 112, 116, 126, 130, 134, 143, 
+       152, 156, 160, 162, 164, 166, 168, 177, 
+       181, 185, 192, 199, 206, 213, 220, 227, 
+       234, 241, 248, 255, 262, 269, 276, 283, 
+       290, 297, 304, 311, 313
+};
+
+static const char _http_parser_indicies[] = {
+       0, 0, 0, 0, 0, 1, 2, 3, 
+       3, 3, 3, 3, 1, 4, 5, 6, 
+       1, 7, 8, 1, 9, 1, 10, 1, 
+       11, 1, 12, 1, 13, 1, 14, 1, 
+       15, 1, 16, 1, 17, 18, 1, 19, 
+       20, 21, 21, 21, 21, 21, 21, 21, 
+       21, 21, 1, 19, 1, 22, 23, 22, 
+       22, 22, 22, 22, 22, 22, 22, 1, 
+       25, 26, 27, 24, 29, 30, 28, 31, 
+       1, 33, 34, 1, 1, 1, 1, 1, 
+       32, 36, 37, 1, 1, 1, 1, 1, 
+       35, 38, 38, 38, 1, 35, 35, 35, 
+       1, 40, 1, 41, 42, 43, 1, 1, 
+       44, 1, 1, 39, 45, 45, 45, 1, 
+       39, 39, 39, 1, 7, 1, 8, 47, 
+       1, 1, 48, 1, 1, 46, 49, 49, 
+       49, 1, 46, 46, 46, 1, 51, 1, 
+       52, 53, 1, 1, 1, 1, 50, 55, 
+       1, 56, 57, 1, 1, 1, 1, 54, 
+       58, 58, 58, 1, 54, 54, 54, 1, 
+       59, 1, 60, 1, 61, 1, 62, 1, 
+       7, 1, 8, 63, 1, 1, 1, 1, 
+       62, 64, 64, 64, 1, 62, 62, 62, 
+       1, 2, 65, 65, 65, 65, 65, 1, 
+       2, 66, 66, 66, 66, 66, 1, 2, 
+       67, 67, 67, 67, 67, 1, 2, 68, 
+       68, 68, 68, 68, 1, 2, 69, 69, 
+       69, 69, 69, 1, 2, 70, 70, 70, 
+       70, 70, 1, 2, 71, 71, 71, 71, 
+       71, 1, 2, 72, 72, 72, 72, 72, 
+       1, 2, 73, 73, 73, 73, 73, 1, 
+       2, 74, 74, 74, 74, 74, 1, 2, 
+       75, 75, 75, 75, 75, 1, 2, 76, 
+       76, 76, 76, 76, 1, 2, 77, 77, 
+       77, 77, 77, 1, 2, 78, 78, 78, 
+       78, 78, 1, 2, 79, 79, 79, 79, 
+       79, 1, 2, 80, 80, 80, 80, 80, 
+       1, 2, 81, 81, 81, 81, 81, 1, 
+       2, 82, 82, 82, 82, 82, 1, 2, 
+       1, 1, 0
+};
+
+static const char _http_parser_trans_targs[] = {
+       2, 0, 3, 41, 4, 24, 34, 5, 
+       20, 6, 7, 8, 9, 10, 11, 12, 
+       13, 14, 19, 60, 15, 16, 16, 17, 
+       18, 14, 19, 17, 18, 14, 19, 14, 
+       21, 5, 22, 21, 5, 22, 23, 24, 
+       5, 20, 25, 27, 30, 26, 27, 28, 
+       30, 29, 31, 5, 20, 32, 31, 5, 
+       20, 32, 33, 35, 36, 37, 38, 39, 
+       40, 42, 43, 44, 45, 46, 47, 48, 
+       49, 50, 51, 52, 53, 54, 55, 56, 
+       57, 58, 59
+};
+
+static const char _http_parser_trans_actions[] = {
+       1, 0, 17, 0, 1, 1, 1, 19, 
+       19, 1, 0, 0, 0, 0, 0, 0, 
+       0, 13, 13, 23, 0, 3, 0, 5, 
+       7, 28, 28, 7, 0, 9, 9, 0, 
+       1, 25, 1, 0, 11, 0, 0, 0, 
+       31, 31, 0, 15, 15, 0, 0, 0, 
+       0, 0, 21, 37, 37, 21, 0, 34, 
+       34, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0
+};
+
+static const int http_parser_start = 1;
+static const int http_parser_first_final = 60;
+static const int http_parser_error = 0;
+
+static const int http_parser_en_main = 1;
+
+
+#line 165 "http11_parser.rl"
+
+static int apply_element(http_parser *parser, int type, const char *begin, const char *end, int max_length)
+{
+  int len = (int)(end-begin);
+  if(len > max_length) {
+    return(0);
+  }
+  if(parser->on_element)
+    parser->on_element(parser->data, type, begin, len);
+  return(1);
+}
+
+
+
+int http_parser_init(http_parser *parser) {
+  int cs = 0;
+  
+#line 256 "http11_parser.c"
+       {
+       cs = http_parser_start;
+       }
+
+#line 182 "http11_parser.rl"
+  parser->cs = cs;
+  parser->body_start = 0;
+  parser->content_len = 0;
+  parser->mark = 0;
+  parser->nread = 0;
+  parser->field_len = 0;
+  parser->field_start = 0;
+
+  return(1);
+}
+
+/** exec **/
+size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len, size_t off)  
+{
+  if(len == 0) return 0;
+
+  const char *p, *pe;
+  int cs = parser->cs;
+
+  assert(off <= len && "offset past end of buffer");
+
+  p = buffer+off;
+  pe = buffer+len;
+
+  assert(pe - p == (int)len - (int)off && "pointers aren't same distance");
+
+  
+#line 289 "http11_parser.c"
+       {
+       int _klen;
+       unsigned int _trans;
+       const char *_acts;
+       unsigned int _nacts;
+       const char *_keys;
+
+       if ( p == pe )
+               goto _test_eof;
+       if ( cs == 0 )
+               goto _out;
+_resume:
+       _keys = _http_parser_trans_keys + _http_parser_key_offsets[cs];
+       _trans = _http_parser_index_offsets[cs];
+
+       _klen = _http_parser_single_lengths[cs];
+       if ( _klen > 0 ) {
+               const char *_lower = _keys;
+               const char *_mid;
+               const char *_upper = _keys + _klen - 1;
+               while (1) {
+                       if ( _upper < _lower )
+                               break;
+
+                       _mid = _lower + ((_upper-_lower) >> 1);
+                       if ( (*p) < *_mid )
+                               _upper = _mid - 1;
+                       else if ( (*p) > *_mid )
+                               _lower = _mid + 1;
+                       else {
+                               _trans += (_mid - _keys);
+                               goto _match;
+                       }
+               }
+               _keys += _klen;
+               _trans += _klen;
+       }
+
+       _klen = _http_parser_range_lengths[cs];
+       if ( _klen > 0 ) {
+               const char *_lower = _keys;
+               const char *_mid;
+               const char *_upper = _keys + (_klen<<1) - 2;
+               while (1) {
+                       if ( _upper < _lower )
+                               break;
+
+                       _mid = _lower + (((_upper-_lower) >> 1) & ~1);
+                       if ( (*p) < _mid[0] )
+                               _upper = _mid - 2;
+                       else if ( (*p) > _mid[1] )
+                               _lower = _mid + 2;
+                       else {
+                               _trans += ((_mid - _keys)>>1);
+                               goto _match;
+                       }
+               }
+               _trans += _klen;
+       }
+
+_match:
+       _trans = _http_parser_indicies[_trans];
+       cs = _http_parser_trans_targs[_trans];
+
+       if ( _http_parser_trans_actions[_trans] == 0 )
+               goto _again;
+
+       _acts = _http_parser_actions + _http_parser_trans_actions[_trans];
+       _nacts = (unsigned int) *_acts++;
+       while ( _nacts-- > 0 )
+       {
+               switch ( *_acts++ )
+               {
+       case 0:
+#line 52 "http11_parser.rl"
+       {MARK(mark, p); }
+       break;
+       case 1:
+#line 55 "http11_parser.rl"
+       { MARK(field_start, p); }
+       break;
+       case 2:
+#line 56 "http11_parser.rl"
+       { 
+    parser->field_len = LEN(field_start, p);
+  }
+       break;
+       case 3:
+#line 60 "http11_parser.rl"
+       { MARK(mark, p); }
+       break;
+       case 4:
+#line 62 "http11_parser.rl"
+       {
+    if(parser->http_field != NULL) {
+      parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
+    }
+  }
+       break;
+       case 5:
+#line 73 "http11_parser.rl"
+       {
+    if(!apply_element(parser, FRAGMENT, PTR_TO(mark), p, 10*1024))
+      {p++; goto _out; }
+  }
+       break;
+       case 6:
+#line 78 "http11_parser.rl"
+       {
+    if(!apply_element(parser, HTTP_VERSION, PTR_TO(mark), p, 10))
+      {p++; goto _out; }
+  }
+       break;
+       case 7:
+#line 83 "http11_parser.rl"
+       {
+    if(!apply_element(parser, REQUEST_PATH, PTR_TO(mark), p, 1024))
+      {p++; goto _out; }
+  }
+       break;
+       case 8:
+#line 88 "http11_parser.rl"
+       {
+    if(!apply_element(parser, REQUEST_METHOD, PTR_TO(mark), p, 1024))
+      {p++; goto _out; }
+  }
+       break;
+       case 9:
+#line 93 "http11_parser.rl"
+       {
+    if(!apply_element(parser, REQUEST_URI, PTR_TO(mark), p, 12*1024))
+      {p++; goto _out; }
+  }
+       break;
+       case 10:
+#line 98 "http11_parser.rl"
+       {MARK(query_start, p); }
+       break;
+       case 11:
+#line 100 "http11_parser.rl"
+       {
+    if(!apply_element(parser, QUERY_STRING, PTR_TO(query_start), p, 10*1024))
+      {p++; goto _out; }
+  }
+       break;
+       case 12:
+#line 105 "http11_parser.rl"
+       {
+    parser->body_start = p - buffer + 1;    
+    if(parser->header_done != NULL)
+      parser->header_done(parser->data, REQUEST_BODY, p + 1, pe - p - 1);
+    {p++; goto _out; }
+  }
+       break;
+#line 444 "http11_parser.c"
+               }
+       }
+
+_again:
+       if ( cs == 0 )
+               goto _out;
+       if ( ++p != pe )
+               goto _resume;
+       _test_eof: {}
+       _out: {}
+       }
+
+#line 209 "http11_parser.rl"
+
+  assert(p <= pe && "Buffer overflow after parsing.");
+
+  if (!http_parser_has_error(parser)) {
+      parser->cs = cs;
+  }
+
+  parser->nread += p - (buffer + off);
+
+  assert(parser->nread <= len && "nread longer than length");
+  assert(parser->body_start <= len && "body starts after buffer end");
+  assert(parser->mark < len && "mark is after buffer end");
+  assert(parser->field_len <= len && "field has length longer than whole buffer");
+  assert(parser->field_start < len && "field starts after buffer end");
+
+  return(parser->nread);
+}
+
+int http_parser_finish(http_parser *parser)
+{
+  if (http_parser_has_error(parser) ) {
+    return -1;
+  } else if (http_parser_is_finished(parser) ) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+int http_parser_has_error(http_parser *parser) {
+  return parser->cs == http_parser_error;
+}
+
+int http_parser_is_finished(http_parser *parser) {
+  return parser->cs >= http_parser_first_final;
+}
index c7f0ae1..2a64836 100644 (file)
@@ -12,6 +12,7 @@ enum { CONTENT_LENGTH
      , REQUEST_PATH
      , REQUEST_METHOD
      , REQUEST_URI
+     , REQUEST_BODY
      };
 
 typedef struct http_parser { 
@@ -28,6 +29,7 @@ typedef struct http_parser {
 
   field_cb http_field;
   element_cb on_element;  
+  element_cb header_done;
 } http_parser;
 
 int http_parser_init(http_parser *parser);
diff --git a/http11_parser.rl b/http11_parser.rl
new file mode 100644 (file)
index 0000000..878858b
--- /dev/null
@@ -0,0 +1,244 @@
+/**
+ *
+ * Copyright (c) 2010, Zed A. Shaw and Mongrel2 Project Contributors.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ * 
+ *     * Neither the name of the Mongrel2 Project, Zed A. Shaw, nor the names
+ *       of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written
+ *       permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "http11_parser.h"
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#define LEN(AT, FPC) (FPC - buffer - parser->AT)
+#define MARK(M,FPC) (parser->M = (FPC) - buffer)
+#define PTR_TO(F) (buffer + parser->F)
+
+/** Machine **/
+
+%%{
+  
+  machine http_parser;
+
+  action mark {MARK(mark, fpc); }
+
+
+  action start_field { MARK(field_start, fpc); }
+  action write_field { 
+    parser->field_len = LEN(field_start, fpc);
+  }
+
+  action start_value { MARK(mark, fpc); }
+
+  action write_value {
+    if(parser->http_field != NULL) {
+      parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, fpc));
+    }
+  }
+
+  action content_type {
+    if(!apply_element(parser, CONTENT_TYPE, PTR_TO(mark), fpc, 10*1024))
+      fbreak;
+  }
+
+  action fragment {
+    if(!apply_element(parser, FRAGMENT, PTR_TO(mark), fpc, 10*1024))
+      fbreak;
+  }
+
+  action http_version {
+    if(!apply_element(parser, HTTP_VERSION, PTR_TO(mark), fpc, 10))
+      fbreak;
+  }
+
+  action request_path {
+    if(!apply_element(parser, REQUEST_PATH, PTR_TO(mark), fpc, 1024))
+      fbreak;
+  }
+
+  action request_method {
+    if(!apply_element(parser, REQUEST_METHOD, PTR_TO(mark), fpc, 1024))
+      fbreak;
+  }
+
+  action request_uri {
+    if(!apply_element(parser, REQUEST_URI, PTR_TO(mark), fpc, 12*1024))
+      fbreak;
+  }
+
+  action start_query {MARK(query_start, fpc); }
+
+  action query_string {
+    if(!apply_element(parser, QUERY_STRING, PTR_TO(query_start), fpc, 10*1024))
+      fbreak;
+  }
+
+  action done {
+    parser->body_start = fpc - buffer + 1;    
+    if(parser->header_done != NULL)
+      parser->header_done(parser->data, REQUEST_BODY, fpc + 1, pe - fpc - 1);
+    fbreak;
+  }
+
+#### HTTP PROTOCOL GRAMMAR
+# line endings
+  CRLF = ("\r\n" | "\n");
+
+# character types
+  CTL = (cntrl | 127);
+  safe = ("$" | "-" | "_" | ".");
+  extra = ("!" | "*" | "'" | "(" | ")" | ",");
+  reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
+  unsafe = (CTL | " " | "\"" | "#" | "%" | "<" | ">");
+  national = any -- (alpha | digit | reserved | extra | safe | unsafe);
+  unreserved = (alpha | digit | safe | extra | national);
+  escape = ("%" xdigit xdigit);
+  uchar = (unreserved | escape);
+  pchar = (uchar | ":" | "@" | "&" | "=" | "+");
+  tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
+
+# elements
+  token = (ascii -- (CTL | tspecials));
+
+# URI schemes and absolute paths
+  scheme = "http";
+  absolute_uri = (scheme ":" (uchar | reserved )*);
+
+  path = ( pchar+ ( "/" pchar* )* ) ;
+  query = ( uchar | reserved )* %query_string ;
+  param = ( pchar | "/" )* ;
+  params = ( param ( ";" param )* ) ;
+  rel_path = ( path? %request_path (";" params)? ) ("?" %start_query query)?;
+  absolute_path = ( "/"+ rel_path );
+
+  Request_URI = ( "*" | absolute_uri | absolute_path ) >mark %request_uri;
+  Fragment = ( uchar | reserved )* >mark %fragment;
+  Method = ( upper | digit | safe ){1,20} >mark %request_method;
+
+  http_number = ( "1." ("0" | "1") ) ;
+  HTTP_Version = ( "HTTP/" http_number ) >mark %http_version ;
+  Request_Line = ( Method " " Request_URI ("#" Fragment){0,1} " " HTTP_Version CRLF ) ;
+
+  field_name = ( token -- ":" )+ >start_field %write_field;
+
+  field_value = any* >start_value %write_value;
+
+  message_header = field_name ":" " "* field_value :> CRLF;
+
+  Request = Request_Line ( message_header )* ( CRLF );
+
+main := (Request ) @done;
+
+}%%
+
+/** Data **/
+%% write data;
+
+static int apply_element(http_parser *parser, int type, const char *begin, const char *end, int max_length)
+{
+  int len = (int)(end-begin);
+  if(len > max_length) {
+    return(0);
+  }
+  if(parser->on_element)
+    parser->on_element(parser->data, type, begin, len);
+  return(1);
+}
+
+
+
+int http_parser_init(http_parser *parser) {
+  int cs = 0;
+  %% write init;
+  parser->cs = cs;
+  parser->body_start = 0;
+  parser->content_len = 0;
+  parser->mark = 0;
+  parser->nread = 0;
+  parser->field_len = 0;
+  parser->field_start = 0;
+
+  return(1);
+}
+
+/** exec **/
+size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len, size_t off)  
+{
+  if(len == 0) return 0;
+
+  const char *p, *pe;
+  int cs = parser->cs;
+
+  assert(off <= len && "offset past end of buffer");
+
+  p = buffer+off;
+  pe = buffer+len;
+
+  assert(pe - p == (int)len - (int)off && "pointers aren't same distance");
+
+  %% write exec;
+
+  assert(p <= pe && "Buffer overflow after parsing.");
+
+  if (!http_parser_has_error(parser)) {
+      parser->cs = cs;
+  }
+
+  parser->nread += p - (buffer + off);
+
+  assert(parser->nread <= len && "nread longer than length");
+  assert(parser->body_start <= len && "body starts after buffer end");
+  assert(parser->mark < len && "mark is after buffer end");
+  assert(parser->field_len <= len && "field has length longer than whole buffer");
+  assert(parser->field_start < len && "field starts after buffer end");
+
+  return(parser->nread);
+}
+
+int http_parser_finish(http_parser *parser)
+{
+  if (http_parser_has_error(parser) ) {
+    return -1;
+  } else if (http_parser_is_finished(parser) ) {
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+int http_parser_has_error(http_parser *parser) {
+  return parser->cs == http_parser_error;
+}
+
+int http_parser_is_finished(http_parser *parser) {
+  return parser->cs >= http_parser_first_final;
+}
index a73cf1a..a93160f 100644 (file)
--- a/mistral.c
+++ b/mistral.c
@@ -117,6 +117,10 @@ void http_on_element(void *data, int type, const char *at, size_t length) {
                        line = "REQUEST_URI";
                        break;
 
+               case REQUEST_BODY:
+                       line = "REQUEST_BODY";
+                       break;
+
                default:
                        line = "UNKNOWN";
        }
@@ -126,6 +130,17 @@ void http_on_element(void *data, int type, const char *at, size_t length) {
        free(val);
 }
 
+void http_on_body(void *data, const char *at, size_t length) {
+       char *line, *val;
+       zval *server_vars = (zval *)data;
+
+       line = "REQUEST_BODY";
+
+       val = strndup(at, length);
+       add_assoc_string(server_vars, (char *) line, (char *) val, 1);
+       free(val);
+}
+
 static int setnonblock(int fd)
 {
        int flags;
@@ -212,12 +227,13 @@ static inline void* execute_php(void *_cli) {
         MAKE_STD_ZVAL(headers[0]);
         array_init(headers[0]);
 
-               cli->done = 0;
+        cli->done = 0;
         cli->rbuff[cli->rlen] = '\0';
 
         http_parser_init(&parser);
         parser.http_field = &http_field_cb;
         parser.on_element = &http_on_element;
+        parser.header_done = &http_on_element;
         parser.data       = headers[0];
         http_parser_execute(&parser, cli->rbuff, cli->rlen, 0);