[
  {
    "path": ".editorconfig",
    "content": "# http://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[{*.js,*.json,*.yml}]\nindent_size = 2\nindent_style = space\n"
  },
  {
    "path": ".eslintignore",
    "content": "coverage\nnode_modules\n"
  },
  {
    "path": ".eslintrc.yml",
    "content": "rules:\n  eol-last: error\n  indent: [\"error\", 2, { \"SwitchCase\": 1 }]\n  no-trailing-spaces: error\n"
  },
  {
    "path": ".gitignore",
    "content": ".nyc_output/\ncoverage/\nnode_modules/\nnpm-debug.log\npackage-lock.json\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"0.10\"\n  - \"4.9\"\n  - \"6.17\"\n  - \"8.16\"\n  - \"10.16\"\n  - \"12.11\"\nsudo: false\ncache:\n  directories:\n    - node_modules\nbefore_install:\n  # Configure npm\n  - |\n    # Skip updating shrinkwrap / lock\n    npm config set shrinkwrap false\n  # Setup Node.js version-specific dependencies\n  - |\n    # eslint for linting\n    # - remove for Node.js < 8\n    if [[ \"$(cut -d. -f1 <<< \"$TRAVIS_NODE_VERSION\")\" -lt 8 ]]; then\n      npm rm --save-dev eslint\n    fi\n  - |\n    # mocha for testing\n    # - use 3.x for Node.js < 4\n    # - use 5.x for Node.js < 6\n    if [[ \"$(cut -d. -f1 <<< \"$TRAVIS_NODE_VERSION\")\" -lt 4 ]]; then\n      npm install --save-dev mocha@3.5.3\n    elif [[ \"$(cut -d. -f1 <<< \"$TRAVIS_NODE_VERSION\")\" -lt 6 ]]; then\n      npm install --save-dev mocha@5.2.0\n    fi\n  - |\n    # nyc for coverage\n    # - use 10.x for Node.js < 4\n    # - use 11.x for Node.js < 6\n    if [[ \"$(cut -d. -f1 <<< \"$TRAVIS_NODE_VERSION\")\" -lt 4 ]]; then\n      npm install --save-dev nyc@10.3.2\n    elif [[ \"$(cut -d. -f1 <<< \"$TRAVIS_NODE_VERSION\")\" -lt 6 ]]; then\n      npm install --save-dev nyc@11.9.0\n    fi\n  - |\n    # supertest for http calls\n    # - use 2.0.0 for Node.js < 4\n    # - use 3.4.2 for Node.js < 6\n    if [[ \"$(cut -d. -f1 <<< \"$TRAVIS_NODE_VERSION\")\" -lt 4 ]]; then\n      npm install --save-dev supertest@2.0.0\n    elif [[ \"$(cut -d. -f1 <<< \"$TRAVIS_NODE_VERSION\")\" -lt 6 ]]; then\n      npm install --save-dev supertest@3.4.2\n    fi\n  # Update Node.js modules\n  - |\n    # Prune & rebuild node_modules\n    if [[ -d node_modules ]]; then\n      npm prune\n      npm rebuild\n    fi\n\nscript:\n  - |\n    # Run test script\n    npm run-script test-ci\n  - |\n    # Run linting\n    if npm -ps ls eslint | grep -q eslint; then\n      npm run-script lint\n    fi\nafter_script:\n  - |\n    # Upload coverage to coveralls, if exists\n    if [[ -d .nyc_output ]]; then\n      npm install --save-dev coveralls@2\n      nyc report --reporter=text-lcov | coveralls\n    fi\n"
  },
  {
    "path": "HISTORY.md",
    "content": "unreleased\n==========\n\n  * deps: http-errors@~1.7.3\n     - Fix error creating objects in some environments\n     - deps: inherits@2.0.4\n     - deps: setprototypeof@1.1.1\n  * deps: qs@~6.7.0\n    - Fix parsing array brackets after index\n  * deps: safe-buffer@5.2.0\n  * deps: type-is@~1.6.18\n    - deps: mime-types@~2.1.24\n    - perf: prevent internal `throw` on invalid type\n\n2.2.0 / 2018-09-14\n==================\n\n  * Fix masking `multiparty` errors as 400\n  * deps: multiparty@~4.2.1\n    - Use http-errors for raised errors\n    - Use uid-safe module to for temp file names\n    - Update to fd-slicer 1.1.0\n    - perf: remove parameter reassignment\n\n2.1.1 / 2018-06-22\n==================\n\n  * deps: multiparty@~4.1.4\n    - Enable strict mode\n    - Fix file extension filtering stopping on certain whitespace characters\n    - Use safe-buffer for improved API safety\n  * deps: qs@~6.5.2\n  * deps: type-is@~1.6.16\n    - deps: mime-types@~2.1.18\n\n2.1.0 / 2017-10-19\n==================\n\n  * deps: multiparty@~4.1.3\n    - Use `os.tmpdir()` instead of `os.tmpDir()`\n    - deps: fd-slicer@~1.0.1\n  * deps: qs@~6.5.1\n    - Fix array parsing from skipping empty values\n    - Fix compacting of nested sparse arrays\n    - Fix parsing & compacting very deep objects\n  * deps: type-is@~1.6.15\n    - Fix type error when given invalid type to match against\n    - deps: mime-types@~2.1.15\n  * perf: enable strict mode\n\n2.0.0 / 2015-07-13\n==================\n\n  * Requires Node.js >= 0.10.0\n  * deps: multiparty@~4.1.2\n  * deps: on-finished@~2.3.0\n  * deps: qs@~4.0.0\n  * deps: type-is@~1.6.4\n\n1.2.5 / 2014-10-14\n==================\n\n  * Update qs to 2.2.4\n  * Update type-is to 1.5.2\n\n1.2.4 / 2014-08-29\n==================\n\n  * Update qs to 2.2.2\n\n1.2.3 / 2014-08-28\n==================\n\n  * Update qs to 2.2.1\n\n1.2.2 / 2014-08-27\n==================\n\n  * Update qs to 2.2.0\n\n1.2.1 / 2014-08-07\n==================\n\n  * Update multiparty to 3.3.2\n  * Update qs to 1.2.0\n\n1.2.0 / 2014-08-06\n==================\n\n  * Update multiparty to 3.3.1\n  * Update qs to 1.1.0\n\n1.1.0 / 2014-07-03\n==================\n\n  * Update multiparty to 3.3.0\n  * Use type-is to check Content-Type\n\n1.0.6 / 2014-07-03\n==================\n\n  * Fix callback hang in node.js 0.8 on errors\n\n1.0.5 / 2014-06-01\n==================\n\n  * Update multiparty to 3.2.8\n\n1.0.4 / 2014-05-26\n==================\n\n  * Fix error causing response to hang\n  * Update multiparty to 3.2.6\n\n1.0.3 / 2014-01-20\n==================\n\n  * Update multiparty to 3.2\n\n1.0.2 / 2014-01-17\n==================\n\n  * Update multiparty to 3.1\n\n1.0.1 / 2013-10-25\n==================\n\n  * Update multiparty to 3.0\n\n1.0.0 / 2013-10-25\n==================\n\n  * revive\n"
  },
  {
    "path": "LICENSE",
    "content": "(The MIT License)\n\nCopyright (c) 2010 Sencha Inc.\nCopyright (c) 2011 TJ Holowaychuk\nCopyright (c) 2013 Andrew Kelley\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "> [!CAUTION]\n> **This repository is archived and no longer actively maintained.**\n>\n> We are no longer accepting issues, feature requests, or pull requests.\n> For additional support or questions, please visit the [Express.js Discussions page](https://github.com/expressjs/express/discussions).\n\n# connect-multiparty\n\n[![NPM Version][npm-image]][npm-url]\n[![NPM Downloads][downloads-image]][downloads-url]\n[![Build Status][travis-image]][travis-url]\n[![Test Coverage][coveralls-image]][coveralls-url]\n\n[connect](https://github.com/senchalabs/connect/) middleware for\n[multiparty](https://github.com/andrewrk/node-multiparty/).\n\nI actually recommend against using this module. It's cleaner to use the\nmultiparty API directly.\n\nThis middleware will create temp files on your server and never clean them\nup. Thus you should not add this middleware to all routes; only to the ones\nin which you want to accept uploads. And in these endpoints, be sure to\ndelete all temp files, even the ones that you don't use.\n\n## Usage\n\n```js\nvar multipart = require('connect-multiparty');\nvar multipartMiddleware = multipart();\napp.post('/upload', multipartMiddleware, function(req, resp) {\n  console.log(req.body, req.files);\n  // don't forget to delete all req.files when done\n});\n```\n\nIf you pass options to `multipart()`, they are passed directly into\nmultiparty.\n\n## License\n\n[MIT](LICENSE)\n\n[coveralls-image]: https://img.shields.io/coveralls/expressjs/connect-multiparty/master.svg\n[coveralls-url]: https://coveralls.io/r/expressjs/connect-multiparty?branch=master\n[downloads-image]: https://img.shields.io/npm/dm/connect-multiparty.svg\n[downloads-url]: https://npmjs.org/package/connect-multiparty\n[npm-image]: https://img.shields.io/npm/v/connect-multiparty.svg\n[npm-url]: https://npmjs.org/package/connect-multiparty\n[travis-image]: https://img.shields.io/travis/expressjs/connect-multiparty/master.svg\n[travis-url]: https://travis-ci.org/expressjs/connect-multiparty\n"
  },
  {
    "path": "index.js",
    "content": "/*!\n * connect-multiparty\n * Copyright(c) 2010 Sencha Inc.\n * Copyright(c) 2011 TJ Holowaychuk\n * Copyright(c) 2013 Andrew Kelley\n * MIT Licensed\n */\n\n'use strict'\n\n/**\n * Module dependencies.\n * @private\n */\n\nvar createError = require('http-errors')\nvar multiparty = require('multiparty');\nvar onFinished = require('on-finished');\nvar qs = require('qs');\nvar typeis = require('type-is');\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = multipart\n\n/**\n * Parse multipart/form-data request bodies, providing the parsed\n * object as `req.body` and `req.files`.\n *\n * The options passed are merged with [multiparty](https://github.com/pillarjs/multiparty)'s\n * `Form` object, allowing you to configure the upload directory,\n * size limits, etc. For example if you wish to change the upload\n * dir do the following:\n *\n *     app.use(multipart({ uploadDir: path }))\n *\n * @param {Object} options\n * @return {Function}\n * @public\n */\n\nfunction multipart (options) {\n  options = options || {};\n\n  return function multipart(req, res, next) {\n    if (req._body) return next();\n    req.body = req.body || {};\n    req.files = req.files || {};\n\n    // ignore GET\n    if ('GET' === req.method || 'HEAD' === req.method) return next();\n\n    // check Content-Type\n    if (!typeis(req, 'multipart/form-data')) return next();\n\n    // flag as parsed\n    req._body = true;\n\n    // parse\n    var form = new multiparty.Form(options);\n    var data = {};\n    var files = {};\n    var done = false;\n\n    function ondata(name, val, data){\n      if (Array.isArray(data[name])) {\n        data[name].push(val);\n      } else if (data[name]) {\n        data[name] = [data[name], val];\n      } else {\n        data[name] = val;\n      }\n    }\n\n    form.on('field', function(name, val){\n      ondata(name, val, data);\n    });\n\n    form.on('file', function(name, val){\n      val.name = val.originalFilename;\n      val.type = val.headers['content-type'] || null;\n      ondata(name, val, files);\n    });\n\n    form.on('error', function(err){\n      if (done) return;\n\n      done = true;\n\n      // set status code on error\n      var error = createError(400, err)\n\n      if (!req.readable) return next(error)\n\n      // read off entire request\n      req.resume();\n      onFinished(req, function(){\n        next(error)\n      });\n    });\n\n    form.on('close', function() {\n      if (done) return;\n\n      done = true;\n\n      // expand names with qs & assign\n      req.body = qs.parse(data, { allowDots: true })\n      req.files = qs.parse(files, { allowDots: true })\n\n      next()\n    });\n\n    form.parse(req);\n  }\n};\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"connect-multiparty\",\n  \"version\": \"2.2.0\",\n  \"description\": \"multipart parsing middleware for connect using multiparty\",\n  \"author\": \"Andrew Kelley <superjoe30@gmail.com>\",\n  \"contributors\": [\n    \"Douglas Christopher Wilson <doug@somethingdoug.com>\"\n  ],\n  \"license\": \"MIT\",\n  \"repository\": \"expressjs/connect-multiparty\",\n  \"dependencies\": {\n    \"http-errors\": \"~1.7.3\",\n    \"multiparty\": \"~4.2.1\",\n    \"on-finished\": \"~2.3.0\",\n    \"qs\": \"~6.7.0\",\n    \"type-is\": \"~1.6.18\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  },\n  \"devDependencies\": {\n    \"connect\": \"3.7.0\",\n    \"deep-equal\": \"1.0.1\",\n    \"eslint\": \"6.5.1\",\n    \"mocha\": \"6.2.1\",\n    \"nyc\": \"14.1.1\",\n    \"safe-buffer\": \"5.2.0\",\n    \"supertest\": \"4.0.2\"\n  },\n  \"files\": [\n    \"HISTORY.md\",\n    \"LICENSE\",\n    \"README.md\",\n    \"index.js\"\n  ],\n  \"scripts\": {\n    \"lint\": \"eslint .\",\n    \"test\": \"mocha --reporter spec\",\n    \"test-ci\": \"nyc --reporter=text npm test\",\n    \"test-cov\": \"nyc --reporter=html --reporter=text npm test\"\n  }\n}\n"
  },
  {
    "path": "test/multipart.js",
    "content": "\nprocess.env.NODE_ENV = 'test';\n\nvar Buffer = require('safe-buffer').Buffer\nvar connect = require('connect');\nvar deepEqual = require('deep-equal')\nvar multipart = require('..');\nvar request = require('supertest');\n\ndescribe('multipart()', function(){\n  it('should ignore GET', function(done){\n    request(createServer())\n      .get('/body')\n      .field('user', 'Tobi')\n      .expect(200, {}, done)\n  })\n\n  describe('with multipart/form-data', function(){\n    it('should populate req.body', function(done){\n      request(createServer())\n        .post('/body')\n        .field('user', 'Tobi')\n        .expect(200, { user: 'Tobi' }, done)\n    })\n\n    it('should handle duplicated middleware', function (done) {\n      var app = connect()\n        .use(multipart())\n        .use(multipart())\n        .use(function (req, res) {\n          res.setHeader('Content-Type', 'application/json; charset=utf-8')\n          res.end(JSON.stringify(req.body))\n        })\n\n      request(app)\n        .post('/body')\n        .field('user', 'Tobi')\n        .expect(200, { user: 'Tobi' }, done)\n    })\n\n    it('should support files', function(done){\n      request(createServer())\n        .post('/files')\n        .attach('text', Buffer.from('some text here'), 'foo.txt')\n        .expect(200)\n        .expect(shouldDeepIncludeInBody({\n          text: {\n            name: 'foo.txt',\n            originalFilename: 'foo.txt',\n            size: 14,\n            type: 'text/plain'\n          }\n        }))\n        .end(done)\n    })\n\n    it('should work with multiple fields', function(done){\n      request(createServer())\n        .post('/body')\n        .field('user', 'Tobi')\n        .field('age', '1')\n        .expect(200, { user: 'Tobi', age: '1' }, done)\n    })\n\n    it('should handle duplicated fields', function (done) {\n      request(createServer())\n        .post('/body')\n        .field('user', 'Tobi')\n        .field('user', 'Loki')\n        .field('user', 'Poki')\n        .expect(200, { user: [ 'Tobi', 'Loki', 'Poki' ] }, done)\n    })\n\n    it('should support nesting', function(done){\n      request(createServer())\n        .post('/body')\n        .field('user[name][first]', 'tobi')\n        .field('user[name][last]', 'holowaychuk')\n        .field('user[age]', '1')\n        .field('species', 'ferret')\n        .expect(200, {\n          species: 'ferret',\n          user: {\n            age: '1',\n            name: { first: 'tobi', last: 'holowaychuk' }\n          }\n        }, done)\n    })\n\n    it('should support multiple files of the same name', function(done){\n      request(createServer())\n        .post('/files')\n        .attach('text', Buffer.from('some text here'), 'foo.txt')\n        .attach('text', Buffer.from('some more text stuff'), 'bar.txt')\n        .expect(200)\n        .expect(shouldDeepIncludeInBody({\n          text: [\n            { name: 'foo.txt' },\n            { name: 'bar.txt' }\n          ]\n        }))\n        .end(done)\n    })\n\n    it('should support nested files', function(done){\n      request(createServer())\n        .post('/files')\n        .attach('docs[foo]', Buffer.from('some text here'), 'foo.txt')\n        .attach('docs[bar]', Buffer.from('some more text stuff'), 'bar.txt')\n        .expect(200)\n        .expect(shouldDeepIncludeInBody({\n          docs: {\n            foo: { name: 'foo.txt' },\n            bar: { name: 'bar.txt' }\n          }\n        }))\n        .end(done)\n    })\n\n    it('should next(err) on multipart failure', function(done){\n      var app = createServer()\n\n      var test = request(app).post('/')\n      test.set('Content-Type', 'multipart/form-data; boundary=foo');\n      test.write('--foo\\r\\n');\n      test.write('Content-filename=\"foo.txt\"\\r\\n');\n      test.write('\\r\\n');\n      test.write('some text here');\n      test.write('Content-Disposition: form-data; name=\"text\"; filename=\"bar.txt\"\\r\\n');\n      test.write('\\r\\n');\n      test.write('some more text stuff');\n      test.write('\\r\\n--foo--');\n      test.expect(400, 'BadRequestError: Expected alphabetic character, received 61', done)\n    })\n\n    it('should not hang request on failure', function(done){\n      var app = createServer()\n      var buf = Buffer.alloc(1024 * 10, '.')\n\n      var test = request(app).post('/')\n      test.set('Content-Type', 'multipart/form-data; boundary=foo');\n      test.write('--foo\\r\\n');\n      test.write('Content-filename=\"foo.txt\"\\r\\n');\n      test.write('\\r\\n');\n      test.write('some text here');\n      test.write('Content-Disposition: form-data; name=\"text\"; filename=\"bar.txt\"\\r\\n');\n      test.write('\\r\\n');\n      test.write('some more text stuff');\n      test.write('\\r\\n--foo--');\n      test.write(buf)\n      test.write(buf)\n      test.write(buf)\n      test.expect(400, 'BadRequestError: Expected alphabetic character, received 61', done)\n    })\n\n    it('should default req.files to {}', function(done){\n      request(createServer())\n        .post('/body')\n        .expect(200, {}, done)\n    })\n\n    it('should return 413 on maxFilesSize exceeded', function (done) {\n      var max = Math.pow(2, 9)\n\n      request(createServer({ maxFilesSize: max }))\n        .post('/files')\n        .field('user[name]', 'Tobi')\n        .attach('text', Buffer.alloc(max + 1, 'x'), 'foo.txt')\n        .expect(413, done)\n    })\n  })\n})\n\nfunction createServer (opts) {\n  var app = connect()\n\n  app.use(multipart(opts))\n\n  app.use('/body', function (req, res) {\n    res.setHeader('Content-Type', 'application/json; charset=utf-8')\n    res.end(JSON.stringify(req.body))\n  })\n\n  app.use('/files', function (req, res) {\n    res.setHeader('Content-Type', 'application/json; charset=utf-8')\n    res.end(JSON.stringify(req.files))\n  })\n\n  app.use(function (err, req, res, next) {\n    res.statusCode = err.statusCode || err.status || 500\n    res.end(err.name + ': ' + err.message)\n  })\n\n  return app\n}\n\nfunction shouldDeepIncludeInBody (obj) {\n  return function (res) {\n    deepEqual(res.body, obj)\n  }\n}\n"
  }
]