initial commit

This commit is contained in:
2012-10-26 18:04:20 -04:00
parent 403c017c48
commit d4c4c34795
806 changed files with 287432 additions and 0 deletions

73
node_modules/formidable/lib/file.js generated vendored Normal file
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,6 @@
// Backwards compatibility ...
try {
module.exports = require('util');
} catch (e) {
module.exports = require('sys');
}