From: Michael Maier Date: Tue, 19 Jun 2012 22:47:53 +0000 (+0200) Subject: Add REQUEST_BODY X-Git-Url: https://repo.or.cz/w/mistral.git/commitdiff_plain/30f3fd97adce0a45d7de8382c243b06c42f6ef06 Add REQUEST_BODY --- diff --git a/AUTHORS b/AUTHORS index b6b1afa..60e4796 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,2 @@ -Michael Maier +Michael Maier Stefan de Konink diff --git a/LICENSE b/LICENSE dissimilarity index 100% index f6584f4..fb6d90b 100644 --- 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. + 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 --- 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 index 0000000..ea8352a --- /dev/null +++ b/examples/formtest.php @@ -0,0 +1,27 @@ +'; + $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(); diff --git a/examples/hello_world.php b/examples/hello_world.php dissimilarity index 62% index 1564e09..86593ab 100644 --- a/examples/hello_world.php +++ b/examples/hello_world.php @@ -1,16 +1,19 @@ - '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(); -?> + '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(); + diff --git a/examples/hello_world_forks.php b/examples/hello_world_forks.php index 9571cbe..c0dbca4 100644 --- a/examples/hello_world_forks.php +++ b/examples/hello_world_forks.php @@ -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 index 0000000..db0c6bd --- /dev/null +++ b/examples/return_vars.php @@ -0,0 +1,26 @@ + '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(); diff --git a/http11_parser.c b/http11_parser.c dissimilarity index 80% index 870dda4..a14238e 100644 --- a/http11_parser.c +++ b/http11_parser.c @@ -1,1300 +1,492 @@ - -#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 -#include -#include -#include -#include - -#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 +#include +#include +#include +#include + +#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; +} diff --git a/http11_parser.h b/http11_parser.h index c7f0ae1..2a64836 100644 --- a/http11_parser.h +++ b/http11_parser.h @@ -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 index 0000000..878858b --- /dev/null +++ b/http11_parser.rl @@ -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 +#include +#include +#include +#include + +#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; +} diff --git a/mistral.c b/mistral.c index a73cf1a..a93160f 100644 --- 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);