vulcan 0.3.0 → 0.4.0

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.
Files changed (211) hide show
  1. data/bin/vulcan +3 -1
  2. data/lib/vulcan/cli.rb +22 -3
  3. data/lib/vulcan/version.rb +1 -1
  4. data/server/bin/make +1 -3
  5. data/server/lib/spawner.js +9 -4
  6. data/server/node_modules/connect-form/node_modules/formidable/Readme.md +13 -2
  7. data/server/node_modules/connect-form/node_modules/formidable/lib/incoming_form.js +19 -7
  8. data/server/node_modules/connect-form/node_modules/formidable/lib/multipart_parser.js +12 -1
  9. data/server/node_modules/connect-form/node_modules/formidable/package.json +1 -1
  10. data/server/node_modules/connect-form/node_modules/formidable/test/fixture/file/plain.txt +1 -0
  11. data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/no-filename/generic.http +13 -0
  12. data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http +0 -10
  13. data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http +0 -9
  14. data/server/node_modules/connect-form/node_modules/formidable/test/fixture/js/no-filename.js +3 -0
  15. data/server/node_modules/connect-form/node_modules/formidable/test/legacy/simple/test-multipart-parser.js +1 -1
  16. data/server/node_modules/cradle/lib/cradle.js +0 -1
  17. data/server/node_modules/cradle/package.json +3 -3
  18. data/server/node_modules/cradle/test/cache-test.js +6 -7
  19. data/server/node_modules/cradle/test/cradle-test.js +4 -5
  20. data/server/node_modules/cradle/test/response-test.js +5 -6
  21. data/server/node_modules/express/History.md +53 -1
  22. data/server/node_modules/express/Makefile +3 -9
  23. data/server/node_modules/express/Readme.md +3 -1
  24. data/server/node_modules/express/bin/express +65 -66
  25. data/server/node_modules/express/lib/express.js +1 -1
  26. data/server/node_modules/express/lib/request.js +23 -9
  27. data/server/node_modules/express/lib/response.js +3 -2
  28. data/server/node_modules/express/lib/utils.js +13 -0
  29. data/server/node_modules/express/lib/view/view.js +2 -1
  30. data/server/node_modules/express/lib/view.js +19 -16
  31. data/server/node_modules/express/node_modules/connect/lib/connect.js +1 -1
  32. data/server/node_modules/express/node_modules/connect/lib/http.js +2 -0
  33. data/server/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js +135 -31
  34. data/server/node_modules/express/node_modules/connect/lib/middleware/limit.js +5 -1
  35. data/server/node_modules/express/node_modules/connect/lib/middleware/session.js +2 -2
  36. data/server/node_modules/express/node_modules/connect/lib/middleware/static.js +26 -21
  37. data/server/node_modules/express/node_modules/connect/lib/middleware/staticCache.js +91 -38
  38. data/server/node_modules/express/node_modules/connect/lib/middleware/vhost.js +1 -1
  39. data/server/node_modules/express/node_modules/connect/lib/utils.js +11 -4
  40. data/server/node_modules/express/node_modules/connect/node_modules/formidable/Makefile +14 -0
  41. data/server/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md +286 -0
  42. data/server/node_modules/express/node_modules/connect/node_modules/formidable/TODO +3 -0
  43. data/server/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js +70 -0
  44. data/server/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js +43 -0
  45. data/server/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js +48 -0
  46. data/server/node_modules/express/node_modules/connect/node_modules/formidable/index.js +1 -0
  47. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js +61 -0
  48. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js +377 -0
  49. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js +3 -0
  50. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js +312 -0
  51. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js +25 -0
  52. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js +6 -0
  53. data/server/node_modules/express/node_modules/connect/node_modules/formidable/package.json +22 -0
  54. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js +19 -0
  55. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt +1 -0
  56. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt +1 -0
  57. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/no-filename/generic.http +13 -0
  58. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md +3 -0
  59. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http +26 -0
  60. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-firefox-3.6.http +24 -0
  61. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-safari-5.http +23 -0
  62. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http +24 -0
  63. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-7.http +22 -0
  64. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-8.http +22 -0
  65. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-safari-5.http +22 -0
  66. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js +3 -0
  67. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js +21 -0
  68. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multi_video.upload +0 -0
  69. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js +72 -0
  70. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js +89 -0
  71. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js +24 -0
  72. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js +80 -0
  73. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js +104 -0
  74. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js +715 -0
  75. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js +50 -0
  76. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js +45 -0
  77. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js +72 -0
  78. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js +2 -0
  79. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js +63 -0
  80. data/server/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js +47 -0
  81. data/server/node_modules/express/node_modules/connect/package.json +7 -6
  82. data/server/node_modules/express/node_modules/connect/test.js +44 -31
  83. data/server/node_modules/express/node_modules/mime/mime.js +3 -3
  84. data/server/node_modules/express/node_modules/mime/package.json +21 -10
  85. data/server/node_modules/express/node_modules/mime/test.js +2 -3
  86. data/server/node_modules/express/node_modules/mime/{mime.types → types/mime.types} +0 -0
  87. data/server/node_modules/express/node_modules/mime/{node.types → types/node.types} +17 -0
  88. data/server/node_modules/express/node_modules/mkdirp/LICENSE +21 -0
  89. data/server/node_modules/express/node_modules/mkdirp/README.markdown +21 -0
  90. data/server/node_modules/express/node_modules/mkdirp/examples/pow.js +6 -0
  91. data/server/node_modules/express/node_modules/mkdirp/examples/pow.js.orig +6 -0
  92. data/server/node_modules/express/node_modules/mkdirp/examples/pow.js.rej +19 -0
  93. data/server/node_modules/express/node_modules/mkdirp/index.js +20 -0
  94. data/server/node_modules/express/node_modules/mkdirp/package.json +23 -0
  95. data/server/node_modules/express/node_modules/mkdirp/test/mkdirp.js +28 -0
  96. data/server/node_modules/express/node_modules/mkdirp/test/race.js +41 -0
  97. data/server/node_modules/express/node_modules/mkdirp/test/rel.js +32 -0
  98. data/server/node_modules/express/node_modules/qs/History.md +11 -0
  99. data/server/node_modules/express/node_modules/qs/Makefile +1 -3
  100. data/server/node_modules/express/node_modules/qs/Readme.md +2 -4
  101. data/server/node_modules/express/node_modules/qs/lib/querystring.js +100 -74
  102. data/server/node_modules/express/node_modules/qs/package.json +9 -2
  103. data/server/node_modules/express/node_modules/qs/test/mocha.opts +2 -0
  104. data/server/node_modules/express/node_modules/qs/test/{parse.test.js → parse.js} +1 -2
  105. data/server/node_modules/express/node_modules/qs/test/{stringify.test.js → stringify.js} +0 -0
  106. data/server/node_modules/express/package.json +9 -8
  107. data/server/node_modules/express/testing/foo/app.js +35 -0
  108. data/server/node_modules/express/testing/foo/package.json +9 -0
  109. data/server/node_modules/express/testing/foo/public/stylesheets/style.css +8 -0
  110. data/server/node_modules/express/testing/foo/routes/index.js +10 -0
  111. data/server/node_modules/express/testing/foo/views/index.jade +2 -0
  112. data/server/node_modules/express/testing/foo/views/layout.jade +6 -0
  113. data/server/node_modules/express/testing/index.js +43 -0
  114. data/server/node_modules/express/testing/public/test.txt +2971 -0
  115. data/server/node_modules/express/testing/views/page.html +1 -0
  116. data/server/node_modules/express/testing/views/page.jade +3 -0
  117. data/server/node_modules/express/testing/views/test.md +1 -0
  118. data/server/node_modules/express/testing/views/user/index.jade +1 -0
  119. data/server/node_modules/express/testing/views/user/list.jade +1 -0
  120. data/server/node_modules/node-uuid/README.md +166 -67
  121. data/server/node_modules/node-uuid/benchmark/README.md +53 -0
  122. data/server/node_modules/node-uuid/benchmark/bench.gnu +174 -0
  123. data/server/node_modules/node-uuid/benchmark/bench.sh +34 -0
  124. data/server/node_modules/node-uuid/{test → benchmark}/benchmark-native.c +0 -0
  125. data/server/node_modules/node-uuid/benchmark/benchmark.js +84 -0
  126. data/server/node_modules/node-uuid/package.json +5 -3
  127. data/server/node_modules/node-uuid/test/benchmark-native +0 -0
  128. data/server/node_modules/node-uuid/test/compare_v1.js +63 -0
  129. data/server/node_modules/node-uuid/test/test.html +3 -0
  130. data/server/node_modules/node-uuid/test/test.js +214 -57
  131. data/server/node_modules/node-uuid/uuid.js +225 -56
  132. data/server/node_modules/restler/README.md +20 -7
  133. data/server/node_modules/restler/bin/restler +1 -1
  134. data/server/node_modules/restler/lib/multipartform.js +9 -8
  135. data/server/node_modules/restler/lib/restler.js +64 -22
  136. data/server/node_modules/restler/package.json +2 -2
  137. data/server/node_modules/restler/test/restler.js +22 -2
  138. data/server/node_modules/restler/test/test_helper.js +20 -1
  139. data/server/package.json +1 -2
  140. data/server/web.js +30 -7
  141. metadata +90 -86
  142. data/server/node_modules/cradle/node_modules/vows/LICENSE +0 -20
  143. data/server/node_modules/cradle/node_modules/vows/Makefile +0 -7
  144. data/server/node_modules/cradle/node_modules/vows/README.md +0 -39
  145. data/server/node_modules/cradle/node_modules/vows/bin/vows +0 -515
  146. data/server/node_modules/cradle/node_modules/vows/lib/assert/error.js +0 -27
  147. data/server/node_modules/cradle/node_modules/vows/lib/assert/macros.js +0 -215
  148. data/server/node_modules/cradle/node_modules/vows/lib/assert/utils.js +0 -77
  149. data/server/node_modules/cradle/node_modules/vows/lib/vows/console.js +0 -131
  150. data/server/node_modules/cradle/node_modules/vows/lib/vows/context.js +0 -55
  151. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/file.js +0 -29
  152. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/fragments/coverage-foot.html +0 -2
  153. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/fragments/coverage-head.html +0 -61
  154. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-html.js +0 -54
  155. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-json.js +0 -54
  156. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-plain.js +0 -38
  157. data/server/node_modules/cradle/node_modules/vows/lib/vows/extras.js +0 -28
  158. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/dot-matrix.js +0 -67
  159. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/json.js +0 -16
  160. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/silent.js +0 -8
  161. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/spec.js +0 -44
  162. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/watch.js +0 -39
  163. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/xunit.js +0 -90
  164. data/server/node_modules/cradle/node_modules/vows/lib/vows/suite.js +0 -319
  165. data/server/node_modules/cradle/node_modules/vows/lib/vows.js +0 -193
  166. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/LICENSE +0 -20
  167. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/Makefile +0 -4
  168. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/README.md +0 -72
  169. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/lib/eyes.js +0 -233
  170. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/package.json +0 -14
  171. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/test/eyes-test.js +0 -55
  172. data/server/node_modules/cradle/node_modules/vows/package.json +0 -14
  173. data/server/node_modules/cradle/node_modules/vows/test/assert-test.js +0 -135
  174. data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/failing.js +0 -18
  175. data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/log.js +0 -18
  176. data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/passing.js +0 -17
  177. data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/stderr.js +0 -18
  178. data/server/node_modules/cradle/node_modules/vows/test/isolate-test.js +0 -140
  179. data/server/node_modules/cradle/node_modules/vows/test/testInherit.js +0 -133
  180. data/server/node_modules/cradle/node_modules/vows/test/vows-error-test.js +0 -51
  181. data/server/node_modules/cradle/node_modules/vows/test/vows-test.js +0 -374
  182. data/server/node_modules/express/node_modules/mime/index.js +0 -1
  183. data/server/node_modules/express/node_modules/qs/support/expresso/History.md +0 -128
  184. data/server/node_modules/express/node_modules/qs/support/expresso/Makefile +0 -53
  185. data/server/node_modules/express/node_modules/qs/support/expresso/Readme.md +0 -61
  186. data/server/node_modules/express/node_modules/qs/support/expresso/bin/expresso +0 -856
  187. data/server/node_modules/express/node_modules/qs/support/expresso/docs/api.html +0 -1080
  188. data/server/node_modules/express/node_modules/qs/support/expresso/docs/index.html +0 -377
  189. data/server/node_modules/express/node_modules/qs/support/expresso/docs/index.md +0 -290
  190. data/server/node_modules/express/node_modules/qs/support/expresso/docs/layout/foot.html +0 -3
  191. data/server/node_modules/express/node_modules/qs/support/expresso/docs/layout/head.html +0 -42
  192. data/server/node_modules/express/node_modules/qs/support/expresso/lib/bar.js +0 -4
  193. data/server/node_modules/express/node_modules/qs/support/expresso/lib/foo.js +0 -16
  194. data/server/node_modules/express/node_modules/qs/support/expresso/package.json +0 -12
  195. data/server/node_modules/express/node_modules/qs/support/expresso/test/assert.test.js +0 -91
  196. data/server/node_modules/express/node_modules/qs/support/expresso/test/async.test.js +0 -12
  197. data/server/node_modules/express/node_modules/qs/support/expresso/test/bar.test.js +0 -13
  198. data/server/node_modules/express/node_modules/qs/support/expresso/test/foo.test.js +0 -14
  199. data/server/node_modules/express/node_modules/qs/support/expresso/test/http.test.js +0 -146
  200. data/server/node_modules/express/node_modules/qs/support/expresso/test/serial/async.test.js +0 -39
  201. data/server/node_modules/express/node_modules/qs/support/expresso/test/serial/http.test.js +0 -48
  202. data/server/node_modules/express/node_modules/qs/support/should/History.md +0 -22
  203. data/server/node_modules/express/node_modules/qs/support/should/Makefile +0 -6
  204. data/server/node_modules/express/node_modules/qs/support/should/Readme.md +0 -248
  205. data/server/node_modules/express/node_modules/qs/support/should/examples/runner.js +0 -53
  206. data/server/node_modules/express/node_modules/qs/support/should/index.js +0 -2
  207. data/server/node_modules/express/node_modules/qs/support/should/lib/eql.js +0 -91
  208. data/server/node_modules/express/node_modules/qs/support/should/lib/should.js +0 -548
  209. data/server/node_modules/express/node_modules/qs/support/should/package.json +0 -8
  210. data/server/node_modules/express/node_modules/qs/support/should/test/should.test.js +0 -358
  211. data/server/node_modules/node-uuid/test/benchmark.js +0 -27
@@ -0,0 +1,377 @@
1
+ if (global.GENTLY) require = GENTLY.hijack(require);
2
+
3
+ var fs = require('fs');
4
+ var util = require('./util'),
5
+ path = require('path'),
6
+ File = require('./file'),
7
+ MultipartParser = require('./multipart_parser').MultipartParser,
8
+ QuerystringParser = require('./querystring_parser').QuerystringParser,
9
+ StringDecoder = require('string_decoder').StringDecoder,
10
+ EventEmitter = require('events').EventEmitter;
11
+
12
+ function IncomingForm() {
13
+ if (!(this instanceof IncomingForm)) return new IncomingForm;
14
+ EventEmitter.call(this);
15
+
16
+ this.error = null;
17
+ this.ended = false;
18
+
19
+ this.maxFieldsSize = 2 * 1024 * 1024;
20
+ this.keepExtensions = false;
21
+ this.uploadDir = IncomingForm.UPLOAD_DIR;
22
+ this.encoding = 'utf-8';
23
+ this.headers = null;
24
+ this.type = null;
25
+
26
+ this.bytesReceived = null;
27
+ this.bytesExpected = null;
28
+
29
+ this._parser = null;
30
+ this._flushing = 0;
31
+ this._fieldsSize = 0;
32
+ };
33
+ util.inherits(IncomingForm, EventEmitter);
34
+ exports.IncomingForm = IncomingForm;
35
+
36
+ IncomingForm.UPLOAD_DIR = (function() {
37
+ var dirs = [process.env.TMP, '/tmp', process.cwd()];
38
+ for (var i = 0; i < dirs.length; i++) {
39
+ var dir = dirs[i];
40
+ var isDirectory = false;
41
+
42
+ try {
43
+ isDirectory = fs.statSync(dir).isDirectory();
44
+ } catch (e) {}
45
+
46
+ if (isDirectory) return dir;
47
+ }
48
+ })();
49
+
50
+ IncomingForm.prototype.parse = function(req, cb) {
51
+ this.pause = function() {
52
+ try {
53
+ req.pause();
54
+ } catch (err) {
55
+ // the stream was destroyed
56
+ if (!this.ended) {
57
+ // before it was completed, crash & burn
58
+ this._error(err);
59
+ }
60
+ return false;
61
+ }
62
+ return true;
63
+ };
64
+
65
+ this.resume = function() {
66
+ try {
67
+ req.resume();
68
+ } catch (err) {
69
+ // the stream was destroyed
70
+ if (!this.ended) {
71
+ // before it was completed, crash & burn
72
+ this._error(err);
73
+ }
74
+ return false;
75
+ }
76
+
77
+ return true;
78
+ };
79
+
80
+ this.writeHeaders(req.headers);
81
+
82
+ var self = this;
83
+ req
84
+ .on('error', function(err) {
85
+ self._error(err);
86
+ })
87
+ .on('aborted', function() {
88
+ self.emit('aborted');
89
+ })
90
+ .on('data', function(buffer) {
91
+ self.write(buffer);
92
+ })
93
+ .on('end', function() {
94
+ if (self.error) {
95
+ return;
96
+ }
97
+
98
+ var err = self._parser.end();
99
+ if (err) {
100
+ self._error(err);
101
+ }
102
+ });
103
+
104
+ if (cb) {
105
+ var fields = {}, files = {};
106
+ this
107
+ .on('field', function(name, value) {
108
+ fields[name] = value;
109
+ })
110
+ .on('file', function(name, file) {
111
+ files[name] = file;
112
+ })
113
+ .on('error', function(err) {
114
+ cb(err, fields, files);
115
+ })
116
+ .on('end', function() {
117
+ cb(null, fields, files);
118
+ });
119
+ }
120
+
121
+ return this;
122
+ };
123
+
124
+ IncomingForm.prototype.writeHeaders = function(headers) {
125
+ this.headers = headers;
126
+ this._parseContentLength();
127
+ this._parseContentType();
128
+ };
129
+
130
+ IncomingForm.prototype.write = function(buffer) {
131
+ if (!this._parser) {
132
+ this._error(new Error('unintialized parser'));
133
+ return;
134
+ }
135
+
136
+ this.bytesReceived += buffer.length;
137
+ this.emit('progress', this.bytesReceived, this.bytesExpected);
138
+
139
+ var bytesParsed = this._parser.write(buffer);
140
+ if (bytesParsed !== buffer.length) {
141
+ this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed'));
142
+ }
143
+
144
+ return bytesParsed;
145
+ };
146
+
147
+ IncomingForm.prototype.pause = function() {
148
+ // this does nothing, unless overwritten in IncomingForm.parse
149
+ return false;
150
+ };
151
+
152
+ IncomingForm.prototype.resume = function() {
153
+ // this does nothing, unless overwritten in IncomingForm.parse
154
+ return false;
155
+ };
156
+
157
+ IncomingForm.prototype.onPart = function(part) {
158
+ // this method can be overwritten by the user
159
+ this.handlePart(part);
160
+ };
161
+
162
+ IncomingForm.prototype.handlePart = function(part) {
163
+ var self = this;
164
+
165
+ if (part.filename === undefined) {
166
+ var value = ''
167
+ , decoder = new StringDecoder(this.encoding);
168
+
169
+ part.on('data', function(buffer) {
170
+ self._fieldsSize += buffer.length;
171
+ if (self._fieldsSize > self.maxFieldsSize) {
172
+ self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data'));
173
+ return;
174
+ }
175
+ value += decoder.write(buffer);
176
+ });
177
+
178
+ part.on('end', function() {
179
+ self.emit('field', part.name, value);
180
+ });
181
+ return;
182
+ }
183
+
184
+ this._flushing++;
185
+
186
+ var file = new File({
187
+ path: this._uploadPath(part.filename),
188
+ name: part.filename,
189
+ type: part.mime,
190
+ });
191
+
192
+ this.emit('fileBegin', part.name, file);
193
+
194
+ file.open();
195
+
196
+ part.on('data', function(buffer) {
197
+ self.pause();
198
+ file.write(buffer, function() {
199
+ self.resume();
200
+ });
201
+ });
202
+
203
+ part.on('end', function() {
204
+ file.end(function() {
205
+ self._flushing--;
206
+ self.emit('file', part.name, file);
207
+ self._maybeEnd();
208
+ });
209
+ });
210
+ };
211
+
212
+ IncomingForm.prototype._parseContentType = function() {
213
+ if (!this.headers['content-type']) {
214
+ this._error(new Error('bad content-type header, no content-type'));
215
+ return;
216
+ }
217
+
218
+ if (this.headers['content-type'].match(/urlencoded/i)) {
219
+ this._initUrlencoded();
220
+ return;
221
+ }
222
+
223
+ if (this.headers['content-type'].match(/multipart/i)) {
224
+ var m;
225
+ if (m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i)) {
226
+ this._initMultipart(m[1] || m[2]);
227
+ } else {
228
+ this._error(new Error('bad content-type header, no multipart boundary'));
229
+ }
230
+ return;
231
+ }
232
+
233
+ this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type']));
234
+ };
235
+
236
+ IncomingForm.prototype._error = function(err) {
237
+ if (this.error) {
238
+ return;
239
+ }
240
+
241
+ this.error = err;
242
+ this.pause();
243
+ this.emit('error', err);
244
+ };
245
+
246
+ IncomingForm.prototype._parseContentLength = function() {
247
+ if (this.headers['content-length']) {
248
+ this.bytesReceived = 0;
249
+ this.bytesExpected = parseInt(this.headers['content-length'], 10);
250
+ }
251
+ };
252
+
253
+ IncomingForm.prototype._newParser = function() {
254
+ return new MultipartParser();
255
+ };
256
+
257
+ IncomingForm.prototype._initMultipart = function(boundary) {
258
+ this.type = 'multipart';
259
+
260
+ var parser = new MultipartParser(),
261
+ self = this,
262
+ headerField,
263
+ headerValue,
264
+ part;
265
+
266
+ parser.initWithBoundary(boundary);
267
+
268
+ parser.onPartBegin = function() {
269
+ part = new EventEmitter();
270
+ part.headers = {};
271
+ part.name = null;
272
+ part.filename = null;
273
+ part.mime = null;
274
+ headerField = '';
275
+ headerValue = '';
276
+ };
277
+
278
+ parser.onHeaderField = function(b, start, end) {
279
+ headerField += b.toString(self.encoding, start, end);
280
+ };
281
+
282
+ parser.onHeaderValue = function(b, start, end) {
283
+ headerValue += b.toString(self.encoding, start, end);
284
+ };
285
+
286
+ parser.onHeaderEnd = function() {
287
+ headerField = headerField.toLowerCase();
288
+ part.headers[headerField] = headerValue;
289
+
290
+ var m;
291
+ if (headerField == 'content-disposition') {
292
+ if (m = headerValue.match(/name="([^"]+)"/i)) {
293
+ part.name = m[1];
294
+ }
295
+
296
+ part.filename = self._fileName(headerValue);
297
+ } else if (headerField == 'content-type') {
298
+ part.mime = headerValue;
299
+ }
300
+
301
+ headerField = '';
302
+ headerValue = '';
303
+ };
304
+
305
+ parser.onHeadersEnd = function() {
306
+ self.onPart(part);
307
+ };
308
+
309
+ parser.onPartData = function(b, start, end) {
310
+ part.emit('data', b.slice(start, end));
311
+ };
312
+
313
+ parser.onPartEnd = function() {
314
+ part.emit('end');
315
+ };
316
+
317
+ parser.onEnd = function() {
318
+ self.ended = true;
319
+ self._maybeEnd();
320
+ };
321
+
322
+ this._parser = parser;
323
+ };
324
+
325
+ IncomingForm.prototype._fileName = function(headerValue) {
326
+ var m = headerValue.match(/filename="(.*?)"($|; )/i)
327
+ if (!m) return;
328
+
329
+ var filename = m[1].substr(m[1].lastIndexOf('\\') + 1);
330
+ filename = filename.replace(/%22/g, '"');
331
+ filename = filename.replace(/&#([\d]{4});/g, function(m, code) {
332
+ return String.fromCharCode(code);
333
+ });
334
+ return filename;
335
+ };
336
+
337
+ IncomingForm.prototype._initUrlencoded = function() {
338
+ this.type = 'urlencoded';
339
+
340
+ var parser = new QuerystringParser()
341
+ , self = this;
342
+
343
+ parser.onField = function(key, val) {
344
+ self.emit('field', key, val);
345
+ };
346
+
347
+ parser.onEnd = function() {
348
+ self.ended = true;
349
+ self._maybeEnd();
350
+ };
351
+
352
+ this._parser = parser;
353
+ };
354
+
355
+ IncomingForm.prototype._uploadPath = function(filename) {
356
+ var name = '';
357
+ for (var i = 0; i < 32; i++) {
358
+ name += Math.floor(Math.random() * 16).toString(16);
359
+ }
360
+
361
+ if (this.keepExtensions) {
362
+ var ext = path.extname(filename);
363
+ ext = ext.replace(/(\.[a-z0-9]+).*/, '$1')
364
+
365
+ name += ext;
366
+ }
367
+
368
+ return path.join(this.uploadDir, name);
369
+ };
370
+
371
+ IncomingForm.prototype._maybeEnd = function() {
372
+ if (!this.ended || this._flushing) {
373
+ return;
374
+ }
375
+
376
+ this.emit('end');
377
+ };
@@ -0,0 +1,3 @@
1
+ var IncomingForm = require('./incoming_form').IncomingForm;
2
+ IncomingForm.IncomingForm = IncomingForm;
3
+ module.exports = IncomingForm;
@@ -0,0 +1,312 @@
1
+ var Buffer = require('buffer').Buffer,
2
+ s = 0,
3
+ S =
4
+ { PARSER_UNINITIALIZED: s++,
5
+ START: s++,
6
+ START_BOUNDARY: s++,
7
+ HEADER_FIELD_START: s++,
8
+ HEADER_FIELD: s++,
9
+ HEADER_VALUE_START: s++,
10
+ HEADER_VALUE: s++,
11
+ HEADER_VALUE_ALMOST_DONE: s++,
12
+ HEADERS_ALMOST_DONE: s++,
13
+ PART_DATA_START: s++,
14
+ PART_DATA: s++,
15
+ PART_END: s++,
16
+ END: s++,
17
+ },
18
+
19
+ f = 1,
20
+ F =
21
+ { PART_BOUNDARY: f,
22
+ LAST_BOUNDARY: f *= 2,
23
+ },
24
+
25
+ LF = 10,
26
+ CR = 13,
27
+ SPACE = 32,
28
+ HYPHEN = 45,
29
+ COLON = 58,
30
+ A = 97,
31
+ Z = 122,
32
+
33
+ lower = function(c) {
34
+ return c | 0x20;
35
+ };
36
+
37
+ for (var s in S) {
38
+ exports[s] = S[s];
39
+ }
40
+
41
+ function MultipartParser() {
42
+ this.boundary = null;
43
+ this.boundaryChars = null;
44
+ this.lookbehind = null;
45
+ this.state = S.PARSER_UNINITIALIZED;
46
+
47
+ this.index = null;
48
+ this.flags = 0;
49
+ };
50
+ exports.MultipartParser = MultipartParser;
51
+
52
+ MultipartParser.stateToString = function(stateNumber) {
53
+ for (var state in S) {
54
+ var number = S[state];
55
+ if (number === stateNumber) return state;
56
+ }
57
+ };
58
+
59
+ MultipartParser.prototype.initWithBoundary = function(str) {
60
+ this.boundary = new Buffer(str.length+4);
61
+ this.boundary.write('\r\n--', 'ascii', 0);
62
+ this.boundary.write(str, 'ascii', 4);
63
+ this.lookbehind = new Buffer(this.boundary.length+8);
64
+ this.state = S.START;
65
+
66
+ this.boundaryChars = {};
67
+ for (var i = 0; i < this.boundary.length; i++) {
68
+ this.boundaryChars[this.boundary[i]] = true;
69
+ }
70
+ };
71
+
72
+ MultipartParser.prototype.write = function(buffer) {
73
+ var self = this,
74
+ i = 0,
75
+ len = buffer.length,
76
+ prevIndex = this.index,
77
+ index = this.index,
78
+ state = this.state,
79
+ flags = this.flags,
80
+ lookbehind = this.lookbehind,
81
+ boundary = this.boundary,
82
+ boundaryChars = this.boundaryChars,
83
+ boundaryLength = this.boundary.length,
84
+ boundaryEnd = boundaryLength - 1,
85
+ bufferLength = buffer.length,
86
+ c,
87
+ cl,
88
+
89
+ mark = function(name) {
90
+ self[name+'Mark'] = i;
91
+ },
92
+ clear = function(name) {
93
+ delete self[name+'Mark'];
94
+ },
95
+ callback = function(name, buffer, start, end) {
96
+ if (start !== undefined && start === end) {
97
+ return;
98
+ }
99
+
100
+ var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
101
+ if (callbackSymbol in self) {
102
+ self[callbackSymbol](buffer, start, end);
103
+ }
104
+ },
105
+ dataCallback = function(name, clear) {
106
+ var markSymbol = name+'Mark';
107
+ if (!(markSymbol in self)) {
108
+ return;
109
+ }
110
+
111
+ if (!clear) {
112
+ callback(name, buffer, self[markSymbol], buffer.length);
113
+ self[markSymbol] = 0;
114
+ } else {
115
+ callback(name, buffer, self[markSymbol], i);
116
+ delete self[markSymbol];
117
+ }
118
+ };
119
+
120
+ for (i = 0; i < len; i++) {
121
+ c = buffer[i];
122
+ switch (state) {
123
+ case S.PARSER_UNINITIALIZED:
124
+ return i;
125
+ case S.START:
126
+ index = 0;
127
+ state = S.START_BOUNDARY;
128
+ case S.START_BOUNDARY:
129
+ if (index == boundary.length - 2) {
130
+ if (c != CR) {
131
+ return i;
132
+ }
133
+ index++;
134
+ break;
135
+ } else if (index - 1 == boundary.length - 2) {
136
+ if (c != LF) {
137
+ return i;
138
+ }
139
+ index = 0;
140
+ callback('partBegin');
141
+ state = S.HEADER_FIELD_START;
142
+ break;
143
+ }
144
+
145
+ if (c != boundary[index+2]) {
146
+ return i;
147
+ }
148
+ index++;
149
+ break;
150
+ case S.HEADER_FIELD_START:
151
+ state = S.HEADER_FIELD;
152
+ mark('headerField');
153
+ index = 0;
154
+ case S.HEADER_FIELD:
155
+ if (c == CR) {
156
+ clear('headerField');
157
+ state = S.HEADERS_ALMOST_DONE;
158
+ break;
159
+ }
160
+
161
+ index++;
162
+ if (c == HYPHEN) {
163
+ break;
164
+ }
165
+
166
+ if (c == COLON) {
167
+ if (index == 1) {
168
+ // empty header field
169
+ return i;
170
+ }
171
+ dataCallback('headerField', true);
172
+ state = S.HEADER_VALUE_START;
173
+ break;
174
+ }
175
+
176
+ cl = lower(c);
177
+ if (cl < A || cl > Z) {
178
+ return i;
179
+ }
180
+ break;
181
+ case S.HEADER_VALUE_START:
182
+ if (c == SPACE) {
183
+ break;
184
+ }
185
+
186
+ mark('headerValue');
187
+ state = S.HEADER_VALUE;
188
+ case S.HEADER_VALUE:
189
+ if (c == CR) {
190
+ dataCallback('headerValue', true);
191
+ callback('headerEnd');
192
+ state = S.HEADER_VALUE_ALMOST_DONE;
193
+ }
194
+ break;
195
+ case S.HEADER_VALUE_ALMOST_DONE:
196
+ if (c != LF) {
197
+ return i;
198
+ }
199
+ state = S.HEADER_FIELD_START;
200
+ break;
201
+ case S.HEADERS_ALMOST_DONE:
202
+ if (c != LF) {
203
+ return i;
204
+ }
205
+
206
+ callback('headersEnd');
207
+ state = S.PART_DATA_START;
208
+ break;
209
+ case S.PART_DATA_START:
210
+ state = S.PART_DATA
211
+ mark('partData');
212
+ case S.PART_DATA:
213
+ prevIndex = index;
214
+
215
+ if (index == 0) {
216
+ // boyer-moore derrived algorithm to safely skip non-boundary data
217
+ i += boundaryEnd;
218
+ while (i < bufferLength && !(buffer[i] in boundaryChars)) {
219
+ i += boundaryLength;
220
+ }
221
+ i -= boundaryEnd;
222
+ c = buffer[i];
223
+ }
224
+
225
+ if (index < boundary.length) {
226
+ if (boundary[index] == c) {
227
+ if (index == 0) {
228
+ dataCallback('partData', true);
229
+ }
230
+ index++;
231
+ } else {
232
+ index = 0;
233
+ }
234
+ } else if (index == boundary.length) {
235
+ index++;
236
+ if (c == CR) {
237
+ // CR = part boundary
238
+ flags |= F.PART_BOUNDARY;
239
+ } else if (c == HYPHEN) {
240
+ // HYPHEN = end boundary
241
+ flags |= F.LAST_BOUNDARY;
242
+ } else {
243
+ index = 0;
244
+ }
245
+ } else if (index - 1 == boundary.length) {
246
+ if (flags & F.PART_BOUNDARY) {
247
+ index = 0;
248
+ if (c == LF) {
249
+ // unset the PART_BOUNDARY flag
250
+ flags &= ~F.PART_BOUNDARY;
251
+ callback('partEnd');
252
+ callback('partBegin');
253
+ state = S.HEADER_FIELD_START;
254
+ break;
255
+ }
256
+ } else if (flags & F.LAST_BOUNDARY) {
257
+ if (c == HYPHEN) {
258
+ callback('partEnd');
259
+ callback('end');
260
+ state = S.END;
261
+ } else {
262
+ index = 0;
263
+ }
264
+ } else {
265
+ index = 0;
266
+ }
267
+ }
268
+
269
+ if (index > 0) {
270
+ // when matching a possible boundary, keep a lookbehind reference
271
+ // in case it turns out to be a false lead
272
+ lookbehind[index-1] = c;
273
+ } else if (prevIndex > 0) {
274
+ // if our boundary turned out to be rubbish, the captured lookbehind
275
+ // belongs to partData
276
+ callback('partData', lookbehind, 0, prevIndex);
277
+ prevIndex = 0;
278
+ mark('partData');
279
+
280
+ // reconsider the current character even so it interrupted the sequence
281
+ // it could be the beginning of a new sequence
282
+ i--;
283
+ }
284
+
285
+ break;
286
+ case S.END:
287
+ break;
288
+ default:
289
+ return i;
290
+ }
291
+ }
292
+
293
+ dataCallback('headerField');
294
+ dataCallback('headerValue');
295
+ dataCallback('partData');
296
+
297
+ this.index = index;
298
+ this.state = state;
299
+ this.flags = flags;
300
+
301
+ return len;
302
+ };
303
+
304
+ MultipartParser.prototype.end = function() {
305
+ if (this.state != S.END) {
306
+ return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain());
307
+ }
308
+ };
309
+
310
+ MultipartParser.prototype.explain = function() {
311
+ return 'state = ' + MultipartParser.stateToString(this.state);
312
+ };
@@ -0,0 +1,25 @@
1
+ if (global.GENTLY) require = GENTLY.hijack(require);
2
+
3
+ // This is a buffering parser, not quite as nice as the multipart one.
4
+ // If I find time I'll rewrite this to be fully streaming as well
5
+ var querystring = require('querystring');
6
+
7
+ function QuerystringParser() {
8
+ this.buffer = '';
9
+ };
10
+ exports.QuerystringParser = QuerystringParser;
11
+
12
+ QuerystringParser.prototype.write = function(buffer) {
13
+ this.buffer += buffer.toString('ascii');
14
+ return buffer.length;
15
+ };
16
+
17
+ QuerystringParser.prototype.end = function() {
18
+ var fields = querystring.parse(this.buffer);
19
+ for (var field in fields) {
20
+ this.onField(field, fields[field]);
21
+ }
22
+ this.buffer = '';
23
+
24
+ this.onEnd();
25
+ };
@@ -0,0 +1,6 @@
1
+ // Backwards compatibility ...
2
+ try {
3
+ module.exports = require('util');
4
+ } catch (e) {
5
+ module.exports = require('sys');
6
+ }