diff options
author | Minteck <contact@minteck.org> | 2023-02-23 19:34:56 +0100 |
---|---|---|
committer | Minteck <contact@minteck.org> | 2023-02-23 19:34:56 +0100 |
commit | 3d1cd02f27518f1a04374c7c8320cd5d82ede6e9 (patch) | |
tree | 75be5fba4368472fb11c8015aee026b2b9a71888 /together/node_modules/formidable/src | |
parent | 8cc1f13c17fa2fb5a4410542d39e650e02945634 (diff) | |
download | pluralconnect-3d1cd02f27518f1a04374c7c8320cd5d82ede6e9.tar.gz pluralconnect-3d1cd02f27518f1a04374c7c8320cd5d82ede6e9.tar.bz2 pluralconnect-3d1cd02f27518f1a04374c7c8320cd5d82ede6e9.zip |
Updated 40 files, added 37 files, deleted 1103 files and renamed 3905 files (automated)
Diffstat (limited to 'together/node_modules/formidable/src')
17 files changed, 0 insertions, 1812 deletions
diff --git a/together/node_modules/formidable/src/Formidable.js b/together/node_modules/formidable/src/Formidable.js deleted file mode 100644 index 0542700..0000000 --- a/together/node_modules/formidable/src/Formidable.js +++ /dev/null @@ -1,617 +0,0 @@ -/* eslint-disable class-methods-use-this */ -/* eslint-disable no-underscore-dangle */ - -'use strict'; - -const os = require('os'); -const path = require('path'); -const hexoid = require('hexoid'); -const once = require('once'); -const dezalgo = require('dezalgo'); -const { EventEmitter } = require('events'); -const { StringDecoder } = require('string_decoder'); -const qs = require('qs'); - -const toHexoId = hexoid(25); -const DEFAULT_OPTIONS = { - maxFields: 1000, - maxFieldsSize: 20 * 1024 * 1024, - maxFileSize: 200 * 1024 * 1024, - minFileSize: 1, - allowEmptyFiles: true, - keepExtensions: false, - encoding: 'utf-8', - hashAlgorithm: false, - uploadDir: os.tmpdir(), - multiples: false, - enabledPlugins: ['octetstream', 'querystring', 'multipart', 'json'], - fileWriteStreamHandler: null, - defaultInvalidName: 'invalid-name', - filter: function () { - return true; - }, -}; - -const PersistentFile = require('./PersistentFile'); -const VolatileFile = require('./VolatileFile'); -const DummyParser = require('./parsers/Dummy'); -const MultipartParser = require('./parsers/Multipart'); -const errors = require('./FormidableError.js'); - -const { FormidableError } = errors; - -function hasOwnProp(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} - -class IncomingForm extends EventEmitter { - constructor(options = {}) { - super(); - - this.options = { ...DEFAULT_OPTIONS, ...options }; - - const dir = path.resolve( - this.options.uploadDir || this.options.uploaddir || os.tmpdir(), - ); - - this.uploaddir = dir; - this.uploadDir = dir; - - // initialize with null - [ - 'error', - 'headers', - 'type', - 'bytesExpected', - 'bytesReceived', - '_parser', - ].forEach((key) => { - this[key] = null; - }); - - this._setUpRename(); - - this._flushing = 0; - this._fieldsSize = 0; - this._fileSize = 0; - this._plugins = []; - this.openedFiles = []; - - this.options.enabledPlugins = [] - .concat(this.options.enabledPlugins) - .filter(Boolean); - - if (this.options.enabledPlugins.length === 0) { - throw new FormidableError( - 'expect at least 1 enabled builtin plugin, see options.enabledPlugins', - errors.missingPlugin, - ); - } - - this.options.enabledPlugins.forEach((pluginName) => { - const plgName = pluginName.toLowerCase(); - // eslint-disable-next-line import/no-dynamic-require, global-require - this.use(require(path.join(__dirname, 'plugins', `${plgName}.js`))); - }); - - this._setUpMaxFields(); - } - - use(plugin) { - if (typeof plugin !== 'function') { - throw new FormidableError( - '.use: expect `plugin` to be a function', - errors.pluginFunction, - ); - } - this._plugins.push(plugin.bind(this)); - return this; - } - - parse(req, cb) { - this.pause = () => { - 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 = () => { - 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; - }; - - // Setup callback first, so we don't miss anything from data events emitted immediately. - if (cb) { - const callback = once(dezalgo(cb)); - const fields = {}; - let mockFields = ''; - const files = {}; - - this.on('field', (name, value) => { - if ( - this.options.multiples && - (this.type === 'multipart' || this.type === 'urlencoded') - ) { - const mObj = { [name]: value }; - mockFields = mockFields - ? `${mockFields}&${qs.stringify(mObj)}` - : `${qs.stringify(mObj)}`; - } else { - fields[name] = value; - } - }); - this.on('file', (name, file) => { - // TODO: too much nesting - if (this.options.multiples) { - if (hasOwnProp(files, name)) { - if (!Array.isArray(files[name])) { - files[name] = [files[name]]; - } - files[name].push(file); - } else { - files[name] = file; - } - } else { - files[name] = file; - } - }); - this.on('error', (err) => { - callback(err, fields, files); - }); - this.on('end', () => { - if (this.options.multiples) { - Object.assign(fields, qs.parse(mockFields)); - } - callback(null, fields, files); - }); - } - - // Parse headers and setup the parser, ready to start listening for data. - this.writeHeaders(req.headers); - - // Start listening for data. - req - .on('error', (err) => { - this._error(err); - }) - .on('aborted', () => { - this.emit('aborted'); - this._error(new FormidableError('Request aborted', errors.aborted)); - }) - .on('data', (buffer) => { - try { - this.write(buffer); - } catch (err) { - this._error(err); - } - }) - .on('end', () => { - if (this.error) { - return; - } - if (this._parser) { - this._parser.end(); - } - this._maybeEnd(); - }); - - return this; - } - - writeHeaders(headers) { - this.headers = headers; - this._parseContentLength(); - this._parseContentType(); - - if (!this._parser) { - this._error( - new FormidableError( - 'no parser found', - errors.noParser, - 415, // Unsupported Media Type - ), - ); - return; - } - - this._parser.once('error', (error) => { - this._error(error); - }); - } - - write(buffer) { - if (this.error) { - return null; - } - if (!this._parser) { - this._error( - new FormidableError('uninitialized parser', errors.uninitializedParser), - ); - return null; - } - - this.bytesReceived += buffer.length; - this.emit('progress', this.bytesReceived, this.bytesExpected); - - this._parser.write(buffer); - - return this.bytesReceived; - } - - pause() { - // this does nothing, unless overwritten in IncomingForm.parse - return false; - } - - resume() { - // this does nothing, unless overwritten in IncomingForm.parse - return false; - } - - onPart(part) { - // this method can be overwritten by the user - this._handlePart(part); - } - - _handlePart(part) { - if (part.originalFilename && typeof part.originalFilename !== 'string') { - this._error( - new FormidableError( - `the part.originalFilename should be string when it exists`, - errors.filenameNotString, - ), - ); - return; - } - - // This MUST check exactly for undefined. You can not change it to !part.originalFilename. - - // todo: uncomment when switch tests to Jest - // console.log(part); - - // ? NOTE(@tunnckocore): no it can be any falsey value, it most probably depends on what's returned - // from somewhere else. Where recently I changed the return statements - // and such thing because code style - // ? NOTE(@tunnckocore): or even better, if there is no mimetype, then it's for sure a field - // ? NOTE(@tunnckocore): originalFilename is an empty string when a field? - if (!part.mimetype) { - let value = ''; - const decoder = new StringDecoder( - part.transferEncoding || this.options.encoding, - ); - - part.on('data', (buffer) => { - this._fieldsSize += buffer.length; - if (this._fieldsSize > this.options.maxFieldsSize) { - this._error( - new FormidableError( - `options.maxFieldsSize (${this.options.maxFieldsSize} bytes) exceeded, received ${this._fieldsSize} bytes of field data`, - errors.maxFieldsSizeExceeded, - 413, // Payload Too Large - ), - ); - return; - } - value += decoder.write(buffer); - }); - - part.on('end', () => { - this.emit('field', part.name, value); - }); - return; - } - - if (!this.options.filter(part)) { - return; - } - - this._flushing += 1; - - const newFilename = this._getNewName(part); - const filepath = this._joinDirectoryName(newFilename); - const file = this._newFile({ - newFilename, - filepath, - originalFilename: part.originalFilename, - mimetype: part.mimetype, - }); - file.on('error', (err) => { - this._error(err); - }); - this.emit('fileBegin', part.name, file); - - file.open(); - this.openedFiles.push(file); - - part.on('data', (buffer) => { - this._fileSize += buffer.length; - if (this._fileSize < this.options.minFileSize) { - this._error( - new FormidableError( - `options.minFileSize (${this.options.minFileSize} bytes) inferior, received ${this._fileSize} bytes of file data`, - errors.smallerThanMinFileSize, - 400, - ), - ); - return; - } - if (this._fileSize > this.options.maxFileSize) { - this._error( - new FormidableError( - `options.maxFileSize (${this.options.maxFileSize} bytes) exceeded, received ${this._fileSize} bytes of file data`, - errors.biggerThanMaxFileSize, - 413, - ), - ); - return; - } - if (buffer.length === 0) { - return; - } - this.pause(); - file.write(buffer, () => { - this.resume(); - }); - }); - - part.on('end', () => { - if (!this.options.allowEmptyFiles && this._fileSize === 0) { - this._error( - new FormidableError( - `options.allowEmptyFiles is false, file size should be greather than 0`, - errors.noEmptyFiles, - 400, - ), - ); - return; - } - - file.end(() => { - this._flushing -= 1; - this.emit('file', part.name, file); - this._maybeEnd(); - }); - }); - } - - // eslint-disable-next-line max-statements - _parseContentType() { - if (this.bytesExpected === 0) { - this._parser = new DummyParser(this, this.options); - return; - } - - if (!this.headers['content-type']) { - this._error( - new FormidableError( - 'bad content-type header, no content-type', - errors.missingContentType, - 400, - ), - ); - return; - } - - const results = []; - const _dummyParser = new DummyParser(this, this.options); - - // eslint-disable-next-line no-plusplus - for (let idx = 0; idx < this._plugins.length; idx++) { - const plugin = this._plugins[idx]; - - let pluginReturn = null; - - try { - pluginReturn = plugin(this, this.options) || this; - } catch (err) { - // directly throw from the `form.parse` method; - // there is no other better way, except a handle through options - const error = new FormidableError( - `plugin on index ${idx} failed with: ${err.message}`, - errors.pluginFailed, - 500, - ); - error.idx = idx; - throw error; - } - - Object.assign(this, pluginReturn); - - // todo: use Set/Map and pass plugin name instead of the `idx` index - this.emit('plugin', idx, pluginReturn); - results.push(pluginReturn); - } - - this.emit('pluginsResults', results); - - // NOTE: probably not needed, because we check options.enabledPlugins in the constructor - // if (results.length === 0 /* && results.length !== this._plugins.length */) { - // this._error( - // new Error( - // `bad content-type header, unknown content-type: ${this.headers['content-type']}`, - // ), - // ); - // } - } - - _error(err, eventName = 'error') { - // if (!err && this.error) { - // this.emit('error', this.error); - // return; - // } - if (this.error || this.ended) { - return; - } - - this.error = err; - this.emit(eventName, err); - - if (Array.isArray(this.openedFiles)) { - this.openedFiles.forEach((file) => { - file.destroy(); - }); - } - } - - _parseContentLength() { - this.bytesReceived = 0; - if (this.headers['content-length']) { - this.bytesExpected = parseInt(this.headers['content-length'], 10); - } else if (this.headers['transfer-encoding'] === undefined) { - this.bytesExpected = 0; - } - - if (this.bytesExpected !== null) { - this.emit('progress', this.bytesReceived, this.bytesExpected); - } - } - - _newParser() { - return new MultipartParser(this.options); - } - - _newFile({ filepath, originalFilename, mimetype, newFilename }) { - return this.options.fileWriteStreamHandler - ? new VolatileFile({ - newFilename, - filepath, - originalFilename, - mimetype, - createFileWriteStream: this.options.fileWriteStreamHandler, - hashAlgorithm: this.options.hashAlgorithm, - }) - : new PersistentFile({ - newFilename, - filepath, - originalFilename, - mimetype, - hashAlgorithm: this.options.hashAlgorithm, - }); - } - - _getFileName(headerValue) { - // matches either a quoted-string or a token (RFC 2616 section 19.5.1) - const m = headerValue.match( - /\bfilename=("(.*?)"|([^()<>{}[\]@,;:"?=\s/\t]+))($|;\s)/i, - ); - if (!m) return null; - - const match = m[2] || m[3] || ''; - let originalFilename = match.substr(match.lastIndexOf('\\') + 1); - originalFilename = originalFilename.replace(/%22/g, '"'); - originalFilename = originalFilename.replace(/&#([\d]{4});/g, (_, code) => - String.fromCharCode(code), - ); - - return originalFilename; - } - - _getExtension(str) { - if (!str) { - return ''; - } - - const basename = path.basename(str); - const firstDot = basename.indexOf('.'); - const lastDot = basename.lastIndexOf('.'); - const extname = path.extname(basename).replace(/(\.[a-z0-9]+).*/i, '$1'); - - if (firstDot === lastDot) { - return extname; - } - - return basename.slice(firstDot, lastDot) + extname; - } - - - - _joinDirectoryName(name) { - const newPath = path.join(this.uploadDir, name); - - // prevent directory traversal attacks - if (!newPath.startsWith(this.uploadDir)) { - return path.join(this.uploadDir, this.options.defaultInvalidName); - } - - return newPath; - } - - _setUpRename() { - const hasRename = typeof this.options.filename === 'function'; - if (hasRename) { - this._getNewName = (part) => { - let ext = ''; - let name = this.options.defaultInvalidName; - if (part.originalFilename) { - // can be null - ({ ext, name } = path.parse(part.originalFilename)); - if (this.options.keepExtensions !== true) { - ext = ''; - } - } - return this.options.filename.call(this, name, ext, part, this); - }; - } else { - this._getNewName = (part) => { - const name = toHexoId(); - - if (part && this.options.keepExtensions) { - const originalFilename = typeof part === 'string' ? part : part.originalFilename; - return `${name}${this._getExtension(originalFilename)}`; - } - - return name; - } - } - } - - _setUpMaxFields() { - if (this.options.maxFields !== 0) { - let fieldsCount = 0; - this.on('field', () => { - fieldsCount += 1; - if (fieldsCount > this.options.maxFields) { - this._error( - new FormidableError( - `options.maxFields (${this.options.maxFields}) exceeded`, - errors.maxFieldsExceeded, - 413, - ), - ); - } - }); - } - } - - _maybeEnd() { - // console.log('ended', this.ended); - // console.log('_flushing', this._flushing); - // console.log('error', this.error); - if (!this.ended || this._flushing || this.error) { - return; - } - - this.emit('end'); - } -} - -IncomingForm.DEFAULT_OPTIONS = DEFAULT_OPTIONS; -module.exports = IncomingForm; diff --git a/together/node_modules/formidable/src/FormidableError.js b/together/node_modules/formidable/src/FormidableError.js deleted file mode 100644 index da5c25f..0000000 --- a/together/node_modules/formidable/src/FormidableError.js +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable no-plusplus */ - -const missingPlugin = 1000; -const pluginFunction = 1001; -const aborted = 1002; -const noParser = 1003; -const uninitializedParser = 1004; -const filenameNotString = 1005; -const maxFieldsSizeExceeded = 1006; -const maxFieldsExceeded = 1007; -const smallerThanMinFileSize = 1008; -const biggerThanMaxFileSize = 1009; -const noEmptyFiles = 1010; -const missingContentType = 1011; -const malformedMultipart = 1012; -const missingMultipartBoundary = 1013; -const unknownTransferEncoding = 1014; - -const FormidableError = class extends Error { - constructor(message, internalCode, httpCode = 500) { - super(message); - this.code = internalCode; - this.httpCode = httpCode; - } -}; - -module.exports = { - missingPlugin, - pluginFunction, - aborted, - noParser, - uninitializedParser, - filenameNotString, - maxFieldsSizeExceeded, - maxFieldsExceeded, - smallerThanMinFileSize, - biggerThanMaxFileSize, - noEmptyFiles, - missingContentType, - malformedMultipart, - missingMultipartBoundary, - unknownTransferEncoding, - - FormidableError, -}; diff --git a/together/node_modules/formidable/src/PersistentFile.js b/together/node_modules/formidable/src/PersistentFile.js deleted file mode 100644 index 3a28aa7..0000000 --- a/together/node_modules/formidable/src/PersistentFile.js +++ /dev/null @@ -1,87 +0,0 @@ -/* eslint-disable no-underscore-dangle */ - -'use strict'; - -const fs = require('fs'); -const crypto = require('crypto'); -const { EventEmitter } = require('events'); - -class PersistentFile extends EventEmitter { - constructor({ filepath, newFilename, originalFilename, mimetype, hashAlgorithm }) { - super(); - - this.lastModifiedDate = null; - Object.assign(this, { filepath, newFilename, originalFilename, mimetype, hashAlgorithm }); - - this.size = 0; - this._writeStream = null; - - if (typeof this.hashAlgorithm === 'string') { - this.hash = crypto.createHash(this.hashAlgorithm); - } else { - this.hash = null; - } - } - - open() { - this._writeStream = new fs.WriteStream(this.filepath); - this._writeStream.on('error', (err) => { - this.emit('error', err); - }); - } - - toJSON() { - const json = { - size: this.size, - filepath: this.filepath, - newFilename: this.newFilename, - mimetype: this.mimetype, - mtime: this.lastModifiedDate, - length: this.length, - originalFilename: this.originalFilename, - }; - if (this.hash && this.hash !== '') { - json.hash = this.hash; - } - return json; - } - - toString() { - return `PersistentFile: ${this._file.newFilename}, Original: ${this._file.originalFilename}, Path: ${this._file.filepath}`; - } - - write(buffer, cb) { - if (this.hash) { - this.hash.update(buffer); - } - - if (this._writeStream.closed) { - cb(); - return; - } - - this._writeStream.write(buffer, () => { - this.lastModifiedDate = new Date(); - this.size += buffer.length; - this.emit('progress', this.size); - cb(); - }); - } - - end(cb) { - if (this.hash) { - this.hash = this.hash.digest('hex'); - } - this._writeStream.end(() => { - this.emit('end'); - cb(); - }); - } - - destroy() { - this._writeStream.destroy(); - fs.unlink(this.filepath, () => {}); - } -} - -module.exports = PersistentFile; diff --git a/together/node_modules/formidable/src/VolatileFile.js b/together/node_modules/formidable/src/VolatileFile.js deleted file mode 100644 index 01af428..0000000 --- a/together/node_modules/formidable/src/VolatileFile.js +++ /dev/null @@ -1,82 +0,0 @@ -/* eslint-disable no-underscore-dangle */ - -'use strict'; - -const crypto = require('crypto'); -const { EventEmitter } = require('events'); - -class VolatileFile extends EventEmitter { - constructor({ filepath, newFilename, originalFilename, mimetype, hashAlgorithm, createFileWriteStream }) { - super(); - - this.lastModifiedDate = null; - Object.assign(this, { filepath, newFilename, originalFilename, mimetype, hashAlgorithm, createFileWriteStream }); - - this.size = 0; - this._writeStream = null; - - if (typeof this.hashAlgorithm === 'string') { - this.hash = crypto.createHash(this.hashAlgorithm); - } else { - this.hash = null; - } - } - - open() { - this._writeStream = this.createFileWriteStream(this); - this._writeStream.on('error', (err) => { - this.emit('error', err); - }); - } - - destroy() { - this._writeStream.destroy(); - } - - toJSON() { - const json = { - size: this.size, - newFilename: this.newFilename, - length: this.length, - originalFilename: this.originalFilename, - mimetype: this.mimetype, - }; - if (this.hash && this.hash !== '') { - json.hash = this.hash; - } - return json; - } - - toString() { - return `VolatileFile: ${this.originalFilename}`; - } - - write(buffer, cb) { - if (this.hash) { - this.hash.update(buffer); - } - - if (this._writeStream.closed || this._writeStream.destroyed) { - cb(); - return; - } - - this._writeStream.write(buffer, () => { - this.size += buffer.length; - this.emit('progress', this.size); - cb(); - }); - } - - end(cb) { - if (this.hash) { - this.hash = this.hash.digest('hex'); - } - this._writeStream.end(() => { - this.emit('end'); - cb(); - }); - } -} - -module.exports = VolatileFile; diff --git a/together/node_modules/formidable/src/index.js b/together/node_modules/formidable/src/index.js deleted file mode 100644 index bf555a9..0000000 --- a/together/node_modules/formidable/src/index.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -const PersistentFile = require('./PersistentFile'); -const VolatileFile = require('./VolatileFile'); -const Formidable = require('./Formidable'); -const FormidableError = require('./FormidableError'); - -const plugins = require('./plugins/index'); -const parsers = require('./parsers/index'); - -// make it available without requiring the `new` keyword -// if you want it access `const formidable.IncomingForm` as v1 -const formidable = (...args) => new Formidable(...args); - -module.exports = Object.assign(formidable, { - errors: FormidableError, - File: PersistentFile, - PersistentFile, - VolatileFile, - Formidable, - formidable, - - // alias - IncomingForm: Formidable, - - // parsers - ...parsers, - parsers, - - // misc - defaultOptions: Formidable.DEFAULT_OPTIONS, - enabledPlugins: Formidable.DEFAULT_OPTIONS.enabledPlugins, - - // plugins - plugins: { - ...plugins, - }, -}); diff --git a/together/node_modules/formidable/src/parsers/Dummy.js b/together/node_modules/formidable/src/parsers/Dummy.js deleted file mode 100644 index 6340959..0000000 --- a/together/node_modules/formidable/src/parsers/Dummy.js +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable no-underscore-dangle */ - -'use strict'; - -const { Transform } = require('stream'); - -class DummyParser extends Transform { - constructor(incomingForm, options = {}) { - super(); - this.globalOptions = { ...options }; - this.incomingForm = incomingForm; - } - - _flush(callback) { - this.incomingForm.ended = true; - this.incomingForm._maybeEnd(); - callback(); - } -} - -module.exports = DummyParser; diff --git a/together/node_modules/formidable/src/parsers/JSON.js b/together/node_modules/formidable/src/parsers/JSON.js deleted file mode 100644 index 9a096c2..0000000 --- a/together/node_modules/formidable/src/parsers/JSON.js +++ /dev/null @@ -1,35 +0,0 @@ -/* eslint-disable no-underscore-dangle */ - -'use strict'; - -const { Transform } = require('stream'); - -class JSONParser extends Transform { - constructor(options = {}) { - super({ readableObjectMode: true }); - this.chunks = []; - this.globalOptions = { ...options }; - } - - _transform(chunk, encoding, callback) { - this.chunks.push(String(chunk)); // todo consider using a string decoder - callback(); - } - - _flush(callback) { - try { - const fields = JSON.parse(this.chunks.join('')); - Object.keys(fields).forEach((key) => { - const value = fields[key]; - this.push({ key, value }); - }); - } catch (e) { - callback(e); - return; - } - this.chunks = null; - callback(); - } -} - -module.exports = JSONParser; diff --git a/together/node_modules/formidable/src/parsers/Multipart.js b/together/node_modules/formidable/src/parsers/Multipart.js deleted file mode 100644 index 23a298a..0000000 --- a/together/node_modules/formidable/src/parsers/Multipart.js +++ /dev/null @@ -1,347 +0,0 @@ -/* eslint-disable no-fallthrough */ -/* eslint-disable no-bitwise */ -/* eslint-disable no-plusplus */ -/* eslint-disable no-underscore-dangle */ - -'use strict'; - -const { Transform } = require('stream'); -const errors = require('../FormidableError.js'); - -const { FormidableError } = errors; - -let s = 0; -const STATE = { - 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++, -}; - -let f = 1; -const FBOUNDARY = { PART_BOUNDARY: f, LAST_BOUNDARY: (f *= 2) }; - -const LF = 10; -const CR = 13; -const SPACE = 32; -const HYPHEN = 45; -const COLON = 58; -const A = 97; -const Z = 122; - -function lower(c) { - return c | 0x20; -} - -exports.STATES = {}; - -Object.keys(STATE).forEach((stateName) => { - exports.STATES[stateName] = STATE[stateName]; -}); - -class MultipartParser extends Transform { - constructor(options = {}) { - super({ readableObjectMode: true }); - this.boundary = null; - this.boundaryChars = null; - this.lookbehind = null; - this.bufferLength = 0; - this.state = STATE.PARSER_UNINITIALIZED; - - this.globalOptions = { ...options }; - this.index = null; - this.flags = 0; - } - - _flush(done) { - if ( - (this.state === STATE.HEADER_FIELD_START && this.index === 0) || - (this.state === STATE.PART_DATA && this.index === this.boundary.length) - ) { - this._handleCallback('partEnd'); - this._handleCallback('end'); - done(); - } else if (this.state !== STATE.END) { - done( - new FormidableError( - `MultipartParser.end(): stream ended unexpectedly: ${this.explain()}`, - errors.malformedMultipart, - 400, - ), - ); - } - } - - initWithBoundary(str) { - this.boundary = Buffer.from(`\r\n--${str}`); - this.lookbehind = Buffer.alloc(this.boundary.length + 8); - this.state = STATE.START; - this.boundaryChars = {}; - - for (let i = 0; i < this.boundary.length; i++) { - this.boundaryChars[this.boundary[i]] = true; - } - } - - // eslint-disable-next-line max-params - _handleCallback(name, buf, start, end) { - if (start !== undefined && start === end) { - return; - } - this.push({ name, buffer: buf, start, end }); - } - - // eslint-disable-next-line max-statements - _transform(buffer, _, done) { - let i = 0; - let prevIndex = this.index; - let { index, state, flags } = this; - const { lookbehind, boundary, boundaryChars } = this; - const boundaryLength = boundary.length; - const boundaryEnd = boundaryLength - 1; - this.bufferLength = buffer.length; - let c = null; - let cl = null; - - const setMark = (name, idx) => { - this[`${name}Mark`] = typeof idx === 'number' ? idx : i; - }; - - const clearMarkSymbol = (name) => { - delete this[`${name}Mark`]; - }; - - const dataCallback = (name, shouldClear) => { - const markSymbol = `${name}Mark`; - if (!(markSymbol in this)) { - return; - } - - if (!shouldClear) { - this._handleCallback(name, buffer, this[markSymbol], buffer.length); - setMark(name, 0); - } else { - this._handleCallback(name, buffer, this[markSymbol], i); - clearMarkSymbol(name); - } - }; - - for (i = 0; i < this.bufferLength; i++) { - c = buffer[i]; - switch (state) { - case STATE.PARSER_UNINITIALIZED: - return i; - case STATE.START: - index = 0; - state = STATE.START_BOUNDARY; - case STATE.START_BOUNDARY: - if (index === boundary.length - 2) { - if (c === HYPHEN) { - flags |= FBOUNDARY.LAST_BOUNDARY; - } else if (c !== CR) { - return i; - } - index++; - break; - } else if (index - 1 === boundary.length - 2) { - if (flags & FBOUNDARY.LAST_BOUNDARY && c === HYPHEN) { - this._handleCallback('end'); - state = STATE.END; - flags = 0; - } else if (!(flags & FBOUNDARY.LAST_BOUNDARY) && c === LF) { - index = 0; - this._handleCallback('partBegin'); - state = STATE.HEADER_FIELD_START; - } else { - return i; - } - break; - } - - if (c !== boundary[index + 2]) { - index = -2; - } - if (c === boundary[index + 2]) { - index++; - } - break; - case STATE.HEADER_FIELD_START: - state = STATE.HEADER_FIELD; - setMark('headerField'); - index = 0; - case STATE.HEADER_FIELD: - if (c === CR) { - clearMarkSymbol('headerField'); - state = STATE.HEADERS_ALMOST_DONE; - break; - } - - index++; - if (c === HYPHEN) { - break; - } - - if (c === COLON) { - if (index === 1) { - // empty header field - return i; - } - dataCallback('headerField', true); - state = STATE.HEADER_VALUE_START; - break; - } - - cl = lower(c); - if (cl < A || cl > Z) { - return i; - } - break; - case STATE.HEADER_VALUE_START: - if (c === SPACE) { - break; - } - - setMark('headerValue'); - state = STATE.HEADER_VALUE; - case STATE.HEADER_VALUE: - if (c === CR) { - dataCallback('headerValue', true); - this._handleCallback('headerEnd'); - state = STATE.HEADER_VALUE_ALMOST_DONE; - } - break; - case STATE.HEADER_VALUE_ALMOST_DONE: - if (c !== LF) { - return i; - } - state = STATE.HEADER_FIELD_START; - break; - case STATE.HEADERS_ALMOST_DONE: - if (c !== LF) { - return i; - } - - this._handleCallback('headersEnd'); - state = STATE.PART_DATA_START; - break; - case STATE.PART_DATA_START: - state = STATE.PART_DATA; - setMark('partData'); - case STATE.PART_DATA: - prevIndex = index; - - if (index === 0) { - // boyer-moore derrived algorithm to safely skip non-boundary data - i += boundaryEnd; - while (i < this.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 |= FBOUNDARY.PART_BOUNDARY; - } else if (c === HYPHEN) { - // HYPHEN = end boundary - flags |= FBOUNDARY.LAST_BOUNDARY; - } else { - index = 0; - } - } else if (index - 1 === boundary.length) { - if (flags & FBOUNDARY.PART_BOUNDARY) { - index = 0; - if (c === LF) { - // unset the PART_BOUNDARY flag - flags &= ~FBOUNDARY.PART_BOUNDARY; - this._handleCallback('partEnd'); - this._handleCallback('partBegin'); - state = STATE.HEADER_FIELD_START; - break; - } - } else if (flags & FBOUNDARY.LAST_BOUNDARY) { - if (c === HYPHEN) { - this._handleCallback('partEnd'); - this._handleCallback('end'); - state = STATE.END; - flags = 0; - } 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 - this._handleCallback('partData', lookbehind, 0, prevIndex); - prevIndex = 0; - setMark('partData'); - - // reconsider the current character even so it interrupted the sequence - // it could be the beginning of a new sequence - i--; - } - - break; - case STATE.END: - break; - default: - return i; - } - } - - dataCallback('headerField'); - dataCallback('headerValue'); - dataCallback('partData'); - - this.index = index; - this.state = state; - this.flags = flags; - - done(); - return this.bufferLength; - } - - explain() { - return `state = ${MultipartParser.stateToString(this.state)}`; - } -} - -// eslint-disable-next-line consistent-return -MultipartParser.stateToString = (stateNumber) => { - // eslint-disable-next-line no-restricted-syntax, guard-for-in - for (const stateName in STATE) { - const number = STATE[stateName]; - if (number === stateNumber) return stateName; - } -}; - -module.exports = Object.assign(MultipartParser, { STATES: exports.STATES }); diff --git a/together/node_modules/formidable/src/parsers/OctetStream.js b/together/node_modules/formidable/src/parsers/OctetStream.js deleted file mode 100644 index cdf55f2..0000000 --- a/together/node_modules/formidable/src/parsers/OctetStream.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -const { PassThrough } = require('stream'); - -class OctetStreamParser extends PassThrough { - constructor(options = {}) { - super(); - this.globalOptions = { ...options }; - } -} - -module.exports = OctetStreamParser; diff --git a/together/node_modules/formidable/src/parsers/Querystring.js b/together/node_modules/formidable/src/parsers/Querystring.js deleted file mode 100644 index a0d4243..0000000 --- a/together/node_modules/formidable/src/parsers/Querystring.js +++ /dev/null @@ -1,38 +0,0 @@ -/* eslint-disable no-underscore-dangle */ - -'use strict'; - -const { Transform } = require('stream'); -const querystring = require('querystring'); - -// 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 -class QuerystringParser extends Transform { - constructor(options = {}) { - super({ readableObjectMode: true }); - this.globalOptions = { ...options }; - this.buffer = ''; - this.bufferLength = 0; - } - - _transform(buffer, encoding, callback) { - this.buffer += buffer.toString('ascii'); - this.bufferLength = this.buffer.length; - callback(); - } - - _flush(callback) { - const fields = querystring.parse(this.buffer, '&', '='); - // eslint-disable-next-line no-restricted-syntax, guard-for-in - for (const key in fields) { - this.push({ - key, - value: fields[key], - }); - } - this.buffer = ''; - callback(); - } -} - -module.exports = QuerystringParser; diff --git a/together/node_modules/formidable/src/parsers/StreamingQuerystring.js b/together/node_modules/formidable/src/parsers/StreamingQuerystring.js deleted file mode 100644 index 06d7577..0000000 --- a/together/node_modules/formidable/src/parsers/StreamingQuerystring.js +++ /dev/null @@ -1,121 +0,0 @@ -// not used -/* eslint-disable no-underscore-dangle */ - -'use strict'; - -const { Transform } = require('stream'); -const errors = require('../FormidableError.js'); - -const { FormidableError } = errors; - -const AMPERSAND = 38; -const EQUALS = 61; - -class QuerystringParser extends Transform { - constructor(options = {}) { - super({ readableObjectMode: true }); - - const { maxFieldSize } = options; - this.maxFieldLength = maxFieldSize; - this.buffer = Buffer.from(''); - this.fieldCount = 0; - this.sectionStart = 0; - this.key = ''; - this.readingKey = true; - } - - _transform(buffer, encoding, callback) { - let len = buffer.length; - if (this.buffer && this.buffer.length) { - // we have some data left over from the last write which we are in the middle of processing - len += this.buffer.length; - buffer = Buffer.concat([this.buffer, buffer], len); - } - - for (let i = this.buffer.length || 0; i < len; i += 1) { - const c = buffer[i]; - if (this.readingKey) { - // KEY, check for = - if (c === EQUALS) { - this.key = this.getSection(buffer, i); - this.readingKey = false; - this.sectionStart = i + 1; - } else if (c === AMPERSAND) { - // just key, no value. Prepare to read another key - this.emitField(this.getSection(buffer, i)); - this.sectionStart = i + 1; - } - // VALUE, check for & - } else if (c === AMPERSAND) { - this.emitField(this.key, this.getSection(buffer, i)); - this.sectionStart = i + 1; - } - - if ( - this.maxFieldLength && - i - this.sectionStart === this.maxFieldLength - ) { - callback( - new FormidableError( - `${ - this.readingKey ? 'Key' : `Value for ${this.key}` - } longer than maxFieldLength`, - ), - errors.maxFieldsSizeExceeded, - 413, - ); - } - } - - // Prepare the remaining key or value (from sectionStart to the end) for the next write() or for end() - len -= this.sectionStart; - if (len) { - // i.e. Unless the last character was a & or = - this.buffer = Buffer.from(this.buffer, 0, this.sectionStart); - } else this.buffer = null; - - this.sectionStart = 0; - callback(); - } - - _flush(callback) { - // Emit the last field - if (this.readingKey) { - // we only have a key if there's something in the buffer. We definitely have no value - if (this.buffer && this.buffer.length){ - this.emitField(this.buffer.toString('ascii')); - } - } else { - // We have a key, we may or may not have a value - this.emitField( - this.key, - this.buffer && this.buffer.length && this.buffer.toString('ascii'), - ); - } - this.buffer = ''; - callback(); - } - - getSection(buffer, i) { - if (i === this.sectionStart) return ''; - - return buffer.toString('ascii', this.sectionStart, i); - } - - emitField(key, val) { - this.key = ''; - this.readingKey = true; - this.push({ key, value: val || '' }); - } -} - -module.exports = QuerystringParser; - -// const q = new QuerystringParser({maxFieldSize: 100}); -// (async function() { -// for await (const chunk of q) { -// console.log(chunk); -// } -// })(); -// q.write("a=b&c=d") -// q.end() diff --git a/together/node_modules/formidable/src/parsers/index.js b/together/node_modules/formidable/src/parsers/index.js deleted file mode 100644 index bbf9ef6..0000000 --- a/together/node_modules/formidable/src/parsers/index.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -const JSONParser = require('./JSON'); -const DummyParser = require('./Dummy'); -const MultipartParser = require('./Multipart'); -const OctetStreamParser = require('./OctetStream'); -const QueryStringParser = require('./Querystring'); - -Object.assign(exports, { - JSONParser, - DummyParser, - MultipartParser, - OctetStreamParser, - OctetstreamParser: OctetStreamParser, - QueryStringParser, - QuerystringParser: QueryStringParser, -}); diff --git a/together/node_modules/formidable/src/plugins/index.js b/together/node_modules/formidable/src/plugins/index.js deleted file mode 100644 index cbd491a..0000000 --- a/together/node_modules/formidable/src/plugins/index.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -const octetstream = require('./octetstream'); -const querystring = require('./querystring'); -const multipart = require('./multipart'); -const json = require('./json'); - -Object.assign(exports, { - octetstream, - querystring, - multipart, - json, -}); diff --git a/together/node_modules/formidable/src/plugins/json.js b/together/node_modules/formidable/src/plugins/json.js deleted file mode 100644 index 20d3b26..0000000 --- a/together/node_modules/formidable/src/plugins/json.js +++ /dev/null @@ -1,38 +0,0 @@ -/* eslint-disable no-underscore-dangle */ - -'use strict'; - -const JSONParser = require('../parsers/JSON'); - -// the `options` is also available through the `this.options` / `formidable.options` -module.exports = function plugin(formidable, options) { - // the `this` context is always formidable, as the first argument of a plugin - // but this allows us to customize/test each plugin - - /* istanbul ignore next */ - const self = this || formidable; - - if (/json/i.test(self.headers['content-type'])) { - init.call(self, self, options); - } -}; - -// Note that it's a good practice (but it's up to you) to use the `this.options` instead -// of the passed `options` (second) param, because when you decide -// to test the plugin you can pass custom `this` context to it (and so `this.options`) -function init(_self, _opts) { - this.type = 'json'; - - const parser = new JSONParser(this.options); - - parser.on('data', ({ key, value }) => { - this.emit('field', key, value); - }); - - parser.once('end', () => { - this.ended = true; - this._maybeEnd(); - }); - - this._parser = parser; -} diff --git a/together/node_modules/formidable/src/plugins/multipart.js b/together/node_modules/formidable/src/plugins/multipart.js deleted file mode 100644 index ba07373..0000000 --- a/together/node_modules/formidable/src/plugins/multipart.js +++ /dev/null @@ -1,173 +0,0 @@ -/* eslint-disable no-underscore-dangle */ - -'use strict'; - -const { Stream } = require('stream'); -const MultipartParser = require('../parsers/Multipart'); -const errors = require('../FormidableError.js'); - -const { FormidableError } = errors; - -// the `options` is also available through the `options` / `formidable.options` -module.exports = function plugin(formidable, options) { - // the `this` context is always formidable, as the first argument of a plugin - // but this allows us to customize/test each plugin - - /* istanbul ignore next */ - const self = this || formidable; - - // NOTE: we (currently) support both multipart/form-data and multipart/related - const multipart = /multipart/i.test(self.headers['content-type']); - - if (multipart) { - const m = self.headers['content-type'].match( - /boundary=(?:"([^"]+)"|([^;]+))/i, - ); - if (m) { - const initMultipart = createInitMultipart(m[1] || m[2]); - initMultipart.call(self, self, options); // lgtm [js/superfluous-trailing-arguments] - } else { - const err = new FormidableError( - 'bad content-type header, no multipart boundary', - errors.missingMultipartBoundary, - 400, - ); - self._error(err); - } - } -}; - -// Note that it's a good practice (but it's up to you) to use the `this.options` instead -// of the passed `options` (second) param, because when you decide -// to test the plugin you can pass custom `this` context to it (and so `this.options`) -function createInitMultipart(boundary) { - return function initMultipart() { - this.type = 'multipart'; - - const parser = new MultipartParser(this.options); - let headerField; - let headerValue; - let part; - - parser.initWithBoundary(boundary); - - // eslint-disable-next-line max-statements, consistent-return - parser.on('data', ({ name, buffer, start, end }) => { - if (name === 'partBegin') { - part = new Stream(); - part.readable = true; - part.headers = {}; - part.name = null; - part.originalFilename = null; - part.mimetype = null; - - part.transferEncoding = this.options.encoding; - part.transferBuffer = ''; - - headerField = ''; - headerValue = ''; - } else if (name === 'headerField') { - headerField += buffer.toString(this.options.encoding, start, end); - } else if (name === 'headerValue') { - headerValue += buffer.toString(this.options.encoding, start, end); - } else if (name === 'headerEnd') { - headerField = headerField.toLowerCase(); - part.headers[headerField] = headerValue; - - // matches either a quoted-string or a token (RFC 2616 section 19.5.1) - const m = headerValue.match( - // eslint-disable-next-line no-useless-escape - /\bname=("([^"]*)"|([^\(\)<>@,;:\\"\/\[\]\?=\{\}\s\t/]+))/i, - ); - if (headerField === 'content-disposition') { - if (m) { - part.name = m[2] || m[3] || ''; - } - - part.originalFilename = this._getFileName(headerValue); - } else if (headerField === 'content-type') { - part.mimetype = headerValue; - } else if (headerField === 'content-transfer-encoding') { - part.transferEncoding = headerValue.toLowerCase(); - } - - headerField = ''; - headerValue = ''; - } else if (name === 'headersEnd') { - switch (part.transferEncoding) { - case 'binary': - case '7bit': - case '8bit': - case 'utf-8': { - const dataPropagation = (ctx) => { - if (ctx.name === 'partData') { - part.emit('data', ctx.buffer.slice(ctx.start, ctx.end)); - } - }; - const dataStopPropagation = (ctx) => { - if (ctx.name === 'partEnd') { - part.emit('end'); - parser.off('data', dataPropagation); - parser.off('data', dataStopPropagation); - } - }; - parser.on('data', dataPropagation); - parser.on('data', dataStopPropagation); - break; - } - case 'base64': { - const dataPropagation = (ctx) => { - if (ctx.name === 'partData') { - part.transferBuffer += ctx.buffer - .slice(ctx.start, ctx.end) - .toString('ascii'); - - /* - four bytes (chars) in base64 converts to three bytes in binary - encoding. So we should always work with a number of bytes that - can be divided by 4, it will result in a number of buytes that - can be divided vy 3. - */ - const offset = parseInt(part.transferBuffer.length / 4, 10) * 4; - part.emit( - 'data', - Buffer.from( - part.transferBuffer.substring(0, offset), - 'base64', - ), - ); - part.transferBuffer = part.transferBuffer.substring(offset); - } - }; - const dataStopPropagation = (ctx) => { - if (ctx.name === 'partEnd') { - part.emit('data', Buffer.from(part.transferBuffer, 'base64')); - part.emit('end'); - parser.off('data', dataPropagation); - parser.off('data', dataStopPropagation); - } - }; - parser.on('data', dataPropagation); - parser.on('data', dataStopPropagation); - break; - } - default: - return this._error( - new FormidableError( - 'unknown transfer-encoding', - errors.unknownTransferEncoding, - 501, - ), - ); - } - - this.onPart(part); - } else if (name === 'end') { - this.ended = true; - this._maybeEnd(); - } - }); - - this._parser = parser; - }; -} diff --git a/together/node_modules/formidable/src/plugins/octetstream.js b/together/node_modules/formidable/src/plugins/octetstream.js deleted file mode 100644 index 96fee40..0000000 --- a/together/node_modules/formidable/src/plugins/octetstream.js +++ /dev/null @@ -1,86 +0,0 @@ -/* eslint-disable no-underscore-dangle */ - -'use strict'; - -const OctetStreamParser = require('../parsers/OctetStream'); - -// the `options` is also available through the `options` / `formidable.options` -module.exports = function plugin(formidable, options) { - // the `this` context is always formidable, as the first argument of a plugin - // but this allows us to customize/test each plugin - - /* istanbul ignore next */ - const self = this || formidable; - - if (/octet-stream/i.test(self.headers['content-type'])) { - init.call(self, self, options); - } - - return self; -}; - -// Note that it's a good practice (but it's up to you) to use the `this.options` instead -// of the passed `options` (second) param, because when you decide -// to test the plugin you can pass custom `this` context to it (and so `this.options`) -function init(_self, _opts) { - this.type = 'octet-stream'; - const originalFilename = this.headers['x-file-name']; - const mimetype = this.headers['content-type']; - - const thisPart = { - originalFilename, - mimetype, - }; - const newFilename = this._getNewName(thisPart); - const filepath = this._joinDirectoryName(newFilename); - const file = this._newFile({ - newFilename, - filepath, - originalFilename, - mimetype, - }); - - this.emit('fileBegin', originalFilename, file); - file.open(); - this.openedFiles.push(file); - this._flushing += 1; - - this._parser = new OctetStreamParser(this.options); - - // Keep track of writes that haven't finished so we don't emit the file before it's done being written - let outstandingWrites = 0; - - this._parser.on('data', (buffer) => { - this.pause(); - outstandingWrites += 1; - - file.write(buffer, () => { - outstandingWrites -= 1; - this.resume(); - - if (this.ended) { - this._parser.emit('doneWritingFile'); - } - }); - }); - - this._parser.on('end', () => { - this._flushing -= 1; - this.ended = true; - - const done = () => { - file.end(() => { - this.emit('file', 'file', file); - this._maybeEnd(); - }); - }; - - if (outstandingWrites === 0) { - done(); - } else { - this._parser.once('doneWritingFile', done); - } - }); - - return this; -} diff --git a/together/node_modules/formidable/src/plugins/querystring.js b/together/node_modules/formidable/src/plugins/querystring.js deleted file mode 100644 index c9dcf1e..0000000 --- a/together/node_modules/formidable/src/plugins/querystring.js +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable no-underscore-dangle */ - -'use strict'; - -const QuerystringParser = require('../parsers/Querystring'); - -// the `options` is also available through the `this.options` / `formidable.options` -module.exports = function plugin(formidable, options) { - // the `this` context is always formidable, as the first argument of a plugin - // but this allows us to customize/test each plugin - - /* istanbul ignore next */ - const self = this || formidable; - - if (/urlencoded/i.test(self.headers['content-type'])) { - init.call(self, self, options); - } - - return self; -}; - -// Note that it's a good practice (but it's up to you) to use the `this.options` instead -// of the passed `options` (second) param, because when you decide -// to test the plugin you can pass custom `this` context to it (and so `this.options`) -function init(_self, _opts) { - this.type = 'urlencoded'; - - const parser = new QuerystringParser(this.options); - - parser.on('data', ({ key, value }) => { - this.emit('field', key, value); - }); - - parser.once('end', () => { - this.ended = true; - this._maybeEnd(); - }); - - this._parser = parser; - - return this; -} |