천현우

module changed

Showing 303 changed files with 4879 additions and 12 deletions
1 +import {voicoding} from './voicoding.js'
2 +
3 +const start = voicoding()
...\ No newline at end of file ...\ No newline at end of file
1 +#!/bin/sh
2 +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3 +
4 +case `uname` in
5 + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
6 +esac
7 +
8 +if [ -x "$basedir/node" ]; then
9 + "$basedir/node" "$basedir/../mkdirp/bin/cmd.js" "$@"
10 + ret=$?
11 +else
12 + node "$basedir/../mkdirp/bin/cmd.js" "$@"
13 + ret=$?
14 +fi
15 +exit $ret
1 +@ECHO off
2 +SETLOCAL
3 +CALL :find_dp0
4 +
5 +IF EXIST "%dp0%\node.exe" (
6 + SET "_prog=%dp0%\node.exe"
7 +) ELSE (
8 + SET "_prog=node"
9 + SET PATHEXT=%PATHEXT:;.JS;=;%
10 +)
11 +
12 +"%_prog%" "%dp0%\..\mkdirp\bin\cmd.js" %*
13 +ENDLOCAL
14 +EXIT /b %errorlevel%
15 +:find_dp0
16 +SET dp0=%~dp0
17 +EXIT /b
1 +#!/usr/bin/env pwsh
2 +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
3 +
4 +$exe=""
5 +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
6 + # Fix case when both the Windows and Linux builds of Node
7 + # are installed in the same directory
8 + $exe=".exe"
9 +}
10 +$ret=0
11 +if (Test-Path "$basedir/node$exe") {
12 + & "$basedir/node$exe" "$basedir/../mkdirp/bin/cmd.js" $args
13 + $ret=$LASTEXITCODE
14 +} else {
15 + & "node$exe" "$basedir/../mkdirp/bin/cmd.js" $args
16 + $ret=$LASTEXITCODE
17 +}
18 +exit $ret
...@@ -8,7 +8,7 @@ This package contains type definitions for Node.js (http://nodejs.org/). ...@@ -8,7 +8,7 @@ This package contains type definitions for Node.js (http://nodejs.org/).
8 Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node. 8 Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node.
9 9
10 ### Additional Details 10 ### Additional Details
11 - * Last updated: Fri, 21 May 2021 10:32:02 GMT 11 + * Last updated: Wed, 02 Jun 2021 07:31:33 GMT
12 * Dependencies: none 12 * Dependencies: none
13 * Global values: `AbortController`, `AbortSignal`, `Buffer`, `__dirname`, `__filename`, `clearImmediate`, `clearInterval`, `clearTimeout`, `console`, `exports`, `global`, `module`, `process`, `queueMicrotask`, `require`, `setImmediate`, `setInterval`, `setTimeout` 13 * Global values: `AbortController`, `AbortSignal`, `Buffer`, `__dirname`, `__filename`, `clearImmediate`, `clearInterval`, `clearTimeout`, `console`, `exports`, `global`, `module`, `process`, `queueMicrotask`, `require`, `setImmediate`, `setInterval`, `setTimeout`
14 14
......
...@@ -167,7 +167,7 @@ declare module 'http' { ...@@ -167,7 +167,7 @@ declare module 'http' {
167 finished: boolean; 167 finished: boolean;
168 headersSent: boolean; 168 headersSent: boolean;
169 /** 169 /**
170 - * @deprecate Use `socket` instead. 170 + * @deprecated Use `socket` instead.
171 */ 171 */
172 connection: Socket | null; 172 connection: Socket | null;
173 socket: Socket | null; 173 socket: Socket | null;
......
1 { 1 {
2 "_from": "@types/node@*", 2 "_from": "@types/node@*",
3 - "_id": "@types/node@15.6.0", 3 + "_id": "@types/node@15.6.2",
4 "_inBundle": false, 4 "_inBundle": false,
5 - "_integrity": "sha512-gCYSfQpy+LYhOFTKAeE8BkyGqaxmlFxe+n4DKM6DR0wzw/HISUE/hAmkC/KT8Sw5PCJblqg062b3z9gucv3k0A==", 5 + "_integrity": "sha512-dxcOx8801kMo3KlU+C+/ctWrzREAH7YvoF3aoVpRdqgs+Kf7flp+PJDN/EX5bME3suDUZHsxes9hpvBmzYlWbA==",
6 "_location": "/@types/node", 6 "_location": "/@types/node",
7 "_phantomChildren": {}, 7 "_phantomChildren": {},
8 "_requested": { 8 "_requested": {
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
22 "/@types/pumpify", 22 "/@types/pumpify",
23 "/protobufjs" 23 "/protobufjs"
24 ], 24 ],
25 - "_resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.0.tgz", 25 + "_resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.2.tgz",
26 - "_shasum": "f0ddca5a61e52627c9dcb771a6039d44694597bc", 26 + "_shasum": "c61d49f38af70da32424b5322eee21f97e627175",
27 "_spec": "@types/node@*", 27 "_spec": "@types/node@*",
28 "_where": "C:\\Users\\1000c\\이것저것\\옾소\\Voicoding\\node_modules\\@types\\pumpify", 28 "_where": "C:\\Users\\1000c\\이것저것\\옾소\\Voicoding\\node_modules\\@types\\pumpify",
29 "bugs": { 29 "bugs": {
...@@ -199,7 +199,7 @@ ...@@ -199,7 +199,7 @@
199 "dependencies": {}, 199 "dependencies": {},
200 "deprecated": false, 200 "deprecated": false,
201 "description": "TypeScript definitions for Node.js", 201 "description": "TypeScript definitions for Node.js",
202 - "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped#readme", 202 + "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node",
203 "license": "MIT", 203 "license": "MIT",
204 "main": "", 204 "main": "",
205 "name": "@types/node", 205 "name": "@types/node",
...@@ -209,9 +209,9 @@ ...@@ -209,9 +209,9 @@
209 "directory": "types/node" 209 "directory": "types/node"
210 }, 210 },
211 "scripts": {}, 211 "scripts": {},
212 - "typeScriptVersion": "3.5", 212 + "typeScriptVersion": "3.6",
213 "types": "index.d.ts", 213 "types": "index.d.ts",
214 - "typesPublisherContentHash": "fe5d90fe4c06a65d482f400f205828b1280c7062026d5afdccc3b2bbccf4adcd", 214 + "typesPublisherContentHash": "f62422deccbd466260cb63740d207022259eb7fc7b6e7c406be463b9d1b0cd19",
215 "typesVersions": { 215 "typesVersions": {
216 "<=3.6": { 216 "<=3.6": {
217 "*": [ 217 "*": [
...@@ -219,5 +219,5 @@ ...@@ -219,5 +219,5 @@
219 ] 219 ]
220 } 220 }
221 }, 221 },
222 - "version": "15.6.0" 222 + "version": "15.6.2"
223 } 223 }
......
...@@ -88,7 +88,10 @@ declare module 'perf_hooks' { ...@@ -88,7 +88,10 @@ declare module 'perf_hooks' {
88 * @param util1 The result of a previous call to eventLoopUtilization() 88 * @param util1 The result of a previous call to eventLoopUtilization()
89 * @param util2 The result of a previous call to eventLoopUtilization() prior to util1 89 * @param util2 The result of a previous call to eventLoopUtilization() prior to util1
90 */ 90 */
91 - type EventLoopUtilityFunction = (util1?: EventLoopUtilization, util2?: EventLoopUtilization) => EventLoopUtilization; 91 + type EventLoopUtilityFunction = (
92 + util1?: EventLoopUtilization,
93 + util2?: EventLoopUtilization,
94 + ) => EventLoopUtilization;
92 95
93 interface Performance { 96 interface Performance {
94 /** 97 /**
...@@ -122,7 +125,7 @@ declare module 'perf_hooks' { ...@@ -122,7 +125,7 @@ declare module 'perf_hooks' {
122 * @param startMark 125 * @param startMark
123 * @param endMark 126 * @param endMark
124 */ 127 */
125 - measure(name: string, startMark: string, endMark: string): void; 128 + measure(name: string, startMark?: string, endMark?: string): void;
126 129
127 /** 130 /**
128 * An instance of the PerformanceNodeTiming class that provides performance metrics for specific Node.js operational milestones. 131 * An instance of the PerformanceNodeTiming class that provides performance metrics for specific Node.js operational milestones.
......
1 +The MIT License (MIT)
2 +
3 +Copyright (c) 2015 Linus Unnebäck
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in all
13 +copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 +SOFTWARE.
1 +# `append-field`
2 +
3 +A [W3C HTML JSON forms spec](http://www.w3.org/TR/html-json-forms/) compliant
4 +field appender (for lack of a better name). Useful for people implementing
5 +`application/x-www-form-urlencoded` and `multipart/form-data` parsers.
6 +
7 +It works best on objects created with `Object.create(null)`. Otherwise it might
8 +conflict with variables from the prototype (e.g. `hasOwnProperty`).
9 +
10 +## Installation
11 +
12 +```sh
13 +npm install --save append-field
14 +```
15 +
16 +## Usage
17 +
18 +```javascript
19 +var appendField = require('append-field')
20 +var obj = Object.create(null)
21 +
22 +appendField(obj, 'pets[0][species]', 'Dahut')
23 +appendField(obj, 'pets[0][name]', 'Hypatia')
24 +appendField(obj, 'pets[1][species]', 'Felis Stultus')
25 +appendField(obj, 'pets[1][name]', 'Billie')
26 +
27 +console.log(obj)
28 +```
29 +
30 +```text
31 +{ pets:
32 + [ { species: 'Dahut', name: 'Hypatia' },
33 + { species: 'Felis Stultus', name: 'Billie' } ] }
34 +```
35 +
36 +## API
37 +
38 +### `appendField(store, key, value)`
39 +
40 +Adds the field named `key` with the value `value` to the object `store`.
41 +
42 +## License
43 +
44 +MIT
1 +var parsePath = require('./lib/parse-path')
2 +var setValue = require('./lib/set-value')
3 +
4 +function appendField (store, key, value) {
5 + var steps = parsePath(key)
6 +
7 + steps.reduce(function (context, step) {
8 + return setValue(context, step, context[step.key], value)
9 + }, store)
10 +}
11 +
12 +module.exports = appendField
1 +var reFirstKey = /^[^\[]*/
2 +var reDigitPath = /^\[(\d+)\]/
3 +var reNormalPath = /^\[([^\]]+)\]/
4 +
5 +function parsePath (key) {
6 + function failure () {
7 + return [{ type: 'object', key: key, last: true }]
8 + }
9 +
10 + var firstKey = reFirstKey.exec(key)[0]
11 + if (!firstKey) return failure()
12 +
13 + var len = key.length
14 + var pos = firstKey.length
15 + var tail = { type: 'object', key: firstKey }
16 + var steps = [tail]
17 +
18 + while (pos < len) {
19 + var m
20 +
21 + if (key[pos] === '[' && key[pos + 1] === ']') {
22 + pos += 2
23 + tail.append = true
24 + if (pos !== len) return failure()
25 + continue
26 + }
27 +
28 + m = reDigitPath.exec(key.substring(pos))
29 + if (m !== null) {
30 + pos += m[0].length
31 + tail.nextType = 'array'
32 + tail = { type: 'array', key: parseInt(m[1], 10) }
33 + steps.push(tail)
34 + continue
35 + }
36 +
37 + m = reNormalPath.exec(key.substring(pos))
38 + if (m !== null) {
39 + pos += m[0].length
40 + tail.nextType = 'object'
41 + tail = { type: 'object', key: m[1] }
42 + steps.push(tail)
43 + continue
44 + }
45 +
46 + return failure()
47 + }
48 +
49 + tail.last = true
50 + return steps
51 +}
52 +
53 +module.exports = parsePath
1 +function valueType (value) {
2 + if (value === undefined) return 'undefined'
3 + if (Array.isArray(value)) return 'array'
4 + if (typeof value === 'object') return 'object'
5 + return 'scalar'
6 +}
7 +
8 +function setLastValue (context, step, currentValue, entryValue) {
9 + switch (valueType(currentValue)) {
10 + case 'undefined':
11 + if (step.append) {
12 + context[step.key] = [entryValue]
13 + } else {
14 + context[step.key] = entryValue
15 + }
16 + break
17 + case 'array':
18 + context[step.key].push(entryValue)
19 + break
20 + case 'object':
21 + return setLastValue(currentValue, { type: 'object', key: '', last: true }, currentValue[''], entryValue)
22 + case 'scalar':
23 + context[step.key] = [context[step.key], entryValue]
24 + break
25 + }
26 +
27 + return context
28 +}
29 +
30 +function setValue (context, step, currentValue, entryValue) {
31 + if (step.last) return setLastValue(context, step, currentValue, entryValue)
32 +
33 + var obj
34 + switch (valueType(currentValue)) {
35 + case 'undefined':
36 + if (step.nextType === 'array') {
37 + context[step.key] = []
38 + } else {
39 + context[step.key] = Object.create(null)
40 + }
41 + return context[step.key]
42 + case 'object':
43 + return context[step.key]
44 + case 'array':
45 + if (step.nextType === 'array') {
46 + return currentValue
47 + }
48 +
49 + obj = Object.create(null)
50 + context[step.key] = obj
51 + currentValue.forEach(function (item, i) {
52 + if (item !== undefined) obj['' + i] = item
53 + })
54 +
55 + return obj
56 + case 'scalar':
57 + obj = Object.create(null)
58 + obj[''] = currentValue
59 + context[step.key] = obj
60 + return obj
61 + }
62 +}
63 +
64 +module.exports = setValue
1 +{
2 + "_from": "append-field@^1.0.0",
3 + "_id": "append-field@1.0.0",
4 + "_inBundle": false,
5 + "_integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=",
6 + "_location": "/append-field",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "append-field@^1.0.0",
12 + "name": "append-field",
13 + "escapedName": "append-field",
14 + "rawSpec": "^1.0.0",
15 + "saveSpec": null,
16 + "fetchSpec": "^1.0.0"
17 + },
18 + "_requiredBy": [
19 + "/multer"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
22 + "_shasum": "1e3440e915f0b1203d23748e78edd7b9b5b43e56",
23 + "_spec": "append-field@^1.0.0",
24 + "_where": "C:\\Users\\1000c\\이것저것\\옾소\\Voicoding\\node_modules\\multer",
25 + "author": {
26 + "name": "Linus Unnebäck",
27 + "email": "linus@folkdatorn.se"
28 + },
29 + "bugs": {
30 + "url": "https://github.com/LinusU/node-append-field/issues"
31 + },
32 + "bundleDependencies": false,
33 + "deprecated": false,
34 + "description": "A [W3C HTML JSON forms spec](http://www.w3.org/TR/html-json-forms/) compliant field appender (for lack of a better name). Useful for people implementing `application/x-www-form-urlencoded` and `multipart/form-data` parsers.",
35 + "devDependencies": {
36 + "mocha": "^2.2.4",
37 + "standard": "^6.0.5",
38 + "testdata-w3c-json-form": "^0.2.0"
39 + },
40 + "homepage": "https://github.com/LinusU/node-append-field#readme",
41 + "license": "MIT",
42 + "main": "index.js",
43 + "name": "append-field",
44 + "repository": {
45 + "type": "git",
46 + "url": "git+ssh://git@github.com/LinusU/node-append-field.git"
47 + },
48 + "scripts": {
49 + "test": "standard && mocha"
50 + },
51 + "version": "1.0.0"
52 +}
1 +/* eslint-env mocha */
2 +
3 +var assert = require('assert')
4 +var appendField = require('../')
5 +var testData = require('testdata-w3c-json-form')
6 +
7 +describe('Append Field', function () {
8 + for (var test of testData) {
9 + it('handles ' + test.name, function () {
10 + var store = Object.create(null)
11 +
12 + for (var field of test.fields) {
13 + appendField(store, field.key, field.value)
14 + }
15 +
16 + assert.deepEqual(store, test.expected)
17 + })
18 + }
19 +})
1 +MIT License
2 +
3 +Copyright (c) 2016, 2018 Linus Unnebäck
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in all
13 +copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 +SOFTWARE.
1 +var toString = Object.prototype.toString
2 +
3 +var isModern = (
4 + typeof Buffer.alloc === 'function' &&
5 + typeof Buffer.allocUnsafe === 'function' &&
6 + typeof Buffer.from === 'function'
7 +)
8 +
9 +function isArrayBuffer (input) {
10 + return toString.call(input).slice(8, -1) === 'ArrayBuffer'
11 +}
12 +
13 +function fromArrayBuffer (obj, byteOffset, length) {
14 + byteOffset >>>= 0
15 +
16 + var maxLength = obj.byteLength - byteOffset
17 +
18 + if (maxLength < 0) {
19 + throw new RangeError("'offset' is out of bounds")
20 + }
21 +
22 + if (length === undefined) {
23 + length = maxLength
24 + } else {
25 + length >>>= 0
26 +
27 + if (length > maxLength) {
28 + throw new RangeError("'length' is out of bounds")
29 + }
30 + }
31 +
32 + return isModern
33 + ? Buffer.from(obj.slice(byteOffset, byteOffset + length))
34 + : new Buffer(new Uint8Array(obj.slice(byteOffset, byteOffset + length)))
35 +}
36 +
37 +function fromString (string, encoding) {
38 + if (typeof encoding !== 'string' || encoding === '') {
39 + encoding = 'utf8'
40 + }
41 +
42 + if (!Buffer.isEncoding(encoding)) {
43 + throw new TypeError('"encoding" must be a valid string encoding')
44 + }
45 +
46 + return isModern
47 + ? Buffer.from(string, encoding)
48 + : new Buffer(string, encoding)
49 +}
50 +
51 +function bufferFrom (value, encodingOrOffset, length) {
52 + if (typeof value === 'number') {
53 + throw new TypeError('"value" argument must not be a number')
54 + }
55 +
56 + if (isArrayBuffer(value)) {
57 + return fromArrayBuffer(value, encodingOrOffset, length)
58 + }
59 +
60 + if (typeof value === 'string') {
61 + return fromString(value, encodingOrOffset)
62 + }
63 +
64 + return isModern
65 + ? Buffer.from(value)
66 + : new Buffer(value)
67 +}
68 +
69 +module.exports = bufferFrom
1 +{
2 + "_from": "buffer-from@^1.0.0",
3 + "_id": "buffer-from@1.1.1",
4 + "_inBundle": false,
5 + "_integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
6 + "_location": "/buffer-from",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "buffer-from@^1.0.0",
12 + "name": "buffer-from",
13 + "escapedName": "buffer-from",
14 + "rawSpec": "^1.0.0",
15 + "saveSpec": null,
16 + "fetchSpec": "^1.0.0"
17 + },
18 + "_requiredBy": [
19 + "/concat-stream"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
22 + "_shasum": "32713bc028f75c02fdb710d7c7bcec1f2c6070ef",
23 + "_spec": "buffer-from@^1.0.0",
24 + "_where": "C:\\Users\\1000c\\이것저것\\옾소\\Voicoding\\node_modules\\concat-stream",
25 + "bugs": {
26 + "url": "https://github.com/LinusU/buffer-from/issues"
27 + },
28 + "bundleDependencies": false,
29 + "deprecated": false,
30 + "description": "A [ponyfill](https://ponyfill.com) for `Buffer.from`, uses native implementation if available.",
31 + "devDependencies": {
32 + "standard": "^7.1.2"
33 + },
34 + "files": [
35 + "index.js"
36 + ],
37 + "homepage": "https://github.com/LinusU/buffer-from#readme",
38 + "keywords": [
39 + "buffer",
40 + "buffer from"
41 + ],
42 + "license": "MIT",
43 + "name": "buffer-from",
44 + "repository": {
45 + "type": "git",
46 + "url": "git+https://github.com/LinusU/buffer-from.git"
47 + },
48 + "scripts": {
49 + "test": "standard && node test"
50 + },
51 + "version": "1.1.1"
52 +}
1 +# Buffer From
2 +
3 +A [ponyfill](https://ponyfill.com) for `Buffer.from`, uses native implementation if available.
4 +
5 +## Installation
6 +
7 +```sh
8 +npm install --save buffer-from
9 +```
10 +
11 +## Usage
12 +
13 +```js
14 +const bufferFrom = require('buffer-from')
15 +
16 +console.log(bufferFrom([1, 2, 3, 4]))
17 +//=> <Buffer 01 02 03 04>
18 +
19 +const arr = new Uint8Array([1, 2, 3, 4])
20 +console.log(bufferFrom(arr.buffer, 1, 2))
21 +//=> <Buffer 02 03>
22 +
23 +console.log(bufferFrom('test', 'utf8'))
24 +//=> <Buffer 74 65 73 74>
25 +
26 +const buf = bufferFrom('test')
27 +console.log(bufferFrom(buf))
28 +//=> <Buffer 74 65 73 74>
29 +```
30 +
31 +## API
32 +
33 +### bufferFrom(array)
34 +
35 +- `array` &lt;Array&gt;
36 +
37 +Allocates a new `Buffer` using an `array` of octets.
38 +
39 +### bufferFrom(arrayBuffer[, byteOffset[, length]])
40 +
41 +- `arrayBuffer` &lt;ArrayBuffer&gt; The `.buffer` property of a TypedArray or ArrayBuffer
42 +- `byteOffset` &lt;Integer&gt; Where to start copying from `arrayBuffer`. **Default:** `0`
43 +- `length` &lt;Integer&gt; How many bytes to copy from `arrayBuffer`. **Default:** `arrayBuffer.length - byteOffset`
44 +
45 +When passed a reference to the `.buffer` property of a TypedArray instance, the
46 +newly created `Buffer` will share the same allocated memory as the TypedArray.
47 +
48 +The optional `byteOffset` and `length` arguments specify a memory range within
49 +the `arrayBuffer` that will be shared by the `Buffer`.
50 +
51 +### bufferFrom(buffer)
52 +
53 +- `buffer` &lt;Buffer&gt; An existing `Buffer` to copy data from
54 +
55 +Copies the passed `buffer` data onto a new `Buffer` instance.
56 +
57 +### bufferFrom(string[, encoding])
58 +
59 +- `string` &lt;String&gt; A string to encode.
60 +- `encoding` &lt;String&gt; The encoding of `string`. **Default:** `'utf8'`
61 +
62 +Creates a new `Buffer` containing the given JavaScript string `string`. If
63 +provided, the `encoding` parameter identifies the character encoding of
64 +`string`.
65 +
66 +## See also
67 +
68 +- [buffer-alloc](https://github.com/LinusU/buffer-alloc) A ponyfill for `Buffer.alloc`
69 +- [buffer-alloc-unsafe](https://github.com/LinusU/buffer-alloc-unsafe) A ponyfill for `Buffer.allocUnsafe`
1 +sudo: false
2 +language: cpp
3 +notifications:
4 + email: false
5 +env:
6 + matrix:
7 + - TRAVIS_NODE_VERSION="0.10"
8 + - TRAVIS_NODE_VERSION="0.12"
9 + - TRAVIS_NODE_VERSION="4"
10 + - TRAVIS_NODE_VERSION="6"
11 + - TRAVIS_NODE_VERSION="7"
12 +install:
13 + - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION
14 + - node --version
15 + - npm --version
16 + - npm install
17 +script: npm test
1 +Copyright Brian White. All rights reserved.
2 +
3 +Permission is hereby granted, free of charge, to any person obtaining a copy
4 +of this software and associated documentation files (the "Software"), to
5 +deal in the Software without restriction, including without limitation the
6 +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 +sell copies of the Software, and to permit persons to whom the Software is
8 +furnished to do so, subject to the following conditions:
9 +
10 +The above copyright notice and this permission notice shall be included in
11 +all copies or substantial portions of the Software.
12 +
13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 +IN THE SOFTWARE.
...\ No newline at end of file ...\ No newline at end of file
1 +Description
2 +===========
3 +
4 +A node.js module for parsing incoming HTML form data.
5 +
6 +If you've found this module to be useful and wish to support it, you may do so by visiting this pledgie campaign:
7 +<a href='https://pledgie.com/campaigns/28774'><img alt='Click here to support busboy' src='https://pledgie.com/campaigns/28774.png?skin_name=chrome' border='0'></a>
8 +
9 +
10 +Requirements
11 +============
12 +
13 +* [node.js](http://nodejs.org/) -- v0.8.0 or newer
14 +
15 +
16 +Install
17 +=======
18 +
19 + npm install busboy
20 +
21 +
22 +Examples
23 +========
24 +
25 +* Parsing (multipart) with default options:
26 +
27 +```javascript
28 +var http = require('http'),
29 + inspect = require('util').inspect;
30 +
31 +var Busboy = require('busboy');
32 +
33 +http.createServer(function(req, res) {
34 + if (req.method === 'POST') {
35 + var busboy = new Busboy({ headers: req.headers });
36 + busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
37 + console.log('File [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype);
38 + file.on('data', function(data) {
39 + console.log('File [' + fieldname + '] got ' + data.length + ' bytes');
40 + });
41 + file.on('end', function() {
42 + console.log('File [' + fieldname + '] Finished');
43 + });
44 + });
45 + busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) {
46 + console.log('Field [' + fieldname + ']: value: ' + inspect(val));
47 + });
48 + busboy.on('finish', function() {
49 + console.log('Done parsing form!');
50 + res.writeHead(303, { Connection: 'close', Location: '/' });
51 + res.end();
52 + });
53 + req.pipe(busboy);
54 + } else if (req.method === 'GET') {
55 + res.writeHead(200, { Connection: 'close' });
56 + res.end('<html><head></head><body>\
57 + <form method="POST" enctype="multipart/form-data">\
58 + <input type="text" name="textfield"><br />\
59 + <input type="file" name="filefield"><br />\
60 + <input type="submit">\
61 + </form>\
62 + </body></html>');
63 + }
64 +}).listen(8000, function() {
65 + console.log('Listening for requests');
66 +});
67 +
68 +// Example output, using http://nodejs.org/images/ryan-speaker.jpg as the file:
69 +//
70 +// Listening for requests
71 +// File [filefield]: filename: ryan-speaker.jpg, encoding: binary
72 +// File [filefield] got 11971 bytes
73 +// Field [textfield]: value: 'testing! :-)'
74 +// File [filefield] Finished
75 +// Done parsing form!
76 +```
77 +
78 +* Save all incoming files to disk:
79 +
80 +```javascript
81 +var http = require('http'),
82 + path = require('path'),
83 + os = require('os'),
84 + fs = require('fs');
85 +
86 +var Busboy = require('busboy');
87 +
88 +http.createServer(function(req, res) {
89 + if (req.method === 'POST') {
90 + var busboy = new Busboy({ headers: req.headers });
91 + busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
92 + var saveTo = path.join(os.tmpDir(), path.basename(fieldname));
93 + file.pipe(fs.createWriteStream(saveTo));
94 + });
95 + busboy.on('finish', function() {
96 + res.writeHead(200, { 'Connection': 'close' });
97 + res.end("That's all folks!");
98 + });
99 + return req.pipe(busboy);
100 + }
101 + res.writeHead(404);
102 + res.end();
103 +}).listen(8000, function() {
104 + console.log('Listening for requests');
105 +});
106 +```
107 +
108 +* Parsing (urlencoded) with default options:
109 +
110 +```javascript
111 +var http = require('http'),
112 + inspect = require('util').inspect;
113 +
114 +var Busboy = require('busboy');
115 +
116 +http.createServer(function(req, res) {
117 + if (req.method === 'POST') {
118 + var busboy = new Busboy({ headers: req.headers });
119 + busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
120 + console.log('File [' + fieldname + ']: filename: ' + filename);
121 + file.on('data', function(data) {
122 + console.log('File [' + fieldname + '] got ' + data.length + ' bytes');
123 + });
124 + file.on('end', function() {
125 + console.log('File [' + fieldname + '] Finished');
126 + });
127 + });
128 + busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
129 + console.log('Field [' + fieldname + ']: value: ' + inspect(val));
130 + });
131 + busboy.on('finish', function() {
132 + console.log('Done parsing form!');
133 + res.writeHead(303, { Connection: 'close', Location: '/' });
134 + res.end();
135 + });
136 + req.pipe(busboy);
137 + } else if (req.method === 'GET') {
138 + res.writeHead(200, { Connection: 'close' });
139 + res.end('<html><head></head><body>\
140 + <form method="POST">\
141 + <input type="text" name="textfield"><br />\
142 + <select name="selectfield">\
143 + <option value="1">1</option>\
144 + <option value="10">10</option>\
145 + <option value="100">100</option>\
146 + <option value="9001">9001</option>\
147 + </select><br />\
148 + <input type="checkbox" name="checkfield">Node.js rules!<br />\
149 + <input type="submit">\
150 + </form>\
151 + </body></html>');
152 + }
153 +}).listen(8000, function() {
154 + console.log('Listening for requests');
155 +});
156 +
157 +// Example output:
158 +//
159 +// Listening for requests
160 +// Field [textfield]: value: 'testing! :-)'
161 +// Field [selectfield]: value: '9001'
162 +// Field [checkfield]: value: 'on'
163 +// Done parsing form!
164 +```
165 +
166 +
167 +API
168 +===
169 +
170 +_Busboy_ is a _Writable_ stream
171 +
172 +Busboy (special) events
173 +-----------------------
174 +
175 +* **file**(< _string_ >fieldname, < _ReadableStream_ >stream, < _string_ >filename, < _string_ >transferEncoding, < _string_ >mimeType) - Emitted for each new file form field found. `transferEncoding` contains the 'Content-Transfer-Encoding' value for the file stream. `mimeType` contains the 'Content-Type' value for the file stream.
176 + * Note: if you listen for this event, you should always handle the `stream` no matter if you care about the file contents or not (e.g. you can simply just do `stream.resume();` if you want to discard the contents), otherwise the 'finish' event will never fire on the Busboy instance. However, if you don't care about **any** incoming files, you can simply not listen for the 'file' event at all and any/all files will be automatically and safely discarded (these discarded files do still count towards `files` and `parts` limits).
177 + * If a configured file size limit was reached, `stream` will both have a boolean property `truncated` (best checked at the end of the stream) and emit a 'limit' event to notify you when this happens.
178 +
179 +* **field**(< _string_ >fieldname, < _string_ >value, < _boolean_ >fieldnameTruncated, < _boolean_ >valueTruncated, < _string_ >transferEncoding, < _string_ >mimeType) - Emitted for each new non-file field found.
180 +
181 +* **partsLimit**() - Emitted when specified `parts` limit has been reached. No more 'file' or 'field' events will be emitted.
182 +
183 +* **filesLimit**() - Emitted when specified `files` limit has been reached. No more 'file' events will be emitted.
184 +
185 +* **fieldsLimit**() - Emitted when specified `fields` limit has been reached. No more 'field' events will be emitted.
186 +
187 +
188 +Busboy methods
189 +--------------
190 +
191 +* **(constructor)**(< _object_ >config) - Creates and returns a new Busboy instance.
192 +
193 + * The constructor takes the following valid `config` settings:
194 +
195 + * **headers** - _object_ - These are the HTTP headers of the incoming request, which are used by individual parsers.
196 +
197 + * **highWaterMark** - _integer_ - highWaterMark to use for this Busboy instance (Default: WritableStream default).
198 +
199 + * **fileHwm** - _integer_ - highWaterMark to use for file streams (Default: ReadableStream default).
200 +
201 + * **defCharset** - _string_ - Default character set to use when one isn't defined (Default: 'utf8').
202 +
203 + * **preservePath** - _boolean_ - If paths in the multipart 'filename' field shall be preserved. (Default: false).
204 +
205 + * **limits** - _object_ - Various limits on incoming data. Valid properties are:
206 +
207 + * **fieldNameSize** - _integer_ - Max field name size (in bytes) (Default: 100 bytes).
208 +
209 + * **fieldSize** - _integer_ - Max field value size (in bytes) (Default: 1MB).
210 +
211 + * **fields** - _integer_ - Max number of non-file fields (Default: Infinity).
212 +
213 + * **fileSize** - _integer_ - For multipart forms, the max file size (in bytes) (Default: Infinity).
214 +
215 + * **files** - _integer_ - For multipart forms, the max number of file fields (Default: Infinity).
216 +
217 + * **parts** - _integer_ - For multipart forms, the max number of parts (fields + files) (Default: Infinity).
218 +
219 + * **headerPairs** - _integer_ - For multipart forms, the max number of header key=>value pairs to parse **Default:** 2000 (same as node's http).
220 +
221 + * The constructor can throw errors:
222 +
223 + * **Unsupported content type: $type** - The `Content-Type` isn't one Busboy can parse.
224 +
225 + * **Missing Content-Type** - The provided headers don't include `Content-Type` at all.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
1 +var fs = require('fs'),
2 + WritableStream = require('stream').Writable
3 + || require('readable-stream').Writable,
4 + inherits = require('util').inherits;
5 +
6 +var parseParams = require('./utils').parseParams;
7 +
8 +function Busboy(opts) {
9 + if (!(this instanceof Busboy))
10 + return new Busboy(opts);
11 + if (opts.highWaterMark !== undefined)
12 + WritableStream.call(this, { highWaterMark: opts.highWaterMark });
13 + else
14 + WritableStream.call(this);
15 +
16 + this._done = false;
17 + this._parser = undefined;
18 + this._finished = false;
19 +
20 + this.opts = opts;
21 + if (opts.headers && typeof opts.headers['content-type'] === 'string')
22 + this.parseHeaders(opts.headers);
23 + else
24 + throw new Error('Missing Content-Type');
25 +}
26 +inherits(Busboy, WritableStream);
27 +
28 +Busboy.prototype.emit = function(ev) {
29 + if (ev === 'finish') {
30 + if (!this._done) {
31 + this._parser && this._parser.end();
32 + return;
33 + } else if (this._finished) {
34 + return;
35 + }
36 + this._finished = true;
37 + }
38 + WritableStream.prototype.emit.apply(this, arguments);
39 +};
40 +
41 +Busboy.prototype.parseHeaders = function(headers) {
42 + this._parser = undefined;
43 + if (headers['content-type']) {
44 + var parsed = parseParams(headers['content-type']),
45 + matched, type;
46 + for (var i = 0; i < TYPES.length; ++i) {
47 + type = TYPES[i];
48 + if (typeof type.detect === 'function')
49 + matched = type.detect(parsed);
50 + else
51 + matched = type.detect.test(parsed[0]);
52 + if (matched)
53 + break;
54 + }
55 + if (matched) {
56 + var cfg = {
57 + limits: this.opts.limits,
58 + headers: headers,
59 + parsedConType: parsed,
60 + highWaterMark: undefined,
61 + fileHwm: undefined,
62 + defCharset: undefined,
63 + preservePath: false
64 + };
65 + if (this.opts.highWaterMark)
66 + cfg.highWaterMark = this.opts.highWaterMark;
67 + if (this.opts.fileHwm)
68 + cfg.fileHwm = this.opts.fileHwm;
69 + cfg.defCharset = this.opts.defCharset;
70 + cfg.preservePath = this.opts.preservePath;
71 + this._parser = type(this, cfg);
72 + return;
73 + }
74 + }
75 + throw new Error('Unsupported content type: ' + headers['content-type']);
76 +};
77 +
78 +Busboy.prototype._write = function(chunk, encoding, cb) {
79 + if (!this._parser)
80 + return cb(new Error('Not ready to parse. Missing Content-Type?'));
81 + this._parser.write(chunk, cb);
82 +};
83 +
84 +var TYPES = [
85 + require('./types/multipart'),
86 + require('./types/urlencoded'),
87 +];
88 +
89 +module.exports = Busboy;
1 +// TODO:
2 +// * support 1 nested multipart level
3 +// (see second multipart example here:
4 +// http://www.w3.org/TR/html401/interact/forms.html#didx-multipartform-data)
5 +// * support limits.fieldNameSize
6 +// -- this will require modifications to utils.parseParams
7 +
8 +var ReadableStream = require('stream').Readable || require('readable-stream'),
9 + inherits = require('util').inherits;
10 +
11 +var Dicer = require('dicer');
12 +
13 +var parseParams = require('../utils').parseParams,
14 + decodeText = require('../utils').decodeText,
15 + basename = require('../utils').basename;
16 +
17 +var RE_BOUNDARY = /^boundary$/i,
18 + RE_FIELD = /^form-data$/i,
19 + RE_CHARSET = /^charset$/i,
20 + RE_FILENAME = /^filename$/i,
21 + RE_NAME = /^name$/i;
22 +
23 +Multipart.detect = /^multipart\/form-data/i;
24 +function Multipart(boy, cfg) {
25 + if (!(this instanceof Multipart))
26 + return new Multipart(boy, cfg);
27 + var i,
28 + len,
29 + self = this,
30 + boundary,
31 + limits = cfg.limits,
32 + parsedConType = cfg.parsedConType || [],
33 + defCharset = cfg.defCharset || 'utf8',
34 + preservePath = cfg.preservePath,
35 + fileopts = (typeof cfg.fileHwm === 'number'
36 + ? { highWaterMark: cfg.fileHwm }
37 + : {});
38 +
39 + for (i = 0, len = parsedConType.length; i < len; ++i) {
40 + if (Array.isArray(parsedConType[i])
41 + && RE_BOUNDARY.test(parsedConType[i][0])) {
42 + boundary = parsedConType[i][1];
43 + break;
44 + }
45 + }
46 +
47 + function checkFinished() {
48 + if (nends === 0 && finished && !boy._done) {
49 + finished = false;
50 + process.nextTick(function() {
51 + boy._done = true;
52 + boy.emit('finish');
53 + });
54 + }
55 + }
56 +
57 + if (typeof boundary !== 'string')
58 + throw new Error('Multipart: Boundary not found');
59 +
60 + var fieldSizeLimit = (limits && typeof limits.fieldSize === 'number'
61 + ? limits.fieldSize
62 + : 1 * 1024 * 1024),
63 + fileSizeLimit = (limits && typeof limits.fileSize === 'number'
64 + ? limits.fileSize
65 + : Infinity),
66 + filesLimit = (limits && typeof limits.files === 'number'
67 + ? limits.files
68 + : Infinity),
69 + fieldsLimit = (limits && typeof limits.fields === 'number'
70 + ? limits.fields
71 + : Infinity),
72 + partsLimit = (limits && typeof limits.parts === 'number'
73 + ? limits.parts
74 + : Infinity);
75 +
76 + var nfiles = 0,
77 + nfields = 0,
78 + nends = 0,
79 + curFile,
80 + curField,
81 + finished = false;
82 +
83 + this._needDrain = false;
84 + this._pause = false;
85 + this._cb = undefined;
86 + this._nparts = 0;
87 + this._boy = boy;
88 +
89 + var parserCfg = {
90 + boundary: boundary,
91 + maxHeaderPairs: (limits && limits.headerPairs)
92 + };
93 + if (fileopts.highWaterMark)
94 + parserCfg.partHwm = fileopts.highWaterMark;
95 + if (cfg.highWaterMark)
96 + parserCfg.highWaterMark = cfg.highWaterMark;
97 +
98 + this.parser = new Dicer(parserCfg);
99 + this.parser.on('drain', function() {
100 + self._needDrain = false;
101 + if (self._cb && !self._pause) {
102 + var cb = self._cb;
103 + self._cb = undefined;
104 + cb();
105 + }
106 + }).on('part', function onPart(part) {
107 + if (++self._nparts > partsLimit) {
108 + self.parser.removeListener('part', onPart);
109 + self.parser.on('part', skipPart);
110 + boy.hitPartsLimit = true;
111 + boy.emit('partsLimit');
112 + return skipPart(part);
113 + }
114 +
115 + // hack because streams2 _always_ doesn't emit 'end' until nextTick, so let
116 + // us emit 'end' early since we know the part has ended if we are already
117 + // seeing the next part
118 + if (curField) {
119 + var field = curField;
120 + field.emit('end');
121 + field.removeAllListeners('end');
122 + }
123 +
124 + part.on('header', function(header) {
125 + var contype,
126 + fieldname,
127 + parsed,
128 + charset,
129 + encoding,
130 + filename,
131 + nsize = 0;
132 +
133 + if (header['content-type']) {
134 + parsed = parseParams(header['content-type'][0]);
135 + if (parsed[0]) {
136 + contype = parsed[0].toLowerCase();
137 + for (i = 0, len = parsed.length; i < len; ++i) {
138 + if (RE_CHARSET.test(parsed[i][0])) {
139 + charset = parsed[i][1].toLowerCase();
140 + break;
141 + }
142 + }
143 + }
144 + }
145 +
146 + if (contype === undefined)
147 + contype = 'text/plain';
148 + if (charset === undefined)
149 + charset = defCharset;
150 +
151 + if (header['content-disposition']) {
152 + parsed = parseParams(header['content-disposition'][0]);
153 + if (!RE_FIELD.test(parsed[0]))
154 + return skipPart(part);
155 + for (i = 0, len = parsed.length; i < len; ++i) {
156 + if (RE_NAME.test(parsed[i][0])) {
157 + fieldname = decodeText(parsed[i][1], 'binary', 'utf8');
158 + } else if (RE_FILENAME.test(parsed[i][0])) {
159 + filename = decodeText(parsed[i][1], 'binary', 'utf8');
160 + if (!preservePath)
161 + filename = basename(filename);
162 + }
163 + }
164 + } else
165 + return skipPart(part);
166 +
167 + if (header['content-transfer-encoding'])
168 + encoding = header['content-transfer-encoding'][0].toLowerCase();
169 + else
170 + encoding = '7bit';
171 +
172 + var onData,
173 + onEnd;
174 + if (contype === 'application/octet-stream' || filename !== undefined) {
175 + // file/binary field
176 + if (nfiles === filesLimit) {
177 + if (!boy.hitFilesLimit) {
178 + boy.hitFilesLimit = true;
179 + boy.emit('filesLimit');
180 + }
181 + return skipPart(part);
182 + }
183 +
184 + ++nfiles;
185 +
186 + if (!boy._events.file) {
187 + self.parser._ignore();
188 + return;
189 + }
190 +
191 + ++nends;
192 + var file = new FileStream(fileopts);
193 + curFile = file;
194 + file.on('end', function() {
195 + --nends;
196 + checkFinished();
197 + if (self._cb && !self._needDrain) {
198 + var cb = self._cb;
199 + self._cb = undefined;
200 + cb();
201 + }
202 + });
203 + file._read = function(n) {
204 + if (!self._pause)
205 + return;
206 + self._pause = false;
207 + if (self._cb && !self._needDrain) {
208 + var cb = self._cb;
209 + self._cb = undefined;
210 + cb();
211 + }
212 + };
213 + boy.emit('file', fieldname, file, filename, encoding, contype);
214 +
215 + onData = function(data) {
216 + if ((nsize += data.length) > fileSizeLimit) {
217 + var extralen = (fileSizeLimit - (nsize - data.length));
218 + if (extralen > 0)
219 + file.push(data.slice(0, extralen));
220 + file.emit('limit');
221 + file.truncated = true;
222 + part.removeAllListeners('data');
223 + } else if (!file.push(data))
224 + self._pause = true;
225 + };
226 +
227 + onEnd = function() {
228 + curFile = undefined;
229 + file.push(null);
230 + };
231 + } else {
232 + // non-file field
233 + if (nfields === fieldsLimit) {
234 + if (!boy.hitFieldsLimit) {
235 + boy.hitFieldsLimit = true;
236 + boy.emit('fieldsLimit');
237 + }
238 + return skipPart(part);
239 + }
240 +
241 + ++nfields;
242 + ++nends;
243 + var buffer = '',
244 + truncated = false;
245 + curField = part;
246 +
247 + onData = function(data) {
248 + if ((nsize += data.length) > fieldSizeLimit) {
249 + var extralen = (fieldSizeLimit - (nsize - data.length));
250 + buffer += data.toString('binary', 0, extralen);
251 + truncated = true;
252 + part.removeAllListeners('data');
253 + } else
254 + buffer += data.toString('binary');
255 + };
256 +
257 + onEnd = function() {
258 + curField = undefined;
259 + if (buffer.length)
260 + buffer = decodeText(buffer, 'binary', charset);
261 + boy.emit('field', fieldname, buffer, false, truncated, encoding, contype);
262 + --nends;
263 + checkFinished();
264 + };
265 + }
266 +
267 + /* As of node@2efe4ab761666 (v0.10.29+/v0.11.14+), busboy had become
268 + broken. Streams2/streams3 is a huge black box of confusion, but
269 + somehow overriding the sync state seems to fix things again (and still
270 + seems to work for previous node versions).
271 + */
272 + part._readableState.sync = false;
273 +
274 + part.on('data', onData);
275 + part.on('end', onEnd);
276 + }).on('error', function(err) {
277 + if (curFile)
278 + curFile.emit('error', err);
279 + });
280 + }).on('error', function(err) {
281 + boy.emit('error', err);
282 + }).on('finish', function() {
283 + finished = true;
284 + checkFinished();
285 + });
286 +}
287 +
288 +Multipart.prototype.write = function(chunk, cb) {
289 + var r;
290 + if ((r = this.parser.write(chunk)) && !this._pause)
291 + cb();
292 + else {
293 + this._needDrain = !r;
294 + this._cb = cb;
295 + }
296 +};
297 +
298 +Multipart.prototype.end = function() {
299 + var self = this;
300 + if (this._nparts === 0 && !self._boy._done) {
301 + process.nextTick(function() {
302 + self._boy._done = true;
303 + self._boy.emit('finish');
304 + });
305 + } else if (this.parser.writable)
306 + this.parser.end();
307 +};
308 +
309 +function skipPart(part) {
310 + part.resume();
311 +}
312 +
313 +function FileStream(opts) {
314 + if (!(this instanceof FileStream))
315 + return new FileStream(opts);
316 + ReadableStream.call(this, opts);
317 +
318 + this.truncated = false;
319 +}
320 +inherits(FileStream, ReadableStream);
321 +
322 +FileStream.prototype._read = function(n) {};
323 +
324 +module.exports = Multipart;
1 +var Decoder = require('../utils').Decoder,
2 + decodeText = require('../utils').decodeText;
3 +
4 +var RE_CHARSET = /^charset$/i;
5 +
6 +UrlEncoded.detect = /^application\/x-www-form-urlencoded/i;
7 +function UrlEncoded(boy, cfg) {
8 + if (!(this instanceof UrlEncoded))
9 + return new UrlEncoded(boy, cfg);
10 + var limits = cfg.limits,
11 + headers = cfg.headers,
12 + parsedConType = cfg.parsedConType;
13 + this.boy = boy;
14 +
15 + this.fieldSizeLimit = (limits && typeof limits.fieldSize === 'number'
16 + ? limits.fieldSize
17 + : 1 * 1024 * 1024);
18 + this.fieldNameSizeLimit = (limits && typeof limits.fieldNameSize === 'number'
19 + ? limits.fieldNameSize
20 + : 100);
21 + this.fieldsLimit = (limits && typeof limits.fields === 'number'
22 + ? limits.fields
23 + : Infinity);
24 +
25 + var charset;
26 + for (var i = 0, len = parsedConType.length; i < len; ++i) {
27 + if (Array.isArray(parsedConType[i])
28 + && RE_CHARSET.test(parsedConType[i][0])) {
29 + charset = parsedConType[i][1].toLowerCase();
30 + break;
31 + }
32 + }
33 +
34 + if (charset === undefined)
35 + charset = cfg.defCharset || 'utf8';
36 +
37 + this.decoder = new Decoder();
38 + this.charset = charset;
39 + this._fields = 0;
40 + this._state = 'key';
41 + this._checkingBytes = true;
42 + this._bytesKey = 0;
43 + this._bytesVal = 0;
44 + this._key = '';
45 + this._val = '';
46 + this._keyTrunc = false;
47 + this._valTrunc = false;
48 + this._hitlimit = false;
49 +}
50 +
51 +UrlEncoded.prototype.write = function(data, cb) {
52 + if (this._fields === this.fieldsLimit) {
53 + if (!this.boy.hitFieldsLimit) {
54 + this.boy.hitFieldsLimit = true;
55 + this.boy.emit('fieldsLimit');
56 + }
57 + return cb();
58 + }
59 +
60 + var idxeq, idxamp, i, p = 0, len = data.length;
61 +
62 + while (p < len) {
63 + if (this._state === 'key') {
64 + idxeq = idxamp = undefined;
65 + for (i = p; i < len; ++i) {
66 + if (!this._checkingBytes)
67 + ++p;
68 + if (data[i] === 0x3D/*=*/) {
69 + idxeq = i;
70 + break;
71 + } else if (data[i] === 0x26/*&*/) {
72 + idxamp = i;
73 + break;
74 + }
75 + if (this._checkingBytes && this._bytesKey === this.fieldNameSizeLimit) {
76 + this._hitLimit = true;
77 + break;
78 + } else if (this._checkingBytes)
79 + ++this._bytesKey;
80 + }
81 +
82 + if (idxeq !== undefined) {
83 + // key with assignment
84 + if (idxeq > p)
85 + this._key += this.decoder.write(data.toString('binary', p, idxeq));
86 + this._state = 'val';
87 +
88 + this._hitLimit = false;
89 + this._checkingBytes = true;
90 + this._val = '';
91 + this._bytesVal = 0;
92 + this._valTrunc = false;
93 + this.decoder.reset();
94 +
95 + p = idxeq + 1;
96 + } else if (idxamp !== undefined) {
97 + // key with no assignment
98 + ++this._fields;
99 + var key, keyTrunc = this._keyTrunc;
100 + if (idxamp > p)
101 + key = (this._key += this.decoder.write(data.toString('binary', p, idxamp)));
102 + else
103 + key = this._key;
104 +
105 + this._hitLimit = false;
106 + this._checkingBytes = true;
107 + this._key = '';
108 + this._bytesKey = 0;
109 + this._keyTrunc = false;
110 + this.decoder.reset();
111 +
112 + if (key.length) {
113 + this.boy.emit('field', decodeText(key, 'binary', this.charset),
114 + '',
115 + keyTrunc,
116 + false);
117 + }
118 +
119 + p = idxamp + 1;
120 + if (this._fields === this.fieldsLimit)
121 + return cb();
122 + } else if (this._hitLimit) {
123 + // we may not have hit the actual limit if there are encoded bytes...
124 + if (i > p)
125 + this._key += this.decoder.write(data.toString('binary', p, i));
126 + p = i;
127 + if ((this._bytesKey = this._key.length) === this.fieldNameSizeLimit) {
128 + // yep, we actually did hit the limit
129 + this._checkingBytes = false;
130 + this._keyTrunc = true;
131 + }
132 + } else {
133 + if (p < len)
134 + this._key += this.decoder.write(data.toString('binary', p));
135 + p = len;
136 + }
137 + } else {
138 + idxamp = undefined;
139 + for (i = p; i < len; ++i) {
140 + if (!this._checkingBytes)
141 + ++p;
142 + if (data[i] === 0x26/*&*/) {
143 + idxamp = i;
144 + break;
145 + }
146 + if (this._checkingBytes && this._bytesVal === this.fieldSizeLimit) {
147 + this._hitLimit = true;
148 + break;
149 + }
150 + else if (this._checkingBytes)
151 + ++this._bytesVal;
152 + }
153 +
154 + if (idxamp !== undefined) {
155 + ++this._fields;
156 + if (idxamp > p)
157 + this._val += this.decoder.write(data.toString('binary', p, idxamp));
158 + this.boy.emit('field', decodeText(this._key, 'binary', this.charset),
159 + decodeText(this._val, 'binary', this.charset),
160 + this._keyTrunc,
161 + this._valTrunc);
162 + this._state = 'key';
163 +
164 + this._hitLimit = false;
165 + this._checkingBytes = true;
166 + this._key = '';
167 + this._bytesKey = 0;
168 + this._keyTrunc = false;
169 + this.decoder.reset();
170 +
171 + p = idxamp + 1;
172 + if (this._fields === this.fieldsLimit)
173 + return cb();
174 + } else if (this._hitLimit) {
175 + // we may not have hit the actual limit if there are encoded bytes...
176 + if (i > p)
177 + this._val += this.decoder.write(data.toString('binary', p, i));
178 + p = i;
179 + if ((this._val === '' && this.fieldSizeLimit === 0)
180 + || (this._bytesVal = this._val.length) === this.fieldSizeLimit) {
181 + // yep, we actually did hit the limit
182 + this._checkingBytes = false;
183 + this._valTrunc = true;
184 + }
185 + } else {
186 + if (p < len)
187 + this._val += this.decoder.write(data.toString('binary', p));
188 + p = len;
189 + }
190 + }
191 + }
192 + cb();
193 +};
194 +
195 +UrlEncoded.prototype.end = function() {
196 + if (this.boy._done)
197 + return;
198 +
199 + if (this._state === 'key' && this._key.length > 0) {
200 + this.boy.emit('field', decodeText(this._key, 'binary', this.charset),
201 + '',
202 + this._keyTrunc,
203 + false);
204 + } else if (this._state === 'val') {
205 + this.boy.emit('field', decodeText(this._key, 'binary', this.charset),
206 + decodeText(this._val, 'binary', this.charset),
207 + this._keyTrunc,
208 + this._valTrunc);
209 + }
210 + this.boy._done = true;
211 + this.boy.emit('finish');
212 +};
213 +
214 +module.exports = UrlEncoded;
1 +var jsencoding = require('../deps/encoding/encoding');
2 +
3 +var RE_ENCODED = /%([a-fA-F0-9]{2})/g;
4 +function encodedReplacer(match, byte) {
5 + return String.fromCharCode(parseInt(byte, 16));
6 +}
7 +function parseParams(str) {
8 + var res = [],
9 + state = 'key',
10 + charset = '',
11 + inquote = false,
12 + escaping = false,
13 + p = 0,
14 + tmp = '';
15 +
16 + for (var i = 0, len = str.length; i < len; ++i) {
17 + if (str[i] === '\\' && inquote) {
18 + if (escaping)
19 + escaping = false;
20 + else {
21 + escaping = true;
22 + continue;
23 + }
24 + } else if (str[i] === '"') {
25 + if (!escaping) {
26 + if (inquote) {
27 + inquote = false;
28 + state = 'key';
29 + } else
30 + inquote = true;
31 + continue;
32 + } else
33 + escaping = false;
34 + } else {
35 + if (escaping && inquote)
36 + tmp += '\\';
37 + escaping = false;
38 + if ((state === 'charset' || state === 'lang') && str[i] === "'") {
39 + if (state === 'charset') {
40 + state = 'lang';
41 + charset = tmp.substring(1);
42 + } else
43 + state = 'value';
44 + tmp = '';
45 + continue;
46 + } else if (state === 'key'
47 + && (str[i] === '*' || str[i] === '=')
48 + && res.length) {
49 + if (str[i] === '*')
50 + state = 'charset';
51 + else
52 + state = 'value';
53 + res[p] = [tmp, undefined];
54 + tmp = '';
55 + continue;
56 + } else if (!inquote && str[i] === ';') {
57 + state = 'key';
58 + if (charset) {
59 + if (tmp.length) {
60 + tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer),
61 + 'binary',
62 + charset);
63 + }
64 + charset = '';
65 + }
66 + if (res[p] === undefined)
67 + res[p] = tmp;
68 + else
69 + res[p][1] = tmp;
70 + tmp = '';
71 + ++p;
72 + continue;
73 + } else if (!inquote && (str[i] === ' ' || str[i] === '\t'))
74 + continue;
75 + }
76 + tmp += str[i];
77 + }
78 + if (charset && tmp.length) {
79 + tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer),
80 + 'binary',
81 + charset);
82 + }
83 +
84 + if (res[p] === undefined) {
85 + if (tmp)
86 + res[p] = tmp;
87 + } else
88 + res[p][1] = tmp;
89 +
90 + return res;
91 +};
92 +exports.parseParams = parseParams;
93 +
94 +
95 +function decodeText(text, textEncoding, destEncoding) {
96 + var ret;
97 + if (text && jsencoding.encodingExists(destEncoding)) {
98 + try {
99 + ret = jsencoding.TextDecoder(destEncoding)
100 + .decode(new Buffer(text, textEncoding));
101 + } catch(e) {}
102 + }
103 + return (typeof ret === 'string' ? ret : text);
104 +}
105 +exports.decodeText = decodeText;
106 +
107 +
108 +var HEX = [
109 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
113 + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115 + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
116 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
117 +], RE_PLUS = /\+/g;
118 +function Decoder() {
119 + this.buffer = undefined;
120 +}
121 +Decoder.prototype.write = function(str) {
122 + // Replace '+' with ' ' before decoding
123 + str = str.replace(RE_PLUS, ' ');
124 + var res = '';
125 + var i = 0, p = 0, len = str.length;
126 + for (; i < len; ++i) {
127 + if (this.buffer !== undefined) {
128 + if (!HEX[str.charCodeAt(i)]) {
129 + res += '%' + this.buffer;
130 + this.buffer = undefined;
131 + --i; // retry character
132 + } else {
133 + this.buffer += str[i];
134 + ++p;
135 + if (this.buffer.length === 2) {
136 + res += String.fromCharCode(parseInt(this.buffer, 16));
137 + this.buffer = undefined;
138 + }
139 + }
140 + } else if (str[i] === '%') {
141 + if (i > p) {
142 + res += str.substring(p, i);
143 + p = i;
144 + }
145 + this.buffer = '';
146 + ++p;
147 + }
148 + }
149 + if (p < len && this.buffer === undefined)
150 + res += str.substring(p);
151 + return res;
152 +};
153 +Decoder.prototype.reset = function() {
154 + this.buffer = undefined;
155 +};
156 +exports.Decoder = Decoder;
157 +
158 +
159 +var RE_SPLIT_POSIX =
160 + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/,
161 + RE_SPLIT_DEVICE =
162 + /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/,
163 + RE_SPLIT_WINDOWS =
164 + /^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/;
165 +function splitPathPosix(filename) {
166 + return RE_SPLIT_POSIX.exec(filename).slice(1);
167 +}
168 +function splitPathWindows(filename) {
169 + // Separate device+slash from tail
170 + var result = RE_SPLIT_DEVICE.exec(filename),
171 + device = (result[1] || '') + (result[2] || ''),
172 + tail = result[3] || '';
173 + // Split the tail into dir, basename and extension
174 + var result2 = RE_SPLIT_WINDOWS.exec(tail),
175 + dir = result2[1],
176 + basename = result2[2],
177 + ext = result2[3];
178 + return [device, dir, basename, ext];
179 +}
180 +function basename(path) {
181 + var f = splitPathPosix(path)[2];
182 + if (f === path)
183 + f = splitPathWindows(path)[2];
184 + return f;
185 +}
186 +exports.basename = basename;
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + "_from": "busboy@^0.2.11",
3 + "_id": "busboy@0.2.14",
4 + "_inBundle": false,
5 + "_integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=",
6 + "_location": "/busboy",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "busboy@^0.2.11",
12 + "name": "busboy",
13 + "escapedName": "busboy",
14 + "rawSpec": "^0.2.11",
15 + "saveSpec": null,
16 + "fetchSpec": "^0.2.11"
17 + },
18 + "_requiredBy": [
19 + "/multer"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz",
22 + "_shasum": "6c2a622efcf47c57bbbe1e2a9c37ad36c7925453",
23 + "_spec": "busboy@^0.2.11",
24 + "_where": "C:\\Users\\1000c\\이것저것\\옾소\\Voicoding\\node_modules\\multer",
25 + "author": {
26 + "name": "Brian White",
27 + "email": "mscdex@mscdex.net"
28 + },
29 + "bugs": {
30 + "url": "https://github.com/mscdex/busboy/issues"
31 + },
32 + "bundleDependencies": false,
33 + "dependencies": {
34 + "dicer": "0.2.5",
35 + "readable-stream": "1.1.x"
36 + },
37 + "deprecated": false,
38 + "description": "A streaming parser for HTML form data for node.js",
39 + "engines": {
40 + "node": ">=0.8.0"
41 + },
42 + "homepage": "https://github.com/mscdex/busboy#readme",
43 + "keywords": [
44 + "uploads",
45 + "forms",
46 + "multipart",
47 + "form-data"
48 + ],
49 + "licenses": [
50 + {
51 + "type": "MIT",
52 + "url": "http://github.com/mscdex/busboy/raw/master/LICENSE"
53 + }
54 + ],
55 + "main": "./lib/main",
56 + "name": "busboy",
57 + "repository": {
58 + "type": "git",
59 + "url": "git+ssh://git@github.com/mscdex/busboy.git"
60 + },
61 + "scripts": {
62 + "test": "node test/test.js"
63 + },
64 + "version": "0.2.14"
65 +}
This diff is collapsed. Click to expand it.
1 +var Busboy = require('..');
2 +
3 +var path = require('path'),
4 + inspect = require('util').inspect,
5 + assert = require('assert');
6 +
7 +var EMPTY_FN = function() {};
8 +
9 +var t = 0,
10 + group = path.basename(__filename, '.js') + '/';
11 +
12 +var tests = [
13 + { source: ['foo'],
14 + expected: [['foo', '', false, false]],
15 + what: 'Unassigned value'
16 + },
17 + { source: ['foo=bar'],
18 + expected: [['foo', 'bar', false, false]],
19 + what: 'Assigned value'
20 + },
21 + { source: ['foo&bar=baz'],
22 + expected: [['foo', '', false, false],
23 + ['bar', 'baz', false, false]],
24 + what: 'Unassigned and assigned value'
25 + },
26 + { source: ['foo=bar&baz'],
27 + expected: [['foo', 'bar', false, false],
28 + ['baz', '', false, false]],
29 + what: 'Assigned and unassigned value'
30 + },
31 + { source: ['foo=bar&baz=bla'],
32 + expected: [['foo', 'bar', false, false],
33 + ['baz', 'bla', false, false]],
34 + what: 'Two assigned values'
35 + },
36 + { source: ['foo&bar'],
37 + expected: [['foo', '', false, false],
38 + ['bar', '', false, false]],
39 + what: 'Two unassigned values'
40 + },
41 + { source: ['foo&bar&'],
42 + expected: [['foo', '', false, false],
43 + ['bar', '', false, false]],
44 + what: 'Two unassigned values and ampersand'
45 + },
46 + { source: ['foo=bar+baz%2Bquux'],
47 + expected: [['foo', 'bar baz+quux', false, false]],
48 + what: 'Assigned value with (plus) space'
49 + },
50 + { source: ['foo=bar%20baz%21'],
51 + expected: [['foo', 'bar baz!', false, false]],
52 + what: 'Assigned value with encoded bytes'
53 + },
54 + { source: ['foo%20bar=baz%20bla%21'],
55 + expected: [['foo bar', 'baz bla!', false, false]],
56 + what: 'Assigned value with encoded bytes #2'
57 + },
58 + { source: ['foo=bar%20baz%21&num=1000'],
59 + expected: [['foo', 'bar baz!', false, false],
60 + ['num', '1000', false, false]],
61 + what: 'Two assigned values, one with encoded bytes'
62 + },
63 + { source: ['foo=bar&baz=bla'],
64 + expected: [],
65 + what: 'Limits: zero fields',
66 + limits: { fields: 0 }
67 + },
68 + { source: ['foo=bar&baz=bla'],
69 + expected: [['foo', 'bar', false, false]],
70 + what: 'Limits: one field',
71 + limits: { fields: 1 }
72 + },
73 + { source: ['foo=bar&baz=bla'],
74 + expected: [['foo', 'bar', false, false],
75 + ['baz', 'bla', false, false]],
76 + what: 'Limits: field part lengths match limits',
77 + limits: { fieldNameSize: 3, fieldSize: 3 }
78 + },
79 + { source: ['foo=bar&baz=bla'],
80 + expected: [['fo', 'bar', true, false],
81 + ['ba', 'bla', true, false]],
82 + what: 'Limits: truncated field name',
83 + limits: { fieldNameSize: 2 }
84 + },
85 + { source: ['foo=bar&baz=bla'],
86 + expected: [['foo', 'ba', false, true],
87 + ['baz', 'bl', false, true]],
88 + what: 'Limits: truncated field value',
89 + limits: { fieldSize: 2 }
90 + },
91 + { source: ['foo=bar&baz=bla'],
92 + expected: [['fo', 'ba', true, true],
93 + ['ba', 'bl', true, true]],
94 + what: 'Limits: truncated field name and value',
95 + limits: { fieldNameSize: 2, fieldSize: 2 }
96 + },
97 + { source: ['foo=bar&baz=bla'],
98 + expected: [['fo', '', true, true],
99 + ['ba', '', true, true]],
100 + what: 'Limits: truncated field name and zero value limit',
101 + limits: { fieldNameSize: 2, fieldSize: 0 }
102 + },
103 + { source: ['foo=bar&baz=bla'],
104 + expected: [['', '', true, true],
105 + ['', '', true, true]],
106 + what: 'Limits: truncated zero field name and zero value limit',
107 + limits: { fieldNameSize: 0, fieldSize: 0 }
108 + },
109 + { source: ['&'],
110 + expected: [],
111 + what: 'Ampersand'
112 + },
113 + { source: ['&&&&&'],
114 + expected: [],
115 + what: 'Many ampersands'
116 + },
117 + { source: ['='],
118 + expected: [['', '', false, false]],
119 + what: 'Assigned value, empty name and value'
120 + },
121 + { source: [''],
122 + expected: [],
123 + what: 'Nothing'
124 + },
125 +];
126 +
127 +function next() {
128 + if (t === tests.length)
129 + return;
130 +
131 + var v = tests[t];
132 +
133 + var busboy = new Busboy({
134 + limits: v.limits,
135 + headers: {
136 + 'content-type': 'application/x-www-form-urlencoded; charset=utf-8'
137 + }
138 + }),
139 + finishes = 0,
140 + results = [];
141 +
142 + busboy.on('field', function(key, val, keyTrunc, valTrunc) {
143 + results.push([key, val, keyTrunc, valTrunc]);
144 + });
145 + busboy.on('file', function() {
146 + throw new Error(makeMsg(v.what, 'Unexpected file'));
147 + });
148 + busboy.on('finish', function() {
149 + assert(finishes++ === 0, makeMsg(v.what, 'finish emitted multiple times'));
150 + assert.deepEqual(results.length,
151 + v.expected.length,
152 + makeMsg(v.what, 'Parsed result count mismatch. Saw '
153 + + results.length
154 + + '. Expected: ' + v.expected.length));
155 +
156 + var i = 0;
157 + results.forEach(function(result) {
158 + assert.deepEqual(result,
159 + v.expected[i],
160 + makeMsg(v.what,
161 + 'Result mismatch:\nParsed: ' + inspect(result)
162 + + '\nExpected: ' + inspect(v.expected[i]))
163 + );
164 + ++i;
165 + });
166 + ++t;
167 + next();
168 + });
169 +
170 + v.source.forEach(function(s) {
171 + busboy.write(new Buffer(s, 'utf8'), EMPTY_FN);
172 + });
173 + busboy.end();
174 +}
175 +next();
176 +
177 +function makeMsg(what, msg) {
178 + return '[' + group + what + ']: ' + msg;
179 +}
180 +
181 +process.on('exit', function() {
182 + assert(t === tests.length, makeMsg('_exit', 'Only finished ' + t + '/' + tests.length + ' tests'));
183 +});
1 +var Decoder = require('../lib/utils').Decoder;
2 +
3 +var path = require('path'),
4 + assert = require('assert');
5 +
6 +var group = path.basename(__filename, '.js') + '/';
7 +
8 +[
9 + { source: ['Hello world'],
10 + expected: 'Hello world',
11 + what: 'No encoded bytes'
12 + },
13 + { source: ['Hello%20world'],
14 + expected: 'Hello world',
15 + what: 'One full encoded byte'
16 + },
17 + { source: ['Hello%20world%21'],
18 + expected: 'Hello world!',
19 + what: 'Two full encoded bytes'
20 + },
21 + { source: ['Hello%', '20world'],
22 + expected: 'Hello world',
23 + what: 'One full encoded byte split #1'
24 + },
25 + { source: ['Hello%2', '0world'],
26 + expected: 'Hello world',
27 + what: 'One full encoded byte split #2'
28 + },
29 + { source: ['Hello%20', 'world'],
30 + expected: 'Hello world',
31 + what: 'One full encoded byte (concat)'
32 + },
33 + { source: ['Hello%2Qworld'],
34 + expected: 'Hello%2Qworld',
35 + what: 'Malformed encoded byte #1'
36 + },
37 + { source: ['Hello%world'],
38 + expected: 'Hello%world',
39 + what: 'Malformed encoded byte #2'
40 + },
41 + { source: ['Hello+world'],
42 + expected: 'Hello world',
43 + what: 'Plus to space'
44 + },
45 + { source: ['Hello+world%21'],
46 + expected: 'Hello world!',
47 + what: 'Plus and encoded byte'
48 + },
49 + { source: ['5%2B5%3D10'],
50 + expected: '5+5=10',
51 + what: 'Encoded plus'
52 + },
53 + { source: ['5+%2B+5+%3D+10'],
54 + expected: '5 + 5 = 10',
55 + what: 'Spaces and encoded plus'
56 + },
57 +].forEach(function(v) {
58 + var dec = new Decoder(), result = '';
59 + v.source.forEach(function(s) {
60 + result += dec.write(s);
61 + });
62 + var msg = '[' + group + v.what + ']: decoded string mismatch.\n'
63 + + 'Saw: ' + result + '\n'
64 + + 'Expected: ' + v.expected;
65 + assert.deepEqual(result, v.expected, msg);
66 +});
1 +var parseParams = require('../lib/utils').parseParams;
2 +
3 +var path = require('path'),
4 + assert = require('assert'),
5 + inspect = require('util').inspect;
6 +
7 +var group = path.basename(__filename, '.js') + '/';
8 +
9 +[
10 + { source: 'video/ogg',
11 + expected: ['video/ogg'],
12 + what: 'No parameters'
13 + },
14 + { source: 'video/ogg;',
15 + expected: ['video/ogg'],
16 + what: 'No parameters (with separator)'
17 + },
18 + { source: 'video/ogg; ',
19 + expected: ['video/ogg'],
20 + what: 'No parameters (with separator followed by whitespace)'
21 + },
22 + { source: ';video/ogg',
23 + expected: ['', 'video/ogg'],
24 + what: 'Empty parameter'
25 + },
26 + { source: 'video/*',
27 + expected: ['video/*'],
28 + what: 'Subtype with asterisk'
29 + },
30 + { source: 'text/plain; encoding=utf8',
31 + expected: ['text/plain', ['encoding', 'utf8']],
32 + what: 'Unquoted'
33 + },
34 + { source: 'text/plain; encoding=',
35 + expected: ['text/plain', ['encoding', '']],
36 + what: 'Unquoted empty string'
37 + },
38 + { source: 'text/plain; encoding="utf8"',
39 + expected: ['text/plain', ['encoding', 'utf8']],
40 + what: 'Quoted'
41 + },
42 + { source: 'text/plain; greeting="hello \\"world\\""',
43 + expected: ['text/plain', ['greeting', 'hello "world"']],
44 + what: 'Quotes within quoted'
45 + },
46 + { source: 'text/plain; encoding=""',
47 + expected: ['text/plain', ['encoding', '']],
48 + what: 'Quoted empty string'
49 + },
50 + { source: 'text/plain; encoding="utf8";\t foo=bar;test',
51 + expected: ['text/plain', ['encoding', 'utf8'], ['foo', 'bar'], 'test'],
52 + what: 'Multiple params with various spacing'
53 + },
54 + { source: "text/plain; filename*=iso-8859-1'en'%A3%20rates",
55 + expected: ['text/plain', ['filename', '£ rates']],
56 + what: 'Extended parameter (RFC 5987) with language'
57 + },
58 + { source: "text/plain; filename*=utf-8''%c2%a3%20and%20%e2%82%ac%20rates",
59 + expected: ['text/plain', ['filename', '£ and € rates']],
60 + what: 'Extended parameter (RFC 5987) without language'
61 + },
62 + { source: "text/plain; filename*=utf-8''%E6%B5%8B%E8%AF%95%E6%96%87%E6%A1%A3",
63 + expected: ['text/plain', ['filename', '测试文档']],
64 + what: 'Extended parameter (RFC 5987) without language #2'
65 + },
66 + { source: "text/plain; filename*=iso-8859-1'en'%A3%20rates; altfilename*=utf-8''%c2%a3%20and%20%e2%82%ac%20rates",
67 + expected: ['text/plain', ['filename', '£ rates'], ['altfilename', '£ and € rates']],
68 + what: 'Multiple extended parameters (RFC 5987) with mixed charsets'
69 + },
70 + { source: "text/plain; filename*=iso-8859-1'en'%A3%20rates; altfilename=\"foobarbaz\"",
71 + expected: ['text/plain', ['filename', '£ rates'], ['altfilename', 'foobarbaz']],
72 + what: 'Mixed regular and extended parameters (RFC 5987)'
73 + },
74 + { source: "text/plain; filename=\"foobarbaz\"; altfilename*=iso-8859-1'en'%A3%20rates",
75 + expected: ['text/plain', ['filename', 'foobarbaz'], ['altfilename', '£ rates']],
76 + what: 'Mixed regular and extended parameters (RFC 5987) #2'
77 + },
78 + { source: 'text/plain; filename="C:\\folder\\test.png"',
79 + expected: ['text/plain', ['filename', 'C:\\folder\\test.png']],
80 + what: 'Unescaped backslashes should be considered backslashes'
81 + },
82 + { source: 'text/plain; filename="John \\"Magic\\" Smith.png"',
83 + expected: ['text/plain', ['filename', 'John "Magic" Smith.png']],
84 + what: 'Escaped double-quotes should be considered double-quotes'
85 + },
86 + { source: 'multipart/form-data; charset=utf-8; boundary=0xKhTmLbOuNdArY',
87 + expected: ['multipart/form-data', ['charset', 'utf-8'], ['boundary', '0xKhTmLbOuNdArY']],
88 + what: 'Multiple non-quoted parameters'
89 + },
90 +].forEach(function(v) {
91 + var result = parseParams(v.source),
92 + msg = '[' + group + v.what + ']: parsed parameters mismatch.\n'
93 + + 'Saw: ' + inspect(result) + '\n'
94 + + 'Expected: ' + inspect(v.expected);
95 + assert.deepEqual(result, v.expected, msg);
96 +});
1 +require('fs').readdirSync(__dirname).forEach(function(f) {
2 + if (f.substr(0, 5) === 'test-')
3 + require('./' + f);
4 +});
...\ No newline at end of file ...\ No newline at end of file
1 +The MIT License
2 +
3 +Copyright (c) 2013 Max Ogden
4 +
5 +Permission is hereby granted, free of charge,
6 +to any person obtaining a copy of this software and
7 +associated documentation files (the "Software"), to
8 +deal in the Software without restriction, including
9 +without limitation the rights to use, copy, modify,
10 +merge, publish, distribute, sublicense, and/or sell
11 +copies of the Software, and to permit persons to whom
12 +the Software is furnished to do so,
13 +subject to the following conditions:
14 +
15 +The above copyright notice and this permission notice
16 +shall be included in all copies or substantial portions of the Software.
17 +
18 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
22 +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
...\ No newline at end of file ...\ No newline at end of file
1 +var Writable = require('readable-stream').Writable
2 +var inherits = require('inherits')
3 +var bufferFrom = require('buffer-from')
4 +
5 +if (typeof Uint8Array === 'undefined') {
6 + var U8 = require('typedarray').Uint8Array
7 +} else {
8 + var U8 = Uint8Array
9 +}
10 +
11 +function ConcatStream(opts, cb) {
12 + if (!(this instanceof ConcatStream)) return new ConcatStream(opts, cb)
13 +
14 + if (typeof opts === 'function') {
15 + cb = opts
16 + opts = {}
17 + }
18 + if (!opts) opts = {}
19 +
20 + var encoding = opts.encoding
21 + var shouldInferEncoding = false
22 +
23 + if (!encoding) {
24 + shouldInferEncoding = true
25 + } else {
26 + encoding = String(encoding).toLowerCase()
27 + if (encoding === 'u8' || encoding === 'uint8') {
28 + encoding = 'uint8array'
29 + }
30 + }
31 +
32 + Writable.call(this, { objectMode: true })
33 +
34 + this.encoding = encoding
35 + this.shouldInferEncoding = shouldInferEncoding
36 +
37 + if (cb) this.on('finish', function () { cb(this.getBody()) })
38 + this.body = []
39 +}
40 +
41 +module.exports = ConcatStream
42 +inherits(ConcatStream, Writable)
43 +
44 +ConcatStream.prototype._write = function(chunk, enc, next) {
45 + this.body.push(chunk)
46 + next()
47 +}
48 +
49 +ConcatStream.prototype.inferEncoding = function (buff) {
50 + var firstBuffer = buff === undefined ? this.body[0] : buff;
51 + if (Buffer.isBuffer(firstBuffer)) return 'buffer'
52 + if (typeof Uint8Array !== 'undefined' && firstBuffer instanceof Uint8Array) return 'uint8array'
53 + if (Array.isArray(firstBuffer)) return 'array'
54 + if (typeof firstBuffer === 'string') return 'string'
55 + if (Object.prototype.toString.call(firstBuffer) === "[object Object]") return 'object'
56 + return 'buffer'
57 +}
58 +
59 +ConcatStream.prototype.getBody = function () {
60 + if (!this.encoding && this.body.length === 0) return []
61 + if (this.shouldInferEncoding) this.encoding = this.inferEncoding()
62 + if (this.encoding === 'array') return arrayConcat(this.body)
63 + if (this.encoding === 'string') return stringConcat(this.body)
64 + if (this.encoding === 'buffer') return bufferConcat(this.body)
65 + if (this.encoding === 'uint8array') return u8Concat(this.body)
66 + return this.body
67 +}
68 +
69 +var isArray = Array.isArray || function (arr) {
70 + return Object.prototype.toString.call(arr) == '[object Array]'
71 +}
72 +
73 +function isArrayish (arr) {
74 + return /Array\]$/.test(Object.prototype.toString.call(arr))
75 +}
76 +
77 +function isBufferish (p) {
78 + return typeof p === 'string' || isArrayish(p) || (p && typeof p.subarray === 'function')
79 +}
80 +
81 +function stringConcat (parts) {
82 + var strings = []
83 + var needsToString = false
84 + for (var i = 0; i < parts.length; i++) {
85 + var p = parts[i]
86 + if (typeof p === 'string') {
87 + strings.push(p)
88 + } else if (Buffer.isBuffer(p)) {
89 + strings.push(p)
90 + } else if (isBufferish(p)) {
91 + strings.push(bufferFrom(p))
92 + } else {
93 + strings.push(bufferFrom(String(p)))
94 + }
95 + }
96 + if (Buffer.isBuffer(parts[0])) {
97 + strings = Buffer.concat(strings)
98 + strings = strings.toString('utf8')
99 + } else {
100 + strings = strings.join('')
101 + }
102 + return strings
103 +}
104 +
105 +function bufferConcat (parts) {
106 + var bufs = []
107 + for (var i = 0; i < parts.length; i++) {
108 + var p = parts[i]
109 + if (Buffer.isBuffer(p)) {
110 + bufs.push(p)
111 + } else if (isBufferish(p)) {
112 + bufs.push(bufferFrom(p))
113 + } else {
114 + bufs.push(bufferFrom(String(p)))
115 + }
116 + }
117 + return Buffer.concat(bufs)
118 +}
119 +
120 +function arrayConcat (parts) {
121 + var res = []
122 + for (var i = 0; i < parts.length; i++) {
123 + res.push.apply(res, parts[i])
124 + }
125 + return res
126 +}
127 +
128 +function u8Concat (parts) {
129 + var len = 0
130 + for (var i = 0; i < parts.length; i++) {
131 + if (typeof parts[i] === 'string') {
132 + parts[i] = bufferFrom(parts[i])
133 + }
134 + len += parts[i].length
135 + }
136 + var u8 = new U8(len)
137 + for (var i = 0, offset = 0; i < parts.length; i++) {
138 + var part = parts[i]
139 + for (var j = 0; j < part.length; j++) {
140 + u8[offset++] = part[j]
141 + }
142 + }
143 + return u8
144 +}
1 +language: node_js
2 +node_js:
3 + - "0.8"
4 + - "0.10"
1 +
2 +test:
3 + @node_modules/.bin/tape test.js
4 +
5 +.PHONY: test
6 +
1 +
2 +# isarray
3 +
4 +`Array#isArray` for older browsers.
5 +
6 +[![build status](https://secure.travis-ci.org/juliangruber/isarray.svg)](http://travis-ci.org/juliangruber/isarray)
7 +[![downloads](https://img.shields.io/npm/dm/isarray.svg)](https://www.npmjs.org/package/isarray)
8 +
9 +[![browser support](https://ci.testling.com/juliangruber/isarray.png)
10 +](https://ci.testling.com/juliangruber/isarray)
11 +
12 +## Usage
13 +
14 +```js
15 +var isArray = require('isarray');
16 +
17 +console.log(isArray([])); // => true
18 +console.log(isArray({})); // => false
19 +```
20 +
21 +## Installation
22 +
23 +With [npm](http://npmjs.org) do
24 +
25 +```bash
26 +$ npm install isarray
27 +```
28 +
29 +Then bundle for the browser with
30 +[browserify](https://github.com/substack/browserify).
31 +
32 +With [component](http://component.io) do
33 +
34 +```bash
35 +$ component install juliangruber/isarray
36 +```
37 +
38 +## License
39 +
40 +(MIT)
41 +
42 +Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
43 +
44 +Permission is hereby granted, free of charge, to any person obtaining a copy of
45 +this software and associated documentation files (the "Software"), to deal in
46 +the Software without restriction, including without limitation the rights to
47 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
48 +of the Software, and to permit persons to whom the Software is furnished to do
49 +so, subject to the following conditions:
50 +
51 +The above copyright notice and this permission notice shall be included in all
52 +copies or substantial portions of the Software.
53 +
54 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
55 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
56 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
57 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
58 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
59 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
60 +SOFTWARE.
1 +{
2 + "name" : "isarray",
3 + "description" : "Array#isArray for older browsers",
4 + "version" : "0.0.1",
5 + "repository" : "juliangruber/isarray",
6 + "homepage": "https://github.com/juliangruber/isarray",
7 + "main" : "index.js",
8 + "scripts" : [
9 + "index.js"
10 + ],
11 + "dependencies" : {},
12 + "keywords": ["browser","isarray","array"],
13 + "author": {
14 + "name": "Julian Gruber",
15 + "email": "mail@juliangruber.com",
16 + "url": "http://juliangruber.com"
17 + },
18 + "license": "MIT"
19 +}
1 +var toString = {}.toString;
2 +
3 +module.exports = Array.isArray || function (arr) {
4 + return toString.call(arr) == '[object Array]';
5 +};
1 +{
2 + "_from": "isarray@~1.0.0",
3 + "_id": "isarray@1.0.0",
4 + "_inBundle": false,
5 + "_integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
6 + "_location": "/concat-stream/isarray",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "isarray@~1.0.0",
12 + "name": "isarray",
13 + "escapedName": "isarray",
14 + "rawSpec": "~1.0.0",
15 + "saveSpec": null,
16 + "fetchSpec": "~1.0.0"
17 + },
18 + "_requiredBy": [
19 + "/concat-stream/readable-stream"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
22 + "_shasum": "bb935d48582cba168c06834957a54a3e07124f11",
23 + "_spec": "isarray@~1.0.0",
24 + "_where": "C:\\Users\\1000c\\이것저것\\옾소\\Voicoding\\node_modules\\concat-stream\\node_modules\\readable-stream",
25 + "author": {
26 + "name": "Julian Gruber",
27 + "email": "mail@juliangruber.com",
28 + "url": "http://juliangruber.com"
29 + },
30 + "bugs": {
31 + "url": "https://github.com/juliangruber/isarray/issues"
32 + },
33 + "bundleDependencies": false,
34 + "dependencies": {},
35 + "deprecated": false,
36 + "description": "Array#isArray for older browsers",
37 + "devDependencies": {
38 + "tape": "~2.13.4"
39 + },
40 + "homepage": "https://github.com/juliangruber/isarray",
41 + "keywords": [
42 + "browser",
43 + "isarray",
44 + "array"
45 + ],
46 + "license": "MIT",
47 + "main": "index.js",
48 + "name": "isarray",
49 + "repository": {
50 + "type": "git",
51 + "url": "git://github.com/juliangruber/isarray.git"
52 + },
53 + "scripts": {
54 + "test": "tape test.js"
55 + },
56 + "testling": {
57 + "files": "test.js",
58 + "browsers": [
59 + "ie/8..latest",
60 + "firefox/17..latest",
61 + "firefox/nightly",
62 + "chrome/22..latest",
63 + "chrome/canary",
64 + "opera/12..latest",
65 + "opera/next",
66 + "safari/5.1..latest",
67 + "ipad/6.0..latest",
68 + "iphone/6.0..latest",
69 + "android-browser/4.2..latest"
70 + ]
71 + },
72 + "version": "1.0.0"
73 +}
1 +var isArray = require('./');
2 +var test = require('tape');
3 +
4 +test('is array', function(t){
5 + t.ok(isArray([]));
6 + t.notOk(isArray({}));
7 + t.notOk(isArray(null));
8 + t.notOk(isArray(false));
9 +
10 + var obj = {};
11 + obj[0] = true;
12 + t.notOk(isArray(obj));
13 +
14 + var arr = [];
15 + arr.foo = 'bar';
16 + t.ok(isArray(arr));
17 +
18 + t.end();
19 +});
20 +
1 +sudo: false
2 +language: node_js
3 +before_install:
4 + - (test $NPM_LEGACY && npm install -g npm@2 && npm install -g npm@3) || true
5 +notifications:
6 + email: false
7 +matrix:
8 + fast_finish: true
9 + include:
10 + - node_js: '0.8'
11 + env: NPM_LEGACY=true
12 + - node_js: '0.10'
13 + env: NPM_LEGACY=true
14 + - node_js: '0.11'
15 + env: NPM_LEGACY=true
16 + - node_js: '0.12'
17 + env: NPM_LEGACY=true
18 + - node_js: 1
19 + env: NPM_LEGACY=true
20 + - node_js: 2
21 + env: NPM_LEGACY=true
22 + - node_js: 3
23 + env: NPM_LEGACY=true
24 + - node_js: 4
25 + - node_js: 5
26 + - node_js: 6
27 + - node_js: 7
28 + - node_js: 8
29 + - node_js: 9
30 +script: "npm run test"
31 +env:
32 + global:
33 + - secure: rE2Vvo7vnjabYNULNyLFxOyt98BoJexDqsiOnfiD6kLYYsiQGfr/sbZkPMOFm9qfQG7pjqx+zZWZjGSswhTt+626C0t/njXqug7Yps4c3dFblzGfreQHp7wNX5TFsvrxd6dAowVasMp61sJcRnB2w8cUzoe3RAYUDHyiHktwqMc=
34 + - secure: g9YINaKAdMatsJ28G9jCGbSaguXCyxSTy+pBO6Ch0Cf57ZLOTka3HqDj8p3nV28LUIHZ3ut5WO43CeYKwt4AUtLpBS3a0dndHdY6D83uY6b2qh5hXlrcbeQTq2cvw2y95F7hm4D1kwrgZ7ViqaKggRcEupAL69YbJnxeUDKWEdI=
1 +Node.js is licensed for use as follows:
2 +
3 +"""
4 +Copyright Node.js contributors. All rights reserved.
5 +
6 +Permission is hereby granted, free of charge, to any person obtaining a copy
7 +of this software and associated documentation files (the "Software"), to
8 +deal in the Software without restriction, including without limitation the
9 +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 +sell copies of the Software, and to permit persons to whom the Software is
11 +furnished to do so, subject to the following conditions:
12 +
13 +The above copyright notice and this permission notice shall be included in
14 +all copies or substantial portions of the Software.
15 +
16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 +IN THE SOFTWARE.
23 +"""
24 +
25 +This license applies to parts of Node.js originating from the
26 +https://github.com/joyent/node repository:
27 +
28 +"""
29 +Copyright Joyent, Inc. and other Node contributors. All rights reserved.
30 +Permission is hereby granted, free of charge, to any person obtaining a copy
31 +of this software and associated documentation files (the "Software"), to
32 +deal in the Software without restriction, including without limitation the
33 +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
34 +sell copies of the Software, and to permit persons to whom the Software is
35 +furnished to do so, subject to the following conditions:
36 +
37 +The above copyright notice and this permission notice shall be included in
38 +all copies or substantial portions of the Software.
39 +
40 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
43 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
44 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
45 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
46 +IN THE SOFTWARE.
47 +"""
1 +# readable-stream
2 +
3 +***Node-core v8.11.1 streams for userland*** [![Build Status](https://travis-ci.org/nodejs/readable-stream.svg?branch=master)](https://travis-ci.org/nodejs/readable-stream)
4 +
5 +
6 +[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/)
7 +[![NPM](https://nodei.co/npm-dl/readable-stream.png?&months=6&height=3)](https://nodei.co/npm/readable-stream/)
8 +
9 +
10 +[![Sauce Test Status](https://saucelabs.com/browser-matrix/readable-stream.svg)](https://saucelabs.com/u/readable-stream)
11 +
12 +```bash
13 +npm install --save readable-stream
14 +```
15 +
16 +***Node-core streams for userland***
17 +
18 +This package is a mirror of the Streams2 and Streams3 implementations in
19 +Node-core.
20 +
21 +Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.11.1/docs/api/stream.html).
22 +
23 +If you want to guarantee a stable streams base, regardless of what version of
24 +Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core, for background see [this blogpost](http://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html).
25 +
26 +As of version 2.0.0 **readable-stream** uses semantic versioning.
27 +
28 +# Streams Working Group
29 +
30 +`readable-stream` is maintained by the Streams Working Group, which
31 +oversees the development and maintenance of the Streams API within
32 +Node.js. The responsibilities of the Streams Working Group include:
33 +
34 +* Addressing stream issues on the Node.js issue tracker.
35 +* Authoring and editing stream documentation within the Node.js project.
36 +* Reviewing changes to stream subclasses within the Node.js project.
37 +* Redirecting changes to streams from the Node.js project to this
38 + project.
39 +* Assisting in the implementation of stream providers within Node.js.
40 +* Recommending versions of `readable-stream` to be included in Node.js.
41 +* Messaging about the future of streams to give the community advance
42 + notice of changes.
43 +
44 +<a name="members"></a>
45 +## Team Members
46 +
47 +* **Chris Dickinson** ([@chrisdickinson](https://github.com/chrisdickinson)) &lt;christopher.s.dickinson@gmail.com&gt;
48 + - Release GPG key: 9554F04D7259F04124DE6B476D5A82AC7E37093B
49 +* **Calvin Metcalf** ([@calvinmetcalf](https://github.com/calvinmetcalf)) &lt;calvin.metcalf@gmail.com&gt;
50 + - Release GPG key: F3EF5F62A87FC27A22E643F714CE4FF5015AA242
51 +* **Rod Vagg** ([@rvagg](https://github.com/rvagg)) &lt;rod@vagg.org&gt;
52 + - Release GPG key: DD8F2338BAE7501E3DD5AC78C273792F7D83545D
53 +* **Sam Newman** ([@sonewman](https://github.com/sonewman)) &lt;newmansam@outlook.com&gt;
54 +* **Mathias Buus** ([@mafintosh](https://github.com/mafintosh)) &lt;mathiasbuus@gmail.com&gt;
55 +* **Domenic Denicola** ([@domenic](https://github.com/domenic)) &lt;d@domenic.me&gt;
56 +* **Matteo Collina** ([@mcollina](https://github.com/mcollina)) &lt;matteo.collina@gmail.com&gt;
57 + - Release GPG key: 3ABC01543F22DD2239285CDD818674489FBC127E
58 +* **Irina Shestak** ([@lrlna](https://github.com/lrlna)) &lt;shestak.irina@gmail.com&gt;
1 +# streams WG Meeting 2015-01-30
2 +
3 +## Links
4 +
5 +* **Google Hangouts Video**: http://www.youtube.com/watch?v=I9nDOSGfwZg
6 +* **GitHub Issue**: https://github.com/iojs/readable-stream/issues/106
7 +* **Original Minutes Google Doc**: https://docs.google.com/document/d/17aTgLnjMXIrfjgNaTUnHQO7m3xgzHR2VXBTmi03Qii4/
8 +
9 +## Agenda
10 +
11 +Extracted from https://github.com/iojs/readable-stream/labels/wg-agenda prior to meeting.
12 +
13 +* adopt a charter [#105](https://github.com/iojs/readable-stream/issues/105)
14 +* release and versioning strategy [#101](https://github.com/iojs/readable-stream/issues/101)
15 +* simpler stream creation [#102](https://github.com/iojs/readable-stream/issues/102)
16 +* proposal: deprecate implicit flowing of streams [#99](https://github.com/iojs/readable-stream/issues/99)
17 +
18 +## Minutes
19 +
20 +### adopt a charter
21 +
22 +* group: +1's all around
23 +
24 +### What versioning scheme should be adopted?
25 +* group: +1’s 3.0.0
26 +* domenic+group: pulling in patches from other sources where appropriate
27 +* mikeal: version independently, suggesting versions for io.js
28 +* mikeal+domenic: work with TC to notify in advance of changes
29 +simpler stream creation
30 +
31 +### streamline creation of streams
32 +* sam: streamline creation of streams
33 +* domenic: nice simple solution posted
34 + but, we lose the opportunity to change the model
35 + may not be backwards incompatible (double check keys)
36 +
37 + **action item:** domenic will check
38 +
39 +### remove implicit flowing of streams on(‘data’)
40 +* add isFlowing / isPaused
41 +* mikeal: worrying that we’re documenting polyfill methods – confuses users
42 +* domenic: more reflective API is probably good, with warning labels for users
43 +* new section for mad scientists (reflective stream access)
44 +* calvin: name the “third state”
45 +* mikeal: maybe borrow the name from whatwg?
46 +* domenic: we’re missing the “third state”
47 +* consensus: kind of difficult to name the third state
48 +* mikeal: figure out differences in states / compat
49 +* mathias: always flow on data – eliminates third state
50 + * explore what it breaks
51 +
52 +**action items:**
53 +* ask isaac for ability to list packages by what public io.js APIs they use (esp. Stream)
54 +* ask rod/build for infrastructure
55 +* **chris**: explore the “flow on data” approach
56 +* add isPaused/isFlowing
57 +* add new docs section
58 +* move isPaused to that section
59 +
60 +
1 +module.exports = require('./lib/_stream_duplex.js');
1 +module.exports = require('./readable').Duplex
1 +// Copyright Joyent, Inc. and other Node contributors.
2 +//
3 +// Permission is hereby granted, free of charge, to any person obtaining a
4 +// copy of this software and associated documentation files (the
5 +// "Software"), to deal in the Software without restriction, including
6 +// without limitation the rights to use, copy, modify, merge, publish,
7 +// distribute, sublicense, and/or sell copies of the Software, and to permit
8 +// persons to whom the Software is furnished to do so, subject to the
9 +// following conditions:
10 +//
11 +// The above copyright notice and this permission notice shall be included
12 +// in all copies or substantial portions of the Software.
13 +//
14 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 +// USE OR OTHER DEALINGS IN THE SOFTWARE.
21 +
22 +// a duplex stream is just a stream that is both readable and writable.
23 +// Since JS doesn't have multiple prototypal inheritance, this class
24 +// prototypally inherits from Readable, and then parasitically from
25 +// Writable.
26 +
27 +'use strict';
28 +
29 +/*<replacement>*/
30 +
31 +var pna = require('process-nextick-args');
32 +/*</replacement>*/
33 +
34 +/*<replacement>*/
35 +var objectKeys = Object.keys || function (obj) {
36 + var keys = [];
37 + for (var key in obj) {
38 + keys.push(key);
39 + }return keys;
40 +};
41 +/*</replacement>*/
42 +
43 +module.exports = Duplex;
44 +
45 +/*<replacement>*/
46 +var util = Object.create(require('core-util-is'));
47 +util.inherits = require('inherits');
48 +/*</replacement>*/
49 +
50 +var Readable = require('./_stream_readable');
51 +var Writable = require('./_stream_writable');
52 +
53 +util.inherits(Duplex, Readable);
54 +
55 +{
56 + // avoid scope creep, the keys array can then be collected
57 + var keys = objectKeys(Writable.prototype);
58 + for (var v = 0; v < keys.length; v++) {
59 + var method = keys[v];
60 + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
61 + }
62 +}
63 +
64 +function Duplex(options) {
65 + if (!(this instanceof Duplex)) return new Duplex(options);
66 +
67 + Readable.call(this, options);
68 + Writable.call(this, options);
69 +
70 + if (options && options.readable === false) this.readable = false;
71 +
72 + if (options && options.writable === false) this.writable = false;
73 +
74 + this.allowHalfOpen = true;
75 + if (options && options.allowHalfOpen === false) this.allowHalfOpen = false;
76 +
77 + this.once('end', onend);
78 +}
79 +
80 +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', {
81 + // making it explicit this property is not enumerable
82 + // because otherwise some prototype manipulation in
83 + // userland will fail
84 + enumerable: false,
85 + get: function () {
86 + return this._writableState.highWaterMark;
87 + }
88 +});
89 +
90 +// the no-half-open enforcer
91 +function onend() {
92 + // if we allow half-open state, or if the writable side ended,
93 + // then we're ok.
94 + if (this.allowHalfOpen || this._writableState.ended) return;
95 +
96 + // no more data can be written.
97 + // But allow more writes to happen in this tick.
98 + pna.nextTick(onEndNT, this);
99 +}
100 +
101 +function onEndNT(self) {
102 + self.end();
103 +}
104 +
105 +Object.defineProperty(Duplex.prototype, 'destroyed', {
106 + get: function () {
107 + if (this._readableState === undefined || this._writableState === undefined) {
108 + return false;
109 + }
110 + return this._readableState.destroyed && this._writableState.destroyed;
111 + },
112 + set: function (value) {
113 + // we ignore the value if the stream
114 + // has not been initialized yet
115 + if (this._readableState === undefined || this._writableState === undefined) {
116 + return;
117 + }
118 +
119 + // backward compatibility, the user is explicitly
120 + // managing destroyed
121 + this._readableState.destroyed = value;
122 + this._writableState.destroyed = value;
123 + }
124 +});
125 +
126 +Duplex.prototype._destroy = function (err, cb) {
127 + this.push(null);
128 + this.end();
129 +
130 + pna.nextTick(cb, err);
131 +};
...\ No newline at end of file ...\ No newline at end of file
1 +// Copyright Joyent, Inc. and other Node contributors.
2 +//
3 +// Permission is hereby granted, free of charge, to any person obtaining a
4 +// copy of this software and associated documentation files (the
5 +// "Software"), to deal in the Software without restriction, including
6 +// without limitation the rights to use, copy, modify, merge, publish,
7 +// distribute, sublicense, and/or sell copies of the Software, and to permit
8 +// persons to whom the Software is furnished to do so, subject to the
9 +// following conditions:
10 +//
11 +// The above copyright notice and this permission notice shall be included
12 +// in all copies or substantial portions of the Software.
13 +//
14 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 +// USE OR OTHER DEALINGS IN THE SOFTWARE.
21 +
22 +// a passthrough stream.
23 +// basically just the most minimal sort of Transform stream.
24 +// Every written chunk gets output as-is.
25 +
26 +'use strict';
27 +
28 +module.exports = PassThrough;
29 +
30 +var Transform = require('./_stream_transform');
31 +
32 +/*<replacement>*/
33 +var util = Object.create(require('core-util-is'));
34 +util.inherits = require('inherits');
35 +/*</replacement>*/
36 +
37 +util.inherits(PassThrough, Transform);
38 +
39 +function PassThrough(options) {
40 + if (!(this instanceof PassThrough)) return new PassThrough(options);
41 +
42 + Transform.call(this, options);
43 +}
44 +
45 +PassThrough.prototype._transform = function (chunk, encoding, cb) {
46 + cb(null, chunk);
47 +};
...\ No newline at end of file ...\ No newline at end of file
1 +// Copyright Joyent, Inc. and other Node contributors.
2 +//
3 +// Permission is hereby granted, free of charge, to any person obtaining a
4 +// copy of this software and associated documentation files (the
5 +// "Software"), to deal in the Software without restriction, including
6 +// without limitation the rights to use, copy, modify, merge, publish,
7 +// distribute, sublicense, and/or sell copies of the Software, and to permit
8 +// persons to whom the Software is furnished to do so, subject to the
9 +// following conditions:
10 +//
11 +// The above copyright notice and this permission notice shall be included
12 +// in all copies or substantial portions of the Software.
13 +//
14 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 +// USE OR OTHER DEALINGS IN THE SOFTWARE.
21 +
22 +// a transform stream is a readable/writable stream where you do
23 +// something with the data. Sometimes it's called a "filter",
24 +// but that's not a great name for it, since that implies a thing where
25 +// some bits pass through, and others are simply ignored. (That would
26 +// be a valid example of a transform, of course.)
27 +//
28 +// While the output is causally related to the input, it's not a
29 +// necessarily symmetric or synchronous transformation. For example,
30 +// a zlib stream might take multiple plain-text writes(), and then
31 +// emit a single compressed chunk some time in the future.
32 +//
33 +// Here's how this works:
34 +//
35 +// The Transform stream has all the aspects of the readable and writable
36 +// stream classes. When you write(chunk), that calls _write(chunk,cb)
37 +// internally, and returns false if there's a lot of pending writes
38 +// buffered up. When you call read(), that calls _read(n) until
39 +// there's enough pending readable data buffered up.
40 +//
41 +// In a transform stream, the written data is placed in a buffer. When
42 +// _read(n) is called, it transforms the queued up data, calling the
43 +// buffered _write cb's as it consumes chunks. If consuming a single
44 +// written chunk would result in multiple output chunks, then the first
45 +// outputted bit calls the readcb, and subsequent chunks just go into
46 +// the read buffer, and will cause it to emit 'readable' if necessary.
47 +//
48 +// This way, back-pressure is actually determined by the reading side,
49 +// since _read has to be called to start processing a new chunk. However,
50 +// a pathological inflate type of transform can cause excessive buffering
51 +// here. For example, imagine a stream where every byte of input is
52 +// interpreted as an integer from 0-255, and then results in that many
53 +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in
54 +// 1kb of data being output. In this case, you could write a very small
55 +// amount of input, and end up with a very large amount of output. In
56 +// such a pathological inflating mechanism, there'd be no way to tell
57 +// the system to stop doing the transform. A single 4MB write could
58 +// cause the system to run out of memory.
59 +//
60 +// However, even in such a pathological case, only a single written chunk
61 +// would be consumed, and then the rest would wait (un-transformed) until
62 +// the results of the previous transformed chunk were consumed.
63 +
64 +'use strict';
65 +
66 +module.exports = Transform;
67 +
68 +var Duplex = require('./_stream_duplex');
69 +
70 +/*<replacement>*/
71 +var util = Object.create(require('core-util-is'));
72 +util.inherits = require('inherits');
73 +/*</replacement>*/
74 +
75 +util.inherits(Transform, Duplex);
76 +
77 +function afterTransform(er, data) {
78 + var ts = this._transformState;
79 + ts.transforming = false;
80 +
81 + var cb = ts.writecb;
82 +
83 + if (!cb) {
84 + return this.emit('error', new Error('write callback called multiple times'));
85 + }
86 +
87 + ts.writechunk = null;
88 + ts.writecb = null;
89 +
90 + if (data != null) // single equals check for both `null` and `undefined`
91 + this.push(data);
92 +
93 + cb(er);
94 +
95 + var rs = this._readableState;
96 + rs.reading = false;
97 + if (rs.needReadable || rs.length < rs.highWaterMark) {
98 + this._read(rs.highWaterMark);
99 + }
100 +}
101 +
102 +function Transform(options) {
103 + if (!(this instanceof Transform)) return new Transform(options);
104 +
105 + Duplex.call(this, options);
106 +
107 + this._transformState = {
108 + afterTransform: afterTransform.bind(this),
109 + needTransform: false,
110 + transforming: false,
111 + writecb: null,
112 + writechunk: null,
113 + writeencoding: null
114 + };
115 +
116 + // start out asking for a readable event once data is transformed.
117 + this._readableState.needReadable = true;
118 +
119 + // we have implemented the _read method, and done the other things
120 + // that Readable wants before the first _read call, so unset the
121 + // sync guard flag.
122 + this._readableState.sync = false;
123 +
124 + if (options) {
125 + if (typeof options.transform === 'function') this._transform = options.transform;
126 +
127 + if (typeof options.flush === 'function') this._flush = options.flush;
128 + }
129 +
130 + // When the writable side finishes, then flush out anything remaining.
131 + this.on('prefinish', prefinish);
132 +}
133 +
134 +function prefinish() {
135 + var _this = this;
136 +
137 + if (typeof this._flush === 'function') {
138 + this._flush(function (er, data) {
139 + done(_this, er, data);
140 + });
141 + } else {
142 + done(this, null, null);
143 + }
144 +}
145 +
146 +Transform.prototype.push = function (chunk, encoding) {
147 + this._transformState.needTransform = false;
148 + return Duplex.prototype.push.call(this, chunk, encoding);
149 +};
150 +
151 +// This is the part where you do stuff!
152 +// override this function in implementation classes.
153 +// 'chunk' is an input chunk.
154 +//
155 +// Call `push(newChunk)` to pass along transformed output
156 +// to the readable side. You may call 'push' zero or more times.
157 +//
158 +// Call `cb(err)` when you are done with this chunk. If you pass
159 +// an error, then that'll put the hurt on the whole operation. If you
160 +// never call cb(), then you'll never get another chunk.
161 +Transform.prototype._transform = function (chunk, encoding, cb) {
162 + throw new Error('_transform() is not implemented');
163 +};
164 +
165 +Transform.prototype._write = function (chunk, encoding, cb) {
166 + var ts = this._transformState;
167 + ts.writecb = cb;
168 + ts.writechunk = chunk;
169 + ts.writeencoding = encoding;
170 + if (!ts.transforming) {
171 + var rs = this._readableState;
172 + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
173 + }
174 +};
175 +
176 +// Doesn't matter what the args are here.
177 +// _transform does all the work.
178 +// That we got here means that the readable side wants more data.
179 +Transform.prototype._read = function (n) {
180 + var ts = this._transformState;
181 +
182 + if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
183 + ts.transforming = true;
184 + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
185 + } else {
186 + // mark that we need a transform, so that any data that comes in
187 + // will get processed, now that we've asked for it.
188 + ts.needTransform = true;
189 + }
190 +};
191 +
192 +Transform.prototype._destroy = function (err, cb) {
193 + var _this2 = this;
194 +
195 + Duplex.prototype._destroy.call(this, err, function (err2) {
196 + cb(err2);
197 + _this2.emit('close');
198 + });
199 +};
200 +
201 +function done(stream, er, data) {
202 + if (er) return stream.emit('error', er);
203 +
204 + if (data != null) // single equals check for both `null` and `undefined`
205 + stream.push(data);
206 +
207 + // if there's nothing in the write buffer, then that means
208 + // that nothing more will ever be provided
209 + if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0');
210 +
211 + if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming');
212 +
213 + return stream.push(null);
214 +}
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4 +
5 +var Buffer = require('safe-buffer').Buffer;
6 +var util = require('util');
7 +
8 +function copyBuffer(src, target, offset) {
9 + src.copy(target, offset);
10 +}
11 +
12 +module.exports = function () {
13 + function BufferList() {
14 + _classCallCheck(this, BufferList);
15 +
16 + this.head = null;
17 + this.tail = null;
18 + this.length = 0;
19 + }
20 +
21 + BufferList.prototype.push = function push(v) {
22 + var entry = { data: v, next: null };
23 + if (this.length > 0) this.tail.next = entry;else this.head = entry;
24 + this.tail = entry;
25 + ++this.length;
26 + };
27 +
28 + BufferList.prototype.unshift = function unshift(v) {
29 + var entry = { data: v, next: this.head };
30 + if (this.length === 0) this.tail = entry;
31 + this.head = entry;
32 + ++this.length;
33 + };
34 +
35 + BufferList.prototype.shift = function shift() {
36 + if (this.length === 0) return;
37 + var ret = this.head.data;
38 + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
39 + --this.length;
40 + return ret;
41 + };
42 +
43 + BufferList.prototype.clear = function clear() {
44 + this.head = this.tail = null;
45 + this.length = 0;
46 + };
47 +
48 + BufferList.prototype.join = function join(s) {
49 + if (this.length === 0) return '';
50 + var p = this.head;
51 + var ret = '' + p.data;
52 + while (p = p.next) {
53 + ret += s + p.data;
54 + }return ret;
55 + };
56 +
57 + BufferList.prototype.concat = function concat(n) {
58 + if (this.length === 0) return Buffer.alloc(0);
59 + if (this.length === 1) return this.head.data;
60 + var ret = Buffer.allocUnsafe(n >>> 0);
61 + var p = this.head;
62 + var i = 0;
63 + while (p) {
64 + copyBuffer(p.data, ret, i);
65 + i += p.data.length;
66 + p = p.next;
67 + }
68 + return ret;
69 + };
70 +
71 + return BufferList;
72 +}();
73 +
74 +if (util && util.inspect && util.inspect.custom) {
75 + module.exports.prototype[util.inspect.custom] = function () {
76 + var obj = util.inspect({ length: this.length });
77 + return this.constructor.name + ' ' + obj;
78 + };
79 +}
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +/*<replacement>*/
4 +
5 +var pna = require('process-nextick-args');
6 +/*</replacement>*/
7 +
8 +// undocumented cb() API, needed for core, not for public API
9 +function destroy(err, cb) {
10 + var _this = this;
11 +
12 + var readableDestroyed = this._readableState && this._readableState.destroyed;
13 + var writableDestroyed = this._writableState && this._writableState.destroyed;
14 +
15 + if (readableDestroyed || writableDestroyed) {
16 + if (cb) {
17 + cb(err);
18 + } else if (err && (!this._writableState || !this._writableState.errorEmitted)) {
19 + pna.nextTick(emitErrorNT, this, err);
20 + }
21 + return this;
22 + }
23 +
24 + // we set destroyed to true before firing error callbacks in order
25 + // to make it re-entrance safe in case destroy() is called within callbacks
26 +
27 + if (this._readableState) {
28 + this._readableState.destroyed = true;
29 + }
30 +
31 + // if this is a duplex stream mark the writable part as destroyed as well
32 + if (this._writableState) {
33 + this._writableState.destroyed = true;
34 + }
35 +
36 + this._destroy(err || null, function (err) {
37 + if (!cb && err) {
38 + pna.nextTick(emitErrorNT, _this, err);
39 + if (_this._writableState) {
40 + _this._writableState.errorEmitted = true;
41 + }
42 + } else if (cb) {
43 + cb(err);
44 + }
45 + });
46 +
47 + return this;
48 +}
49 +
50 +function undestroy() {
51 + if (this._readableState) {
52 + this._readableState.destroyed = false;
53 + this._readableState.reading = false;
54 + this._readableState.ended = false;
55 + this._readableState.endEmitted = false;
56 + }
57 +
58 + if (this._writableState) {
59 + this._writableState.destroyed = false;
60 + this._writableState.ended = false;
61 + this._writableState.ending = false;
62 + this._writableState.finished = false;
63 + this._writableState.errorEmitted = false;
64 + }
65 +}
66 +
67 +function emitErrorNT(self, err) {
68 + self.emit('error', err);
69 +}
70 +
71 +module.exports = {
72 + destroy: destroy,
73 + undestroy: undestroy
74 +};
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + "_from": "readable-stream@^2.2.2",
3 + "_id": "readable-stream@2.3.7",
4 + "_inBundle": false,
5 + "_integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
6 + "_location": "/concat-stream/readable-stream",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "readable-stream@^2.2.2",
12 + "name": "readable-stream",
13 + "escapedName": "readable-stream",
14 + "rawSpec": "^2.2.2",
15 + "saveSpec": null,
16 + "fetchSpec": "^2.2.2"
17 + },
18 + "_requiredBy": [
19 + "/concat-stream"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
22 + "_shasum": "1eca1cf711aef814c04f62252a36a62f6cb23b57",
23 + "_spec": "readable-stream@^2.2.2",
24 + "_where": "C:\\Users\\1000c\\이것저것\\옾소\\Voicoding\\node_modules\\concat-stream",
25 + "browser": {
26 + "util": false,
27 + "./readable.js": "./readable-browser.js",
28 + "./writable.js": "./writable-browser.js",
29 + "./duplex.js": "./duplex-browser.js",
30 + "./lib/internal/streams/stream.js": "./lib/internal/streams/stream-browser.js"
31 + },
32 + "bugs": {
33 + "url": "https://github.com/nodejs/readable-stream/issues"
34 + },
35 + "bundleDependencies": false,
36 + "dependencies": {
37 + "core-util-is": "~1.0.0",
38 + "inherits": "~2.0.3",
39 + "isarray": "~1.0.0",
40 + "process-nextick-args": "~2.0.0",
41 + "safe-buffer": "~5.1.1",
42 + "string_decoder": "~1.1.1",
43 + "util-deprecate": "~1.0.1"
44 + },
45 + "deprecated": false,
46 + "description": "Streams3, a user-land copy of the stream library from Node.js",
47 + "devDependencies": {
48 + "assert": "^1.4.0",
49 + "babel-polyfill": "^6.9.1",
50 + "buffer": "^4.9.0",
51 + "lolex": "^2.3.2",
52 + "nyc": "^6.4.0",
53 + "tap": "^0.7.0",
54 + "tape": "^4.8.0"
55 + },
56 + "homepage": "https://github.com/nodejs/readable-stream#readme",
57 + "keywords": [
58 + "readable",
59 + "stream",
60 + "pipe"
61 + ],
62 + "license": "MIT",
63 + "main": "readable.js",
64 + "name": "readable-stream",
65 + "nyc": {
66 + "include": [
67 + "lib/**.js"
68 + ]
69 + },
70 + "repository": {
71 + "type": "git",
72 + "url": "git://github.com/nodejs/readable-stream.git"
73 + },
74 + "scripts": {
75 + "ci": "tap test/parallel/*.js test/ours/*.js --tap | tee test.tap && node test/verify-dependencies.js",
76 + "cover": "nyc npm test",
77 + "report": "nyc report --reporter=lcov",
78 + "test": "tap test/parallel/*.js test/ours/*.js && node test/verify-dependencies.js"
79 + },
80 + "version": "2.3.7"
81 +}
1 +module.exports = require('./readable').PassThrough
1 +exports = module.exports = require('./lib/_stream_readable.js');
2 +exports.Stream = exports;
3 +exports.Readable = exports;
4 +exports.Writable = require('./lib/_stream_writable.js');
5 +exports.Duplex = require('./lib/_stream_duplex.js');
6 +exports.Transform = require('./lib/_stream_transform.js');
7 +exports.PassThrough = require('./lib/_stream_passthrough.js');
1 +var Stream = require('stream');
2 +if (process.env.READABLE_STREAM === 'disable' && Stream) {
3 + module.exports = Stream;
4 + exports = module.exports = Stream.Readable;
5 + exports.Readable = Stream.Readable;
6 + exports.Writable = Stream.Writable;
7 + exports.Duplex = Stream.Duplex;
8 + exports.Transform = Stream.Transform;
9 + exports.PassThrough = Stream.PassThrough;
10 + exports.Stream = Stream;
11 +} else {
12 + exports = module.exports = require('./lib/_stream_readable.js');
13 + exports.Stream = Stream || exports;
14 + exports.Readable = exports;
15 + exports.Writable = require('./lib/_stream_writable.js');
16 + exports.Duplex = require('./lib/_stream_duplex.js');
17 + exports.Transform = require('./lib/_stream_transform.js');
18 + exports.PassThrough = require('./lib/_stream_passthrough.js');
19 +}
1 +module.exports = require('./readable').Transform
1 +module.exports = require('./lib/_stream_writable.js');
1 +var Stream = require("stream")
2 +var Writable = require("./lib/_stream_writable.js")
3 +
4 +if (process.env.READABLE_STREAM === 'disable') {
5 + module.exports = Stream && Stream.Writable || Writable
6 +} else {
7 + module.exports = Writable
8 +}
1 +sudo: false
2 +language: node_js
3 +before_install:
4 + - npm install -g npm@2
5 + - test $NPM_LEGACY && npm install -g npm@latest-3 || npm install npm -g
6 +notifications:
7 + email: false
8 +matrix:
9 + fast_finish: true
10 + include:
11 + - node_js: '0.8'
12 + env:
13 + - TASK=test
14 + - NPM_LEGACY=true
15 + - node_js: '0.10'
16 + env:
17 + - TASK=test
18 + - NPM_LEGACY=true
19 + - node_js: '0.11'
20 + env:
21 + - TASK=test
22 + - NPM_LEGACY=true
23 + - node_js: '0.12'
24 + env:
25 + - TASK=test
26 + - NPM_LEGACY=true
27 + - node_js: 1
28 + env:
29 + - TASK=test
30 + - NPM_LEGACY=true
31 + - node_js: 2
32 + env:
33 + - TASK=test
34 + - NPM_LEGACY=true
35 + - node_js: 3
36 + env:
37 + - TASK=test
38 + - NPM_LEGACY=true
39 + - node_js: 4
40 + env: TASK=test
41 + - node_js: 5
42 + env: TASK=test
43 + - node_js: 6
44 + env: TASK=test
45 + - node_js: 7
46 + env: TASK=test
47 + - node_js: 8
48 + env: TASK=test
49 + - node_js: 9
50 + env: TASK=test
1 +Node.js is licensed for use as follows:
2 +
3 +"""
4 +Copyright Node.js contributors. All rights reserved.
5 +
6 +Permission is hereby granted, free of charge, to any person obtaining a copy
7 +of this software and associated documentation files (the "Software"), to
8 +deal in the Software without restriction, including without limitation the
9 +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 +sell copies of the Software, and to permit persons to whom the Software is
11 +furnished to do so, subject to the following conditions:
12 +
13 +The above copyright notice and this permission notice shall be included in
14 +all copies or substantial portions of the Software.
15 +
16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 +IN THE SOFTWARE.
23 +"""
24 +
25 +This license applies to parts of Node.js originating from the
26 +https://github.com/joyent/node repository:
27 +
28 +"""
29 +Copyright Joyent, Inc. and other Node contributors. All rights reserved.
30 +Permission is hereby granted, free of charge, to any person obtaining a copy
31 +of this software and associated documentation files (the "Software"), to
32 +deal in the Software without restriction, including without limitation the
33 +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
34 +sell copies of the Software, and to permit persons to whom the Software is
35 +furnished to do so, subject to the following conditions:
36 +
37 +The above copyright notice and this permission notice shall be included in
38 +all copies or substantial portions of the Software.
39 +
40 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
43 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
44 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
45 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
46 +IN THE SOFTWARE.
47 +"""
48 +
1 +# string_decoder
2 +
3 +***Node-core v8.9.4 string_decoder for userland***
4 +
5 +
6 +[![NPM](https://nodei.co/npm/string_decoder.png?downloads=true&downloadRank=true)](https://nodei.co/npm/string_decoder/)
7 +[![NPM](https://nodei.co/npm-dl/string_decoder.png?&months=6&height=3)](https://nodei.co/npm/string_decoder/)
8 +
9 +
10 +```bash
11 +npm install --save string_decoder
12 +```
13 +
14 +***Node-core string_decoder for userland***
15 +
16 +This package is a mirror of the string_decoder implementation in Node-core.
17 +
18 +Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.9.4/docs/api/).
19 +
20 +As of version 1.0.0 **string_decoder** uses semantic versioning.
21 +
22 +## Previous versions
23 +
24 +Previous version numbers match the versions found in Node core, e.g. 0.10.24 matches Node 0.10.24, likewise 0.11.10 matches Node 0.11.10.
25 +
26 +## Update
27 +
28 +The *build/* directory contains a build script that will scrape the source from the [nodejs/node](https://github.com/nodejs/node) repo given a specific Node version.
29 +
30 +## Streams Working Group
31 +
32 +`string_decoder` is maintained by the Streams Working Group, which
33 +oversees the development and maintenance of the Streams API within
34 +Node.js. The responsibilities of the Streams Working Group include:
35 +
36 +* Addressing stream issues on the Node.js issue tracker.
37 +* Authoring and editing stream documentation within the Node.js project.
38 +* Reviewing changes to stream subclasses within the Node.js project.
39 +* Redirecting changes to streams from the Node.js project to this
40 + project.
41 +* Assisting in the implementation of stream providers within Node.js.
42 +* Recommending versions of `readable-stream` to be included in Node.js.
43 +* Messaging about the future of streams to give the community advance
44 + notice of changes.
45 +
46 +See [readable-stream](https://github.com/nodejs/readable-stream) for
47 +more details.
1 +{
2 + "_from": "string_decoder@~1.1.1",
3 + "_id": "string_decoder@1.1.1",
4 + "_inBundle": false,
5 + "_integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
6 + "_location": "/concat-stream/string_decoder",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "string_decoder@~1.1.1",
12 + "name": "string_decoder",
13 + "escapedName": "string_decoder",
14 + "rawSpec": "~1.1.1",
15 + "saveSpec": null,
16 + "fetchSpec": "~1.1.1"
17 + },
18 + "_requiredBy": [
19 + "/concat-stream/readable-stream"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
22 + "_shasum": "9cf1611ba62685d7030ae9e4ba34149c3af03fc8",
23 + "_spec": "string_decoder@~1.1.1",
24 + "_where": "C:\\Users\\1000c\\이것저것\\옾소\\Voicoding\\node_modules\\concat-stream\\node_modules\\readable-stream",
25 + "bugs": {
26 + "url": "https://github.com/nodejs/string_decoder/issues"
27 + },
28 + "bundleDependencies": false,
29 + "dependencies": {
30 + "safe-buffer": "~5.1.0"
31 + },
32 + "deprecated": false,
33 + "description": "The string_decoder module from Node core",
34 + "devDependencies": {
35 + "babel-polyfill": "^6.23.0",
36 + "core-util-is": "^1.0.2",
37 + "inherits": "^2.0.3",
38 + "tap": "~0.4.8"
39 + },
40 + "homepage": "https://github.com/nodejs/string_decoder",
41 + "keywords": [
42 + "string",
43 + "decoder",
44 + "browser",
45 + "browserify"
46 + ],
47 + "license": "MIT",
48 + "main": "lib/string_decoder.js",
49 + "name": "string_decoder",
50 + "repository": {
51 + "type": "git",
52 + "url": "git://github.com/nodejs/string_decoder.git"
53 + },
54 + "scripts": {
55 + "ci": "tap test/parallel/*.js test/ours/*.js --tap | tee test.tap && node test/verify-dependencies.js",
56 + "test": "tap test/parallel/*.js && node test/verify-dependencies"
57 + },
58 + "version": "1.1.1"
59 +}
1 +{
2 + "_from": "concat-stream@^1.5.2",
3 + "_id": "concat-stream@1.6.2",
4 + "_inBundle": false,
5 + "_integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
6 + "_location": "/concat-stream",
7 + "_phantomChildren": {
8 + "core-util-is": "1.0.2",
9 + "inherits": "2.0.4",
10 + "process-nextick-args": "2.0.1",
11 + "safe-buffer": "5.1.2",
12 + "util-deprecate": "1.0.2"
13 + },
14 + "_requested": {
15 + "type": "range",
16 + "registry": true,
17 + "raw": "concat-stream@^1.5.2",
18 + "name": "concat-stream",
19 + "escapedName": "concat-stream",
20 + "rawSpec": "^1.5.2",
21 + "saveSpec": null,
22 + "fetchSpec": "^1.5.2"
23 + },
24 + "_requiredBy": [
25 + "/multer"
26 + ],
27 + "_resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
28 + "_shasum": "904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34",
29 + "_spec": "concat-stream@^1.5.2",
30 + "_where": "C:\\Users\\1000c\\이것저것\\옾소\\Voicoding\\node_modules\\multer",
31 + "author": {
32 + "name": "Max Ogden",
33 + "email": "max@maxogden.com"
34 + },
35 + "bugs": {
36 + "url": "http://github.com/maxogden/concat-stream/issues"
37 + },
38 + "bundleDependencies": false,
39 + "dependencies": {
40 + "buffer-from": "^1.0.0",
41 + "inherits": "^2.0.3",
42 + "readable-stream": "^2.2.2",
43 + "typedarray": "^0.0.6"
44 + },
45 + "deprecated": false,
46 + "description": "writable stream that concatenates strings or binary data and calls a callback with the result",
47 + "devDependencies": {
48 + "tape": "^4.6.3"
49 + },
50 + "engines": [
51 + "node >= 0.8"
52 + ],
53 + "files": [
54 + "index.js"
55 + ],
56 + "homepage": "https://github.com/maxogden/concat-stream#readme",
57 + "license": "MIT",
58 + "main": "index.js",
59 + "name": "concat-stream",
60 + "repository": {
61 + "type": "git",
62 + "url": "git+ssh://git@github.com/maxogden/concat-stream.git"
63 + },
64 + "scripts": {
65 + "test": "tape test/*.js test/server/*.js"
66 + },
67 + "tags": [
68 + "stream",
69 + "simple",
70 + "util",
71 + "utility"
72 + ],
73 + "testling": {
74 + "files": "test/*.js",
75 + "browsers": [
76 + "ie/8..latest",
77 + "firefox/17..latest",
78 + "firefox/nightly",
79 + "chrome/22..latest",
80 + "chrome/canary",
81 + "opera/12..latest",
82 + "opera/next",
83 + "safari/5.1..latest",
84 + "ipad/6.0..latest",
85 + "iphone/6.0..latest",
86 + "android-browser/4.2..latest"
87 + ]
88 + },
89 + "version": "1.6.2"
90 +}
1 +# concat-stream
2 +
3 +Writable stream that concatenates all the data from a stream and calls a callback with the result. Use this when you want to collect all the data from a stream into a single buffer.
4 +
5 +[![Build Status](https://travis-ci.org/maxogden/concat-stream.svg?branch=master)](https://travis-ci.org/maxogden/concat-stream)
6 +
7 +[![NPM](https://nodei.co/npm/concat-stream.png)](https://nodei.co/npm/concat-stream/)
8 +
9 +### description
10 +
11 +Streams emit many buffers. If you want to collect all of the buffers, and when the stream ends concatenate all of the buffers together and receive a single buffer then this is the module for you.
12 +
13 +Only use this if you know you can fit all of the output of your stream into a single Buffer (e.g. in RAM).
14 +
15 +There are also `objectMode` streams that emit things other than Buffers, and you can concatenate these too. See below for details.
16 +
17 +## Related
18 +
19 +`concat-stream` is part of the [mississippi stream utility collection](https://github.com/maxogden/mississippi) which includes more useful stream modules similar to this one.
20 +
21 +### examples
22 +
23 +#### Buffers
24 +
25 +```js
26 +var fs = require('fs')
27 +var concat = require('concat-stream')
28 +
29 +var readStream = fs.createReadStream('cat.png')
30 +var concatStream = concat(gotPicture)
31 +
32 +readStream.on('error', handleError)
33 +readStream.pipe(concatStream)
34 +
35 +function gotPicture(imageBuffer) {
36 + // imageBuffer is all of `cat.png` as a node.js Buffer
37 +}
38 +
39 +function handleError(err) {
40 + // handle your error appropriately here, e.g.:
41 + console.error(err) // print the error to STDERR
42 + process.exit(1) // exit program with non-zero exit code
43 +}
44 +
45 +```
46 +
47 +#### Arrays
48 +
49 +```js
50 +var write = concat(function(data) {})
51 +write.write([1,2,3])
52 +write.write([4,5,6])
53 +write.end()
54 +// data will be [1,2,3,4,5,6] in the above callback
55 +```
56 +
57 +#### Uint8Arrays
58 +
59 +```js
60 +var write = concat(function(data) {})
61 +var a = new Uint8Array(3)
62 +a[0] = 97; a[1] = 98; a[2] = 99
63 +write.write(a)
64 +write.write('!')
65 +write.end(Buffer.from('!!1'))
66 +```
67 +
68 +See `test/` for more examples
69 +
70 +# methods
71 +
72 +```js
73 +var concat = require('concat-stream')
74 +```
75 +
76 +## var writable = concat(opts={}, cb)
77 +
78 +Return a `writable` stream that will fire `cb(data)` with all of the data that
79 +was written to the stream. Data can be written to `writable` as strings,
80 +Buffers, arrays of byte integers, and Uint8Arrays.
81 +
82 +By default `concat-stream` will give you back the same data type as the type of the first buffer written to the stream. Use `opts.encoding` to set what format `data` should be returned as, e.g. if you if you don't want to rely on the built-in type checking or for some other reason.
83 +
84 +* `string` - get a string
85 +* `buffer` - get back a Buffer
86 +* `array` - get an array of byte integers
87 +* `uint8array`, `u8`, `uint8` - get back a Uint8Array
88 +* `object`, get back an array of Objects
89 +
90 +If you don't specify an encoding, and the types can't be inferred (e.g. you write things that aren't in the list above), it will try to convert concat them into a `Buffer`.
91 +
92 +If nothing is written to `writable` then `data` will be an empty array `[]`.
93 +
94 +# error handling
95 +
96 +`concat-stream` does not handle errors for you, so you must handle errors on whatever streams you pipe into `concat-stream`. This is a general rule when programming with node.js streams: always handle errors on each and every stream. Since `concat-stream` is not itself a stream it does not emit errors.
97 +
98 +We recommend using [`end-of-stream`](https://npmjs.org/end-of-stream) or [`pump`](https://npmjs.org/pump) for writing error tolerant stream code.
99 +
100 +# license
101 +
102 +MIT LICENSE
1 +Copyright Node.js contributors. All rights reserved.
2 +
3 +Permission is hereby granted, free of charge, to any person obtaining a copy
4 +of this software and associated documentation files (the "Software"), to
5 +deal in the Software without restriction, including without limitation the
6 +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 +sell copies of the Software, and to permit persons to whom the Software is
8 +furnished to do so, subject to the following conditions:
9 +
10 +The above copyright notice and this permission notice shall be included in
11 +all copies or substantial portions of the Software.
12 +
13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 +IN THE SOFTWARE.
1 +# core-util-is
2 +
3 +The `util.is*` functions introduced in Node v0.12.
This diff is collapsed. Click to expand it.
1 +// Copyright Joyent, Inc. and other Node contributors.
2 +//
3 +// Permission is hereby granted, free of charge, to any person obtaining a
4 +// copy of this software and associated documentation files (the
5 +// "Software"), to deal in the Software without restriction, including
6 +// without limitation the rights to use, copy, modify, merge, publish,
7 +// distribute, sublicense, and/or sell copies of the Software, and to permit
8 +// persons to whom the Software is furnished to do so, subject to the
9 +// following conditions:
10 +//
11 +// The above copyright notice and this permission notice shall be included
12 +// in all copies or substantial portions of the Software.
13 +//
14 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 +// USE OR OTHER DEALINGS IN THE SOFTWARE.
21 +
22 +// NOTE: These type checking functions intentionally don't use `instanceof`
23 +// because it is fragile and can be easily faked with `Object.create()`.
24 +
25 +function isArray(arg) {
26 + if (Array.isArray) {
27 + return Array.isArray(arg);
28 + }
29 + return objectToString(arg) === '[object Array]';
30 +}
31 +exports.isArray = isArray;
32 +
33 +function isBoolean(arg) {
34 + return typeof arg === 'boolean';
35 +}
36 +exports.isBoolean = isBoolean;
37 +
38 +function isNull(arg) {
39 + return arg === null;
40 +}
41 +exports.isNull = isNull;
42 +
43 +function isNullOrUndefined(arg) {
44 + return arg == null;
45 +}
46 +exports.isNullOrUndefined = isNullOrUndefined;
47 +
48 +function isNumber(arg) {
49 + return typeof arg === 'number';
50 +}
51 +exports.isNumber = isNumber;
52 +
53 +function isString(arg) {
54 + return typeof arg === 'string';
55 +}
56 +exports.isString = isString;
57 +
58 +function isSymbol(arg) {
59 + return typeof arg === 'symbol';
60 +}
61 +exports.isSymbol = isSymbol;
62 +
63 +function isUndefined(arg) {
64 + return arg === void 0;
65 +}
66 +exports.isUndefined = isUndefined;
67 +
68 +function isRegExp(re) {
69 + return objectToString(re) === '[object RegExp]';
70 +}
71 +exports.isRegExp = isRegExp;
72 +
73 +function isObject(arg) {
74 + return typeof arg === 'object' && arg !== null;
75 +}
76 +exports.isObject = isObject;
77 +
78 +function isDate(d) {
79 + return objectToString(d) === '[object Date]';
80 +}
81 +exports.isDate = isDate;
82 +
83 +function isError(e) {
84 + return (objectToString(e) === '[object Error]' || e instanceof Error);
85 +}
86 +exports.isError = isError;
87 +
88 +function isFunction(arg) {
89 + return typeof arg === 'function';
90 +}
91 +exports.isFunction = isFunction;
92 +
93 +function isPrimitive(arg) {
94 + return arg === null ||
95 + typeof arg === 'boolean' ||
96 + typeof arg === 'number' ||
97 + typeof arg === 'string' ||
98 + typeof arg === 'symbol' || // ES6 symbol
99 + typeof arg === 'undefined';
100 +}
101 +exports.isPrimitive = isPrimitive;
102 +
103 +exports.isBuffer = Buffer.isBuffer;
104 +
105 +function objectToString(o) {
106 + return Object.prototype.toString.call(o);
107 +}
1 +{
2 + "_from": "core-util-is@~1.0.0",
3 + "_id": "core-util-is@1.0.2",
4 + "_inBundle": false,
5 + "_integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
6 + "_location": "/core-util-is",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "core-util-is@~1.0.0",
12 + "name": "core-util-is",
13 + "escapedName": "core-util-is",
14 + "rawSpec": "~1.0.0",
15 + "saveSpec": null,
16 + "fetchSpec": "~1.0.0"
17 + },
18 + "_requiredBy": [
19 + "/concat-stream/readable-stream",
20 + "/readable-stream"
21 + ],
22 + "_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
23 + "_shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7",
24 + "_spec": "core-util-is@~1.0.0",
25 + "_where": "C:\\Users\\1000c\\이것저것\\옾소\\Voicoding\\node_modules\\readable-stream",
26 + "author": {
27 + "name": "Isaac Z. Schlueter",
28 + "email": "i@izs.me",
29 + "url": "http://blog.izs.me/"
30 + },
31 + "bugs": {
32 + "url": "https://github.com/isaacs/core-util-is/issues"
33 + },
34 + "bundleDependencies": false,
35 + "deprecated": false,
36 + "description": "The `util.is*` functions introduced in Node v0.12.",
37 + "devDependencies": {
38 + "tap": "^2.3.0"
39 + },
40 + "homepage": "https://github.com/isaacs/core-util-is#readme",
41 + "keywords": [
42 + "util",
43 + "isBuffer",
44 + "isArray",
45 + "isNumber",
46 + "isString",
47 + "isRegExp",
48 + "isThis",
49 + "isThat",
50 + "polyfill"
51 + ],
52 + "license": "MIT",
53 + "main": "lib/util.js",
54 + "name": "core-util-is",
55 + "repository": {
56 + "type": "git",
57 + "url": "git://github.com/isaacs/core-util-is.git"
58 + },
59 + "scripts": {
60 + "test": "tap test.js"
61 + },
62 + "version": "1.0.2"
63 +}
1 +var assert = require('tap');
2 +
3 +var t = require('./lib/util');
4 +
5 +assert.equal(t.isArray([]), true);
6 +assert.equal(t.isArray({}), false);
7 +
8 +assert.equal(t.isBoolean(null), false);
9 +assert.equal(t.isBoolean(true), true);
10 +assert.equal(t.isBoolean(false), true);
11 +
12 +assert.equal(t.isNull(null), true);
13 +assert.equal(t.isNull(undefined), false);
14 +assert.equal(t.isNull(false), false);
15 +assert.equal(t.isNull(), false);
16 +
17 +assert.equal(t.isNullOrUndefined(null), true);
18 +assert.equal(t.isNullOrUndefined(undefined), true);
19 +assert.equal(t.isNullOrUndefined(false), false);
20 +assert.equal(t.isNullOrUndefined(), true);
21 +
22 +assert.equal(t.isNumber(null), false);
23 +assert.equal(t.isNumber('1'), false);
24 +assert.equal(t.isNumber(1), true);
25 +
26 +assert.equal(t.isString(null), false);
27 +assert.equal(t.isString('1'), true);
28 +assert.equal(t.isString(1), false);
29 +
30 +assert.equal(t.isSymbol(null), false);
31 +assert.equal(t.isSymbol('1'), false);
32 +assert.equal(t.isSymbol(1), false);
33 +assert.equal(t.isSymbol(Symbol()), true);
34 +
35 +assert.equal(t.isUndefined(null), false);
36 +assert.equal(t.isUndefined(undefined), true);
37 +assert.equal(t.isUndefined(false), false);
38 +assert.equal(t.isUndefined(), true);
39 +
40 +assert.equal(t.isRegExp(null), false);
41 +assert.equal(t.isRegExp('1'), false);
42 +assert.equal(t.isRegExp(new RegExp()), true);
43 +
44 +assert.equal(t.isObject({}), true);
45 +assert.equal(t.isObject([]), true);
46 +assert.equal(t.isObject(new RegExp()), true);
47 +assert.equal(t.isObject(new Date()), true);
48 +
49 +assert.equal(t.isDate(null), false);
50 +assert.equal(t.isDate('1'), false);
51 +assert.equal(t.isDate(new Date()), true);
52 +
53 +assert.equal(t.isError(null), false);
54 +assert.equal(t.isError({ err: true }), false);
55 +assert.equal(t.isError(new Error()), true);
56 +
57 +assert.equal(t.isFunction(null), false);
58 +assert.equal(t.isFunction({ }), false);
59 +assert.equal(t.isFunction(function() {}), true);
60 +
61 +assert.equal(t.isPrimitive(null), true);
62 +assert.equal(t.isPrimitive(''), true);
63 +assert.equal(t.isPrimitive(0), true);
64 +assert.equal(t.isPrimitive(new Date()), false);
65 +
66 +assert.equal(t.isBuffer(null), false);
67 +assert.equal(t.isBuffer({}), false);
68 +assert.equal(t.isBuffer(new Buffer(0)), true);
1 +sudo: false
2 +language: cpp
3 +notifications:
4 + email: false
5 +env:
6 + matrix:
7 + - TRAVIS_NODE_VERSION="0.10"
8 + - TRAVIS_NODE_VERSION="0.12"
9 + - TRAVIS_NODE_VERSION="4"
10 + - TRAVIS_NODE_VERSION="5"
11 +install:
12 + - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION
13 + - node --version
14 + - npm --version
15 + - npm install
16 +script: npm test
1 +Copyright Brian White. All rights reserved.
2 +
3 +Permission is hereby granted, free of charge, to any person obtaining a copy
4 +of this software and associated documentation files (the "Software"), to
5 +deal in the Software without restriction, including without limitation the
6 +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 +sell copies of the Software, and to permit persons to whom the Software is
8 +furnished to do so, subject to the following conditions:
9 +
10 +The above copyright notice and this permission notice shall be included in
11 +all copies or substantial portions of the Software.
12 +
13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 +IN THE SOFTWARE.
...\ No newline at end of file ...\ No newline at end of file
1 +
2 +Description
3 +===========
4 +
5 +A very fast streaming multipart parser for node.js.
6 +
7 +Benchmarks can be found [here](https://github.com/mscdex/dicer/wiki/Benchmarks).
8 +
9 +
10 +Requirements
11 +============
12 +
13 +* [node.js](http://nodejs.org/) -- v0.8.0 or newer
14 +
15 +
16 +Install
17 +============
18 +
19 + npm install dicer
20 +
21 +
22 +Examples
23 +========
24 +
25 +* Parse an HTTP form upload
26 +
27 +```javascript
28 +var inspect = require('util').inspect,
29 + http = require('http');
30 +
31 +var Dicer = require('dicer');
32 +
33 + // quick and dirty way to parse multipart boundary
34 +var RE_BOUNDARY = /^multipart\/.+?(?:; boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i,
35 + HTML = new Buffer('<html><head></head><body>\
36 + <form method="POST" enctype="multipart/form-data">\
37 + <input type="text" name="textfield"><br />\
38 + <input type="file" name="filefield"><br />\
39 + <input type="submit">\
40 + </form>\
41 + </body></html>'),
42 + PORT = 8080;
43 +
44 +http.createServer(function(req, res) {
45 + var m;
46 + if (req.method === 'POST'
47 + && req.headers['content-type']
48 + && (m = RE_BOUNDARY.exec(req.headers['content-type']))) {
49 + var d = new Dicer({ boundary: m[1] || m[2] });
50 +
51 + d.on('part', function(p) {
52 + console.log('New part!');
53 + p.on('header', function(header) {
54 + for (var h in header) {
55 + console.log('Part header: k: ' + inspect(h)
56 + + ', v: ' + inspect(header[h]));
57 + }
58 + });
59 + p.on('data', function(data) {
60 + console.log('Part data: ' + inspect(data.toString()));
61 + });
62 + p.on('end', function() {
63 + console.log('End of part\n');
64 + });
65 + });
66 + d.on('finish', function() {
67 + console.log('End of parts');
68 + res.writeHead(200);
69 + res.end('Form submission successful!');
70 + });
71 + req.pipe(d);
72 + } else if (req.method === 'GET' && req.url === '/') {
73 + res.writeHead(200);
74 + res.end(HTML);
75 + } else {
76 + res.writeHead(404);
77 + res.end();
78 + }
79 +}).listen(PORT, function() {
80 + console.log('Listening for requests on port ' + PORT);
81 +});
82 +```
83 +
84 +
85 +API
86 +===
87 +
88 +_Dicer_ is a _WritableStream_
89 +
90 +Dicer (special) events
91 +----------------------
92 +
93 +* **finish**() - Emitted when all parts have been parsed and the Dicer instance has been ended.
94 +
95 +* **part**(< _PartStream_ >stream) - Emitted when a new part has been found.
96 +
97 +* **preamble**(< _PartStream_ >stream) - Emitted for preamble if you should happen to need it (can usually be ignored).
98 +
99 +* **trailer**(< _Buffer_ >data) - Emitted when trailing data was found after the terminating boundary (as with the preamble, this can usually be ignored too).
100 +
101 +
102 +Dicer methods
103 +-------------
104 +
105 +* **(constructor)**(< _object_ >config) - Creates and returns a new Dicer instance with the following valid `config` settings:
106 +
107 + * **boundary** - _string_ - This is the boundary used to detect the beginning of a new part.
108 +
109 + * **headerFirst** - _boolean_ - If true, preamble header parsing will be performed first.
110 +
111 + * **maxHeaderPairs** - _integer_ - The maximum number of header key=>value pairs to parse **Default:** 2000 (same as node's http).
112 +
113 +* **setBoundary**(< _string_ >boundary) - _(void)_ - Sets the boundary to use for parsing and performs some initialization needed for parsing. You should only need to use this if you set `headerFirst` to true in the constructor and are parsing the boundary from the preamble header.
114 +
115 +
116 +
117 +_PartStream_ is a _ReadableStream_
118 +
119 +PartStream (special) events
120 +---------------------------
121 +
122 +* **header**(< _object_ >header) - An object containing the header for this particular part. Each property value is an _array_ of one or more string values.
1 +var assert = require('assert');
2 +var Dicer = require('..'),
3 + boundary = '-----------------------------168072824752491622650073',
4 + d = new Dicer({ boundary: boundary }),
5 + mb = 100,
6 + buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
7 + callbacks =
8 + { partBegin: -1,
9 + partEnd: -1,
10 + headerField: -1,
11 + headerValue: -1,
12 + partData: -1,
13 + end: -1,
14 + };
15 +
16 +
17 +d.on('part', function(p) {
18 + callbacks.partBegin++;
19 + p.on('header', function(header) {
20 + /*for (var h in header)
21 + console.log('Part header: k: ' + inspect(h) + ', v: ' + inspect(header[h]));*/
22 + });
23 + p.on('data', function(data) {
24 + callbacks.partData++;
25 + //console.log('Part data: ' + inspect(data.toString()));
26 + });
27 + p.on('end', function() {
28 + //console.log('End of part\n');
29 + callbacks.partEnd++;
30 + });
31 +});
32 +d.on('end', function() {
33 + //console.log('End of parts');
34 + callbacks.end++;
35 +});
36 +
37 +var start = +new Date(),
38 + nparsed = d.write(buffer),
39 + duration = +new Date - start,
40 + mbPerSec = (mb / (duration / 1000)).toFixed(2);
41 +
42 +console.log(mbPerSec+' mb/sec');
43 +
44 +//assert.equal(nparsed, buffer.length);
45 +
46 +function createMultipartBuffer(boundary, size) {
47 + var head =
48 + '--'+boundary+'\r\n'
49 + + 'content-disposition: form-data; name="field1"\r\n'
50 + + '\r\n'
51 + , tail = '\r\n--'+boundary+'--\r\n'
52 + , buffer = new Buffer(size);
53 +
54 + buffer.write(head, 'ascii', 0);
55 + buffer.write(tail, 'ascii', buffer.length - tail.length);
56 + return buffer;
57 +}
58 +
59 +process.on('exit', function() {
60 + /*for (var k in callbacks) {
61 + assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
62 + }*/
63 +});
1 +var assert = require('assert');
2 +require('../node_modules/formidable/test/common');
3 +var multipartParser = require('../node_modules/formidable/lib/multipart_parser'),
4 + MultipartParser = multipartParser.MultipartParser,
5 + parser = new MultipartParser(),
6 + boundary = '-----------------------------168072824752491622650073',
7 + mb = 100,
8 + buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
9 + callbacks =
10 + { partBegin: -1,
11 + partEnd: -1,
12 + headerField: -1,
13 + headerValue: -1,
14 + partData: -1,
15 + end: -1,
16 + };
17 +
18 +
19 +parser.initWithBoundary(boundary);
20 +parser.onHeaderField = function() {
21 + callbacks.headerField++;
22 +};
23 +
24 +parser.onHeaderValue = function() {
25 + callbacks.headerValue++;
26 +};
27 +
28 +parser.onPartBegin = function() {
29 + callbacks.partBegin++;
30 +};
31 +
32 +parser.onPartData = function() {
33 + callbacks.partData++;
34 +};
35 +
36 +parser.onPartEnd = function() {
37 + callbacks.partEnd++;
38 +};
39 +
40 +parser.onEnd = function() {
41 + callbacks.end++;
42 +};
43 +
44 +var start = +new Date(),
45 + nparsed = parser.write(buffer),
46 + duration = +new Date - start,
47 + mbPerSec = (mb / (duration / 1000)).toFixed(2);
48 +
49 +console.log(mbPerSec+' mb/sec');
50 +
51 +//assert.equal(nparsed, buffer.length);
52 +
53 +function createMultipartBuffer(boundary, size) {
54 + var head =
55 + '--'+boundary+'\r\n'
56 + + 'content-disposition: form-data; name="field1"\r\n'
57 + + '\r\n'
58 + , tail = '\r\n--'+boundary+'--\r\n'
59 + , buffer = new Buffer(size);
60 +
61 + buffer.write(head, 'ascii', 0);
62 + buffer.write(tail, 'ascii', buffer.length - tail.length);
63 + return buffer;
64 +}
65 +
66 +process.on('exit', function() {
67 + /*for (var k in callbacks) {
68 + assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
69 + }*/
70 +});
1 +var assert = require('assert');
2 +var multipartser = require('multipartser'),
3 + boundary = '-----------------------------168072824752491622650073',
4 + parser = multipartser(),
5 + mb = 100,
6 + buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
7 + callbacks =
8 + { partBegin: -1,
9 + partEnd: -1,
10 + headerField: -1,
11 + headerValue: -1,
12 + partData: -1,
13 + end: -1,
14 + };
15 +
16 +parser.boundary( boundary );
17 +
18 +parser.on( 'part', function ( part ) {
19 +});
20 +
21 +parser.on( 'end', function () {
22 + //console.log( 'completed parsing' );
23 +});
24 +
25 +parser.on( 'error', function ( error ) {
26 + console.error( error );
27 +});
28 +
29 +var start = +new Date(),
30 + nparsed = parser.data(buffer),
31 + nend = parser.end(),
32 + duration = +new Date - start,
33 + mbPerSec = (mb / (duration / 1000)).toFixed(2);
34 +
35 +console.log(mbPerSec+' mb/sec');
36 +
37 +//assert.equal(nparsed, buffer.length);
38 +
39 +function createMultipartBuffer(boundary, size) {
40 + var head =
41 + '--'+boundary+'\r\n'
42 + + 'content-disposition: form-data; name="field1"\r\n'
43 + + '\r\n'
44 + , tail = '\r\n--'+boundary+'--\r\n'
45 + , buffer = new Buffer(size);
46 +
47 + buffer.write(head, 'ascii', 0);
48 + buffer.write(tail, 'ascii', buffer.length - tail.length);
49 + return buffer;
50 +}
51 +
52 +process.on('exit', function() {
53 + /*for (var k in callbacks) {
54 + assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
55 + }*/
56 +});
1 +var assert = require('assert'),
2 + Form = require('multiparty').Form,
3 + boundary = '-----------------------------168072824752491622650073',
4 + mb = 100,
5 + buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
6 + callbacks =
7 + { partBegin: -1,
8 + partEnd: -1,
9 + headerField: -1,
10 + headerValue: -1,
11 + partData: -1,
12 + end: -1,
13 + };
14 +
15 +var form = new Form({ boundary: boundary });
16 +
17 +hijack('onParseHeaderField', function() {
18 + callbacks.headerField++;
19 +});
20 +
21 +hijack('onParseHeaderValue', function() {
22 + callbacks.headerValue++;
23 +});
24 +
25 +hijack('onParsePartBegin', function() {
26 + callbacks.partBegin++;
27 +});
28 +
29 +hijack('onParsePartData', function() {
30 + callbacks.partData++;
31 +});
32 +
33 +hijack('onParsePartEnd', function() {
34 + callbacks.partEnd++;
35 +});
36 +
37 +form.on('finish', function() {
38 + callbacks.end++;
39 +});
40 +
41 +var start = new Date();
42 +form.write(buffer, function(err) {
43 + var duration = new Date() - start;
44 + assert.ifError(err);
45 + var mbPerSec = (mb / (duration / 1000)).toFixed(2);
46 + console.log(mbPerSec+' mb/sec');
47 +});
48 +
49 +//assert.equal(nparsed, buffer.length);
50 +
51 +function createMultipartBuffer(boundary, size) {
52 + var head =
53 + '--'+boundary+'\r\n'
54 + + 'content-disposition: form-data; name="field1"\r\n'
55 + + '\r\n'
56 + , tail = '\r\n--'+boundary+'--\r\n'
57 + , buffer = new Buffer(size);
58 +
59 + buffer.write(head, 'ascii', 0);
60 + buffer.write(tail, 'ascii', buffer.length - tail.length);
61 + return buffer;
62 +}
63 +
64 +process.on('exit', function() {
65 + /*for (var k in callbacks) {
66 + assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
67 + }*/
68 +});
69 +
70 +function hijack(name, fn) {
71 + var oldFn = form[name];
72 + form[name] = function() {
73 + fn();
74 + return oldFn.apply(this, arguments);
75 + };
76 +}
1 +// A special, edited version of the multipart parser from parted is needed here
2 +// because otherwise it attempts to do some things above and beyond just parsing
3 +// -- like saving to disk and whatnot
4 +
5 +var assert = require('assert');
6 +var Parser = require('./parted-multipart'),
7 + boundary = '-----------------------------168072824752491622650073',
8 + parser = new Parser('boundary=' + boundary),
9 + mb = 100,
10 + buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
11 + callbacks =
12 + { partBegin: -1,
13 + partEnd: -1,
14 + headerField: -1,
15 + headerValue: -1,
16 + partData: -1,
17 + end: -1,
18 + };
19 +
20 +
21 +parser.on('header', function() {
22 + //callbacks.headerField++;
23 +});
24 +
25 +parser.on('data', function() {
26 + //callbacks.partBegin++;
27 +});
28 +
29 +parser.on('part', function() {
30 +
31 +});
32 +
33 +parser.on('end', function() {
34 + //callbacks.end++;
35 +});
36 +
37 +var start = +new Date(),
38 + nparsed = parser.write(buffer),
39 + duration = +new Date - start,
40 + mbPerSec = (mb / (duration / 1000)).toFixed(2);
41 +
42 +console.log(mbPerSec+' mb/sec');
43 +
44 +//assert.equal(nparsed, buffer.length);
45 +
46 +function createMultipartBuffer(boundary, size) {
47 + var head =
48 + '--'+boundary+'\r\n'
49 + + 'content-disposition: form-data; name="field1"\r\n'
50 + + '\r\n'
51 + , tail = '\r\n--'+boundary+'--\r\n'
52 + , buffer = new Buffer(size);
53 +
54 + buffer.write(head, 'ascii', 0);
55 + buffer.write(tail, 'ascii', buffer.length - tail.length);
56 + return buffer;
57 +}
58 +
59 +process.on('exit', function() {
60 + /*for (var k in callbacks) {
61 + assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
62 + }*/
63 +});
1 +/**
2 + * Parted (https://github.com/chjj/parted)
3 + * A streaming multipart state parser.
4 + * Copyright (c) 2011, Christopher Jeffrey. (MIT Licensed)
5 + */
6 +
7 +var fs = require('fs')
8 + , path = require('path')
9 + , EventEmitter = require('events').EventEmitter
10 + , StringDecoder = require('string_decoder').StringDecoder
11 + , set = require('qs').set
12 + , each = Array.prototype.forEach;
13 +
14 +/**
15 + * Character Constants
16 + */
17 +
18 +var DASH = '-'.charCodeAt(0)
19 + , CR = '\r'.charCodeAt(0)
20 + , LF = '\n'.charCodeAt(0)
21 + , COLON = ':'.charCodeAt(0)
22 + , SPACE = ' '.charCodeAt(0);
23 +
24 +/**
25 + * Parser
26 + */
27 +
28 +var Parser = function(type, options) {
29 + if (!(this instanceof Parser)) {
30 + return new Parser(type, options);
31 + }
32 +
33 + EventEmitter.call(this);
34 +
35 + this.writable = true;
36 + this.readable = true;
37 +
38 + this.options = options || {};
39 +
40 + var key = grab(type, 'boundary');
41 + if (!key) {
42 + return this._error('No boundary key found.');
43 + }
44 +
45 + this.key = new Buffer('\r\n--' + key);
46 +
47 + this._key = {};
48 + each.call(this.key, function(ch) {
49 + this._key[ch] = true;
50 + }, this);
51 +
52 + this.state = 'start';
53 + this.pending = 0;
54 + this.written = 0;
55 + this.writtenDisk = 0;
56 + this.buff = new Buffer(200);
57 +
58 + this.preamble = true;
59 + this.epilogue = false;
60 +
61 + this._reset();
62 +};
63 +
64 +Parser.prototype.__proto__ = EventEmitter.prototype;
65 +
66 +/**
67 + * Parsing
68 + */
69 +
70 +Parser.prototype.write = function(data) {
71 + if (!this.writable
72 + || this.epilogue) return;
73 +
74 + try {
75 + this._parse(data);
76 + } catch (e) {
77 + this._error(e);
78 + }
79 +
80 + return true;
81 +};
82 +
83 +Parser.prototype.end = function(data) {
84 + if (!this.writable) return;
85 +
86 + if (data) this.write(data);
87 +
88 + if (!this.epilogue) {
89 + return this._error('Message underflow.');
90 + }
91 +
92 + return true;
93 +};
94 +
95 +Parser.prototype._parse = function(data) {
96 + var i = 0
97 + , len = data.length
98 + , buff = this.buff
99 + , key = this.key
100 + , ch
101 + , val
102 + , j;
103 +
104 + for (; i < len; i++) {
105 + if (this.pos >= 200) {
106 + return this._error('Potential buffer overflow.');
107 + }
108 +
109 + ch = data[i];
110 +
111 + switch (this.state) {
112 + case 'start':
113 + switch (ch) {
114 + case DASH:
115 + this.pos = 3;
116 + this.state = 'key';
117 + break;
118 + default:
119 + break;
120 + }
121 + break;
122 + case 'key':
123 + if (this.pos === key.length) {
124 + this.state = 'key_end';
125 + i--;
126 + } else if (ch !== key[this.pos]) {
127 + if (this.preamble) {
128 + this.state = 'start';
129 + i--;
130 + } else {
131 + this.state = 'body';
132 + val = this.pos - i;
133 + if (val > 0) {
134 + this._write(key.slice(0, val));
135 + }
136 + i--;
137 + }
138 + } else {
139 + this.pos++;
140 + }
141 + break;
142 + case 'key_end':
143 + switch (ch) {
144 + case CR:
145 + this.state = 'key_line_end';
146 + break;
147 + case DASH:
148 + this.state = 'key_dash_end';
149 + break;
150 + default:
151 + return this._error('Expected CR or DASH.');
152 + }
153 + break;
154 + case 'key_line_end':
155 + switch (ch) {
156 + case LF:
157 + if (this.preamble) {
158 + this.preamble = false;
159 + } else {
160 + this._finish();
161 + }
162 + this.state = 'header_name';
163 + this.pos = 0;
164 + break;
165 + default:
166 + return this._error('Expected CR.');
167 + }
168 + break;
169 + case 'key_dash_end':
170 + switch (ch) {
171 + case DASH:
172 + this.epilogue = true;
173 + this._finish();
174 + return;
175 + default:
176 + return this._error('Expected DASH.');
177 + }
178 + break;
179 + case 'header_name':
180 + switch (ch) {
181 + case COLON:
182 + this.header = buff.toString('ascii', 0, this.pos);
183 + this.pos = 0;
184 + this.state = 'header_val';
185 + break;
186 + default:
187 + buff[this.pos++] = ch | 32;
188 + break;
189 + }
190 + break;
191 + case 'header_val':
192 + switch (ch) {
193 + case CR:
194 + this.state = 'header_val_end';
195 + break;
196 + case SPACE:
197 + if (this.pos === 0) {
198 + break;
199 + }
200 + ; // FALL-THROUGH
201 + default:
202 + buff[this.pos++] = ch;
203 + break;
204 + }
205 + break;
206 + case 'header_val_end':
207 + switch (ch) {
208 + case LF:
209 + val = buff.toString('ascii', 0, this.pos);
210 + this._header(this.header, val);
211 + this.pos = 0;
212 + this.state = 'header_end';
213 + break;
214 + default:
215 + return this._error('Expected LF.');
216 + }
217 + break;
218 + case 'header_end':
219 + switch (ch) {
220 + case CR:
221 + this.state = 'head_end';
222 + break;
223 + default:
224 + this.state = 'header_name';
225 + i--;
226 + break;
227 + }
228 + break;
229 + case 'head_end':
230 + switch (ch) {
231 + case LF:
232 + this.state = 'body';
233 + i++;
234 + if (i >= len) return;
235 + data = data.slice(i);
236 + i = -1;
237 + len = data.length;
238 + break;
239 + default:
240 + return this._error('Expected LF.');
241 + }
242 + break;
243 + case 'body':
244 + switch (ch) {
245 + case CR:
246 + if (i > 0) {
247 + this._write(data.slice(0, i));
248 + }
249 + this.pos = 1;
250 + this.state = 'key';
251 + data = data.slice(i);
252 + i = 0;
253 + len = data.length;
254 + break;
255 + default:
256 + // boyer-moore-like algorithm
257 + // at felixge's suggestion
258 + while ((j = i + key.length - 1) < len) {
259 + if (this._key[data[j]]) break;
260 + i = j;
261 + }
262 + break;
263 + }
264 + break;
265 + }
266 + }
267 +
268 + if (this.state === 'body') {
269 + this._write(data);
270 + }
271 +};
272 +
273 +Parser.prototype._header = function(name, val) {
274 + /*if (name === 'content-disposition') {
275 + this.field = grab(val, 'name');
276 + this.file = grab(val, 'filename');
277 +
278 + if (this.file) {
279 + this.data = stream(this.file, this.options.path);
280 + } else {
281 + this.decode = new StringDecoder('utf8');
282 + this.data = '';
283 + }
284 + }*/
285 +
286 + return this.emit('header', name, val);
287 +};
288 +
289 +Parser.prototype._write = function(data) {
290 + /*if (this.data == null) {
291 + return this._error('No disposition.');
292 + }
293 +
294 + if (this.file) {
295 + this.data.write(data);
296 + this.writtenDisk += data.length;
297 + } else {
298 + this.data += this.decode.write(data);
299 + this.written += data.length;
300 + }*/
301 +
302 + this.emit('data', data);
303 +};
304 +
305 +Parser.prototype._reset = function() {
306 + this.pos = 0;
307 + this.decode = null;
308 + this.field = null;
309 + this.data = null;
310 + this.file = null;
311 + this.header = null;
312 +};
313 +
314 +Parser.prototype._error = function(err) {
315 + this.destroy();
316 + this.emit('error', typeof err === 'string'
317 + ? new Error(err)
318 + : err);
319 +};
320 +
321 +Parser.prototype.destroy = function(err) {
322 + this.writable = false;
323 + this.readable = false;
324 + this._reset();
325 +};
326 +
327 +Parser.prototype._finish = function() {
328 + var self = this
329 + , field = this.field
330 + , data = this.data
331 + , file = this.file
332 + , part;
333 +
334 + this.pending++;
335 +
336 + this._reset();
337 +
338 + if (data && data.path) {
339 + part = data.path;
340 + data.end(next);
341 + } else {
342 + part = data;
343 + next();
344 + }
345 +
346 + function next() {
347 + if (!self.readable) return;
348 +
349 + self.pending--;
350 +
351 + self.emit('part', field, part);
352 +
353 + if (data && data.path) {
354 + self.emit('file', field, part, file);
355 + }
356 +
357 + if (self.epilogue && !self.pending) {
358 + self.emit('end');
359 + self.destroy();
360 + }
361 + }
362 +};
363 +
364 +/**
365 + * Uploads
366 + */
367 +
368 +Parser.root = process.platform === 'win32'
369 + ? 'C:/Temp'
370 + : '/tmp';
371 +
372 +/**
373 + * Middleware
374 + */
375 +
376 +Parser.middleware = function(options) {
377 + options = options || {};
378 + return function(req, res, next) {
379 + if (options.ensureBody) {
380 + req.body = {};
381 + }
382 +
383 + if (req.method === 'GET'
384 + || req.method === 'HEAD'
385 + || req._multipart) return next();
386 +
387 + req._multipart = true;
388 +
389 + var type = req.headers['content-type'];
390 +
391 + if (type) type = type.split(';')[0].trim().toLowerCase();
392 +
393 + if (type === 'multipart/form-data') {
394 + Parser.handle(req, res, next, options);
395 + } else {
396 + next();
397 + }
398 + };
399 +};
400 +
401 +/**
402 + * Handler
403 + */
404 +
405 +Parser.handle = function(req, res, next, options) {
406 + var parser = new Parser(req.headers['content-type'], options)
407 + , diskLimit = options.diskLimit
408 + , limit = options.limit
409 + , parts = {}
410 + , files = {};
411 +
412 + parser.on('error', function(err) {
413 + req.destroy();
414 + next(err);
415 + });
416 +
417 + parser.on('part', function(field, part) {
418 + set(parts, field, part);
419 + });
420 +
421 + parser.on('file', function(field, path, name) {
422 + set(files, field, {
423 + path: path,
424 + name: name,
425 + toString: function() {
426 + return path;
427 + }
428 + });
429 + });
430 +
431 + parser.on('data', function() {
432 + if (this.writtenDisk > diskLimit || this.written > limit) {
433 + this.emit('error', new Error('Overflow.'));
434 + this.destroy();
435 + }
436 + });
437 +
438 + parser.on('end', next);
439 +
440 + req.body = parts;
441 + req.files = files;
442 + req.pipe(parser);
443 +};
444 +
445 +/**
446 + * Helpers
447 + */
448 +
449 +var isWindows = process.platform === 'win32';
450 +
451 +var stream = function(name, dir) {
452 + var ext = path.extname(name) || ''
453 + , name = path.basename(name, ext) || ''
454 + , dir = dir || Parser.root
455 + , tag;
456 +
457 + tag = Math.random().toString(36).substring(2);
458 +
459 + name = name.substring(0, 200) + '.' + tag;
460 + name = path.join(dir, name) + ext.substring(0, 6);
461 + name = name.replace(/\0/g, '');
462 +
463 + if (isWindows) {
464 + name = name.replace(/[:*<>|"?]/g, '');
465 + }
466 +
467 + return fs.createWriteStream(name);
468 +};
469 +
470 +var grab = function(str, name) {
471 + if (!str) return;
472 +
473 + var rx = new RegExp('\\b' + name + '\\s*=\\s*("[^"]+"|\'[^\']+\'|[^;,]+)', 'i')
474 + , cap = rx.exec(str);
475 +
476 + if (cap) {
477 + return cap[1].trim().replace(/^['"]|['"]$/g, '');
478 + }
479 +};
480 +
481 +/**
482 + * Expose
483 + */
484 +
485 +module.exports = Parser;
...\ No newline at end of file ...\ No newline at end of file
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.