From 7785910640d2d54b53a35622f4dfe7cab85a0c01 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Tue, 29 Jun 2010 10:38:26 -0700 Subject: [PATCH] Removed bundled formidable --- index.js | 2 +- package.json | 2 +- support/formidable/.gitignore | 1 - support/formidable/Makefile | 4 - support/formidable/Readme.md | 157 ----- .../benchmark/bench-multipart-parser.js | 66 -- support/formidable/example/post.js | 43 -- support/formidable/example/upload.js | 48 -- support/formidable/index.js | 1 - .../formidable/lib/formidable/formidable.js | 1 - .../lib/formidable/incoming_form.js | 326 ---------- support/formidable/lib/formidable/index.js | 1 - .../lib/formidable/multipart_parser.js | 311 --------- .../lib/formidable/querystring_parser.js | 25 - support/formidable/package.json | 6 - support/formidable/test/common.js | 61 -- support/formidable/test/fixture/multipart.js | 47 -- .../test/integration/test-multipart-parser.js | 86 --- .../test/simple/test-incoming-form.js | 614 ------------------ .../test/simple/test-multipart-parser.js | 50 -- .../test/simple/test-querystring-parser.js | 45 -- 21 files changed, 2 insertions(+), 1895 deletions(-) delete mode 100644 support/formidable/.gitignore delete mode 100644 support/formidable/Makefile delete mode 100644 support/formidable/Readme.md delete mode 100644 support/formidable/benchmark/bench-multipart-parser.js delete mode 100644 support/formidable/example/post.js delete mode 100644 support/formidable/example/upload.js delete mode 100644 support/formidable/index.js delete mode 100644 support/formidable/lib/formidable/formidable.js delete mode 100644 support/formidable/lib/formidable/incoming_form.js delete mode 100644 support/formidable/lib/formidable/index.js delete mode 100644 support/formidable/lib/formidable/multipart_parser.js delete mode 100644 support/formidable/lib/formidable/querystring_parser.js delete mode 100644 support/formidable/package.json delete mode 100644 support/formidable/test/common.js delete mode 100644 support/formidable/test/fixture/multipart.js delete mode 100644 support/formidable/test/integration/test-multipart-parser.js delete mode 100644 support/formidable/test/simple/test-incoming-form.js delete mode 100644 support/formidable/test/simple/test-multipart-parser.js delete mode 100644 support/formidable/test/simple/test-querystring-parser.js diff --git a/index.js b/index.js index f5da521..cf737cb 100644 --- a/index.js +++ b/index.js @@ -10,7 +10,7 @@ */ var utils = require('connect/utils'), - formidable = require('./support/formidable'); + formidable = require('formidable'); /** * Setup form with the given `options`. diff --git a/package.json b/package.json index 7fff736..59b0c62 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "urlencoded / multipart form parsing middleware for Connect", "version": "0.0.1", "author": "TJ Holowaychuk ", - "dependencies": { "connect": "*", "formidable": ">= 0.9.3" }, + "dependencies": { "formidable": ">= 0.9.3" }, "main": "./index", "engines": { "node": ">= 0.1.98" } } \ No newline at end of file diff --git a/support/formidable/.gitignore b/support/formidable/.gitignore deleted file mode 100644 index 6ae115e..0000000 --- a/support/formidable/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/test/tmp/* \ No newline at end of file diff --git a/support/formidable/Makefile b/support/formidable/Makefile deleted file mode 100644 index 14765f2..0000000 --- a/support/formidable/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -test: - @find test/{simple,integration}/test-*.js | xargs -n 1 -t node - -.PHONY: test \ No newline at end of file diff --git a/support/formidable/Readme.md b/support/formidable/Readme.md deleted file mode 100644 index 171c0d5..0000000 --- a/support/formidable/Readme.md +++ /dev/null @@ -1,157 +0,0 @@ -# Formidable - -## Purpose - -A node.js module for dealing with web forms. - -## Features - -* Fast (~500mb/sec), non-buffering multipart parser -* Automatically writing file uploads to disk -* Low memory footprint -* Graceful error handling -* Very high test coverage - -### Todo - -* Limit buffer size for fields -* Implement QuerystringParser the same way as MultipartParser - -## Installation - -Via [npm](http://github.com/isaacs/npm): - - npm install formidable@latest - -Manually: - - git clone git://github.com/felixge/node-formidable.git formidable - vim my.js - # var formidable = require('./formidable'); - -Note: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library. - -## Example - -Parse an incoming file upload. - - var formidable = require('formidable') - , http = require('http') - , sys = require('sys'); - - http.createServer(function(req, res) { - if (req.url == '/upload' && req.method.toLowerCase() == 'post') { - // parse a file upload - var form = new formidable.IncomingForm(); - form.parse(req, function(fields, files) { - res.writeHead(200, {'content-type': 'text/plain'}); - res.write('received upload:\n\n'); - res.end(sys.inspect({fields: fields, files: files})); - }); - return; - } - - // show a file upload form - res.writeHead(200, {'content-type': 'text/html'}); - res.end - ( '
' - + '
' - + '
' - + '' - + '
' - ); - }); - -## API - -### formdiable.IncomingForm - -#### new formdiable.IncomingForm() - -Creates a new incoming form. - -#### incomingForm.encoding = 'utf-8' - -The encoding to use for incoming form fields. - -#### incomingForm.uploadDir = '/tmp' - -The directory for placing file uploads in. You can later on move them using `fs.rename()`. - -#### incomingForm.keepExtensions = false - -If you want the files written to `incomingForm.uploadDir` to include the extensions of the original files, set this property to `true`. - -#### incomingForm.type - -Either 'multipart' or 'urlencoded' depending on the incoming request. - -#### incomingForm.bytesReceived - -The amount of bytes received for this form so far. - -#### incomingForm.bytesExpected - -The expected number of bytes in this form. - -#### incomingForm.parse(request, [cb]) - -Parses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback: - - incomingForm.parse(req, function(err, fields, files) { - // ... - }); - -#### incomingForm.onPart(part) - -You may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing. - - incomingForm.onPart = function(part) { - part.addListener('data', function() { - // ... - }); - } - -If you want to use formidable to only handle certain parts for you, you can do so: - - incomingForm.onPart = function(part) { - if (!part.filename) { - // let formidable handle all non-file parts - incomingForm.handlePart(part); - } - } - -Check the code in this method for further inspiration. - -#### Event: 'progress' (bytesReceived, bytesExpected) - -Emitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar. - -#### Event: 'field' (name, value) - -Emitted whenever a field / value pair has been received. - -#### Event: 'file' (name, file) - -Emitted whenever a field / file pair has been received. `file` is a JS object with the following properties: - - { path: 'the path in the uploadDir this file was written to' - , filename: 'the name this file had on the computer of the uploader' - , mime: 'the mime type specified by the user agent of the uploader' - } - -#### Event: 'error' (err) - -Emitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events. - -#### Event: 'end' () - -Emitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response. - -## License - -Formidable is licensed under the MIT license. - -## Credits - -* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js diff --git a/support/formidable/benchmark/bench-multipart-parser.js b/support/formidable/benchmark/bench-multipart-parser.js deleted file mode 100644 index eb9cb35..0000000 --- a/support/formidable/benchmark/bench-multipart-parser.js +++ /dev/null @@ -1,66 +0,0 @@ -require('../test/common'); -var multipartParser = require('formidable/multipart_parser') - , MultipartParser = multipartParser.MultipartParser - , parser = new MultipartParser() - , Buffer = require('buffer').Buffer - , boundary = '-----------------------------168072824752491622650073' - , mb = 100 - , buffer = createMultipartBuffer(boundary, mb * 1024 * 1024) - , callbacks = - { partBegin: -1 - , partEnd: -1 - , headerField: -1 - , headerValue: -1 - , partData: -1 - , end: -1 - }; - - -parser.initWithBoundary(boundary); -parser.onHeaderField = function() { - callbacks.headerField++; -}; - -parser.onHeaderValue = function() { - callbacks.headerValue++; -}; - -parser.onPartBegin = function() { - callbacks.partBegin++; -}; - -parser.onPartData = function() { - callbacks.partData++; -}; - -parser.onPartEnd = function() { - callbacks.partEnd++; -}; - -parser.onEnd = function() { - callbacks.end++; -}; - -var start = +new Date() - , nparsed = parser.write(buffer) - , duration = +new Date - start - , mbPerSec = (mb / (duration / 1000)).toFixed(2); - -p(mbPerSec+' mb/sec'); - -assert.equal(nparsed, buffer.length); - -function createMultipartBuffer(boundary, size) { - var head = - '--'+boundary+'\r\n' - + 'content-disposition: form-data; name="field1"\r\n' - + '\r\n' - , tail = '\r\n--'+boundary+'--\r\n' - , buffer = new Buffer(size); - - buffer.write(head, 'ascii', 0); - buffer.write(tail, 'ascii', buffer.length - tail.length); - return buffer; -} - -assert.callbacks(callbacks); \ No newline at end of file diff --git a/support/formidable/example/post.js b/support/formidable/example/post.js deleted file mode 100644 index 7bea111..0000000 --- a/support/formidable/example/post.js +++ /dev/null @@ -1,43 +0,0 @@ -require('../test/common'); -var http = require('http') - , sys = require('sys') - , formidable = require('formidable') - , server; - -server = http.createServer(function(req, res) { - if (req.url == '/') { - res.writeHead(200, {'content-type': 'text/html'}); - res.end - ( '
' - + '
' - + '
' - + '' - + '
' - ) - } else if (req.url == '/post') { - var form = new formidable.IncomingForm() - , fields = []; - - form - .addListener('error', function(err) { - res.writeHead(200, {'content-type': 'text/plain'}); - res.end('error:\n\n'+sys.inspect(err)); - }) - .addListener('field', function(field, value) { - p([field, value]); - fields.push([field, value]); - }) - .addListener('end', function() { - puts('-> post done'); - res.writeHead(200, {'content-type': 'text/plain'}); - res.end('received fields:\n\n '+sys.inspect(fields)); - }); - form.parse(req); - } else { - res.writeHead(404, {'content-type': 'text/plain'}); - res.end('404'); - } -}); -server.listen(TEST_PORT); - -sys.puts('listening on http://localhost:'+TEST_PORT+'/'); \ No newline at end of file diff --git a/support/formidable/example/upload.js b/support/formidable/example/upload.js deleted file mode 100644 index 75bc26e..0000000 --- a/support/formidable/example/upload.js +++ /dev/null @@ -1,48 +0,0 @@ -require('../test/common'); -var http = require('http') - , sys = require('sys') - , formidable = require('formidable') - , server; - -server = http.createServer(function(req, res) { - if (req.url == '/') { - res.writeHead(200, {'content-type': 'text/html'}); - res.end - ( '
' - + '
' - + '
' - + '' - + '
' - ) - } else if (req.url == '/upload') { - var form = new formidable.IncomingForm() - , files = [] - , fields = []; - - form.uploadDir = TEST_TMP; - - form - .addListener('field', function(field, value) { - p([field, value]); - fields.push([field, value]); - }) - .addListener('file', function(field, file) { - p([field, file]); - files.push([field, file]); - }) - .addListener('end', function() { - puts('-> upload done'); - res.writeHead(200, {'content-type': 'text/plain'}); - res.write('received fields:\n\n '+sys.inspect(fields)); - res.write('\n\n'); - res.end('received files:\n\n '+sys.inspect(files)); - }); - form.parse(req); - } else { - res.writeHead(404, {'content-type': 'text/plain'}); - res.end('404'); - } -}); -server.listen(TEST_PORT); - -sys.puts('listening on http://localhost:'+TEST_PORT+'/'); \ No newline at end of file diff --git a/support/formidable/index.js b/support/formidable/index.js deleted file mode 100644 index be41032..0000000 --- a/support/formidable/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./lib/formidable'); \ No newline at end of file diff --git a/support/formidable/lib/formidable/formidable.js b/support/formidable/lib/formidable/formidable.js deleted file mode 100644 index b2a17a2..0000000 --- a/support/formidable/lib/formidable/formidable.js +++ /dev/null @@ -1 +0,0 @@ -exports.IncomingForm = require('./incoming_form').IncomingForm; \ No newline at end of file diff --git a/support/formidable/lib/formidable/incoming_form.js b/support/formidable/lib/formidable/incoming_form.js deleted file mode 100644 index c2332b5..0000000 --- a/support/formidable/lib/formidable/incoming_form.js +++ /dev/null @@ -1,326 +0,0 @@ -if (global.GENTLY) require = GENTLY.hijack(require); - -var sys = require('sys') - , path = require('path') - , WriteStream = require('fs').WriteStream - , MultipartParser = require('./multipart_parser').MultipartParser - , QuerystringParser = require('./querystring_parser').QuerystringParser - , StringDecoder = require('string_decoder').StringDecoder - , EventEmitter = require('events').EventEmitter; - -function IncomingForm() { - EventEmitter.call(this); - - this.error = null; - this.ended = false; - - this.keepExtensions = false; - this.uploadDir = '/tmp'; - this.encoding = 'utf-8'; - this.headers = null; - this.type = null; - - this.bytesReceived = null; - this.bytesExpected = null; - - this._parser = null; - this._flushing = 0; -}; -sys.inherits(IncomingForm, EventEmitter); -exports.IncomingForm = IncomingForm; - -IncomingForm.prototype.parse = function(req, cb) { - this.pause = function() { - req.pause(); - return true; - }; - - this.resume = function() { - try { - req.resume(); - } catch (err) { - this._error(err); - return false; - } - - return true; - }; - - this.writeHeaders(req.headers); - - var self = this; - req - .addListener('error', function(err) { - self._error(err); - }) - .addListener('data', function(buffer) { - self.write(buffer); - }) - .addListener('end', function() { - if (self.error) { - return; - } - - var err = self._parser.end(); - if (err) { - self._error(err); - } - }); - - if (cb) { - var fields = {}, files = {}; - this - .addListener('field', function(name, value) { - fields[name] = value; - }) - .addListener('file', function(name, file) { - files[name] = file; - }) - .addListener('error', function(err) { - cb(err, fields, files); - }) - .addListener('end', function() { - cb(null, fields, files); - }); - } - - return this; -}; - -IncomingForm.prototype.writeHeaders = function(headers) { - this.headers = headers; - this._parseContentLength(); - this._parseContentType(); -}; - -IncomingForm.prototype.write = function(buffer) { - if (!this._parser) { - this._error(new Error('unintialized parser')); - return; - } - - var bytesParsed = this._parser.write(buffer); - if (bytesParsed !== buffer.length) { - this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed')); - } - - this.bytesReceived += bytesParsed; - this.emit('progress', this.bytesReceived, this.bytesExpected); - - return bytesParsed; -}; - -IncomingForm.prototype.pause = function() { - // this does nothing, unless overwritten in IncomingForm.parse - return false; -}; - -IncomingForm.prototype.resume = function() { - // this does nothing, unless overwritten in IncomingForm.parse - return false; -}; - -IncomingForm.prototype.onPart = function(part) { - // this method can be overwritten by the user - this.handlePart(part); -}; - -IncomingForm.prototype.handlePart = function(part) { - var self = this; - - if (!part.filename) { - var value = '' - , decoder = new StringDecoder(this.encoding); - - part.addListener('data', function(buffer) { - value += decoder.write(buffer); - }); - - part.addListener('end', function() { - if (value) { - self.emit('field', part.name, value); - } - }); - return; - } - - this._flushing++; - - var file = new WriteStream(this._uploadPath(part.filename)); - part.addListener('data', function(buffer) { - self.pause(); - file.write(buffer, function() { - self.resume(); - }); - }); - - part.addListener('end', function() { - file.end(function() { - self._flushing--; - self.emit - ( 'file' - , part.name - , { path: file.path - , filename: part.filename - , mime: part.mime - } - ); - self._maybeEnd(); - }); - }); -}; - -IncomingForm.prototype._parseContentType = function() { - if (!this.headers['content-type']) { - this._error(new Error('bad content-type header, no content-type')); - return; - } - - if (this.headers['content-type'].match(/urlencoded/i)) { - this._initUrlencoded(); - return; - } - - if (this.headers['content-type'].match(/multipart/i)) { - var m; - if (m = this.headers['content-type'].match(/boundary=([^;]+)/i)) { - this._initMultipart(m[1]); - } else { - this._error(new Error('bad content-type header, no multipart boundary')); - } - return; - } - - this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type'])); -}; - -IncomingForm.prototype._error = function(err) { - if (this.error) { - return; - } - - this.error = err; - this.pause(); - this.emit('error', err); -}; - -IncomingForm.prototype._parseContentLength = function() { - if (this.headers['content-length']) { - this.bytesReceived = 0; - this.bytesExpected = parseInt(this.headers['content-length'], 10); - } -}; - -IncomingForm.prototype._newParser = function() { - return new MultipartParser(); -}; - -IncomingForm.prototype._initMultipart = function(boundary) { - this.type = 'multipart'; - - var parser = new MultipartParser() - , self = this - , headerField = '' - , headerValue = '' - , part - , addHeader = function() { - headerField = headerField.toLowerCase(); - part.headers[headerField] = headerValue; - - var m; - if (headerField == 'content-disposition') { - if (m = headerValue.match(/name="([^"]+)"/i)) { - part.name = m[1]; - } - - if (m = headerValue.match(/filename="([^"]+)"/i)) { - part.filename = m[1].substr(m[1].lastIndexOf('\\') + 1); - } - } else if (headerField == 'content-type') { - part.mime = headerValue; - } - - headerField = ''; - headerValue = ''; - }; - - parser.initWithBoundary(boundary); - - parser.onPartBegin = function() { - part = new EventEmitter(); - part.headers = {}; - part.name = null; - part.filename = null; - part.mime = null; - }; - - parser.onHeaderField = function(b, start, end) { - if (headerValue) { - addHeader(); - } - headerField += b.toString(self.encoding, start, end); - }; - - parser.onHeaderValue = function(b, start, end) { - headerValue += b.toString(self.encoding, start, end); - }; - - parser.onPartData = function(b, start, end) { - if (headerValue) { - addHeader(); - self.onPart(part); - } - - part.emit('data', b.slice(start, end)); - }; - - parser.onPartEnd = function() { - part.emit('end'); - }; - - parser.onEnd = function() { - self.ended = true; - self._maybeEnd(); - }; - - this._parser = parser; -}; - -IncomingForm.prototype._initUrlencoded = function() { - this.type = 'urlencoded'; - - var parser = new QuerystringParser() - , self = this; - - parser.onField = function(key, val) { - self.emit('field', key, val); - }; - - parser.onEnd = function() { - self.ended = true; - self._maybeEnd(); - }; - - this._parser = parser; -}; - -IncomingForm.prototype._uploadPath = function(filename) { - var name = ''; - for (i = 0; i < 32; i++) { - name += Math.floor(Math.random() * 16).toString(16); - } - - if (this.keepExtensions) { - name += path.extname(filename); - } - - return path.join(this.uploadDir, name); -}; - -IncomingForm.prototype._maybeEnd = function() { - if (!this.ended || this._flushing) { - return; - } - - this.emit('end'); -}; \ No newline at end of file diff --git a/support/formidable/lib/formidable/index.js b/support/formidable/lib/formidable/index.js deleted file mode 100644 index 34c3a5e..0000000 --- a/support/formidable/lib/formidable/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./formidable'); \ No newline at end of file diff --git a/support/formidable/lib/formidable/multipart_parser.js b/support/formidable/lib/formidable/multipart_parser.js deleted file mode 100644 index ef5203d..0000000 --- a/support/formidable/lib/formidable/multipart_parser.js +++ /dev/null @@ -1,311 +0,0 @@ -var Buffer = require('buffer').Buffer - , s = 0 - , S = - { PARSER_UNINITIALIZED: s++ - , START: s++ - , START_BOUNDARY: s++ - , HEADER_FIELD_START: s++ - , HEADER_FIELD: s++ - , HEADER_VALUE_START: s++ - , HEADER_VALUE: s++ - , HEADER_VALUE_ALMOST_DONE: s++ - , HEADERS_ALMOST_DONE: s++ - , PART_DATA_START: s++ - , PART_DATA: s++ - , PART_END: s++ - , END: s++ - } - - , f = 1 - , F = - { PART_BOUNDARY: f - , LAST_BOUNDARY: f *= 2 - } - - , LF = 10 - , CR = 13 - , SPACE = 32 - , HYPHEN = 45 - , COLON = 58 - , A = 97 - , Z = 122 - - , lower = function(c) { - return c | 0x20; - }; - -for (var s in S) { - exports[s] = S[s]; -} - -function MultipartParser() { - this.boundary = null; - this.boundaryChars = null; - this.lookbehind = null; - this.state = S.PARSER_UNINITIALIZED; - - this.index = null; - this.flags = 0; -}; -exports.MultipartParser = MultipartParser; - -MultipartParser.prototype.initWithBoundary = function(str) { - this.boundary = new Buffer(str.length+4); - this.boundary.write('\r\n--', 'ascii', 0); - this.boundary.write(str, 'ascii', 4); - this.lookbehind = new Buffer(this.boundary.length+8); - this.state = S.START; - - this.boundaryChars = {}; - for (var i = 0; i < this.boundary.length; i++) { - this.boundaryChars[this.boundary[i]] = true; - } -}; - -MultipartParser.prototype.write = function(buffer) { - var self = this - , i = 0 - , len = buffer.length - , prevIndex = this.index - , index = this.index - , state = this.state - , flags = this.flags - , lookbehind = this.lookbehind - , boundary = this.boundary - , boundaryChars = this.boundaryChars - , boundaryLength = this.boundary.length - , boundaryEnd = boundaryLength - 1 - , bufferLength = buffer.length - , c - , cl - - , mark = function(name) { - self[name+'Mark'] = i; - } - , clear = function(name) { - delete self[name+'Mark']; - } - , callback = function(name, buffer, start, end) { - if (start !== undefined && start === end) { - return; - } - - var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1); - if (callbackSymbol in self) { - self[callbackSymbol](buffer, start, end); - } - } - , dataCallback = function(name, clear) { - var markSymbol = name+'Mark'; - if (!(markSymbol in self)) { - return; - } - - if (!clear) { - callback(name, buffer, self[markSymbol], buffer.length); - self[markSymbol] = 0; - } else { - callback(name, buffer, self[markSymbol], i); - delete self[markSymbol]; - } - }; - - for (i = 0; i < len; i++) { - c = buffer[i]; - switch (state) { - case S.PARSER_UNINITIALIZED: - return i; - case S.START: - index = 0; - state = S.START_BOUNDARY; - case S.START_BOUNDARY: - if (index == boundary.length - 2) { - if (c != CR) { - return i; - } - index++; - break; - } else if (index - 1 == boundary.length - 2) { - if (c != LF) { - return i; - } - index = 0; - callback('partBegin'); - state = S.HEADER_FIELD_START; - break; - } - - if (c != boundary[index+2]) { - return i; - } - index++; - break; - case S.HEADER_FIELD_START: - state = S.HEADER_FIELD; - mark('headerField'); - index = 0; - case S.HEADER_FIELD: - if (c == CR) { - clear('headerField'); - state = S.HEADERS_ALMOST_DONE; - break; - } - - index++; - if (c == HYPHEN) { - break; - } - - if (c == COLON) { - if (index == 1) { - // empty header field - return i; - } - dataCallback('headerField', true); - state = S.HEADER_VALUE_START; - break; - } - - cl = lower(c); - if (cl < A || cl > Z) { - return i; - } - break; - case S.HEADER_VALUE_START: - if (c == SPACE) { - break; - } - - mark('headerValue'); - state = S.HEADER_VALUE; - case S.HEADER_VALUE: - if (c == CR) { - dataCallback('headerValue', true); - state = S.HEADER_VALUE_ALMOST_DONE; - } - break; - case S.HEADER_VALUE_ALMOST_DONE: - if (c != LF) { - return i; - } - state = S.HEADER_FIELD_START; - break; - case S.HEADERS_ALMOST_DONE: - if (c != LF) { - return i; - } - - state = S.PART_DATA_START; - break; - case S.PART_DATA_START: - state = S.PART_DATA - mark('partData'); - case S.PART_DATA: - prevIndex = index; - - if (index == 0) { - // boyer-moore derrived algorithm to safely skip non-boundary data - while (i + boundaryLength <= bufferLength) { - if (buffer[i + boundaryEnd] in boundaryChars) { - break; - } - - i += boundaryLength; - } - c = buffer[i]; - } - - if (index < boundary.length) { - if (boundary[index] == c) { - if (index == 0) { - dataCallback('partData', true); - } - index++; - } else { - index = 0; - } - } else if (index == boundary.length) { - index++; - if (c == CR) { - // CR = part boundary - flags |= F.PART_BOUNDARY; - } else if (c == HYPHEN) { - // HYPHEN = end boundary - flags |= F.LAST_BOUNDARY; - } else { - index = 0; - } - } else if (index - 1 == boundary.length) { - if (flags & F.PART_BOUNDARY) { - index = 0; - if (c == LF) { - // unset the PART_BOUNDARY flag - flags &= ~F.PART_BOUNDARY; - callback('partEnd'); - callback('partBegin'); - state = S.HEADER_FIELD_START; - break; - } - } else if (flags & F.LAST_BOUNDARY) { - if (c == HYPHEN) { - index++; - } else { - index = 0; - } - } else { - index = 0; - } - } else if (index - 2 == boundary.length) { - if (c == CR) { - index++; - } else { - index = 0; - } - } else if (index - boundary.length == 3) { - index = 0; - if (c == LF) { - callback('partEnd'); - callback('end'); - state = S.END; - break; - } - } - - if (index > 0) { - // when matching a possible boundary, keep a lookbehind reference - // in case it turns out to be a false lead - lookbehind[index-1] = c; - } else if (prevIndex > 0) { - // if our boundary turned out to be rubbish, the captured lookbehind - // belongs to partData - callback('partData', lookbehind, 0, prevIndex); - prevIndex = 0; - mark('partData'); - - // reconsider the current character even so it interrupted the sequence - // it could be the beginning of a new sequence - i--; - } - - break; - default: - return i; - } - } - - dataCallback('headerField'); - dataCallback('headerValue'); - dataCallback('partData'); - - this.index = index; - this.state = state; - this.flags = flags; - - return len; -}; - -MultipartParser.prototype.end = function() { - if (this.state != S.END) { - return new Error('MultipartParser.end(): stream ended unexpectedly'); - } -}; \ No newline at end of file diff --git a/support/formidable/lib/formidable/querystring_parser.js b/support/formidable/lib/formidable/querystring_parser.js deleted file mode 100644 index 63f109e..0000000 --- a/support/formidable/lib/formidable/querystring_parser.js +++ /dev/null @@ -1,25 +0,0 @@ -if (global.GENTLY) require = GENTLY.hijack(require); - -// This is a buffering parser, not quite as nice as the multipart one. -// If I find time I'll rewrite this to be fully streaming as well -var querystring = require('querystring'); - -function QuerystringParser() { - this.buffer = ''; -}; -exports.QuerystringParser = QuerystringParser; - -QuerystringParser.prototype.write = function(buffer) { - this.buffer += buffer.toString('ascii'); - return buffer.length; -}; - -QuerystringParser.prototype.end = function() { - var fields = querystring.parse(this.buffer); - for (var field in fields) { - this.onField(field, fields[field]); - } - this.buffer = ''; - - this.onEnd(); -}; \ No newline at end of file diff --git a/support/formidable/package.json b/support/formidable/package.json deleted file mode 100644 index 56a5df5..0000000 --- a/support/formidable/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ "name" : "formidable" -, "version": "0.9.3" -, "dependencies": {"gently": ">=0.7.0"} -, "directories" : { "lib" : "./lib/formidable" } -, "main" : "./lib/formidable/index" -} \ No newline at end of file diff --git a/support/formidable/test/common.js b/support/formidable/test/common.js deleted file mode 100644 index ff8f525..0000000 --- a/support/formidable/test/common.js +++ /dev/null @@ -1,61 +0,0 @@ -var path = require('path') - , fs = require('fs') - , sys = require('sys') - , timeout; - -require.paths.unshift(path.dirname(__dirname)+'/lib'); - -try { - global.Gently = require('gently'); -} catch (e) { - throw new Error('this test suite requires node-gently'); -} - -global.GENTLY = new Gently(); - -global.puts = sys.puts; -global.p = function() { - sys.error(sys.inspect.apply(null, arguments)); -}; -global.assert = require('assert'); -global.TEST_PORT = 13532; -global.TEST_FIXTURES = path.join(__dirname, 'fixture'); -global.TEST_TMP = path.join(__dirname, 'tmp'); - -assert.timeout = function(ms) { - return setTimeout(function() { - timeout = 'timeout (after '+ms+' ms): '; - process.emit('exit'); - - throw new Error('timeout after '+ms+' ms'); - }, ms); -}; - -assert.callbacks = function(callbacks) { - process.addListener('exit', function() { - for (var k in callbacks) { - assert.equal(0, callbacks[k], (timeout || '')+k+' count off by '+callbacks[k]); - } - }); -}; - -assert.properties = function(obj, properties) { - properties.forEach(function(property) { - assert.ok(property in obj, 'has property: '+property); - }); - - for (var property in obj) { - if (!obj.hasOwnProperty(property)) { - continue; - } - - if (typeof obj[property] == 'function') { - continue; - } - - assert.ok( - properties.indexOf(property) > -1, - 'does not have property: '+property - ); - } -}; \ No newline at end of file diff --git a/support/formidable/test/fixture/multipart.js b/support/formidable/test/fixture/multipart.js deleted file mode 100644 index 3fa2e5f..0000000 --- a/support/formidable/test/fixture/multipart.js +++ /dev/null @@ -1,47 +0,0 @@ -var puts = require('sys').puts; -var p = require('sys').p; - -exports['rfc1867'] = - { boundary: 'AaB03x' - , raw: - '--AaB03x\r\n'+ - 'content-disposition: form-data; name="field1"\r\n'+ - '\r\n'+ - 'Joe Blow\r\nalmost tricked you!\r\n'+ - '--AaB03x\r\n'+ - 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ - 'Content-Type: text/plain\r\n'+ - '\r\n'+ - '... contents of file1.txt ...\r\r\n'+ - '--AaB03x--\r\n' - , parts: - [ { headers: - { 'content-disposition': 'form-data; name="field1"' - } - , data: 'Joe Blow\r\nalmost tricked you!' - } - , { headers: - { 'content-disposition': 'form-data; name="pics"; filename="file1.txt"' - , 'Content-Type': 'text/plain' - } - , data: '... contents of file1.txt ...\r' - } - ] - }; - -exports['emptyHeader'] = - { boundary: 'AaB03x' - , raw: - '--AaB03x\r\n'+ - 'content-disposition: form-data; name="field1"\r\n'+ - ': foo\r\n'+ - '\r\n'+ - 'Joe Blow\r\nalmost tricked you!\r\n'+ - '--AaB03x\r\n'+ - 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ - 'Content-Type: text/plain\r\n'+ - '\r\n'+ - '... contents of file1.txt ...\r\r\n'+ - '--AaB03x--\r\n' - , expectError: true - }; \ No newline at end of file diff --git a/support/formidable/test/integration/test-multipart-parser.js b/support/formidable/test/integration/test-multipart-parser.js deleted file mode 100644 index d18d2c4..0000000 --- a/support/formidable/test/integration/test-multipart-parser.js +++ /dev/null @@ -1,86 +0,0 @@ -require('../common'); -var CHUNK_LENGTH = 10 - , multipartParser = require('formidable/multipart_parser') - , MultipartParser = multipartParser.MultipartParser - , parser = new MultipartParser() - , fixtures = require('../fixture/multipart') - , Buffer = require('buffer').Buffer; - -Object.keys(fixtures).forEach(function(name) { - var fixture = fixtures[name] - , buffer = new Buffer(Buffer.byteLength(fixture.raw, 'binary')) - , offset = 0 - , chunk - , nparsed - - , parts = [] - , part = null - , headerField = null - , headerValue = null - , endCalled = false; - - parser.initWithBoundary(fixture.boundary); - parser.onPartBegin = function() { - part = {headers: {}, data: ''}; - parts.push(part); - headerField = ''; - headerValue = ''; - }; - - parser.onHeaderField = function(b, start, end) { - var str = b.toString('ascii', start, end); - if (headerValue) { - part.headers[headerField] = headerValue; - headerField = ''; - headerValue = ''; - } - headerField += str; - }; - - parser.onHeaderValue = function(b, start, end) { - var str = b.toString('ascii', start, end); - headerValue += str; - } - - parser.onPartData = function(b, start, end) { - var str = b.toString('ascii', start, end); - if (headerField) { - part.headers[headerField] = headerValue; - headerValue = ''; - headerField = ''; - } - part.data += b.binarySlice(start, end); - } - - parser.onEnd = function() { - endCalled = true; - } - - buffer.write(fixture.raw, 'binary', 0); - - while (offset < buffer.length) { - if (offset + CHUNK_LENGTH < buffer.length) { - chunk = buffer.slice(offset, offset+CHUNK_LENGTH); - } else { - chunk = buffer.slice(offset, buffer.length); - } - offset = offset + CHUNK_LENGTH; - - nparsed = parser.write(chunk); - if (nparsed != chunk.length) { - if (fixture.expectError) { - return; - } - puts('-- ERROR --'); - p(chunk.toString('ascii')); - throw new Error(chunk.length+' bytes written, but only '+nparsed+' bytes parsed!'); - } - } - - if (fixture.expectError) { - throw new Error('expected parse error did not happen'); - } - - assert.ok(endCalled); - assert.deepEqual(parts, fixture.parts); -}); \ No newline at end of file diff --git a/support/formidable/test/simple/test-incoming-form.js b/support/formidable/test/simple/test-incoming-form.js deleted file mode 100644 index d71f8ff..0000000 --- a/support/formidable/test/simple/test-incoming-form.js +++ /dev/null @@ -1,614 +0,0 @@ -require('../common'); -var MultipartParserStub = GENTLY.stub('./multipart_parser', 'MultipartParser') - , QuerystringParserStub = GENTLY.stub('./querystring_parser', 'QuerystringParser') - , EventEmitterStub = GENTLY.stub('events', 'EventEmitter') - , WriteStreamStub = GENTLY.stub('fs', 'WriteStream'); - -var IncomingForm = require('formidable/incoming_form').IncomingForm - , events = require('events') - , fs = require('fs') - , path = require('path') - , Buffer = require('buffer').Buffer - , fixtures = require('../fixture/multipart') - , form - , gently; - -function test(test) { - gently = new Gently(); - gently.expect(EventEmitterStub, 'call'); - form = new IncomingForm(); - test(); - gently.verify(test.name); -} - -test(function constructor() { - assert.strictEqual(form.error, null); - assert.strictEqual(form.ended, false); - assert.strictEqual(form.type, null); - assert.strictEqual(form.headers, null); - assert.strictEqual(form.keepExtensions, false); - assert.strictEqual(form.uploadDir, '/tmp'); - assert.strictEqual(form.encoding, 'utf-8'); - assert.strictEqual(form.bytesReceived, null); - assert.strictEqual(form.bytesExpected, null); - assert.strictEqual(form._parser, null); - assert.strictEqual(form._flushing, 0); - assert.ok(form instanceof EventEmitterStub); - assert.equal(form.constructor.name, 'IncomingForm'); -}); - -test(function parse() { - var REQ = {headers: {}} - , emit = {}; - - gently.expect(form, 'writeHeaders', function(headers) { - assert.strictEqual(headers, REQ.headers); - }); - - var events = ['error', 'data', 'end']; - gently.expect(REQ, 'addListener', events.length, function(event, fn) { - assert.equal(event, events.shift()); - emit[event] = fn; - return this; - }); - - form.parse(REQ); - - (function testPause() { - gently.expect(REQ, 'pause'); - assert.strictEqual(form.pause(), true); - })(); - - (function testResume() { - gently.expect(REQ, 'resume'); - assert.strictEqual(form.resume(), true); - })(); - - (function testResumeException() { - var ERR = new Error('dasdsa'); - gently.expect(REQ, 'resume', function() { - throw ERR; - }); - - gently.expect(form, '_error', function(err) { - assert.strictEqual(err, ERR); - }); - - assert.strictEqual(form.resume(), false); - })(); - - (function testEmitError() { - var ERR = new Error('something bad happened'); - gently.expect(form, '_error',function(err) { - assert.strictEqual(err, ERR); - }); - emit.error(ERR); - })(); - - (function testEmitData() { - var BUFFER = [1, 2, 3]; - gently.expect(form, 'write', function(buffer) { - assert.strictEqual(buffer, BUFFER); - }); - emit.data(BUFFER); - })(); - - (function testEmitEnd() { - form._parser = {}; - - (function testWithError() { - var ERR = new Error('haha'); - gently.expect(form._parser, 'end', function() { - return ERR; - }); - - gently.expect(form, '_error', function(err) { - assert.strictEqual(err, ERR); - }); - - emit.end(); - })(); - - (function testWithoutError() { - gently.expect(form._parser, 'end'); - emit.end(); - })(); - - (function testAfterError() { - form.error = true; - emit.end(); - })(); - })(); - - - (function testWithCallback() { - gently.expect(EventEmitterStub, 'call'); - var form = new IncomingForm() - , REQ = {headers: {}} - , parseCalled = 0; - - gently.expect(form, 'writeHeaders'); - gently.expect(REQ, 'addListener', 3, function() { - return this; - }); - - gently.expect(form, 'addListener', 4, function(event, fn) { - if (event == 'field') { - fn('field1', 'foo'); - fn('field1', 'bar'); - fn('field2', 'nice'); - } - - if (event == 'file') { - fn('file1', '1'); - fn('file1', '2'); - fn('file2', '3'); - } - - if (event == 'end') { - fn(); - } - return this; - }); - - form.parse(REQ, gently.expect(function parseCbOk(err, fields, files) { - assert.deepEqual(fields, {field1: 'bar', field2: 'nice'}); - assert.deepEqual(files, {file1: '2', file2: '3'}); - })); - - gently.expect(form, 'writeHeaders'); - gently.expect(REQ, 'addListener', 3, function() { - return this; - }); - - var ERR = new Error('test'); - gently.expect(form, 'addListener', 3, function(event, fn) { - if (event == 'field') { - fn('foo', 'bar'); - } - - if (event == 'error') { - fn(ERR); - gently.expect(form, 'addListener'); - } - return this; - }); - - form.parse(REQ, gently.expect(function parseCbErr(err, fields, files) { - assert.strictEqual(err, ERR); - assert.deepEqual(fields, {foo: 'bar'}); - })); - })(); -}); - -test(function pause() { - assert.strictEqual(form.pause(), false); -}); - -test(function resume() { - assert.strictEqual(form.resume(), false); -}); - - -test(function writeHeaders() { - var HEADERS = {}; - gently.expect(form, '_parseContentLength'); - gently.expect(form, '_parseContentType'); - - form.writeHeaders(HEADERS); - assert.strictEqual(form.headers, HEADERS); -}); - -test(function write() { - var parser = {} - , BUFFER = [1, 2, 3]; - - form._parser = parser; - form.bytesExpected = 523423; - - (function testBasic() { - gently.expect(parser, 'write', function(buffer) { - assert.strictEqual(buffer, BUFFER); - return buffer.length; - }); - - gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { - assert.equal(event, 'progress'); - assert.equal(bytesReceived, BUFFER.length); - assert.equal(bytesExpected, form.bytesExpected); - }); - - assert.equal(form.write(BUFFER), BUFFER.length); - assert.equal(form.bytesReceived, BUFFER.length); - })(); - - (function testParserError() { - gently.expect(parser, 'write', function(buffer) { - assert.strictEqual(buffer, BUFFER); - return buffer.length - 1; - }); - - gently.expect(form, '_error', function(err) { - assert.ok(err.message.match(/parser error/i)); - }); - - gently.expect(form, 'emit'); - - assert.equal(form.write(BUFFER), BUFFER.length - 1); - assert.equal(form.bytesReceived, BUFFER.length + BUFFER.length - 1); - })(); - - (function testUninitialized() { - delete form._parser; - - gently.expect(form, '_error', function(err) { - assert.ok(err.message.match(/unintialized parser/i)); - }); - form.write(BUFFER); - })(); -}); - -test(function parseContentType() { - var HEADERS = {}; - - form.headers = {'content-type': 'application/x-www-form-urlencoded'}; - gently.expect(form, '_initUrlencoded'); - form._parseContentType(); - - // accept anything that has 'urlencoded' in it - form.headers = {'content-type': 'broken-client/urlencoded-stupid'}; - gently.expect(form, '_initUrlencoded'); - form._parseContentType(); - - var BOUNDARY = '---------------------------57814261102167618332366269'; - form.headers = {'content-type': 'multipart/form-data; boundary='+BOUNDARY}; - - gently.expect(form, '_initMultipart', function(boundary) { - assert.equal(boundary, BOUNDARY); - }); - form._parseContentType(); - - (function testNoBoundary() { - form.headers = {'content-type': 'multipart/form-data'}; - - gently.expect(form, '_error', function(err) { - assert.ok(err.message.match(/no multipart boundary/i)); - }); - form._parseContentType(); - })(); - - (function testNoContentType() { - form.headers = {}; - - gently.expect(form, '_error', function(err) { - assert.ok(err.message.match(/no content-type/i)); - }); - form._parseContentType(); - })(); - - (function testUnknownContentType() { - form.headers = {'content-type': 'invalid'}; - - gently.expect(form, '_error', function(err) { - assert.ok(err.message.match(/unknown content-type/i)); - }); - form._parseContentType(); - })(); -}); - -test(function parseContentLength() { - var HEADERS = {}; - - form.headers = {}; - form._parseContentLength(); - assert.strictEqual(form.bytesExpected, null); - - form.headers['content-length'] = '8'; - form._parseContentLength(); - assert.strictEqual(form.bytesReceived, 0); - assert.strictEqual(form.bytesExpected, 8); - - // JS can be evil, lets make sure we are not - form.headers['content-length'] = '08'; - form._parseContentLength(); - assert.strictEqual(form.bytesExpected, 8); -}); - -test(function _initMultipart() { - var BOUNDARY = '123' - , PARSER; - - gently.expect(MultipartParserStub, 'new', function() { - PARSER = this; - }); - - gently.expect(MultipartParserStub.prototype, 'initWithBoundary', function(boundary) { - assert.equal(boundary, BOUNDARY); - }); - - form._initMultipart(BOUNDARY); - assert.equal(form.type, 'multipart'); - assert.strictEqual(form._parser, PARSER); - - (function testRegularField() { - var PART; - gently.expect(EventEmitterStub, 'new', function() { - PART = this; - }); - - gently.expect(form, 'onPart', function(part) { - assert.strictEqual(part, PART); - assert.deepEqual - ( part.headers - , { 'content-disposition': 'form-data; name="field1"' - , 'foo': 'bar' - } - ); - assert.equal(part.name, 'field1'); - - var strings = ['hello', ' world']; - gently.expect(part, 'emit', 2, function(event, b) { - assert.equal(event, 'data'); - assert.equal(b.toString(), strings.shift()); - }); - - gently.expect(part, 'emit', function(event, b) { - assert.equal(event, 'end'); - }); - }); - - PARSER.onPartBegin(); - PARSER.onHeaderField(new Buffer('content-disposition'), 0, 10); - PARSER.onHeaderField(new Buffer('content-disposition'), 10, 19); - PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 0, 14); - PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 14, 24); - PARSER.onHeaderField(new Buffer('foo'), 0, 3); - PARSER.onHeaderValue(new Buffer('bar'), 0, 3); - PARSER.onPartData(new Buffer('hello world'), 0, 5); - PARSER.onPartData(new Buffer('hello world'), 5, 11); - PARSER.onPartEnd(); - })(); - - (function testFileField() { - var PART; - gently.expect(EventEmitterStub, 'new', function() { - PART = this; - }); - - gently.expect(form, 'onPart', function(part) { - assert.deepEqual - ( part.headers - , { 'content-disposition': 'form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sunset.jpg"' - , 'content-type': 'text/plain' - } - ); - assert.equal(part.name, 'field2'); - assert.equal(part.filename, 'Sunset.jpg'); - assert.equal(part.mime, 'text/plain'); - - gently.expect(part, 'emit', function(event, b) { - assert.equal(event, 'data'); - assert.equal(b.toString(), '... contents of file1.txt ...'); - }); - - gently.expect(part, 'emit', function(event, b) { - assert.equal(event, 'end'); - }); - }); - - PARSER.onPartBegin(); - PARSER.onHeaderField(new Buffer('content-disposition'), 0, 19); - PARSER.onHeaderValue(new Buffer('form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sunset.jpg"'), 0, 85); - PARSER.onHeaderField(new Buffer('Content-Type'), 0, 12); - PARSER.onHeaderValue(new Buffer('text/plain'), 0, 10); - PARSER.onPartData(new Buffer('... contents of file1.txt ...'), 0, 29); - PARSER.onPartEnd(); - })(); - - (function testEnd() { - gently.expect(form, '_maybeEnd'); - PARSER.onEnd(); - assert.ok(form.ended); - })(); -}); - -test(function _initUrlencoded() { - var PARSER; - - gently.expect(QuerystringParserStub, 'new', function() { - PARSER = this; - }); - - form._initUrlencoded(); - assert.equal(form.type, 'urlencoded'); - assert.strictEqual(form._parser, PARSER); - - (function testOnField() { - var KEY = 'KEY', VAL = 'VAL'; - gently.expect(form, 'emit', function(field, key, val) { - assert.equal(field, 'field'); - assert.equal(key, KEY); - assert.equal(val, VAL); - }); - - PARSER.onField(KEY, VAL); - })(); - - (function testOnEnd() { - gently.expect(form, '_maybeEnd'); - - PARSER.onEnd(); - assert.equal(form.ended, true); - })(); -}); - -test(function _error() { - var ERR = new Error('bla'); - - gently.expect(form, 'pause'); - gently.expect(form, 'emit', function(event, err) { - assert.equal(event, 'error'); - assert.strictEqual(err, ERR); - }); - - form._error(ERR); - assert.strictEqual(form.error, ERR); - - // make sure _error only does its thing once - form._error(ERR); -}); - -test(function onPart() { - var PART = {}; - gently.expect(form, 'handlePart', function(part) { - assert.strictEqual(part, PART); - }); - - form.onPart(PART); -}); - -test(function handlePart() { - (function testUtf8Field() { - var PART = new events.EventEmitter(); - PART.name = 'my_field'; - - gently.expect(form, 'emit', function(event, field, value) { - assert.equal(event, 'field'); - assert.equal(field, 'my_field'); - assert.equal(value, 'hello world: €'); - }); - - form.handlePart(PART); - PART.emit('data', new Buffer('hello')); - PART.emit('data', new Buffer(' world: ')); - PART.emit('data', new Buffer([0xE2])); - PART.emit('data', new Buffer([0x82, 0xAC])); - PART.emit('end'); - })(); - - (function testBinaryField() { - var PART = new events.EventEmitter(); - PART.name = 'my_field2'; - - gently.expect(form, 'emit', function(event, field, value) { - assert.equal(event, 'field'); - assert.equal(field, 'my_field2'); - assert.equal(value, 'hello world: '+new Buffer([0xE2, 0x82, 0xAC]).toString('binary')); - }); - - form.encoding = 'binary'; - form.handlePart(PART); - PART.emit('data', new Buffer('hello')); - PART.emit('data', new Buffer(' world: ')); - PART.emit('data', new Buffer([0xE2])); - PART.emit('data', new Buffer([0x82, 0xAC])); - PART.emit('end'); - })(); - - (function testFilePart() { - var PART = new events.EventEmitter() - , FILE = new events.EventEmitter() - , PATH = '/foo/bar'; - - PART.name = 'my_file'; - PART.filename = 'sweet.txt'; - PART.mime = 'sweet.txt'; - - gently.expect(form, '_uploadPath', function(filename) { - assert.equal(filename, PART.filename); - return PATH; - }); - - gently.expect(WriteStreamStub, 'new', function(path) { - assert.equal(path, PATH); - FILE = this; - }); - - form.handlePart(PART); - assert.equal(form._flushing, 1); - - var BUFFER; - gently.expect(form, 'pause'); - gently.expect(FILE, 'write', function(buffer, cb) { - assert.strictEqual(buffer, BUFFER); - gently.expect(form, 'resume'); - // @todo handle cb(new Err) - cb(); - }); - - PART.emit('data', BUFFER = new Buffer('test')); - - gently.expect(FILE, 'end', function(cb) { - gently.expect(form, 'emit', function(event, field, file) { - assert.equal(event, 'file'); - assert.deepEqual - ( file - , { path: FILE.path - , filename: PART.filename - , mime: PART.mime - } - ); - }); - - gently.expect(form, '_maybeEnd'); - - cb(); - assert.equal(form._flushing, 0); - }); - - PART.emit('end'); - })(); -}); - -test(function _uploadPath() { - (function testUniqueId() { - var UUID_A, UUID_B; - gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) { - assert.equal(uploadDir, form.uploadDir); - UUID_A = uuid; - }); - form._uploadPath(); - - gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) { - UUID_B = uuid; - }); - form._uploadPath(); - - assert.notEqual(UUID_A, UUID_B); - })(); - - (function testFileExtension() { - form.keepExtensions = true; - var FILENAME = 'foo.jpg' - , EXT = '.bar'; - - gently.expect(GENTLY.hijacked.path, 'extname', function(filename) { - assert.equal(filename, FILENAME); - gently.restore(path, 'extname'); - - return EXT; - }); - - gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, name) { - assert.equal(path.extname(name), EXT); - }); - form._uploadPath(FILENAME); - })(); -}); - -test(function _maybeEnd() { - gently.expect(form, 'emit', 0); - form._maybeEnd(); - - form.ended = true; - form._flushing = 1; - form._maybeEnd(); - - gently.expect(form, 'emit', function(event) { - assert.equal(event, 'end'); - }); - - form.ended = true; - form._flushing = 0; - form._maybeEnd(); -}); \ No newline at end of file diff --git a/support/formidable/test/simple/test-multipart-parser.js b/support/formidable/test/simple/test-multipart-parser.js deleted file mode 100644 index d7dd124..0000000 --- a/support/formidable/test/simple/test-multipart-parser.js +++ /dev/null @@ -1,50 +0,0 @@ -require('../common'); -var multipartParser = require('formidable/multipart_parser') - , MultipartParser = multipartParser.MultipartParser - , events = require('events') - , Buffer = require('buffer').Buffer - , parser; - -function test(test) { - parser = new MultipartParser(); - test(); -} - -test(function constructor() { - assert.equal(parser.boundary, null); - assert.equal(parser.state, 0); - assert.equal(parser.flags, 0); - assert.equal(parser.boundaryChars, null); - assert.equal(parser.index, null); - assert.equal(parser.lookbehind, null); - assert.equal(parser.constructor.name, 'MultipartParser'); -}); - -test(function initWithBoundary() { - var boundary = 'abc'; - parser.initWithBoundary(boundary); - assert.deepEqual(Array.prototype.slice.call(parser.boundary), [13, 10, 45, 45, 97, 98, 99]); - assert.equal(parser.state, multipartParser.START); - - assert.deepEqual(parser.boundaryChars, {10: true, 13: true, 45: true, 97: true, 98: true, 99: true}); -}); - -test(function parserError() { - var boundary = 'abc' - , buffer = new Buffer(5); - - parser.initWithBoundary(boundary); - buffer.write('--ad', 'ascii', 0); - assert.equal(parser.write(buffer), 3); -}); - -test(function end() { - (function testError() { - assert.equal(parser.end().message, 'MultipartParser.end(): stream ended unexpectedly'); - })(); - - (function testRegular() { - parser.state = multipartParser.END; - assert.strictEqual(parser.end(), undefined); - })(); -}); \ No newline at end of file diff --git a/support/formidable/test/simple/test-querystring-parser.js b/support/formidable/test/simple/test-querystring-parser.js deleted file mode 100644 index 9ad0540..0000000 --- a/support/formidable/test/simple/test-querystring-parser.js +++ /dev/null @@ -1,45 +0,0 @@ -require('../common'); -var QuerystringParser = require('formidable/querystring_parser').QuerystringParser - , Buffer = require('buffer').Buffer - , gently - , parser; - -function test(test) { - gently = new Gently(); - parser = new QuerystringParser(); - test(); - gently.verify(test.name); -} - -test(function constructor() { - assert.equal(parser.buffer, ''); - assert.equal(parser.constructor.name, 'QuerystringParser'); -}); - -test(function write() { - var a = new Buffer('a=1'); - assert.equal(parser.write(a), a.length); - - var b = new Buffer('&b=2'); - parser.write(b); - assert.equal(parser.buffer, a + b); -}); - -test(function end() { - var FIELDS = {a: ['b', {c: 'd'}], e: 'f'}; - - gently.expect(GENTLY.hijacked.querystring, 'parse', function(str) { - assert.equal(str, parser.buffer); - return FIELDS; - }); - - gently.expect(parser, 'onField', Object.keys(FIELDS).length, function(key, val) { - assert.deepEqual(FIELDS[key], val); - }); - - gently.expect(parser, 'onEnd'); - - parser.buffer = 'my buffer'; - parser.end(); - assert.equal(parser.buffer, ''); -}); \ No newline at end of file