mirror of
https://github.com/sstent/alex_app1.git
synced 2026-01-26 00:52:15 +00:00
lots of work so far-- mostly tidying
This commit is contained in:
4
node_modules/formidable/.npmignore
generated
vendored
Normal file
4
node_modules/formidable/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/test/tmp/
|
||||
*.upload
|
||||
*.un~
|
||||
*.http
|
||||
4
node_modules/formidable/.travis.yml
generated
vendored
Normal file
4
node_modules/formidable/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.4
|
||||
- 0.6
|
||||
14
node_modules/formidable/Makefile
generated
vendored
Normal file
14
node_modules/formidable/Makefile
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
SHELL := /bin/bash
|
||||
|
||||
test:
|
||||
@./test/run.js
|
||||
|
||||
build: npm test
|
||||
|
||||
npm:
|
||||
npm install .
|
||||
|
||||
clean:
|
||||
rm test/tmp/*
|
||||
|
||||
.PHONY: test clean build
|
||||
311
node_modules/formidable/Readme.md
generated
vendored
Normal file
311
node_modules/formidable/Readme.md
generated
vendored
Normal file
@@ -0,0 +1,311 @@
|
||||
# Formidable
|
||||
|
||||
[](http://travis-ci.org/felixge/node-formidable)
|
||||
|
||||
## Purpose
|
||||
|
||||
A node.js module for parsing form data, especially file uploads.
|
||||
|
||||
## Current status
|
||||
|
||||
This module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading
|
||||
and encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from
|
||||
a large variety of clients and is considered production-ready.
|
||||
|
||||
## Features
|
||||
|
||||
* Fast (~500mb/sec), non-buffering multipart parser
|
||||
* Automatically writing file uploads to disk
|
||||
* Low memory footprint
|
||||
* Graceful error handling
|
||||
* Very high test coverage
|
||||
|
||||
## Changelog
|
||||
|
||||
### v1.0.9
|
||||
|
||||
* Emit progress when content length header parsed (Tim Koschützki)
|
||||
* Fix Readme syntax due to GitHub changes (goob)
|
||||
* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara)
|
||||
|
||||
### v1.0.8
|
||||
|
||||
* Strip potentially unsafe characters when using `keepExtensions: true`.
|
||||
* Switch to utest / urun for testing
|
||||
* Add travis build
|
||||
|
||||
### v1.0.7
|
||||
|
||||
* Remove file from package that was causing problems when installing on windows. (#102)
|
||||
* Fix typos in Readme (Jason Davies).
|
||||
|
||||
### v1.0.6
|
||||
|
||||
* Do not default to the default to the field name for file uploads where
|
||||
filename="".
|
||||
|
||||
### v1.0.5
|
||||
|
||||
* Support filename="" in multipart parts
|
||||
* Explain unexpected end() errors in parser better
|
||||
|
||||
**Note:** Starting with this version, formidable emits 'file' events for empty
|
||||
file input fields. Previously those were incorrectly emitted as regular file
|
||||
input fields with value = "".
|
||||
|
||||
### v1.0.4
|
||||
|
||||
* Detect a good default tmp directory regardless of platform. (#88)
|
||||
|
||||
### v1.0.3
|
||||
|
||||
* Fix problems with utf8 characters (#84) / semicolons in filenames (#58)
|
||||
* Small performance improvements
|
||||
* New test suite and fixture system
|
||||
|
||||
### v1.0.2
|
||||
|
||||
* Exclude node\_modules folder from git
|
||||
* Implement new `'aborted'` event
|
||||
* Fix files in example folder to work with recent node versions
|
||||
* Make gently a devDependency
|
||||
|
||||
[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2)
|
||||
|
||||
### v1.0.1
|
||||
|
||||
* Fix package.json to refer to proper main directory. (#68, Dean Landolt)
|
||||
|
||||
[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1)
|
||||
|
||||
### v1.0.0
|
||||
|
||||
* Add support for multipart boundaries that are quoted strings. (Jeff Craig)
|
||||
|
||||
This marks the beginning of development on version 2.0 which will include
|
||||
several architectural improvements.
|
||||
|
||||
[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0)
|
||||
|
||||
### v0.9.11
|
||||
|
||||
* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki)
|
||||
* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class
|
||||
|
||||
**Important:** The old property names of the File class will be removed in a
|
||||
future release.
|
||||
|
||||
[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11)
|
||||
|
||||
### Older releases
|
||||
|
||||
These releases were done before starting to maintain the above Changelog:
|
||||
|
||||
* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10)
|
||||
* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9)
|
||||
* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8)
|
||||
* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7)
|
||||
* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6)
|
||||
* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5)
|
||||
* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4)
|
||||
* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3)
|
||||
* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2)
|
||||
* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1)
|
||||
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
||||
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
||||
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
||||
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
||||
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
||||
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
||||
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
||||
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
||||
* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0)
|
||||
|
||||
## 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'),
|
||||
|
||||
util = require('util');
|
||||
|
||||
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(err, fields, files) {
|
||||
res.writeHead(200, {'content-type': 'text/plain'});
|
||||
res.write('received upload:\n\n');
|
||||
res.end(util.inspect({fields: fields, files: files}));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// show a file upload form
|
||||
res.writeHead(200, {'content-type': 'text/html'});
|
||||
res.end(
|
||||
'<form action="/upload" enctype="multipart/form-data" method="post">'+
|
||||
'<input type="text" name="title"><br>'+
|
||||
'<input type="file" name="upload" multiple="multiple"><br>'+
|
||||
'<input type="submit" value="Upload">'+
|
||||
'</form>'
|
||||
);
|
||||
}).listen(80);
|
||||
|
||||
## API
|
||||
|
||||
### formidable.IncomingForm
|
||||
|
||||
__new formidable.IncomingForm()__
|
||||
|
||||
Creates a new incoming form.
|
||||
|
||||
__incomingForm.encoding = 'utf-8'__
|
||||
|
||||
The encoding to use for incoming form fields.
|
||||
|
||||
__incomingForm.uploadDir = process.env.TMP || '/tmp' || process.cwd()__
|
||||
|
||||
The directory for placing file uploads in. You can move them later on using
|
||||
`fs.rename()`. The default directory is picked at module load time depending on
|
||||
the first existing directory from those listed above.
|
||||
|
||||
__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.maxFieldsSize = 2 * 1024 * 1024__
|
||||
|
||||
Limits the amount of memory a field (not file) can allocate in bytes.
|
||||
If this value is exceeded, an `'error'` event is emitted. The default
|
||||
size is 2MB.
|
||||
|
||||
__incomingForm.hash = false__
|
||||
|
||||
If you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`.
|
||||
|
||||
__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: 'fileBegin' (name, file)__
|
||||
|
||||
Emitted whenever a new file is detected in the upload stream. Use this even if
|
||||
you want to stream the file to somewhere else while buffering the upload on
|
||||
the file system.
|
||||
|
||||
__Event: 'file' (name, file)__
|
||||
|
||||
Emitted whenever a field / file pair has been received. `file` is an instance of `File`.
|
||||
|
||||
__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: 'aborted'__
|
||||
|
||||
Emitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core).
|
||||
|
||||
__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.
|
||||
|
||||
### formidable.File
|
||||
|
||||
__file.size = 0__
|
||||
|
||||
The size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet.
|
||||
|
||||
__file.path = null__
|
||||
|
||||
The path this file is being written to. You can modify this in the `'fileBegin'` event in
|
||||
case you are unhappy with the way formidable generates a temporary path for your files.
|
||||
|
||||
__file.name = null__
|
||||
|
||||
The name this file had according to the uploading client.
|
||||
|
||||
__file.type = null__
|
||||
|
||||
The mime type of this file, according to the uploading client.
|
||||
|
||||
__file.lastModifiedDate = null__
|
||||
|
||||
A date object (or `null`) containing the time this file was last written to. Mostly
|
||||
here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).
|
||||
|
||||
__file.hash = null__
|
||||
|
||||
If hash calculation was set, you can read the hex digest out of this var.
|
||||
|
||||
## License
|
||||
|
||||
Formidable is licensed under the MIT license.
|
||||
|
||||
## Ports
|
||||
|
||||
* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable
|
||||
|
||||
## 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
|
||||
3
node_modules/formidable/TODO
generated
vendored
Normal file
3
node_modules/formidable/TODO
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
- Better bufferMaxSize handling approach
|
||||
- Add tests for JSON parser pull request and merge it
|
||||
- Implement QuerystringParser the same way as MultipartParser
|
||||
70
node_modules/formidable/benchmark/bench-multipart-parser.js
generated
vendored
Normal file
70
node_modules/formidable/benchmark/bench-multipart-parser.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
require('../test/common');
|
||||
var multipartParser = require('../lib/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);
|
||||
|
||||
console.log(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;
|
||||
}
|
||||
|
||||
process.on('exit', function() {
|
||||
for (var k in callbacks) {
|
||||
assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
|
||||
}
|
||||
});
|
||||
43
node_modules/formidable/example/post.js
generated
vendored
Normal file
43
node_modules/formidable/example/post.js
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
require('../test/common');
|
||||
var http = require('http'),
|
||||
util = require('util'),
|
||||
formidable = require('formidable'),
|
||||
server;
|
||||
|
||||
server = http.createServer(function(req, res) {
|
||||
if (req.url == '/') {
|
||||
res.writeHead(200, {'content-type': 'text/html'});
|
||||
res.end(
|
||||
'<form action="/post" method="post">'+
|
||||
'<input type="text" name="title"><br>'+
|
||||
'<input type="text" name="data[foo][]"><br>'+
|
||||
'<input type="submit" value="Submit">'+
|
||||
'</form>'
|
||||
);
|
||||
} else if (req.url == '/post') {
|
||||
var form = new formidable.IncomingForm(),
|
||||
fields = [];
|
||||
|
||||
form
|
||||
.on('error', function(err) {
|
||||
res.writeHead(200, {'content-type': 'text/plain'});
|
||||
res.end('error:\n\n'+util.inspect(err));
|
||||
})
|
||||
.on('field', function(field, value) {
|
||||
console.log(field, value);
|
||||
fields.push([field, value]);
|
||||
})
|
||||
.on('end', function() {
|
||||
console.log('-> post done');
|
||||
res.writeHead(200, {'content-type': 'text/plain'});
|
||||
res.end('received fields:\n\n '+util.inspect(fields));
|
||||
});
|
||||
form.parse(req);
|
||||
} else {
|
||||
res.writeHead(404, {'content-type': 'text/plain'});
|
||||
res.end('404');
|
||||
}
|
||||
});
|
||||
server.listen(TEST_PORT);
|
||||
|
||||
console.log('listening on http://localhost:'+TEST_PORT+'/');
|
||||
48
node_modules/formidable/example/upload.js
generated
vendored
Normal file
48
node_modules/formidable/example/upload.js
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
require('../test/common');
|
||||
var http = require('http'),
|
||||
util = require('util'),
|
||||
formidable = require('formidable'),
|
||||
server;
|
||||
|
||||
server = http.createServer(function(req, res) {
|
||||
if (req.url == '/') {
|
||||
res.writeHead(200, {'content-type': 'text/html'});
|
||||
res.end(
|
||||
'<form action="/upload" enctype="multipart/form-data" method="post">'+
|
||||
'<input type="text" name="title"><br>'+
|
||||
'<input type="file" name="upload" multiple="multiple"><br>'+
|
||||
'<input type="submit" value="Upload">'+
|
||||
'</form>'
|
||||
);
|
||||
} else if (req.url == '/upload') {
|
||||
var form = new formidable.IncomingForm(),
|
||||
files = [],
|
||||
fields = [];
|
||||
|
||||
form.uploadDir = TEST_TMP;
|
||||
|
||||
form
|
||||
.on('field', function(field, value) {
|
||||
console.log(field, value);
|
||||
fields.push([field, value]);
|
||||
})
|
||||
.on('file', function(field, file) {
|
||||
console.log(field, file);
|
||||
files.push([field, file]);
|
||||
})
|
||||
.on('end', function() {
|
||||
console.log('-> upload done');
|
||||
res.writeHead(200, {'content-type': 'text/plain'});
|
||||
res.write('received fields:\n\n '+util.inspect(fields));
|
||||
res.write('\n\n');
|
||||
res.end('received files:\n\n '+util.inspect(files));
|
||||
});
|
||||
form.parse(req);
|
||||
} else {
|
||||
res.writeHead(404, {'content-type': 'text/plain'});
|
||||
res.end('404');
|
||||
}
|
||||
});
|
||||
server.listen(TEST_PORT);
|
||||
|
||||
console.log('listening on http://localhost:'+TEST_PORT+'/');
|
||||
1
node_modules/formidable/index.js
generated
vendored
Normal file
1
node_modules/formidable/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib/formidable');
|
||||
73
node_modules/formidable/lib/file.js
generated
vendored
Normal file
73
node_modules/formidable/lib/file.js
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
if (global.GENTLY) require = GENTLY.hijack(require);
|
||||
|
||||
var util = require('./util'),
|
||||
WriteStream = require('fs').WriteStream,
|
||||
EventEmitter = require('events').EventEmitter,
|
||||
crypto = require('crypto');
|
||||
|
||||
function File(properties) {
|
||||
EventEmitter.call(this);
|
||||
|
||||
this.size = 0;
|
||||
this.path = null;
|
||||
this.name = null;
|
||||
this.type = null;
|
||||
this.hash = null;
|
||||
this.lastModifiedDate = null;
|
||||
|
||||
this._writeStream = null;
|
||||
|
||||
for (var key in properties) {
|
||||
this[key] = properties[key];
|
||||
}
|
||||
|
||||
if(typeof this.hash === 'string') {
|
||||
this.hash = crypto.createHash(properties.hash);
|
||||
}
|
||||
|
||||
this._backwardsCompatibility();
|
||||
}
|
||||
module.exports = File;
|
||||
util.inherits(File, EventEmitter);
|
||||
|
||||
// @todo Next release: Show error messages when accessing these
|
||||
File.prototype._backwardsCompatibility = function() {
|
||||
var self = this;
|
||||
this.__defineGetter__('length', function() {
|
||||
return self.size;
|
||||
});
|
||||
this.__defineGetter__('filename', function() {
|
||||
return self.name;
|
||||
});
|
||||
this.__defineGetter__('mime', function() {
|
||||
return self.type;
|
||||
});
|
||||
};
|
||||
|
||||
File.prototype.open = function() {
|
||||
this._writeStream = new WriteStream(this.path);
|
||||
};
|
||||
|
||||
File.prototype.write = function(buffer, cb) {
|
||||
var self = this;
|
||||
this._writeStream.write(buffer, function() {
|
||||
if(self.hash) {
|
||||
self.hash.update(buffer);
|
||||
}
|
||||
self.lastModifiedDate = new Date();
|
||||
self.size += buffer.length;
|
||||
self.emit('progress', self.size);
|
||||
cb();
|
||||
});
|
||||
};
|
||||
|
||||
File.prototype.end = function(cb) {
|
||||
var self = this;
|
||||
this._writeStream.end(function() {
|
||||
if(self.hash) {
|
||||
self.hash = self.hash.digest('hex');
|
||||
}
|
||||
self.emit('end');
|
||||
cb();
|
||||
});
|
||||
};
|
||||
384
node_modules/formidable/lib/incoming_form.js
generated
vendored
Normal file
384
node_modules/formidable/lib/incoming_form.js
generated
vendored
Normal file
@@ -0,0 +1,384 @@
|
||||
if (global.GENTLY) require = GENTLY.hijack(require);
|
||||
|
||||
var fs = require('fs');
|
||||
var util = require('./util'),
|
||||
path = require('path'),
|
||||
File = require('./file'),
|
||||
MultipartParser = require('./multipart_parser').MultipartParser,
|
||||
QuerystringParser = require('./querystring_parser').QuerystringParser,
|
||||
StringDecoder = require('string_decoder').StringDecoder,
|
||||
EventEmitter = require('events').EventEmitter,
|
||||
Stream = require('stream').Stream;
|
||||
|
||||
function IncomingForm(opts) {
|
||||
if (!(this instanceof IncomingForm)) return new IncomingForm;
|
||||
EventEmitter.call(this);
|
||||
|
||||
opts=opts||{};
|
||||
|
||||
this.error = null;
|
||||
this.ended = false;
|
||||
|
||||
this.maxFieldsSize = opts.maxFieldsSize || 2 * 1024 * 1024;
|
||||
this.keepExtensions = opts.keepExtensions || false;
|
||||
this.uploadDir = opts.uploadDir || IncomingForm.UPLOAD_DIR;
|
||||
this.encoding = opts.encoding || 'utf-8';
|
||||
this.headers = null;
|
||||
this.type = null;
|
||||
this.hash = false;
|
||||
|
||||
this.bytesReceived = null;
|
||||
this.bytesExpected = null;
|
||||
|
||||
this._parser = null;
|
||||
this._flushing = 0;
|
||||
this._fieldsSize = 0;
|
||||
};
|
||||
util.inherits(IncomingForm, EventEmitter);
|
||||
exports.IncomingForm = IncomingForm;
|
||||
|
||||
IncomingForm.UPLOAD_DIR = (function() {
|
||||
var dirs = [process.env.TMP, '/tmp', process.cwd()];
|
||||
for (var i = 0; i < dirs.length; i++) {
|
||||
var dir = dirs[i];
|
||||
var isDirectory = false;
|
||||
|
||||
try {
|
||||
isDirectory = fs.statSync(dir).isDirectory();
|
||||
} catch (e) {}
|
||||
|
||||
if (isDirectory) return dir;
|
||||
}
|
||||
})();
|
||||
|
||||
IncomingForm.prototype.parse = function(req, cb) {
|
||||
this.pause = function() {
|
||||
try {
|
||||
req.pause();
|
||||
} catch (err) {
|
||||
// the stream was destroyed
|
||||
if (!this.ended) {
|
||||
// before it was completed, crash & burn
|
||||
this._error(err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
this.resume = function() {
|
||||
try {
|
||||
req.resume();
|
||||
} catch (err) {
|
||||
// the stream was destroyed
|
||||
if (!this.ended) {
|
||||
// before it was completed, crash & burn
|
||||
this._error(err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
this.writeHeaders(req.headers);
|
||||
|
||||
var self = this;
|
||||
req
|
||||
.on('error', function(err) {
|
||||
self._error(err);
|
||||
})
|
||||
.on('aborted', function() {
|
||||
self.emit('aborted');
|
||||
})
|
||||
.on('data', function(buffer) {
|
||||
self.write(buffer);
|
||||
})
|
||||
.on('end', function() {
|
||||
if (self.error) {
|
||||
return;
|
||||
}
|
||||
|
||||
var err = self._parser.end();
|
||||
if (err) {
|
||||
self._error(err);
|
||||
}
|
||||
});
|
||||
|
||||
if (cb) {
|
||||
var fields = {}, files = {};
|
||||
this
|
||||
.on('field', function(name, value) {
|
||||
fields[name] = value;
|
||||
})
|
||||
.on('file', function(name, file) {
|
||||
files[name] = file;
|
||||
})
|
||||
.on('error', function(err) {
|
||||
cb(err, fields, files);
|
||||
})
|
||||
.on('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;
|
||||
}
|
||||
|
||||
this.bytesReceived += buffer.length;
|
||||
this.emit('progress', this.bytesReceived, this.bytesExpected);
|
||||
|
||||
var bytesParsed = this._parser.write(buffer);
|
||||
if (bytesParsed !== buffer.length) {
|
||||
this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed'));
|
||||
}
|
||||
|
||||
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 === undefined) {
|
||||
var value = ''
|
||||
, decoder = new StringDecoder(this.encoding);
|
||||
|
||||
part.on('data', function(buffer) {
|
||||
self._fieldsSize += buffer.length;
|
||||
if (self._fieldsSize > self.maxFieldsSize) {
|
||||
self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data'));
|
||||
return;
|
||||
}
|
||||
value += decoder.write(buffer);
|
||||
});
|
||||
|
||||
part.on('end', function() {
|
||||
self.emit('field', part.name, value);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this._flushing++;
|
||||
|
||||
var file = new File({
|
||||
path: this._uploadPath(part.filename),
|
||||
name: part.filename,
|
||||
type: part.mime,
|
||||
hash: self.hash
|
||||
});
|
||||
|
||||
this.emit('fileBegin', part.name, file);
|
||||
|
||||
file.open();
|
||||
|
||||
part.on('data', function(buffer) {
|
||||
self.pause();
|
||||
file.write(buffer, function() {
|
||||
self.resume();
|
||||
});
|
||||
});
|
||||
|
||||
part.on('end', function() {
|
||||
file.end(function() {
|
||||
self._flushing--;
|
||||
self.emit('file', part.name, file);
|
||||
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] || m[2]);
|
||||
} 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);
|
||||
this.emit('progress', this.bytesReceived, this.bytesExpected);
|
||||
}
|
||||
};
|
||||
|
||||
IncomingForm.prototype._newParser = function() {
|
||||
return new MultipartParser();
|
||||
};
|
||||
|
||||
IncomingForm.prototype._initMultipart = function(boundary) {
|
||||
this.type = 'multipart';
|
||||
|
||||
var parser = new MultipartParser(),
|
||||
self = this,
|
||||
headerField,
|
||||
headerValue,
|
||||
part;
|
||||
|
||||
parser.initWithBoundary(boundary);
|
||||
|
||||
parser.onPartBegin = function() {
|
||||
part = new Stream();
|
||||
part.readable = true;
|
||||
part.headers = {};
|
||||
part.name = null;
|
||||
part.filename = null;
|
||||
part.mime = null;
|
||||
headerField = '';
|
||||
headerValue = '';
|
||||
};
|
||||
|
||||
parser.onHeaderField = function(b, start, end) {
|
||||
headerField += b.toString(self.encoding, start, end);
|
||||
};
|
||||
|
||||
parser.onHeaderValue = function(b, start, end) {
|
||||
headerValue += b.toString(self.encoding, start, end);
|
||||
};
|
||||
|
||||
parser.onHeaderEnd = function() {
|
||||
headerField = headerField.toLowerCase();
|
||||
part.headers[headerField] = headerValue;
|
||||
|
||||
var m;
|
||||
if (headerField == 'content-disposition') {
|
||||
if (m = headerValue.match(/name="([^"]+)"/i)) {
|
||||
part.name = m[1];
|
||||
}
|
||||
|
||||
part.filename = self._fileName(headerValue);
|
||||
} else if (headerField == 'content-type') {
|
||||
part.mime = headerValue;
|
||||
}
|
||||
|
||||
headerField = '';
|
||||
headerValue = '';
|
||||
};
|
||||
|
||||
parser.onHeadersEnd = function() {
|
||||
self.onPart(part);
|
||||
};
|
||||
|
||||
parser.onPartData = function(b, start, end) {
|
||||
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._fileName = function(headerValue) {
|
||||
var m = headerValue.match(/filename="(.*?)"($|; )/i)
|
||||
if (!m) return;
|
||||
|
||||
var filename = m[1].substr(m[1].lastIndexOf('\\') + 1);
|
||||
filename = filename.replace(/%22/g, '"');
|
||||
filename = filename.replace(/&#([\d]{4});/g, function(m, code) {
|
||||
return String.fromCharCode(code);
|
||||
});
|
||||
return filename;
|
||||
};
|
||||
|
||||
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 (var i = 0; i < 32; i++) {
|
||||
name += Math.floor(Math.random() * 16).toString(16);
|
||||
}
|
||||
|
||||
if (this.keepExtensions) {
|
||||
var ext = path.extname(filename);
|
||||
ext = ext.replace(/(\.[a-z0-9]+).*/, '$1')
|
||||
|
||||
name += ext;
|
||||
}
|
||||
|
||||
return path.join(this.uploadDir, name);
|
||||
};
|
||||
|
||||
IncomingForm.prototype._maybeEnd = function() {
|
||||
if (!this.ended || this._flushing) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.emit('end');
|
||||
};
|
||||
3
node_modules/formidable/lib/index.js
generated
vendored
Normal file
3
node_modules/formidable/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
var IncomingForm = require('./incoming_form').IncomingForm;
|
||||
IncomingForm.IncomingForm = IncomingForm;
|
||||
module.exports = IncomingForm;
|
||||
312
node_modules/formidable/lib/multipart_parser.js
generated
vendored
Normal file
312
node_modules/formidable/lib/multipart_parser.js
generated
vendored
Normal file
@@ -0,0 +1,312 @@
|
||||
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.stateToString = function(stateNumber) {
|
||||
for (var state in S) {
|
||||
var number = S[state];
|
||||
if (number === stateNumber) return state;
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
callback('headerEnd');
|
||||
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;
|
||||
}
|
||||
|
||||
callback('headersEnd');
|
||||
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
|
||||
i += boundaryEnd;
|
||||
while (i < bufferLength && !(buffer[i] in boundaryChars)) {
|
||||
i += boundaryLength;
|
||||
}
|
||||
i -= boundaryEnd;
|
||||
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) {
|
||||
callback('partEnd');
|
||||
callback('end');
|
||||
state = S.END;
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
case S.END:
|
||||
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: ' + this.explain());
|
||||
}
|
||||
};
|
||||
|
||||
MultipartParser.prototype.explain = function() {
|
||||
return 'state = ' + MultipartParser.stateToString(this.state);
|
||||
};
|
||||
25
node_modules/formidable/lib/querystring_parser.js
generated
vendored
Normal file
25
node_modules/formidable/lib/querystring_parser.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
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();
|
||||
};
|
||||
6
node_modules/formidable/lib/util.js
generated
vendored
Normal file
6
node_modules/formidable/lib/util.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// Backwards compatibility ...
|
||||
try {
|
||||
module.exports = require('util');
|
||||
} catch (e) {
|
||||
module.exports = require('sys');
|
||||
}
|
||||
4
node_modules/formidable/node-gently/Makefile
generated
vendored
Normal file
4
node_modules/formidable/node-gently/Makefile
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
test:
|
||||
@find test/simple/test-*.js | xargs -n 1 -t node
|
||||
|
||||
.PHONY: test
|
||||
167
node_modules/formidable/node-gently/Readme.md
generated
vendored
Normal file
167
node_modules/formidable/node-gently/Readme.md
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
# Gently
|
||||
|
||||
## Purpose
|
||||
|
||||
A node.js module that helps with stubbing and behavior verification. It allows you to test the most remote and nested corners of your code while keeping being fully unobtrusive.
|
||||
|
||||
## Features
|
||||
|
||||
* Overwrite and stub individual object functions
|
||||
* Verify that all expected calls have been made in the expected order
|
||||
* Restore stubbed functions to their original behavior
|
||||
* Detect object / class names from obj.constructor.name and obj.toString()
|
||||
* Hijack any required module function or class constructor
|
||||
|
||||
## Installation
|
||||
|
||||
Via [npm](http://github.com/isaacs/npm):
|
||||
|
||||
npm install gently@latest
|
||||
|
||||
## Example
|
||||
|
||||
Make sure your dog is working properly:
|
||||
|
||||
function Dog() {}
|
||||
|
||||
Dog.prototype.seeCat = function() {
|
||||
this.bark('whuf, whuf');
|
||||
this.run();
|
||||
}
|
||||
|
||||
Dog.prototype.bark = function(bark) {
|
||||
require('sys').puts(bark);
|
||||
}
|
||||
|
||||
var gently = new (require('gently'))
|
||||
, assert = require('assert')
|
||||
, dog = new Dog();
|
||||
|
||||
gently.expect(dog, 'bark', function(bark) {
|
||||
assert.equal(bark, 'whuf, whuf');
|
||||
});
|
||||
gently.expect(dog, 'run');
|
||||
|
||||
dog.seeCat();
|
||||
|
||||
You can also easily test event emitters with this, for example a simple sequence of 2 events emitted by `fs.WriteStream`:
|
||||
|
||||
var gently = new (require('gently'))
|
||||
, stream = new (require('fs').WriteStream)('my_file.txt');
|
||||
|
||||
gently.expect(stream, 'emit', function(event) {
|
||||
assert.equal(event, 'open');
|
||||
});
|
||||
|
||||
gently.expect(stream, 'emit', function(event) {
|
||||
assert.equal(event, 'drain');
|
||||
});
|
||||
|
||||
For a full read world example, check out this test case: [test-incoming-form.js](http://github.com/felixge/node-formidable/blob/master/test/simple/test-incoming-form.js) (in [node-formdiable](http://github.com/felixge/node-formidable)).
|
||||
|
||||
## API
|
||||
|
||||
### Gently
|
||||
|
||||
#### new Gently()
|
||||
|
||||
Creates a new gently instance. It listens to the process `'exit'` event to make sure all expectations have been verified.
|
||||
|
||||
#### gently.expect(obj, method, [[count], stubFn])
|
||||
|
||||
Creates an expectation for an objects method to be called. You can optionally specify the call `count` you are expecting, as well as `stubFn` function that will run instead of the original function.
|
||||
|
||||
Returns a reference to the function that is getting overwritten.
|
||||
|
||||
#### gently.expect([count], stubFn)
|
||||
|
||||
Returns a function that is supposed to be executed `count` times, delegating any calls to the provided `stubFn` function. Naming your stubFn closure will help to properly diagnose errors that are being thrown:
|
||||
|
||||
childProcess.exec('ls', gently.expect(function lsCallback(code) {
|
||||
assert.equal(0, code);
|
||||
}));
|
||||
|
||||
#### gently.restore(obj, method)
|
||||
|
||||
Restores an object method that has been previously overwritten using `gently.expect()`.
|
||||
|
||||
#### gently.hijack(realRequire)
|
||||
|
||||
Returns a new require functions that catches a reference to all required modules into `gently.hijacked`.
|
||||
|
||||
To use this function, include a line like this in your `'my-module.js'`.
|
||||
|
||||
if (global.GENTLY) require = GENTLY.hijack(require);
|
||||
|
||||
var sys = require('sys');
|
||||
exports.hello = function() {
|
||||
sys.log('world');
|
||||
};
|
||||
|
||||
Now you can write a test for the module above:
|
||||
|
||||
var gently = global.GENTLY = new (require('gently'))
|
||||
, myModule = require('./my-module');
|
||||
|
||||
gently.expect(gently.hijacked.sys, 'log', function(str) {
|
||||
assert.equal(str, 'world');
|
||||
});
|
||||
|
||||
myModule.hello();
|
||||
|
||||
#### gently.stub(location, [exportsName])
|
||||
|
||||
Returns a stub class that will be used instead of the real class from the module at `location` with the given `exportsName`.
|
||||
|
||||
This allows to test an OOP version of the previous example, where `'my-module.js'`.
|
||||
|
||||
if (global.GENTLY) require = GENTLY.hijack(require);
|
||||
|
||||
var World = require('./world');
|
||||
|
||||
exports.hello = function() {
|
||||
var world = new World();
|
||||
world.hello();
|
||||
}
|
||||
|
||||
And `world.js` looks like this:
|
||||
|
||||
var sys = require('sys');
|
||||
|
||||
function World() {
|
||||
|
||||
}
|
||||
module.exports = World;
|
||||
|
||||
World.prototype.hello = function() {
|
||||
sys.log('world');
|
||||
};
|
||||
|
||||
Testing `'my-module.js'` can now easily be accomplished:
|
||||
|
||||
var gently = global.GENTLY = new (require('gently'))
|
||||
, WorldStub = gently.stub('./world')
|
||||
, myModule = require('./my-module')
|
||||
, WORLD;
|
||||
|
||||
gently.expect(WorldStub, 'new', function() {
|
||||
WORLD = this;
|
||||
});
|
||||
|
||||
gently.expect(WORLD, 'hello');
|
||||
|
||||
myModule.hello();
|
||||
|
||||
#### gently.hijacked
|
||||
|
||||
An object that holds the references to all hijacked modules.
|
||||
|
||||
#### gently.verify([msg])
|
||||
|
||||
Verifies that all expectations of this gently instance have been satisfied. If not called manually, this method is called when the process `'exit'` event is fired.
|
||||
|
||||
If `msg` is given, it will appear in any error that might be thrown.
|
||||
|
||||
## License
|
||||
|
||||
Gently is licensed under the MIT license.
|
||||
22
node_modules/formidable/node-gently/example/dog.js
generated
vendored
Normal file
22
node_modules/formidable/node-gently/example/dog.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
require('../test/common');
|
||||
function Dog() {}
|
||||
|
||||
Dog.prototype.seeCat = function() {
|
||||
this.bark('whuf, whuf');
|
||||
this.run();
|
||||
}
|
||||
|
||||
Dog.prototype.bark = function(bark) {
|
||||
require('sys').puts(bark);
|
||||
}
|
||||
|
||||
var gently = new (require('gently'))
|
||||
, assert = require('assert')
|
||||
, dog = new Dog();
|
||||
|
||||
gently.expect(dog, 'bark', function(bark) {
|
||||
assert.equal(bark, 'whuf, whuf');
|
||||
});
|
||||
gently.expect(dog, 'run');
|
||||
|
||||
dog.seeCat();
|
||||
11
node_modules/formidable/node-gently/example/event_emitter.js
generated
vendored
Normal file
11
node_modules/formidable/node-gently/example/event_emitter.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
require('../test/common');
|
||||
var gently = new (require('gently'))
|
||||
, stream = new (require('fs').WriteStream)('my_file.txt');
|
||||
|
||||
gently.expect(stream, 'emit', function(event) {
|
||||
assert.equal(event, 'open');
|
||||
});
|
||||
|
||||
gently.expect(stream, 'emit', function(event) {
|
||||
assert.equal(event, 'drain');
|
||||
});
|
||||
1
node_modules/formidable/node-gently/index.js
generated
vendored
Normal file
1
node_modules/formidable/node-gently/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib/gently');
|
||||
184
node_modules/formidable/node-gently/lib/gently/gently.js
generated
vendored
Normal file
184
node_modules/formidable/node-gently/lib/gently/gently.js
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
var path = require('path');
|
||||
|
||||
function Gently() {
|
||||
this.expectations = [];
|
||||
this.hijacked = {};
|
||||
|
||||
var self = this;
|
||||
process.addListener('exit', function() {
|
||||
self.verify('process exit');
|
||||
});
|
||||
};
|
||||
module.exports = Gently;
|
||||
|
||||
Gently.prototype.stub = function(location, exportsName) {
|
||||
function Stub() {
|
||||
return Stub['new'].apply(this, arguments);
|
||||
};
|
||||
|
||||
Stub['new'] = function () {};
|
||||
|
||||
var stubName = 'require('+JSON.stringify(location)+')';
|
||||
if (exportsName) {
|
||||
stubName += '.'+exportsName;
|
||||
}
|
||||
|
||||
Stub.prototype.toString = Stub.toString = function() {
|
||||
return stubName;
|
||||
};
|
||||
|
||||
var exports = this.hijacked[location] || {};
|
||||
if (exportsName) {
|
||||
exports[exportsName] = Stub;
|
||||
} else {
|
||||
exports = Stub;
|
||||
}
|
||||
|
||||
this.hijacked[location] = exports;
|
||||
return Stub;
|
||||
};
|
||||
|
||||
Gently.prototype.hijack = function(realRequire) {
|
||||
var self = this;
|
||||
return function(location) {
|
||||
return self.hijacked[location] = (self.hijacked[location])
|
||||
? self.hijacked[location]
|
||||
: realRequire(location);
|
||||
};
|
||||
};
|
||||
|
||||
Gently.prototype.expect = function(obj, method, count, stubFn) {
|
||||
if (typeof obj != 'function' && typeof obj != 'object' && typeof obj != 'number') {
|
||||
throw new Error
|
||||
( 'Bad 1st argument for gently.expect(), '
|
||||
+ 'object, function, or number expected, got: '+(typeof obj)
|
||||
);
|
||||
} else if (typeof obj == 'function' && (typeof method != 'string')) {
|
||||
// expect(stubFn) interface
|
||||
stubFn = obj;
|
||||
obj = null;
|
||||
method = null;
|
||||
count = 1;
|
||||
} else if (typeof method == 'function') {
|
||||
// expect(count, stubFn) interface
|
||||
count = obj;
|
||||
stubFn = method;
|
||||
obj = null;
|
||||
method = null;
|
||||
} else if (typeof count == 'function') {
|
||||
// expect(obj, method, stubFn) interface
|
||||
stubFn = count;
|
||||
count = 1;
|
||||
} else if (count === undefined) {
|
||||
// expect(obj, method) interface
|
||||
count = 1;
|
||||
}
|
||||
|
||||
var name = this._name(obj, method, stubFn);
|
||||
this.expectations.push({obj: obj, method: method, stubFn: stubFn, name: name, count: count});
|
||||
|
||||
var self = this;
|
||||
function delegate() {
|
||||
return self._stubFn(this, obj, method, name, Array.prototype.slice.call(arguments));
|
||||
}
|
||||
|
||||
if (!obj) {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
var original = (obj[method])
|
||||
? obj[method]._original || obj[method]
|
||||
: undefined;
|
||||
|
||||
obj[method] = delegate;
|
||||
return obj[method]._original = original;
|
||||
};
|
||||
|
||||
Gently.prototype.restore = function(obj, method) {
|
||||
if (!obj[method] || !obj[method]._original) {
|
||||
throw new Error(this._name(obj, method)+' is not gently stubbed');
|
||||
}
|
||||
obj[method] = obj[method]._original;
|
||||
};
|
||||
|
||||
Gently.prototype.verify = function(msg) {
|
||||
if (!this.expectations.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var validExpectations = [];
|
||||
for (var i = 0, l = this.expectations.length; i < l; i++) {
|
||||
var expectation = this.expectations[i];
|
||||
|
||||
if (expectation.count > 0) {
|
||||
validExpectations.push(expectation);
|
||||
}
|
||||
}
|
||||
|
||||
this.expectations = []; // reset so that no duplicate verification attempts are made
|
||||
|
||||
if (!validExpectations.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var expectation = validExpectations[0];
|
||||
|
||||
throw new Error
|
||||
( 'Expected call to '+expectation.name+' did not happen'
|
||||
+ ( (msg)
|
||||
? ' ('+msg+')'
|
||||
: ''
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
Gently.prototype._stubFn = function(self, obj, method, name, args) {
|
||||
var expectation = this.expectations[0], obj, method;
|
||||
|
||||
if (!expectation) {
|
||||
throw new Error('Unexpected call to '+name+', no call was expected');
|
||||
}
|
||||
|
||||
if (expectation.obj !== obj || expectation.method !== method) {
|
||||
throw new Error('Unexpected call to '+name+', expected call to '+ expectation.name);
|
||||
}
|
||||
|
||||
expectation.count -= 1;
|
||||
if (expectation.count === 0) {
|
||||
this.expectations.shift();
|
||||
|
||||
// autorestore original if its not a closure
|
||||
// and no more expectations on that object
|
||||
var has_more_expectations = this.expectations.reduce(function (memo, expectation) {
|
||||
return memo || (expectation.obj === obj && expectation.method === method);
|
||||
}, false);
|
||||
if (obj !== null && method !== null && !has_more_expectations) {
|
||||
if (typeof obj[method]._original !== 'undefined') {
|
||||
obj[method] = obj[method]._original;
|
||||
delete obj[method]._original;
|
||||
} else {
|
||||
delete obj[method];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (expectation.stubFn) {
|
||||
return expectation.stubFn.apply(self, args);
|
||||
}
|
||||
};
|
||||
|
||||
Gently.prototype._name = function(obj, method, stubFn) {
|
||||
if (obj) {
|
||||
var objectName = obj.toString();
|
||||
if (objectName == '[object Object]' && obj.constructor.name) {
|
||||
objectName = '['+obj.constructor.name+']';
|
||||
}
|
||||
return (objectName)+'.'+method+'()';
|
||||
}
|
||||
|
||||
if (stubFn.name) {
|
||||
return stubFn.name+'()';
|
||||
}
|
||||
|
||||
return '>> '+stubFn.toString()+' <<';
|
||||
};
|
||||
1
node_modules/formidable/node-gently/lib/gently/index.js
generated
vendored
Normal file
1
node_modules/formidable/node-gently/lib/gently/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('./gently');
|
||||
14
node_modules/formidable/node-gently/package.json
generated
vendored
Normal file
14
node_modules/formidable/node-gently/package.json
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "gently",
|
||||
"version": "0.9.2",
|
||||
"directories": {
|
||||
"lib": "./lib/gently"
|
||||
},
|
||||
"main": "./lib/gently/index",
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"optionalDependencies": {}
|
||||
}
|
||||
8
node_modules/formidable/node-gently/test/common.js
generated
vendored
Normal file
8
node_modules/formidable/node-gently/test/common.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
var path = require('path')
|
||||
, sys = require('sys');
|
||||
|
||||
require.paths.unshift(path.dirname(__dirname)+'/lib');
|
||||
|
||||
global.puts = sys.puts;
|
||||
global.p = function() {sys.error(sys.inspect.apply(null, arguments))};;
|
||||
global.assert = require('assert');
|
||||
348
node_modules/formidable/node-gently/test/simple/test-gently.js
generated
vendored
Normal file
348
node_modules/formidable/node-gently/test/simple/test-gently.js
generated
vendored
Normal file
@@ -0,0 +1,348 @@
|
||||
require('../common');
|
||||
var Gently = require('gently')
|
||||
, gently;
|
||||
|
||||
function test(test) {
|
||||
process.removeAllListeners('exit');
|
||||
gently = new Gently();
|
||||
test();
|
||||
}
|
||||
|
||||
test(function constructor() {
|
||||
assert.deepEqual(gently.expectations, []);
|
||||
assert.deepEqual(gently.hijacked, {});
|
||||
assert.equal(gently.constructor.name, 'Gently');
|
||||
});
|
||||
|
||||
test(function expectBadArgs() {
|
||||
var BAD_ARG = 'oh no';
|
||||
try {
|
||||
gently.expect(BAD_ARG);
|
||||
assert.ok(false, 'throw needs to happen');
|
||||
} catch (e) {
|
||||
assert.equal(e.message, 'Bad 1st argument for gently.expect(), object, function, or number expected, got: '+(typeof BAD_ARG));
|
||||
}
|
||||
});
|
||||
|
||||
test(function expectObjMethod() {
|
||||
var OBJ = {}, NAME = 'foobar';
|
||||
OBJ.foo = function(x) {
|
||||
return x;
|
||||
};
|
||||
|
||||
gently._name = function() {
|
||||
return NAME;
|
||||
};
|
||||
|
||||
var original = OBJ.foo
|
||||
, stubFn = function() {};
|
||||
|
||||
(function testAddOne() {
|
||||
assert.strictEqual(gently.expect(OBJ, 'foo', stubFn), original);
|
||||
|
||||
assert.equal(gently.expectations.length, 1);
|
||||
var expectation = gently.expectations[0];
|
||||
assert.strictEqual(expectation.obj, OBJ);
|
||||
assert.strictEqual(expectation.method, 'foo');
|
||||
assert.strictEqual(expectation.stubFn, stubFn);
|
||||
assert.strictEqual(expectation.name, NAME);
|
||||
assert.strictEqual(OBJ.foo._original, original);
|
||||
})();
|
||||
|
||||
(function testAddTwo() {
|
||||
gently.expect(OBJ, 'foo', 2, stubFn);
|
||||
assert.equal(gently.expectations.length, 2);
|
||||
assert.strictEqual(OBJ.foo._original, original);
|
||||
})();
|
||||
|
||||
(function testAddOneWithoutMock() {
|
||||
gently.expect(OBJ, 'foo');
|
||||
assert.equal(gently.expectations.length, 3);
|
||||
})();
|
||||
|
||||
var stubFnCalled = 0, SELF = {};
|
||||
gently._stubFn = function(self, obj, method, name, args) {
|
||||
stubFnCalled++;
|
||||
assert.strictEqual(self, SELF);
|
||||
assert.strictEqual(obj, OBJ);
|
||||
assert.strictEqual(method, 'foo');
|
||||
assert.strictEqual(name, NAME);
|
||||
assert.deepEqual(args, [1, 2]);
|
||||
return 23;
|
||||
};
|
||||
assert.equal(OBJ.foo.apply(SELF, [1, 2]), 23);
|
||||
assert.equal(stubFnCalled, 1);
|
||||
});
|
||||
|
||||
test(function expectClosure() {
|
||||
var NAME = 'MY CLOSURE';
|
||||
function closureFn() {};
|
||||
|
||||
gently._name = function() {
|
||||
return NAME;
|
||||
};
|
||||
|
||||
var fn = gently.expect(closureFn);
|
||||
assert.equal(gently.expectations.length, 1);
|
||||
var expectation = gently.expectations[0];
|
||||
assert.strictEqual(expectation.obj, null);
|
||||
assert.strictEqual(expectation.method, null);
|
||||
assert.strictEqual(expectation.stubFn, closureFn);
|
||||
assert.strictEqual(expectation.name, NAME);
|
||||
|
||||
var stubFnCalled = 0, SELF = {};
|
||||
gently._stubFn = function(self, obj, method, name, args) {
|
||||
stubFnCalled++;
|
||||
assert.strictEqual(self, SELF);
|
||||
assert.strictEqual(obj, null);
|
||||
assert.strictEqual(method, null);
|
||||
assert.strictEqual(name, NAME);
|
||||
assert.deepEqual(args, [1, 2]);
|
||||
return 23;
|
||||
};
|
||||
assert.equal(fn.apply(SELF, [1, 2]), 23);
|
||||
assert.equal(stubFnCalled, 1);
|
||||
});
|
||||
|
||||
test(function expectClosureCount() {
|
||||
var stubFnCalled = 0;
|
||||
function closureFn() {stubFnCalled++};
|
||||
|
||||
var fn = gently.expect(2, closureFn);
|
||||
assert.equal(gently.expectations.length, 1);
|
||||
fn();
|
||||
assert.equal(gently.expectations.length, 1);
|
||||
fn();
|
||||
assert.equal(stubFnCalled, 2);
|
||||
});
|
||||
|
||||
test(function restore() {
|
||||
var OBJ = {}, NAME = '[my object].myFn()';
|
||||
OBJ.foo = function(x) {
|
||||
return x;
|
||||
};
|
||||
|
||||
gently._name = function() {
|
||||
return NAME;
|
||||
};
|
||||
|
||||
var original = OBJ.foo;
|
||||
gently.expect(OBJ, 'foo');
|
||||
gently.restore(OBJ, 'foo');
|
||||
assert.strictEqual(OBJ.foo, original);
|
||||
|
||||
(function testError() {
|
||||
try {
|
||||
gently.restore(OBJ, 'foo');
|
||||
assert.ok(false, 'throw needs to happen');
|
||||
} catch (e) {
|
||||
assert.equal(e.message, NAME+' is not gently stubbed');
|
||||
}
|
||||
})();
|
||||
});
|
||||
|
||||
test(function _stubFn() {
|
||||
var OBJ1 = {toString: function() {return '[OBJ 1]'}}
|
||||
, OBJ2 = {toString: function() {return '[OBJ 2]'}, foo: function () {return 'bar';}}
|
||||
, SELF = {};
|
||||
|
||||
gently.expect(OBJ1, 'foo', function(x) {
|
||||
assert.strictEqual(this, SELF);
|
||||
return x * 2;
|
||||
});
|
||||
|
||||
assert.equal(gently._stubFn(SELF, OBJ1, 'foo', 'dummy_name', [5]), 10);
|
||||
|
||||
(function testAutorestore() {
|
||||
assert.equal(OBJ2.foo(), 'bar');
|
||||
|
||||
gently.expect(OBJ2, 'foo', function() {
|
||||
return 'stubbed foo';
|
||||
});
|
||||
|
||||
gently.expect(OBJ2, 'foo', function() {
|
||||
return "didn't restore yet";
|
||||
});
|
||||
|
||||
assert.equal(gently._stubFn(SELF, OBJ2, 'foo', 'dummy_name', []), 'stubbed foo');
|
||||
assert.equal(gently._stubFn(SELF, OBJ2, 'foo', 'dummy_name', []), "didn't restore yet");
|
||||
assert.equal(OBJ2.foo(), 'bar');
|
||||
assert.deepEqual(gently.expectations, []);
|
||||
})();
|
||||
|
||||
(function testNoMoreCallExpected() {
|
||||
try {
|
||||
gently._stubFn(SELF, OBJ1, 'foo', 'dummy_name', [5]);
|
||||
assert.ok(false, 'throw needs to happen');
|
||||
} catch (e) {
|
||||
assert.equal(e.message, 'Unexpected call to dummy_name, no call was expected');
|
||||
}
|
||||
})();
|
||||
|
||||
(function testDifferentCallExpected() {
|
||||
gently.expect(OBJ2, 'bar');
|
||||
try {
|
||||
gently._stubFn(SELF, OBJ1, 'foo', 'dummy_name', [5]);
|
||||
assert.ok(false, 'throw needs to happen');
|
||||
} catch (e) {
|
||||
assert.equal(e.message, 'Unexpected call to dummy_name, expected call to '+gently._name(OBJ2, 'bar'));
|
||||
}
|
||||
|
||||
assert.equal(gently.expectations.length, 1);
|
||||
})();
|
||||
|
||||
(function testNoMockCallback() {
|
||||
OBJ2.bar();
|
||||
assert.equal(gently.expectations.length, 0);
|
||||
})();
|
||||
});
|
||||
|
||||
test(function stub() {
|
||||
var LOCATION = './my_class';
|
||||
|
||||
(function testRegular() {
|
||||
var Stub = gently.stub(LOCATION);
|
||||
assert.ok(Stub instanceof Function);
|
||||
assert.strictEqual(gently.hijacked[LOCATION], Stub);
|
||||
assert.ok(Stub['new'] instanceof Function);
|
||||
assert.equal(Stub.toString(), 'require('+JSON.stringify(LOCATION)+')');
|
||||
|
||||
(function testConstructor() {
|
||||
var newCalled = 0
|
||||
, STUB
|
||||
, ARGS = ['foo', 'bar'];
|
||||
|
||||
Stub['new'] = function(a, b) {
|
||||
assert.equal(a, ARGS[0]);
|
||||
assert.equal(b, ARGS[1]);
|
||||
newCalled++;
|
||||
STUB = this;
|
||||
};
|
||||
|
||||
var stub = new Stub(ARGS[0], ARGS[1]);
|
||||
assert.strictEqual(stub, STUB);
|
||||
assert.equal(newCalled, 1);
|
||||
assert.equal(stub.toString(), 'require('+JSON.stringify(LOCATION)+')');
|
||||
})();
|
||||
|
||||
(function testUseReturnValueAsInstance() {
|
||||
var R = {};
|
||||
|
||||
Stub['new'] = function() {
|
||||
return R;
|
||||
};
|
||||
|
||||
var stub = new Stub();
|
||||
assert.strictEqual(stub, R);
|
||||
|
||||
})();
|
||||
})();
|
||||
|
||||
var EXPORTS_NAME = 'MyClass';
|
||||
test(function testExportsName() {
|
||||
var Stub = gently.stub(LOCATION, EXPORTS_NAME);
|
||||
assert.strictEqual(gently.hijacked[LOCATION][EXPORTS_NAME], Stub);
|
||||
assert.equal(Stub.toString(), 'require('+JSON.stringify(LOCATION)+').'+EXPORTS_NAME);
|
||||
|
||||
(function testConstructor() {
|
||||
var stub = new Stub();
|
||||
assert.equal(Stub.toString(), 'require('+JSON.stringify(LOCATION)+').'+EXPORTS_NAME);
|
||||
})();
|
||||
});
|
||||
});
|
||||
|
||||
test(function hijack() {
|
||||
var LOCATION = './foo'
|
||||
, REQUIRE_CALLS = 0
|
||||
, EXPORTS = {}
|
||||
, REQUIRE = function() {
|
||||
REQUIRE_CALLS++;
|
||||
return EXPORTS;
|
||||
};
|
||||
|
||||
var hijackedRequire = gently.hijack(REQUIRE);
|
||||
hijackedRequire(LOCATION);
|
||||
assert.strictEqual(gently.hijacked[LOCATION], EXPORTS);
|
||||
|
||||
assert.equal(REQUIRE_CALLS, 1);
|
||||
|
||||
// make sure we are caching the hijacked module
|
||||
hijackedRequire(LOCATION);
|
||||
assert.equal(REQUIRE_CALLS, 1);
|
||||
});
|
||||
|
||||
test(function verify() {
|
||||
var OBJ = {toString: function() {return '[OBJ]'}};
|
||||
gently.verify();
|
||||
|
||||
gently.expect(OBJ, 'foo');
|
||||
try {
|
||||
gently.verify();
|
||||
assert.ok(false, 'throw needs to happen');
|
||||
} catch (e) {
|
||||
assert.equal(e.message, 'Expected call to [OBJ].foo() did not happen');
|
||||
}
|
||||
|
||||
try {
|
||||
gently.verify('foo');
|
||||
assert.ok(false, 'throw needs to happen');
|
||||
} catch (e) {
|
||||
assert.equal(e.message, 'Expected call to [OBJ].foo() did not happen (foo)');
|
||||
}
|
||||
});
|
||||
|
||||
test(function processExit() {
|
||||
var verifyCalled = 0;
|
||||
gently.verify = function(msg) {
|
||||
verifyCalled++;
|
||||
assert.equal(msg, 'process exit');
|
||||
};
|
||||
|
||||
process.emit('exit');
|
||||
assert.equal(verifyCalled, 1);
|
||||
});
|
||||
|
||||
test(function _name() {
|
||||
(function testNamedClass() {
|
||||
function Foo() {};
|
||||
var foo = new Foo();
|
||||
assert.equal(gently._name(foo, 'bar'), '[Foo].bar()');
|
||||
})();
|
||||
|
||||
(function testToStringPreference() {
|
||||
function Foo() {};
|
||||
Foo.prototype.toString = function() {
|
||||
return '[Superman 123]';
|
||||
};
|
||||
var foo = new Foo();
|
||||
assert.equal(gently._name(foo, 'bar'), '[Superman 123].bar()');
|
||||
})();
|
||||
|
||||
(function testUnamedClass() {
|
||||
var Foo = function() {};
|
||||
var foo = new Foo();
|
||||
assert.equal(gently._name(foo, 'bar'), foo.toString()+'.bar()');
|
||||
})();
|
||||
|
||||
(function testNamedClosure() {
|
||||
function myClosure() {};
|
||||
assert.equal(gently._name(null, null, myClosure), myClosure.name+'()');
|
||||
})();
|
||||
|
||||
(function testUnamedClosure() {
|
||||
var myClosure = function() {2+2 == 5};
|
||||
assert.equal(gently._name(null, null, myClosure), '>> '+myClosure.toString()+' <<');
|
||||
})();
|
||||
});
|
||||
|
||||
test(function verifyExpectNone() {
|
||||
var OBJ = {toString: function() {return '[OBJ]'}};
|
||||
gently.verify();
|
||||
|
||||
gently.expect(OBJ, 'foo', 0);
|
||||
try {
|
||||
gently.verify();
|
||||
} catch (e) {
|
||||
assert.fail('Exception should not have been thrown');
|
||||
}
|
||||
});
|
||||
28
node_modules/formidable/package.json
generated
vendored
Normal file
28
node_modules/formidable/package.json
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
19
node_modules/formidable/test/common.js
generated
vendored
Normal file
19
node_modules/formidable/test/common.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
var mysql = require('..');
|
||||
var path = require('path');
|
||||
|
||||
var root = path.join(__dirname, '../');
|
||||
exports.dir = {
|
||||
root : root,
|
||||
lib : root + '/lib',
|
||||
fixture : root + '/test/fixture',
|
||||
tmp : root + '/test/tmp',
|
||||
};
|
||||
|
||||
exports.port = 13532;
|
||||
|
||||
exports.formidable = require('..');
|
||||
exports.assert = require('assert');
|
||||
|
||||
exports.require = function(lib) {
|
||||
return require(exports.dir.lib + '/' + lib);
|
||||
};
|
||||
1
node_modules/formidable/test/fixture/file/funkyfilename.txt
generated
vendored
Normal file
1
node_modules/formidable/test/fixture/file/funkyfilename.txt
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
I am a text file with a funky name!
|
||||
1
node_modules/formidable/test/fixture/file/plain.txt
generated
vendored
Normal file
1
node_modules/formidable/test/fixture/file/plain.txt
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
I am a plain text file
|
||||
3
node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md
generated
vendored
Normal file
3
node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
* Opera does not allow submitting this file, it shows a warning to the
|
||||
user that the file could not be found instead. Tested in 9.8, 11.51 on OSX.
|
||||
Reported to Opera on 08.09.2011 (tracking email DSK-346009@bugs.opera.com).
|
||||
3
node_modules/formidable/test/fixture/js/no-filename.js
generated
vendored
Normal file
3
node_modules/formidable/test/fixture/js/no-filename.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports['generic.http'] = [
|
||||
{type: 'file', name: 'upload', filename: '', fixture: 'plain.txt'},
|
||||
];
|
||||
21
node_modules/formidable/test/fixture/js/special-chars-in-filename.js
generated
vendored
Normal file
21
node_modules/formidable/test/fixture/js/special-chars-in-filename.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
var properFilename = 'funkyfilename.txt';
|
||||
|
||||
function expect(filename) {
|
||||
return [
|
||||
{type: 'field', name: 'title', value: 'Weird filename'},
|
||||
{type: 'file', name: 'upload', filename: filename, fixture: properFilename},
|
||||
];
|
||||
};
|
||||
|
||||
var webkit = " ? % * | \" < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt";
|
||||
var ffOrIe = " ? % * | \" < > . ☃ ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt";
|
||||
|
||||
module.exports = {
|
||||
'osx-chrome-13.http' : expect(webkit),
|
||||
'osx-firefox-3.6.http' : expect(ffOrIe),
|
||||
'osx-safari-5.http' : expect(webkit),
|
||||
'xp-chrome-12.http' : expect(webkit),
|
||||
'xp-ie-7.http' : expect(ffOrIe),
|
||||
'xp-ie-8.http' : expect(ffOrIe),
|
||||
'xp-safari-5.http' : expect(webkit),
|
||||
};
|
||||
72
node_modules/formidable/test/fixture/multipart.js
generated
vendored
Normal file
72
node_modules/formidable/test/fixture/multipart.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
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['noTrailing\r\n'] =
|
||||
{ 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--',
|
||||
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,
|
||||
};
|
||||
89
node_modules/formidable/test/integration/test-fixtures.js
generated
vendored
Normal file
89
node_modules/formidable/test/integration/test-fixtures.js
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
var hashish = require('hashish');
|
||||
var fs = require('fs');
|
||||
var findit = require('findit');
|
||||
var path = require('path');
|
||||
var http = require('http');
|
||||
var net = require('net');
|
||||
var assert = require('assert');
|
||||
|
||||
var common = require('../common');
|
||||
var formidable = common.formidable;
|
||||
|
||||
var server = http.createServer();
|
||||
server.listen(common.port, findFixtures);
|
||||
|
||||
function findFixtures() {
|
||||
var fixtures = [];
|
||||
findit
|
||||
.sync(common.dir.fixture + '/js')
|
||||
.forEach(function(jsPath) {
|
||||
if (!/\.js$/.test(jsPath)) return;
|
||||
|
||||
var group = path.basename(jsPath, '.js');
|
||||
hashish.forEach(require(jsPath), function(fixture, name) {
|
||||
fixtures.push({
|
||||
name : group + '/' + name,
|
||||
fixture : fixture,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
testNext(fixtures);
|
||||
}
|
||||
|
||||
function testNext(fixtures) {
|
||||
var fixture = fixtures.shift();
|
||||
if (!fixture) return server.close();
|
||||
|
||||
var name = fixture.name;
|
||||
var fixture = fixture.fixture;
|
||||
|
||||
uploadFixture(name, function(err, parts) {
|
||||
if (err) throw err;
|
||||
|
||||
fixture.forEach(function(expectedPart, i) {
|
||||
var parsedPart = parts[i];
|
||||
assert.equal(parsedPart.type, expectedPart.type);
|
||||
assert.equal(parsedPart.name, expectedPart.name);
|
||||
|
||||
if (parsedPart.type === 'file') {
|
||||
var filename = parsedPart.value.name;
|
||||
assert.equal(filename, expectedPart.filename);
|
||||
}
|
||||
});
|
||||
|
||||
testNext(fixtures);
|
||||
});
|
||||
};
|
||||
|
||||
function uploadFixture(name, cb) {
|
||||
server.once('request', function(req, res) {
|
||||
var form = new formidable.IncomingForm();
|
||||
form.uploadDir = common.dir.tmp;
|
||||
form.parse(req);
|
||||
|
||||
function callback() {
|
||||
var realCallback = cb;
|
||||
cb = function() {};
|
||||
realCallback.apply(null, arguments);
|
||||
}
|
||||
|
||||
var parts = [];
|
||||
form
|
||||
.on('error', callback)
|
||||
.on('fileBegin', function(name, value) {
|
||||
parts.push({type: 'file', name: name, value: value});
|
||||
})
|
||||
.on('field', function(name, value) {
|
||||
parts.push({type: 'field', name: name, value: value});
|
||||
})
|
||||
.on('end', function() {
|
||||
callback(null, parts);
|
||||
});
|
||||
});
|
||||
|
||||
var socket = net.createConnection(common.port);
|
||||
var file = fs.createReadStream(common.dir.fixture + '/http/' + name);
|
||||
|
||||
file.pipe(socket);
|
||||
}
|
||||
24
node_modules/formidable/test/legacy/common.js
generated
vendored
Normal file
24
node_modules/formidable/test/legacy/common.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
var path = require('path'),
|
||||
fs = require('fs');
|
||||
|
||||
try {
|
||||
global.Gently = require('gently');
|
||||
} catch (e) {
|
||||
throw new Error('this test suite requires node-gently');
|
||||
}
|
||||
|
||||
exports.lib = path.join(__dirname, '../../lib');
|
||||
|
||||
global.GENTLY = new Gently();
|
||||
|
||||
global.assert = require('assert');
|
||||
global.TEST_PORT = 13532;
|
||||
global.TEST_FIXTURES = path.join(__dirname, '../fixture');
|
||||
global.TEST_TMP = path.join(__dirname, '../tmp');
|
||||
|
||||
// Stupid new feature in node that complains about gently attaching too many
|
||||
// listeners to process 'exit'. This is a workaround until I can think of a
|
||||
// better way to deal with this.
|
||||
if (process.setMaxListeners) {
|
||||
process.setMaxListeners(10000);
|
||||
}
|
||||
80
node_modules/formidable/test/legacy/integration/test-multipart-parser.js
generated
vendored
Normal file
80
node_modules/formidable/test/legacy/integration/test-multipart-parser.js
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
var common = require('../common');
|
||||
var CHUNK_LENGTH = 10,
|
||||
multipartParser = require(common.lib + '/multipart_parser'),
|
||||
MultipartParser = multipartParser.MultipartParser,
|
||||
parser = new MultipartParser(),
|
||||
fixtures = require(TEST_FIXTURES + '/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,
|
||||
headerValue,
|
||||
endCalled = '';
|
||||
|
||||
parser.initWithBoundary(fixture.boundary);
|
||||
parser.onPartBegin = function() {
|
||||
part = {headers: {}, data: ''};
|
||||
parts.push(part);
|
||||
headerField = '';
|
||||
headerValue = '';
|
||||
};
|
||||
|
||||
parser.onHeaderField = function(b, start, end) {
|
||||
headerField += b.toString('ascii', start, end);
|
||||
};
|
||||
|
||||
parser.onHeaderValue = function(b, start, end) {
|
||||
headerValue += b.toString('ascii', start, end);
|
||||
}
|
||||
|
||||
parser.onHeaderEnd = function() {
|
||||
part.headers[headerField] = headerValue;
|
||||
headerField = '';
|
||||
headerValue = '';
|
||||
};
|
||||
|
||||
parser.onPartData = function(b, start, end) {
|
||||
var str = b.toString('ascii', start, end);
|
||||
part.data += b.slice(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);
|
||||
});
|
||||
104
node_modules/formidable/test/legacy/simple/test-file.js
generated
vendored
Normal file
104
node_modules/formidable/test/legacy/simple/test-file.js
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
var common = require('../common');
|
||||
var WriteStreamStub = GENTLY.stub('fs', 'WriteStream');
|
||||
|
||||
var File = require(common.lib + '/file'),
|
||||
EventEmitter = require('events').EventEmitter,
|
||||
file,
|
||||
gently;
|
||||
|
||||
function test(test) {
|
||||
gently = new Gently();
|
||||
file = new File();
|
||||
test();
|
||||
gently.verify(test.name);
|
||||
}
|
||||
|
||||
test(function constructor() {
|
||||
assert.ok(file instanceof EventEmitter);
|
||||
assert.strictEqual(file.size, 0);
|
||||
assert.strictEqual(file.path, null);
|
||||
assert.strictEqual(file.name, null);
|
||||
assert.strictEqual(file.type, null);
|
||||
assert.strictEqual(file.lastModifiedDate, null);
|
||||
|
||||
assert.strictEqual(file._writeStream, null);
|
||||
|
||||
(function testSetProperties() {
|
||||
var file2 = new File({foo: 'bar'});
|
||||
assert.equal(file2.foo, 'bar');
|
||||
})();
|
||||
});
|
||||
|
||||
test(function open() {
|
||||
var WRITE_STREAM;
|
||||
file.path = '/foo';
|
||||
|
||||
gently.expect(WriteStreamStub, 'new', function (path) {
|
||||
WRITE_STREAM = this;
|
||||
assert.strictEqual(path, file.path);
|
||||
});
|
||||
|
||||
file.open();
|
||||
assert.strictEqual(file._writeStream, WRITE_STREAM);
|
||||
});
|
||||
|
||||
test(function write() {
|
||||
var BUFFER = {length: 10},
|
||||
CB_STUB,
|
||||
CB = function() {
|
||||
CB_STUB.apply(this, arguments);
|
||||
};
|
||||
|
||||
file._writeStream = {};
|
||||
|
||||
gently.expect(file._writeStream, 'write', function (buffer, cb) {
|
||||
assert.strictEqual(buffer, BUFFER);
|
||||
|
||||
gently.expect(file, 'emit', function (event, bytesWritten) {
|
||||
assert.ok(file.lastModifiedDate instanceof Date);
|
||||
assert.equal(event, 'progress');
|
||||
assert.equal(bytesWritten, file.size);
|
||||
});
|
||||
|
||||
CB_STUB = gently.expect(function writeCb() {
|
||||
assert.equal(file.size, 10);
|
||||
});
|
||||
|
||||
cb();
|
||||
|
||||
gently.expect(file, 'emit', function (event, bytesWritten) {
|
||||
assert.equal(event, 'progress');
|
||||
assert.equal(bytesWritten, file.size);
|
||||
});
|
||||
|
||||
CB_STUB = gently.expect(function writeCb() {
|
||||
assert.equal(file.size, 20);
|
||||
});
|
||||
|
||||
cb();
|
||||
});
|
||||
|
||||
file.write(BUFFER, CB);
|
||||
});
|
||||
|
||||
test(function end() {
|
||||
var CB_STUB,
|
||||
CB = function() {
|
||||
CB_STUB.apply(this, arguments);
|
||||
};
|
||||
|
||||
file._writeStream = {};
|
||||
|
||||
gently.expect(file._writeStream, 'end', function (cb) {
|
||||
gently.expect(file, 'emit', function (event) {
|
||||
assert.equal(event, 'end');
|
||||
});
|
||||
|
||||
CB_STUB = gently.expect(function endCb() {
|
||||
});
|
||||
|
||||
cb();
|
||||
});
|
||||
|
||||
file.end(CB);
|
||||
});
|
||||
727
node_modules/formidable/test/legacy/simple/test-incoming-form.js
generated
vendored
Normal file
727
node_modules/formidable/test/legacy/simple/test-incoming-form.js
generated
vendored
Normal file
@@ -0,0 +1,727 @@
|
||||
var common = require('../common');
|
||||
var MultipartParserStub = GENTLY.stub('./multipart_parser', 'MultipartParser'),
|
||||
QuerystringParserStub = GENTLY.stub('./querystring_parser', 'QuerystringParser'),
|
||||
EventEmitterStub = GENTLY.stub('events', 'EventEmitter'),
|
||||
StreamStub = GENTLY.stub('stream', 'Stream'),
|
||||
FileStub = GENTLY.stub('./file');
|
||||
|
||||
var formidable = require(common.lib + '/index'),
|
||||
IncomingForm = formidable.IncomingForm,
|
||||
events = require('events'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
Buffer = require('buffer').Buffer,
|
||||
fixtures = require(TEST_FIXTURES + '/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.maxFieldsSize, 2 * 1024 * 1024);
|
||||
assert.strictEqual(form._parser, null);
|
||||
assert.strictEqual(form._flushing, 0);
|
||||
assert.strictEqual(form._fieldsSize, 0);
|
||||
assert.ok(form instanceof EventEmitterStub);
|
||||
assert.equal(form.constructor.name, 'IncomingForm');
|
||||
|
||||
(function testSimpleConstructor() {
|
||||
gently.expect(EventEmitterStub, 'call');
|
||||
var form = IncomingForm();
|
||||
assert.ok(form instanceof IncomingForm);
|
||||
})();
|
||||
|
||||
(function testSimpleConstructorShortcut() {
|
||||
gently.expect(EventEmitterStub, 'call');
|
||||
var form = formidable();
|
||||
assert.ok(form instanceof IncomingForm);
|
||||
})();
|
||||
});
|
||||
|
||||
test(function parse() {
|
||||
var REQ = {headers: {}}
|
||||
, emit = {};
|
||||
|
||||
gently.expect(form, 'writeHeaders', function(headers) {
|
||||
assert.strictEqual(headers, REQ.headers);
|
||||
});
|
||||
|
||||
var events = ['error', 'aborted', 'data', 'end'];
|
||||
gently.expect(REQ, 'on', 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 testPauseCriticalException() {
|
||||
form.ended = false;
|
||||
|
||||
var ERR = new Error('dasdsa');
|
||||
gently.expect(REQ, 'pause', function() {
|
||||
throw ERR;
|
||||
});
|
||||
|
||||
gently.expect(form, '_error', function(err) {
|
||||
assert.strictEqual(err, ERR);
|
||||
});
|
||||
|
||||
assert.strictEqual(form.pause(), false);
|
||||
})();
|
||||
|
||||
(function testPauseHarmlessException() {
|
||||
form.ended = true;
|
||||
|
||||
var ERR = new Error('dasdsa');
|
||||
gently.expect(REQ, 'pause', function() {
|
||||
throw ERR;
|
||||
});
|
||||
|
||||
assert.strictEqual(form.pause(), false);
|
||||
})();
|
||||
|
||||
(function testResume() {
|
||||
gently.expect(REQ, 'resume');
|
||||
assert.strictEqual(form.resume(), true);
|
||||
})();
|
||||
|
||||
(function testResumeCriticalException() {
|
||||
form.ended = false;
|
||||
|
||||
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 testResumeHarmlessException() {
|
||||
form.ended = true;
|
||||
|
||||
var ERR = new Error('dasdsa');
|
||||
gently.expect(REQ, 'resume', function() {
|
||||
throw 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 testEmitAborted() {
|
||||
gently.expect(form, 'emit',function(event) {
|
||||
assert.equal(event, 'aborted');
|
||||
});
|
||||
|
||||
emit.aborted();
|
||||
})();
|
||||
|
||||
|
||||
(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, 'on', 4, function() {
|
||||
return this;
|
||||
});
|
||||
|
||||
gently.expect(form, 'on', 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, 'on', 4, function() {
|
||||
return this;
|
||||
});
|
||||
|
||||
var ERR = new Error('test');
|
||||
gently.expect(form, 'on', 3, function(event, fn) {
|
||||
if (event == 'field') {
|
||||
fn('foo', 'bar');
|
||||
}
|
||||
|
||||
if (event == 'error') {
|
||||
fn(ERR);
|
||||
gently.expect(form, 'on');
|
||||
}
|
||||
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(form, 'emit', function(event, bytesReceived, bytesExpected) {
|
||||
assert.equal(event, 'progress');
|
||||
assert.equal(bytesReceived, BUFFER.length);
|
||||
assert.equal(bytesExpected, form.bytesExpected);
|
||||
});
|
||||
|
||||
gently.expect(parser, 'write', function(buffer) {
|
||||
assert.strictEqual(buffer, BUFFER);
|
||||
return buffer.length;
|
||||
});
|
||||
|
||||
assert.equal(form.write(BUFFER), BUFFER.length);
|
||||
assert.equal(form.bytesReceived, BUFFER.length);
|
||||
})();
|
||||
|
||||
(function testParserError() {
|
||||
gently.expect(form, 'emit');
|
||||
|
||||
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));
|
||||
});
|
||||
|
||||
assert.equal(form.write(BUFFER), BUFFER.length - 1);
|
||||
assert.equal(form.bytesReceived, BUFFER.length + BUFFER.length);
|
||||
})();
|
||||
|
||||
(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 testQuotedBoundary() {
|
||||
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.bytesReceived, null);
|
||||
assert.strictEqual(form.bytesExpected, null);
|
||||
|
||||
form.headers['content-length'] = '8';
|
||||
gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
|
||||
assert.equal(event, 'progress');
|
||||
assert.equal(bytesReceived, 0);
|
||||
assert.equal(bytesExpected, 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';
|
||||
gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
|
||||
assert.equal(event, 'progress');
|
||||
assert.equal(bytesReceived, 0);
|
||||
assert.equal(bytesExpected, 8);
|
||||
});
|
||||
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(StreamStub, '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.onHeaderEnd();
|
||||
PARSER.onHeaderField(new Buffer('foo'), 0, 3);
|
||||
PARSER.onHeaderValue(new Buffer('bar'), 0, 3);
|
||||
PARSER.onHeaderEnd();
|
||||
PARSER.onHeadersEnd();
|
||||
PARSER.onPartData(new Buffer('hello world'), 0, 5);
|
||||
PARSER.onPartData(new Buffer('hello world'), 5, 11);
|
||||
PARSER.onPartEnd();
|
||||
})();
|
||||
|
||||
(function testFileField() {
|
||||
var PART;
|
||||
gently.expect(StreamStub, '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\\Sun"et.jpg"'
|
||||
, 'content-type': 'text/plain'
|
||||
}
|
||||
);
|
||||
assert.equal(part.name, 'field2');
|
||||
assert.equal(part.filename, 'Sun"et.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\\Sun"et.jpg"'), 0, 85);
|
||||
PARSER.onHeaderEnd();
|
||||
PARSER.onHeaderField(new Buffer('Content-Type'), 0, 12);
|
||||
PARSER.onHeaderValue(new Buffer('text/plain'), 0, 10);
|
||||
PARSER.onHeaderEnd();
|
||||
PARSER.onHeadersEnd();
|
||||
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 _fileName() {
|
||||
// TODO
|
||||
return;
|
||||
});
|
||||
|
||||
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 testFieldSize() {
|
||||
form.maxFieldsSize = 8;
|
||||
var PART = new events.EventEmitter();
|
||||
PART.name = 'my_field';
|
||||
|
||||
gently.expect(form, '_error', function(err) {
|
||||
assert.equal(err.message, 'maxFieldsSize exceeded, received 9 bytes of field data');
|
||||
});
|
||||
|
||||
form.handlePart(PART);
|
||||
form._fieldsSize = 1;
|
||||
PART.emit('data', new Buffer(7));
|
||||
PART.emit('data', new Buffer(1));
|
||||
})();
|
||||
|
||||
(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(FileStub, 'new', function(properties) {
|
||||
assert.equal(properties.path, PATH);
|
||||
assert.equal(properties.name, PART.filename);
|
||||
assert.equal(properties.type, PART.mime);
|
||||
FILE = this;
|
||||
|
||||
gently.expect(form, 'emit', function (event, field, file) {
|
||||
assert.equal(event, 'fileBegin');
|
||||
assert.strictEqual(field, PART.name);
|
||||
assert.strictEqual(file, FILE);
|
||||
});
|
||||
|
||||
gently.expect(FILE, 'open');
|
||||
});
|
||||
|
||||
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.strictEqual(file, FILE);
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
50
node_modules/formidable/test/legacy/simple/test-multipart-parser.js
generated
vendored
Normal file
50
node_modules/formidable/test/legacy/simple/test-multipart-parser.js
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
var common = require('../common');
|
||||
var multipartParser = require(common.lib + '/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: ' + parser.explain());
|
||||
})();
|
||||
|
||||
(function testRegular() {
|
||||
parser.state = multipartParser.END;
|
||||
assert.strictEqual(parser.end(), undefined);
|
||||
})();
|
||||
});
|
||||
45
node_modules/formidable/test/legacy/simple/test-querystring-parser.js
generated
vendored
Normal file
45
node_modules/formidable/test/legacy/simple/test-querystring-parser.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
var common = require('../common');
|
||||
var QuerystringParser = require(common.lib + '/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, '');
|
||||
});
|
||||
75
node_modules/formidable/test/legacy/system/test-multi-video-upload.js
generated
vendored
Normal file
75
node_modules/formidable/test/legacy/system/test-multi-video-upload.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
var common = require('../common');
|
||||
var BOUNDARY = '---------------------------10102754414578508781458777923',
|
||||
FIXTURE = TEST_FIXTURES+'/multi_video.upload',
|
||||
fs = require('fs'),
|
||||
util = require(common.lib + '/util'),
|
||||
http = require('http'),
|
||||
formidable = require(common.lib + '/index'),
|
||||
server = http.createServer();
|
||||
|
||||
server.on('request', function(req, res) {
|
||||
var form = new formidable.IncomingForm(),
|
||||
uploads = {};
|
||||
|
||||
form.uploadDir = TEST_TMP;
|
||||
form.hash = 'sha1';
|
||||
form.parse(req);
|
||||
|
||||
form
|
||||
.on('fileBegin', function(field, file) {
|
||||
assert.equal(field, 'upload');
|
||||
|
||||
var tracker = {file: file, progress: [], ended: false};
|
||||
uploads[file.filename] = tracker;
|
||||
file
|
||||
.on('progress', function(bytesReceived) {
|
||||
tracker.progress.push(bytesReceived);
|
||||
assert.equal(bytesReceived, file.length);
|
||||
})
|
||||
.on('end', function() {
|
||||
tracker.ended = true;
|
||||
});
|
||||
})
|
||||
.on('field', function(field, value) {
|
||||
assert.equal(field, 'title');
|
||||
assert.equal(value, '');
|
||||
})
|
||||
.on('file', function(field, file) {
|
||||
assert.equal(field, 'upload');
|
||||
assert.strictEqual(uploads[file.filename].file, file);
|
||||
})
|
||||
.on('end', function() {
|
||||
assert.ok(uploads['shortest_video.flv']);
|
||||
assert.ok(uploads['shortest_video.flv'].ended);
|
||||
assert.ok(uploads['shortest_video.flv'].progress.length > 3);
|
||||
assert.equal(uploads['shortest_video.flv'].file.hash, 'd6a17616c7143d1b1438ceeef6836d1a09186b3a');
|
||||
assert.equal(uploads['shortest_video.flv'].progress.slice(-1), uploads['shortest_video.flv'].file.length);
|
||||
assert.ok(uploads['shortest_video.mp4']);
|
||||
assert.ok(uploads['shortest_video.mp4'].ended);
|
||||
assert.ok(uploads['shortest_video.mp4'].progress.length > 3);
|
||||
assert.equal(uploads['shortest_video.mp4'].file.hash, '937dfd4db263f4887ceae19341dcc8d63bcd557f');
|
||||
|
||||
server.close();
|
||||
res.writeHead(200);
|
||||
res.end('good');
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(TEST_PORT, function() {
|
||||
var client = http.createClient(TEST_PORT),
|
||||
stat = fs.statSync(FIXTURE),
|
||||
headers = {
|
||||
'content-type': 'multipart/form-data; boundary='+BOUNDARY,
|
||||
'content-length': stat.size,
|
||||
}
|
||||
request = client.request('POST', '/', headers),
|
||||
fixture = new fs.ReadStream(FIXTURE);
|
||||
|
||||
fixture
|
||||
.on('data', function(b) {
|
||||
request.write(b);
|
||||
})
|
||||
.on('end', function() {
|
||||
request.end();
|
||||
});
|
||||
});
|
||||
2
node_modules/formidable/test/run.js
generated
vendored
Normal file
2
node_modules/formidable/test/run.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env node
|
||||
require('urun')(__dirname)
|
||||
63
node_modules/formidable/test/unit/test-incoming-form.js
generated
vendored
Normal file
63
node_modules/formidable/test/unit/test-incoming-form.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
var common = require('../common');
|
||||
var test = require('utest');
|
||||
var assert = common.assert;
|
||||
var IncomingForm = common.require('incoming_form').IncomingForm;
|
||||
var path = require('path');
|
||||
|
||||
var form;
|
||||
test('IncomingForm', {
|
||||
before: function() {
|
||||
form = new IncomingForm();
|
||||
},
|
||||
|
||||
'#_fileName with regular characters': function() {
|
||||
var filename = 'foo.txt';
|
||||
assert.equal(form._fileName(makeHeader(filename)), 'foo.txt');
|
||||
},
|
||||
|
||||
'#_fileName with unescaped quote': function() {
|
||||
var filename = 'my".txt';
|
||||
assert.equal(form._fileName(makeHeader(filename)), 'my".txt');
|
||||
},
|
||||
|
||||
'#_fileName with escaped quote': function() {
|
||||
var filename = 'my%22.txt';
|
||||
assert.equal(form._fileName(makeHeader(filename)), 'my".txt');
|
||||
},
|
||||
|
||||
'#_fileName with bad quote and additional sub-header': function() {
|
||||
var filename = 'my".txt';
|
||||
var header = makeHeader(filename) + '; foo="bar"';
|
||||
assert.equal(form._fileName(header), filename);
|
||||
},
|
||||
|
||||
'#_fileName with semicolon': function() {
|
||||
var filename = 'my;.txt';
|
||||
assert.equal(form._fileName(makeHeader(filename)), 'my;.txt');
|
||||
},
|
||||
|
||||
'#_fileName with utf8 character': function() {
|
||||
var filename = 'my☃.txt';
|
||||
assert.equal(form._fileName(makeHeader(filename)), 'my☃.txt');
|
||||
},
|
||||
|
||||
'#_uploadPath strips harmful characters from extension when keepExtensions': function() {
|
||||
form.keepExtensions = true;
|
||||
|
||||
var ext = path.extname(form._uploadPath('fine.jpg?foo=bar'));
|
||||
assert.equal(ext, '.jpg');
|
||||
|
||||
var ext = path.extname(form._uploadPath('fine?foo=bar'));
|
||||
assert.equal(ext, '');
|
||||
|
||||
var ext = path.extname(form._uploadPath('super.cr2+dsad'));
|
||||
assert.equal(ext, '.cr2');
|
||||
|
||||
var ext = path.extname(form._uploadPath('super.bar'));
|
||||
assert.equal(ext, '.bar');
|
||||
},
|
||||
});
|
||||
|
||||
function makeHeader(filename) {
|
||||
return 'Content-Disposition: form-data; name="upload"; filename="' + filename + '"';
|
||||
}
|
||||
47
node_modules/formidable/tool/record.js
generated
vendored
Normal file
47
node_modules/formidable/tool/record.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
var http = require('http');
|
||||
var fs = require('fs');
|
||||
var connections = 0;
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
var socket = req.socket;
|
||||
console.log('Request: %s %s -> %s', req.method, req.url, socket.filename);
|
||||
|
||||
req.on('end', function() {
|
||||
if (req.url !== '/') {
|
||||
res.end(JSON.stringify({
|
||||
method: req.method,
|
||||
url: req.url,
|
||||
filename: socket.filename,
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
res.writeHead(200, {'content-type': 'text/html'});
|
||||
res.end(
|
||||
'<form action="/upload" enctype="multipart/form-data" method="post">'+
|
||||
'<input type="text" name="title"><br>'+
|
||||
'<input type="file" name="upload" multiple="multiple"><br>'+
|
||||
'<input type="submit" value="Upload">'+
|
||||
'</form>'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
server.on('connection', function(socket) {
|
||||
connections++;
|
||||
|
||||
socket.id = connections;
|
||||
socket.filename = 'connection-' + socket.id + '.http';
|
||||
socket.file = fs.createWriteStream(socket.filename);
|
||||
socket.pipe(socket.file);
|
||||
|
||||
console.log('--> %s', socket.filename);
|
||||
socket.on('close', function() {
|
||||
console.log('<-- %s', socket.filename);
|
||||
});
|
||||
});
|
||||
|
||||
var port = process.env.PORT || 8080;
|
||||
server.listen(port, function() {
|
||||
console.log('Recording connections on port %s', port);
|
||||
});
|
||||
Reference in New Issue
Block a user