aboutsummaryrefslogtreecommitdiff
path: root/node_modules/formidable
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/formidable')
-rw-r--r--node_modules/formidable/LICENSE22
-rw-r--r--node_modules/formidable/README.md735
-rw-r--r--node_modules/formidable/benchmark-2020-01-29_xeon-x3440.pngbin0 -> 25658 bytes
-rw-r--r--node_modules/formidable/lib/file.js81
-rw-r--r--node_modules/formidable/lib/incoming_form.js558
-rw-r--r--node_modules/formidable/lib/index.js3
-rw-r--r--node_modules/formidable/lib/json_parser.js30
-rw-r--r--node_modules/formidable/lib/multipart_parser.js332
-rw-r--r--node_modules/formidable/lib/octet_parser.js20
-rw-r--r--node_modules/formidable/lib/querystring_parser.js27
-rw-r--r--node_modules/formidable/package.json60
11 files changed, 1868 insertions, 0 deletions
diff --git a/node_modules/formidable/LICENSE b/node_modules/formidable/LICENSE
new file mode 100644
index 0000000..7c66bea
--- /dev/null
+++ b/node_modules/formidable/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2011-present Felix Geisendörfer, and contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/node_modules/formidable/README.md b/node_modules/formidable/README.md
new file mode 100644
index 0000000..e6c5075
--- /dev/null
+++ b/node_modules/formidable/README.md
@@ -0,0 +1,735 @@
+<p align="center">
+ <img alt="npm formidable package logo" src="https://raw.githubusercontent.com/node-formidable/formidable/master/logo.png" />
+</p>
+
+# formidable [![npm version][npmv-img]][npmv-url] [![MIT license][license-img]][license-url] [![Libera Manifesto][libera-manifesto-img]][libera-manifesto-url] [![Twitter][twitter-img]][twitter-url]
+
+> A Node.js module for parsing form data, especially file uploads.
+
+### Important Notes
+
+- This README is for the upcoming (end of February) v2 release!
+- Every version prior and including `v1.2.2` is deprecated, please upgrade!
+- Install with `formidable@canary` until v2 land officially in `latest`
+- see more about the changes in the [CHANGELOG.md](https://github.com/node-formidable/formidable/blob/master/CHANGELOG.md)
+
+[![Code style][codestyle-img]][codestyle-url]
+[![codecoverage][codecov-img]][codecov-url]
+[![linux build status][linux-build-img]][build-url]
+[![windows build status][windows-build-img]][build-url]
+[![macos build status][macos-build-img]][build-url]
+
+If you have any _how-to_ kind of questions, please read the [Contributing
+Guide][contributing-url] and [Code of Conduct][code_of_conduct-url]
+documents.<br /> For bugs reports and feature requests, [please create an
+issue][open-issue-url] or ping [@tunnckoCore](https://twitter.com/tunnckoCore)
+at Twitter.
+
+[![Conventional Commits][ccommits-img]][ccommits-url]
+[![Minimum Required Nodejs][nodejs-img]][npmv-url]
+[![Tidelift Subcsription][tidelift-img]][tidelift-url]
+[![Buy me a Kofi][kofi-img]][kofi-url]
+[![Renovate App Status][renovateapp-img]][renovateapp-url]
+[![Make A Pull Request][prs-welcome-img]][prs-welcome-url]
+
+This project is [semantically versioned](https://semver.org) and available as
+part of the [Tidelift Subscription][tidelift-url] for professional grade
+assurances, enhanced support and security.
+[Learn more.](https://tidelift.com/subscription/pkg/npm-formidable?utm_source=npm-formidable&utm_medium=referral&utm_campaign=enterprise)
+
+_The maintainers of `formidable` and thousands of other packages are working
+with Tidelift to deliver commercial support and maintenance for the Open Source
+dependencies you use to build your applications. Save time, reduce risk, and
+improve code health, while paying the maintainers of the exact dependencies you
+use._
+
+[![][npm-weekly-img]][npmv-url] [![][npm-monthly-img]][npmv-url]
+[![][npm-yearly-img]][npmv-url] [![][npm-alltime-img]][npmv-url]
+
+## Status: Maintained [![npm version][npmv-canary-img]][npmv-url]
+
+This module was initially developed by
+[**@felixge**](https://github.com/felixge) for
+[Transloadit](http://transloadit.com/), a service focused on uploading and
+encoding images and videos. It has been battle-tested against hundreds of GBs of
+file uploads from a large variety of clients and is considered production-ready
+and is used in production for years.
+
+Currently, we are few maintainers trying to deal with it. :) More contributors
+are always welcome! :heart: Jump on
+[issue #412](https://github.com/felixge/node-formidable/issues/412) which is
+closed, but if you are interested we can discuss it and add you after strict rules, like
+enabling Two-Factor Auth in your npm and GitHub accounts.
+
+_**Note:** The github `master` branch is a "canary" branch - try it with `npm i formidable@canary`.
+Do not expect (for now) things from it to be inside the`latest` "dist-tag" in the
+Npm. The`formidable@latest`is the`v1.2.1` version and probably it will be the
+last`v1` release!_
+
+_**Note: v2 is coming soon!**_
+
+## Highlights
+
+- [Fast (~900-2500 mb/sec)](#benchmarks) & streaming multipart parser
+- Automatically writing file uploads to disk (soon optionally)
+- [Plugins API](#useplugin-plugin) - allowing custom parsers and plugins
+- Low memory footprint
+- Graceful error handling
+- Very high test coverage
+
+## Install
+
+This project requires `Node.js >= 10.13`. Install it using
+[yarn](https://yarnpkg.com) or [npm](https://npmjs.com).<br /> _We highly
+recommend to use Yarn when you think to contribute to this project._
+
+```sh
+npm install formidable
+# or the canary version
+npm install formidable@canary
+```
+
+or with Yarn v1/v2
+
+```sh
+yarn add formidable
+# or the canary version
+yarn add formidable@canary
+```
+
+This is a low-level package, and if you're using a high-level framework it _may_
+already be included. Check the examples below and the `examples/` folder.
+
+## Examples
+
+For more examples look at the `examples/` directory.
+
+### with Node.js http module
+
+Parse an incoming file upload, with the
+[Node.js's built-in `http` module](https://nodejs.org/api/http.html).
+
+```js
+const http = require('http');
+const formidable = require('formidable');
+
+const server = http.createServer((req, res) => {
+ if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
+ // parse a file upload
+ const form = formidable({ multiples: true });
+
+ form.parse(req, (err, fields, files) => {
+ res.writeHead(200, { 'content-type': 'application/json' });
+ res.end(JSON.stringify({ fields, files }, null, 2));
+ });
+
+ return;
+ }
+
+ // show a file upload form
+ res.writeHead(200, { 'content-type': 'text/html' });
+ res.end(`
+ <h2>With Node.js <code>"http"</code> module</h2>
+ <form action="/api/upload" enctype="multipart/form-data" method="post">
+ <div>Text field title: <input type="text" name="title" /></div>
+ <div>File: <input type="file" name="multipleFiles" multiple="multiple" /></div>
+ <input type="submit" value="Upload" />
+ </form>
+ `);
+});
+
+server.listen(8080, () => {
+ console.log('Server listening on http://localhost:8080/ ...');
+});
+```
+
+### with Express.js
+
+There are multiple variants to do this, but Formidable just need Node.js Request
+stream, so something like the following example should work just fine, without
+any third-party [Express.js](https://ghub.now.sh/express) middleware.
+
+Or try the
+[examples/with-express.js](https://github.com/node-formidable/node-formidable/blob/master/examples/with-express.js)
+
+```js
+const express = require('express');
+const formidable = require('formidable');
+
+const app = express();
+
+app.get('/', (req, res) => {
+ res.send(`
+ <h2>With <code>"express"</code> npm package</h2>
+ <form action="/api/upload" enctype="multipart/form-data" method="post">
+ <div>Text field title: <input type="text" name="title" /></div>
+ <div>File: <input type="file" name="someExpressFiles" multiple="multiple" /></div>
+ <input type="submit" value="Upload" />
+ </form>
+ `);
+});
+
+app.post('/api/upload', (req, res, next) => {
+ const form = formidable({ multiples: true });
+
+ form.parse(req, (err, fields, files) => {
+ if (err) {
+ next(err);
+ return;
+ }
+ res.json({ fields, files });
+ });
+});
+
+app.listen(3000, () => {
+ console.log('Server listening on http://localhost:3000 ...');
+});
+```
+
+### with Koa and Formidable
+
+Of course, with [Koa v1, v2 or future v3](https://ghub.now.sh/koa) the things
+are very similar. You can use `formidable` manually as shown below or through
+the [koa-better-body](https://ghub.now.sh/koa-better-body) package which is
+using `formidable` under the hood and support more features and different
+request bodies, check its documentation for more info.
+
+_Note: this example is assuming Koa v2. Be aware that you should pass `ctx.req`
+which is Node.js's Request, and **NOT** the `ctx.request` which is Koa's Request
+object - there is a difference._
+
+```js
+const Koa = require('koa');
+const formidable = require('formidable');
+
+const app = new Koa();
+
+app.on('error', (err) => {
+ console.error('server error', err);
+});
+
+app.use(async (ctx, next) => {
+ if (ctx.url === '/api/upload' && ctx.method.toLowerCase() === 'post') {
+ const form = formidable({ multiples: true });
+
+ // not very elegant, but that's for now if you don't want touse `koa-better-body`
+ // or other middlewares.
+ await new Promise((resolve, reject) => {
+ form.parse(ctx.req, (err, fields, files) => {
+ if (err) {
+ reject(err);
+ return;
+ }
+
+ ctx.set('Content-Type', 'application/json');
+ ctx.status = 200;
+ ctx.state = { fields, files };
+ ctx.body = JSON.stringify(ctx.state, null, 2);
+ resolve();
+ });
+ });
+ await next();
+ return;
+ }
+
+ // show a file upload form
+ ctx.set('Content-Type', 'text/html');
+ ctx.status = 200;
+ ctx.body = `
+ <h2>With <code>"koa"</code> npm package</h2>
+ <form action="/api/upload" enctype="multipart/form-data" method="post">
+ <div>Text field title: <input type="text" name="title" /></div>
+ <div>File: <input type="file" name="koaFiles" multiple="multiple" /></div>
+ <input type="submit" value="Upload" />
+ </form>
+ `;
+});
+
+app.use((ctx) => {
+ console.log('The next middleware is called');
+ console.log('Results:', ctx.state);
+});
+
+app.listen(3000, () => {
+ console.log('Server listening on http://localhost:3000 ...');
+});
+```
+
+## Benchmarks (for v2)
+
+The benchmark is quite old, from the old codebase. But maybe quite true though.
+Previously the numbers was around ~500 mb/sec. Currently with moving to the new
+Node.js Streams API it's faster. You can clearly see the differences between the
+Node versions.
+
+_Note: a lot better benchmarking could and should be done in future._
+
+Benchmarked on 8GB RAM, Xeon X3440 (2.53 GHz, 4 cores, 8 threads)
+
+```
+~/github/node-formidable master
+❯ nve --parallel 8 10 12 13 node benchmark/bench-multipart-parser.js
+
+ ⬢ Node 8
+
+1261.08 mb/sec
+
+ ⬢ Node 10
+
+1113.04 mb/sec
+
+ ⬢ Node 12
+
+2107.00 mb/sec
+
+ ⬢ Node 13
+
+2566.42 mb/sec
+```
+
+![benchmark January 29th, 2020](./benchmark-2020-01-29_xeon-x3440.png)
+
+## API
+
+### Formidable / IncomingForm
+
+All shown are equivalent.
+
+_Please pass [`options`](#options) to the function/constructor, not by assigning
+them to the instance `form`_
+
+```js
+const formidable = require('formidable');
+const form = formidable(options);
+
+// or
+const { formidable } = require('formidable');
+const form = formidable(options);
+
+// or
+const { IncomingForm } = require('formidable');
+const form = new IncomingForm(options);
+
+// or
+const { Formidable } = require('formidable');
+const form = new Formidable(options);
+```
+
+### Options
+
+See it's defaults in [src/Formidable.js](./src/Formidable.js#L14-L22) (the
+`DEFAULT_OPTIONS` constant).
+
+- `options.encoding` **{string}** - default `'utf-8'`; sets encoding for
+ incoming form fields,
+- `options.uploadDir` **{string}** - default `os.tmpdir()`; the directory for
+ placing file uploads in. You can move them later by using `fs.rename()`
+- `options.keepExtensions` **{boolean}** - default `false`; to include the
+ extensions of the original files or not
+- `options.maxFileSize` **{number}** - default `200 * 1024 * 1024` (200mb);
+ limit the size of uploaded file.
+- `options.maxFields` **{number}** - default `1000`; limit the number of fields
+ that the Querystring parser will decode, set 0 for unlimited
+- `options.maxFieldsSize` **{number}** - default `20 * 1024 * 1024` (20mb);
+ limit the amount of memory all fields together (except files) can allocate in
+ bytes.
+- `options.hash` **{boolean}** - default `false`; include checksums calculated
+ for incoming files, set this to some hash algorithm, see
+ [crypto.createHash](https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options)
+ for available algorithms
+- `options.multiples` **{boolean}** - default `false`; when you call the
+ `.parse` method, the `files` argument (of the callback) will contain arrays of
+ files for inputs which submit multiple files using the HTML5 `multiple`
+ attribute. Also, the `fields` argument will contain arrays of values for
+ fields that have names ending with '[]'.
+
+_**Note:** If this size of combined fields, or size of some file is exceeded, an
+`'error'` event is fired._
+
+```js
+// The amount of bytes received for this form so far.
+form.bytesReceived;
+```
+
+```js
+// The expected number of bytes in this form.
+form.bytesExpected;
+```
+
+### .parse(request, callback)
+
+Parses an incoming Node.js `request` containing form data. If `callback` is
+provided, all fields and files are collected and passed to the callback.
+
+```js
+const formidable = require('formidable');
+
+const form = formidable({ multiples: true, uploadDir: __dirname });
+
+form.parse(req, (err, fields, files) => {
+ console.log('fields:', fields);
+ console.log('files:', files);
+});
+```
+
+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.
+
+In the example below, we listen on couple of events and direct them to the
+`data` listener, so you can do whatever you choose there, based on whether its
+before the file been emitted, the header value, the header name, on field, on
+file and etc.
+
+Or the other way could be to just override the `form.onPart` as it's shown a bit
+later.
+
+```js
+form.once('error', console.error);
+
+form.on('fileBegin', (filename, file) => {
+ form.emit('data', { name: 'fileBegin', filename, value: file });
+});
+
+form.on('file', (filename, file) => {
+ form.emit('data', { name: 'file', key: filename, value: file });
+});
+
+form.on('field', (fieldName, fieldValue) => {
+ form.emit('data', { name: 'field', key: fieldName, value: fieldValue });
+});
+
+form.once('end', () => {
+ console.log('Done!');
+});
+
+// If you want to customize whatever you want...
+form.on('data', ({ name, key, value, buffer, start, end, ...more }) => {
+ if (name === 'partBegin') {
+ }
+ if (name === 'partData') {
+ }
+ if (name === 'headerField') {
+ }
+ if (name === 'headerValue') {
+ }
+ if (name === 'headerEnd') {
+ }
+ if (name === 'headersEnd') {
+ }
+ if (name === 'field') {
+ console.log('field name:', key);
+ console.log('field value:', value);
+ }
+ if (name === 'file') {
+ console.log('file:', key, value);
+ }
+ if (name === 'fileBegin') {
+ console.log('fileBegin:', key, value);
+ }
+});
+```
+
+### .use(plugin: Plugin)
+
+A method that allows you to extend the Formidable library. By default we include
+4 plugins, which esentially are adapters to plug the different built-in parsers.
+
+**The plugins added by this method are always enabled.**
+
+_See [src/plugins/](./src/plugins/) for more detailed look on default plugins._
+
+The `plugin` param has such signature:
+
+```typescript
+function(formidable: Formidable, options: Options): void;
+```
+
+The architecture is simple. The `plugin` is a function that is passed with the
+Formidable instance (the `form` across the README examples) and the options.
+
+**Note:** the plugin function's `this` context is also the same instance.
+
+```js
+const formidable = require('formidable');
+
+const form = formidable({ keepExtensions: true });
+
+form.use((self, options) => {
+ // self === this === form
+ console.log('woohoo, custom plugin');
+ // do your stuff; check `src/plugins` for inspiration
+});
+
+form.parse(req, (error, fields, files) => {
+ console.log('done!');
+});
+```
+
+**Important to note**, is that inside plugin `this.options`, `self.options` and
+`options` MAY or MAY NOT be the same. General best practice is to always use the
+`this`, so you can later test your plugin independently and more easily.
+
+If you want to disable some parsing capabilities of Formidable, you can disable
+the plugin which corresponds to the parser. For example, if you want to disable
+multipart parsing (so the [src/parsers/Multipart.js](./src/parsers/Multipart.js)
+which is used in [src/plugins/multipart.js](./src/plugins/multipart.js)), then
+you can remove it from the `options.enabledPlugins`, like so
+
+```js
+const { Formidable } = require('formidable');
+
+const form = new Formidable({
+ hash: 'sha1',
+ enabledPlugins: ['octetstream', 'querystring', 'json'],
+});
+```
+
+**Be aware** that the order _MAY_ be important too. The names corresponds 1:1 to
+files in [src/plugins/](./src/plugins) folder.
+
+Pull requests for new built-in plugins MAY be accepted - for example, more
+advanced querystring parser. Add your plugin as a new file in `src/plugins/`
+folder (lowercased) and follow how the other plugins are made.
+
+### form.onPart
+
+If you want to use Formidable to only handle certain parts for you, you can do
+something similar. Or see
+[#387](https://github.com/node-formidable/node-formidable/issues/387) for
+inspiration, you can for example validate the mime-type.
+
+```js
+const form = formidable();
+
+form.onPart = (part) => {
+ part.on('data', (buffer) {
+ // do whatever you want here
+ });
+};
+```
+
+For example, force Formidable to be used only on non-file "parts" (i.e., html
+fields)
+
+```js
+const form = formidable();
+
+form.onPart = function(part) {
+ // let formidable handle only non-file parts
+ if (part.filename === '' || !part.mime) {
+ // used internally, please do not override!
+ form.handlePart(part);
+ }
+};
+```
+
+### File
+
+```ts
+export interface File {
+ // 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.size: number;
+
+ // 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.path: string;
+
+ // The name this file had according to the uploading client.
+ file.name: string | null;
+
+ // The mime type of this file, according to the uploading client.
+ file.type: string | 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.lastModifiedDate: Date | null;
+
+ // If `options.hash` calculation was set, you can read the hex digest out of this var.
+ file.hash: string | 'sha1' | 'md5' | 'sha256' | null;
+}
+```
+
+#### file.toJSON()
+
+This method returns a JSON-representation of the file, allowing you to
+`JSON.stringify()` the file which is useful for logging and responding to
+requests.
+
+### Events
+
+#### `'progress'`
+
+Emitted after each incoming chunk of data that has been parsed. Can be used to
+roll your own progress bar.
+
+```js
+form.on('progress', (bytesReceived, bytesExpected) => {});
+```
+
+#### `'field'`
+
+Emitted whenever a field / value pair has been received.
+
+```js
+form.on('field', (name, value) => {});
+```
+
+#### `'fileBegin'`
+
+Emitted whenever a new file is detected in the upload stream. Use this event if
+you want to stream the file to somewhere else while buffering the upload on the
+file system.
+
+```js
+form.on('fileBegin', (name, file) => {});
+```
+
+#### `'file'`
+
+Emitted whenever a field / file pair has been received. `file` is an instance of
+`File`.
+
+```js
+form.on('file', (name, file) => {});
+```
+
+#### `'error'`
+
+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.
+
+```js
+form.on('error', (err) => {});
+```
+
+#### `'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. After this event is emitted, an
+`error` event will follow. In the future there will be a separate 'timeout'
+event (needs a change in the node core).
+
+```js
+form.on('aborted', () => {});
+```
+
+#### `'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.
+
+```js
+form.on('end', () => {});
+```
+
+## Ports & Credits
+
+- [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++
+ parser based on formidable
+- [Ryan Dahl](http://twitter.com/ryah) for his work on
+ [http-parser](http://github.com/ry/http-parser) which heavily inspired the
+ initial `multipart_parser.js`.
+
+## Contributing
+
+If the documentation is unclear or has a typo, please click on the page's `Edit`
+button (pencil icon) and suggest a correction. If you would like to help us fix
+a bug or add a new feature, please check our
+[Contributing Guide](./CONTRIBUTING.md). Pull requests are welcome!
+
+Thanks goes to these wonderful people
+([emoji key](https://allcontributors.org/docs/en/emoji-key)):
+
+<!-- ALL-CONTRIBUTORS-LIST:START -->
+<!-- prettier-ignore-start -->
+<!-- markdownlint-disable -->
+<table>
+ <tr>
+ <td align="center"><a href="https://twitter.com/felixge"><img src="https://avatars3.githubusercontent.com/u/15000?s=460&v=4" width="100px;" alt=""/><br /><sub><b>Felix Geisendörfer</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=felixge" title="Code">💻</a> <a href="#design-felixge" title="Design">🎨</a> <a href="#ideas-felixge" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=felixge" title="Documentation">📖</a></td>
+ <td align="center"><a href="https://tunnckoCore.com"><img src="https://avatars3.githubusercontent.com/u/5038030?v=4" width="100px;" alt=""/><br /><sub><b>Charlike Mike Reagent</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3AtunnckoCore" title="Bug reports">🐛</a> <a href="#infra-tunnckoCore" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#design-tunnckoCore" title="Design">🎨</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=tunnckoCore" title="Code">💻</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=tunnckoCore" title="Documentation">📖</a> <a href="#example-tunnckoCore" title="Examples">💡</a> <a href="#ideas-tunnckoCore" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-tunnckoCore" title="Maintenance">🚧</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=tunnckoCore" title="Tests">⚠️</a></td>
+ <td align="center"><a href="https://github.com/kedarv"><img src="https://avatars1.githubusercontent.com/u/1365665?v=4" width="100px;" alt=""/><br /><sub><b>Kedar</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=kedarv" title="Code">💻</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=kedarv" title="Tests">⚠️</a> <a href="#question-kedarv" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Akedarv" title="Bug reports">🐛</a></td>
+ <td align="center"><a href="https://github.com/GrosSacASac"><img src="https://avatars0.githubusercontent.com/u/5721194?v=4" width="100px;" alt=""/><br /><sub><b>Walle Cyril</b></sub></a><br /><a href="#question-GrosSacASac" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3AGrosSacASac" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=GrosSacASac" title="Code">💻</a> <a href="#financial-GrosSacASac" title="Financial">💵</a> <a href="#ideas-GrosSacASac" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-GrosSacASac" title="Maintenance">🚧</a></td>
+ <td align="center"><a href="https://github.com/xarguments"><img src="https://avatars2.githubusercontent.com/u/40522463?v=4" width="100px;" alt=""/><br /><sub><b>Xargs</b></sub></a><br /><a href="#question-xarguments" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Axarguments" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=xarguments" title="Code">💻</a> <a href="#maintenance-xarguments" title="Maintenance">🚧</a></td>
+ <td align="center"><a href="https://github.com/Amit-A"><img src="https://avatars1.githubusercontent.com/u/7987238?v=4" width="100px;" alt=""/><br /><sub><b>Amit-A</b></sub></a><br /><a href="#question-Amit-A" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3AAmit-A" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=Amit-A" title="Code">💻</a></td>
+ </tr>
+ <tr>
+ <td align="center"><a href="https://charmander.me/"><img src="https://avatars1.githubusercontent.com/u/1889843?v=4" width="100px;" alt=""/><br /><sub><b>Charmander</b></sub></a><br /><a href="#question-charmander" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Acharmander" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=charmander" title="Code">💻</a> <a href="#ideas-charmander" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-charmander" title="Maintenance">🚧</a></td>
+ <td align="center"><a href="https://twitter.com/dylan_piercey"><img src="https://avatars2.githubusercontent.com/u/4985201?v=4" width="100px;" alt=""/><br /><sub><b>Dylan Piercey</b></sub></a><br /><a href="#ideas-DylanPiercey" title="Ideas, Planning, & Feedback">🤔</a></td>
+ <td align="center"><a href="http://ochrona.jawne.info.pl"><img src="https://avatars1.githubusercontent.com/u/3618479?v=4" width="100px;" alt=""/><br /><sub><b>Adam Dobrawy</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Aad-m" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=ad-m" title="Documentation">📖</a></td>
+ <td align="center"><a href="https://github.com/amitrohatgi"><img src="https://avatars3.githubusercontent.com/u/12177021?v=4" width="100px;" alt=""/><br /><sub><b>amitrohatgi</b></sub></a><br /><a href="#ideas-amitrohatgi" title="Ideas, Planning, & Feedback">🤔</a></td>
+ <td align="center"><a href="https://github.com/fengxinming"><img src="https://avatars2.githubusercontent.com/u/6262382?v=4" width="100px;" alt=""/><br /><sub><b>Jesse Feng</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Afengxinming" title="Bug reports">🐛</a></td>
+ <td align="center"><a href="https://qtmsheep.com"><img src="https://avatars1.githubusercontent.com/u/7271496?v=4" width="100px;" alt=""/><br /><sub><b>Nathanael Demacon</b></sub></a><br /><a href="#question-quantumsheep" title="Answering Questions">💬</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=quantumsheep" title="Code">💻</a> <a href="https://github.com/node-formidable/node-formidable/pulls?q=is%3Apr+reviewed-by%3Aquantumsheep" title="Reviewed Pull Requests">👀</a></td>
+ </tr>
+ <tr>
+ <td align="center"><a href="https://github.com/MunMunMiao"><img src="https://avatars1.githubusercontent.com/u/18216142?v=4" width="100px;" alt=""/><br /><sub><b>MunMunMiao</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3AMunMunMiao" title="Bug reports">🐛</a></td>
+ <td align="center"><a href="https://github.com/gabipetrovay"><img src="https://avatars0.githubusercontent.com/u/1170398?v=4" width="100px;" alt=""/><br /><sub><b>Gabriel Petrovay</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/issues?q=author%3Agabipetrovay" title="Bug reports">🐛</a> <a href="https://github.com/node-formidable/node-formidable/commits?author=gabipetrovay" title="Code">💻</a></td>
+ <td align="center"><a href="https://github.com/Elzair"><img src="https://avatars0.githubusercontent.com/u/2352818?v=4" width="100px;" alt=""/><br /><sub><b>Philip Woods</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=Elzair" title="Code">💻</a> <a href="#ideas-Elzair" title="Ideas, Planning, & Feedback">🤔</a></td>
+ <td align="center"><a href="https://github.com/dmolim"><img src="https://avatars2.githubusercontent.com/u/7090374?v=4" width="100px;" alt=""/><br /><sub><b>Dmitry Ivonin</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=dmolim" title="Documentation">📖</a></td>
+ <td align="center"><a href="https://audiobox.fm"><img src="https://avatars1.githubusercontent.com/u/12844?v=4" width="100px;" alt=""/><br /><sub><b>Claudio Poli</b></sub></a><br /><a href="https://github.com/node-formidable/node-formidable/commits?author=masterkain" title="Code">💻</a></td>
+ </tr>
+</table>
+
+<!-- markdownlint-enable -->
+<!-- prettier-ignore-end -->
+
+<!-- ALL-CONTRIBUTORS-LIST:END -->
+
+## License
+
+Formidable is licensed under the [MIT License][license-url].
+
+<!-- badges -->
+<!-- prettier-ignore-start -->
+
+[codestyle-url]: https://github.com/airbnb/javascript
+[codestyle-img]: https://badgen.net/badge/code%20style/airbnb%20%2B%20prettier/ff5a5f?icon=airbnb&cache=300
+[codecov-url]: https://codecov.io/gh/node-formidable/node-formidable
+[codecov-img]: https://badgen.net/codecov/c/github/node-formidable/node-formidable/master?icon=codecov
+[npmv-canary-img]: https://badgen.net/npm/v/formidable/canary?icon=npm
+[npmv-dev-img]: https://badgen.net/npm/v/formidable/dev?icon=npm
+[npmv-img]: https://badgen.net/npm/v/formidable?icon=npm
+[npmv-url]: https://npmjs.com/package/formidable
+[license-img]: https://badgen.net/npm/license/formidable
+[license-url]: https://github.com/node-formidable/node-formidable/blob/master/LICENSE
+[chat-img]: https://badgen.net/badge/chat/on%20gitter/46BC99?icon=gitter
+[chat-url]: https://gitter.im/node-formidable/Lobby
+[libera-manifesto-url]: https://liberamanifesto.com
+[libera-manifesto-img]: https://badgen.net/badge/libera/manifesto/grey
+[renovateapp-url]: https://renovatebot.com
+[renovateapp-img]: https://badgen.net/badge/renovate/enabled/green?cache=300
+[prs-welcome-img]: https://badgen.net/badge/PRs/welcome/green?cache=300
+[prs-welcome-url]: http://makeapullrequest.com
+[twitter-url]: https://twitter.com/tunnckoCore
+[twitter-img]: https://badgen.net/twitter/follow/tunnckoCore?icon=twitter&color=1da1f2&cache=300
+
+[npm-weekly-img]: https://badgen.net/npm/dw/formidable?icon=npm&cache=300
+[npm-monthly-img]: https://badgen.net/npm/dm/formidable?icon=npm&cache=300
+[npm-yearly-img]: https://badgen.net/npm/dy/formidable?icon=npm&cache=300
+[npm-alltime-img]: https://badgen.net/npm/dt/formidable?icon=npm&cache=300&label=total%20downloads
+
+[nodejs-img]: https://badgen.net/badge/node/>=%2010.13/green?cache=300
+
+[ccommits-url]: https://conventionalcommits.org/
+[ccommits-img]: https://badgen.net/badge/conventional%20commits/v1.0.0/green?cache=300
+
+[contributing-url]: https://github.com/node-formidable/node-formidable/blob/master/CONTRIBUTING.md
+[code_of_conduct-url]: https://github.com/node-formidable/node-formidable/blob/master/CODE_OF_CONDUCT.md
+
+[open-issue-url]: https://github.com/node-formidable/node-formidable/issues/new
+
+[tidelift-url]: https://tidelift.com/subscription/pkg/npm-formidable?utm_source=npm-formidable&utm_medium=referral&utm_campaign=enterprise
+[tidelift-img]: https://badgen.net/badge/tidelift/subscription/4B5168?labelColor=F6914D
+
+[kofi-url]: https://ko-fi.com/tunnckoCore/commissions
+[kofi-img]: https://badgen.net/badge/ko-fi/support/29abe0c2?cache=300&icon=https://rawcdn.githack.com/tunnckoCore/badgen-icons/f8264c6414e0bec449dd86f2241d50a9b89a1203/icons/kofi.svg
+
+[linux-build-img]: https://badgen-net.charlike.now.sh/github/checks/node-formidable/node-formidable?label=linux%20build&icon=github
+[macos-build-img]: https://badgen-net.charlike.now.sh/github/checks/node-formidable/node-formidable?label=macos%20build&icon=github
+[windows-build-img]: https://badgen-net.charlike.now.sh/github/checks/node-formidable/node-formidable?label=windows%20build&icon=github
+[build-url]: https://github.com/node-formidable/node-formidable/actions?query=workflow%3Anodejs
+<!-- prettier-ignore-end -->
diff --git a/node_modules/formidable/benchmark-2020-01-29_xeon-x3440.png b/node_modules/formidable/benchmark-2020-01-29_xeon-x3440.png
new file mode 100644
index 0000000..ef6f0fb
--- /dev/null
+++ b/node_modules/formidable/benchmark-2020-01-29_xeon-x3440.png
Binary files differ
diff --git a/node_modules/formidable/lib/file.js b/node_modules/formidable/lib/file.js
new file mode 100644
index 0000000..50d34c0
--- /dev/null
+++ b/node_modules/formidable/lib/file.js
@@ -0,0 +1,81 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+var util = require('util'),
+ fs = require('fs'),
+ 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);
+ } else {
+ this.hash = null;
+ }
+}
+module.exports = File;
+util.inherits(File, EventEmitter);
+
+File.prototype.open = function() {
+ this._writeStream = new fs.WriteStream(this.path);
+};
+
+File.prototype.toJSON = function() {
+ var json = {
+ size: this.size,
+ path: this.path,
+ name: this.name,
+ type: this.type,
+ mtime: this.lastModifiedDate,
+ length: this.length,
+ filename: this.filename,
+ mime: this.mime
+ };
+ if (this.hash && this.hash != "") {
+ json.hash = this.hash;
+ }
+ return json;
+};
+
+File.prototype.write = function(buffer, cb) {
+ var self = this;
+ if (self.hash) {
+ self.hash.update(buffer);
+ }
+
+ if (this._writeStream.closed) {
+ return cb();
+ }
+
+ this._writeStream.write(buffer, function() {
+ self.lastModifiedDate = new Date();
+ self.size += buffer.length;
+ self.emit('progress', self.size);
+ cb();
+ });
+};
+
+File.prototype.end = function(cb) {
+ var self = this;
+ if (self.hash) {
+ self.hash = self.hash.digest('hex');
+ }
+ this._writeStream.end(function() {
+ self.emit('end');
+ cb();
+ });
+};
diff --git a/node_modules/formidable/lib/incoming_form.js b/node_modules/formidable/lib/incoming_form.js
new file mode 100644
index 0000000..dbd920b
--- /dev/null
+++ b/node_modules/formidable/lib/incoming_form.js
@@ -0,0 +1,558 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+var crypto = require('crypto');
+var fs = require('fs');
+var util = require('util'),
+ path = require('path'),
+ File = require('./file'),
+ MultipartParser = require('./multipart_parser').MultipartParser,
+ QuerystringParser = require('./querystring_parser').QuerystringParser,
+ OctetParser = require('./octet_parser').OctetParser,
+ JSONParser = require('./json_parser').JSONParser,
+ StringDecoder = require('string_decoder').StringDecoder,
+ EventEmitter = require('events').EventEmitter,
+ Stream = require('stream').Stream,
+ os = require('os');
+
+function IncomingForm(opts) {
+ if (!(this instanceof IncomingForm)) return new IncomingForm(opts);
+ EventEmitter.call(this);
+
+ opts=opts||{};
+
+ this.error = null;
+ this.ended = false;
+
+ this.maxFields = opts.maxFields || 1000;
+ this.maxFieldsSize = opts.maxFieldsSize || 20 * 1024 * 1024;
+ this.maxFileSize = opts.maxFileSize || 200 * 1024 * 1024;
+ this.keepExtensions = opts.keepExtensions || false;
+ this.uploadDir = opts.uploadDir || (os.tmpdir && os.tmpdir()) || os.tmpDir();
+ this.encoding = opts.encoding || 'utf-8';
+ this.headers = null;
+ this.type = null;
+ this.hash = opts.hash || false;
+ this.multiples = opts.multiples || false;
+
+ this.bytesReceived = null;
+ this.bytesExpected = null;
+
+ this._parser = null;
+ this._flushing = 0;
+ this._fieldsSize = 0;
+ this._fileSize = 0;
+ this.openedFiles = [];
+
+ return this;
+}
+util.inherits(IncomingForm, EventEmitter);
+exports.IncomingForm = IncomingForm;
+
+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;
+ };
+
+ // Setup callback first, so we don't miss anything from data events emitted
+ // immediately.
+ if (cb) {
+ var fields = {}, files = {};
+ this
+ .on('field', function(name, value) {
+ fields[name] = value;
+ })
+ .on('file', function(name, file) {
+ if (this.multiples) {
+ if (files[name]) {
+ if (!Array.isArray(files[name])) {
+ files[name] = [files[name]];
+ }
+ files[name].push(file);
+ } else {
+ files[name] = file;
+ }
+ } else {
+ files[name] = file;
+ }
+ })
+ .on('error', function(err) {
+ cb(err, fields, files);
+ })
+ .on('end', function() {
+ cb(null, fields, files);
+ });
+ }
+
+ // Parse headers and setup the parser, ready to start listening for data.
+ this.writeHeaders(req.headers);
+
+ // Start listening for data.
+ var self = this;
+ req
+ .on('error', function(err) {
+ self._error(err);
+ })
+ .on('aborted', function() {
+ self.emit('aborted');
+ self._error(new Error('Request 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);
+ }
+ });
+
+ return this;
+};
+
+IncomingForm.prototype.writeHeaders = function(headers) {
+ this.headers = headers;
+ this._parseContentLength();
+ this._parseContentType();
+};
+
+IncomingForm.prototype.write = function(buffer) {
+ if (this.error) {
+ return;
+ }
+ if (!this._parser) {
+ this._error(new Error('uninitialized 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;
+
+ // This MUST check exactly for undefined. You can not change it to !part.filename.
+ 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();
+ this.openedFiles.push(file);
+
+ part.on('data', function(buffer) {
+ self._fileSize += buffer.length;
+ if (self._fileSize > self.maxFileSize) {
+ self._error(new Error('maxFileSize exceeded, received '+self._fileSize+' bytes of file data'));
+ return;
+ }
+ if (buffer.length == 0) {
+ return;
+ }
+ 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();
+ });
+ });
+};
+
+function dummyParser(self) {
+ return {
+ end: function () {
+ self.ended = true;
+ self._maybeEnd();
+ return null;
+ }
+ };
+}
+
+IncomingForm.prototype._parseContentType = function() {
+ if (this.bytesExpected === 0) {
+ this._parser = dummyParser(this);
+ return;
+ }
+
+ if (!this.headers['content-type']) {
+ this._error(new Error('bad content-type header, no content-type'));
+ return;
+ }
+
+ if (this.headers['content-type'].match(/octet-stream/i)) {
+ this._initOctetStream();
+ return;
+ }
+
+ if (this.headers['content-type'].match(/urlencoded/i)) {
+ this._initUrlencoded();
+ return;
+ }
+
+ if (this.headers['content-type'].match(/multipart/i)) {
+ var m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i);
+ if (m) {
+ this._initMultipart(m[1] || m[2]);
+ } else {
+ this._error(new Error('bad content-type header, no multipart boundary'));
+ }
+ return;
+ }
+
+ if (this.headers['content-type'].match(/json/i)) {
+ this._initJSONencoded();
+ return;
+ }
+
+ this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type']));
+};
+
+IncomingForm.prototype._error = function(err) {
+ if (this.error || this.ended) {
+ return;
+ }
+
+ this.error = err;
+ this.emit('error', err);
+
+ if (Array.isArray(this.openedFiles)) {
+ this.openedFiles.forEach(function(file) {
+ file._writeStream.destroy();
+ setTimeout(fs.unlink, 0, file.path, function(error) { });
+ });
+ }
+};
+
+IncomingForm.prototype._parseContentLength = function() {
+ 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);
+ }
+};
+
+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;
+
+ part.transferEncoding = 'binary';
+ part.transferBuffer = '';
+
+ 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;
+
+ // matches either a quoted-string or a token (RFC 2616 section 19.5.1)
+ var m = headerValue.match(/\bname=("([^"]*)"|([^\(\)<>@,;:\\"\/\[\]\?=\{\}\s\t/]+))/i);
+ if (headerField == 'content-disposition') {
+ if (m) {
+ part.name = m[2] || m[3] || '';
+ }
+
+ part.filename = self._fileName(headerValue);
+ } else if (headerField == 'content-type') {
+ part.mime = headerValue;
+ } else if (headerField == 'content-transfer-encoding') {
+ part.transferEncoding = headerValue.toLowerCase();
+ }
+
+ headerField = '';
+ headerValue = '';
+ };
+
+ parser.onHeadersEnd = function() {
+ switch(part.transferEncoding){
+ case 'binary':
+ case '7bit':
+ case '8bit':
+ parser.onPartData = function(b, start, end) {
+ part.emit('data', b.slice(start, end));
+ };
+
+ parser.onPartEnd = function() {
+ part.emit('end');
+ };
+ break;
+
+ case 'base64':
+ parser.onPartData = function(b, start, end) {
+ part.transferBuffer += b.slice(start, 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.
+ */
+ var offset = parseInt(part.transferBuffer.length / 4, 10) * 4;
+ part.emit('data', new Buffer(part.transferBuffer.substring(0, offset), 'base64'));
+ part.transferBuffer = part.transferBuffer.substring(offset);
+ };
+
+ parser.onPartEnd = function() {
+ part.emit('data', new Buffer(part.transferBuffer, 'base64'));
+ part.emit('end');
+ };
+ break;
+
+ default:
+ return self._error(new Error('unknown transfer-encoding'));
+ }
+
+ self.onPart(part);
+ };
+
+
+ parser.onEnd = function() {
+ self.ended = true;
+ self._maybeEnd();
+ };
+
+ this._parser = parser;
+};
+
+IncomingForm.prototype._fileName = function(headerValue) {
+ // matches either a quoted-string or a token (RFC 2616 section 19.5.1)
+ var m = headerValue.match(/\bfilename=("(.*?)"|([^\(\)<>@,;:\\"\/\[\]\?=\{\}\s\t/]+))($|;\s)/i);
+ if (!m) return;
+
+ var match = m[2] || m[3] || '';
+ var filename = match.substr(match.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(this.maxFields)
+ , 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._initOctetStream = function() {
+ this.type = 'octet-stream';
+ var filename = this.headers['x-file-name'];
+ var mime = this.headers['content-type'];
+
+ var file = new File({
+ path: this._uploadPath(filename),
+ name: filename,
+ type: mime
+ });
+
+ this.emit('fileBegin', filename, file);
+ file.open();
+ this.openedFiles.push(file);
+ this._flushing++;
+
+ var self = this;
+
+ self._parser = new OctetParser();
+
+ //Keep track of writes that haven't finished so we don't emit the file before it's done being written
+ var outstandingWrites = 0;
+
+ self._parser.on('data', function(buffer){
+ self.pause();
+ outstandingWrites++;
+
+ file.write(buffer, function() {
+ outstandingWrites--;
+ self.resume();
+
+ if(self.ended){
+ self._parser.emit('doneWritingFile');
+ }
+ });
+ });
+
+ self._parser.on('end', function(){
+ self._flushing--;
+ self.ended = true;
+
+ var done = function(){
+ file.end(function() {
+ self.emit('file', 'file', file);
+ self._maybeEnd();
+ });
+ };
+
+ if(outstandingWrites === 0){
+ done();
+ } else {
+ self._parser.once('doneWritingFile', done);
+ }
+ });
+};
+
+IncomingForm.prototype._initJSONencoded = function() {
+ this.type = 'json';
+
+ var parser = new JSONParser(this)
+ , 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 buf = crypto.randomBytes(16);
+ var name = 'upload_' + buf.toString('hex');
+
+ if (this.keepExtensions) {
+ var ext = path.extname(filename);
+ ext = ext.replace(/(\.[a-z0-9]+).*/i, '$1');
+
+ name += ext;
+ }
+
+ return path.join(this.uploadDir, name);
+};
+
+IncomingForm.prototype._maybeEnd = function() {
+ if (!this.ended || this._flushing || this.error) {
+ return;
+ }
+
+ this.emit('end');
+};
diff --git a/node_modules/formidable/lib/index.js b/node_modules/formidable/lib/index.js
new file mode 100644
index 0000000..7a6e3e1
--- /dev/null
+++ b/node_modules/formidable/lib/index.js
@@ -0,0 +1,3 @@
+var IncomingForm = require('./incoming_form').IncomingForm;
+IncomingForm.IncomingForm = IncomingForm;
+module.exports = IncomingForm;
diff --git a/node_modules/formidable/lib/json_parser.js b/node_modules/formidable/lib/json_parser.js
new file mode 100644
index 0000000..28a23ba
--- /dev/null
+++ b/node_modules/formidable/lib/json_parser.js
@@ -0,0 +1,30 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+var Buffer = require('buffer').Buffer;
+
+function JSONParser(parent) {
+ this.parent = parent;
+ this.chunks = [];
+ this.bytesWritten = 0;
+}
+exports.JSONParser = JSONParser;
+
+JSONParser.prototype.write = function(buffer) {
+ this.bytesWritten += buffer.length;
+ this.chunks.push(buffer);
+ return buffer.length;
+};
+
+JSONParser.prototype.end = function() {
+ try {
+ var fields = JSON.parse(Buffer.concat(this.chunks));
+ for (var field in fields) {
+ this.onField(field, fields[field]);
+ }
+ } catch (e) {
+ this.parent.emit('error', e);
+ }
+ this.data = null;
+
+ this.onEnd();
+};
diff --git a/node_modules/formidable/lib/multipart_parser.js b/node_modules/formidable/lib/multipart_parser.js
new file mode 100644
index 0000000..36de2b0
--- /dev/null
+++ b/node_modules/formidable/lib/multipart_parser.js
@@ -0,0 +1,332 @@
+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 (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--', 0);
+ this.boundary.write(str, 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 == HYPHEN) {
+ flags |= F.LAST_BOUNDARY;
+ } else if (c != CR) {
+ return i;
+ }
+ index++;
+ break;
+ } else if (index - 1 == boundary.length - 2) {
+ if (flags & F.LAST_BOUNDARY && c == HYPHEN){
+ callback('end');
+ state = S.END;
+ flags = 0;
+ } else if (!(flags & F.LAST_BOUNDARY) && c == LF) {
+ index = 0;
+ callback('partBegin');
+ state = S.HEADER_FIELD_START;
+ } else {
+ return i;
+ }
+ break;
+ }
+
+ if (c != boundary[index+2]) {
+ index = -2;
+ }
+ if (c == boundary[index+2]) {
+ 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;
+ 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
+ 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() {
+ var callback = function(self, name) {
+ var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
+ if (callbackSymbol in self) {
+ self[callbackSymbol]();
+ }
+ };
+ if ((this.state == S.HEADER_FIELD_START && this.index === 0) ||
+ (this.state == S.PART_DATA && this.index == this.boundary.length)) {
+ callback(this, 'partEnd');
+ callback(this, 'end');
+ } else 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);
+};
diff --git a/node_modules/formidable/lib/octet_parser.js b/node_modules/formidable/lib/octet_parser.js
new file mode 100644
index 0000000..6e8b551
--- /dev/null
+++ b/node_modules/formidable/lib/octet_parser.js
@@ -0,0 +1,20 @@
+var EventEmitter = require('events').EventEmitter
+ , util = require('util');
+
+function OctetParser(options){
+ if(!(this instanceof OctetParser)) return new OctetParser(options);
+ EventEmitter.call(this);
+}
+
+util.inherits(OctetParser, EventEmitter);
+
+exports.OctetParser = OctetParser;
+
+OctetParser.prototype.write = function(buffer) {
+ this.emit('data', buffer);
+ return buffer.length;
+};
+
+OctetParser.prototype.end = function() {
+ this.emit('end');
+};
diff --git a/node_modules/formidable/lib/querystring_parser.js b/node_modules/formidable/lib/querystring_parser.js
new file mode 100644
index 0000000..fcaffe0
--- /dev/null
+++ b/node_modules/formidable/lib/querystring_parser.js
@@ -0,0 +1,27 @@
+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(maxKeys) {
+ this.maxKeys = maxKeys;
+ 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, '&', '=', { maxKeys: this.maxKeys });
+ for (var field in fields) {
+ this.onField(field, fields[field]);
+ }
+ this.buffer = '';
+
+ this.onEnd();
+};
+
diff --git a/node_modules/formidable/package.json b/node_modules/formidable/package.json
new file mode 100644
index 0000000..d63b7b9
--- /dev/null
+++ b/node_modules/formidable/package.json
@@ -0,0 +1,60 @@
+{
+ "_args": [
+ [
+ "formidable@1.2.2",
+ "/data/dev/Projets/FNS Electrode/Projets/FNS Electrode"
+ ]
+ ],
+ "_from": "formidable@1.2.2",
+ "_id": "formidable@1.2.2",
+ "_inBundle": false,
+ "_integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==",
+ "_location": "/formidable",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "version",
+ "registry": true,
+ "raw": "formidable@1.2.2",
+ "name": "formidable",
+ "escapedName": "formidable",
+ "rawSpec": "1.2.2",
+ "saveSpec": null,
+ "fetchSpec": "1.2.2"
+ },
+ "_requiredBy": [
+ "/"
+ ],
+ "_resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
+ "_spec": "1.2.2",
+ "_where": "/data/dev/Projets/FNS Electrode/Projets/FNS Electrode",
+ "bugs": {
+ "url": "https://github.com/node-formidable/formidable/issues"
+ },
+ "description": "A node.js module for parsing form data, especially file uploads.",
+ "devDependencies": {
+ "findit": "^0.1.2",
+ "gently": "^0.8.0",
+ "hashish": "^0.0.4",
+ "request": "^2.11.4",
+ "urun": "^0.0.6",
+ "utest": "^0.0.8"
+ },
+ "files": [
+ "lib",
+ "benchmark-2020-01-29_xeon-x3440.png"
+ ],
+ "funding": "https://ko-fi.com/tunnckoCore/commissions",
+ "homepage": "https://github.com/node-formidable/formidable",
+ "license": "MIT",
+ "main": "./lib/index.js",
+ "name": "formidable",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/node-formidable/formidable.git"
+ },
+ "scripts": {
+ "clean": "rm test/tmp/*",
+ "test": "node test/run.js"
+ },
+ "version": "1.2.2"
+}