done purchases remove, ocr scan, read image
This commit is contained in:
89
express-server/node_modules/busboy/lib/main.js
generated
vendored
Normal file
89
express-server/node_modules/busboy/lib/main.js
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
var fs = require('fs'),
|
||||
WritableStream = require('stream').Writable
|
||||
|| require('readable-stream').Writable,
|
||||
inherits = require('util').inherits;
|
||||
|
||||
var parseParams = require('./utils').parseParams;
|
||||
|
||||
function Busboy(opts) {
|
||||
if (!(this instanceof Busboy))
|
||||
return new Busboy(opts);
|
||||
if (opts.highWaterMark !== undefined)
|
||||
WritableStream.call(this, { highWaterMark: opts.highWaterMark });
|
||||
else
|
||||
WritableStream.call(this);
|
||||
|
||||
this._done = false;
|
||||
this._parser = undefined;
|
||||
this._finished = false;
|
||||
|
||||
this.opts = opts;
|
||||
if (opts.headers && typeof opts.headers['content-type'] === 'string')
|
||||
this.parseHeaders(opts.headers);
|
||||
else
|
||||
throw new Error('Missing Content-Type');
|
||||
}
|
||||
inherits(Busboy, WritableStream);
|
||||
|
||||
Busboy.prototype.emit = function(ev) {
|
||||
if (ev === 'finish') {
|
||||
if (!this._done) {
|
||||
this._parser && this._parser.end();
|
||||
return;
|
||||
} else if (this._finished) {
|
||||
return;
|
||||
}
|
||||
this._finished = true;
|
||||
}
|
||||
WritableStream.prototype.emit.apply(this, arguments);
|
||||
};
|
||||
|
||||
Busboy.prototype.parseHeaders = function(headers) {
|
||||
this._parser = undefined;
|
||||
if (headers['content-type']) {
|
||||
var parsed = parseParams(headers['content-type']),
|
||||
matched, type;
|
||||
for (var i = 0; i < TYPES.length; ++i) {
|
||||
type = TYPES[i];
|
||||
if (typeof type.detect === 'function')
|
||||
matched = type.detect(parsed);
|
||||
else
|
||||
matched = type.detect.test(parsed[0]);
|
||||
if (matched)
|
||||
break;
|
||||
}
|
||||
if (matched) {
|
||||
var cfg = {
|
||||
limits: this.opts.limits,
|
||||
headers: headers,
|
||||
parsedConType: parsed,
|
||||
highWaterMark: undefined,
|
||||
fileHwm: undefined,
|
||||
defCharset: undefined,
|
||||
preservePath: false
|
||||
};
|
||||
if (this.opts.highWaterMark)
|
||||
cfg.highWaterMark = this.opts.highWaterMark;
|
||||
if (this.opts.fileHwm)
|
||||
cfg.fileHwm = this.opts.fileHwm;
|
||||
cfg.defCharset = this.opts.defCharset;
|
||||
cfg.preservePath = this.opts.preservePath;
|
||||
this._parser = type(this, cfg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new Error('Unsupported content type: ' + headers['content-type']);
|
||||
};
|
||||
|
||||
Busboy.prototype._write = function(chunk, encoding, cb) {
|
||||
if (!this._parser)
|
||||
return cb(new Error('Not ready to parse. Missing Content-Type?'));
|
||||
this._parser.write(chunk, cb);
|
||||
};
|
||||
|
||||
var TYPES = [
|
||||
require('./types/multipart'),
|
||||
require('./types/urlencoded'),
|
||||
];
|
||||
|
||||
module.exports = Busboy;
|
324
express-server/node_modules/busboy/lib/types/multipart.js
generated
vendored
Normal file
324
express-server/node_modules/busboy/lib/types/multipart.js
generated
vendored
Normal file
@ -0,0 +1,324 @@
|
||||
// TODO:
|
||||
// * support 1 nested multipart level
|
||||
// (see second multipart example here:
|
||||
// http://www.w3.org/TR/html401/interact/forms.html#didx-multipartform-data)
|
||||
// * support limits.fieldNameSize
|
||||
// -- this will require modifications to utils.parseParams
|
||||
|
||||
var ReadableStream = require('stream').Readable || require('readable-stream'),
|
||||
inherits = require('util').inherits;
|
||||
|
||||
var Dicer = require('dicer');
|
||||
|
||||
var parseParams = require('../utils').parseParams,
|
||||
decodeText = require('../utils').decodeText,
|
||||
basename = require('../utils').basename;
|
||||
|
||||
var RE_BOUNDARY = /^boundary$/i,
|
||||
RE_FIELD = /^form-data$/i,
|
||||
RE_CHARSET = /^charset$/i,
|
||||
RE_FILENAME = /^filename$/i,
|
||||
RE_NAME = /^name$/i;
|
||||
|
||||
Multipart.detect = /^multipart\/form-data/i;
|
||||
function Multipart(boy, cfg) {
|
||||
if (!(this instanceof Multipart))
|
||||
return new Multipart(boy, cfg);
|
||||
var i,
|
||||
len,
|
||||
self = this,
|
||||
boundary,
|
||||
limits = cfg.limits,
|
||||
parsedConType = cfg.parsedConType || [],
|
||||
defCharset = cfg.defCharset || 'utf8',
|
||||
preservePath = cfg.preservePath,
|
||||
fileopts = (typeof cfg.fileHwm === 'number'
|
||||
? { highWaterMark: cfg.fileHwm }
|
||||
: {});
|
||||
|
||||
for (i = 0, len = parsedConType.length; i < len; ++i) {
|
||||
if (Array.isArray(parsedConType[i])
|
||||
&& RE_BOUNDARY.test(parsedConType[i][0])) {
|
||||
boundary = parsedConType[i][1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function checkFinished() {
|
||||
if (nends === 0 && finished && !boy._done) {
|
||||
finished = false;
|
||||
process.nextTick(function() {
|
||||
boy._done = true;
|
||||
boy.emit('finish');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof boundary !== 'string')
|
||||
throw new Error('Multipart: Boundary not found');
|
||||
|
||||
var fieldSizeLimit = (limits && typeof limits.fieldSize === 'number'
|
||||
? limits.fieldSize
|
||||
: 1 * 1024 * 1024),
|
||||
fileSizeLimit = (limits && typeof limits.fileSize === 'number'
|
||||
? limits.fileSize
|
||||
: Infinity),
|
||||
filesLimit = (limits && typeof limits.files === 'number'
|
||||
? limits.files
|
||||
: Infinity),
|
||||
fieldsLimit = (limits && typeof limits.fields === 'number'
|
||||
? limits.fields
|
||||
: Infinity),
|
||||
partsLimit = (limits && typeof limits.parts === 'number'
|
||||
? limits.parts
|
||||
: Infinity);
|
||||
|
||||
var nfiles = 0,
|
||||
nfields = 0,
|
||||
nends = 0,
|
||||
curFile,
|
||||
curField,
|
||||
finished = false;
|
||||
|
||||
this._needDrain = false;
|
||||
this._pause = false;
|
||||
this._cb = undefined;
|
||||
this._nparts = 0;
|
||||
this._boy = boy;
|
||||
|
||||
var parserCfg = {
|
||||
boundary: boundary,
|
||||
maxHeaderPairs: (limits && limits.headerPairs)
|
||||
};
|
||||
if (fileopts.highWaterMark)
|
||||
parserCfg.partHwm = fileopts.highWaterMark;
|
||||
if (cfg.highWaterMark)
|
||||
parserCfg.highWaterMark = cfg.highWaterMark;
|
||||
|
||||
this.parser = new Dicer(parserCfg);
|
||||
this.parser.on('drain', function() {
|
||||
self._needDrain = false;
|
||||
if (self._cb && !self._pause) {
|
||||
var cb = self._cb;
|
||||
self._cb = undefined;
|
||||
cb();
|
||||
}
|
||||
}).on('part', function onPart(part) {
|
||||
if (++self._nparts > partsLimit) {
|
||||
self.parser.removeListener('part', onPart);
|
||||
self.parser.on('part', skipPart);
|
||||
boy.hitPartsLimit = true;
|
||||
boy.emit('partsLimit');
|
||||
return skipPart(part);
|
||||
}
|
||||
|
||||
// hack because streams2 _always_ doesn't emit 'end' until nextTick, so let
|
||||
// us emit 'end' early since we know the part has ended if we are already
|
||||
// seeing the next part
|
||||
if (curField) {
|
||||
var field = curField;
|
||||
field.emit('end');
|
||||
field.removeAllListeners('end');
|
||||
}
|
||||
|
||||
part.on('header', function(header) {
|
||||
var contype,
|
||||
fieldname,
|
||||
parsed,
|
||||
charset,
|
||||
encoding,
|
||||
filename,
|
||||
nsize = 0;
|
||||
|
||||
if (header['content-type']) {
|
||||
parsed = parseParams(header['content-type'][0]);
|
||||
if (parsed[0]) {
|
||||
contype = parsed[0].toLowerCase();
|
||||
for (i = 0, len = parsed.length; i < len; ++i) {
|
||||
if (RE_CHARSET.test(parsed[i][0])) {
|
||||
charset = parsed[i][1].toLowerCase();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (contype === undefined)
|
||||
contype = 'text/plain';
|
||||
if (charset === undefined)
|
||||
charset = defCharset;
|
||||
|
||||
if (header['content-disposition']) {
|
||||
parsed = parseParams(header['content-disposition'][0]);
|
||||
if (!RE_FIELD.test(parsed[0]))
|
||||
return skipPart(part);
|
||||
for (i = 0, len = parsed.length; i < len; ++i) {
|
||||
if (RE_NAME.test(parsed[i][0])) {
|
||||
fieldname = decodeText(parsed[i][1], 'binary', 'utf8');
|
||||
} else if (RE_FILENAME.test(parsed[i][0])) {
|
||||
filename = decodeText(parsed[i][1], 'binary', 'utf8');
|
||||
if (!preservePath)
|
||||
filename = basename(filename);
|
||||
}
|
||||
}
|
||||
} else
|
||||
return skipPart(part);
|
||||
|
||||
if (header['content-transfer-encoding'])
|
||||
encoding = header['content-transfer-encoding'][0].toLowerCase();
|
||||
else
|
||||
encoding = '7bit';
|
||||
|
||||
var onData,
|
||||
onEnd;
|
||||
if (contype === 'application/octet-stream' || filename !== undefined) {
|
||||
// file/binary field
|
||||
if (nfiles === filesLimit) {
|
||||
if (!boy.hitFilesLimit) {
|
||||
boy.hitFilesLimit = true;
|
||||
boy.emit('filesLimit');
|
||||
}
|
||||
return skipPart(part);
|
||||
}
|
||||
|
||||
++nfiles;
|
||||
|
||||
if (!boy._events.file) {
|
||||
self.parser._ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
++nends;
|
||||
var file = new FileStream(fileopts);
|
||||
curFile = file;
|
||||
file.on('end', function() {
|
||||
--nends;
|
||||
checkFinished();
|
||||
if (self._cb && !self._needDrain) {
|
||||
var cb = self._cb;
|
||||
self._cb = undefined;
|
||||
cb();
|
||||
}
|
||||
});
|
||||
file._read = function(n) {
|
||||
if (!self._pause)
|
||||
return;
|
||||
self._pause = false;
|
||||
if (self._cb && !self._needDrain) {
|
||||
var cb = self._cb;
|
||||
self._cb = undefined;
|
||||
cb();
|
||||
}
|
||||
};
|
||||
boy.emit('file', fieldname, file, filename, encoding, contype);
|
||||
|
||||
onData = function(data) {
|
||||
if ((nsize += data.length) > fileSizeLimit) {
|
||||
var extralen = (fileSizeLimit - (nsize - data.length));
|
||||
if (extralen > 0)
|
||||
file.push(data.slice(0, extralen));
|
||||
file.emit('limit');
|
||||
file.truncated = true;
|
||||
part.removeAllListeners('data');
|
||||
} else if (!file.push(data))
|
||||
self._pause = true;
|
||||
};
|
||||
|
||||
onEnd = function() {
|
||||
curFile = undefined;
|
||||
file.push(null);
|
||||
};
|
||||
} else {
|
||||
// non-file field
|
||||
if (nfields === fieldsLimit) {
|
||||
if (!boy.hitFieldsLimit) {
|
||||
boy.hitFieldsLimit = true;
|
||||
boy.emit('fieldsLimit');
|
||||
}
|
||||
return skipPart(part);
|
||||
}
|
||||
|
||||
++nfields;
|
||||
++nends;
|
||||
var buffer = '',
|
||||
truncated = false;
|
||||
curField = part;
|
||||
|
||||
onData = function(data) {
|
||||
if ((nsize += data.length) > fieldSizeLimit) {
|
||||
var extralen = (fieldSizeLimit - (nsize - data.length));
|
||||
buffer += data.toString('binary', 0, extralen);
|
||||
truncated = true;
|
||||
part.removeAllListeners('data');
|
||||
} else
|
||||
buffer += data.toString('binary');
|
||||
};
|
||||
|
||||
onEnd = function() {
|
||||
curField = undefined;
|
||||
if (buffer.length)
|
||||
buffer = decodeText(buffer, 'binary', charset);
|
||||
boy.emit('field', fieldname, buffer, false, truncated, encoding, contype);
|
||||
--nends;
|
||||
checkFinished();
|
||||
};
|
||||
}
|
||||
|
||||
/* As of node@2efe4ab761666 (v0.10.29+/v0.11.14+), busboy had become
|
||||
broken. Streams2/streams3 is a huge black box of confusion, but
|
||||
somehow overriding the sync state seems to fix things again (and still
|
||||
seems to work for previous node versions).
|
||||
*/
|
||||
part._readableState.sync = false;
|
||||
|
||||
part.on('data', onData);
|
||||
part.on('end', onEnd);
|
||||
}).on('error', function(err) {
|
||||
if (curFile)
|
||||
curFile.emit('error', err);
|
||||
});
|
||||
}).on('error', function(err) {
|
||||
boy.emit('error', err);
|
||||
}).on('finish', function() {
|
||||
finished = true;
|
||||
checkFinished();
|
||||
});
|
||||
}
|
||||
|
||||
Multipart.prototype.write = function(chunk, cb) {
|
||||
var r;
|
||||
if ((r = this.parser.write(chunk)) && !this._pause)
|
||||
cb();
|
||||
else {
|
||||
this._needDrain = !r;
|
||||
this._cb = cb;
|
||||
}
|
||||
};
|
||||
|
||||
Multipart.prototype.end = function() {
|
||||
var self = this;
|
||||
if (this._nparts === 0 && !self._boy._done) {
|
||||
process.nextTick(function() {
|
||||
self._boy._done = true;
|
||||
self._boy.emit('finish');
|
||||
});
|
||||
} else if (this.parser.writable)
|
||||
this.parser.end();
|
||||
};
|
||||
|
||||
function skipPart(part) {
|
||||
part.resume();
|
||||
}
|
||||
|
||||
function FileStream(opts) {
|
||||
if (!(this instanceof FileStream))
|
||||
return new FileStream(opts);
|
||||
ReadableStream.call(this, opts);
|
||||
|
||||
this.truncated = false;
|
||||
}
|
||||
inherits(FileStream, ReadableStream);
|
||||
|
||||
FileStream.prototype._read = function(n) {};
|
||||
|
||||
module.exports = Multipart;
|
214
express-server/node_modules/busboy/lib/types/urlencoded.js
generated
vendored
Normal file
214
express-server/node_modules/busboy/lib/types/urlencoded.js
generated
vendored
Normal file
@ -0,0 +1,214 @@
|
||||
var Decoder = require('../utils').Decoder,
|
||||
decodeText = require('../utils').decodeText;
|
||||
|
||||
var RE_CHARSET = /^charset$/i;
|
||||
|
||||
UrlEncoded.detect = /^application\/x-www-form-urlencoded/i;
|
||||
function UrlEncoded(boy, cfg) {
|
||||
if (!(this instanceof UrlEncoded))
|
||||
return new UrlEncoded(boy, cfg);
|
||||
var limits = cfg.limits,
|
||||
headers = cfg.headers,
|
||||
parsedConType = cfg.parsedConType;
|
||||
this.boy = boy;
|
||||
|
||||
this.fieldSizeLimit = (limits && typeof limits.fieldSize === 'number'
|
||||
? limits.fieldSize
|
||||
: 1 * 1024 * 1024);
|
||||
this.fieldNameSizeLimit = (limits && typeof limits.fieldNameSize === 'number'
|
||||
? limits.fieldNameSize
|
||||
: 100);
|
||||
this.fieldsLimit = (limits && typeof limits.fields === 'number'
|
||||
? limits.fields
|
||||
: Infinity);
|
||||
|
||||
var charset;
|
||||
for (var i = 0, len = parsedConType.length; i < len; ++i) {
|
||||
if (Array.isArray(parsedConType[i])
|
||||
&& RE_CHARSET.test(parsedConType[i][0])) {
|
||||
charset = parsedConType[i][1].toLowerCase();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (charset === undefined)
|
||||
charset = cfg.defCharset || 'utf8';
|
||||
|
||||
this.decoder = new Decoder();
|
||||
this.charset = charset;
|
||||
this._fields = 0;
|
||||
this._state = 'key';
|
||||
this._checkingBytes = true;
|
||||
this._bytesKey = 0;
|
||||
this._bytesVal = 0;
|
||||
this._key = '';
|
||||
this._val = '';
|
||||
this._keyTrunc = false;
|
||||
this._valTrunc = false;
|
||||
this._hitlimit = false;
|
||||
}
|
||||
|
||||
UrlEncoded.prototype.write = function(data, cb) {
|
||||
if (this._fields === this.fieldsLimit) {
|
||||
if (!this.boy.hitFieldsLimit) {
|
||||
this.boy.hitFieldsLimit = true;
|
||||
this.boy.emit('fieldsLimit');
|
||||
}
|
||||
return cb();
|
||||
}
|
||||
|
||||
var idxeq, idxamp, i, p = 0, len = data.length;
|
||||
|
||||
while (p < len) {
|
||||
if (this._state === 'key') {
|
||||
idxeq = idxamp = undefined;
|
||||
for (i = p; i < len; ++i) {
|
||||
if (!this._checkingBytes)
|
||||
++p;
|
||||
if (data[i] === 0x3D/*=*/) {
|
||||
idxeq = i;
|
||||
break;
|
||||
} else if (data[i] === 0x26/*&*/) {
|
||||
idxamp = i;
|
||||
break;
|
||||
}
|
||||
if (this._checkingBytes && this._bytesKey === this.fieldNameSizeLimit) {
|
||||
this._hitLimit = true;
|
||||
break;
|
||||
} else if (this._checkingBytes)
|
||||
++this._bytesKey;
|
||||
}
|
||||
|
||||
if (idxeq !== undefined) {
|
||||
// key with assignment
|
||||
if (idxeq > p)
|
||||
this._key += this.decoder.write(data.toString('binary', p, idxeq));
|
||||
this._state = 'val';
|
||||
|
||||
this._hitLimit = false;
|
||||
this._checkingBytes = true;
|
||||
this._val = '';
|
||||
this._bytesVal = 0;
|
||||
this._valTrunc = false;
|
||||
this.decoder.reset();
|
||||
|
||||
p = idxeq + 1;
|
||||
} else if (idxamp !== undefined) {
|
||||
// key with no assignment
|
||||
++this._fields;
|
||||
var key, keyTrunc = this._keyTrunc;
|
||||
if (idxamp > p)
|
||||
key = (this._key += this.decoder.write(data.toString('binary', p, idxamp)));
|
||||
else
|
||||
key = this._key;
|
||||
|
||||
this._hitLimit = false;
|
||||
this._checkingBytes = true;
|
||||
this._key = '';
|
||||
this._bytesKey = 0;
|
||||
this._keyTrunc = false;
|
||||
this.decoder.reset();
|
||||
|
||||
if (key.length) {
|
||||
this.boy.emit('field', decodeText(key, 'binary', this.charset),
|
||||
'',
|
||||
keyTrunc,
|
||||
false);
|
||||
}
|
||||
|
||||
p = idxamp + 1;
|
||||
if (this._fields === this.fieldsLimit)
|
||||
return cb();
|
||||
} else if (this._hitLimit) {
|
||||
// we may not have hit the actual limit if there are encoded bytes...
|
||||
if (i > p)
|
||||
this._key += this.decoder.write(data.toString('binary', p, i));
|
||||
p = i;
|
||||
if ((this._bytesKey = this._key.length) === this.fieldNameSizeLimit) {
|
||||
// yep, we actually did hit the limit
|
||||
this._checkingBytes = false;
|
||||
this._keyTrunc = true;
|
||||
}
|
||||
} else {
|
||||
if (p < len)
|
||||
this._key += this.decoder.write(data.toString('binary', p));
|
||||
p = len;
|
||||
}
|
||||
} else {
|
||||
idxamp = undefined;
|
||||
for (i = p; i < len; ++i) {
|
||||
if (!this._checkingBytes)
|
||||
++p;
|
||||
if (data[i] === 0x26/*&*/) {
|
||||
idxamp = i;
|
||||
break;
|
||||
}
|
||||
if (this._checkingBytes && this._bytesVal === this.fieldSizeLimit) {
|
||||
this._hitLimit = true;
|
||||
break;
|
||||
}
|
||||
else if (this._checkingBytes)
|
||||
++this._bytesVal;
|
||||
}
|
||||
|
||||
if (idxamp !== undefined) {
|
||||
++this._fields;
|
||||
if (idxamp > p)
|
||||
this._val += this.decoder.write(data.toString('binary', p, idxamp));
|
||||
this.boy.emit('field', decodeText(this._key, 'binary', this.charset),
|
||||
decodeText(this._val, 'binary', this.charset),
|
||||
this._keyTrunc,
|
||||
this._valTrunc);
|
||||
this._state = 'key';
|
||||
|
||||
this._hitLimit = false;
|
||||
this._checkingBytes = true;
|
||||
this._key = '';
|
||||
this._bytesKey = 0;
|
||||
this._keyTrunc = false;
|
||||
this.decoder.reset();
|
||||
|
||||
p = idxamp + 1;
|
||||
if (this._fields === this.fieldsLimit)
|
||||
return cb();
|
||||
} else if (this._hitLimit) {
|
||||
// we may not have hit the actual limit if there are encoded bytes...
|
||||
if (i > p)
|
||||
this._val += this.decoder.write(data.toString('binary', p, i));
|
||||
p = i;
|
||||
if ((this._val === '' && this.fieldSizeLimit === 0)
|
||||
|| (this._bytesVal = this._val.length) === this.fieldSizeLimit) {
|
||||
// yep, we actually did hit the limit
|
||||
this._checkingBytes = false;
|
||||
this._valTrunc = true;
|
||||
}
|
||||
} else {
|
||||
if (p < len)
|
||||
this._val += this.decoder.write(data.toString('binary', p));
|
||||
p = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
cb();
|
||||
};
|
||||
|
||||
UrlEncoded.prototype.end = function() {
|
||||
if (this.boy._done)
|
||||
return;
|
||||
|
||||
if (this._state === 'key' && this._key.length > 0) {
|
||||
this.boy.emit('field', decodeText(this._key, 'binary', this.charset),
|
||||
'',
|
||||
this._keyTrunc,
|
||||
false);
|
||||
} else if (this._state === 'val') {
|
||||
this.boy.emit('field', decodeText(this._key, 'binary', this.charset),
|
||||
decodeText(this._val, 'binary', this.charset),
|
||||
this._keyTrunc,
|
||||
this._valTrunc);
|
||||
}
|
||||
this.boy._done = true;
|
||||
this.boy.emit('finish');
|
||||
};
|
||||
|
||||
module.exports = UrlEncoded;
|
186
express-server/node_modules/busboy/lib/utils.js
generated
vendored
Normal file
186
express-server/node_modules/busboy/lib/utils.js
generated
vendored
Normal file
@ -0,0 +1,186 @@
|
||||
var jsencoding = require('../deps/encoding/encoding');
|
||||
|
||||
var RE_ENCODED = /%([a-fA-F0-9]{2})/g;
|
||||
function encodedReplacer(match, byte) {
|
||||
return String.fromCharCode(parseInt(byte, 16));
|
||||
}
|
||||
function parseParams(str) {
|
||||
var res = [],
|
||||
state = 'key',
|
||||
charset = '',
|
||||
inquote = false,
|
||||
escaping = false,
|
||||
p = 0,
|
||||
tmp = '';
|
||||
|
||||
for (var i = 0, len = str.length; i < len; ++i) {
|
||||
if (str[i] === '\\' && inquote) {
|
||||
if (escaping)
|
||||
escaping = false;
|
||||
else {
|
||||
escaping = true;
|
||||
continue;
|
||||
}
|
||||
} else if (str[i] === '"') {
|
||||
if (!escaping) {
|
||||
if (inquote) {
|
||||
inquote = false;
|
||||
state = 'key';
|
||||
} else
|
||||
inquote = true;
|
||||
continue;
|
||||
} else
|
||||
escaping = false;
|
||||
} else {
|
||||
if (escaping && inquote)
|
||||
tmp += '\\';
|
||||
escaping = false;
|
||||
if ((state === 'charset' || state === 'lang') && str[i] === "'") {
|
||||
if (state === 'charset') {
|
||||
state = 'lang';
|
||||
charset = tmp.substring(1);
|
||||
} else
|
||||
state = 'value';
|
||||
tmp = '';
|
||||
continue;
|
||||
} else if (state === 'key'
|
||||
&& (str[i] === '*' || str[i] === '=')
|
||||
&& res.length) {
|
||||
if (str[i] === '*')
|
||||
state = 'charset';
|
||||
else
|
||||
state = 'value';
|
||||
res[p] = [tmp, undefined];
|
||||
tmp = '';
|
||||
continue;
|
||||
} else if (!inquote && str[i] === ';') {
|
||||
state = 'key';
|
||||
if (charset) {
|
||||
if (tmp.length) {
|
||||
tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer),
|
||||
'binary',
|
||||
charset);
|
||||
}
|
||||
charset = '';
|
||||
}
|
||||
if (res[p] === undefined)
|
||||
res[p] = tmp;
|
||||
else
|
||||
res[p][1] = tmp;
|
||||
tmp = '';
|
||||
++p;
|
||||
continue;
|
||||
} else if (!inquote && (str[i] === ' ' || str[i] === '\t'))
|
||||
continue;
|
||||
}
|
||||
tmp += str[i];
|
||||
}
|
||||
if (charset && tmp.length) {
|
||||
tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer),
|
||||
'binary',
|
||||
charset);
|
||||
}
|
||||
|
||||
if (res[p] === undefined) {
|
||||
if (tmp)
|
||||
res[p] = tmp;
|
||||
} else
|
||||
res[p][1] = tmp;
|
||||
|
||||
return res;
|
||||
};
|
||||
exports.parseParams = parseParams;
|
||||
|
||||
|
||||
function decodeText(text, textEncoding, destEncoding) {
|
||||
var ret;
|
||||
if (text && jsencoding.encodingExists(destEncoding)) {
|
||||
try {
|
||||
ret = jsencoding.TextDecoder(destEncoding)
|
||||
.decode(new Buffer(text, textEncoding));
|
||||
} catch(e) {}
|
||||
}
|
||||
return (typeof ret === 'string' ? ret : text);
|
||||
}
|
||||
exports.decodeText = decodeText;
|
||||
|
||||
|
||||
var HEX = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
], RE_PLUS = /\+/g;
|
||||
function Decoder() {
|
||||
this.buffer = undefined;
|
||||
}
|
||||
Decoder.prototype.write = function(str) {
|
||||
// Replace '+' with ' ' before decoding
|
||||
str = str.replace(RE_PLUS, ' ');
|
||||
var res = '';
|
||||
var i = 0, p = 0, len = str.length;
|
||||
for (; i < len; ++i) {
|
||||
if (this.buffer !== undefined) {
|
||||
if (!HEX[str.charCodeAt(i)]) {
|
||||
res += '%' + this.buffer;
|
||||
this.buffer = undefined;
|
||||
--i; // retry character
|
||||
} else {
|
||||
this.buffer += str[i];
|
||||
++p;
|
||||
if (this.buffer.length === 2) {
|
||||
res += String.fromCharCode(parseInt(this.buffer, 16));
|
||||
this.buffer = undefined;
|
||||
}
|
||||
}
|
||||
} else if (str[i] === '%') {
|
||||
if (i > p) {
|
||||
res += str.substring(p, i);
|
||||
p = i;
|
||||
}
|
||||
this.buffer = '';
|
||||
++p;
|
||||
}
|
||||
}
|
||||
if (p < len && this.buffer === undefined)
|
||||
res += str.substring(p);
|
||||
return res;
|
||||
};
|
||||
Decoder.prototype.reset = function() {
|
||||
this.buffer = undefined;
|
||||
};
|
||||
exports.Decoder = Decoder;
|
||||
|
||||
|
||||
var RE_SPLIT_POSIX =
|
||||
/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,
|
||||
RE_SPLIT_DEVICE =
|
||||
/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/,
|
||||
RE_SPLIT_WINDOWS =
|
||||
/^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/;
|
||||
function splitPathPosix(filename) {
|
||||
return RE_SPLIT_POSIX.exec(filename).slice(1);
|
||||
}
|
||||
function splitPathWindows(filename) {
|
||||
// Separate device+slash from tail
|
||||
var result = RE_SPLIT_DEVICE.exec(filename),
|
||||
device = (result[1] || '') + (result[2] || ''),
|
||||
tail = result[3] || '';
|
||||
// Split the tail into dir, basename and extension
|
||||
var result2 = RE_SPLIT_WINDOWS.exec(tail),
|
||||
dir = result2[1],
|
||||
basename = result2[2],
|
||||
ext = result2[3];
|
||||
return [device, dir, basename, ext];
|
||||
}
|
||||
function basename(path) {
|
||||
var f = splitPathPosix(path)[2];
|
||||
if (f === path)
|
||||
f = splitPathWindows(path)[2];
|
||||
return f;
|
||||
}
|
||||
exports.basename = basename;
|
Reference in New Issue
Block a user