2 #line 1 "http11_parser.rl"
5 * Copyright (c) 2010, Zed A. Shaw and Mongrel2 Project Contributors.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * * Neither the name of the Mongrel2 Project, Zed A. Shaw, nor the names
20 * of its contributors may be used to endorse or promote products
21 * derived from this software without specific prior written
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #include "http11_parser.h"
44 #define LEN(AT, FPC) (FPC - buffer - parser->AT)
45 #define MARK(M,FPC) (parser->M = (FPC) - buffer)
46 #define PTR_TO(F) (buffer + parser->F)
51 #line 161 "http11_parser.rl"
56 #line 57 "http11_parser.c"
57 static const char _http_parser_actions
[] = {
58 0, 1, 0, 1, 1, 1, 2, 1,
59 3, 1, 4, 1, 5, 1, 6, 1,
60 7, 1, 8, 1, 9, 1, 10, 1,
61 12, 2, 0, 5, 2, 3, 4, 2,
62 7, 9, 2, 11, 9, 3, 10, 11,
66 static const short _http_parser_key_offsets
[] = {
67 0, 0, 8, 17, 20, 22, 23, 24,
68 25, 26, 27, 28, 29, 31, 33, 50,
69 51, 67, 70, 72, 73, 82, 91, 97,
70 103, 114, 120, 126, 136, 142, 148, 157,
71 166, 172, 178, 179, 180, 181, 182, 191,
72 197, 203, 212, 221, 230, 239, 248, 257,
73 266, 275, 284, 293, 302, 311, 320, 329,
74 338, 347, 356, 365, 366
77 static const char _http_parser_trans_keys
[] = {
78 36, 95, 45, 46, 48, 57, 65, 90,
79 32, 36, 95, 45, 46, 48, 57, 65,
80 90, 42, 47, 104, 32, 35, 72, 84,
81 84, 80, 47, 49, 46, 48, 49, 10,
82 13, 10, 13, 33, 124, 126, 35, 39,
83 42, 43, 45, 46, 48, 57, 65, 90,
84 94, 122, 10, 33, 58, 124, 126, 35,
85 39, 42, 43, 45, 46, 48, 57, 65,
86 90, 94, 122, 10, 13, 32, 10, 13,
87 10, 32, 37, 60, 62, 127, 0, 31,
88 34, 35, 32, 37, 60, 62, 127, 0,
89 31, 34, 35, 48, 57, 65, 70, 97,
90 102, 48, 57, 65, 70, 97, 102, 32,
91 34, 35, 37, 59, 60, 62, 63, 127,
92 0, 31, 48, 57, 65, 70, 97, 102,
93 48, 57, 65, 70, 97, 102, 32, 34,
94 35, 37, 60, 62, 63, 127, 0, 31,
95 48, 57, 65, 70, 97, 102, 48, 57,
96 65, 70, 97, 102, 32, 34, 35, 37,
97 60, 62, 127, 0, 31, 32, 34, 35,
98 37, 60, 62, 127, 0, 31, 48, 57,
99 65, 70, 97, 102, 48, 57, 65, 70,
100 97, 102, 116, 116, 112, 58, 32, 34,
101 35, 37, 60, 62, 127, 0, 31, 48,
102 57, 65, 70, 97, 102, 48, 57, 65,
103 70, 97, 102, 32, 36, 95, 45, 46,
104 48, 57, 65, 90, 32, 36, 95, 45,
105 46, 48, 57, 65, 90, 32, 36, 95,
106 45, 46, 48, 57, 65, 90, 32, 36,
107 95, 45, 46, 48, 57, 65, 90, 32,
108 36, 95, 45, 46, 48, 57, 65, 90,
109 32, 36, 95, 45, 46, 48, 57, 65,
110 90, 32, 36, 95, 45, 46, 48, 57,
111 65, 90, 32, 36, 95, 45, 46, 48,
112 57, 65, 90, 32, 36, 95, 45, 46,
113 48, 57, 65, 90, 32, 36, 95, 45,
114 46, 48, 57, 65, 90, 32, 36, 95,
115 45, 46, 48, 57, 65, 90, 32, 36,
116 95, 45, 46, 48, 57, 65, 90, 32,
117 36, 95, 45, 46, 48, 57, 65, 90,
118 32, 36, 95, 45, 46, 48, 57, 65,
119 90, 32, 36, 95, 45, 46, 48, 57,
120 65, 90, 32, 36, 95, 45, 46, 48,
121 57, 65, 90, 32, 36, 95, 45, 46,
122 48, 57, 65, 90, 32, 36, 95, 45,
123 46, 48, 57, 65, 90, 32, 0
126 static const char _http_parser_single_lengths
[] = {
127 0, 2, 3, 3, 2, 1, 1, 1,
128 1, 1, 1, 1, 0, 2, 5, 1,
129 4, 3, 2, 1, 5, 5, 0, 0,
130 9, 0, 0, 8, 0, 0, 7, 7,
131 0, 0, 1, 1, 1, 1, 7, 0,
132 0, 3, 3, 3, 3, 3, 3, 3,
133 3, 3, 3, 3, 3, 3, 3, 3,
137 static const char _http_parser_range_lengths
[] = {
138 0, 3, 3, 0, 0, 0, 0, 0,
139 0, 0, 0, 0, 1, 0, 6, 0,
140 6, 0, 0, 0, 2, 2, 3, 3,
141 1, 3, 3, 1, 3, 3, 1, 1,
142 3, 3, 0, 0, 0, 0, 1, 3,
143 3, 3, 3, 3, 3, 3, 3, 3,
144 3, 3, 3, 3, 3, 3, 3, 3,
148 static const short _http_parser_index_offsets
[] = {
149 0, 0, 6, 13, 17, 20, 22, 24,
150 26, 28, 30, 32, 34, 36, 39, 51,
151 53, 64, 68, 71, 73, 81, 89, 93,
152 97, 108, 112, 116, 126, 130, 134, 143,
153 152, 156, 160, 162, 164, 166, 168, 177,
154 181, 185, 192, 199, 206, 213, 220, 227,
155 234, 241, 248, 255, 262, 269, 276, 283,
156 290, 297, 304, 311, 313
159 static const char _http_parser_indicies
[] = {
160 0, 0, 0, 0, 0, 1, 2, 3,
161 3, 3, 3, 3, 1, 4, 5, 6,
162 1, 7, 8, 1, 9, 1, 10, 1,
163 11, 1, 12, 1, 13, 1, 14, 1,
164 15, 1, 16, 1, 17, 18, 1, 19,
165 20, 21, 21, 21, 21, 21, 21, 21,
166 21, 21, 1, 19, 1, 22, 23, 22,
167 22, 22, 22, 22, 22, 22, 22, 1,
168 25, 26, 27, 24, 29, 30, 28, 31,
169 1, 33, 34, 1, 1, 1, 1, 1,
170 32, 36, 37, 1, 1, 1, 1, 1,
171 35, 38, 38, 38, 1, 35, 35, 35,
172 1, 40, 1, 41, 42, 43, 1, 1,
173 44, 1, 1, 39, 45, 45, 45, 1,
174 39, 39, 39, 1, 7, 1, 8, 47,
175 1, 1, 48, 1, 1, 46, 49, 49,
176 49, 1, 46, 46, 46, 1, 51, 1,
177 52, 53, 1, 1, 1, 1, 50, 55,
178 1, 56, 57, 1, 1, 1, 1, 54,
179 58, 58, 58, 1, 54, 54, 54, 1,
180 59, 1, 60, 1, 61, 1, 62, 1,
181 7, 1, 8, 63, 1, 1, 1, 1,
182 62, 64, 64, 64, 1, 62, 62, 62,
183 1, 2, 65, 65, 65, 65, 65, 1,
184 2, 66, 66, 66, 66, 66, 1, 2,
185 67, 67, 67, 67, 67, 1, 2, 68,
186 68, 68, 68, 68, 1, 2, 69, 69,
187 69, 69, 69, 1, 2, 70, 70, 70,
188 70, 70, 1, 2, 71, 71, 71, 71,
189 71, 1, 2, 72, 72, 72, 72, 72,
190 1, 2, 73, 73, 73, 73, 73, 1,
191 2, 74, 74, 74, 74, 74, 1, 2,
192 75, 75, 75, 75, 75, 1, 2, 76,
193 76, 76, 76, 76, 1, 2, 77, 77,
194 77, 77, 77, 1, 2, 78, 78, 78,
195 78, 78, 1, 2, 79, 79, 79, 79,
196 79, 1, 2, 80, 80, 80, 80, 80,
197 1, 2, 81, 81, 81, 81, 81, 1,
198 2, 82, 82, 82, 82, 82, 1, 2,
202 static const char _http_parser_trans_targs
[] = {
203 2, 0, 3, 41, 4, 24, 34, 5,
204 20, 6, 7, 8, 9, 10, 11, 12,
205 13, 14, 19, 60, 15, 16, 16, 17,
206 18, 14, 19, 17, 18, 14, 19, 14,
207 21, 5, 22, 21, 5, 22, 23, 24,
208 5, 20, 25, 27, 30, 26, 27, 28,
209 30, 29, 31, 5, 20, 32, 31, 5,
210 20, 32, 33, 35, 36, 37, 38, 39,
211 40, 42, 43, 44, 45, 46, 47, 48,
212 49, 50, 51, 52, 53, 54, 55, 56,
216 static const char _http_parser_trans_actions
[] = {
217 1, 0, 17, 0, 1, 1, 1, 19,
218 19, 1, 0, 0, 0, 0, 0, 0,
219 0, 13, 13, 23, 0, 3, 0, 5,
220 7, 28, 28, 7, 0, 9, 9, 0,
221 1, 25, 1, 0, 11, 0, 0, 0,
222 31, 31, 0, 15, 15, 0, 0, 0,
223 0, 0, 21, 37, 37, 21, 0, 34,
224 34, 0, 0, 0, 0, 0, 0, 0,
225 0, 0, 0, 0, 0, 0, 0, 0,
226 0, 0, 0, 0, 0, 0, 0, 0,
230 static const int http_parser_start
= 1;
231 static const int http_parser_first_final
= 60;
232 static const int http_parser_error
= 0;
234 static const int http_parser_en_main
= 1;
237 #line 165 "http11_parser.rl"
239 static int apply_element(http_parser
*parser
, int type
, const char *begin
, const char *end
, int max_length
)
241 int len
= (int)(end
-begin
);
242 if(len
> max_length
) {
245 if(parser
->on_element
)
246 parser
->on_element(parser
->data
, type
, begin
, len
);
252 int http_parser_init(http_parser
*parser
) {
255 #line 256 "http11_parser.c"
257 cs
= http_parser_start
;
260 #line 182 "http11_parser.rl"
262 parser
->body_start
= 0;
263 parser
->content_len
= 0;
266 parser
->field_len
= 0;
267 parser
->field_start
= 0;
273 size_t http_parser_execute(http_parser
*parser
, const char *buffer
, size_t len
, size_t off
)
275 if(len
== 0) return 0;
280 assert(off
<= len
&& "offset past end of buffer");
285 assert(pe
- p
== (int)len
- (int)off
&& "pointers aren't same distance");
288 #line 289 "http11_parser.c"
301 _keys
= _http_parser_trans_keys
+ _http_parser_key_offsets
[cs
];
302 _trans
= _http_parser_index_offsets
[cs
];
304 _klen
= _http_parser_single_lengths
[cs
];
306 const char *_lower
= _keys
;
308 const char *_upper
= _keys
+ _klen
- 1;
310 if ( _upper
< _lower
)
313 _mid
= _lower
+ ((_upper
-_lower
) >> 1);
316 else if ( (*p
) > *_mid
)
319 _trans
+= (_mid
- _keys
);
327 _klen
= _http_parser_range_lengths
[cs
];
329 const char *_lower
= _keys
;
331 const char *_upper
= _keys
+ (_klen
<<1) - 2;
333 if ( _upper
< _lower
)
336 _mid
= _lower
+ (((_upper
-_lower
) >> 1) & ~1);
337 if ( (*p
) < _mid
[0] )
339 else if ( (*p
) > _mid
[1] )
342 _trans
+= ((_mid
- _keys
)>>1);
350 _trans
= _http_parser_indicies
[_trans
];
351 cs
= _http_parser_trans_targs
[_trans
];
353 if ( _http_parser_trans_actions
[_trans
] == 0 )
356 _acts
= _http_parser_actions
+ _http_parser_trans_actions
[_trans
];
357 _nacts
= (unsigned int) *_acts
++;
358 while ( _nacts
-- > 0 )
363 #line 52 "http11_parser.rl"
367 #line 55 "http11_parser.rl"
368 { MARK(field_start
, p
); }
371 #line 56 "http11_parser.rl"
373 parser
->field_len
= LEN(field_start
, p
);
377 #line 60 "http11_parser.rl"
381 #line 62 "http11_parser.rl"
383 if(parser
->http_field
!= NULL
) {
384 parser
->http_field(parser
->data
, PTR_TO(field_start
), parser
->field_len
, PTR_TO(mark
), LEN(mark
, p
));
389 #line 73 "http11_parser.rl"
391 if(!apply_element(parser
, FRAGMENT
, PTR_TO(mark
), p
, 10*1024))
396 #line 78 "http11_parser.rl"
398 if(!apply_element(parser
, HTTP_VERSION
, PTR_TO(mark
), p
, 10))
403 #line 83 "http11_parser.rl"
405 if(!apply_element(parser
, REQUEST_PATH
, PTR_TO(mark
), p
, 1024))
410 #line 88 "http11_parser.rl"
412 if(!apply_element(parser
, REQUEST_METHOD
, PTR_TO(mark
), p
, 1024))
417 #line 93 "http11_parser.rl"
419 if(!apply_element(parser
, REQUEST_URI
, PTR_TO(mark
), p
, 12*1024))
424 #line 98 "http11_parser.rl"
425 {MARK(query_start
, p
); }
428 #line 100 "http11_parser.rl"
430 if(!apply_element(parser
, QUERY_STRING
, PTR_TO(query_start
), p
, 10*1024))
435 #line 105 "http11_parser.rl"
437 parser
->body_start
= p
- buffer
+ 1;
438 if(parser
->header_done
!= NULL
)
439 parser
->header_done(parser
->data
, REQUEST_BODY
, p
+ 1, pe
- p
- 1);
443 #line 444 "http11_parser.c"
456 #line 209 "http11_parser.rl"
458 assert(p
<= pe
&& "Buffer overflow after parsing.");
460 if (!http_parser_has_error(parser
)) {
464 parser
->nread
+= p
- (buffer
+ off
);
466 assert(parser
->nread
<= len
&& "nread longer than length");
467 assert(parser
->body_start
<= len
&& "body starts after buffer end");
468 assert(parser
->mark
< len
&& "mark is after buffer end");
469 assert(parser
->field_len
<= len
&& "field has length longer than whole buffer");
470 assert(parser
->field_start
< len
&& "field starts after buffer end");
472 return(parser
->nread
);
475 int http_parser_finish(http_parser
*parser
)
477 if (http_parser_has_error(parser
) ) {
479 } else if (http_parser_is_finished(parser
) ) {
486 int http_parser_has_error(http_parser
*parser
) {
487 return parser
->cs
== http_parser_error
;
490 int http_parser_is_finished(http_parser
*parser
) {
491 return parser
->cs
>= http_parser_first_final
;