vulcan 0.1.6 → 0.2.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 (181) hide show
  1. data/lib/vulcan/cli.rb +3 -0
  2. data/lib/vulcan/version.rb +1 -1
  3. data/server/lib/spawner.js +9 -4
  4. data/server/node_modules/cradle/lib/cradle.js +0 -1
  5. data/server/node_modules/cradle/package.json +3 -3
  6. data/server/node_modules/cradle/test/cache-test.js +6 -7
  7. data/server/node_modules/cradle/test/cradle-test.js +4 -5
  8. data/server/node_modules/cradle/test/response-test.js +5 -6
  9. data/server/node_modules/express/History.md +40 -0
  10. data/server/node_modules/express/Makefile +3 -9
  11. data/server/node_modules/express/Readme.md +3 -1
  12. data/server/node_modules/express/bin/express +61 -63
  13. data/server/node_modules/express/lib/express.js +1 -1
  14. data/server/node_modules/express/lib/request.js +9 -7
  15. data/server/node_modules/express/lib/view.js +19 -16
  16. data/server/node_modules/express/node_modules/connect/lib/connect.js +1 -1
  17. data/server/node_modules/express/node_modules/connect/lib/http.js +2 -0
  18. data/server/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js +135 -31
  19. data/server/node_modules/express/node_modules/connect/lib/middleware/limit.js +5 -1
  20. data/server/node_modules/express/node_modules/connect/lib/middleware/session.js +2 -2
  21. data/server/node_modules/express/node_modules/connect/lib/middleware/static.js +26 -21
  22. data/server/node_modules/express/node_modules/connect/lib/middleware/staticCache.js +91 -38
  23. data/server/node_modules/express/node_modules/connect/lib/middleware/vhost.js +1 -1
  24. data/server/node_modules/express/node_modules/connect/lib/utils.js +11 -4
  25. data/server/node_modules/express/node_modules/connect/node_modules/formidable/Makefile +14 -0
  26. data/server/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md +286 -0
  27. data/server/node_modules/express/node_modules/connect/node_modules/formidable/TODO +3 -0
  28. data/server/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js +70 -0
  29. data/server/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js +43 -0
  30. data/server/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js +48 -0
  31. data/server/node_modules/express/node_modules/connect/node_modules/formidable/index.js +1 -0
  32. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js +61 -0
  33. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js +377 -0
  34. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js +3 -0
  35. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js +312 -0
  36. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js +25 -0
  37. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js +6 -0
  38. data/server/node_modules/express/node_modules/connect/node_modules/formidable/package.json +22 -0
  39. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js +19 -0
  40. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt +1 -0
  41. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt +1 -0
  42. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/no-filename/generic.http +13 -0
  43. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md +3 -0
  44. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http +26 -0
  45. 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
  46. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-safari-5.http +23 -0
  47. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http +24 -0
  48. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-7.http +22 -0
  49. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-8.http +22 -0
  50. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-safari-5.http +22 -0
  51. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js +3 -0
  52. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js +21 -0
  53. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multi_video.upload +0 -0
  54. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js +72 -0
  55. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js +89 -0
  56. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js +24 -0
  57. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js +80 -0
  58. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js +104 -0
  59. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js +715 -0
  60. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js +50 -0
  61. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js +45 -0
  62. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js +72 -0
  63. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js +2 -0
  64. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js +63 -0
  65. data/server/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js +47 -0
  66. data/server/node_modules/express/node_modules/connect/package.json +7 -6
  67. data/server/node_modules/express/node_modules/connect/test.js +44 -31
  68. data/server/node_modules/express/node_modules/qs/History.md +11 -0
  69. data/server/node_modules/express/node_modules/qs/Makefile +1 -3
  70. data/server/node_modules/express/node_modules/qs/Readme.md +2 -4
  71. data/server/node_modules/express/node_modules/qs/lib/querystring.js +100 -74
  72. data/server/node_modules/express/node_modules/qs/package.json +9 -2
  73. data/server/node_modules/express/node_modules/qs/test/mocha.opts +2 -0
  74. data/server/node_modules/express/node_modules/qs/test/{parse.test.js → parse.js} +1 -2
  75. data/server/node_modules/express/node_modules/qs/test/{stringify.test.js → stringify.js} +0 -0
  76. data/server/node_modules/express/package.json +7 -7
  77. data/server/node_modules/express/testing/foo/app.js +35 -0
  78. data/server/node_modules/express/testing/foo/package.json +9 -0
  79. data/server/node_modules/express/testing/foo/public/stylesheets/style.css +8 -0
  80. data/server/node_modules/express/testing/foo/routes/index.js +10 -0
  81. data/server/node_modules/express/testing/foo/views/index.jade +2 -0
  82. data/server/node_modules/express/testing/foo/views/layout.jade +6 -0
  83. data/server/node_modules/express/testing/index.js +31 -5
  84. data/server/node_modules/express/testing/public/test.txt +2971 -0
  85. data/server/node_modules/express/testing/views/page.html +1 -0
  86. data/server/node_modules/express/testing/views/page.jade +3 -0
  87. data/server/node_modules/express/testing/views/test.md +1 -0
  88. data/server/node_modules/express/testing/views/user/index.jade +1 -0
  89. data/server/node_modules/express/testing/views/user/list.jade +1 -0
  90. data/server/node_modules/node-uuid/README.md +166 -67
  91. data/server/node_modules/node-uuid/benchmark/README.md +53 -0
  92. data/server/node_modules/node-uuid/benchmark/bench.gnu +174 -0
  93. data/server/node_modules/node-uuid/benchmark/bench.sh +34 -0
  94. data/server/node_modules/node-uuid/{test → benchmark}/benchmark-native.c +0 -0
  95. data/server/node_modules/node-uuid/benchmark/benchmark.js +84 -0
  96. data/server/node_modules/node-uuid/package.json +5 -3
  97. data/server/node_modules/node-uuid/test/benchmark-native +0 -0
  98. data/server/node_modules/node-uuid/test/compare_v1.js +63 -0
  99. data/server/node_modules/node-uuid/test/test.html +3 -0
  100. data/server/node_modules/node-uuid/test/test.js +214 -57
  101. data/server/node_modules/node-uuid/uuid.js +225 -56
  102. data/server/node_modules/restler/README.md +20 -7
  103. data/server/node_modules/restler/bin/restler +1 -1
  104. data/server/node_modules/restler/lib/multipartform.js +9 -8
  105. data/server/node_modules/restler/lib/restler.js +64 -22
  106. data/server/node_modules/restler/package.json +2 -2
  107. data/server/node_modules/restler/test/restler.js +22 -2
  108. data/server/node_modules/restler/test/test_helper.js +20 -1
  109. data/server/package.json +8 -8
  110. data/server/web.js +22 -6
  111. metadata +72 -82
  112. data/server/node_modules/cradle/node_modules/vows/LICENSE +0 -20
  113. data/server/node_modules/cradle/node_modules/vows/Makefile +0 -7
  114. data/server/node_modules/cradle/node_modules/vows/README.md +0 -39
  115. data/server/node_modules/cradle/node_modules/vows/bin/vows +0 -515
  116. data/server/node_modules/cradle/node_modules/vows/lib/assert/error.js +0 -27
  117. data/server/node_modules/cradle/node_modules/vows/lib/assert/macros.js +0 -215
  118. data/server/node_modules/cradle/node_modules/vows/lib/assert/utils.js +0 -77
  119. data/server/node_modules/cradle/node_modules/vows/lib/vows.js +0 -193
  120. data/server/node_modules/cradle/node_modules/vows/lib/vows/console.js +0 -131
  121. data/server/node_modules/cradle/node_modules/vows/lib/vows/context.js +0 -55
  122. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/file.js +0 -29
  123. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/fragments/coverage-foot.html +0 -2
  124. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/fragments/coverage-head.html +0 -61
  125. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-html.js +0 -54
  126. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-json.js +0 -54
  127. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-plain.js +0 -38
  128. data/server/node_modules/cradle/node_modules/vows/lib/vows/extras.js +0 -28
  129. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/dot-matrix.js +0 -67
  130. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/json.js +0 -16
  131. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/silent.js +0 -8
  132. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/spec.js +0 -44
  133. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/watch.js +0 -39
  134. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/xunit.js +0 -90
  135. data/server/node_modules/cradle/node_modules/vows/lib/vows/suite.js +0 -319
  136. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/LICENSE +0 -20
  137. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/Makefile +0 -4
  138. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/README.md +0 -72
  139. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/lib/eyes.js +0 -233
  140. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/package.json +0 -14
  141. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/test/eyes-test.js +0 -55
  142. data/server/node_modules/cradle/node_modules/vows/package.json +0 -14
  143. data/server/node_modules/cradle/node_modules/vows/test/assert-test.js +0 -135
  144. data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/failing.js +0 -18
  145. data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/log.js +0 -18
  146. data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/passing.js +0 -17
  147. data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/stderr.js +0 -18
  148. data/server/node_modules/cradle/node_modules/vows/test/isolate-test.js +0 -140
  149. data/server/node_modules/cradle/node_modules/vows/test/testInherit.js +0 -133
  150. data/server/node_modules/cradle/node_modules/vows/test/vows-error-test.js +0 -51
  151. data/server/node_modules/cradle/node_modules/vows/test/vows-test.js +0 -374
  152. data/server/node_modules/express/node_modules/qs/support/expresso/History.md +0 -128
  153. data/server/node_modules/express/node_modules/qs/support/expresso/Makefile +0 -53
  154. data/server/node_modules/express/node_modules/qs/support/expresso/Readme.md +0 -61
  155. data/server/node_modules/express/node_modules/qs/support/expresso/bin/expresso +0 -856
  156. data/server/node_modules/express/node_modules/qs/support/expresso/docs/api.html +0 -1080
  157. data/server/node_modules/express/node_modules/qs/support/expresso/docs/index.html +0 -377
  158. data/server/node_modules/express/node_modules/qs/support/expresso/docs/index.md +0 -290
  159. data/server/node_modules/express/node_modules/qs/support/expresso/docs/layout/foot.html +0 -3
  160. data/server/node_modules/express/node_modules/qs/support/expresso/docs/layout/head.html +0 -42
  161. data/server/node_modules/express/node_modules/qs/support/expresso/lib/bar.js +0 -4
  162. data/server/node_modules/express/node_modules/qs/support/expresso/lib/foo.js +0 -16
  163. data/server/node_modules/express/node_modules/qs/support/expresso/package.json +0 -12
  164. data/server/node_modules/express/node_modules/qs/support/expresso/test/assert.test.js +0 -91
  165. data/server/node_modules/express/node_modules/qs/support/expresso/test/async.test.js +0 -12
  166. data/server/node_modules/express/node_modules/qs/support/expresso/test/bar.test.js +0 -13
  167. data/server/node_modules/express/node_modules/qs/support/expresso/test/foo.test.js +0 -14
  168. data/server/node_modules/express/node_modules/qs/support/expresso/test/http.test.js +0 -146
  169. data/server/node_modules/express/node_modules/qs/support/expresso/test/serial/async.test.js +0 -39
  170. data/server/node_modules/express/node_modules/qs/support/expresso/test/serial/http.test.js +0 -48
  171. data/server/node_modules/express/node_modules/qs/support/should/History.md +0 -22
  172. data/server/node_modules/express/node_modules/qs/support/should/Makefile +0 -6
  173. data/server/node_modules/express/node_modules/qs/support/should/Readme.md +0 -248
  174. data/server/node_modules/express/node_modules/qs/support/should/examples/runner.js +0 -53
  175. data/server/node_modules/express/node_modules/qs/support/should/index.js +0 -2
  176. data/server/node_modules/express/node_modules/qs/support/should/lib/eql.js +0 -91
  177. data/server/node_modules/express/node_modules/qs/support/should/lib/should.js +0 -548
  178. data/server/node_modules/express/node_modules/qs/support/should/package.json +0 -8
  179. data/server/node_modules/express/node_modules/qs/support/should/test/should.test.js +0 -358
  180. data/server/node_modules/express/testing/views/users.jade +0 -1
  181. data/server/node_modules/node-uuid/test/benchmark.js +0 -27
@@ -0,0 +1,3 @@
1
+ - Better bufferMaxSize handling approach
2
+ - Add tests for JSON parser pull request and merge it
3
+ - Implement QuerystringParser the same way as MultipartParser
@@ -0,0 +1,70 @@
1
+ require('../test/common');
2
+ var multipartParser = require('../lib/multipart_parser'),
3
+ MultipartParser = multipartParser.MultipartParser,
4
+ parser = new MultipartParser(),
5
+ Buffer = require('buffer').Buffer,
6
+ boundary = '-----------------------------168072824752491622650073',
7
+ mb = 100,
8
+ buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
9
+ callbacks =
10
+ { partBegin: -1,
11
+ partEnd: -1,
12
+ headerField: -1,
13
+ headerValue: -1,
14
+ partData: -1,
15
+ end: -1,
16
+ };
17
+
18
+
19
+ parser.initWithBoundary(boundary);
20
+ parser.onHeaderField = function() {
21
+ callbacks.headerField++;
22
+ };
23
+
24
+ parser.onHeaderValue = function() {
25
+ callbacks.headerValue++;
26
+ };
27
+
28
+ parser.onPartBegin = function() {
29
+ callbacks.partBegin++;
30
+ };
31
+
32
+ parser.onPartData = function() {
33
+ callbacks.partData++;
34
+ };
35
+
36
+ parser.onPartEnd = function() {
37
+ callbacks.partEnd++;
38
+ };
39
+
40
+ parser.onEnd = function() {
41
+ callbacks.end++;
42
+ };
43
+
44
+ var start = +new Date(),
45
+ nparsed = parser.write(buffer),
46
+ duration = +new Date - start,
47
+ mbPerSec = (mb / (duration / 1000)).toFixed(2);
48
+
49
+ console.log(mbPerSec+' mb/sec');
50
+
51
+ assert.equal(nparsed, buffer.length);
52
+
53
+ function createMultipartBuffer(boundary, size) {
54
+ var head =
55
+ '--'+boundary+'\r\n'
56
+ + 'content-disposition: form-data; name="field1"\r\n'
57
+ + '\r\n'
58
+ , tail = '\r\n--'+boundary+'--\r\n'
59
+ , buffer = new Buffer(size);
60
+
61
+ buffer.write(head, 'ascii', 0);
62
+ buffer.write(tail, 'ascii', buffer.length - tail.length);
63
+ return buffer;
64
+ }
65
+
66
+ process.on('exit', function() {
67
+ for (var k in callbacks) {
68
+ assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
69
+ }
70
+ });
@@ -0,0 +1,43 @@
1
+ require('../test/common');
2
+ var http = require('http'),
3
+ util = require('util'),
4
+ formidable = require('formidable'),
5
+ server;
6
+
7
+ server = http.createServer(function(req, res) {
8
+ if (req.url == '/') {
9
+ res.writeHead(200, {'content-type': 'text/html'});
10
+ res.end(
11
+ '<form action="/post" method="post">'+
12
+ '<input type="text" name="title"><br>'+
13
+ '<input type="text" name="data[foo][]"><br>'+
14
+ '<input type="submit" value="Submit">'+
15
+ '</form>'
16
+ );
17
+ } else if (req.url == '/post') {
18
+ var form = new formidable.IncomingForm(),
19
+ fields = [];
20
+
21
+ form
22
+ .on('error', function(err) {
23
+ res.writeHead(200, {'content-type': 'text/plain'});
24
+ res.end('error:\n\n'+util.inspect(err));
25
+ })
26
+ .on('field', function(field, value) {
27
+ console.log(field, value);
28
+ fields.push([field, value]);
29
+ })
30
+ .on('end', function() {
31
+ console.log('-> post done');
32
+ res.writeHead(200, {'content-type': 'text/plain'});
33
+ res.end('received fields:\n\n '+util.inspect(fields));
34
+ });
35
+ form.parse(req);
36
+ } else {
37
+ res.writeHead(404, {'content-type': 'text/plain'});
38
+ res.end('404');
39
+ }
40
+ });
41
+ server.listen(TEST_PORT);
42
+
43
+ console.log('listening on http://localhost:'+TEST_PORT+'/');
@@ -0,0 +1,48 @@
1
+ require('../test/common');
2
+ var http = require('http'),
3
+ util = require('util'),
4
+ formidable = require('formidable'),
5
+ server;
6
+
7
+ server = http.createServer(function(req, res) {
8
+ if (req.url == '/') {
9
+ res.writeHead(200, {'content-type': 'text/html'});
10
+ res.end(
11
+ '<form action="/upload" enctype="multipart/form-data" method="post">'+
12
+ '<input type="text" name="title"><br>'+
13
+ '<input type="file" name="upload" multiple="multiple"><br>'+
14
+ '<input type="submit" value="Upload">'+
15
+ '</form>'
16
+ );
17
+ } else if (req.url == '/upload') {
18
+ var form = new formidable.IncomingForm(),
19
+ files = [],
20
+ fields = [];
21
+
22
+ form.uploadDir = TEST_TMP;
23
+
24
+ form
25
+ .on('field', function(field, value) {
26
+ console.log(field, value);
27
+ fields.push([field, value]);
28
+ })
29
+ .on('file', function(field, file) {
30
+ console.log(field, file);
31
+ files.push([field, file]);
32
+ })
33
+ .on('end', function() {
34
+ console.log('-> upload done');
35
+ res.writeHead(200, {'content-type': 'text/plain'});
36
+ res.write('received fields:\n\n '+util.inspect(fields));
37
+ res.write('\n\n');
38
+ res.end('received files:\n\n '+util.inspect(files));
39
+ });
40
+ form.parse(req);
41
+ } else {
42
+ res.writeHead(404, {'content-type': 'text/plain'});
43
+ res.end('404');
44
+ }
45
+ });
46
+ server.listen(TEST_PORT);
47
+
48
+ console.log('listening on http://localhost:'+TEST_PORT+'/');
@@ -0,0 +1 @@
1
+ module.exports = require('./lib/formidable');
@@ -0,0 +1,61 @@
1
+ if (global.GENTLY) require = GENTLY.hijack(require);
2
+
3
+ var util = require('./util'),
4
+ WriteStream = require('fs').WriteStream,
5
+ EventEmitter = require('events').EventEmitter;
6
+
7
+ function File(properties) {
8
+ EventEmitter.call(this);
9
+
10
+ this.size = 0;
11
+ this.path = null;
12
+ this.name = null;
13
+ this.type = null;
14
+ this.lastModifiedDate = null;
15
+
16
+ this._writeStream = null;
17
+
18
+ for (var key in properties) {
19
+ this[key] = properties[key];
20
+ }
21
+
22
+ this._backwardsCompatibility();
23
+ }
24
+ module.exports = File;
25
+ util.inherits(File, EventEmitter);
26
+
27
+ // @todo Next release: Show error messages when accessing these
28
+ File.prototype._backwardsCompatibility = function() {
29
+ var self = this;
30
+ this.__defineGetter__('length', function() {
31
+ return self.size;
32
+ });
33
+ this.__defineGetter__('filename', function() {
34
+ return self.name;
35
+ });
36
+ this.__defineGetter__('mime', function() {
37
+ return self.type;
38
+ });
39
+ };
40
+
41
+ File.prototype.open = function() {
42
+ this._writeStream = new WriteStream(this.path);
43
+ };
44
+
45
+ File.prototype.write = function(buffer, cb) {
46
+ var self = this;
47
+ this._writeStream.write(buffer, function() {
48
+ self.lastModifiedDate = new Date();
49
+ self.size += buffer.length;
50
+ self.emit('progress', self.size);
51
+ cb();
52
+ });
53
+ };
54
+
55
+ File.prototype.end = function(cb) {
56
+ var self = this;
57
+ this._writeStream.end(function() {
58
+ self.emit('end');
59
+ cb();
60
+ });
61
+ };
@@ -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
+ };