sproutit-narwhal 0.1.106

Sign up to get free protection for your applications and to get access to all the features.
Files changed (291) hide show
  1. data/DISTRIBUTION.yml +15 -0
  2. data/README.md +86 -0
  3. data/Rakefile +349 -0
  4. data/VERSION.yml +7 -0
  5. data/bin/activate +50 -0
  6. data/bin/activate.bash +50 -0
  7. data/bin/activate.cmd +3 -0
  8. data/bin/js +67 -0
  9. data/bin/json +2 -0
  10. data/bin/narwhal +67 -0
  11. data/bin/narwhal.cmd +29 -0
  12. data/bin/sea +45 -0
  13. data/bin/sea.cmd +25 -0
  14. data/bin/tusk +2 -0
  15. data/bin/tusk.cmd +5 -0
  16. data/catalog.json +902 -0
  17. data/docs/available-packages.md +32 -0
  18. data/docs/browser-api-plan.md +290 -0
  19. data/docs/browser-api.md +153 -0
  20. data/docs/download.md +25 -0
  21. data/docs/engines.md +32 -0
  22. data/docs/json-tool.md +121 -0
  23. data/docs/lib/binary.wiki +242 -0
  24. data/docs/lib/file.wiki +325 -0
  25. data/docs/lib/os/popen.md +70 -0
  26. data/docs/modules.md +38 -0
  27. data/docs/narwhal.md +487 -0
  28. data/docs/packages-howto.md +32 -0
  29. data/docs/packages.md +30 -0
  30. data/docs/posts/2009-07-29-hello-0.1.md +19 -0
  31. data/docs/quick-start.md +69 -0
  32. data/docs/sea.md +49 -0
  33. data/engines/browser/lib/binary.js +2 -0
  34. data/engines/browser/lib/reactor.js +21 -0
  35. data/engines/browser/lib/system.js +3 -0
  36. data/engines/default/lib/array.js +164 -0
  37. data/engines/default/lib/binary-engine.js +53 -0
  38. data/engines/default/lib/binary.js +755 -0
  39. data/engines/default/lib/date.js +8 -0
  40. data/engines/default/lib/file-engine.js +119 -0
  41. data/engines/default/lib/function.js +119 -0
  42. data/engines/default/lib/global.js +11 -0
  43. data/engines/default/lib/io-engine.js +26 -0
  44. data/engines/default/lib/json.js +488 -0
  45. data/engines/default/lib/object.js +69 -0
  46. data/engines/default/lib/os-engine.js +3 -0
  47. data/engines/default/lib/reactor.js +12 -0
  48. data/engines/default/lib/string.js +84 -0
  49. data/engines/default/lib/system.js +20 -0
  50. data/engines/default/lib/worker.js +133 -0
  51. data/engines/jsc/README.md +18 -0
  52. data/engines/jsc/bootstrap.js +53 -0
  53. data/engines/jsc/deps/http-parser/LICENSE +77 -0
  54. data/engines/jsc/deps/http-parser/README.md +145 -0
  55. data/engines/jsc/deps/http-parser/http_parser.c +6087 -0
  56. data/engines/jsc/deps/http-parser/http_parser.h +141 -0
  57. data/engines/jsc/deps/http-parser/http_parser.rl +500 -0
  58. data/engines/jsc/deps/http-parser/test.c +858 -0
  59. data/engines/jsc/include/binary-engine.h +11 -0
  60. data/engines/jsc/include/io-engine.h +23 -0
  61. data/engines/jsc/include/narwhal.h +427 -0
  62. data/engines/jsc/lib/file-engine.js +31 -0
  63. data/engines/jsc/lib/http.js +1 -0
  64. data/engines/jsc/lib/io-engine.js +202 -0
  65. data/engines/jsc/lib/os-engine.js +25 -0
  66. data/engines/jsc/lib/system.js +18 -0
  67. data/engines/jsc/lib/zip.js +1 -0
  68. data/engines/jsc/narwhal-jsc.c +273 -0
  69. data/engines/jsc/narwhal.c +29 -0
  70. data/engines/jsc/package.json +8 -0
  71. data/engines/jsc/src/binary-engine.cc +290 -0
  72. data/engines/jsc/src/file-engine.cc +405 -0
  73. data/engines/jsc/src/io-engine.cc +423 -0
  74. data/engines/jsc/src/jack/handler/jill.cc +710 -0
  75. data/engines/jsc/src/os-engine.cc +210 -0
  76. data/engines/rhino/bin/narwhal-rhino +68 -0
  77. data/engines/rhino/bin/narwhal-rhino.cmd +34 -0
  78. data/engines/rhino/bootstrap.js +119 -0
  79. data/engines/rhino/jars/jline.jar +0 -0
  80. data/engines/rhino/jars/jna.jar +0 -0
  81. data/engines/rhino/jars/js.jar +0 -0
  82. data/engines/rhino/lib/binary-engine.js +83 -0
  83. data/engines/rhino/lib/concurrency.js +6 -0
  84. data/engines/rhino/lib/event-queue.js +18 -0
  85. data/engines/rhino/lib/file-engine.js +216 -0
  86. data/engines/rhino/lib/http-client-engine.js +90 -0
  87. data/engines/rhino/lib/http-engine.js +10 -0
  88. data/engines/rhino/lib/io-engine.js +347 -0
  89. data/engines/rhino/lib/md5-engine.js +40 -0
  90. data/engines/rhino/lib/os-engine.js +150 -0
  91. data/engines/rhino/lib/packages-engine.js +71 -0
  92. data/engines/rhino/lib/sandbox-engine.js +70 -0
  93. data/engines/rhino/lib/system.js +38 -0
  94. data/engines/rhino/lib/worker-engine.js +23 -0
  95. data/engines/rhino/lib/zip.js +78 -0
  96. data/engines/rhino/package.json +4 -0
  97. data/engines/secure/lib/file.js +6 -0
  98. data/engines/secure/lib/system.js +6 -0
  99. data/engines/template/bin/narwhal-engine-name +32 -0
  100. data/engines/template/bootstrap.js +40 -0
  101. data/engines/template/lib/file-engine.js +118 -0
  102. data/engines/template/lib/system.js +17 -0
  103. data/examples/browser-deployment-jackconfig.js +35 -0
  104. data/examples/fibonacci-worker.js +35 -0
  105. data/examples/fibonacci.js +19 -0
  106. data/examples/hello +2 -0
  107. data/examples/narwhal +3 -0
  108. data/examples/not-quite-a-quine.js +1 -0
  109. data/extconf.rb +44 -0
  110. data/gem_bin/narwhal +5 -0
  111. data/gem_bin/sea +4 -0
  112. data/gem_bin/tusk +4 -0
  113. data/lib/args.js +849 -0
  114. data/lib/base16.js +16 -0
  115. data/lib/base64.js +120 -0
  116. data/lib/codec/base64.js +8 -0
  117. data/lib/crc32.js +60 -0
  118. data/lib/file-bootstrap.js +187 -0
  119. data/lib/file.js +659 -0
  120. data/lib/hash.js +28 -0
  121. data/lib/hashp.js +65 -0
  122. data/lib/html.js +16 -0
  123. data/lib/http-client.js +134 -0
  124. data/lib/http.js +17 -0
  125. data/lib/io.js +98 -0
  126. data/lib/jsmin.js +315 -0
  127. data/lib/jsonpath.js +89 -0
  128. data/lib/logger.js +55 -0
  129. data/lib/md4.js +146 -0
  130. data/lib/md5.js +164 -0
  131. data/lib/mime.js +166 -0
  132. data/lib/narwhal.js +102 -0
  133. data/lib/narwhal/client.js +261 -0
  134. data/lib/narwhal/compile.js +99 -0
  135. data/lib/narwhal/env.js +140 -0
  136. data/lib/narwhal/inline.js +106 -0
  137. data/lib/narwhal/json.js +324 -0
  138. data/lib/narwhal/json.md +178 -0
  139. data/lib/narwhal/repl.js +96 -0
  140. data/lib/narwhal/server-test.js +6 -0
  141. data/lib/narwhal/server.js +270 -0
  142. data/lib/narwhal/tusk.js +170 -0
  143. data/lib/narwhal/tusk/bin.js +13 -0
  144. data/lib/narwhal/tusk/bundle.js +0 -0
  145. data/lib/narwhal/tusk/catalog.js +22 -0
  146. data/lib/narwhal/tusk/clone.js +66 -0
  147. data/lib/narwhal/tusk/consolidate.js +25 -0
  148. data/lib/narwhal/tusk/create-catalog.js +80 -0
  149. data/lib/narwhal/tusk/engine.js +42 -0
  150. data/lib/narwhal/tusk/freeze.js +0 -0
  151. data/lib/narwhal/tusk/init.js +56 -0
  152. data/lib/narwhal/tusk/install.js +288 -0
  153. data/lib/narwhal/tusk/list.js +20 -0
  154. data/lib/narwhal/tusk/orphans.js +0 -0
  155. data/lib/narwhal/tusk/reheat.js +15 -0
  156. data/lib/narwhal/tusk/remove.js +15 -0
  157. data/lib/narwhal/tusk/search.js +145 -0
  158. data/lib/narwhal/tusk/update.js +21 -0
  159. data/lib/narwhal/tusk/upgrade.js +0 -0
  160. data/lib/os.js +33 -0
  161. data/lib/packages.js +423 -0
  162. data/lib/printf.js +169 -0
  163. data/lib/promise.js +352 -0
  164. data/lib/querystring.js +176 -0
  165. data/lib/ref-send.js +257 -0
  166. data/lib/regexp.js +12 -0
  167. data/lib/sandbox.js +422 -0
  168. data/lib/sha.js +112 -0
  169. data/lib/sha256.js +102 -0
  170. data/lib/struct.js +228 -0
  171. data/lib/term.js +179 -0
  172. data/lib/test/assert.js +95 -0
  173. data/lib/test/equiv.js +188 -0
  174. data/lib/test/jsdump.js +165 -0
  175. data/lib/test/runner.js +129 -0
  176. data/lib/unload.js +13 -0
  177. data/lib/uri.js +378 -0
  178. data/lib/url.js +5 -0
  179. data/lib/utf8.js +64 -0
  180. data/lib/util.js +985 -0
  181. data/lib/uuid.js +89 -0
  182. data/lib/xregexp.js +521 -0
  183. data/local.json.template +1 -0
  184. data/narwhal.gemspec +105 -0
  185. data/narwhal.js +213 -0
  186. data/package.json +26 -0
  187. data/packages/readline/engines/default/lib/readline.js +4 -0
  188. data/packages/readline/engines/rhino/lib/readline.js +6 -0
  189. data/packages/readline/package.json +5 -0
  190. data/sources.json +207 -0
  191. data/tests/all-tests.js +17 -0
  192. data/tests/args.js +31 -0
  193. data/tests/args/domain.js +215 -0
  194. data/tests/args/options.js +36 -0
  195. data/tests/args/shifting.js +92 -0
  196. data/tests/args/validation.js +31 -0
  197. data/tests/base64.js +23 -0
  198. data/tests/commonjs.js +3 -0
  199. data/tests/commonjs/all-tests.js +12 -0
  200. data/tests/commonjs/bytearray-encodings-tests.js +69 -0
  201. data/tests/commonjs/bytearray-tests.js +465 -0
  202. data/tests/commonjs/bytestring-encodings-tests.js +89 -0
  203. data/tests/commonjs/bytestring-tests.js +263 -0
  204. data/tests/commonjs/es5/all-tests.js +3 -0
  205. data/tests/commonjs/es5/bind.js +29 -0
  206. data/tests/commonjs/file-tests.js +315 -0
  207. data/tests/commonjs/file/dirname.js +31 -0
  208. data/tests/commonjs/file/extension.js +45 -0
  209. data/tests/commonjs/file/is-absolute.js +11 -0
  210. data/tests/commonjs/file/iterator.js +101 -0
  211. data/tests/commonjs/file/normal.js +27 -0
  212. data/tests/commonjs/file/path.js +17 -0
  213. data/tests/commonjs/file/relative.js +42 -0
  214. data/tests/commonjs/file/resolve.js +44 -0
  215. data/tests/commonjs/module-tests.js +9 -0
  216. data/tests/commonjs/modules/absolute/b.js +1 -0
  217. data/tests/commonjs/modules/absolute/program.js +5 -0
  218. data/tests/commonjs/modules/absolute/submodule/a.js +3 -0
  219. data/tests/commonjs/modules/absolute/test.js +9 -0
  220. data/tests/commonjs/modules/all-tests.js +47 -0
  221. data/tests/commonjs/modules/config.js +11 -0
  222. data/tests/commonjs/modules/cyclic/a.js +4 -0
  223. data/tests/commonjs/modules/cyclic/b.js +4 -0
  224. data/tests/commonjs/modules/cyclic/program.js +10 -0
  225. data/tests/commonjs/modules/cyclic/test.js +9 -0
  226. data/tests/commonjs/modules/determinism/program.js +3 -0
  227. data/tests/commonjs/modules/determinism/submodule/a.js +8 -0
  228. data/tests/commonjs/modules/determinism/submodule/b.js +2 -0
  229. data/tests/commonjs/modules/determinism/test.js +9 -0
  230. data/tests/commonjs/modules/exactExports/a.js +3 -0
  231. data/tests/commonjs/modules/exactExports/program.js +4 -0
  232. data/tests/commonjs/modules/exactExports/test.js +9 -0
  233. data/tests/commonjs/modules/hasOwnProperty/hasOwnProperty.js +0 -0
  234. data/tests/commonjs/modules/hasOwnProperty/program.js +3 -0
  235. data/tests/commonjs/modules/hasOwnProperty/test.js +9 -0
  236. data/tests/commonjs/modules/hasOwnProperty/toString.js +0 -0
  237. data/tests/commonjs/modules/method/a.js +12 -0
  238. data/tests/commonjs/modules/method/program.js +8 -0
  239. data/tests/commonjs/modules/method/test.js +9 -0
  240. data/tests/commonjs/modules/missing/program.js +8 -0
  241. data/tests/commonjs/modules/missing/test.js +9 -0
  242. data/tests/commonjs/modules/monkeys/a.js +1 -0
  243. data/tests/commonjs/modules/monkeys/program.js +4 -0
  244. data/tests/commonjs/modules/monkeys/test.js +9 -0
  245. data/tests/commonjs/modules/nested/a/b/c/d.js +3 -0
  246. data/tests/commonjs/modules/nested/program.js +3 -0
  247. data/tests/commonjs/modules/nested/test.js +9 -0
  248. data/tests/commonjs/modules/relative/program.js +5 -0
  249. data/tests/commonjs/modules/relative/submodule/a.js +1 -0
  250. data/tests/commonjs/modules/relative/submodule/b.js +2 -0
  251. data/tests/commonjs/modules/relative/test.js +9 -0
  252. data/tests/commonjs/modules/transitive/a.js +1 -0
  253. data/tests/commonjs/modules/transitive/b.js +1 -0
  254. data/tests/commonjs/modules/transitive/c.js +3 -0
  255. data/tests/commonjs/modules/transitive/program.js +3 -0
  256. data/tests/commonjs/modules/transitive/test.js +9 -0
  257. data/tests/file/all-tests.js +61 -0
  258. data/tests/file/fnmatch.js +102 -0
  259. data/tests/file/glob.js +466 -0
  260. data/tests/file/match.js +102 -0
  261. data/tests/global.js +6 -0
  262. data/tests/global/array.js +19 -0
  263. data/tests/hashes.js +94 -0
  264. data/tests/html.js +13 -0
  265. data/tests/io/stringio.js +21 -0
  266. data/tests/os/all-tests.js +4 -0
  267. data/tests/os/popen.js +41 -0
  268. data/tests/os/system.js +22 -0
  269. data/tests/printf.js +123 -0
  270. data/tests/query-string.js +87 -0
  271. data/tests/sandbox/byte-io.js +20 -0
  272. data/tests/sandbox/fileName.js +3 -0
  273. data/tests/sandbox/foo.js +0 -0
  274. data/tests/sandbox/reload.js +79 -0
  275. data/tests/string.js +35 -0
  276. data/tests/uri.js +41 -0
  277. data/tests/util/all-tests.js +79 -0
  278. data/tests/util/array.js +207 -0
  279. data/tests/util/array/is-arguments.js +29 -0
  280. data/tests/util/array/is-array-like.js +29 -0
  281. data/tests/util/case.js +9 -0
  282. data/tests/util/collection.js +104 -0
  283. data/tests/util/eq.js +57 -0
  284. data/tests/util/expand.js +45 -0
  285. data/tests/util/object.js +125 -0
  286. data/tests/util/operator.js +25 -0
  287. data/tests/util/range.js +19 -0
  288. data/tests/util/repr.js +26 -0
  289. data/tests/util/string.js +34 -0
  290. data/tests/util/unique.js +12 -0
  291. metadata +434 -0
@@ -0,0 +1,141 @@
1
+ /* Copyright (c) 2008, 2009 Ryan Dahl (ry@tinyclouds.org)
2
+ * Based on Zed Shaw's Mongrel, copyright (c) Zed A. Shaw
3
+ *
4
+ * All rights reserved.
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining
7
+ * a copy of this software and associated documentation files (the
8
+ * "Software"), to deal in the Software without restriction, including
9
+ * without limitation the rights to use, copy, modify, merge, publish,
10
+ * distribute, sublicense, and/or sell copies of the Software, and to
11
+ * permit persons to whom the Software is furnished to do so, subject to
12
+ * the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be
15
+ * included in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ */
25
+ #ifndef http_parser_h
26
+ #define http_parser_h
27
+ #ifdef __cplusplus
28
+ extern "C" {
29
+ #endif
30
+
31
+ #ifdef _MSC_VER
32
+ # include <stddef.h>
33
+ #endif
34
+ #include <sys/types.h>
35
+
36
+ typedef struct http_parser http_parser;
37
+
38
+ /* Callbacks should return non-zero to indicate an error. The parse will
39
+ * then halt execution.
40
+ *
41
+ * http_data_cb does not return data chunks. It will be call arbitrarally
42
+ * many times for each string. E.G. you might get 10 callbacks for "on_path"
43
+ * each providing just a few characters more data.
44
+ */
45
+ typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
46
+ typedef int (*http_cb) (http_parser*);
47
+
48
+ /* Request Methods */
49
+ #define HTTP_COPY 0x0001
50
+ #define HTTP_DELETE 0x0002
51
+ #define HTTP_GET 0x0004
52
+ #define HTTP_HEAD 0x0008
53
+ #define HTTP_LOCK 0x0010
54
+ #define HTTP_MKCOL 0x0020
55
+ #define HTTP_MOVE 0x0040
56
+ #define HTTP_OPTIONS 0x0080
57
+ #define HTTP_POST 0x0100
58
+ #define HTTP_PROPFIND 0x0200
59
+ #define HTTP_PROPPATCH 0x0400
60
+ #define HTTP_PUT 0x0800
61
+ #define HTTP_TRACE 0x1000
62
+ #define HTTP_UNLOCK 0x2000
63
+
64
+ enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE };
65
+
66
+ #define HTTP_VERSION_OTHER 0x00
67
+ #define HTTP_VERSION_11 0x01
68
+ #define HTTP_VERSION_10 0x02
69
+ #define HTTP_VERSION_09 0x04
70
+
71
+ struct http_parser {
72
+ /** PRIVATE **/
73
+ int cs;
74
+ enum http_parser_type type;
75
+
76
+ size_t chunk_size;
77
+ char flags;
78
+
79
+ size_t body_read;
80
+
81
+ const char *header_field_mark;
82
+ size_t header_field_size;
83
+ const char *header_value_mark;
84
+ size_t header_value_size;
85
+ const char *query_string_mark;
86
+ size_t query_string_size;
87
+ const char *path_mark;
88
+ size_t path_size;
89
+ const char *uri_mark;
90
+ size_t uri_size;
91
+ const char *fragment_mark;
92
+ size_t fragment_size;
93
+
94
+ /** READ-ONLY **/
95
+ unsigned short status_code; /* responses only */
96
+ unsigned short method; /* requests only */
97
+ short version;
98
+ short keep_alive;
99
+ ssize_t content_length;
100
+
101
+ /** PUBLIC **/
102
+ void *data; /* A pointer to get hook to the "connection" or "socket" object */
103
+
104
+ /* an ordered list of callbacks */
105
+
106
+ http_cb on_message_begin;
107
+
108
+ /* requests only */
109
+ http_data_cb on_path;
110
+ http_data_cb on_query_string;
111
+ http_data_cb on_uri;
112
+ http_data_cb on_fragment;
113
+
114
+ http_data_cb on_header_field;
115
+ http_data_cb on_header_value;
116
+ http_cb on_headers_complete;
117
+ http_data_cb on_body;
118
+ http_cb on_message_complete;
119
+ };
120
+
121
+ /* Initializes an http_parser structure. The second argument specifies if
122
+ * it will be parsing requests or responses.
123
+ */
124
+ void http_parser_init (http_parser *parser, enum http_parser_type);
125
+
126
+ void http_parser_execute (http_parser *parser, const char *data, size_t len);
127
+
128
+ int http_parser_has_error (http_parser *parser);
129
+
130
+ static inline int
131
+ http_parser_should_keep_alive (http_parser *parser)
132
+ {
133
+ if (parser->keep_alive == -1) return (parser->version == HTTP_VERSION_11);
134
+ return parser->keep_alive;
135
+ }
136
+
137
+
138
+ #ifdef __cplusplus
139
+ }
140
+ #endif
141
+ #endif
@@ -0,0 +1,500 @@
1
+ /* Copyright (c) 2008, 2009 Ryan Dahl (ry@tinyclouds.org)
2
+ * Based on Zed Shaw's Mongrel, copyright (c) Zed A. Shaw
3
+ *
4
+ * All rights reserved.
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining
7
+ * a copy of this software and associated documentation files (the
8
+ * "Software"), to deal in the Software without restriction, including
9
+ * without limitation the rights to use, copy, modify, merge, publish,
10
+ * distribute, sublicense, and/or sell copies of the Software, and to
11
+ * permit persons to whom the Software is furnished to do so, subject to
12
+ * the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be
15
+ * included in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ */
25
+ #include "http_parser.h"
26
+ #include <limits.h>
27
+ #include <assert.h>
28
+
29
+ /* parser->flags */
30
+ #define EATING 0x01
31
+ #define ERROR 0x02
32
+ #define CHUNKED 0x04
33
+ #define EAT_FOREVER 0x10
34
+
35
+ static int unhex[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
36
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
37
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
38
+ , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
39
+ ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
40
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
41
+ ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
42
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
43
+ };
44
+
45
+ #undef MIN
46
+ #define MIN(a,b) ((a) < (b) ? (a) : (b))
47
+
48
+ #undef NULL
49
+ #define NULL ((void*)(0))
50
+
51
+ #define MAX_FIELD_SIZE (80*1024)
52
+
53
+ #define REMAINING (unsigned long)(pe - p)
54
+ #define CALLBACK(FOR) \
55
+ do { \
56
+ if (parser->FOR##_mark) { \
57
+ parser->FOR##_size += p - parser->FOR##_mark; \
58
+ if (parser->FOR##_size > MAX_FIELD_SIZE) { \
59
+ parser->flags |= ERROR; \
60
+ return; \
61
+ } \
62
+ if (parser->on_##FOR) { \
63
+ callback_return_value = parser->on_##FOR(parser, \
64
+ parser->FOR##_mark, \
65
+ p - parser->FOR##_mark); \
66
+ } \
67
+ if (callback_return_value != 0) { \
68
+ parser->flags |= ERROR; \
69
+ return; \
70
+ } \
71
+ } \
72
+ } while(0)
73
+
74
+ #define RESET_PARSER(parser) \
75
+ parser->chunk_size = 0; \
76
+ parser->flags = 0; \
77
+ parser->header_field_mark = NULL; \
78
+ parser->header_value_mark = NULL; \
79
+ parser->query_string_mark = NULL; \
80
+ parser->path_mark = NULL; \
81
+ parser->uri_mark = NULL; \
82
+ parser->fragment_mark = NULL; \
83
+ parser->status_code = 0; \
84
+ parser->method = 0; \
85
+ parser->version = HTTP_VERSION_OTHER; \
86
+ parser->keep_alive = -1; \
87
+ parser->content_length = -1; \
88
+ parser->body_read = 0
89
+
90
+ #define END_REQUEST \
91
+ do { \
92
+ if (parser->on_message_complete) { \
93
+ callback_return_value = \
94
+ parser->on_message_complete(parser); \
95
+ } \
96
+ RESET_PARSER(parser); \
97
+ } while (0)
98
+
99
+ #define SKIP_BODY(nskip) \
100
+ do { \
101
+ tmp = (nskip); \
102
+ if (parser->on_body && tmp > 0) { \
103
+ callback_return_value = parser->on_body(parser, p, tmp); \
104
+ } \
105
+ if (callback_return_value == 0) { \
106
+ p += tmp; \
107
+ parser->body_read += tmp; \
108
+ parser->chunk_size -= tmp; \
109
+ if (0 == parser->chunk_size) { \
110
+ parser->flags &= ~EATING; \
111
+ if (!(parser->flags & CHUNKED)) { \
112
+ END_REQUEST; \
113
+ } \
114
+ } else { \
115
+ parser->flags |= EATING; \
116
+ } \
117
+ } \
118
+ } while (0)
119
+
120
+ %%{
121
+ machine http_parser;
122
+
123
+ action mark_header_field {
124
+ parser->header_field_mark = p;
125
+ parser->header_field_size = 0;
126
+ }
127
+
128
+ action mark_header_value {
129
+ parser->header_value_mark = p;
130
+ parser->header_value_size = 0;
131
+ }
132
+
133
+ action mark_fragment {
134
+ parser->fragment_mark = p;
135
+ parser->fragment_size = 0;
136
+ }
137
+
138
+ action mark_query_string {
139
+ parser->query_string_mark = p;
140
+ parser->query_string_size = 0;
141
+ }
142
+
143
+ action mark_request_path {
144
+ parser->path_mark = p;
145
+ parser->path_size = 0;
146
+ }
147
+
148
+ action mark_request_uri {
149
+ parser->uri_mark = p;
150
+ parser->uri_size = 0;
151
+ }
152
+
153
+ action header_field {
154
+ CALLBACK(header_field);
155
+ parser->header_field_mark = NULL;
156
+ parser->header_field_size = 0;
157
+ }
158
+
159
+ action header_value {
160
+ CALLBACK(header_value);
161
+ parser->header_value_mark = NULL;
162
+ parser->header_value_size = 0;
163
+ }
164
+
165
+ action request_uri {
166
+ CALLBACK(uri);
167
+ parser->uri_mark = NULL;
168
+ parser->uri_size = 0;
169
+ }
170
+
171
+ action fragment {
172
+ CALLBACK(fragment);
173
+ parser->fragment_mark = NULL;
174
+ parser->fragment_size = 0;
175
+ }
176
+
177
+ action query_string {
178
+ CALLBACK(query_string);
179
+ parser->query_string_mark = NULL;
180
+ parser->query_string_size = 0;
181
+ }
182
+
183
+ action request_path {
184
+ CALLBACK(path);
185
+ parser->path_mark = NULL;
186
+ parser->path_size = 0;
187
+ }
188
+
189
+ action headers_complete {
190
+ if(parser->on_headers_complete) {
191
+ callback_return_value = parser->on_headers_complete(parser);
192
+ if (callback_return_value != 0) {
193
+ parser->flags |= ERROR;
194
+ return;
195
+ }
196
+ }
197
+ }
198
+
199
+ action begin_message {
200
+ if(parser->on_message_begin) {
201
+ callback_return_value = parser->on_message_begin(parser);
202
+ if (callback_return_value != 0) {
203
+ parser->flags |= ERROR;
204
+ return;
205
+ }
206
+ }
207
+ }
208
+
209
+ action content_length {
210
+ if (parser->content_length == -1) parser->content_length = 0;
211
+ if (parser->content_length > INT_MAX) {
212
+ parser->flags |= ERROR;
213
+ return;
214
+ }
215
+ parser->content_length *= 10;
216
+ parser->content_length += *p - '0';
217
+ }
218
+
219
+ action status_code {
220
+ parser->status_code *= 10;
221
+ parser->status_code += *p - '0';
222
+ }
223
+
224
+ action use_chunked_encoding { parser->flags |= CHUNKED; }
225
+
226
+ action set_keep_alive { parser->keep_alive = 1; }
227
+ action set_not_keep_alive { parser->keep_alive = 0; }
228
+
229
+ action version_11 { parser->version = HTTP_VERSION_11; }
230
+ action version_10 { parser->version = HTTP_VERSION_10; }
231
+ action version_09 { parser->version = HTTP_VERSION_09; }
232
+
233
+ action add_to_chunk_size {
234
+ parser->chunk_size *= 16;
235
+ parser->chunk_size += unhex[(int)*p];
236
+ }
237
+
238
+ action skip_chunk_data {
239
+ SKIP_BODY(MIN(parser->chunk_size, REMAINING));
240
+ if (callback_return_value != 0) {
241
+ parser->flags |= ERROR;
242
+ return;
243
+ }
244
+
245
+ fhold;
246
+ if (parser->chunk_size > REMAINING) {
247
+ fbreak;
248
+ } else {
249
+ fgoto chunk_end;
250
+ }
251
+ }
252
+
253
+ action end_chunked_body {
254
+ END_REQUEST;
255
+ if (parser->type == HTTP_REQUEST) {
256
+ fnext Requests;
257
+ } else {
258
+ fnext Responses;
259
+ }
260
+ }
261
+
262
+ action body_logic {
263
+ if (parser->flags & CHUNKED) {
264
+ fnext ChunkedBody;
265
+ } else {
266
+ /* this is pretty stupid. i'd prefer to combine this with
267
+ * skip_chunk_data */
268
+ if (parser->content_length < 0) {
269
+ /* If we didn't get a content length; if not keep-alive
270
+ * just read body until EOF */
271
+ if (!http_parser_should_keep_alive(parser)) {
272
+ parser->flags |= EAT_FOREVER;
273
+ parser->chunk_size = REMAINING;
274
+ } else {
275
+ /* Otherwise, if keep-alive, then assume the message
276
+ * has no body. */
277
+ parser->chunk_size = parser->content_length = 0;
278
+ }
279
+ } else {
280
+ parser->chunk_size = parser->content_length;
281
+ }
282
+ p += 1;
283
+
284
+ SKIP_BODY(MIN(REMAINING, parser->chunk_size));
285
+
286
+ if (callback_return_value != 0) {
287
+ parser->flags |= ERROR;
288
+ return;
289
+ }
290
+
291
+ fhold;
292
+ if(parser->chunk_size > REMAINING) {
293
+ fbreak;
294
+ }
295
+ }
296
+ }
297
+
298
+ CRLF = "\r\n";
299
+
300
+ # character types
301
+ CTL = (cntrl | 127);
302
+ safe = ("$" | "-" | "_" | ".");
303
+ extra = ("!" | "*" | "'" | "(" | ")" | ",");
304
+ reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
305
+ unsafe = (CTL | " " | "\"" | "#" | "%" | "<" | ">");
306
+ national = any -- (alpha | digit | reserved | extra | safe | unsafe);
307
+ unreserved = (alpha | digit | safe | extra | national);
308
+ escape = ("%" xdigit xdigit);
309
+ uchar = (unreserved | escape);
310
+ pchar = (uchar | ":" | "@" | "&" | "=" | "+");
311
+ tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\""
312
+ | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
313
+
314
+ # elements
315
+ token = (ascii -- (CTL | tspecials));
316
+ quote = "\"";
317
+ # qdtext = token -- "\"";
318
+ # quoted_pair = "\" ascii;
319
+ # quoted_string = "\"" (qdtext | quoted_pair )* "\"";
320
+
321
+ # headers
322
+
323
+ Method = ( "COPY" %{ parser->method = HTTP_COPY; }
324
+ | "DELETE" %{ parser->method = HTTP_DELETE; }
325
+ | "GET" %{ parser->method = HTTP_GET; }
326
+ | "HEAD" %{ parser->method = HTTP_HEAD; }
327
+ | "LOCK" %{ parser->method = HTTP_LOCK; }
328
+ | "MKCOL" %{ parser->method = HTTP_MKCOL; }
329
+ | "MOVE" %{ parser->method = HTTP_MOVE; }
330
+ | "OPTIONS" %{ parser->method = HTTP_OPTIONS; }
331
+ | "POST" %{ parser->method = HTTP_POST; }
332
+ | "PROPFIND" %{ parser->method = HTTP_PROPFIND; }
333
+ | "PROPPATCH" %{ parser->method = HTTP_PROPPATCH; }
334
+ | "PUT" %{ parser->method = HTTP_PUT; }
335
+ | "TRACE" %{ parser->method = HTTP_TRACE; }
336
+ | "UNLOCK" %{ parser->method = HTTP_UNLOCK; }
337
+ ); # Not allowing extension methods
338
+
339
+ HTTP_Version = "HTTP/" ( "1.1" %version_11
340
+ | "1.0" %version_10
341
+ | "0.9" %version_09
342
+ | (digit "." digit)
343
+ );
344
+
345
+ scheme = ( alpha | digit | "+" | "-" | "." )* ;
346
+ absolute_uri = (scheme ":" (uchar | reserved )*);
347
+ path = ( pchar+ ( "/" pchar* )* ) ;
348
+ query = ( uchar | reserved )* >mark_query_string %query_string ;
349
+ param = ( pchar | "/" )* ;
350
+ params = ( param ( ";" param )* ) ;
351
+ rel_path = ( path? (";" params)? ) ;
352
+ absolute_path = ( "/"+ rel_path ) >mark_request_path %request_path ("?" query)?;
353
+ Request_URI = ( "*" | absolute_uri | absolute_path ) >mark_request_uri %request_uri;
354
+ Fragment = ( uchar | reserved )* >mark_fragment %fragment;
355
+
356
+ field_name = ( token -- ":" )+;
357
+ Field_Name = field_name >mark_header_field %header_field;
358
+
359
+ field_value = ((any - " ") any*)?;
360
+ Field_Value = field_value >mark_header_value %header_value;
361
+
362
+ hsep = ":" " "*;
363
+ header = (field_name hsep field_value) :> CRLF;
364
+ Header = ( ("Content-Length"i hsep digit+ $content_length)
365
+ | ("Connection"i hsep
366
+ ( "Keep-Alive"i %set_keep_alive
367
+ | "close"i %set_not_keep_alive
368
+ )
369
+ )
370
+ | ("Transfer-Encoding" hsep "chunked"i %use_chunked_encoding)
371
+ | (Field_Name hsep Field_Value)
372
+ ) :> CRLF;
373
+
374
+ Headers = (Header)* :> CRLF @headers_complete;
375
+
376
+ Request_Line = ( Method " " Request_URI ("#" Fragment)? " " HTTP_Version CRLF ) ;
377
+
378
+ StatusCode = (digit digit digit) $status_code;
379
+ ReasonPhrase = ascii* -- ("\r" | "\n");
380
+ StatusLine = HTTP_Version " " StatusCode (" " ReasonPhrase)? CRLF;
381
+
382
+ # chunked message
383
+ trailing_headers = header*;
384
+ #chunk_ext_val = token | quoted_string;
385
+ chunk_ext_val = token*;
386
+ chunk_ext_name = token*;
387
+ chunk_extension = ( ";" " "* chunk_ext_name ("=" chunk_ext_val)? )*;
388
+ last_chunk = "0"+ ( chunk_extension | " "+) CRLF;
389
+ chunk_size = (xdigit* [1-9a-fA-F] xdigit* ) $add_to_chunk_size;
390
+ chunk_end = CRLF;
391
+ chunk_body = any >skip_chunk_data;
392
+ chunk_begin = chunk_size ( chunk_extension | " "+ ) CRLF;
393
+ chunk = chunk_begin chunk_body chunk_end;
394
+ ChunkedBody := chunk* last_chunk trailing_headers CRLF @end_chunked_body;
395
+
396
+ Request = (Request_Line Headers) >begin_message @body_logic;
397
+ Response = (StatusLine Headers) >begin_message @body_logic;
398
+
399
+ Requests := Request*;
400
+ Responses := Response*;
401
+
402
+ main := any >{
403
+ fhold;
404
+ if (parser->type == HTTP_REQUEST) {
405
+ fgoto Requests;
406
+ } else {
407
+ fgoto Responses;
408
+ }
409
+ };
410
+
411
+ }%%
412
+
413
+ %% write data;
414
+
415
+ void
416
+ http_parser_init (http_parser *parser, enum http_parser_type type)
417
+ {
418
+ int cs = 0;
419
+ %% write init;
420
+ parser->cs = cs;
421
+ parser->type = type;
422
+
423
+ parser->on_message_begin = NULL;
424
+ parser->on_path = NULL;
425
+ parser->on_query_string = NULL;
426
+ parser->on_uri = NULL;
427
+ parser->on_fragment = NULL;
428
+ parser->on_header_field = NULL;
429
+ parser->on_header_value = NULL;
430
+ parser->on_headers_complete = NULL;
431
+ parser->on_body = NULL;
432
+ parser->on_message_complete = NULL;
433
+
434
+ RESET_PARSER(parser);
435
+ }
436
+
437
+ /** exec **/
438
+ void
439
+ http_parser_execute (http_parser *parser, const char *buffer, size_t len)
440
+ {
441
+ size_t tmp; // REMOVE ME this is extremely hacky
442
+ int callback_return_value = 0;
443
+ const char *p, *pe, *eof;
444
+ int cs = parser->cs;
445
+
446
+ p = buffer;
447
+ pe = buffer+len;
448
+ eof = len ? NULL : pe;
449
+
450
+ if (parser->flags & EAT_FOREVER) {
451
+ if (len == 0) {
452
+ if (parser->on_message_complete) {
453
+ callback_return_value = parser->on_message_complete(parser);
454
+ if (callback_return_value != 0) parser->flags |= ERROR;
455
+ }
456
+ } else {
457
+ if (parser->on_body) {
458
+ callback_return_value = parser->on_body(parser, p, len);
459
+ if (callback_return_value != 0) parser->flags |= ERROR;
460
+ }
461
+ }
462
+ return;
463
+ }
464
+
465
+ if (0 < parser->chunk_size && (parser->flags & EATING)) {
466
+ /* eat body */
467
+ SKIP_BODY(MIN(len, parser->chunk_size));
468
+ if (callback_return_value != 0) {
469
+ parser->flags |= ERROR;
470
+ return;
471
+ }
472
+ }
473
+
474
+ if (parser->header_field_mark) parser->header_field_mark = buffer;
475
+ if (parser->header_value_mark) parser->header_value_mark = buffer;
476
+ if (parser->fragment_mark) parser->fragment_mark = buffer;
477
+ if (parser->query_string_mark) parser->query_string_mark = buffer;
478
+ if (parser->path_mark) parser->path_mark = buffer;
479
+ if (parser->uri_mark) parser->uri_mark = buffer;
480
+
481
+ %% write exec;
482
+
483
+ parser->cs = cs;
484
+
485
+ CALLBACK(header_field);
486
+ CALLBACK(header_value);
487
+ CALLBACK(fragment);
488
+ CALLBACK(query_string);
489
+ CALLBACK(path);
490
+ CALLBACK(uri);
491
+
492
+ assert(p <= pe && "buffer overflow after parsing execute");
493
+ }
494
+
495
+ int
496
+ http_parser_has_error (http_parser *parser)
497
+ {
498
+ if (parser->flags & ERROR) return 1;
499
+ return parser->cs == http_parser_error;
500
+ }