http_parser.rb 0.5.1-x86-mswin32-60 → 0.5.2-x86-mswin32-60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile.lock +16 -16
- data/LICENSE-MIT +20 -0
- data/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java +68 -11
- data/ext/ruby_http_parser/ruby_http_parser.c +74 -6
- data/ext/ruby_http_parser/vendor/http-parser-java/LICENSE-MIT +26 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/README.md +23 -143
- data/ext/ruby_http_parser/vendor/http-parser-java/TODO +3 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/build.xml +74 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c +115 -61
- data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h +19 -3
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java +8 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java +34 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java +12 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java +4 -2
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java +64 -52
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java +5 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java +323 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/{lolevel/Util.java → Util.java} +27 -28
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java +259 -85
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java +1 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java +324 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Requests.java +69 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Responses.java +51 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Test.java +15 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestHeaderOverflowError.java +47 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestLoaderNG.java +183 -447
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestNoOverflowLongBody.java +61 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java +2 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Upgrade.java +26 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Util.java +165 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/WrongContentLength.java +58 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/test.c +232 -29
- data/ext/ruby_http_parser/vendor/http-parser-java/test_permutations +1 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/test_unit +1 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/test_utf8 +1 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/tests.dumped +154 -7
- data/ext/ruby_http_parser/vendor/http-parser-java/tests.utf8 +17 -0
- data/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT +1 -1
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.c +52 -10
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.h +3 -1
- data/ext/ruby_http_parser/vendor/http-parser/test.c +89 -3
- data/http_parser.rb.gemspec +8 -2
- data/lib/http_parser.rb +17 -0
- data/spec/parser_spec.rb +97 -6
- data/tasks/compile.rake +3 -1
- metadata +83 -20
- data/ext/ruby_http_parser/vendor/http-parser-java/CONTRIBUTIONS +0 -4
@@ -1,35 +1,34 @@
|
|
1
|
-
package http_parser
|
1
|
+
package http_parser;
|
2
2
|
|
3
3
|
import java.nio.ByteBuffer;
|
4
|
-
import http_parser.HTTPException;
|
5
4
|
|
6
5
|
public class Util {
|
7
|
-
public static String toString(HTTPParser p) {
|
8
|
-
StringBuilder builder = new StringBuilder();
|
9
|
-
|
10
|
-
// the stuff up to the break is ephermeral and only meaningful
|
11
|
-
// while the parser is parsing. In general, this method is
|
12
|
-
// probably only useful during debugging.
|
13
|
-
|
14
|
-
builder.append("state :"); builder.append(p.state); builder.append("\n");
|
15
|
-
builder.append("header_state :"); builder.append(p.header_state); builder.append("\n");
|
16
|
-
builder.append("strict :"); builder.append(p.strict); builder.append("\n");
|
17
|
-
builder.append("index :"); builder.append(p.index); builder.append("\n");
|
18
|
-
builder.append("flags :"); builder.append(p.flags); builder.append("\n");
|
19
|
-
builder.append("nread :"); builder.append(p.nread); builder.append("\n");
|
20
|
-
builder.append("content_length :"); builder.append(p.content_length); builder.append("\n");
|
21
|
-
|
22
|
-
|
23
|
-
builder.append("type :"); builder.append(p.type); builder.append("\n");
|
24
|
-
builder.append("http_major :"); builder.append(p.http_major); builder.append("\n");
|
25
|
-
builder.append("http_minor :"); builder.append(p.http_minor); builder.append("\n");
|
26
|
-
builder.append("status_code :"); builder.append(p.status_code); builder.append("\n");
|
27
|
-
builder.append("method :"); builder.append(p.method); builder.append("\n");
|
28
|
-
builder.append("upgrade :"); builder.append(p.upgrade); builder.append("\n");
|
29
|
-
|
30
|
-
return builder.toString();
|
31
|
-
|
32
|
-
}
|
6
|
+
// public static String toString(http_parser.lolevel.HTTPParser p) {
|
7
|
+
// StringBuilder builder = new StringBuilder();
|
8
|
+
//
|
9
|
+
// // the stuff up to the break is ephermeral and only meaningful
|
10
|
+
// // while the parser is parsing. In general, this method is
|
11
|
+
// // probably only useful during debugging.
|
12
|
+
//
|
13
|
+
// builder.append("state :"); builder.append(p.state); builder.append("\n");
|
14
|
+
// builder.append("header_state :"); builder.append(p.header_state); builder.append("\n");
|
15
|
+
// builder.append("strict :"); builder.append(p.strict); builder.append("\n");
|
16
|
+
// builder.append("index :"); builder.append(p.index); builder.append("\n");
|
17
|
+
// builder.append("flags :"); builder.append(p.flags); builder.append("\n");
|
18
|
+
// builder.append("nread :"); builder.append(p.nread); builder.append("\n");
|
19
|
+
// builder.append("content_length :"); builder.append(p.content_length); builder.append("\n");
|
20
|
+
//
|
21
|
+
//
|
22
|
+
// builder.append("type :"); builder.append(p.type); builder.append("\n");
|
23
|
+
// builder.append("http_major :"); builder.append(p.http_major); builder.append("\n");
|
24
|
+
// builder.append("http_minor :"); builder.append(p.http_minor); builder.append("\n");
|
25
|
+
// builder.append("status_code :"); builder.append(p.status_code); builder.append("\n");
|
26
|
+
// builder.append("method :"); builder.append(p.method); builder.append("\n");
|
27
|
+
// builder.append("upgrade :"); builder.append(p.upgrade); builder.append("\n");
|
28
|
+
//
|
29
|
+
// return builder.toString();
|
30
|
+
//
|
31
|
+
// }
|
33
32
|
|
34
33
|
public static String error (String mes, ByteBuffer b, int begining) {
|
35
34
|
// the error message should look like this:
|
data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java
CHANGED
@@ -22,19 +22,21 @@ public class HTTPParser {
|
|
22
22
|
int nread;
|
23
23
|
int content_length;
|
24
24
|
|
25
|
-
|
25
|
+
int start_position;
|
26
|
+
ByteBuffer data;
|
27
|
+
|
26
28
|
/** READ-ONLY **/
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
public int http_major;
|
30
|
+
public int http_minor;
|
31
|
+
public int status_code; /* responses only */
|
32
|
+
public HTTPMethod method; /* requests only */
|
31
33
|
|
32
34
|
/* true = Upgrade header was present and the parser has exited because of that.
|
33
35
|
* false = No upgrade header present.
|
34
36
|
* Should be checked when http_parser_execute() returns in addition to
|
35
37
|
* error checking.
|
36
38
|
*/
|
37
|
-
|
39
|
+
public boolean upgrade;
|
38
40
|
|
39
41
|
/** PUBLIC **/
|
40
42
|
// TODO : this is used in c to maintain application state.
|
@@ -95,21 +97,39 @@ public class HTTPParser {
|
|
95
97
|
* correctly (obviously) and a will be updated approriately when the
|
96
98
|
* method returns to reflect the consumed data.
|
97
99
|
*/
|
98
|
-
public
|
100
|
+
public int execute(ParserSettings settings, ByteBuffer data) {
|
99
101
|
|
100
102
|
int p = data.position();
|
101
103
|
int p_err = p; // this is used for pretty printing errors.
|
104
|
+
|
105
|
+
this.start_position = p;
|
106
|
+
this.data = data;
|
102
107
|
|
103
108
|
// In case the headers don't provide information about the content
|
104
109
|
// length, `execute` needs to be called with an empty buffer to
|
105
110
|
// indicate that all the data has been send be the client/server,
|
106
111
|
// else there is no way of knowing the message is complete.
|
107
112
|
int len = (data.limit() - data.position());
|
108
|
-
|
109
|
-
if (State.body_identity_eof == state) {
|
110
|
-
settings.call_on_message_complete(this);
|
111
|
-
}
|
112
|
-
|
113
|
+
if (0 == len) {
|
114
|
+
// if (State.body_identity_eof == state) {
|
115
|
+
// settings.call_on_message_complete(this);
|
116
|
+
// }
|
117
|
+
switch (state) {
|
118
|
+
case body_identity_eof:
|
119
|
+
settings.call_on_message_complete(this);
|
120
|
+
return data.position() - start_position;
|
121
|
+
|
122
|
+
case dead:
|
123
|
+
case start_res_or_res:
|
124
|
+
case start_res:
|
125
|
+
case start_req:
|
126
|
+
return data.position() - start_position;
|
127
|
+
|
128
|
+
default:
|
129
|
+
// should we really consider this an error!?
|
130
|
+
throw new HTTPException("empty bytes! "+state); // error
|
131
|
+
}
|
132
|
+
}
|
113
133
|
|
114
134
|
|
115
135
|
// in case the _previous_ call to the parser only has data to get to
|
@@ -151,6 +171,7 @@ public class HTTPParser {
|
|
151
171
|
int pe = data.limit();
|
152
172
|
|
153
173
|
byte ch = data.get(); // the current character to process.
|
174
|
+
int chi = ch & 0xff; // utility, ch without signedness for table lookups.
|
154
175
|
byte c = -1; // utility variably used for up- and downcasing etc.
|
155
176
|
int to_read = 0; // used to keep track of how much of body, etc. is left to read
|
156
177
|
|
@@ -158,9 +179,10 @@ public class HTTPParser {
|
|
158
179
|
++nread;
|
159
180
|
if (nread > HTTP_MAX_HEADER_SIZE) {
|
160
181
|
settings.call_on_error(this, "possible buffer overflow", data, p_err);
|
182
|
+
return error();
|
161
183
|
}
|
162
184
|
}
|
163
|
-
|
185
|
+
//p(state + ":" + ch +":"+p);
|
164
186
|
switch (state) {
|
165
187
|
/*
|
166
188
|
* this state is used after a 'Connection: close' message
|
@@ -168,6 +190,7 @@ public class HTTPParser {
|
|
168
190
|
*/
|
169
191
|
case dead:
|
170
192
|
settings.call_on_error(this, "Connection already closed", data, p_err);
|
193
|
+
return error();
|
171
194
|
|
172
195
|
|
173
196
|
|
@@ -187,6 +210,7 @@ public class HTTPParser {
|
|
187
210
|
method = start_req_method_assign(ch);
|
188
211
|
if (null == method) {
|
189
212
|
settings.call_on_error(this, "invalid method", data, p_err);
|
213
|
+
return error();
|
190
214
|
}
|
191
215
|
index = 1;
|
192
216
|
state = State.req_method;
|
@@ -202,6 +226,7 @@ public class HTTPParser {
|
|
202
226
|
} else {
|
203
227
|
if (E != ch) {
|
204
228
|
settings.call_on_error(this, "not E", data, p_err);
|
229
|
+
return error();
|
205
230
|
}
|
206
231
|
type = ParserType.HTTP_REQUEST;
|
207
232
|
method = HTTPMethod.HTTP_HEAD;
|
@@ -227,6 +252,7 @@ public class HTTPParser {
|
|
227
252
|
break;
|
228
253
|
default:
|
229
254
|
settings.call_on_error(this, "Not H or CR/LF", data, p_err);
|
255
|
+
return error();
|
230
256
|
}
|
231
257
|
break;
|
232
258
|
|
@@ -235,24 +261,28 @@ public class HTTPParser {
|
|
235
261
|
case res_H:
|
236
262
|
if (strict && T != ch) {
|
237
263
|
settings.call_on_error(this, "Not T", data, p_err);
|
264
|
+
return error();
|
238
265
|
}
|
239
266
|
state = State.res_HT;
|
240
267
|
break;
|
241
268
|
case res_HT:
|
242
269
|
if (strict && T != ch) {
|
243
270
|
settings.call_on_error(this, "Not T2", data, p_err);
|
271
|
+
return error();
|
244
272
|
}
|
245
273
|
state = State.res_HTT;
|
246
274
|
break;
|
247
275
|
case res_HTT:
|
248
276
|
if (strict && P != ch) {
|
249
277
|
settings.call_on_error(this, "Not P", data, p_err);
|
278
|
+
return error();
|
250
279
|
}
|
251
280
|
state = State.res_HTTP;
|
252
281
|
break;
|
253
282
|
case res_HTTP:
|
254
283
|
if (strict && SLASH != ch) {
|
255
284
|
settings.call_on_error(this, "Not '/'", data, p_err);
|
285
|
+
return error();
|
256
286
|
}
|
257
287
|
state = State.res_first_http_major;
|
258
288
|
break;
|
@@ -262,6 +292,7 @@ public class HTTPParser {
|
|
262
292
|
case res_first_http_major:
|
263
293
|
if (!isDigit(ch)) {
|
264
294
|
settings.call_on_error(this, "Not a digit", data, p_err);
|
295
|
+
return error();
|
265
296
|
}
|
266
297
|
http_major = (int) ch - 0x30;
|
267
298
|
state = State.res_http_major;
|
@@ -270,17 +301,19 @@ public class HTTPParser {
|
|
270
301
|
/* major HTTP version or dot */
|
271
302
|
case res_http_major:
|
272
303
|
if (DOT == ch) {
|
273
|
-
state = State.
|
304
|
+
state = State.res_first_http_minor;
|
274
305
|
break;
|
275
306
|
}
|
276
307
|
if (!isDigit(ch)) {
|
277
308
|
settings.call_on_error(this, "Not a digit", data, p_err);
|
309
|
+
return error();
|
278
310
|
}
|
279
311
|
http_major *= 10;
|
280
312
|
http_major += (ch - 0x30);
|
281
313
|
|
282
314
|
if (http_major > 999) {
|
283
315
|
settings.call_on_error(this, "invalid http major version: "+http_major, data, p_err);
|
316
|
+
return error();
|
284
317
|
}
|
285
318
|
break;
|
286
319
|
|
@@ -288,6 +321,7 @@ public class HTTPParser {
|
|
288
321
|
case res_first_http_minor:
|
289
322
|
if (!isDigit(ch)) {
|
290
323
|
settings.call_on_error(this, "Not a digit", data, p_err);
|
324
|
+
return error();
|
291
325
|
}
|
292
326
|
http_minor = (int)ch - 0x30;
|
293
327
|
state = State.res_http_minor;
|
@@ -301,12 +335,13 @@ public class HTTPParser {
|
|
301
335
|
}
|
302
336
|
if (!isDigit(ch)) {
|
303
337
|
settings.call_on_error(this, "Not a digit", data, p_err);
|
338
|
+
return error();
|
304
339
|
}
|
305
340
|
http_minor *= 10;
|
306
341
|
http_minor += (ch - 0x30);
|
307
|
-
|
308
342
|
if (http_minor > 999) {
|
309
343
|
settings.call_on_error(this, "invalid http minor version: "+http_minor, data, p_err);
|
344
|
+
return error();
|
310
345
|
}
|
311
346
|
break;
|
312
347
|
|
@@ -318,6 +353,7 @@ public class HTTPParser {
|
|
318
353
|
break;
|
319
354
|
}
|
320
355
|
settings.call_on_error(this, "Not a digit (status code)", data, p_err);
|
356
|
+
return error();
|
321
357
|
}
|
322
358
|
status_code = (int)ch - 0x30;
|
323
359
|
state = State.res_status_code;
|
@@ -337,6 +373,7 @@ public class HTTPParser {
|
|
337
373
|
break;
|
338
374
|
default:
|
339
375
|
settings.call_on_error(this, "not a valid status code", data, p_err);
|
376
|
+
return error();
|
340
377
|
}
|
341
378
|
break;
|
342
379
|
}
|
@@ -344,6 +381,7 @@ public class HTTPParser {
|
|
344
381
|
status_code += (int)ch - 0x30;
|
345
382
|
if (status_code > 999) {
|
346
383
|
settings.call_on_error(this, "ridiculous status code:"+status_code, data, p_err);
|
384
|
+
return error();
|
347
385
|
}
|
348
386
|
break;
|
349
387
|
|
@@ -365,6 +403,7 @@ public class HTTPParser {
|
|
365
403
|
case res_line_almost_done:
|
366
404
|
if (strict && LF != ch) {
|
367
405
|
settings.call_on_error(this, "not LF", data, p_err);
|
406
|
+
return error();
|
368
407
|
}
|
369
408
|
state = State.header_field_start;
|
370
409
|
break;
|
@@ -372,7 +411,7 @@ public class HTTPParser {
|
|
372
411
|
|
373
412
|
|
374
413
|
case start_req:
|
375
|
-
if (CR==ch || LF ==
|
414
|
+
if (CR==ch || LF == ch) {
|
376
415
|
break;
|
377
416
|
}
|
378
417
|
flags = 0;
|
@@ -381,6 +420,7 @@ public class HTTPParser {
|
|
381
420
|
method = start_req_method_assign(ch);
|
382
421
|
if (null == method) {
|
383
422
|
settings.call_on_error(this, "invalid method", data, p_err);
|
423
|
+
return error();
|
384
424
|
}
|
385
425
|
index = 1;
|
386
426
|
state = State.req_method;
|
@@ -391,6 +431,7 @@ public class HTTPParser {
|
|
391
431
|
case req_method:
|
392
432
|
if (0 == ch) {
|
393
433
|
settings.call_on_error(this, "NULL in method", data, p_err);
|
434
|
+
return error();
|
394
435
|
}
|
395
436
|
|
396
437
|
byte [] arr = method.bytes;
|
@@ -410,6 +451,8 @@ public class HTTPParser {
|
|
410
451
|
method = HTTPMethod.HTTP_MOVE;
|
411
452
|
} else if (1 == index && E == ch) {
|
412
453
|
method = HTTPMethod.HTTP_MERGE;
|
454
|
+
} else if (1 == index && DASH == ch) { /* M-SEARCH */
|
455
|
+
method = HTTPMethod.HTTP_MSEARCH;
|
413
456
|
} else if (2 == index && A == ch) {
|
414
457
|
method = HTTPMethod.HTTP_MKACTIVITY;
|
415
458
|
}
|
@@ -417,10 +460,13 @@ public class HTTPParser {
|
|
417
460
|
method = HTTPMethod.HTTP_PROPFIND;
|
418
461
|
} else if (1 == index && HTTPMethod.HTTP_POST == method && U == ch) {
|
419
462
|
method = HTTPMethod.HTTP_PUT;
|
463
|
+
} else if (2 == index && HTTPMethod.HTTP_UNLOCK == method && S == ch) {
|
464
|
+
method = HTTPMethod.HTTP_UNSUBSCRIBE;
|
420
465
|
} else if (4 == index && HTTPMethod.HTTP_PROPFIND == method && P == ch) {
|
421
466
|
method = HTTPMethod.HTTP_PROPPATCH;
|
422
467
|
} else {
|
423
468
|
settings.call_on_error(this, "Invalid HTTP method", data, p_err);
|
469
|
+
return error();
|
424
470
|
}
|
425
471
|
|
426
472
|
++index;
|
@@ -433,7 +479,7 @@ public class HTTPParser {
|
|
433
479
|
if (SPACE == ch) {
|
434
480
|
break;
|
435
481
|
}
|
436
|
-
if (SLASH == ch) {
|
482
|
+
if (SLASH == ch || STAR == ch) {
|
437
483
|
url_mark = p;
|
438
484
|
path_mark = p;
|
439
485
|
state = State.req_path;
|
@@ -445,6 +491,7 @@ public class HTTPParser {
|
|
445
491
|
break;
|
446
492
|
}
|
447
493
|
settings.call_on_error(this, "Invalid something", data, p_err);
|
494
|
+
return error();
|
448
495
|
|
449
496
|
case req_schema:
|
450
497
|
if (isAtoZ(ch)){
|
@@ -453,15 +500,17 @@ public class HTTPParser {
|
|
453
500
|
if (COLON == ch) {
|
454
501
|
state = State.req_schema_slash;
|
455
502
|
break;
|
456
|
-
} else if (DOT == ch) {
|
503
|
+
} else if (DOT == ch || isDigit(ch)) {
|
457
504
|
state = State.req_host;
|
458
505
|
break;
|
459
506
|
}
|
460
507
|
settings.call_on_error(this, "invalid char in schema: "+ch, data, p_err);
|
508
|
+
return error();
|
461
509
|
|
462
510
|
case req_schema_slash:
|
463
511
|
if (strict && SLASH != ch) {
|
464
512
|
settings.call_on_error(this, "invalid char in schema, not /", data, p_err);
|
513
|
+
return error();
|
465
514
|
}
|
466
515
|
state = State.req_schema_slash_slash;
|
467
516
|
break;
|
@@ -469,6 +518,7 @@ public class HTTPParser {
|
|
469
518
|
case req_schema_slash_slash:
|
470
519
|
if (strict && SLASH != ch) {
|
471
520
|
settings.call_on_error(this, "invalid char in schema, not /", data, p_err);
|
521
|
+
return error();
|
472
522
|
}
|
473
523
|
state = State.req_host;
|
474
524
|
break;
|
@@ -494,8 +544,12 @@ public class HTTPParser {
|
|
494
544
|
url_mark = -1;
|
495
545
|
state = State.req_http_start;
|
496
546
|
break;
|
547
|
+
case QMARK:
|
548
|
+
state = State.req_query_string_start;
|
549
|
+
break;
|
497
550
|
default:
|
498
551
|
settings.call_on_error(this, "host error in method line", data, p_err);
|
552
|
+
return error();
|
499
553
|
}
|
500
554
|
break;
|
501
555
|
|
@@ -515,13 +569,17 @@ public class HTTPParser {
|
|
515
569
|
url_mark = -1;
|
516
570
|
state = State.req_http_start;
|
517
571
|
break;
|
572
|
+
case QMARK:
|
573
|
+
state = State.req_query_string_start;
|
574
|
+
break;
|
518
575
|
default:
|
519
576
|
settings.call_on_error(this, "invalid port", data, p_err);
|
577
|
+
return error();
|
520
578
|
}
|
521
579
|
break;
|
522
580
|
|
523
581
|
case req_path:
|
524
|
-
if (normal_url_char[
|
582
|
+
if (normal_url_char[chi]) break;
|
525
583
|
switch (ch) {
|
526
584
|
case SPACE:
|
527
585
|
settings.call_on_url(this,data,url_mark, p-url_mark);
|
@@ -571,11 +629,12 @@ public class HTTPParser {
|
|
571
629
|
|
572
630
|
default:
|
573
631
|
settings.call_on_error(this, "unexpected char in path", data, p_err);
|
632
|
+
return error();
|
574
633
|
}
|
575
634
|
break;
|
576
635
|
|
577
636
|
case req_query_string_start:
|
578
|
-
if (normal_url_char[
|
637
|
+
if (normal_url_char[chi]) {
|
579
638
|
query_string_mark = p;
|
580
639
|
state = State.req_query_string;
|
581
640
|
break;
|
@@ -605,11 +664,12 @@ public class HTTPParser {
|
|
605
664
|
break;
|
606
665
|
default:
|
607
666
|
settings.call_on_error(this, "unexpected char in path", data, p_err);
|
667
|
+
return error();
|
608
668
|
}
|
609
669
|
break;
|
610
670
|
|
611
671
|
case req_query_string:
|
612
|
-
if (normal_url_char[
|
672
|
+
if (normal_url_char[chi]) {
|
613
673
|
break;
|
614
674
|
}
|
615
675
|
|
@@ -652,11 +712,12 @@ public class HTTPParser {
|
|
652
712
|
break;
|
653
713
|
default:
|
654
714
|
settings.call_on_error(this, "unexpected char in path", data, p_err);
|
715
|
+
return error();
|
655
716
|
}
|
656
717
|
break;
|
657
718
|
|
658
719
|
case req_fragment_start:
|
659
|
-
if (normal_url_char[
|
720
|
+
if (normal_url_char[chi]) {
|
660
721
|
fragment_mark = p;
|
661
722
|
state = State.req_fragment;
|
662
723
|
break;
|
@@ -691,11 +752,12 @@ public class HTTPParser {
|
|
691
752
|
break;
|
692
753
|
default:
|
693
754
|
settings.call_on_error(this, "unexpected char in path", data, p_err);
|
755
|
+
return error();
|
694
756
|
}
|
695
757
|
break;
|
696
758
|
|
697
759
|
case req_fragment:
|
698
|
-
if (normal_url_char[
|
760
|
+
if (normal_url_char[chi]) {
|
699
761
|
break;
|
700
762
|
}
|
701
763
|
|
@@ -734,6 +796,7 @@ public class HTTPParser {
|
|
734
796
|
break;
|
735
797
|
default:
|
736
798
|
settings.call_on_error(this, "unexpected char in path", data, p_err);
|
799
|
+
return error();
|
737
800
|
}
|
738
801
|
break;
|
739
802
|
/******************* URL *******************/
|
@@ -750,12 +813,14 @@ public class HTTPParser {
|
|
750
813
|
break;
|
751
814
|
default:
|
752
815
|
settings.call_on_error(this, "error in req_http_H", data, p_err);
|
816
|
+
return error();
|
753
817
|
}
|
754
818
|
break;
|
755
819
|
|
756
820
|
case req_http_H:
|
757
821
|
if (strict && T != ch) {
|
758
822
|
settings.call_on_error(this, "unexpected char", data, p_err);
|
823
|
+
return error();
|
759
824
|
}
|
760
825
|
state = State.req_http_HT;
|
761
826
|
break;
|
@@ -763,6 +828,7 @@ public class HTTPParser {
|
|
763
828
|
case req_http_HT:
|
764
829
|
if (strict && T != ch) {
|
765
830
|
settings.call_on_error(this, "unexpected char", data, p_err);
|
831
|
+
return error();
|
766
832
|
}
|
767
833
|
state = State.req_http_HTT;
|
768
834
|
break;
|
@@ -770,6 +836,7 @@ public class HTTPParser {
|
|
770
836
|
case req_http_HTT:
|
771
837
|
if (strict && P != ch) {
|
772
838
|
settings.call_on_error(this, "unexpected char", data, p_err);
|
839
|
+
return error();
|
773
840
|
}
|
774
841
|
state = State.req_http_HTTP;
|
775
842
|
break;
|
@@ -777,6 +844,7 @@ public class HTTPParser {
|
|
777
844
|
case req_http_HTTP:
|
778
845
|
if (strict && SLASH != ch) {
|
779
846
|
settings.call_on_error(this, "unexpected char", data, p_err);
|
847
|
+
return error();
|
780
848
|
}
|
781
849
|
state = req_first_http_major;
|
782
850
|
break;
|
@@ -785,6 +853,7 @@ public class HTTPParser {
|
|
785
853
|
case req_first_http_major:
|
786
854
|
if (!isDigit(ch)) {
|
787
855
|
settings.call_on_error(this, "non digit in http major", data, p_err);
|
856
|
+
return error();
|
788
857
|
}
|
789
858
|
http_major = (int)ch - 0x30;
|
790
859
|
state = State.req_http_major;
|
@@ -799,6 +868,7 @@ public class HTTPParser {
|
|
799
868
|
|
800
869
|
if (!isDigit(ch)) {
|
801
870
|
settings.call_on_error(this, "non digit in http major", data, p_err);
|
871
|
+
return error();
|
802
872
|
}
|
803
873
|
|
804
874
|
http_major *= 10;
|
@@ -806,6 +876,7 @@ public class HTTPParser {
|
|
806
876
|
|
807
877
|
if (http_major > 999) {
|
808
878
|
settings.call_on_error(this, "ridiculous http major", data, p_err);
|
879
|
+
return error();
|
809
880
|
};
|
810
881
|
break;
|
811
882
|
|
@@ -813,6 +884,7 @@ public class HTTPParser {
|
|
813
884
|
case req_first_http_minor:
|
814
885
|
if (!isDigit(ch)) {
|
815
886
|
settings.call_on_error(this, "non digit in http minor", data, p_err);
|
887
|
+
return error();
|
816
888
|
}
|
817
889
|
http_minor = (int)ch - 0x30;
|
818
890
|
state = State.req_http_minor;
|
@@ -833,6 +905,7 @@ public class HTTPParser {
|
|
833
905
|
|
834
906
|
if (!isDigit(ch)) {
|
835
907
|
settings.call_on_error(this, "non digit in http minor", data, p_err);
|
908
|
+
return error();
|
836
909
|
}
|
837
910
|
|
838
911
|
http_minor *= 10;
|
@@ -841,6 +914,7 @@ public class HTTPParser {
|
|
841
914
|
|
842
915
|
if (http_minor > 999) {
|
843
916
|
settings.call_on_error(this, "ridiculous http minor", data, p_err);
|
917
|
+
return error();
|
844
918
|
};
|
845
919
|
|
846
920
|
break;
|
@@ -850,6 +924,7 @@ public class HTTPParser {
|
|
850
924
|
{
|
851
925
|
if (ch != LF) {
|
852
926
|
settings.call_on_error(this, "missing LF after request line", data, p_err);
|
927
|
+
return error();
|
853
928
|
}
|
854
929
|
state = State.header_field_start;
|
855
930
|
break;
|
@@ -873,14 +948,19 @@ public class HTTPParser {
|
|
873
948
|
state = State.headers_almost_done;
|
874
949
|
if (!headers_almost_done(ch, settings)) {
|
875
950
|
settings.call_on_error(this, "header not properly completed", data, p_err);
|
951
|
+
return error();
|
952
|
+
}
|
953
|
+
if (upgrade) {
|
954
|
+
return data.position() - start_position;
|
876
955
|
}
|
877
956
|
break;
|
878
957
|
}
|
879
958
|
|
880
|
-
c =
|
959
|
+
c = token(ch);
|
881
960
|
|
882
|
-
if (
|
883
|
-
settings.call_on_error(this, "invalid char in header", data, p_err);
|
961
|
+
if (0 == c) {
|
962
|
+
settings.call_on_error(this, "invalid char in header:"+c, data, p_err);
|
963
|
+
return error();
|
884
964
|
};
|
885
965
|
|
886
966
|
header_field_mark = p;
|
@@ -916,7 +996,7 @@ public class HTTPParser {
|
|
916
996
|
|
917
997
|
case header_field:
|
918
998
|
{
|
919
|
-
c = (
|
999
|
+
c = token(ch);
|
920
1000
|
if (0 != c) {
|
921
1001
|
switch (header_state) {
|
922
1002
|
case general:
|
@@ -1011,6 +1091,7 @@ public class HTTPParser {
|
|
1011
1091
|
|
1012
1092
|
default:
|
1013
1093
|
settings.call_on_error(this, "Unknown Header State", data, p_err);
|
1094
|
+
return error();
|
1014
1095
|
} // switch: header_state
|
1015
1096
|
break;
|
1016
1097
|
} // 0 != c
|
@@ -1040,6 +1121,7 @@ public class HTTPParser {
|
|
1040
1121
|
}
|
1041
1122
|
|
1042
1123
|
settings.call_on_error(this, "invalid header field", data, p_err);
|
1124
|
+
return error();
|
1043
1125
|
}
|
1044
1126
|
|
1045
1127
|
|
@@ -1053,30 +1135,27 @@ public class HTTPParser {
|
|
1053
1135
|
state = State.header_value;
|
1054
1136
|
index = 0;
|
1055
1137
|
|
1056
|
-
c = (byte)acceptable_header[ch];
|
1057
|
-
|
1058
|
-
if (c == 0) {
|
1059
|
-
if (CR == ch) {
|
1060
|
-
settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
|
1061
|
-
header_value_mark = -1;
|
1062
1138
|
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
}
|
1067
|
-
|
1068
|
-
if (LF == ch) {
|
1069
|
-
settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
|
1070
|
-
header_value_mark = -1;
|
1071
|
-
|
1072
|
-
state = State.header_field_start;
|
1073
|
-
break;
|
1074
|
-
}
|
1139
|
+
if (CR == ch) {
|
1140
|
+
settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
|
1141
|
+
header_value_mark = -1;
|
1075
1142
|
|
1076
1143
|
header_state = HState.general;
|
1144
|
+
state = State.header_almost_done;
|
1145
|
+
break;
|
1146
|
+
}
|
1147
|
+
|
1148
|
+
if (LF == ch) {
|
1149
|
+
settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
|
1150
|
+
header_value_mark = -1;
|
1151
|
+
|
1152
|
+
state = State.header_field_start;
|
1077
1153
|
break;
|
1078
1154
|
}
|
1079
1155
|
|
1156
|
+
|
1157
|
+
c = upper(ch);
|
1158
|
+
|
1080
1159
|
switch (header_state) {
|
1081
1160
|
case upgrade:
|
1082
1161
|
flags |= F_UPGRADE;
|
@@ -1095,6 +1174,7 @@ public class HTTPParser {
|
|
1095
1174
|
case content_length:
|
1096
1175
|
if (!isDigit(ch)) {
|
1097
1176
|
settings.call_on_error(this, "Content-Length not numeric", data, p_err);
|
1177
|
+
return error();
|
1098
1178
|
}
|
1099
1179
|
content_length = (int)ch - 0x30;
|
1100
1180
|
break;
|
@@ -1122,29 +1202,27 @@ public class HTTPParser {
|
|
1122
1202
|
|
1123
1203
|
case header_value:
|
1124
1204
|
{
|
1125
|
-
c = (byte)acceptable_header[ch];
|
1126
1205
|
|
1127
|
-
if (
|
1128
|
-
|
1129
|
-
|
1130
|
-
header_value_mark = -1;
|
1206
|
+
if (CR == ch) {
|
1207
|
+
settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
|
1208
|
+
header_value_mark = -1;
|
1131
1209
|
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1210
|
+
state = State.header_almost_done;
|
1211
|
+
break;
|
1212
|
+
}
|
1135
1213
|
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
break;
|
1214
|
+
if (LF == ch) {
|
1215
|
+
settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
|
1216
|
+
header_value_mark = -1;
|
1217
|
+
|
1218
|
+
if (!header_almost_done(ch)) {
|
1219
|
+
settings.call_on_error(this,"incorrect header ending, expection LF", data, p_err);
|
1220
|
+
return error();
|
1144
1221
|
}
|
1145
1222
|
break;
|
1146
1223
|
}
|
1147
1224
|
|
1225
|
+
c = upper(ch);
|
1148
1226
|
switch (header_state) {
|
1149
1227
|
case general:
|
1150
1228
|
break;
|
@@ -1152,6 +1230,7 @@ public class HTTPParser {
|
|
1152
1230
|
case connection:
|
1153
1231
|
case transfer_encoding:
|
1154
1232
|
settings.call_on_error(this, "Shouldn't be here", data, p_err);
|
1233
|
+
return error();
|
1155
1234
|
|
1156
1235
|
case content_length:
|
1157
1236
|
if (SPACE == ch) {
|
@@ -1159,6 +1238,7 @@ public class HTTPParser {
|
|
1159
1238
|
}
|
1160
1239
|
if (!isDigit(ch)) {
|
1161
1240
|
settings.call_on_error(this, "Content-Length not numeric", data, p_err);
|
1241
|
+
return error();
|
1162
1242
|
}
|
1163
1243
|
|
1164
1244
|
content_length *= 10;
|
@@ -1214,12 +1294,17 @@ public class HTTPParser {
|
|
1214
1294
|
case header_almost_done:
|
1215
1295
|
if (!header_almost_done(ch)) {
|
1216
1296
|
settings.call_on_error(this,"incorrect header ending, expection LF", data, p_err);
|
1297
|
+
return error();
|
1217
1298
|
}
|
1218
1299
|
break;
|
1219
1300
|
|
1220
1301
|
case headers_almost_done:
|
1221
1302
|
if (!headers_almost_done(ch, settings)) {
|
1222
1303
|
settings.call_on_error(this, "header not properly completed", data, p_err);
|
1304
|
+
return error();
|
1305
|
+
}
|
1306
|
+
if (upgrade) {
|
1307
|
+
return data.position()-start_position ;
|
1223
1308
|
}
|
1224
1309
|
break;
|
1225
1310
|
|
@@ -1258,13 +1343,20 @@ public class HTTPParser {
|
|
1258
1343
|
|
1259
1344
|
/******************* Chunk *******************/
|
1260
1345
|
case chunk_size_start:
|
1346
|
+
if (1 != this.nread) {
|
1347
|
+
settings.call_on_error(this, "nread != 1 (chunking)", data, p_err);
|
1348
|
+
return error();
|
1349
|
+
|
1350
|
+
}
|
1261
1351
|
if (0 == (flags & F_CHUNKED)) {
|
1262
1352
|
settings.call_on_error(this, "not chunked", data, p_err);
|
1353
|
+
return error();
|
1263
1354
|
}
|
1264
1355
|
|
1265
|
-
c = UNHEX[
|
1356
|
+
c = UNHEX[chi];
|
1266
1357
|
if (c == -1) {
|
1267
1358
|
settings.call_on_error(this, "invalid hex char in chunk content length", data, p_err);
|
1359
|
+
return error();
|
1268
1360
|
}
|
1269
1361
|
content_length = c;
|
1270
1362
|
state = State.chunk_size;
|
@@ -1275,6 +1367,7 @@ public class HTTPParser {
|
|
1275
1367
|
case chunk_size:
|
1276
1368
|
if (0 == (flags & F_CHUNKED)) {
|
1277
1369
|
settings.call_on_error(this, "not chunked", data, p_err);
|
1370
|
+
return error();
|
1278
1371
|
}
|
1279
1372
|
|
1280
1373
|
if (CR == ch) {
|
@@ -1282,7 +1375,7 @@ public class HTTPParser {
|
|
1282
1375
|
break;
|
1283
1376
|
}
|
1284
1377
|
|
1285
|
-
c = UNHEX[
|
1378
|
+
c = UNHEX[chi];
|
1286
1379
|
|
1287
1380
|
if (c == -1) {
|
1288
1381
|
if (SEMI == ch || SPACE == ch) {
|
@@ -1290,6 +1383,7 @@ public class HTTPParser {
|
|
1290
1383
|
break;
|
1291
1384
|
}
|
1292
1385
|
settings.call_on_error(this, "invalid hex char in chunk content length", data, p_err);
|
1386
|
+
return error();
|
1293
1387
|
}
|
1294
1388
|
|
1295
1389
|
content_length *= 16;
|
@@ -1301,6 +1395,7 @@ public class HTTPParser {
|
|
1301
1395
|
case chunk_parameters:
|
1302
1396
|
if (0 == (flags & F_CHUNKED)) {
|
1303
1397
|
settings.call_on_error(this, "not chunked", data, p_err);
|
1398
|
+
return error();
|
1304
1399
|
}
|
1305
1400
|
/* just ignore this shit. TODO check for overflow */
|
1306
1401
|
if (CR == ch) {
|
@@ -1314,11 +1409,15 @@ public class HTTPParser {
|
|
1314
1409
|
case chunk_size_almost_done:
|
1315
1410
|
if (0 == (flags & F_CHUNKED)) {
|
1316
1411
|
settings.call_on_error(this, "not chunked", data, p_err);
|
1412
|
+
return error();
|
1317
1413
|
}
|
1318
1414
|
if (strict && LF != ch) {
|
1319
1415
|
settings.call_on_error(this, "expected LF at end of chunk size", data, p_err);
|
1416
|
+
return error();
|
1320
1417
|
}
|
1321
1418
|
|
1419
|
+
this.nread = 0;
|
1420
|
+
|
1322
1421
|
if (0 == content_length) {
|
1323
1422
|
flags |= F_TRAILING;
|
1324
1423
|
state = State.header_field_start;
|
@@ -1333,6 +1432,7 @@ public class HTTPParser {
|
|
1333
1432
|
{
|
1334
1433
|
if (0 == (flags & F_CHUNKED)) {
|
1335
1434
|
settings.call_on_error(this, "not chunked", data, p_err);
|
1435
|
+
return error();
|
1336
1436
|
}
|
1337
1437
|
|
1338
1438
|
to_read = min(pe-p, content_length);
|
@@ -1354,9 +1454,11 @@ public class HTTPParser {
|
|
1354
1454
|
case chunk_data_almost_done:
|
1355
1455
|
if (0 == (flags & F_CHUNKED)) {
|
1356
1456
|
settings.call_on_error(this, "not chunked", data, p_err);
|
1457
|
+
return error();
|
1357
1458
|
}
|
1358
1459
|
if (strict && CR != ch) {
|
1359
1460
|
settings.call_on_error(this, "chunk data terminated incorrectly, expected CR", data, p_err);
|
1461
|
+
return error();
|
1360
1462
|
}
|
1361
1463
|
state = State.chunk_data_done;
|
1362
1464
|
break;
|
@@ -1366,9 +1468,11 @@ public class HTTPParser {
|
|
1366
1468
|
case chunk_data_done:
|
1367
1469
|
if (0 == (flags & F_CHUNKED)) {
|
1368
1470
|
settings.call_on_error(this, "not chunked", data, p_err);
|
1471
|
+
return error();
|
1369
1472
|
}
|
1370
1473
|
if (strict && LF != ch) {
|
1371
1474
|
settings.call_on_error(this, "chunk data terminated incorrectly, expected LF", data, p_err);
|
1475
|
+
return error();
|
1372
1476
|
}
|
1373
1477
|
state = State.chunk_size_start;
|
1374
1478
|
break;
|
@@ -1378,6 +1482,7 @@ public class HTTPParser {
|
|
1378
1482
|
|
1379
1483
|
default:
|
1380
1484
|
settings.call_on_error(this, "unhandled state", data, p_err);
|
1485
|
+
return error();
|
1381
1486
|
|
1382
1487
|
} // switch
|
1383
1488
|
} // while
|
@@ -1394,9 +1499,15 @@ public class HTTPParser {
|
|
1394
1499
|
settings.call_on_query_string(this, data, query_string_mark, p-query_string_mark);
|
1395
1500
|
settings.call_on_path (this, data, path_mark, p-path_mark);
|
1396
1501
|
settings.call_on_url (this, data, url_mark, p-url_mark);
|
1397
|
-
|
1502
|
+
|
1503
|
+
return data.position()-start_position;
|
1398
1504
|
} // execute
|
1399
1505
|
|
1506
|
+
int error () {
|
1507
|
+
this.state = State.dead;
|
1508
|
+
return this.data.position()-start_position;
|
1509
|
+
}
|
1510
|
+
|
1400
1511
|
/* If http_should_keep_alive() in the on_headers_complete or
|
1401
1512
|
* on_message_complete callback returns true, then this will be should be
|
1402
1513
|
* the last message on the connection.
|
@@ -1442,6 +1553,10 @@ public class HTTPParser {
|
|
1442
1553
|
char c = (char)(b);
|
1443
1554
|
return (byte)Character.toUpperCase(c);
|
1444
1555
|
}
|
1556
|
+
|
1557
|
+
byte token(byte b) {
|
1558
|
+
return (byte)tokens[b];
|
1559
|
+
}
|
1445
1560
|
|
1446
1561
|
|
1447
1562
|
HTTPMethod start_req_method_assign(byte c){
|
@@ -1451,12 +1566,14 @@ public class HTTPParser {
|
|
1451
1566
|
case G: return HTTPMethod.HTTP_GET;
|
1452
1567
|
case H: return HTTPMethod.HTTP_HEAD;
|
1453
1568
|
case L: return HTTPMethod.HTTP_LOCK;
|
1454
|
-
case M: return HTTPMethod.HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE */
|
1569
|
+
case M: return HTTPMethod.HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH */
|
1570
|
+
case N: return HTTPMethod.HTTP_NOTIFY;
|
1455
1571
|
case O: return HTTPMethod.HTTP_OPTIONS;
|
1456
1572
|
case P: return HTTPMethod.HTTP_POST; /* or PROPFIND, PROPPATH, PUT */
|
1457
1573
|
case R: return HTTPMethod.HTTP_REPORT;
|
1574
|
+
case S: return HTTPMethod.HTTP_SUBSCRIBE;
|
1458
1575
|
case T: return HTTPMethod.HTTP_TRACE;
|
1459
|
-
case U: return HTTPMethod.HTTP_UNLOCK;
|
1576
|
+
case U: return HTTPMethod.HTTP_UNLOCK; /* or UNSUBSCRIBE */
|
1460
1577
|
}
|
1461
1578
|
return null; // ugh.
|
1462
1579
|
}
|
@@ -1489,7 +1606,6 @@ public class HTTPParser {
|
|
1489
1606
|
if (LF != ch) {
|
1490
1607
|
return false;
|
1491
1608
|
}
|
1492
|
-
|
1493
1609
|
if (0 != (flags & F_TRAILING)) {
|
1494
1610
|
/* End of a chunked request */
|
1495
1611
|
|
@@ -1553,6 +1669,7 @@ public class HTTPParser {
|
|
1553
1669
|
// Exit, the rest of the connect is in a different protocol.
|
1554
1670
|
if (upgrade) {
|
1555
1671
|
settings.call_on_message_complete(this);
|
1672
|
+
state = State.body_identity_eof;
|
1556
1673
|
return true;
|
1557
1674
|
}
|
1558
1675
|
|
@@ -1608,10 +1725,6 @@ public class HTTPParser {
|
|
1608
1725
|
boolean parsing_header(State state) {
|
1609
1726
|
|
1610
1727
|
switch (state) {
|
1611
|
-
case chunk_size_start :
|
1612
|
-
case chunk_size :
|
1613
|
-
case chunk_size_almost_done :
|
1614
|
-
case chunk_parameters :
|
1615
1728
|
case chunk_data :
|
1616
1729
|
case chunk_data_almost_done :
|
1617
1730
|
case chunk_data_done :
|
@@ -1620,7 +1733,7 @@ public class HTTPParser {
|
|
1620
1733
|
return false;
|
1621
1734
|
|
1622
1735
|
}
|
1623
|
-
|
1736
|
+
return true;
|
1624
1737
|
}
|
1625
1738
|
|
1626
1739
|
/* "Dial C for Constants" */
|
@@ -1676,12 +1789,16 @@ public class HTTPParser {
|
|
1676
1789
|
static final byte [] CLOSE = {
|
1677
1790
|
0x43, 0x4c, 0x4f, 0x53, 0x45,
|
1678
1791
|
};
|
1679
|
-
|
1680
|
-
|
1681
|
-
*
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1792
|
+
|
1793
|
+
/* Tokens as defined by rfc 2616. Also lowercases them.
|
1794
|
+
* token = 1*<any CHAR except CTLs or separators>
|
1795
|
+
* separators = "(" | ")" | "<" | ">" | "@"
|
1796
|
+
* | "," | ";" | ":" | "\" | <">
|
1797
|
+
* | "/" | "[" | "]" | "?" | "="
|
1798
|
+
* | "{" | "}" | SP | HT
|
1799
|
+
*/
|
1800
|
+
|
1801
|
+
static final char [] tokens = {
|
1685
1802
|
/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
|
1686
1803
|
0, 0, 0, 0, 0, 0, 0, 0,
|
1687
1804
|
/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
|
@@ -1691,9 +1808,9 @@ public class HTTPParser {
|
|
1691
1808
|
/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
|
1692
1809
|
0, 0, 0, 0, 0, 0, 0, 0,
|
1693
1810
|
/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
|
1694
|
-
' ',
|
1811
|
+
' ', '!', '"', '#', '$', '%', '&', '\'',
|
1695
1812
|
/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
|
1696
|
-
0, 0,
|
1813
|
+
0, 0, '*', '+', 0, '-', '.', '/' ,
|
1697
1814
|
/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
|
1698
1815
|
'0', '1', '2', '3', '4', '5', '6', '7',
|
1699
1816
|
/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
|
@@ -1713,7 +1830,24 @@ public class HTTPParser {
|
|
1713
1830
|
/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
|
1714
1831
|
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
|
1715
1832
|
/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
|
1716
|
-
'X', 'Y', 'Z', 0,
|
1833
|
+
'X', 'Y', 'Z', 0, '|', '}', 0, 0,
|
1834
|
+
/* hi bit set, not ascii */
|
1835
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1836
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1837
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1838
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1839
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1840
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1841
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1842
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1843
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1844
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1845
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1846
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1847
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1848
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1849
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
1850
|
+
0, 0, 0, 0, 0, 0, 0, 0, };
|
1717
1851
|
|
1718
1852
|
static final byte [] UNHEX =
|
1719
1853
|
{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
@@ -1724,6 +1858,14 @@ public class HTTPParser {
|
|
1724
1858
|
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
1725
1859
|
,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
1726
1860
|
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
1861
|
+
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
1862
|
+
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
1863
|
+
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
1864
|
+
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
1865
|
+
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
1866
|
+
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
1867
|
+
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
1868
|
+
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
1727
1869
|
};
|
1728
1870
|
|
1729
1871
|
static final boolean [] normal_url_char = {
|
@@ -1758,7 +1900,31 @@ public class HTTPParser {
|
|
1758
1900
|
/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
|
1759
1901
|
true, true, true, true, true, true, true, true,
|
1760
1902
|
/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
|
1761
|
-
true, true, true, true, true, true, true, false
|
1903
|
+
true, true, true, true, true, true, true, false,
|
1904
|
+
|
1905
|
+
/* hi bit set, not ascii */
|
1906
|
+
/* Remainder of non-ASCII range are accepted as-is to support implicitly UTF-8
|
1907
|
+
* encoded paths. This is out of spec, but clients generate this and most other
|
1908
|
+
* HTTP servers support it. We should, too. */
|
1909
|
+
|
1910
|
+
true, true, true, true, true, true, true, true,
|
1911
|
+
true, true, true, true, true, true, true, true,
|
1912
|
+
true, true, true, true, true, true, true, true,
|
1913
|
+
true, true, true, true, true, true, true, true,
|
1914
|
+
true, true, true, true, true, true, true, true,
|
1915
|
+
true, true, true, true, true, true, true, true,
|
1916
|
+
true, true, true, true, true, true, true, true,
|
1917
|
+
true, true, true, true, true, true, true, true,
|
1918
|
+
true, true, true, true, true, true, true, true,
|
1919
|
+
true, true, true, true, true, true, true, true,
|
1920
|
+
true, true, true, true, true, true, true, true,
|
1921
|
+
true, true, true, true, true, true, true, true,
|
1922
|
+
true, true, true, true, true, true, true, true,
|
1923
|
+
true, true, true, true, true, true, true, true,
|
1924
|
+
true, true, true, true, true, true, true, true,
|
1925
|
+
true, true, true, true, true, true, true, true,
|
1926
|
+
|
1927
|
+
};
|
1762
1928
|
|
1763
1929
|
public static final byte A = 0x41;
|
1764
1930
|
public static final byte B = 0x42;
|
@@ -1796,6 +1962,7 @@ public class HTTPParser {
|
|
1796
1962
|
public static final byte QMARK = 0x3f;
|
1797
1963
|
public static final byte SLASH = 0x2f;
|
1798
1964
|
public static final byte DASH = 0x2d;
|
1965
|
+
public static final byte STAR = 0x2a;
|
1799
1966
|
public static final byte NULL = 0x00;
|
1800
1967
|
}
|
1801
1968
|
|
@@ -1851,12 +2018,19 @@ public class HTTPParser {
|
|
1851
2018
|
|
1852
2019
|
, header_almost_done
|
1853
2020
|
|
1854
|
-
, headers_almost_done
|
1855
|
-
|
1856
2021
|
, chunk_size_start
|
1857
2022
|
, chunk_size
|
1858
|
-
, chunk_size_almost_done
|
1859
2023
|
, chunk_parameters
|
2024
|
+
, chunk_size_almost_done
|
2025
|
+
|
2026
|
+
, headers_almost_done
|
2027
|
+
// This space intentionally not left blank, comment from c, for orientation...
|
2028
|
+
// the c version uses <= s_header_almost_done in java, we list the states explicitly
|
2029
|
+
// in `parsing_header()`
|
2030
|
+
/* Important: 's_headers_almost_done' must be the last 'header' state. All
|
2031
|
+
* states beyond this must be 'body' states. It is used for overflow
|
2032
|
+
* checking. See the PARSING_HEADER() macro.
|
2033
|
+
*/
|
1860
2034
|
, chunk_data
|
1861
2035
|
, chunk_data_almost_done
|
1862
2036
|
, chunk_data_done
|