all da files
This commit is contained in:
55
node_modules/tabletop/node_modules/request/LICENSE
generated
vendored
Normal file
55
node_modules/tabletop/node_modules/request/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
Apache License
|
||||
|
||||
Version 2.0, January 2004
|
||||
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
||||
|
||||
You must cause any modified files to carry prominent notices stating that You changed the files; and
|
||||
|
||||
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
||||
|
||||
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
342
node_modules/tabletop/node_modules/request/README.md
generated
vendored
Normal file
342
node_modules/tabletop/node_modules/request/README.md
generated
vendored
Normal file
@@ -0,0 +1,342 @@
|
||||
# Request -- Simplified HTTP request method
|
||||
|
||||
## Install
|
||||
|
||||
<pre>
|
||||
npm install request
|
||||
</pre>
|
||||
|
||||
Or from source:
|
||||
|
||||
<pre>
|
||||
git clone git://github.com/mikeal/request.git
|
||||
cd request
|
||||
npm link
|
||||
</pre>
|
||||
|
||||
## Super simple to use
|
||||
|
||||
Request is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.
|
||||
|
||||
```javascript
|
||||
var request = require('request');
|
||||
request('http://www.google.com', function (error, response, body) {
|
||||
if (!error && response.statusCode == 200) {
|
||||
console.log(body) // Print the google web page.
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Streaming
|
||||
|
||||
You can stream any response to a file stream.
|
||||
|
||||
```javascript
|
||||
request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))
|
||||
```
|
||||
|
||||
You can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.
|
||||
|
||||
```javascript
|
||||
fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))
|
||||
```
|
||||
|
||||
Request can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.
|
||||
|
||||
```javascript
|
||||
request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))
|
||||
```
|
||||
|
||||
Now let's get fancy.
|
||||
|
||||
```javascript
|
||||
http.createServer(function (req, resp) {
|
||||
if (req.url === '/doodle.png') {
|
||||
if (req.method === 'PUT') {
|
||||
req.pipe(request.put('http://mysite.com/doodle.png'))
|
||||
} else if (req.method === 'GET' || req.method === 'HEAD') {
|
||||
request.get('http://mysite.com/doodle.png').pipe(resp)
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:
|
||||
|
||||
```javascript
|
||||
http.createServer(function (req, resp) {
|
||||
if (req.url === '/doodle.png') {
|
||||
var x = request('http://mysite.com/doodle.png')
|
||||
req.pipe(x)
|
||||
x.pipe(resp)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
And since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)
|
||||
|
||||
```javascript
|
||||
req.pipe(request('http://mysite.com/doodle.png')).pipe(resp)
|
||||
```
|
||||
|
||||
Also, none of this new functionality conflicts with requests previous features, it just expands them.
|
||||
|
||||
```javascript
|
||||
var r = request.defaults({'proxy':'http://localproxy.com'})
|
||||
|
||||
http.createServer(function (req, resp) {
|
||||
if (req.url === '/doodle.png') {
|
||||
r.get('http://google.com/doodle.png').pipe(resp)
|
||||
}
|
||||
})
|
||||
```
|
||||
You can still use intermediate proxies, the requests will still follow HTTP forwards, etc.
|
||||
|
||||
## Forms
|
||||
|
||||
`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API.
|
||||
|
||||
Url encoded forms are simple
|
||||
|
||||
```javascript
|
||||
request.post('http://service.com/upload', {form:{key:'value'}})
|
||||
// or
|
||||
request.post('http://service.com/upload').form({key:'value'})
|
||||
```
|
||||
|
||||
For `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don't need to worry about piping the form object or setting the headers, `request` will handle that for you.
|
||||
|
||||
```javascript
|
||||
var r = request.post('http://service.com/upload')
|
||||
var form = r.form()
|
||||
form.append('my_field', 'my_value')
|
||||
form.append('my_buffer', new Buffer([1, 2, 3]))
|
||||
form.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png'))
|
||||
form.append('remote_file', request('http://google.com/doodle.png'))
|
||||
```
|
||||
|
||||
## HTTP Authentication
|
||||
|
||||
```javascript
|
||||
request.auth('username', 'password', false).get('http://some.server.com/');
|
||||
// or
|
||||
request.get('http://some.server.com/', {
|
||||
'auth': {
|
||||
'user': 'username',
|
||||
'pass': 'password',
|
||||
'sendImmediately': false
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
If passed as an option, `auth` should be a hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional). The method form takes parameters `auth(username, password, sendImmediately)`.
|
||||
|
||||
`sendImmediately` defaults to true, which will cause a basic authentication header to be sent. If `sendImmediately` is `false`, then `request` will retry with a proper authentication header after receiving a 401 response from the server (which must contain a `WWW-Authenticate` header indicating the required authentication method).
|
||||
|
||||
Digest authentication is supported, but it only works with `sendImmediately` set to `false` (otherwise `request` will send basic authentication on the initial request, which will probably cause the request to fail).
|
||||
|
||||
## OAuth Signing
|
||||
|
||||
```javascript
|
||||
// Twitter OAuth
|
||||
var qs = require('querystring')
|
||||
, oauth =
|
||||
{ callback: 'http://mysite.com/callback/'
|
||||
, consumer_key: CONSUMER_KEY
|
||||
, consumer_secret: CONSUMER_SECRET
|
||||
}
|
||||
, url = 'https://api.twitter.com/oauth/request_token'
|
||||
;
|
||||
request.post({url:url, oauth:oauth}, function (e, r, body) {
|
||||
// Ideally, you would take the body in the response
|
||||
// and construct a URL that a user clicks on (like a sign in button).
|
||||
// The verifier is only available in the response after a user has
|
||||
// verified with twitter that they are authorizing your app.
|
||||
var access_token = qs.parse(body)
|
||||
, oauth =
|
||||
{ consumer_key: CONSUMER_KEY
|
||||
, consumer_secret: CONSUMER_SECRET
|
||||
, token: access_token.oauth_token
|
||||
, verifier: access_token.oauth_verifier
|
||||
}
|
||||
, url = 'https://api.twitter.com/oauth/access_token'
|
||||
;
|
||||
request.post({url:url, oauth:oauth}, function (e, r, body) {
|
||||
var perm_token = qs.parse(body)
|
||||
, oauth =
|
||||
{ consumer_key: CONSUMER_KEY
|
||||
, consumer_secret: CONSUMER_SECRET
|
||||
, token: perm_token.oauth_token
|
||||
, token_secret: perm_token.oauth_token_secret
|
||||
}
|
||||
, url = 'https://api.twitter.com/1/users/show.json?'
|
||||
, params =
|
||||
{ screen_name: perm_token.screen_name
|
||||
, user_id: perm_token.user_id
|
||||
}
|
||||
;
|
||||
url += qs.stringify(params)
|
||||
request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {
|
||||
console.log(user)
|
||||
})
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
|
||||
### request(options, callback)
|
||||
|
||||
The first argument can be either a url or an options object. The only required option is uri, all others are optional.
|
||||
|
||||
* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()
|
||||
* `qs` - object containing querystring values to be appended to the uri
|
||||
* `method` - http method, defaults to GET
|
||||
* `headers` - http headers, defaults to {}
|
||||
* `body` - entity body for PATCH, POST and PUT requests. Must be buffer or string.
|
||||
* `form` - when passed an object this will set `body` but to a querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no option a FormData instance is returned that will be piped to request.
|
||||
* `auth` - A hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional). See documentation above.
|
||||
* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as json.
|
||||
* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.
|
||||
* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.
|
||||
* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.
|
||||
* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.
|
||||
* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.
|
||||
* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.
|
||||
* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.
|
||||
* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request
|
||||
* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.
|
||||
* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.
|
||||
* `hawk` - Options for [Hawk signing](https://github.com/hueniverse/hawk). The `credentials` key must contain the necessary signing info, [see hawk docs for details](https://github.com/hueniverse/hawk#usage-example).
|
||||
* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.
|
||||
* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)
|
||||
* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services)
|
||||
|
||||
|
||||
The callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.
|
||||
|
||||
## Convenience methods
|
||||
|
||||
There are also shorthand methods for different HTTP METHODs and some other conveniences.
|
||||
|
||||
### request.defaults(options)
|
||||
|
||||
This method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.
|
||||
|
||||
### request.put
|
||||
|
||||
Same as request() but defaults to `method: "PUT"`.
|
||||
|
||||
```javascript
|
||||
request.put(url)
|
||||
```
|
||||
|
||||
### request.patch
|
||||
|
||||
Same as request() but defaults to `method: "PATCH"`.
|
||||
|
||||
```javascript
|
||||
request.patch(url)
|
||||
```
|
||||
|
||||
### request.post
|
||||
|
||||
Same as request() but defaults to `method: "POST"`.
|
||||
|
||||
```javascript
|
||||
request.post(url)
|
||||
```
|
||||
|
||||
### request.head
|
||||
|
||||
Same as request() but defaults to `method: "HEAD"`.
|
||||
|
||||
```javascript
|
||||
request.head(url)
|
||||
```
|
||||
|
||||
### request.del
|
||||
|
||||
Same as request() but defaults to `method: "DELETE"`.
|
||||
|
||||
```javascript
|
||||
request.del(url)
|
||||
```
|
||||
|
||||
### request.get
|
||||
|
||||
Alias to normal request method for uniformity.
|
||||
|
||||
```javascript
|
||||
request.get(url)
|
||||
```
|
||||
### request.cookie
|
||||
|
||||
Function that creates a new cookie.
|
||||
|
||||
```javascript
|
||||
request.cookie('cookie_string_here')
|
||||
```
|
||||
### request.jar
|
||||
|
||||
Function that creates a new cookie jar.
|
||||
|
||||
```javascript
|
||||
request.jar()
|
||||
```
|
||||
|
||||
|
||||
## Examples:
|
||||
|
||||
```javascript
|
||||
var request = require('request')
|
||||
, rand = Math.floor(Math.random()*100000000).toString()
|
||||
;
|
||||
request(
|
||||
{ method: 'PUT'
|
||||
, uri: 'http://mikeal.iriscouch.com/testjs/' + rand
|
||||
, multipart:
|
||||
[ { 'content-type': 'application/json'
|
||||
, body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})
|
||||
}
|
||||
, { body: 'I am an attachment' }
|
||||
]
|
||||
}
|
||||
, function (error, response, body) {
|
||||
if(response.statusCode == 201){
|
||||
console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)
|
||||
} else {
|
||||
console.log('error: '+ response.statusCode)
|
||||
console.log(body)
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
Cookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent).
|
||||
|
||||
```javascript
|
||||
var request = request.defaults({jar: false})
|
||||
request('http://www.google.com', function () {
|
||||
request('http://images.google.com')
|
||||
})
|
||||
```
|
||||
|
||||
If you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:
|
||||
|
||||
```javascript
|
||||
var j = request.jar()
|
||||
var request = request.defaults({jar:j})
|
||||
request('http://www.google.com', function () {
|
||||
request('http://images.google.com')
|
||||
})
|
||||
```
|
||||
OR
|
||||
|
||||
```javascript
|
||||
var j = request.jar()
|
||||
var cookie = request.cookie('your_cookie_here')
|
||||
j.add(cookie)
|
||||
request({url: 'http://www.google.com', jar: j}, function () {
|
||||
request('http://images.google.com')
|
||||
})
|
||||
```
|
1328
node_modules/tabletop/node_modules/request/index.js
generated
vendored
Executable file
1328
node_modules/tabletop/node_modules/request/index.js
generated
vendored
Executable file
File diff suppressed because it is too large
Load Diff
202
node_modules/tabletop/node_modules/request/node_modules/aws-sign/index.js
generated
vendored
Normal file
202
node_modules/tabletop/node_modules/request/node_modules/aws-sign/index.js
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
/*!
|
||||
* knox - auth
|
||||
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var crypto = require('crypto')
|
||||
, parse = require('url').parse
|
||||
;
|
||||
|
||||
/**
|
||||
* Valid keys.
|
||||
*/
|
||||
|
||||
var keys =
|
||||
[ 'acl'
|
||||
, 'location'
|
||||
, 'logging'
|
||||
, 'notification'
|
||||
, 'partNumber'
|
||||
, 'policy'
|
||||
, 'requestPayment'
|
||||
, 'torrent'
|
||||
, 'uploadId'
|
||||
, 'uploads'
|
||||
, 'versionId'
|
||||
, 'versioning'
|
||||
, 'versions'
|
||||
, 'website'
|
||||
]
|
||||
|
||||
/**
|
||||
* Return an "Authorization" header value with the given `options`
|
||||
* in the form of "AWS <key>:<signature>"
|
||||
*
|
||||
* @param {Object} options
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function authorization (options) {
|
||||
return 'AWS ' + options.key + ':' + sign(options)
|
||||
}
|
||||
|
||||
module.exports = authorization
|
||||
module.exports.authorization = authorization
|
||||
|
||||
/**
|
||||
* Simple HMAC-SHA1 Wrapper
|
||||
*
|
||||
* @param {Object} options
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function hmacSha1 (options) {
|
||||
return crypto.createHmac('sha1', options.secret).update(options.message).digest('base64')
|
||||
}
|
||||
|
||||
module.exports.hmacSha1 = hmacSha1
|
||||
|
||||
/**
|
||||
* Create a base64 sha1 HMAC for `options`.
|
||||
*
|
||||
* @param {Object} options
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function sign (options) {
|
||||
options.message = stringToSign(options)
|
||||
return hmacSha1(options)
|
||||
}
|
||||
module.exports.sign = sign
|
||||
|
||||
/**
|
||||
* Create a base64 sha1 HMAC for `options`.
|
||||
*
|
||||
* Specifically to be used with S3 presigned URLs
|
||||
*
|
||||
* @param {Object} options
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function signQuery (options) {
|
||||
options.message = queryStringToSign(options)
|
||||
return hmacSha1(options)
|
||||
}
|
||||
module.exports.signQuery= signQuery
|
||||
|
||||
/**
|
||||
* Return a string for sign() with the given `options`.
|
||||
*
|
||||
* Spec:
|
||||
*
|
||||
* <verb>\n
|
||||
* <md5>\n
|
||||
* <content-type>\n
|
||||
* <date>\n
|
||||
* [headers\n]
|
||||
* <resource>
|
||||
*
|
||||
* @param {Object} options
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function stringToSign (options) {
|
||||
var headers = options.amazonHeaders || ''
|
||||
if (headers) headers += '\n'
|
||||
var r =
|
||||
[ options.verb
|
||||
, options.md5
|
||||
, options.contentType
|
||||
, options.date.toUTCString()
|
||||
, headers + options.resource
|
||||
]
|
||||
return r.join('\n')
|
||||
}
|
||||
module.exports.queryStringToSign = stringToSign
|
||||
|
||||
/**
|
||||
* Return a string for sign() with the given `options`, but is meant exclusively
|
||||
* for S3 presigned URLs
|
||||
*
|
||||
* Spec:
|
||||
*
|
||||
* <date>\n
|
||||
* <resource>
|
||||
*
|
||||
* @param {Object} options
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function queryStringToSign (options){
|
||||
return 'GET\n\n\n' + options.date + '\n' + options.resource
|
||||
}
|
||||
module.exports.queryStringToSign = queryStringToSign
|
||||
|
||||
/**
|
||||
* Perform the following:
|
||||
*
|
||||
* - ignore non-amazon headers
|
||||
* - lowercase fields
|
||||
* - sort lexicographically
|
||||
* - trim whitespace between ":"
|
||||
* - join with newline
|
||||
*
|
||||
* @param {Object} headers
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function canonicalizeHeaders (headers) {
|
||||
var buf = []
|
||||
, fields = Object.keys(headers)
|
||||
;
|
||||
for (var i = 0, len = fields.length; i < len; ++i) {
|
||||
var field = fields[i]
|
||||
, val = headers[field]
|
||||
, field = field.toLowerCase()
|
||||
;
|
||||
if (0 !== field.indexOf('x-amz')) continue
|
||||
buf.push(field + ':' + val)
|
||||
}
|
||||
return buf.sort().join('\n')
|
||||
}
|
||||
module.exports.canonicalizeHeaders = canonicalizeHeaders
|
||||
|
||||
/**
|
||||
* Perform the following:
|
||||
*
|
||||
* - ignore non sub-resources
|
||||
* - sort lexicographically
|
||||
*
|
||||
* @param {String} resource
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function canonicalizeResource (resource) {
|
||||
var url = parse(resource, true)
|
||||
, path = url.pathname
|
||||
, buf = []
|
||||
;
|
||||
|
||||
Object.keys(url.query).forEach(function(key){
|
||||
if (!~keys.indexOf(key)) return
|
||||
var val = '' == url.query[key] ? '' : '=' + encodeURIComponent(url.query[key])
|
||||
buf.push(key + val)
|
||||
})
|
||||
|
||||
return path + (buf.length ? '?' + buf.sort().join('&') : '')
|
||||
}
|
||||
module.exports.canonicalizeResource = canonicalizeResource
|
23
node_modules/tabletop/node_modules/request/node_modules/aws-sign/package.json
generated
vendored
Normal file
23
node_modules/tabletop/node_modules/request/node_modules/aws-sign/package.json
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"author": {
|
||||
"name": "Mikeal Rogers",
|
||||
"email": "mikeal.rogers@gmail.com",
|
||||
"url": "http://www.futurealoof.com"
|
||||
},
|
||||
"name": "aws-sign",
|
||||
"description": "AWS signing. Originally pulled from LearnBoost/knox, maintained as vendor in request, now a standalone module.",
|
||||
"version": "0.2.0",
|
||||
"repository": {
|
||||
"url": "https://github.com/mikeal/aws-sign"
|
||||
},
|
||||
"main": "index.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"optionalDependencies": {},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"_id": "aws-sign@0.2.0",
|
||||
"readme": "ERROR: No README.md file found!",
|
||||
"_from": "aws-sign@~0.2.0"
|
||||
}
|
67
node_modules/tabletop/node_modules/request/node_modules/cookie-jar/index.js
generated
vendored
Normal file
67
node_modules/tabletop/node_modules/request/node_modules/cookie-jar/index.js
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/*!
|
||||
* Tobi - Cookie
|
||||
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var url = require('url');
|
||||
|
||||
/**
|
||||
* Initialize a new `Cookie` with the given cookie `str` and `req`.
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {IncomingRequest} req
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var Cookie = exports = module.exports = function Cookie(str, req) {
|
||||
this.str = str;
|
||||
|
||||
// Map the key/val pairs
|
||||
str.split(/ *; */).reduce(function(obj, pair){
|
||||
var p = pair.indexOf('=');
|
||||
var key = p > 0 ? pair.substring(0, p).trim() : pair.trim();
|
||||
var lowerCasedKey = key.toLowerCase();
|
||||
var value = p > 0 ? pair.substring(p + 1).trim() : true;
|
||||
|
||||
if (!obj.name) {
|
||||
// First key is the name
|
||||
obj.name = key;
|
||||
obj.value = value;
|
||||
}
|
||||
else if (lowerCasedKey === 'httponly') {
|
||||
obj.httpOnly = value;
|
||||
}
|
||||
else {
|
||||
obj[lowerCasedKey] = value;
|
||||
}
|
||||
return obj;
|
||||
}, this);
|
||||
|
||||
// Expires
|
||||
this.expires = this.expires
|
||||
? new Date(this.expires)
|
||||
: Infinity;
|
||||
|
||||
// Default or trim path
|
||||
this.path = this.path
|
||||
? this.path.trim(): req
|
||||
? url.parse(req.url).pathname: '/';
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the original cookie string.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Cookie.prototype.toString = function(){
|
||||
return this.str;
|
||||
};
|
||||
|
||||
module.exports.Jar = require('./jar')
|
72
node_modules/tabletop/node_modules/request/node_modules/cookie-jar/jar.js
generated
vendored
Normal file
72
node_modules/tabletop/node_modules/request/node_modules/cookie-jar/jar.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/*!
|
||||
* Tobi - CookieJar
|
||||
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var url = require('url');
|
||||
|
||||
/**
|
||||
* Initialize a new `CookieJar`.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var CookieJar = exports = module.exports = function CookieJar() {
|
||||
this.cookies = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the given `cookie` to the jar.
|
||||
*
|
||||
* @param {Cookie} cookie
|
||||
* @api private
|
||||
*/
|
||||
|
||||
CookieJar.prototype.add = function(cookie){
|
||||
this.cookies = this.cookies.filter(function(c){
|
||||
// Avoid duplication (same path, same name)
|
||||
return !(c.name == cookie.name && c.path == cookie.path);
|
||||
});
|
||||
this.cookies.push(cookie);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get cookies for the given `req`.
|
||||
*
|
||||
* @param {IncomingRequest} req
|
||||
* @return {Array}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
CookieJar.prototype.get = function(req){
|
||||
var path = url.parse(req.url).pathname
|
||||
, now = new Date
|
||||
, specificity = {};
|
||||
return this.cookies.filter(function(cookie){
|
||||
if (0 == path.indexOf(cookie.path) && now < cookie.expires
|
||||
&& cookie.path.length > (specificity[cookie.name] || 0))
|
||||
return specificity[cookie.name] = cookie.path.length;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Return Cookie string for the given `req`.
|
||||
*
|
||||
* @param {IncomingRequest} req
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
CookieJar.prototype.cookieString = function(req){
|
||||
var cookies = this.get(req);
|
||||
if (cookies.length) {
|
||||
return cookies.map(function(cookie){
|
||||
return cookie.name + '=' + cookie.value;
|
||||
}).join('; ');
|
||||
}
|
||||
};
|
26
node_modules/tabletop/node_modules/request/node_modules/cookie-jar/package.json
generated
vendored
Normal file
26
node_modules/tabletop/node_modules/request/node_modules/cookie-jar/package.json
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"author": {
|
||||
"name": "Mikeal Rogers",
|
||||
"email": "mikeal.rogers@gmail.com",
|
||||
"url": "http://www.futurealoof.com"
|
||||
},
|
||||
"name": "cookie-jar",
|
||||
"description": "Cookie Jar. Originally pulled form tobi, maintained as vendor in request, now a standalone module.",
|
||||
"version": "0.2.0",
|
||||
"repository": {
|
||||
"url": "https://github.com/mikeal/cookie-jar"
|
||||
},
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "node tests/run.js"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"optionalDependencies": {},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"_id": "cookie-jar@0.2.0",
|
||||
"readme": "ERROR: No README.md file found!",
|
||||
"_from": "cookie-jar@~0.2.0"
|
||||
}
|
40
node_modules/tabletop/node_modules/request/node_modules/cookie-jar/tests/run.js
generated
vendored
Normal file
40
node_modules/tabletop/node_modules/request/node_modules/cookie-jar/tests/run.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
var spawn = require('child_process').spawn
|
||||
, exitCode = 0
|
||||
, timeout = 10000
|
||||
, fs = require('fs')
|
||||
;
|
||||
|
||||
fs.readdir(__dirname, function (e, files) {
|
||||
if (e) throw e
|
||||
|
||||
var tests = files.filter(function (f) {return f.slice(0, 'test-'.length) === 'test-'})
|
||||
|
||||
var next = function () {
|
||||
if (tests.length === 0) process.exit(exitCode);
|
||||
|
||||
var file = tests.shift()
|
||||
console.log(file)
|
||||
var proc = spawn('node', [ 'tests/' + file ])
|
||||
|
||||
var killed = false
|
||||
var t = setTimeout(function () {
|
||||
proc.kill()
|
||||
exitCode += 1
|
||||
console.error(file + ' timeout')
|
||||
killed = true
|
||||
}, timeout)
|
||||
|
||||
proc.stdout.pipe(process.stdout)
|
||||
proc.stderr.pipe(process.stderr)
|
||||
proc.on('exit', function (code) {
|
||||
if (code && !killed) console.error(file + ' failed')
|
||||
exitCode += code || 0
|
||||
clearTimeout(t)
|
||||
next()
|
||||
})
|
||||
}
|
||||
next()
|
||||
|
||||
})
|
||||
|
||||
|
29
node_modules/tabletop/node_modules/request/node_modules/cookie-jar/tests/test-cookie.js
generated
vendored
Normal file
29
node_modules/tabletop/node_modules/request/node_modules/cookie-jar/tests/test-cookie.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
var Cookie = require('../index')
|
||||
, assert = require('assert');
|
||||
|
||||
var str = 'Sid="s543qactge.wKE61E01Bs%2BKhzmxrwrnug="; Path=/; httpOnly; Expires=Sat, 04 Dec 2010 23:27:28 GMT';
|
||||
var cookie = new Cookie(str);
|
||||
|
||||
// test .toString()
|
||||
assert.equal(cookie.toString(), str);
|
||||
|
||||
// test .path
|
||||
assert.equal(cookie.path, '/');
|
||||
|
||||
// test .httpOnly
|
||||
assert.equal(cookie.httpOnly, true);
|
||||
|
||||
// test .name
|
||||
assert.equal(cookie.name, 'Sid');
|
||||
|
||||
// test .value
|
||||
assert.equal(cookie.value, '"s543qactge.wKE61E01Bs%2BKhzmxrwrnug="');
|
||||
|
||||
// test .expires
|
||||
assert.equal(cookie.expires instanceof Date, true);
|
||||
|
||||
// test .path default
|
||||
var cookie = new Cookie('foo=bar', { url: 'http://foo.com/bar' });
|
||||
assert.equal(cookie.path, '/bar');
|
||||
|
||||
console.log('All tests passed');
|
90
node_modules/tabletop/node_modules/request/node_modules/cookie-jar/tests/test-cookiejar.js
generated
vendored
Normal file
90
node_modules/tabletop/node_modules/request/node_modules/cookie-jar/tests/test-cookiejar.js
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
var Cookie = require('../index')
|
||||
, Jar = Cookie.Jar
|
||||
, assert = require('assert');
|
||||
|
||||
function expires(ms) {
|
||||
return new Date(Date.now() + ms).toUTCString();
|
||||
}
|
||||
|
||||
// test .get() expiration
|
||||
(function() {
|
||||
var jar = new Jar;
|
||||
var cookie = new Cookie('sid=1234; path=/; expires=' + expires(1000));
|
||||
jar.add(cookie);
|
||||
setTimeout(function(){
|
||||
var cookies = jar.get({ url: 'http://foo.com/foo' });
|
||||
assert.equal(cookies.length, 1);
|
||||
assert.equal(cookies[0], cookie);
|
||||
setTimeout(function(){
|
||||
var cookies = jar.get({ url: 'http://foo.com/foo' });
|
||||
assert.equal(cookies.length, 0);
|
||||
}, 1000);
|
||||
}, 5);
|
||||
})();
|
||||
|
||||
// test .get() path support
|
||||
(function() {
|
||||
var jar = new Jar;
|
||||
var a = new Cookie('sid=1234; path=/');
|
||||
var b = new Cookie('sid=1111; path=/foo/bar');
|
||||
var c = new Cookie('sid=2222; path=/');
|
||||
jar.add(a);
|
||||
jar.add(b);
|
||||
jar.add(c);
|
||||
|
||||
// should remove the duplicates
|
||||
assert.equal(jar.cookies.length, 2);
|
||||
|
||||
// same name, same path, latter prevails
|
||||
var cookies = jar.get({ url: 'http://foo.com/' });
|
||||
assert.equal(cookies.length, 1);
|
||||
assert.equal(cookies[0], c);
|
||||
|
||||
// same name, diff path, path specifity prevails, latter prevails
|
||||
var cookies = jar.get({ url: 'http://foo.com/foo/bar' });
|
||||
assert.equal(cookies.length, 1);
|
||||
assert.equal(cookies[0], b);
|
||||
|
||||
var jar = new Jar;
|
||||
var a = new Cookie('sid=1111; path=/foo/bar');
|
||||
var b = new Cookie('sid=1234; path=/');
|
||||
jar.add(a);
|
||||
jar.add(b);
|
||||
|
||||
var cookies = jar.get({ url: 'http://foo.com/foo/bar' });
|
||||
assert.equal(cookies.length, 1);
|
||||
assert.equal(cookies[0], a);
|
||||
|
||||
var cookies = jar.get({ url: 'http://foo.com/' });
|
||||
assert.equal(cookies.length, 1);
|
||||
assert.equal(cookies[0], b);
|
||||
|
||||
var jar = new Jar;
|
||||
var a = new Cookie('sid=1111; path=/foo/bar');
|
||||
var b = new Cookie('sid=3333; path=/foo/bar');
|
||||
var c = new Cookie('pid=3333; path=/foo/bar');
|
||||
var d = new Cookie('sid=2222; path=/foo/');
|
||||
var e = new Cookie('sid=1234; path=/');
|
||||
jar.add(a);
|
||||
jar.add(b);
|
||||
jar.add(c);
|
||||
jar.add(d);
|
||||
jar.add(e);
|
||||
|
||||
var cookies = jar.get({ url: 'http://foo.com/foo/bar' });
|
||||
assert.equal(cookies.length, 2);
|
||||
assert.equal(cookies[0], b);
|
||||
assert.equal(cookies[1], c);
|
||||
|
||||
var cookies = jar.get({ url: 'http://foo.com/foo/' });
|
||||
assert.equal(cookies.length, 1);
|
||||
assert.equal(cookies[0], d);
|
||||
|
||||
var cookies = jar.get({ url: 'http://foo.com/' });
|
||||
assert.equal(cookies.length, 1);
|
||||
assert.equal(cookies[0], e);
|
||||
})();
|
||||
|
||||
setTimeout(function() {
|
||||
console.log('All tests passed');
|
||||
}, 1200);
|
103
node_modules/tabletop/node_modules/request/node_modules/forever-agent/index.js
generated
vendored
Normal file
103
node_modules/tabletop/node_modules/request/node_modules/forever-agent/index.js
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
module.exports = ForeverAgent
|
||||
ForeverAgent.SSL = ForeverAgentSSL
|
||||
|
||||
var util = require('util')
|
||||
, Agent = require('http').Agent
|
||||
, net = require('net')
|
||||
, tls = require('tls')
|
||||
, AgentSSL = require('https').Agent
|
||||
|
||||
function ForeverAgent(options) {
|
||||
var self = this
|
||||
self.options = options || {}
|
||||
self.requests = {}
|
||||
self.sockets = {}
|
||||
self.freeSockets = {}
|
||||
self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets
|
||||
self.minSockets = self.options.minSockets || ForeverAgent.defaultMinSockets
|
||||
self.on('free', function(socket, host, port) {
|
||||
var name = host + ':' + port
|
||||
if (self.requests[name] && self.requests[name].length) {
|
||||
self.requests[name].shift().onSocket(socket)
|
||||
} else if (self.sockets[name].length < self.minSockets) {
|
||||
if (!self.freeSockets[name]) self.freeSockets[name] = []
|
||||
self.freeSockets[name].push(socket)
|
||||
|
||||
// if an error happens while we don't use the socket anyway, meh, throw the socket away
|
||||
function onIdleError() {
|
||||
socket.destroy()
|
||||
}
|
||||
socket._onIdleError = onIdleError
|
||||
socket.on('error', onIdleError)
|
||||
} else {
|
||||
// If there are no pending requests just destroy the
|
||||
// socket and it will get removed from the pool. This
|
||||
// gets us out of timeout issues and allows us to
|
||||
// default to Connection:keep-alive.
|
||||
socket.destroy()
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
util.inherits(ForeverAgent, Agent)
|
||||
|
||||
ForeverAgent.defaultMinSockets = 5
|
||||
|
||||
|
||||
ForeverAgent.prototype.createConnection = net.createConnection
|
||||
ForeverAgent.prototype.addRequestNoreuse = Agent.prototype.addRequest
|
||||
ForeverAgent.prototype.addRequest = function(req, host, port) {
|
||||
var name = host + ':' + port
|
||||
if (this.freeSockets[name] && this.freeSockets[name].length > 0 && !req.useChunkedEncodingByDefault) {
|
||||
var idleSocket = this.freeSockets[name].pop()
|
||||
idleSocket.removeListener('error', idleSocket._onIdleError)
|
||||
delete idleSocket._onIdleError
|
||||
req._reusedSocket = true
|
||||
req.onSocket(idleSocket)
|
||||
} else {
|
||||
this.addRequestNoreuse(req, host, port)
|
||||
}
|
||||
}
|
||||
|
||||
ForeverAgent.prototype.removeSocket = function(s, name, host, port) {
|
||||
if (this.sockets[name]) {
|
||||
var index = this.sockets[name].indexOf(s)
|
||||
if (index !== -1) {
|
||||
this.sockets[name].splice(index, 1)
|
||||
}
|
||||
} else if (this.sockets[name] && this.sockets[name].length === 0) {
|
||||
// don't leak
|
||||
delete this.sockets[name]
|
||||
delete this.requests[name]
|
||||
}
|
||||
|
||||
if (this.freeSockets[name]) {
|
||||
var index = this.freeSockets[name].indexOf(s)
|
||||
if (index !== -1) {
|
||||
this.freeSockets[name].splice(index, 1)
|
||||
if (this.freeSockets[name].length === 0) {
|
||||
delete this.freeSockets[name]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.requests[name] && this.requests[name].length) {
|
||||
// If we have pending requests and a socket gets closed a new one
|
||||
// needs to be created to take over in the pool for the one that closed.
|
||||
this.createSocket(name, host, port).emit('free')
|
||||
}
|
||||
}
|
||||
|
||||
function ForeverAgentSSL (options) {
|
||||
ForeverAgent.call(this, options)
|
||||
}
|
||||
util.inherits(ForeverAgentSSL, ForeverAgent)
|
||||
|
||||
ForeverAgentSSL.prototype.createConnection = createConnectionSSL
|
||||
ForeverAgentSSL.prototype.addRequestNoreuse = AgentSSL.prototype.addRequest
|
||||
|
||||
function createConnectionSSL (port, host, options) {
|
||||
options.port = port
|
||||
options.host = host
|
||||
return tls.connect(options)
|
||||
}
|
23
node_modules/tabletop/node_modules/request/node_modules/forever-agent/package.json
generated
vendored
Normal file
23
node_modules/tabletop/node_modules/request/node_modules/forever-agent/package.json
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"author": {
|
||||
"name": "Mikeal Rogers",
|
||||
"email": "mikeal.rogers@gmail.com",
|
||||
"url": "http://www.futurealoof.com"
|
||||
},
|
||||
"name": "forever-agent",
|
||||
"description": "HTTP Agent that keeps socket connections alive between keep-alive requests. Formerly part of mikeal/request, now a standalone module.",
|
||||
"version": "0.2.0",
|
||||
"repository": {
|
||||
"url": "https://github.com/mikeal/forever-agent"
|
||||
},
|
||||
"main": "index.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"optionalDependencies": {},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"_id": "forever-agent@0.2.0",
|
||||
"readme": "ERROR: No README.md file found!",
|
||||
"_from": "forever-agent@~0.2.0"
|
||||
}
|
19
node_modules/tabletop/node_modules/request/node_modules/form-data/License
generated
vendored
Normal file
19
node_modules/tabletop/node_modules/request/node_modules/form-data/License
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
146
node_modules/tabletop/node_modules/request/node_modules/form-data/Readme.md
generated
vendored
Normal file
146
node_modules/tabletop/node_modules/request/node_modules/form-data/Readme.md
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
# Form-Data [](https://travis-ci.org/alexindigo/node-form-data) [](https://gemnasium.com/alexindigo/node-form-data)
|
||||
|
||||
A module to create readable `"multipart/form-data"` streams. Can be used to
|
||||
submit forms and file uploads to other web applications.
|
||||
|
||||
The API of this module is inspired by the
|
||||
[XMLHttpRequest-2 FormData Interface][xhr2-fd].
|
||||
|
||||
[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
npm install form-data
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
In this example we are constructing a form with 3 fields that contain a string,
|
||||
a buffer and a file stream.
|
||||
|
||||
``` javascript
|
||||
var FormData = require('form-data');
|
||||
var fs = require('fs');
|
||||
|
||||
var form = new FormData();
|
||||
form.append('my_field', 'my value');
|
||||
form.append('my_buffer', new Buffer(10));
|
||||
form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
|
||||
```
|
||||
|
||||
Also you can use http-response stream:
|
||||
|
||||
``` javascript
|
||||
var FormData = require('form-data');
|
||||
var http = require('http');
|
||||
|
||||
var form = new FormData();
|
||||
|
||||
http.request('http://nodejs.org/images/logo.png', function(response) {
|
||||
form.append('my_field', 'my value');
|
||||
form.append('my_buffer', new Buffer(10));
|
||||
form.append('my_logo', response);
|
||||
});
|
||||
```
|
||||
|
||||
Or @mikeal's request stream:
|
||||
|
||||
``` javascript
|
||||
var FormData = require('form-data');
|
||||
var request = require('request');
|
||||
|
||||
var form = new FormData();
|
||||
|
||||
form.append('my_field', 'my value');
|
||||
form.append('my_buffer', new Buffer(10));
|
||||
form.append('my_logo', request('http://nodejs.org/images/logo.png'));
|
||||
```
|
||||
|
||||
In order to submit this form to a web application, you can use node's http
|
||||
client interface:
|
||||
|
||||
``` javascript
|
||||
var http = require('http');
|
||||
|
||||
var request = http.request({
|
||||
method: 'post',
|
||||
host: 'example.org',
|
||||
path: '/upload',
|
||||
headers: form.getHeaders()
|
||||
});
|
||||
|
||||
form.pipe(request);
|
||||
|
||||
request.on('response', function(res) {
|
||||
console.log(res.statusCode);
|
||||
});
|
||||
```
|
||||
|
||||
Or if you would prefer the `'Content-Length'` header to be set for you:
|
||||
|
||||
``` javascript
|
||||
form.submit('example.org/upload', function(err, res) {
|
||||
console.log(res.statusCode);
|
||||
});
|
||||
```
|
||||
|
||||
To use custom headers and pre-known length in parts:
|
||||
|
||||
``` javascript
|
||||
var CRLF = '\r\n';
|
||||
var form = new FormData();
|
||||
|
||||
var options = {
|
||||
header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF,
|
||||
knownLength: 1
|
||||
};
|
||||
|
||||
form.append('my_buffer', buffer, options);
|
||||
|
||||
form.submit('http://example.com/', function(err, res) {
|
||||
if (err) throw err;
|
||||
console.log('Done');
|
||||
});
|
||||
```
|
||||
|
||||
Form-Data can recognize and fetch all the required information from common types of streams (fs.readStream, http.response and mikeal's request), for some other types of streams you'd need to provide "file"-related information manually:
|
||||
|
||||
``` javascript
|
||||
someModule.stream(function(err, stdout, stderr) {
|
||||
if (err) throw err;
|
||||
|
||||
var form = new FormData();
|
||||
|
||||
form.append('file', stdout, {
|
||||
filename: 'unicycle.jpg',
|
||||
contentType: 'image/jpg',
|
||||
knownLength: 19806
|
||||
});
|
||||
|
||||
form.submit('http://example.com/', function(err, res) {
|
||||
if (err) throw err;
|
||||
console.log('Done');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
For edge cases, like POST request to URL with query string or to pass HTTP auth credentials, object can be passed to `form.submit()` as first parameter:
|
||||
|
||||
``` javascript
|
||||
form.submit({
|
||||
host: 'example.com',
|
||||
path: '/probably.php?extra=params',
|
||||
auth: 'username:password'
|
||||
}, function(err, res) {
|
||||
console.log(res.statusCode);
|
||||
});
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
||||
- Add new streams (0.10) support and try really hard not to break it for 0.8.x.
|
||||
|
||||
## License
|
||||
|
||||
Form-Data is licensed under the MIT license.
|
292
node_modules/tabletop/node_modules/request/node_modules/form-data/lib/form_data.js
generated
vendored
Normal file
292
node_modules/tabletop/node_modules/request/node_modules/form-data/lib/form_data.js
generated
vendored
Normal file
@@ -0,0 +1,292 @@
|
||||
var CombinedStream = require('combined-stream');
|
||||
var util = require('util');
|
||||
var path = require('path');
|
||||
var http = require('http');
|
||||
var https = require('https');
|
||||
var parseUrl = require('url').parse;
|
||||
var fs = require('fs');
|
||||
var mime = require('mime');
|
||||
var async = require('async');
|
||||
|
||||
module.exports = FormData;
|
||||
function FormData() {
|
||||
this._overheadLength = 0;
|
||||
this._valueLength = 0;
|
||||
this._lengthRetrievers = [];
|
||||
|
||||
CombinedStream.call(this);
|
||||
}
|
||||
util.inherits(FormData, CombinedStream);
|
||||
|
||||
FormData.LINE_BREAK = '\r\n';
|
||||
|
||||
FormData.prototype.append = function(field, value, options) {
|
||||
options = options || {};
|
||||
|
||||
var append = CombinedStream.prototype.append.bind(this);
|
||||
|
||||
// all that streamy business can't handle numbers
|
||||
if (typeof value == 'number') value = ''+value;
|
||||
|
||||
var header = this._multiPartHeader(field, value, options);
|
||||
var footer = this._multiPartFooter(field, value, options);
|
||||
|
||||
append(header);
|
||||
append(value);
|
||||
append(footer);
|
||||
|
||||
// pass along options.knownLength
|
||||
this._trackLength(header, value, options);
|
||||
};
|
||||
|
||||
FormData.prototype._trackLength = function(header, value, options) {
|
||||
var valueLength = 0;
|
||||
|
||||
// used w/ trackLengthSync(), when length is known.
|
||||
// e.g. for streaming directly from a remote server,
|
||||
// w/ a known file a size, and not wanting to wait for
|
||||
// incoming file to finish to get its size.
|
||||
if (options.knownLength != null) {
|
||||
valueLength += +options.knownLength;
|
||||
} else if (Buffer.isBuffer(value)) {
|
||||
valueLength = value.length;
|
||||
} else if (typeof value === 'string') {
|
||||
valueLength = Buffer.byteLength(value);
|
||||
}
|
||||
|
||||
this._valueLength += valueLength;
|
||||
|
||||
// @check why add CRLF? does this account for custom/multiple CRLFs?
|
||||
this._overheadLength +=
|
||||
Buffer.byteLength(header) +
|
||||
+ FormData.LINE_BREAK.length;
|
||||
|
||||
// empty or either doesn't have path or not an http response
|
||||
if (!value || ( !value.path && !(value.readable && value.hasOwnProperty('httpVersion')) )) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._lengthRetrievers.push(function(next) {
|
||||
|
||||
// do we already know the size?
|
||||
// 0 additional leaves value from getSyncLength()
|
||||
if (options.knownLength != null) {
|
||||
next(null, 0);
|
||||
|
||||
// check if it's local file
|
||||
} else if (value.hasOwnProperty('fd')) {
|
||||
fs.stat(value.path, function(err, stat) {
|
||||
if (err) {
|
||||
next(err);
|
||||
return;
|
||||
}
|
||||
|
||||
next(null, stat.size);
|
||||
});
|
||||
|
||||
// or http response
|
||||
} else if (value.hasOwnProperty('httpVersion')) {
|
||||
next(null, +value.headers['content-length']);
|
||||
|
||||
// or request stream http://github.com/mikeal/request
|
||||
} else if (value.hasOwnProperty('httpModule')) {
|
||||
// wait till response come back
|
||||
value.on('response', function(response) {
|
||||
value.pause();
|
||||
next(null, +response.headers['content-length']);
|
||||
});
|
||||
value.resume();
|
||||
|
||||
// something else
|
||||
} else {
|
||||
next('Unknown stream');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
FormData.prototype._multiPartHeader = function(field, value, options) {
|
||||
var boundary = this.getBoundary();
|
||||
var header = '';
|
||||
|
||||
// custom header specified (as string)?
|
||||
// it becomes responsible for boundary
|
||||
// (e.g. to handle extra CRLFs on .NET servers)
|
||||
if (options.header != null) {
|
||||
header = options.header;
|
||||
} else {
|
||||
header += '--' + boundary + FormData.LINE_BREAK +
|
||||
'Content-Disposition: form-data; name="' + field + '"';
|
||||
|
||||
// fs- and request- streams have path property
|
||||
// or use custom filename and/or contentType
|
||||
// TODO: Use request's response mime-type
|
||||
if (options.filename || value.path) {
|
||||
header +=
|
||||
'; filename="' + path.basename(options.filename || value.path) + '"' + FormData.LINE_BREAK +
|
||||
'Content-Type: ' + (options.contentType || mime.lookup(options.filename || value.path));
|
||||
|
||||
// http response has not
|
||||
} else if (value.readable && value.hasOwnProperty('httpVersion')) {
|
||||
header +=
|
||||
'; filename="' + path.basename(value.client._httpMessage.path) + '"' + FormData.LINE_BREAK +
|
||||
'Content-Type: ' + value.headers['content-type'];
|
||||
}
|
||||
|
||||
header += FormData.LINE_BREAK + FormData.LINE_BREAK;
|
||||
}
|
||||
|
||||
return header;
|
||||
};
|
||||
|
||||
FormData.prototype._multiPartFooter = function(field, value, options) {
|
||||
return function(next) {
|
||||
var footer = FormData.LINE_BREAK;
|
||||
|
||||
var lastPart = (this._streams.length === 0);
|
||||
if (lastPart) {
|
||||
footer += this._lastBoundary();
|
||||
}
|
||||
|
||||
next(footer);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
FormData.prototype._lastBoundary = function() {
|
||||
return '--' + this.getBoundary() + '--';
|
||||
};
|
||||
|
||||
FormData.prototype.getHeaders = function(userHeaders) {
|
||||
var formHeaders = {
|
||||
'content-type': 'multipart/form-data; boundary=' + this.getBoundary()
|
||||
};
|
||||
|
||||
for (var header in userHeaders) {
|
||||
formHeaders[header.toLowerCase()] = userHeaders[header];
|
||||
}
|
||||
|
||||
return formHeaders;
|
||||
}
|
||||
|
||||
FormData.prototype.getCustomHeaders = function(contentType) {
|
||||
contentType = contentType ? contentType : 'multipart/form-data';
|
||||
|
||||
var formHeaders = {
|
||||
'content-type': contentType + '; boundary=' + this.getBoundary(),
|
||||
'content-length': this.getLengthSync()
|
||||
};
|
||||
|
||||
return formHeaders;
|
||||
}
|
||||
|
||||
FormData.prototype.getBoundary = function() {
|
||||
if (!this._boundary) {
|
||||
this._generateBoundary();
|
||||
}
|
||||
|
||||
return this._boundary;
|
||||
};
|
||||
|
||||
FormData.prototype._generateBoundary = function() {
|
||||
// This generates a 50 character boundary similar to those used by Firefox.
|
||||
// They are optimized for boyer-moore parsing.
|
||||
var boundary = '--------------------------';
|
||||
for (var i = 0; i < 24; i++) {
|
||||
boundary += Math.floor(Math.random() * 10).toString(16);
|
||||
}
|
||||
|
||||
this._boundary = boundary;
|
||||
};
|
||||
|
||||
FormData.prototype.getLengthSync = function() {
|
||||
var knownLength = this._overheadLength + this._valueLength;
|
||||
|
||||
if (this._streams.length) {
|
||||
knownLength += this._lastBoundary().length;
|
||||
}
|
||||
|
||||
return knownLength;
|
||||
};
|
||||
|
||||
FormData.prototype.getLength = function(cb) {
|
||||
var knownLength = this._overheadLength + this._valueLength;
|
||||
|
||||
if (this._streams.length) {
|
||||
knownLength += this._lastBoundary().length;
|
||||
}
|
||||
|
||||
if (!this._lengthRetrievers.length) {
|
||||
process.nextTick(cb.bind(this, null, knownLength));
|
||||
return;
|
||||
}
|
||||
|
||||
async.parallel(this._lengthRetrievers, function(err, values) {
|
||||
if (err) {
|
||||
cb(err);
|
||||
return;
|
||||
}
|
||||
|
||||
values.forEach(function(length) {
|
||||
knownLength += length;
|
||||
});
|
||||
|
||||
cb(null, knownLength);
|
||||
});
|
||||
};
|
||||
|
||||
FormData.prototype.submit = function(params, cb) {
|
||||
this.getLength(function(err, length) {
|
||||
|
||||
var request
|
||||
, options
|
||||
, defaults = {
|
||||
method : 'post',
|
||||
port : 80,
|
||||
headers: this.getHeaders({'Content-Length': length})
|
||||
};
|
||||
|
||||
// parse provided url if it's string
|
||||
// or treat it as options object
|
||||
if (typeof params == 'string') {
|
||||
params = parseUrl(params);
|
||||
|
||||
options = populate({
|
||||
port: params.port,
|
||||
path: params.pathname,
|
||||
host: params.hostname
|
||||
}, defaults);
|
||||
}
|
||||
else // use custom params
|
||||
{
|
||||
options = populate(params, defaults);
|
||||
}
|
||||
|
||||
// https if specified, fallback to http in any other case
|
||||
if (params.protocol == 'https:') {
|
||||
// override default port
|
||||
if (!params.port) options.port = 443;
|
||||
request = https.request(options);
|
||||
} else {
|
||||
request = http.request(options);
|
||||
}
|
||||
|
||||
this.pipe(request);
|
||||
if (cb) {
|
||||
request.on('error', cb);
|
||||
request.on('response', cb.bind(this, null));
|
||||
}
|
||||
|
||||
return request;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/*
|
||||
* Santa's little helpers
|
||||
*/
|
||||
|
||||
// populates missing values
|
||||
function populate(dst, src) {
|
||||
for (var prop in src) {
|
||||
if (!dst[prop]) dst[prop] = src[prop];
|
||||
}
|
||||
return dst;
|
||||
}
|
19
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/async/LICENSE
generated
vendored
Normal file
19
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/async/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2010 Caolan McMahon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
1414
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/async/README.md
generated
vendored
Normal file
1414
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/async/README.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
952
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js
generated
vendored
Executable file
952
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js
generated
vendored
Executable file
@@ -0,0 +1,952 @@
|
||||
/*global setImmediate: false, setTimeout: false, console: false */
|
||||
(function () {
|
||||
|
||||
var async = {};
|
||||
|
||||
// global on the server, window in the browser
|
||||
var root, previous_async;
|
||||
|
||||
root = this;
|
||||
if (root != null) {
|
||||
previous_async = root.async;
|
||||
}
|
||||
|
||||
async.noConflict = function () {
|
||||
root.async = previous_async;
|
||||
return async;
|
||||
};
|
||||
|
||||
function only_once(fn) {
|
||||
var called = false;
|
||||
return function() {
|
||||
if (called) throw new Error("Callback was already called.");
|
||||
called = true;
|
||||
fn.apply(root, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
//// cross-browser compatiblity functions ////
|
||||
|
||||
var _each = function (arr, iterator) {
|
||||
if (arr.forEach) {
|
||||
return arr.forEach(iterator);
|
||||
}
|
||||
for (var i = 0; i < arr.length; i += 1) {
|
||||
iterator(arr[i], i, arr);
|
||||
}
|
||||
};
|
||||
|
||||
var _map = function (arr, iterator) {
|
||||
if (arr.map) {
|
||||
return arr.map(iterator);
|
||||
}
|
||||
var results = [];
|
||||
_each(arr, function (x, i, a) {
|
||||
results.push(iterator(x, i, a));
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
var _reduce = function (arr, iterator, memo) {
|
||||
if (arr.reduce) {
|
||||
return arr.reduce(iterator, memo);
|
||||
}
|
||||
_each(arr, function (x, i, a) {
|
||||
memo = iterator(memo, x, i, a);
|
||||
});
|
||||
return memo;
|
||||
};
|
||||
|
||||
var _keys = function (obj) {
|
||||
if (Object.keys) {
|
||||
return Object.keys(obj);
|
||||
}
|
||||
var keys = [];
|
||||
for (var k in obj) {
|
||||
if (obj.hasOwnProperty(k)) {
|
||||
keys.push(k);
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
};
|
||||
|
||||
//// exported async module functions ////
|
||||
|
||||
//// nextTick implementation with browser-compatible fallback ////
|
||||
if (typeof process === 'undefined' || !(process.nextTick)) {
|
||||
if (typeof setImmediate === 'function') {
|
||||
async.setImmediate = setImmediate;
|
||||
async.nextTick = setImmediate;
|
||||
}
|
||||
else {
|
||||
async.nextTick = function (fn) {
|
||||
setTimeout(fn, 0);
|
||||
};
|
||||
async.setImmediate = async.nextTick;
|
||||
}
|
||||
}
|
||||
else {
|
||||
async.nextTick = process.nextTick;
|
||||
if (typeof setImmediate !== 'undefined') {
|
||||
async.setImmediate = setImmediate;
|
||||
}
|
||||
else {
|
||||
async.setImmediate = async.nextTick;
|
||||
}
|
||||
}
|
||||
|
||||
async.each = function (arr, iterator, callback) {
|
||||
callback = callback || function () {};
|
||||
if (!arr.length) {
|
||||
return callback();
|
||||
}
|
||||
var completed = 0;
|
||||
_each(arr, function (x) {
|
||||
iterator(x, only_once(function (err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
callback = function () {};
|
||||
}
|
||||
else {
|
||||
completed += 1;
|
||||
if (completed >= arr.length) {
|
||||
callback(null);
|
||||
}
|
||||
}
|
||||
}));
|
||||
});
|
||||
};
|
||||
async.forEach = async.each;
|
||||
|
||||
async.eachSeries = function (arr, iterator, callback) {
|
||||
callback = callback || function () {};
|
||||
if (!arr.length) {
|
||||
return callback();
|
||||
}
|
||||
var completed = 0;
|
||||
var iterate = function () {
|
||||
iterator(arr[completed], function (err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
callback = function () {};
|
||||
}
|
||||
else {
|
||||
completed += 1;
|
||||
if (completed >= arr.length) {
|
||||
callback(null);
|
||||
}
|
||||
else {
|
||||
iterate();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
iterate();
|
||||
};
|
||||
async.forEachSeries = async.eachSeries;
|
||||
|
||||
async.eachLimit = function (arr, limit, iterator, callback) {
|
||||
var fn = _eachLimit(limit);
|
||||
fn.apply(null, [arr, iterator, callback]);
|
||||
};
|
||||
async.forEachLimit = async.eachLimit;
|
||||
|
||||
var _eachLimit = function (limit) {
|
||||
|
||||
return function (arr, iterator, callback) {
|
||||
callback = callback || function () {};
|
||||
if (!arr.length || limit <= 0) {
|
||||
return callback();
|
||||
}
|
||||
var completed = 0;
|
||||
var started = 0;
|
||||
var running = 0;
|
||||
|
||||
(function replenish () {
|
||||
if (completed >= arr.length) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
while (running < limit && started < arr.length) {
|
||||
started += 1;
|
||||
running += 1;
|
||||
iterator(arr[started - 1], function (err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
callback = function () {};
|
||||
}
|
||||
else {
|
||||
completed += 1;
|
||||
running -= 1;
|
||||
if (completed >= arr.length) {
|
||||
callback();
|
||||
}
|
||||
else {
|
||||
replenish();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
var doParallel = function (fn) {
|
||||
return function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
return fn.apply(null, [async.each].concat(args));
|
||||
};
|
||||
};
|
||||
var doParallelLimit = function(limit, fn) {
|
||||
return function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
return fn.apply(null, [_eachLimit(limit)].concat(args));
|
||||
};
|
||||
};
|
||||
var doSeries = function (fn) {
|
||||
return function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
return fn.apply(null, [async.eachSeries].concat(args));
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
var _asyncMap = function (eachfn, arr, iterator, callback) {
|
||||
var results = [];
|
||||
arr = _map(arr, function (x, i) {
|
||||
return {index: i, value: x};
|
||||
});
|
||||
eachfn(arr, function (x, callback) {
|
||||
iterator(x.value, function (err, v) {
|
||||
results[x.index] = v;
|
||||
callback(err);
|
||||
});
|
||||
}, function (err) {
|
||||
callback(err, results);
|
||||
});
|
||||
};
|
||||
async.map = doParallel(_asyncMap);
|
||||
async.mapSeries = doSeries(_asyncMap);
|
||||
async.mapLimit = function (arr, limit, iterator, callback) {
|
||||
return _mapLimit(limit)(arr, iterator, callback);
|
||||
};
|
||||
|
||||
var _mapLimit = function(limit) {
|
||||
return doParallelLimit(limit, _asyncMap);
|
||||
};
|
||||
|
||||
// reduce only has a series version, as doing reduce in parallel won't
|
||||
// work in many situations.
|
||||
async.reduce = function (arr, memo, iterator, callback) {
|
||||
async.eachSeries(arr, function (x, callback) {
|
||||
iterator(memo, x, function (err, v) {
|
||||
memo = v;
|
||||
callback(err);
|
||||
});
|
||||
}, function (err) {
|
||||
callback(err, memo);
|
||||
});
|
||||
};
|
||||
// inject alias
|
||||
async.inject = async.reduce;
|
||||
// foldl alias
|
||||
async.foldl = async.reduce;
|
||||
|
||||
async.reduceRight = function (arr, memo, iterator, callback) {
|
||||
var reversed = _map(arr, function (x) {
|
||||
return x;
|
||||
}).reverse();
|
||||
async.reduce(reversed, memo, iterator, callback);
|
||||
};
|
||||
// foldr alias
|
||||
async.foldr = async.reduceRight;
|
||||
|
||||
var _filter = function (eachfn, arr, iterator, callback) {
|
||||
var results = [];
|
||||
arr = _map(arr, function (x, i) {
|
||||
return {index: i, value: x};
|
||||
});
|
||||
eachfn(arr, function (x, callback) {
|
||||
iterator(x.value, function (v) {
|
||||
if (v) {
|
||||
results.push(x);
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}, function (err) {
|
||||
callback(_map(results.sort(function (a, b) {
|
||||
return a.index - b.index;
|
||||
}), function (x) {
|
||||
return x.value;
|
||||
}));
|
||||
});
|
||||
};
|
||||
async.filter = doParallel(_filter);
|
||||
async.filterSeries = doSeries(_filter);
|
||||
// select alias
|
||||
async.select = async.filter;
|
||||
async.selectSeries = async.filterSeries;
|
||||
|
||||
var _reject = function (eachfn, arr, iterator, callback) {
|
||||
var results = [];
|
||||
arr = _map(arr, function (x, i) {
|
||||
return {index: i, value: x};
|
||||
});
|
||||
eachfn(arr, function (x, callback) {
|
||||
iterator(x.value, function (v) {
|
||||
if (!v) {
|
||||
results.push(x);
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}, function (err) {
|
||||
callback(_map(results.sort(function (a, b) {
|
||||
return a.index - b.index;
|
||||
}), function (x) {
|
||||
return x.value;
|
||||
}));
|
||||
});
|
||||
};
|
||||
async.reject = doParallel(_reject);
|
||||
async.rejectSeries = doSeries(_reject);
|
||||
|
||||
var _detect = function (eachfn, arr, iterator, main_callback) {
|
||||
eachfn(arr, function (x, callback) {
|
||||
iterator(x, function (result) {
|
||||
if (result) {
|
||||
main_callback(x);
|
||||
main_callback = function () {};
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}, function (err) {
|
||||
main_callback();
|
||||
});
|
||||
};
|
||||
async.detect = doParallel(_detect);
|
||||
async.detectSeries = doSeries(_detect);
|
||||
|
||||
async.some = function (arr, iterator, main_callback) {
|
||||
async.each(arr, function (x, callback) {
|
||||
iterator(x, function (v) {
|
||||
if (v) {
|
||||
main_callback(true);
|
||||
main_callback = function () {};
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}, function (err) {
|
||||
main_callback(false);
|
||||
});
|
||||
};
|
||||
// any alias
|
||||
async.any = async.some;
|
||||
|
||||
async.every = function (arr, iterator, main_callback) {
|
||||
async.each(arr, function (x, callback) {
|
||||
iterator(x, function (v) {
|
||||
if (!v) {
|
||||
main_callback(false);
|
||||
main_callback = function () {};
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}, function (err) {
|
||||
main_callback(true);
|
||||
});
|
||||
};
|
||||
// all alias
|
||||
async.all = async.every;
|
||||
|
||||
async.sortBy = function (arr, iterator, callback) {
|
||||
async.map(arr, function (x, callback) {
|
||||
iterator(x, function (err, criteria) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
}
|
||||
else {
|
||||
callback(null, {value: x, criteria: criteria});
|
||||
}
|
||||
});
|
||||
}, function (err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
else {
|
||||
var fn = function (left, right) {
|
||||
var a = left.criteria, b = right.criteria;
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
};
|
||||
callback(null, _map(results.sort(fn), function (x) {
|
||||
return x.value;
|
||||
}));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
async.auto = function (tasks, callback) {
|
||||
callback = callback || function () {};
|
||||
var keys = _keys(tasks);
|
||||
if (!keys.length) {
|
||||
return callback(null);
|
||||
}
|
||||
|
||||
var results = {};
|
||||
|
||||
var listeners = [];
|
||||
var addListener = function (fn) {
|
||||
listeners.unshift(fn);
|
||||
};
|
||||
var removeListener = function (fn) {
|
||||
for (var i = 0; i < listeners.length; i += 1) {
|
||||
if (listeners[i] === fn) {
|
||||
listeners.splice(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
var taskComplete = function () {
|
||||
_each(listeners.slice(0), function (fn) {
|
||||
fn();
|
||||
});
|
||||
};
|
||||
|
||||
addListener(function () {
|
||||
if (_keys(results).length === keys.length) {
|
||||
callback(null, results);
|
||||
callback = function () {};
|
||||
}
|
||||
});
|
||||
|
||||
_each(keys, function (k) {
|
||||
var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
|
||||
var taskCallback = function (err) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (args.length <= 1) {
|
||||
args = args[0];
|
||||
}
|
||||
if (err) {
|
||||
var safeResults = {};
|
||||
_each(_keys(results), function(rkey) {
|
||||
safeResults[rkey] = results[rkey];
|
||||
});
|
||||
safeResults[k] = args;
|
||||
callback(err, safeResults);
|
||||
// stop subsequent errors hitting callback multiple times
|
||||
callback = function () {};
|
||||
}
|
||||
else {
|
||||
results[k] = args;
|
||||
async.setImmediate(taskComplete);
|
||||
}
|
||||
};
|
||||
var requires = task.slice(0, Math.abs(task.length - 1)) || [];
|
||||
var ready = function () {
|
||||
return _reduce(requires, function (a, x) {
|
||||
return (a && results.hasOwnProperty(x));
|
||||
}, true) && !results.hasOwnProperty(k);
|
||||
};
|
||||
if (ready()) {
|
||||
task[task.length - 1](taskCallback, results);
|
||||
}
|
||||
else {
|
||||
var listener = function () {
|
||||
if (ready()) {
|
||||
removeListener(listener);
|
||||
task[task.length - 1](taskCallback, results);
|
||||
}
|
||||
};
|
||||
addListener(listener);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
async.waterfall = function (tasks, callback) {
|
||||
callback = callback || function () {};
|
||||
if (tasks.constructor !== Array) {
|
||||
var err = new Error('First argument to waterfall must be an array of functions');
|
||||
return callback(err);
|
||||
}
|
||||
if (!tasks.length) {
|
||||
return callback();
|
||||
}
|
||||
var wrapIterator = function (iterator) {
|
||||
return function (err) {
|
||||
if (err) {
|
||||
callback.apply(null, arguments);
|
||||
callback = function () {};
|
||||
}
|
||||
else {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
var next = iterator.next();
|
||||
if (next) {
|
||||
args.push(wrapIterator(next));
|
||||
}
|
||||
else {
|
||||
args.push(callback);
|
||||
}
|
||||
async.setImmediate(function () {
|
||||
iterator.apply(null, args);
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
wrapIterator(async.iterator(tasks))();
|
||||
};
|
||||
|
||||
var _parallel = function(eachfn, tasks, callback) {
|
||||
callback = callback || function () {};
|
||||
if (tasks.constructor === Array) {
|
||||
eachfn.map(tasks, function (fn, callback) {
|
||||
if (fn) {
|
||||
fn(function (err) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (args.length <= 1) {
|
||||
args = args[0];
|
||||
}
|
||||
callback.call(null, err, args);
|
||||
});
|
||||
}
|
||||
}, callback);
|
||||
}
|
||||
else {
|
||||
var results = {};
|
||||
eachfn.each(_keys(tasks), function (k, callback) {
|
||||
tasks[k](function (err) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (args.length <= 1) {
|
||||
args = args[0];
|
||||
}
|
||||
results[k] = args;
|
||||
callback(err);
|
||||
});
|
||||
}, function (err) {
|
||||
callback(err, results);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
async.parallel = function (tasks, callback) {
|
||||
_parallel({ map: async.map, each: async.each }, tasks, callback);
|
||||
};
|
||||
|
||||
async.parallelLimit = function(tasks, limit, callback) {
|
||||
_parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
|
||||
};
|
||||
|
||||
async.series = function (tasks, callback) {
|
||||
callback = callback || function () {};
|
||||
if (tasks.constructor === Array) {
|
||||
async.mapSeries(tasks, function (fn, callback) {
|
||||
if (fn) {
|
||||
fn(function (err) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (args.length <= 1) {
|
||||
args = args[0];
|
||||
}
|
||||
callback.call(null, err, args);
|
||||
});
|
||||
}
|
||||
}, callback);
|
||||
}
|
||||
else {
|
||||
var results = {};
|
||||
async.eachSeries(_keys(tasks), function (k, callback) {
|
||||
tasks[k](function (err) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (args.length <= 1) {
|
||||
args = args[0];
|
||||
}
|
||||
results[k] = args;
|
||||
callback(err);
|
||||
});
|
||||
}, function (err) {
|
||||
callback(err, results);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
async.iterator = function (tasks) {
|
||||
var makeCallback = function (index) {
|
||||
var fn = function () {
|
||||
if (tasks.length) {
|
||||
tasks[index].apply(null, arguments);
|
||||
}
|
||||
return fn.next();
|
||||
};
|
||||
fn.next = function () {
|
||||
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
|
||||
};
|
||||
return fn;
|
||||
};
|
||||
return makeCallback(0);
|
||||
};
|
||||
|
||||
async.apply = function (fn) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return function () {
|
||||
return fn.apply(
|
||||
null, args.concat(Array.prototype.slice.call(arguments))
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
var _concat = function (eachfn, arr, fn, callback) {
|
||||
var r = [];
|
||||
eachfn(arr, function (x, cb) {
|
||||
fn(x, function (err, y) {
|
||||
r = r.concat(y || []);
|
||||
cb(err);
|
||||
});
|
||||
}, function (err) {
|
||||
callback(err, r);
|
||||
});
|
||||
};
|
||||
async.concat = doParallel(_concat);
|
||||
async.concatSeries = doSeries(_concat);
|
||||
|
||||
async.whilst = function (test, iterator, callback) {
|
||||
if (test()) {
|
||||
iterator(function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
async.whilst(test, iterator, callback);
|
||||
});
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
async.doWhilst = function (iterator, test, callback) {
|
||||
iterator(function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
if (test()) {
|
||||
async.doWhilst(iterator, test, callback);
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
async.until = function (test, iterator, callback) {
|
||||
if (!test()) {
|
||||
iterator(function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
async.until(test, iterator, callback);
|
||||
});
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
async.doUntil = function (iterator, test, callback) {
|
||||
iterator(function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
if (!test()) {
|
||||
async.doUntil(iterator, test, callback);
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
async.queue = function (worker, concurrency) {
|
||||
if (concurrency === undefined) {
|
||||
concurrency = 1;
|
||||
}
|
||||
function _insert(q, data, pos, callback) {
|
||||
if(data.constructor !== Array) {
|
||||
data = [data];
|
||||
}
|
||||
_each(data, function(task) {
|
||||
var item = {
|
||||
data: task,
|
||||
callback: typeof callback === 'function' ? callback : null
|
||||
};
|
||||
|
||||
if (pos) {
|
||||
q.tasks.unshift(item);
|
||||
} else {
|
||||
q.tasks.push(item);
|
||||
}
|
||||
|
||||
if (q.saturated && q.tasks.length === concurrency) {
|
||||
q.saturated();
|
||||
}
|
||||
async.setImmediate(q.process);
|
||||
});
|
||||
}
|
||||
|
||||
var workers = 0;
|
||||
var q = {
|
||||
tasks: [],
|
||||
concurrency: concurrency,
|
||||
saturated: null,
|
||||
empty: null,
|
||||
drain: null,
|
||||
push: function (data, callback) {
|
||||
_insert(q, data, false, callback);
|
||||
},
|
||||
unshift: function (data, callback) {
|
||||
_insert(q, data, true, callback);
|
||||
},
|
||||
process: function () {
|
||||
if (workers < q.concurrency && q.tasks.length) {
|
||||
var task = q.tasks.shift();
|
||||
if (q.empty && q.tasks.length === 0) {
|
||||
q.empty();
|
||||
}
|
||||
workers += 1;
|
||||
var next = function () {
|
||||
workers -= 1;
|
||||
if (task.callback) {
|
||||
task.callback.apply(task, arguments);
|
||||
}
|
||||
if (q.drain && q.tasks.length + workers === 0) {
|
||||
q.drain();
|
||||
}
|
||||
q.process();
|
||||
};
|
||||
var cb = only_once(next);
|
||||
worker(task.data, cb);
|
||||
}
|
||||
},
|
||||
length: function () {
|
||||
return q.tasks.length;
|
||||
},
|
||||
running: function () {
|
||||
return workers;
|
||||
}
|
||||
};
|
||||
return q;
|
||||
};
|
||||
|
||||
async.cargo = function (worker, payload) {
|
||||
var working = false,
|
||||
tasks = [];
|
||||
|
||||
var cargo = {
|
||||
tasks: tasks,
|
||||
payload: payload,
|
||||
saturated: null,
|
||||
empty: null,
|
||||
drain: null,
|
||||
push: function (data, callback) {
|
||||
if(data.constructor !== Array) {
|
||||
data = [data];
|
||||
}
|
||||
_each(data, function(task) {
|
||||
tasks.push({
|
||||
data: task,
|
||||
callback: typeof callback === 'function' ? callback : null
|
||||
});
|
||||
if (cargo.saturated && tasks.length === payload) {
|
||||
cargo.saturated();
|
||||
}
|
||||
});
|
||||
async.setImmediate(cargo.process);
|
||||
},
|
||||
process: function process() {
|
||||
if (working) return;
|
||||
if (tasks.length === 0) {
|
||||
if(cargo.drain) cargo.drain();
|
||||
return;
|
||||
}
|
||||
|
||||
var ts = typeof payload === 'number'
|
||||
? tasks.splice(0, payload)
|
||||
: tasks.splice(0);
|
||||
|
||||
var ds = _map(ts, function (task) {
|
||||
return task.data;
|
||||
});
|
||||
|
||||
if(cargo.empty) cargo.empty();
|
||||
working = true;
|
||||
worker(ds, function () {
|
||||
working = false;
|
||||
|
||||
var args = arguments;
|
||||
_each(ts, function (data) {
|
||||
if (data.callback) {
|
||||
data.callback.apply(null, args);
|
||||
}
|
||||
});
|
||||
|
||||
process();
|
||||
});
|
||||
},
|
||||
length: function () {
|
||||
return tasks.length;
|
||||
},
|
||||
running: function () {
|
||||
return working;
|
||||
}
|
||||
};
|
||||
return cargo;
|
||||
};
|
||||
|
||||
var _console_fn = function (name) {
|
||||
return function (fn) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
fn.apply(null, args.concat([function (err) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (typeof console !== 'undefined') {
|
||||
if (err) {
|
||||
if (console.error) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
else if (console[name]) {
|
||||
_each(args, function (x) {
|
||||
console[name](x);
|
||||
});
|
||||
}
|
||||
}
|
||||
}]));
|
||||
};
|
||||
};
|
||||
async.log = _console_fn('log');
|
||||
async.dir = _console_fn('dir');
|
||||
/*async.info = _console_fn('info');
|
||||
async.warn = _console_fn('warn');
|
||||
async.error = _console_fn('error');*/
|
||||
|
||||
async.memoize = function (fn, hasher) {
|
||||
var memo = {};
|
||||
var queues = {};
|
||||
hasher = hasher || function (x) {
|
||||
return x;
|
||||
};
|
||||
var memoized = function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var callback = args.pop();
|
||||
var key = hasher.apply(null, args);
|
||||
if (key in memo) {
|
||||
callback.apply(null, memo[key]);
|
||||
}
|
||||
else if (key in queues) {
|
||||
queues[key].push(callback);
|
||||
}
|
||||
else {
|
||||
queues[key] = [callback];
|
||||
fn.apply(null, args.concat([function () {
|
||||
memo[key] = arguments;
|
||||
var q = queues[key];
|
||||
delete queues[key];
|
||||
for (var i = 0, l = q.length; i < l; i++) {
|
||||
q[i].apply(null, arguments);
|
||||
}
|
||||
}]));
|
||||
}
|
||||
};
|
||||
memoized.memo = memo;
|
||||
memoized.unmemoized = fn;
|
||||
return memoized;
|
||||
};
|
||||
|
||||
async.unmemoize = function (fn) {
|
||||
return function () {
|
||||
return (fn.unmemoized || fn).apply(null, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
async.times = function (count, iterator, callback) {
|
||||
var counter = [];
|
||||
for (var i = 0; i < count; i++) {
|
||||
counter.push(i);
|
||||
}
|
||||
return async.map(counter, iterator, callback);
|
||||
};
|
||||
|
||||
async.timesSeries = function (count, iterator, callback) {
|
||||
var counter = [];
|
||||
for (var i = 0; i < count; i++) {
|
||||
counter.push(i);
|
||||
}
|
||||
return async.mapSeries(counter, iterator, callback);
|
||||
};
|
||||
|
||||
async.compose = function (/* functions... */) {
|
||||
var fns = Array.prototype.reverse.call(arguments);
|
||||
return function () {
|
||||
var that = this;
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var callback = args.pop();
|
||||
async.reduce(fns, args, function (newargs, fn, cb) {
|
||||
fn.apply(that, newargs.concat([function () {
|
||||
var err = arguments[0];
|
||||
var nextargs = Array.prototype.slice.call(arguments, 1);
|
||||
cb(err, nextargs);
|
||||
}]))
|
||||
},
|
||||
function (err, results) {
|
||||
callback.apply(that, [err].concat(results));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
var _applyEach = function (eachfn, fns /*args...*/) {
|
||||
var go = function () {
|
||||
var that = this;
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var callback = args.pop();
|
||||
return eachfn(fns, function (fn, cb) {
|
||||
fn.apply(that, args.concat([cb]));
|
||||
},
|
||||
callback);
|
||||
};
|
||||
if (arguments.length > 2) {
|
||||
var args = Array.prototype.slice.call(arguments, 2);
|
||||
return go.apply(this, args);
|
||||
}
|
||||
else {
|
||||
return go;
|
||||
}
|
||||
};
|
||||
async.applyEach = doParallel(_applyEach);
|
||||
async.applyEachSeries = doSeries(_applyEach);
|
||||
|
||||
async.forever = function (fn, callback) {
|
||||
function next(err) {
|
||||
if (err) {
|
||||
if (callback) {
|
||||
return callback(err);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
fn(next);
|
||||
}
|
||||
next();
|
||||
};
|
||||
|
||||
// AMD / RequireJS
|
||||
if (typeof define !== 'undefined' && define.amd) {
|
||||
define([], function () {
|
||||
return async;
|
||||
});
|
||||
}
|
||||
// Node.js
|
||||
else if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = async;
|
||||
}
|
||||
// included directly via <script> tag
|
||||
else {
|
||||
root.async = async;
|
||||
}
|
||||
|
||||
}());
|
46
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/async/package.json
generated
vendored
Normal file
46
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/async/package.json
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
3
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore
generated
vendored
Normal file
3
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*.un~
|
||||
/node_modules
|
||||
/test/tmp
|
19
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/License
generated
vendored
Normal file
19
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/License
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
7
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile
generated
vendored
Normal file
7
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
SHELL := /bin/bash
|
||||
|
||||
test:
|
||||
@./test/run.js
|
||||
|
||||
.PHONY: test
|
||||
|
132
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md
generated
vendored
Normal file
132
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
# combined-stream
|
||||
|
||||
A stream that emits multiple other streams one after another.
|
||||
|
||||
## Installation
|
||||
|
||||
``` bash
|
||||
npm install combined-stream
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Here is a simple example that shows how you can use combined-stream to combine
|
||||
two files into one:
|
||||
|
||||
``` javascript
|
||||
var CombinedStream = require('combined-stream');
|
||||
var fs = require('fs');
|
||||
|
||||
var combinedStream = CombinedStream.create();
|
||||
combinedStream.append(fs.createReadStream('file1.txt'));
|
||||
combinedStream.append(fs.createReadStream('file2.txt'));
|
||||
|
||||
combinedStream.pipe(fs.createWriteStream('combined.txt'));
|
||||
```
|
||||
|
||||
While the example above works great, it will pause all source streams until
|
||||
they are needed. If you don't want that to happen, you can set `pauseStreams`
|
||||
to `false`:
|
||||
|
||||
``` javascript
|
||||
var CombinedStream = require('combined-stream');
|
||||
var fs = require('fs');
|
||||
|
||||
var combinedStream = CombinedStream.create({pauseStreams: false});
|
||||
combinedStream.append(fs.createReadStream('file1.txt'));
|
||||
combinedStream.append(fs.createReadStream('file2.txt'));
|
||||
|
||||
combinedStream.pipe(fs.createWriteStream('combined.txt'));
|
||||
```
|
||||
|
||||
However, what if you don't have all the source streams yet, or you don't want
|
||||
to allocate the resources (file descriptors, memory, etc.) for them right away?
|
||||
Well, in that case you can simply provide a callback that supplies the stream
|
||||
by calling a `next()` function:
|
||||
|
||||
``` javascript
|
||||
var CombinedStream = require('combined-stream');
|
||||
var fs = require('fs');
|
||||
|
||||
var combinedStream = CombinedStream.create();
|
||||
combinedStream.append(function(next) {
|
||||
next(fs.createReadStream('file1.txt'));
|
||||
});
|
||||
combinedStream.append(function(next) {
|
||||
next(fs.createReadStream('file2.txt'));
|
||||
});
|
||||
|
||||
combinedStream.pipe(fs.createWriteStream('combined.txt'));
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### CombinedStream.create([options])
|
||||
|
||||
Returns a new combined stream object. Available options are:
|
||||
|
||||
* `maxDataSize`
|
||||
* `pauseStreams`
|
||||
|
||||
The effect of those options is described below.
|
||||
|
||||
### combinedStream.pauseStreams = true
|
||||
|
||||
Whether to apply back pressure to the underlaying streams. If set to `false`,
|
||||
the underlaying streams will never be paused. If set to `true`, the
|
||||
underlaying streams will be paused right after being appended, as well as when
|
||||
`delayedStream.pipe()` wants to throttle.
|
||||
|
||||
### combinedStream.maxDataSize = 2 * 1024 * 1024
|
||||
|
||||
The maximum amount of bytes (or characters) to buffer for all source streams.
|
||||
If this value is exceeded, `combinedStream` emits an `'error'` event.
|
||||
|
||||
### combinedStream.dataSize = 0
|
||||
|
||||
The amount of bytes (or characters) currently buffered by `combinedStream`.
|
||||
|
||||
### combinedStream.append(stream)
|
||||
|
||||
Appends the given `stream` to the combinedStream object. If `pauseStreams` is
|
||||
set to `true, this stream will also be paused right away.
|
||||
|
||||
`streams` can also be a function that takes one parameter called `next`. `next`
|
||||
is a function that must be invoked in order to provide the `next` stream, see
|
||||
example above.
|
||||
|
||||
Regardless of how the `stream` is appended, combined-stream always attaches an
|
||||
`'error'` listener to it, so you don't have to do that manually.
|
||||
|
||||
Special case: `stream` can also be a String or Buffer.
|
||||
|
||||
### combinedStream.write(data)
|
||||
|
||||
You should not call this, `combinedStream` takes care of piping the appended
|
||||
streams into itself for you.
|
||||
|
||||
### combinedStream.resume()
|
||||
|
||||
Causes `combinedStream` to start drain the streams it manages. The function is
|
||||
idempotent, and also emits a `'resume'` event each time which usually goes to
|
||||
the stream that is currently being drained.
|
||||
|
||||
### combinedStream.pause();
|
||||
|
||||
If `combinedStream.pauseStreams` is set to `false`, this does nothing.
|
||||
Otherwise a `'pause'` event is emitted, this goes to the stream that is
|
||||
currently being drained, so you can use it to apply back pressure.
|
||||
|
||||
### combinedStream.end();
|
||||
|
||||
Sets `combinedStream.writable` to false, emits an `'end'` event, and removes
|
||||
all streams from the queue.
|
||||
|
||||
### combinedStream.destroy();
|
||||
|
||||
Same as `combinedStream.end()`, except it emits a `'close'` event instead of
|
||||
`'end'`.
|
||||
|
||||
## License
|
||||
|
||||
combined-stream is licensed under the MIT license.
|
185
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js
generated
vendored
Normal file
185
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js
generated
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
var util = require('util');
|
||||
var Stream = require('stream').Stream;
|
||||
var DelayedStream = require('delayed-stream');
|
||||
|
||||
module.exports = CombinedStream;
|
||||
function CombinedStream() {
|
||||
this.writable = false;
|
||||
this.readable = true;
|
||||
this.dataSize = 0;
|
||||
this.maxDataSize = 2 * 1024 * 1024;
|
||||
this.pauseStreams = true;
|
||||
|
||||
this._released = false;
|
||||
this._streams = [];
|
||||
this._currentStream = null;
|
||||
}
|
||||
util.inherits(CombinedStream, Stream);
|
||||
|
||||
CombinedStream.create = function(options) {
|
||||
var combinedStream = new this();
|
||||
|
||||
options = options || {};
|
||||
for (var option in options) {
|
||||
combinedStream[option] = options[option];
|
||||
}
|
||||
|
||||
return combinedStream;
|
||||
};
|
||||
|
||||
CombinedStream.isStreamLike = function(stream) {
|
||||
return (typeof stream !== 'function')
|
||||
&& (typeof stream !== 'string')
|
||||
&& (typeof stream !== 'boolean')
|
||||
&& (typeof stream !== 'number')
|
||||
&& (!Buffer.isBuffer(stream));
|
||||
};
|
||||
|
||||
CombinedStream.prototype.append = function(stream) {
|
||||
var isStreamLike = CombinedStream.isStreamLike(stream);
|
||||
|
||||
if (isStreamLike) {
|
||||
if (!(stream instanceof DelayedStream)) {
|
||||
stream.on('data', this._checkDataSize.bind(this));
|
||||
|
||||
stream = DelayedStream.create(stream, {
|
||||
maxDataSize: Infinity,
|
||||
pauseStream: this.pauseStreams,
|
||||
});
|
||||
}
|
||||
|
||||
this._handleErrors(stream);
|
||||
|
||||
if (this.pauseStreams) {
|
||||
stream.pause();
|
||||
}
|
||||
}
|
||||
|
||||
this._streams.push(stream);
|
||||
return this;
|
||||
};
|
||||
|
||||
CombinedStream.prototype.pipe = function(dest, options) {
|
||||
Stream.prototype.pipe.call(this, dest, options);
|
||||
this.resume();
|
||||
};
|
||||
|
||||
CombinedStream.prototype._getNext = function() {
|
||||
this._currentStream = null;
|
||||
var stream = this._streams.shift();
|
||||
|
||||
|
||||
if (typeof stream == 'undefined') {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof stream !== 'function') {
|
||||
this._pipeNext(stream);
|
||||
return;
|
||||
}
|
||||
|
||||
var getStream = stream;
|
||||
getStream(function(stream) {
|
||||
var isStreamLike = CombinedStream.isStreamLike(stream);
|
||||
if (isStreamLike) {
|
||||
stream.on('data', this._checkDataSize.bind(this));
|
||||
this._handleErrors(stream);
|
||||
}
|
||||
|
||||
this._pipeNext(stream);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
CombinedStream.prototype._pipeNext = function(stream) {
|
||||
this._currentStream = stream;
|
||||
|
||||
var isStreamLike = CombinedStream.isStreamLike(stream);
|
||||
if (isStreamLike) {
|
||||
stream.on('end', this._getNext.bind(this))
|
||||
stream.pipe(this, {end: false});
|
||||
return;
|
||||
}
|
||||
|
||||
var value = stream;
|
||||
this.write(value);
|
||||
this._getNext();
|
||||
};
|
||||
|
||||
CombinedStream.prototype._handleErrors = function(stream) {
|
||||
var self = this;
|
||||
stream.on('error', function(err) {
|
||||
self._emitError(err);
|
||||
});
|
||||
};
|
||||
|
||||
CombinedStream.prototype.write = function(data) {
|
||||
this.emit('data', data);
|
||||
};
|
||||
|
||||
CombinedStream.prototype.pause = function() {
|
||||
if (!this.pauseStreams) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.emit('pause');
|
||||
};
|
||||
|
||||
CombinedStream.prototype.resume = function() {
|
||||
if (!this._released) {
|
||||
this._released = true;
|
||||
this.writable = true;
|
||||
this._getNext();
|
||||
}
|
||||
|
||||
this.emit('resume');
|
||||
};
|
||||
|
||||
CombinedStream.prototype.end = function() {
|
||||
this._reset();
|
||||
this.emit('end');
|
||||
};
|
||||
|
||||
CombinedStream.prototype.destroy = function() {
|
||||
this._reset();
|
||||
this.emit('close');
|
||||
};
|
||||
|
||||
CombinedStream.prototype._reset = function() {
|
||||
this.writable = false;
|
||||
this._streams = [];
|
||||
this._currentStream = null;
|
||||
};
|
||||
|
||||
CombinedStream.prototype._checkDataSize = function() {
|
||||
this._updateDataSize();
|
||||
if (this.dataSize <= this.maxDataSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
var message =
|
||||
'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.'
|
||||
this._emitError(new Error(message));
|
||||
};
|
||||
|
||||
CombinedStream.prototype._updateDataSize = function() {
|
||||
this.dataSize = 0;
|
||||
|
||||
var self = this;
|
||||
this._streams.forEach(function(stream) {
|
||||
if (!stream.dataSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.dataSize += stream.dataSize;
|
||||
});
|
||||
|
||||
if (this._currentStream && this._currentStream.dataSize) {
|
||||
this.dataSize += this._currentStream.dataSize;
|
||||
}
|
||||
};
|
||||
|
||||
CombinedStream.prototype._emitError = function(err) {
|
||||
this._reset();
|
||||
this.emit('error', err);
|
||||
};
|
@@ -0,0 +1,2 @@
|
||||
*.un~
|
||||
/node_modules/*
|
19
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License
generated
vendored
Normal file
19
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
7
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile
generated
vendored
Normal file
7
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
SHELL := /bin/bash
|
||||
|
||||
test:
|
||||
@./test/run.js
|
||||
|
||||
.PHONY: test
|
||||
|
154
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md
generated
vendored
Normal file
154
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
# delayed-stream
|
||||
|
||||
Buffers events from a stream until you are ready to handle them.
|
||||
|
||||
## Installation
|
||||
|
||||
``` bash
|
||||
npm install delayed-stream
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
The following example shows how to write a http echo server that delays its
|
||||
response by 1000 ms.
|
||||
|
||||
``` javascript
|
||||
var DelayedStream = require('delayed-stream');
|
||||
var http = require('http');
|
||||
|
||||
http.createServer(function(req, res) {
|
||||
var delayed = DelayedStream.create(req);
|
||||
|
||||
setTimeout(function() {
|
||||
res.writeHead(200);
|
||||
delayed.pipe(res);
|
||||
}, 1000);
|
||||
});
|
||||
```
|
||||
|
||||
If you are not using `Stream#pipe`, you can also manually release the buffered
|
||||
events by calling `delayedStream.resume()`:
|
||||
|
||||
``` javascript
|
||||
var delayed = DelayedStream.create(req);
|
||||
|
||||
setTimeout(function() {
|
||||
// Emit all buffered events and resume underlaying source
|
||||
delayed.resume();
|
||||
}, 1000);
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
In order to use this meta stream properly, here are a few things you should
|
||||
know about the implementation.
|
||||
|
||||
### Event Buffering / Proxying
|
||||
|
||||
All events of the `source` stream are hijacked by overwriting the `source.emit`
|
||||
method. Until node implements a catch-all event listener, this is the only way.
|
||||
|
||||
However, delayed-stream still continues to emit all events it captures on the
|
||||
`source`, regardless of whether you have released the delayed stream yet or
|
||||
not.
|
||||
|
||||
Upon creation, delayed-stream captures all `source` events and stores them in
|
||||
an internal event buffer. Once `delayedStream.release()` is called, all
|
||||
buffered events are emitted on the `delayedStream`, and the event buffer is
|
||||
cleared. After that, delayed-stream merely acts as a proxy for the underlaying
|
||||
source.
|
||||
|
||||
### Error handling
|
||||
|
||||
Error events on `source` are buffered / proxied just like any other events.
|
||||
However, `delayedStream.create` attaches a no-op `'error'` listener to the
|
||||
`source`. This way you only have to handle errors on the `delayedStream`
|
||||
object, rather than in two places.
|
||||
|
||||
### Buffer limits
|
||||
|
||||
delayed-stream provides a `maxDataSize` property that can be used to limit
|
||||
the amount of data being buffered. In order to protect you from bad `source`
|
||||
streams that don't react to `source.pause()`, this feature is enabled by
|
||||
default.
|
||||
|
||||
## API
|
||||
|
||||
### DelayedStream.create(source, [options])
|
||||
|
||||
Returns a new `delayedStream`. Available options are:
|
||||
|
||||
* `pauseStream`
|
||||
* `maxDataSize`
|
||||
|
||||
The description for those properties can be found below.
|
||||
|
||||
### delayedStream.source
|
||||
|
||||
The `source` stream managed by this object. This is useful if you are
|
||||
passing your `delayedStream` around, and you still want to access properties
|
||||
on the `source` object.
|
||||
|
||||
### delayedStream.pauseStream = true
|
||||
|
||||
Whether to pause the underlaying `source` when calling
|
||||
`DelayedStream.create()`. Modifying this property afterwards has no effect.
|
||||
|
||||
### delayedStream.maxDataSize = 1024 * 1024
|
||||
|
||||
The amount of data to buffer before emitting an `error`.
|
||||
|
||||
If the underlaying source is emitting `Buffer` objects, the `maxDataSize`
|
||||
refers to bytes.
|
||||
|
||||
If the underlaying source is emitting JavaScript strings, the size refers to
|
||||
characters.
|
||||
|
||||
If you know what you are doing, you can set this property to `Infinity` to
|
||||
disable this feature. You can also modify this property during runtime.
|
||||
|
||||
### delayedStream.maxDataSize = 1024 * 1024
|
||||
|
||||
The amount of data to buffer before emitting an `error`.
|
||||
|
||||
If the underlaying source is emitting `Buffer` objects, the `maxDataSize`
|
||||
refers to bytes.
|
||||
|
||||
If the underlaying source is emitting JavaScript strings, the size refers to
|
||||
characters.
|
||||
|
||||
If you know what you are doing, you can set this property to `Infinity` to
|
||||
disable this feature.
|
||||
|
||||
### delayedStream.dataSize = 0
|
||||
|
||||
The amount of data buffered so far.
|
||||
|
||||
### delayedStream.readable
|
||||
|
||||
An ECMA5 getter that returns the value of `source.readable`.
|
||||
|
||||
### delayedStream.resume()
|
||||
|
||||
If the `delayedStream` has not been released so far, `delayedStream.release()`
|
||||
is called.
|
||||
|
||||
In either case, `source.resume()` is called.
|
||||
|
||||
### delayedStream.pause()
|
||||
|
||||
Calls `source.pause()`.
|
||||
|
||||
### delayedStream.pipe(dest)
|
||||
|
||||
Calls `delayedStream.resume()` and then proxies the arguments to `source.pipe`.
|
||||
|
||||
### delayedStream.release()
|
||||
|
||||
Emits and clears all events that have been buffered up so far. This does not
|
||||
resume the underlaying source, use `delayedStream.resume()` instead.
|
||||
|
||||
## License
|
||||
|
||||
delayed-stream is licensed under the MIT license.
|
@@ -0,0 +1,99 @@
|
||||
var Stream = require('stream').Stream;
|
||||
var util = require('util');
|
||||
|
||||
module.exports = DelayedStream;
|
||||
function DelayedStream() {
|
||||
this.source = null;
|
||||
this.dataSize = 0;
|
||||
this.maxDataSize = 1024 * 1024;
|
||||
this.pauseStream = true;
|
||||
|
||||
this._maxDataSizeExceeded = false;
|
||||
this._released = false;
|
||||
this._bufferedEvents = [];
|
||||
}
|
||||
util.inherits(DelayedStream, Stream);
|
||||
|
||||
DelayedStream.create = function(source, options) {
|
||||
var delayedStream = new this();
|
||||
|
||||
options = options || {};
|
||||
for (var option in options) {
|
||||
delayedStream[option] = options[option];
|
||||
}
|
||||
|
||||
delayedStream.source = source;
|
||||
|
||||
var realEmit = source.emit;
|
||||
source.emit = function() {
|
||||
delayedStream._handleEmit(arguments);
|
||||
return realEmit.apply(source, arguments);
|
||||
};
|
||||
|
||||
source.on('error', function() {});
|
||||
if (delayedStream.pauseStream) {
|
||||
source.pause();
|
||||
}
|
||||
|
||||
return delayedStream;
|
||||
};
|
||||
|
||||
DelayedStream.prototype.__defineGetter__('readable', function() {
|
||||
return this.source.readable;
|
||||
});
|
||||
|
||||
DelayedStream.prototype.resume = function() {
|
||||
if (!this._released) {
|
||||
this.release();
|
||||
}
|
||||
|
||||
this.source.resume();
|
||||
};
|
||||
|
||||
DelayedStream.prototype.pause = function() {
|
||||
this.source.pause();
|
||||
};
|
||||
|
||||
DelayedStream.prototype.release = function() {
|
||||
this._released = true;
|
||||
|
||||
this._bufferedEvents.forEach(function(args) {
|
||||
this.emit.apply(this, args);
|
||||
}.bind(this));
|
||||
this._bufferedEvents = [];
|
||||
};
|
||||
|
||||
DelayedStream.prototype.pipe = function() {
|
||||
var r = Stream.prototype.pipe.apply(this, arguments);
|
||||
this.resume();
|
||||
return r;
|
||||
};
|
||||
|
||||
DelayedStream.prototype._handleEmit = function(args) {
|
||||
if (this._released) {
|
||||
this.emit.apply(this, args);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[0] === 'data') {
|
||||
this.dataSize += args[1].length;
|
||||
this._checkIfMaxDataSizeExceeded();
|
||||
}
|
||||
|
||||
this._bufferedEvents.push(args);
|
||||
};
|
||||
|
||||
DelayedStream.prototype._checkIfMaxDataSizeExceeded = function() {
|
||||
if (this._maxDataSizeExceeded) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.dataSize <= this.maxDataSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._maxDataSizeExceeded = true;
|
||||
var message =
|
||||
'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.'
|
||||
this.emit('error', new Error(message));
|
||||
};
|
32
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json
generated
vendored
Normal file
32
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"author": {
|
||||
"name": "Felix Geisendörfer",
|
||||
"email": "felix@debuggable.com",
|
||||
"url": "http://debuggable.com/"
|
||||
},
|
||||
"name": "delayed-stream",
|
||||
"description": "Buffers events from a stream until you are ready to handle them.",
|
||||
"version": "0.0.5",
|
||||
"homepage": "https://github.com/felixge/node-delayed-stream",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/felixge/node-delayed-stream.git"
|
||||
},
|
||||
"main": "./lib/delayed_stream",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"fake": "0.2.0",
|
||||
"far": "0.0.1"
|
||||
},
|
||||
"readme": "# delayed-stream\n\nBuffers events from a stream until you are ready to handle them.\n\n## Installation\n\n``` bash\nnpm install delayed-stream\n```\n\n## Usage\n\nThe following example shows how to write a http echo server that delays its\nresponse by 1000 ms.\n\n``` javascript\nvar DelayedStream = require('delayed-stream');\nvar http = require('http');\n\nhttp.createServer(function(req, res) {\n var delayed = DelayedStream.create(req);\n\n setTimeout(function() {\n res.writeHead(200);\n delayed.pipe(res);\n }, 1000);\n});\n```\n\nIf you are not using `Stream#pipe`, you can also manually release the buffered\nevents by calling `delayedStream.resume()`:\n\n``` javascript\nvar delayed = DelayedStream.create(req);\n\nsetTimeout(function() {\n // Emit all buffered events and resume underlaying source\n delayed.resume();\n}, 1000);\n```\n\n## Implementation\n\nIn order to use this meta stream properly, here are a few things you should\nknow about the implementation.\n\n### Event Buffering / Proxying\n\nAll events of the `source` stream are hijacked by overwriting the `source.emit`\nmethod. Until node implements a catch-all event listener, this is the only way.\n\nHowever, delayed-stream still continues to emit all events it captures on the\n`source`, regardless of whether you have released the delayed stream yet or\nnot.\n\nUpon creation, delayed-stream captures all `source` events and stores them in\nan internal event buffer. Once `delayedStream.release()` is called, all\nbuffered events are emitted on the `delayedStream`, and the event buffer is\ncleared. After that, delayed-stream merely acts as a proxy for the underlaying\nsource.\n\n### Error handling\n\nError events on `source` are buffered / proxied just like any other events.\nHowever, `delayedStream.create` attaches a no-op `'error'` listener to the\n`source`. This way you only have to handle errors on the `delayedStream`\nobject, rather than in two places.\n\n### Buffer limits\n\ndelayed-stream provides a `maxDataSize` property that can be used to limit\nthe amount of data being buffered. In order to protect you from bad `source`\nstreams that don't react to `source.pause()`, this feature is enabled by\ndefault.\n\n## API\n\n### DelayedStream.create(source, [options])\n\nReturns a new `delayedStream`. Available options are:\n\n* `pauseStream`\n* `maxDataSize`\n\nThe description for those properties can be found below.\n\n### delayedStream.source\n\nThe `source` stream managed by this object. This is useful if you are\npassing your `delayedStream` around, and you still want to access properties\non the `source` object.\n\n### delayedStream.pauseStream = true\n\nWhether to pause the underlaying `source` when calling\n`DelayedStream.create()`. Modifying this property afterwards has no effect.\n\n### delayedStream.maxDataSize = 1024 * 1024\n\nThe amount of data to buffer before emitting an `error`.\n\nIf the underlaying source is emitting `Buffer` objects, the `maxDataSize`\nrefers to bytes.\n\nIf the underlaying source is emitting JavaScript strings, the size refers to\ncharacters.\n\nIf you know what you are doing, you can set this property to `Infinity` to\ndisable this feature. You can also modify this property during runtime.\n\n### delayedStream.maxDataSize = 1024 * 1024\n\nThe amount of data to buffer before emitting an `error`.\n\nIf the underlaying source is emitting `Buffer` objects, the `maxDataSize`\nrefers to bytes.\n\nIf the underlaying source is emitting JavaScript strings, the size refers to\ncharacters.\n\nIf you know what you are doing, you can set this property to `Infinity` to\ndisable this feature.\n\n### delayedStream.dataSize = 0\n\nThe amount of data buffered so far.\n\n### delayedStream.readable\n\nAn ECMA5 getter that returns the value of `source.readable`.\n\n### delayedStream.resume()\n\nIf the `delayedStream` has not been released so far, `delayedStream.release()`\nis called.\n\nIn either case, `source.resume()` is called.\n\n### delayedStream.pause()\n\nCalls `source.pause()`.\n\n### delayedStream.pipe(dest)\n\nCalls `delayedStream.resume()` and then proxies the arguments to `source.pipe`.\n\n### delayedStream.release()\n\nEmits and clears all events that have been buffered up so far. This does not\nresume the underlaying source, use `delayedStream.resume()` instead.\n\n## License\n\ndelayed-stream is licensed under the MIT license.\n",
|
||||
"readmeFilename": "Readme.md",
|
||||
"_id": "delayed-stream@0.0.5",
|
||||
"dist": {
|
||||
"shasum": "66839603c076296710bcc7f2e84ebd3348ae6343"
|
||||
},
|
||||
"_from": "delayed-stream@0.0.5",
|
||||
"_resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz"
|
||||
}
|
@@ -0,0 +1,6 @@
|
||||
var common = module.exports;
|
||||
|
||||
common.DelayedStream = require('..');
|
||||
common.assert = require('assert');
|
||||
common.fake = require('fake');
|
||||
common.PORT = 49252;
|
@@ -0,0 +1,38 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var DelayedStream = common.DelayedStream;
|
||||
var http = require('http');
|
||||
|
||||
var UPLOAD = new Buffer(10 * 1024 * 1024);
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
var delayed = DelayedStream.create(req, {maxDataSize: UPLOAD.length});
|
||||
|
||||
setTimeout(function() {
|
||||
res.writeHead(200);
|
||||
delayed.pipe(res);
|
||||
}, 10);
|
||||
});
|
||||
server.listen(common.PORT, function() {
|
||||
var request = http.request({
|
||||
method: 'POST',
|
||||
port: common.PORT,
|
||||
});
|
||||
|
||||
request.write(UPLOAD);
|
||||
request.end();
|
||||
|
||||
request.on('response', function(res) {
|
||||
var received = 0;
|
||||
res
|
||||
.on('data', function(chunk) {
|
||||
received += chunk.length;
|
||||
})
|
||||
.on('end', function() {
|
||||
assert.equal(received, UPLOAD.length);
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -0,0 +1,21 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var fake = common.fake.create();
|
||||
var DelayedStream = common.DelayedStream;
|
||||
var Stream = require('stream').Stream;
|
||||
|
||||
(function testAutoPause() {
|
||||
var source = new Stream();
|
||||
|
||||
fake.expect(source, 'pause', 1);
|
||||
var delayedStream = DelayedStream.create(source);
|
||||
fake.verify();
|
||||
})();
|
||||
|
||||
(function testDisableAutoPause() {
|
||||
var source = new Stream();
|
||||
fake.expect(source, 'pause', 0);
|
||||
|
||||
var delayedStream = DelayedStream.create(source, {pauseStream: false});
|
||||
fake.verify();
|
||||
})();
|
@@ -0,0 +1,14 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var fake = common.fake.create();
|
||||
var DelayedStream = common.DelayedStream;
|
||||
var Stream = require('stream').Stream;
|
||||
|
||||
(function testDelayEventsUntilResume() {
|
||||
var source = new Stream();
|
||||
var delayedStream = DelayedStream.create(source, {pauseStream: false});
|
||||
|
||||
fake.expect(source, 'pause');
|
||||
delayedStream.pause();
|
||||
fake.verify();
|
||||
})();
|
@@ -0,0 +1,48 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var fake = common.fake.create();
|
||||
var DelayedStream = common.DelayedStream;
|
||||
var Stream = require('stream').Stream;
|
||||
|
||||
(function testDelayEventsUntilResume() {
|
||||
var source = new Stream();
|
||||
var delayedStream = DelayedStream.create(source, {pauseStream: false});
|
||||
|
||||
// delayedStream must not emit until we resume
|
||||
fake.expect(delayedStream, 'emit', 0);
|
||||
|
||||
// but our original source must emit
|
||||
var params = [];
|
||||
source.on('foo', function(param) {
|
||||
params.push(param);
|
||||
});
|
||||
|
||||
source.emit('foo', 1);
|
||||
source.emit('foo', 2);
|
||||
|
||||
// Make sure delayedStream did not emit, and source did
|
||||
assert.deepEqual(params, [1, 2]);
|
||||
fake.verify();
|
||||
|
||||
// After resume, delayedStream must playback all events
|
||||
fake
|
||||
.stub(delayedStream, 'emit')
|
||||
.times(Infinity)
|
||||
.withArg(1, 'newListener');
|
||||
fake.expect(delayedStream, 'emit', ['foo', 1]);
|
||||
fake.expect(delayedStream, 'emit', ['foo', 2]);
|
||||
fake.expect(source, 'resume');
|
||||
|
||||
delayedStream.resume();
|
||||
fake.verify();
|
||||
|
||||
// Calling resume again will delegate to source
|
||||
fake.expect(source, 'resume');
|
||||
delayedStream.resume();
|
||||
fake.verify();
|
||||
|
||||
// Emitting more events directly leads to them being emitted
|
||||
fake.expect(delayedStream, 'emit', ['foo', 3]);
|
||||
source.emit('foo', 3);
|
||||
fake.verify();
|
||||
})();
|
@@ -0,0 +1,15 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var fake = common.fake.create();
|
||||
var DelayedStream = common.DelayedStream;
|
||||
var Stream = require('stream').Stream;
|
||||
|
||||
(function testHandleSourceErrors() {
|
||||
var source = new Stream();
|
||||
var delayedStream = DelayedStream.create(source, {pauseStream: false});
|
||||
|
||||
// We deal with this by attaching a no-op listener to 'error' on the source
|
||||
// when creating a new DelayedStream. This way error events on the source
|
||||
// won't throw.
|
||||
source.emit('error', new Error('something went wrong'));
|
||||
})();
|
@@ -0,0 +1,18 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var fake = common.fake.create();
|
||||
var DelayedStream = common.DelayedStream;
|
||||
var Stream = require('stream').Stream;
|
||||
|
||||
(function testMaxDataSize() {
|
||||
var source = new Stream();
|
||||
var delayedStream = DelayedStream.create(source, {maxDataSize: 1024, pauseStream: false});
|
||||
|
||||
source.emit('data', new Buffer(1024));
|
||||
|
||||
fake
|
||||
.expect(delayedStream, 'emit')
|
||||
.withArg(1, 'error');
|
||||
source.emit('data', new Buffer(1));
|
||||
fake.verify();
|
||||
})();
|
@@ -0,0 +1,13 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var fake = common.fake.create();
|
||||
var DelayedStream = common.DelayedStream;
|
||||
var Stream = require('stream').Stream;
|
||||
|
||||
(function testPipeReleases() {
|
||||
var source = new Stream();
|
||||
var delayedStream = DelayedStream.create(source, {pauseStream: false});
|
||||
|
||||
fake.expect(delayedStream, 'resume');
|
||||
delayedStream.pipe(new Stream());
|
||||
})();
|
@@ -0,0 +1,13 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var fake = common.fake.create();
|
||||
var DelayedStream = common.DelayedStream;
|
||||
var Stream = require('stream').Stream;
|
||||
|
||||
(function testProxyReadableProperty() {
|
||||
var source = new Stream();
|
||||
var delayedStream = DelayedStream.create(source, {pauseStream: false});
|
||||
|
||||
source.readable = fake.value('source.readable');
|
||||
assert.strictEqual(delayedStream.readable, source.readable);
|
||||
})();
|
7
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js
generated
vendored
Executable file
7
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js
generated
vendored
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
var far = require('far').create();
|
||||
|
||||
far.add(__dirname);
|
||||
far.include(/test-.*\.js$/);
|
||||
|
||||
far.execute();
|
29
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json
generated
vendored
Normal file
29
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"author": {
|
||||
"name": "Felix Geisendörfer",
|
||||
"email": "felix@debuggable.com",
|
||||
"url": "http://debuggable.com/"
|
||||
},
|
||||
"name": "combined-stream",
|
||||
"description": "A stream that emits multiple other streams one after another.",
|
||||
"version": "0.0.4",
|
||||
"homepage": "https://github.com/felixge/node-combined-stream",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/felixge/node-combined-stream.git"
|
||||
},
|
||||
"main": "./lib/combined_stream",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
"delayed-stream": "0.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"far": "0.0.1"
|
||||
},
|
||||
"readme": "# combined-stream\n\nA stream that emits multiple other streams one after another.\n\n## Installation\n\n``` bash\nnpm install combined-stream\n```\n\n## Usage\n\nHere is a simple example that shows how you can use combined-stream to combine\ntwo files into one:\n\n``` javascript\nvar CombinedStream = require('combined-stream');\nvar fs = require('fs');\n\nvar combinedStream = CombinedStream.create();\ncombinedStream.append(fs.createReadStream('file1.txt'));\ncombinedStream.append(fs.createReadStream('file2.txt'));\n\ncombinedStream.pipe(fs.createWriteStream('combined.txt'));\n```\n\nWhile the example above works great, it will pause all source streams until\nthey are needed. If you don't want that to happen, you can set `pauseStreams`\nto `false`:\n\n``` javascript\nvar CombinedStream = require('combined-stream');\nvar fs = require('fs');\n\nvar combinedStream = CombinedStream.create({pauseStreams: false});\ncombinedStream.append(fs.createReadStream('file1.txt'));\ncombinedStream.append(fs.createReadStream('file2.txt'));\n\ncombinedStream.pipe(fs.createWriteStream('combined.txt'));\n```\n\nHowever, what if you don't have all the source streams yet, or you don't want\nto allocate the resources (file descriptors, memory, etc.) for them right away?\nWell, in that case you can simply provide a callback that supplies the stream\nby calling a `next()` function:\n\n``` javascript\nvar CombinedStream = require('combined-stream');\nvar fs = require('fs');\n\nvar combinedStream = CombinedStream.create();\ncombinedStream.append(function(next) {\n next(fs.createReadStream('file1.txt'));\n});\ncombinedStream.append(function(next) {\n next(fs.createReadStream('file2.txt'));\n});\n\ncombinedStream.pipe(fs.createWriteStream('combined.txt'));\n```\n\n## API\n\n### CombinedStream.create([options])\n\nReturns a new combined stream object. Available options are:\n\n* `maxDataSize`\n* `pauseStreams`\n\nThe effect of those options is described below.\n\n### combinedStream.pauseStreams = true\n\nWhether to apply back pressure to the underlaying streams. If set to `false`,\nthe underlaying streams will never be paused. If set to `true`, the\nunderlaying streams will be paused right after being appended, as well as when\n`delayedStream.pipe()` wants to throttle.\n\n### combinedStream.maxDataSize = 2 * 1024 * 1024\n\nThe maximum amount of bytes (or characters) to buffer for all source streams.\nIf this value is exceeded, `combinedStream` emits an `'error'` event.\n\n### combinedStream.dataSize = 0\n\nThe amount of bytes (or characters) currently buffered by `combinedStream`.\n\n### combinedStream.append(stream)\n\nAppends the given `stream` to the combinedStream object. If `pauseStreams` is\nset to `true, this stream will also be paused right away.\n\n`streams` can also be a function that takes one parameter called `next`. `next`\nis a function that must be invoked in order to provide the `next` stream, see\nexample above.\n\nRegardless of how the `stream` is appended, combined-stream always attaches an\n`'error'` listener to it, so you don't have to do that manually.\n\nSpecial case: `stream` can also be a String or Buffer.\n\n### combinedStream.write(data)\n\nYou should not call this, `combinedStream` takes care of piping the appended\nstreams into itself for you.\n\n### combinedStream.resume()\n\nCauses `combinedStream` to start drain the streams it manages. The function is\nidempotent, and also emits a `'resume'` event each time which usually goes to\nthe stream that is currently being drained.\n\n### combinedStream.pause();\n\nIf `combinedStream.pauseStreams` is set to `false`, this does nothing.\nOtherwise a `'pause'` event is emitted, this goes to the stream that is\ncurrently being drained, so you can use it to apply back pressure.\n\n### combinedStream.end();\n\nSets `combinedStream.writable` to false, emits an `'end'` event, and removes\nall streams from the queue.\n\n### combinedStream.destroy();\n\nSame as `combinedStream.end()`, except it emits a `'close'` event instead of\n`'end'`.\n\n## License\n\ncombined-stream is licensed under the MIT license.\n",
|
||||
"readmeFilename": "Readme.md",
|
||||
"_id": "combined-stream@0.0.4",
|
||||
"_from": "combined-stream@~0.0.4"
|
||||
}
|
23
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js
generated
vendored
Normal file
23
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
var common = module.exports;
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var root = path.join(__dirname, '..');
|
||||
|
||||
common.dir = {
|
||||
fixture: root + '/test/fixture',
|
||||
tmp: root + '/test/tmp',
|
||||
};
|
||||
|
||||
// Create tmp directory if it does not exist
|
||||
// Not using fs.exists so as to be node 0.6.x compatible
|
||||
try {
|
||||
fs.statSync(common.dir.tmp);
|
||||
}
|
||||
catch (e) {
|
||||
// Dir does not exist
|
||||
fs.mkdirSync(common.dir.tmp);
|
||||
}
|
||||
|
||||
common.CombinedStream = require(root);
|
||||
common.assert = require('assert');
|
256
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt
generated
vendored
Normal file
256
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt
generated
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
||||
10101010101010101010101010101010101010101010101010101010101010101010101010101010
|
||||
01010101010101010101010101010101010101010101010101010101010101010101010101010101
|
256
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt
generated
vendored
Normal file
256
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt
generated
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
||||
20202020202020202020202020202020202020202020202020202020202020202020202020202020
|
||||
02020202020202020202020202020202020202020202020202020202020202020202020202020202
|
27
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js
generated
vendored
Normal file
27
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var CombinedStream = common.CombinedStream;
|
||||
var fs = require('fs');
|
||||
|
||||
var FILE1 = common.dir.fixture + '/file1.txt';
|
||||
var FILE2 = common.dir.fixture + '/file2.txt';
|
||||
var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2);
|
||||
|
||||
(function testDelayedStreams() {
|
||||
var combinedStream = CombinedStream.create();
|
||||
combinedStream.append(function(next) {
|
||||
next(fs.createReadStream(FILE1));
|
||||
});
|
||||
combinedStream.append(function(next) {
|
||||
next(fs.createReadStream(FILE2));
|
||||
});
|
||||
|
||||
var tmpFile = common.dir.tmp + '/combined.txt';
|
||||
var dest = fs.createWriteStream(tmpFile);
|
||||
combinedStream.pipe(dest);
|
||||
|
||||
dest.on('end', function() {
|
||||
var written = fs.readFileSync(tmpFile, 'utf8');
|
||||
assert.strictEqual(written, EXPECTED);
|
||||
});
|
||||
})();
|
34
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js
generated
vendored
Normal file
34
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var CombinedStream = common.CombinedStream;
|
||||
|
||||
(function testDataSizeGetter() {
|
||||
var combinedStream = CombinedStream.create();
|
||||
|
||||
assert.strictEqual(combinedStream.dataSize, 0);
|
||||
|
||||
// Test one stream
|
||||
combinedStream._streams.push({dataSize: 10});
|
||||
combinedStream._updateDataSize();
|
||||
assert.strictEqual(combinedStream.dataSize, 10);
|
||||
|
||||
// Test two streams
|
||||
combinedStream._streams.push({dataSize: 23});
|
||||
combinedStream._updateDataSize();
|
||||
assert.strictEqual(combinedStream.dataSize, 33);
|
||||
|
||||
// Test currentStream
|
||||
combinedStream._currentStream = {dataSize: 20};
|
||||
combinedStream._updateDataSize();
|
||||
assert.strictEqual(combinedStream.dataSize, 53);
|
||||
|
||||
// Test currentStream without dataSize
|
||||
combinedStream._currentStream = {};
|
||||
combinedStream._updateDataSize();
|
||||
assert.strictEqual(combinedStream.dataSize, 33);
|
||||
|
||||
// Test stream function
|
||||
combinedStream._streams.push(function() {});
|
||||
combinedStream._updateDataSize();
|
||||
assert.strictEqual(combinedStream.dataSize, 33);
|
||||
})();
|
@@ -0,0 +1,38 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var CombinedStream = common.CombinedStream;
|
||||
var fs = require('fs');
|
||||
|
||||
var FILE1 = common.dir.fixture + '/file1.txt';
|
||||
var BUFFER = new Buffer('Bacon is delicious');
|
||||
var FILE2 = common.dir.fixture + '/file2.txt';
|
||||
var STRING = 'The € kicks the $\'s ass!';
|
||||
|
||||
var EXPECTED =
|
||||
fs.readFileSync(FILE1)
|
||||
+ BUFFER
|
||||
+ fs.readFileSync(FILE2)
|
||||
+ STRING;
|
||||
var GOT;
|
||||
|
||||
(function testDelayedStreams() {
|
||||
var combinedStream = CombinedStream.create();
|
||||
combinedStream.append(fs.createReadStream(FILE1));
|
||||
combinedStream.append(BUFFER);
|
||||
combinedStream.append(fs.createReadStream(FILE2));
|
||||
combinedStream.append(function(next) {
|
||||
next(STRING);
|
||||
});
|
||||
|
||||
var tmpFile = common.dir.tmp + '/combined-file1-buffer-file2-string.txt';
|
||||
var dest = fs.createWriteStream(tmpFile);
|
||||
combinedStream.pipe(dest);
|
||||
|
||||
dest.on('close', function() {
|
||||
GOT = fs.readFileSync(tmpFile, 'utf8');
|
||||
});
|
||||
})();
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.strictEqual(GOT, EXPECTED);
|
||||
});
|
35
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js
generated
vendored
Normal file
35
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var CombinedStream = common.CombinedStream;
|
||||
var fs = require('fs');
|
||||
|
||||
var FILE1 = common.dir.fixture + '/file1.txt';
|
||||
var FILE2 = common.dir.fixture + '/file2.txt';
|
||||
var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2);
|
||||
var GOT;
|
||||
|
||||
(function testDelayedStreams() {
|
||||
var combinedStream = CombinedStream.create();
|
||||
combinedStream.append(fs.createReadStream(FILE1));
|
||||
combinedStream.append(fs.createReadStream(FILE2));
|
||||
|
||||
var stream1 = combinedStream._streams[0];
|
||||
var stream2 = combinedStream._streams[1];
|
||||
|
||||
stream1.on('end', function() {
|
||||
assert.equal(stream2.dataSize, 0);
|
||||
});
|
||||
|
||||
var tmpFile = common.dir.tmp + '/combined.txt';
|
||||
var dest = fs.createWriteStream(tmpFile);
|
||||
combinedStream.pipe(dest);
|
||||
|
||||
dest.on('close', function() {
|
||||
GOT = fs.readFileSync(tmpFile, 'utf8');
|
||||
});
|
||||
})();
|
||||
|
||||
process.on('exit', function() {
|
||||
console.error(GOT.length, EXPECTED.length);
|
||||
assert.strictEqual(GOT, EXPECTED);
|
||||
});
|
39
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js
generated
vendored
Normal file
39
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var CombinedStream = common.CombinedStream;
|
||||
var util = require('util');
|
||||
var Stream = require('stream').Stream;
|
||||
|
||||
var s = CombinedStream.create();
|
||||
|
||||
|
||||
function StringStream(){
|
||||
this.writable=true;
|
||||
this.str=""
|
||||
}
|
||||
util.inherits(StringStream,Stream);
|
||||
|
||||
StringStream.prototype.write=function(chunk,encoding){
|
||||
this.str+=chunk.toString();
|
||||
this.emit('data',chunk);
|
||||
}
|
||||
|
||||
StringStream.prototype.end=function(chunk,encoding){
|
||||
this.emit('end');
|
||||
}
|
||||
|
||||
StringStream.prototype.toString=function(){
|
||||
return this.str;
|
||||
}
|
||||
|
||||
|
||||
s.append("foo.");
|
||||
s.append("");
|
||||
s.append("bar");
|
||||
|
||||
var ss = new StringStream();
|
||||
|
||||
s.pipe(ss);
|
||||
s.resume();
|
||||
|
||||
assert.equal(ss.toString(),"foo.bar");
|
17
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js
generated
vendored
Normal file
17
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
var fs = require('fs');
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var CombinedStream = common.CombinedStream;
|
||||
var FILE1 = common.dir.fixture + '/file1.txt';
|
||||
var fileStream = fs.createReadStream(FILE1);
|
||||
|
||||
var foo = function(){};
|
||||
|
||||
(function testIsStreamLike() {
|
||||
assert(! CombinedStream.isStreamLike(true));
|
||||
assert(! CombinedStream.isStreamLike("I am a string"));
|
||||
assert(! CombinedStream.isStreamLike(7));
|
||||
assert(! CombinedStream.isStreamLike(foo));
|
||||
|
||||
assert(CombinedStream.isStreamLike(fileStream));
|
||||
})();
|
24
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js
generated
vendored
Normal file
24
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var CombinedStream = common.CombinedStream;
|
||||
var fs = require('fs');
|
||||
|
||||
var FILE1 = common.dir.fixture + '/file1.txt';
|
||||
var FILE2 = common.dir.fixture + '/file2.txt';
|
||||
var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2);
|
||||
|
||||
(function testDelayedStreams() {
|
||||
var combinedStream = CombinedStream.create({pauseStreams: false, maxDataSize: 20736});
|
||||
combinedStream.append(fs.createReadStream(FILE1));
|
||||
combinedStream.append(fs.createReadStream(FILE2));
|
||||
|
||||
var gotErr = null;
|
||||
combinedStream.on('error', function(err) {
|
||||
gotErr = err;
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.ok(gotErr);
|
||||
assert.ok(gotErr.message.match(/bytes/));
|
||||
});
|
||||
})();
|
30
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js
generated
vendored
Normal file
30
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
var common = require('../common');
|
||||
var assert = common.assert;
|
||||
var CombinedStream = common.CombinedStream;
|
||||
var fs = require('fs');
|
||||
|
||||
var FILE1 = common.dir.fixture + '/file1.txt';
|
||||
var FILE2 = common.dir.fixture + '/file2.txt';
|
||||
var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2);
|
||||
|
||||
(function testDelayedStreams() {
|
||||
var combinedStream = CombinedStream.create({pauseStreams: false});
|
||||
combinedStream.append(fs.createReadStream(FILE1));
|
||||
combinedStream.append(fs.createReadStream(FILE2));
|
||||
|
||||
var stream1 = combinedStream._streams[0];
|
||||
var stream2 = combinedStream._streams[1];
|
||||
|
||||
stream1.on('end', function() {
|
||||
assert.ok(stream2.dataSize > 0);
|
||||
});
|
||||
|
||||
var tmpFile = common.dir.tmp + '/combined.txt';
|
||||
var dest = fs.createWriteStream(tmpFile);
|
||||
combinedStream.pipe(dest);
|
||||
|
||||
dest.on('end', function() {
|
||||
var written = fs.readFileSync(tmpFile, 'utf8');
|
||||
assert.strictEqual(written, EXPECTED);
|
||||
});
|
||||
})();
|
7
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js
generated
vendored
Executable file
7
node_modules/tabletop/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js
generated
vendored
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
var far = require('far').create();
|
||||
|
||||
far.add(__dirname);
|
||||
far.include(/test-.*\.js$/);
|
||||
|
||||
far.execute();
|
40
node_modules/tabletop/node_modules/request/node_modules/form-data/package.json
generated
vendored
Normal file
40
node_modules/tabletop/node_modules/request/node_modules/form-data/package.json
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"author": {
|
||||
"name": "Felix Geisendörfer",
|
||||
"email": "felix@debuggable.com",
|
||||
"url": "http://debuggable.com/"
|
||||
},
|
||||
"name": "form-data",
|
||||
"description": "A module to create readable `\"multipart/form-data\"` streams. Can be used to submit forms and file uploads to other web applications.",
|
||||
"version": "0.0.10",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/felixge/node-form-data.git"
|
||||
},
|
||||
"main": "./lib/form_data",
|
||||
"scripts": {
|
||||
"test": "node test/run.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"combined-stream": "~0.0.4",
|
||||
"mime": "~1.2.2",
|
||||
"async": "~0.2.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"fake": "~0.2.1",
|
||||
"far": "~0.0.7",
|
||||
"formidable": "~1.0.13",
|
||||
"request": "~2.16.6"
|
||||
},
|
||||
"readme": "# Form-Data [](https://travis-ci.org/alexindigo/node-form-data) [](https://gemnasium.com/alexindigo/node-form-data)\n\nA module to create readable `\"multipart/form-data\"` streams. Can be used to\nsubmit forms and file uploads to other web applications.\n\nThe API of this module is inspired by the\n[XMLHttpRequest-2 FormData Interface][xhr2-fd].\n\n[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface\n\n## Install\n\n```\nnpm install form-data\n```\n\n## Usage\n\nIn this example we are constructing a form with 3 fields that contain a string,\na buffer and a file stream.\n\n``` javascript\nvar FormData = require('form-data');\nvar fs = require('fs');\n\nvar form = new FormData();\nform.append('my_field', 'my value');\nform.append('my_buffer', new Buffer(10));\nform.append('my_file', fs.createReadStream('/foo/bar.jpg'));\n```\n\nAlso you can use http-response stream:\n\n``` javascript\nvar FormData = require('form-data');\nvar http = require('http');\n\nvar form = new FormData();\n\nhttp.request('http://nodejs.org/images/logo.png', function(response) {\n form.append('my_field', 'my value');\n form.append('my_buffer', new Buffer(10));\n form.append('my_logo', response);\n});\n```\n\nOr @mikeal's request stream:\n\n``` javascript\nvar FormData = require('form-data');\nvar request = require('request');\n\nvar form = new FormData();\n\nform.append('my_field', 'my value');\nform.append('my_buffer', new Buffer(10));\nform.append('my_logo', request('http://nodejs.org/images/logo.png'));\n```\n\nIn order to submit this form to a web application, you can use node's http\nclient interface:\n\n``` javascript\nvar http = require('http');\n\nvar request = http.request({\n method: 'post',\n host: 'example.org',\n path: '/upload',\n headers: form.getHeaders()\n});\n\nform.pipe(request);\n\nrequest.on('response', function(res) {\n console.log(res.statusCode);\n});\n```\n\nOr if you would prefer the `'Content-Length'` header to be set for you:\n\n``` javascript\nform.submit('example.org/upload', function(err, res) {\n console.log(res.statusCode);\n});\n```\n\nTo use custom headers and pre-known length in parts:\n\n``` javascript\nvar CRLF = '\\r\\n';\nvar form = new FormData();\n\nvar options = {\n header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF,\n knownLength: 1\n};\n\nform.append('my_buffer', buffer, options);\n\nform.submit('http://example.com/', function(err, res) {\n if (err) throw err;\n console.log('Done');\n});\n```\n\nForm-Data can recognize and fetch all the required information from common types of streams (fs.readStream, http.response and mikeal's request), for some other types of streams you'd need to provide \"file\"-related information manually:\n\n``` javascript\nsomeModule.stream(function(err, stdout, stderr) {\n if (err) throw err;\n\n var form = new FormData();\n\n form.append('file', stdout, {\n filename: 'unicycle.jpg',\n contentType: 'image/jpg',\n knownLength: 19806\n });\n\n form.submit('http://example.com/', function(err, res) {\n if (err) throw err;\n console.log('Done');\n });\n});\n```\n\nFor edge cases, like POST request to URL with query string or to pass HTTP auth credentials, object can be passed to `form.submit()` as first parameter:\n\n``` javascript\nform.submit({\n host: 'example.com',\n path: '/probably.php?extra=params',\n auth: 'username:password'\n}, function(err, res) {\n console.log(res.statusCode);\n});\n```\n\n## TODO\n\n- Add new streams (0.10) support and try really hard not to break it for 0.8.x.\n\n## License\n\nForm-Data is licensed under the MIT license.\n",
|
||||
"readmeFilename": "Readme.md",
|
||||
"_id": "form-data@0.0.10",
|
||||
"dist": {
|
||||
"shasum": "851b672bd10ef4d37ff854258f0f383964fb3adf"
|
||||
},
|
||||
"_from": "form-data@~0.0.3",
|
||||
"_resolved": "https://registry.npmjs.org/form-data/-/form-data-0.0.10.tgz"
|
||||
}
|
18
node_modules/tabletop/node_modules/request/node_modules/hawk/.npmignore
generated
vendored
Normal file
18
node_modules/tabletop/node_modules/request/node_modules/hawk/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
.idea
|
||||
*.iml
|
||||
npm-debug.log
|
||||
dump.rdb
|
||||
node_modules
|
||||
results.tap
|
||||
results.xml
|
||||
npm-shrinkwrap.json
|
||||
config.json
|
||||
.DS_Store
|
||||
*/.DS_Store
|
||||
*/*/.DS_Store
|
||||
._*
|
||||
*/._*
|
||||
*/*/._*
|
||||
coverage.*
|
||||
lib-cov
|
||||
|
5
node_modules/tabletop/node_modules/request/node_modules/hawk/.travis.yml
generated
vendored
Executable file
5
node_modules/tabletop/node_modules/request/node_modules/hawk/.travis.yml
generated
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- 0.8
|
||||
|
24
node_modules/tabletop/node_modules/request/node_modules/hawk/LICENSE
generated
vendored
Executable file
24
node_modules/tabletop/node_modules/request/node_modules/hawk/LICENSE
generated
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
Copyright (c) 2012-2013, Eran Hammer.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Eran Hammer nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ERAN HAMMER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
11
node_modules/tabletop/node_modules/request/node_modules/hawk/Makefile
generated
vendored
Executable file
11
node_modules/tabletop/node_modules/request/node_modules/hawk/Makefile
generated
vendored
Executable file
@@ -0,0 +1,11 @@
|
||||
test:
|
||||
@./node_modules/.bin/lab
|
||||
test-cov:
|
||||
@./node_modules/.bin/lab -r threshold -t 100
|
||||
test-cov-html:
|
||||
@./node_modules/.bin/lab -r html -o coverage.html
|
||||
complexity:
|
||||
@./node_modules/.bin/cr -o complexity.md -f markdown lib
|
||||
|
||||
.PHONY: test test-cov test-cov-html complexity
|
||||
|
604
node_modules/tabletop/node_modules/request/node_modules/hawk/README.md
generated
vendored
Executable file
604
node_modules/tabletop/node_modules/request/node_modules/hawk/README.md
generated
vendored
Executable file
@@ -0,0 +1,604 @@
|
||||

|
||||
|
||||
<img align="right" src="https://raw.github.com/hueniverse/hawk/master/images/logo.png" /> **Hawk** is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial
|
||||
HTTP request cryptographic verification. For more complex use cases such as access delegation, see [Oz](https://github.com/hueniverse/oz).
|
||||
|
||||
Current version: **0.10.1**
|
||||
|
||||
[](http://travis-ci.org/hueniverse/hawk)
|
||||
|
||||
# Table of Content
|
||||
|
||||
- [**Introduction**](#introduction)
|
||||
- [Replay Protection](#replay-protection)
|
||||
- [Usage Example](#usage-example)
|
||||
- [Protocol Example](#protocol-example)
|
||||
- [Payload Validation](#payload-validation)
|
||||
- [Response Payload Validation](#response-payload-validation)
|
||||
<p></p>
|
||||
- [**Single URI Authorization**](#single-uri-authorization)
|
||||
- [Usage Example](#bewit-usage-example)
|
||||
<p></p>
|
||||
- [**Security Considerations**](#security-considerations)
|
||||
- [MAC Keys Transmission](#mac-keys-transmission)
|
||||
- [Confidentiality of Requests](#confidentiality-of-requests)
|
||||
- [Spoofing by Counterfeit Servers](#spoofing-by-counterfeit-servers)
|
||||
- [Plaintext Storage of Credentials](#plaintext-storage-of-credentials)
|
||||
- [Entropy of Keys](#entropy-of-keys)
|
||||
- [Coverage Limitations](#coverage-limitations)
|
||||
- [Future Time Manipulation](#future-time-manipulation)
|
||||
- [Client Clock Poisoning](#client-clock-poisoning)
|
||||
- [Bewit Limitations](#bewit-limitations)
|
||||
<p></p>
|
||||
- [**Frequently Asked Questions**](#frequently-asked-questions)
|
||||
<p></p>
|
||||
- [**Acknowledgements**](#acknowledgements)
|
||||
|
||||
# Introduction
|
||||
|
||||
**Hawk** is an HTTP authentication scheme providing mechanisms for making authenticated HTTP requests with
|
||||
partial cryptographic verification of the request and response, covering the HTTP method, request URI, host,
|
||||
and optionally the request payload.
|
||||
|
||||
Similar to the HTTP [Digest access authentication schemes](http://www.ietf.org/rfc/rfc2617.txt), **Hawk** uses a set of
|
||||
client credentials which include an identifier (e.g. username) and key (e.g. password). Likewise, just as with the Digest scheme,
|
||||
the key is never included in authenticated requests. Instead, it is used to calculate a request MAC value which is
|
||||
included in its place.
|
||||
|
||||
However, **Hawk** has several differences from Digest. In particular, while both use a nonce to limit the possibility of
|
||||
replay attacks, in **Hawk** the client generates the nonce and uses it in combination with a timestamp, leading to less
|
||||
"chattiness" (interaction with the server).
|
||||
|
||||
Also unlike Digest, this scheme is not intended to protect the key itself (the password in Digest) because
|
||||
the client and server must both have access to the key material in the clear.
|
||||
|
||||
The primary design goals of this scheme are to:
|
||||
* simplify and improve HTTP authentication for services that are unwilling or unable to deploy TLS for all resources,
|
||||
* secure credentials against leakage (e.g., when the client uses some form of dynamic configuration to determine where
|
||||
to send an authenticated request), and
|
||||
* avoid the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client
|
||||
failure to validate the server's identity as part of its TLS handshake.
|
||||
|
||||
In addition, **Hawk** supports a method for granting third-parties temporary access to individual resources using
|
||||
a query parameter called _bewit_ (in falconry, a leather strap used to attach a tracking device to the leg of a hawk).
|
||||
|
||||
The **Hawk** scheme requires the establishment of a shared symmetric key between the client and the server,
|
||||
which is beyond the scope of this module. Typically, the shared credentials are established via an initial
|
||||
TLS-protected phase or derived from some other shared confidential information available to both the client
|
||||
and the server.
|
||||
|
||||
|
||||
## Replay Protection
|
||||
|
||||
Without replay protection, an attacker can use a compromised (but otherwise valid and authenticated) request more
|
||||
than once, gaining access to a protected resource. To mitigate this, clients include both a nonce and a timestamp when
|
||||
making requests. This gives the server enough information to prevent replay attacks.
|
||||
|
||||
The nonce is generated by the client, and is a string unique across all requests with the same timestamp and
|
||||
key identifier combination.
|
||||
|
||||
The timestamp enables the server to restrict the validity period of the credentials where requests occuring afterwards
|
||||
are rejected. It also removes the need for the server to retain an unbounded number of nonce values for future checks.
|
||||
By default, **Hawk** uses a time window of 1 minute to allow for time skew between the client and server (which in
|
||||
practice translates to a maximum of 2 minutes as the skew can be positive or negative).
|
||||
|
||||
Using a timestamp requires the client's clock to be in sync with the server's clock. **Hawk** requires both the client
|
||||
clock and the server clock to use NTP to ensure synchronization. However, given the limitations of some client types
|
||||
(e.g. browsers) to deploy NTP, the server provides the client with its current time in response to a bad timestamp.
|
||||
|
||||
There is no expectation that the client will adjust its system clock to match the server (in fact, this would be a
|
||||
potential attack vector). Instead, the client only uses the server's time to calculate an offset used only
|
||||
for communications with that particular server. The protocol rewards clients with synchronized clocks by reducing
|
||||
the number of round trips required to authenticate the first request.
|
||||
|
||||
|
||||
## Usage Example
|
||||
|
||||
Server code:
|
||||
|
||||
```javascript
|
||||
var Http = require('http');
|
||||
var Hawk = require('hawk');
|
||||
|
||||
|
||||
// Credentials lookup function
|
||||
|
||||
var credentialsFunc = function (id, callback) {
|
||||
|
||||
var credentials = {
|
||||
key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
|
||||
algorithm: 'sha256',
|
||||
user: 'Steve'
|
||||
};
|
||||
|
||||
return callback(null, credentials);
|
||||
};
|
||||
|
||||
// Create HTTP server
|
||||
|
||||
var handler = function (req, res) {
|
||||
|
||||
// Authenticate incoming request
|
||||
|
||||
Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
|
||||
|
||||
// Prepare response
|
||||
|
||||
var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!');
|
||||
var headers = { 'Content-Type': 'text/plain' };
|
||||
|
||||
// Generate Server-Authorization response header
|
||||
|
||||
var header = Hawk.server.header(artifacts, { payload: payload, contentType: headers['Content-Type'] });
|
||||
headers['Server-Authorization'] = header;
|
||||
|
||||
// Send the response back
|
||||
|
||||
res.writeHead(!err ? 200 : 401, headers);
|
||||
res.end(payload);
|
||||
});
|
||||
};
|
||||
|
||||
// Start server
|
||||
|
||||
Http.createServer(handler).listen(8000, 'example.com');
|
||||
```
|
||||
|
||||
Client code:
|
||||
|
||||
```javascript
|
||||
var Request = require('request');
|
||||
var Hawk = require('hawk');
|
||||
|
||||
|
||||
// Client credentials
|
||||
|
||||
var credentials = {
|
||||
id: 'dh37fgj492je',
|
||||
key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
|
||||
algorithm: 'sha256'
|
||||
}
|
||||
|
||||
// Request options
|
||||
|
||||
var requestOptions = {
|
||||
uri: 'http://example.com:8000/resource/1?b=1&a=2',
|
||||
method: 'GET',
|
||||
headers: {}
|
||||
};
|
||||
|
||||
// Generate Authorization request header
|
||||
|
||||
var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'some-app-data' });
|
||||
requestOptions.headers.Authorization = header.field;
|
||||
|
||||
// Send authenticated request
|
||||
|
||||
Request(requestOptions, function (error, response, body) {
|
||||
|
||||
// Authenticate the server's response
|
||||
|
||||
var isValid = Hawk.client.authenticate(response, header.artifacts, { payload: body });
|
||||
|
||||
// Output results
|
||||
|
||||
console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));
|
||||
});
|
||||
```
|
||||
|
||||
**Hawk** utilized the [**SNTP**](https://github.com/hueniverse/sntp) module for time sync management. By default, the local
|
||||
machine time is used. To automatically retrieve and synchronice the clock within the application, use the SNTP 'start()' method.
|
||||
|
||||
```javascript
|
||||
Hawk.sntp.start();
|
||||
```
|
||||
|
||||
|
||||
## Protocol Example
|
||||
|
||||
The client attempts to access a protected resource without authentication, sending the following HTTP request to
|
||||
the resource server:
|
||||
|
||||
```
|
||||
GET /resource/1?b=1&a=2 HTTP/1.1
|
||||
Host: example.com:8000
|
||||
```
|
||||
|
||||
The resource server returns an authentication challenge.
|
||||
|
||||
```
|
||||
HTTP/1.1 401 Unauthorized
|
||||
WWW-Authenticate: Hawk
|
||||
```
|
||||
|
||||
The client has previously obtained a set of **Hawk** credentials for accessing resources on the "http://example.com/"
|
||||
server. The **Hawk** credentials issued to the client include the following attributes:
|
||||
|
||||
* Key identifier: dh37fgj492je
|
||||
* Key: werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn
|
||||
* Algorithm: sha256
|
||||
|
||||
The client generates the authentication header by calculating a timestamp (e.g. the number of seconds since January 1,
|
||||
1970 00:00:00 GMT), generating a nonce, and constructing the normalized request string (each value followed by a newline
|
||||
character):
|
||||
|
||||
```
|
||||
hawk.1.header
|
||||
1353832234
|
||||
j4h3g2
|
||||
GET
|
||||
/resource?a=1&b=2
|
||||
example.com
|
||||
8000
|
||||
|
||||
some-app-ext-data
|
||||
|
||||
```
|
||||
|
||||
The request MAC is calculated using HMAC with the specified hash algorithm "sha256" and the key over the normalized request string.
|
||||
The result is base64-encoded to produce the request MAC:
|
||||
|
||||
```
|
||||
6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=
|
||||
```
|
||||
|
||||
The client includes the **Hawk** key identifier, timestamp, nonce, application specific data, and request MAC with the request using
|
||||
the HTTP `Authorization` request header field:
|
||||
|
||||
```
|
||||
GET /resource/1?b=1&a=2 HTTP/1.1
|
||||
Host: example.com:8000
|
||||
Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="
|
||||
```
|
||||
|
||||
The server validates the request by calculating the request MAC again based on the request received and verifies the validity
|
||||
and scope of the **Hawk** credentials. If valid, the server responds with the requested resource.
|
||||
|
||||
|
||||
### Payload Validation
|
||||
|
||||
**Hawk** provides optional payload validation. When generating the authentication header, the client calculates a payload hash
|
||||
using the specified hash algorithm. The hash is calculated over the concatenated value of (each followed by a newline character):
|
||||
* `hawk.1.payload`
|
||||
* the content-type in lowercase, without any parameters (e.g. `application/json`)
|
||||
* the request payload prior to any content encoding (the exact representation requirements should be specified by the server for payloads other than simple single-part ascii to ensure interoperability)
|
||||
|
||||
For example:
|
||||
|
||||
* Payload: `Thank you for flying Hawk`
|
||||
* Content Type: `text/plain`
|
||||
* Hash (sha256): `Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=`
|
||||
|
||||
Results in the following input to the payload hash function (newline terminated values):
|
||||
|
||||
```
|
||||
hawk.1.payload
|
||||
text/plain
|
||||
Thank you for flying Hawk
|
||||
|
||||
```
|
||||
|
||||
Which produces the following hash value:
|
||||
|
||||
```
|
||||
Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=
|
||||
```
|
||||
|
||||
The client constructs the normalized request string (newline terminated values):
|
||||
|
||||
```
|
||||
hawk.1.header
|
||||
1353832234
|
||||
j4h3g2
|
||||
POST
|
||||
/resource?a=1&b=2
|
||||
example.com
|
||||
8000
|
||||
Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=
|
||||
some-app-ext-data
|
||||
|
||||
```
|
||||
|
||||
Then calculates the request MAC and includes the **Hawk** key identifier, timestamp, nonce, payload hash, application specific data,
|
||||
and request MAC, with the request using the HTTP `Authorization` request header field:
|
||||
|
||||
```
|
||||
POST /resource/1 HTTP/1.1
|
||||
Host: example.com:8000
|
||||
Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="
|
||||
```
|
||||
|
||||
It is up to the server if and when it validates the payload for any given request, based solely on it's security policy
|
||||
and the nature of the data included.
|
||||
|
||||
If the payload is available at the time of authentication, the server uses the hash value provided by the client to construct
|
||||
the normalized string and validates the MAC. If the MAC is valid, the server calculates the payload hash and compares the value
|
||||
with the provided payload hash in the header. In many cases, checking the MAC first is faster than calculating the payload hash.
|
||||
|
||||
However, if the payload is not available at authentication time (e.g. too large to fit in memory, streamed elsewhere, or processed
|
||||
at a different stage in the application), the server may choose to defer payload validation for later by retaining the hash value
|
||||
provided by the client after validating the MAC.
|
||||
|
||||
It is important to note that MAC validation does not mean the hash value provided by the client is valid, only that the value
|
||||
included in the header was not modified. Without calculating the payload hash on the server and comparing it to the value provided
|
||||
by the client, the payload may be modified by an attacker.
|
||||
|
||||
|
||||
## Response Payload Validation
|
||||
|
||||
**Hawk** provides partial response payload validation. The server includes the `Server-Authorization` response header which enables the
|
||||
client to authenticate the response and ensure it is talking to the right server. **Hawk** defines the HTTP `Server-Authorization` header
|
||||
as a response header using the exact same syntax as the `Authorization` request header field.
|
||||
|
||||
The header is contructed using the same process as the client's request header. The server uses the same credentials and other
|
||||
artifacts provided by the client to constructs the normalized request string. The `ext` and `hash` values are replaced with
|
||||
new values based on the server response. The rest as identical to those used by the client.
|
||||
|
||||
The result MAC digest is included with the optional `hash` and `ext` values:
|
||||
|
||||
```
|
||||
Server-Authorization: Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"
|
||||
```
|
||||
|
||||
|
||||
# Single URI Authorization
|
||||
|
||||
There are cases in which limited and short-term access to a protected resource is granted to a third party which does not
|
||||
have access to the shared credentials. For example, displaying a protected image on a web page accessed by anyone. **Hawk**
|
||||
provides limited support for such URIs in the form of a _bewit_ - a URI query parameter appended to the request URI which contains
|
||||
the necessary credentials to authenticate the request.
|
||||
|
||||
Because of the significant security risks involved in issuing such access, bewit usage is purposely limited only to GET requests
|
||||
and for a finite period of time. Both the client and server can issue bewit credentials, however, the server should not use the same
|
||||
credentials as the client to maintain clear traceability as to who issued which credentials.
|
||||
|
||||
In order to simplify implementation, bewit credentials do not support single-use policy and can be replayed multiple times within
|
||||
the granted access timeframe.
|
||||
|
||||
|
||||
## Bewit Usage Example
|
||||
|
||||
Server code:
|
||||
|
||||
```javascript
|
||||
var Http = require('http');
|
||||
var Hawk = require('hawk');
|
||||
|
||||
|
||||
// Credentials lookup function
|
||||
|
||||
var credentialsFunc = function (id, callback) {
|
||||
|
||||
var credentials = {
|
||||
key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
|
||||
algorithm: 'sha256'
|
||||
};
|
||||
|
||||
return callback(null, credentials);
|
||||
};
|
||||
|
||||
// Create HTTP server
|
||||
|
||||
var handler = function (req, res) {
|
||||
|
||||
Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
|
||||
|
||||
res.writeHead(!err ? 200 : 401, { 'Content-Type': 'text/plain' });
|
||||
res.end(!err ? 'Access granted' : 'Shoosh!');
|
||||
});
|
||||
};
|
||||
|
||||
Http.createServer(handler).listen(8000, 'example.com');
|
||||
```
|
||||
|
||||
Bewit code generation:
|
||||
|
||||
```javascript
|
||||
var Request = require('request');
|
||||
var Hawk = require('hawk');
|
||||
|
||||
|
||||
// Client credentials
|
||||
|
||||
var credentials = {
|
||||
id: 'dh37fgj492je',
|
||||
key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
|
||||
algorithm: 'sha256'
|
||||
}
|
||||
|
||||
// Generate bewit
|
||||
|
||||
var duration = 60 * 5; // 5 Minutes
|
||||
var bewit = Hawk.uri.getBewit('http://example.com:8080/resource/1?b=1&a=2', { credentials: credentials, ttlSec: duration, ext: 'some-app-data' });
|
||||
var uri = 'http://example.com:8000/resource/1?b=1&a=2' + '&bewit=' + bewit;
|
||||
```
|
||||
|
||||
|
||||
# Security Considerations
|
||||
|
||||
The greatest sources of security risks are usually found not in **Hawk** but in the policies and procedures surrounding its use.
|
||||
Implementers are strongly encouraged to assess how this module addresses their security requirements. This section includes
|
||||
an incomplete list of security considerations that must be reviewed and understood before deploying **Hawk** on the server.
|
||||
Many of the protections provided in **Hawk** depends on whether and how they are used.
|
||||
|
||||
### MAC Keys Transmission
|
||||
|
||||
**Hawk** does not provide any mechanism for obtaining or transmitting the set of shared credentials required. Any mechanism used
|
||||
to obtain **Hawk** credentials must ensure that these transmissions are protected using transport-layer mechanisms such as TLS.
|
||||
|
||||
### Confidentiality of Requests
|
||||
|
||||
While **Hawk** provides a mechanism for verifying the integrity of HTTP requests, it provides no guarantee of request
|
||||
confidentiality. Unless other precautions are taken, eavesdroppers will have full access to the request content. Servers should
|
||||
carefully consider the types of data likely to be sent as part of such requests, and employ transport-layer security mechanisms
|
||||
to protect sensitive resources.
|
||||
|
||||
### Spoofing by Counterfeit Servers
|
||||
|
||||
**Hawk** provides limited verification of the server authenticity. When receiving a response back from the server, the server
|
||||
may choose to include a response `Server-Authorization` header which the client can use to verify the response. However, it is up to
|
||||
the server to determine when such measure is included, to up to the client to enforce that policy.
|
||||
|
||||
A hostile party could take advantage of this by intercepting the client's requests and returning misleading or otherwise
|
||||
incorrect responses. Service providers should consider such attacks when developing services using this protocol, and should
|
||||
require transport-layer security for any requests where the authenticity of the resource server or of server responses is an issue.
|
||||
|
||||
### Plaintext Storage of Credentials
|
||||
|
||||
The **Hawk** key functions the same way passwords do in traditional authentication systems. In order to compute the request MAC,
|
||||
the server must have access to the key in plaintext form. This is in contrast, for example, to modern operating systems, which
|
||||
store only a one-way hash of user credentials.
|
||||
|
||||
If an attacker were to gain access to these keys - or worse, to the server's database of all such keys - he or she would be able
|
||||
to perform any action on behalf of any resource owner. Accordingly, it is critical that servers protect these keys from unauthorized
|
||||
access.
|
||||
|
||||
### Entropy of Keys
|
||||
|
||||
Unless a transport-layer security protocol is used, eavesdroppers will have full access to authenticated requests and request
|
||||
MAC values, and will thus be able to mount offline brute-force attacks to recover the key used. Servers should be careful to
|
||||
assign keys which are long enough, and random enough, to resist such attacks for at least the length of time that the **Hawk**
|
||||
credentials are valid.
|
||||
|
||||
For example, if the credentials are valid for two weeks, servers should ensure that it is not possible to mount a brute force
|
||||
attack that recovers the key in less than two weeks. Of course, servers are urged to err on the side of caution, and use the
|
||||
longest key reasonable.
|
||||
|
||||
It is equally important that the pseudo-random number generator (PRNG) used to generate these keys be of sufficiently high
|
||||
quality. Many PRNG implementations generate number sequences that may appear to be random, but which nevertheless exhibit
|
||||
patterns or other weaknesses which make cryptanalysis or brute force attacks easier. Implementers should be careful to use
|
||||
cryptographically secure PRNGs to avoid these problems.
|
||||
|
||||
### Coverage Limitations
|
||||
|
||||
The request MAC only covers the HTTP `Host` header and optionally the `Content-Type` header. It does not cover any other headers
|
||||
which can often affect how the request body is interpreted by the server. If the server behavior is influenced by the presence
|
||||
or value of such headers, an attacker can manipulate the request headers without being detected. Implementers should use the
|
||||
`ext` feature to pass application-specific information via the `Authorization` header which is protected by the request MAC.
|
||||
|
||||
The response authentication, when performed, only covers the response payload, content-type, and the request information
|
||||
provided by the client in it's request (method, resource, timestamp, nonce, etc.). It does not cover the HTTP status code or
|
||||
any other response header field (e.g. Location) which can affect the client's behaviour.
|
||||
|
||||
### Future Time Manipulation
|
||||
|
||||
The protocol relies on a clock sync between the client and server. To accomplish this, the server informs the client of its
|
||||
current time when an invalid timestamp is received.
|
||||
|
||||
If an attacker is able to manipulate this information and cause the client to use an incorrect time, it would be able to cause
|
||||
the client to generate authenticated requests using time in the future. Such requests will fail when sent by the client, and will
|
||||
not likely leave a trace on the server (given the common implementation of nonce, if at all enforced). The attacker will then
|
||||
be able to replay the request at the correct time without detection.
|
||||
|
||||
The client must only use the time information provided by the server if:
|
||||
* it was delivered over a TLS connection and the server identity has been verified, or
|
||||
* the `tsm` MAC digest calculated using the same client credentials over the timestamp has been verified.
|
||||
|
||||
### Client Clock Poisoning
|
||||
|
||||
When receiving a request with a bad timestamp, the server provides the client with its current time. The client must never use
|
||||
the time received from the server to adjust its own clock, and must only use it to calculate an offset for communicating with
|
||||
that particular server.
|
||||
|
||||
### Bewit Limitations
|
||||
|
||||
Special care must be taken when issuing bewit credentials to third parties. Bewit credentials are valid until expiration and cannot
|
||||
be revoked or limited without using other means. Whatever resource they grant access to will be completely exposed to anyone with
|
||||
access to the bewit credentials which act as bearer credentials for that particular resource. While bewit usage is limited to GET
|
||||
requests only and therefore cannot be used to perform transactions or change server state, it can still be used to expose private
|
||||
and sensitive information.
|
||||
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
### Where is the protocol specification?
|
||||
|
||||
If you are looking for some prose explaining how all this works, **this is it**. **Hawk** is being developed as an open source
|
||||
project instead of a standard. In other words, the [code](/hueniverse/hawk/tree/master/lib) is the specification. Not sure about
|
||||
something? Open an issue!
|
||||
|
||||
### Is it done?
|
||||
|
||||
At if version 0.10.0, **Hawk** is feature-complete. However, until this module reaches version 1.0.0 it is considered experimental
|
||||
and is likely to change. This also means your feedback and contribution are very welcome. Feel free to open issues with questions
|
||||
and suggestions.
|
||||
|
||||
### Where can I find **Hawk** implementations in other languages?
|
||||
|
||||
**Hawk**'s only reference implementation is provided in JavaScript as a node.js module. However, others are actively porting it to other
|
||||
platforms. There is already a [PHP](https://github.com/alexbilbie/PHP-Hawk),
|
||||
[.NET](https://github.com/pcibraro/hawknet), and [JAVA](https://github.com/wealdtech/hawk) libraries available. The full list
|
||||
is maintained [here](https://github.com/hueniverse/hawk/issues?labels=port). Please add an issue if you are working on another
|
||||
port. A cross-platform test-suite is in the works.
|
||||
|
||||
### Why isn't the algorithm part of the challenge or dynamically negotiated?
|
||||
|
||||
The algorithm used is closely related to the key issued as different algorithms require different key sizes (and other
|
||||
requirements). While some keys can be used for multiple algorithm, the protocol is designed to closely bind the key and algorithm
|
||||
together as part of the issued credentials.
|
||||
|
||||
### Why is Host and Content-Type the only headers covered by the request MAC?
|
||||
|
||||
It is really hard to include other headers. Headers can be changed by proxies and other intermediaries and there is no
|
||||
well-established way to normalize them. Many platforms change the case of header field names and values. The only
|
||||
straight-forward solution is to include the headers in some blob (say, base64 encoded JSON) and include that with the request,
|
||||
an approach taken by JWT and other such formats. However, that design violates the HTTP header boundaries, repeats information,
|
||||
and introduces other security issues because firewalls will not be aware of these "hidden" headers. In addition, any information
|
||||
repeated must be compared to the duplicated information in the header and therefore only moves the problem elsewhere.
|
||||
|
||||
### Why not just use HTTP Digest?
|
||||
|
||||
Digest requires pre-negotiation to establish a nonce. This means you can't just make a request - you must first send
|
||||
a protocol handshake to the server. This pattern has become unacceptable for most web services, especially mobile
|
||||
where extra round-trip are costly.
|
||||
|
||||
### Why bother with all this nonce and timestamp business?
|
||||
|
||||
**Hawk** is an attempt to find a reasonable, practical compromise between security and usability. OAuth 1.0 got timestamp
|
||||
and nonces halfway right but failed when it came to scalability and consistent developer experience. **Hawk** addresses
|
||||
it by requiring the client to sync its clock, but provides it with tools to accomplish it.
|
||||
|
||||
In general, replay protection is a matter of application-specific threat model. It is less of an issue on a TLS-protected
|
||||
system where the clients are implemented using best practices and are under the control of the server. Instead of dropping
|
||||
replay protection, **Hawk** offers a required time window and an optional nonce verification. Together, it provides developers
|
||||
with the ability to decide how to enforce their security policy without impacting the client's implementation.
|
||||
|
||||
### What are `app` and `dlg` in the authorization header and normalized mac string?
|
||||
|
||||
The original motivation for **Hawk** was to replace the OAuth 1.0 use cases. This included both a simple client-server mode which
|
||||
this module is specifically designed for, and a delegated access mode which is being developed separately in
|
||||
[Oz](https://github.com/hueniverse/oz). In addition to the **Hawk** use cases, Oz requires another attribute: the application id `app`.
|
||||
This provides binding between the credentials and the application in a way that prevents an attacker from tricking an application
|
||||
to use credentials issued to someone else. It also has an optional 'delegated-by' attribute `dlg` which is the application id of the
|
||||
application the credentials were directly issued to. The goal of these two additions is to allow Oz to utilize **Hawk** directly,
|
||||
but with the additional security of delegated credentials.
|
||||
|
||||
### What is the purpose of the static strings used in each normalized MAC input?
|
||||
|
||||
When calculating a hash or MAC, a static prefix (tag) is added. The prefix is used to prevent MAC values from being
|
||||
used or reused for a purpose other than what they were created for (i.e. prevents switching MAC values between a request,
|
||||
response, and a bewit use cases). It also protects against expliots created after a potential change in how the protocol
|
||||
creates the normalized string. For example, if a future version would switch the order of nonce and timestamp, it
|
||||
can create an exploit opportunity for cases where the nonce is similar in format to a timestamp.
|
||||
|
||||
### Does **Hawk** have anything to do with OAuth?
|
||||
|
||||
Short answer: no.
|
||||
|
||||
**Hawk** was originally proposed as the OAuth MAC Token specification. However, the OAuth working group in its consistent
|
||||
incompetence failed to produce a final, usable solution to address one of the most popular use cases of OAuth 1.0 - using it
|
||||
to authenticate simple client-server transactions (i.e. two-legged). As you can guess, the OAuth working group is still hard
|
||||
at work to produce more garbage.
|
||||
|
||||
**Hawk** provides a simple HTTP authentication scheme for making client-server requests. It does not address the OAuth use case
|
||||
of delegating access to a third party. If you are looking for an OAuth alternative, check out [Oz](/hueniverse/oz).
|
||||
|
||||
|
||||
# Acknowledgements
|
||||
|
||||
**Hawk** is a derivative work of the [HTTP MAC Authentication Scheme](http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05) proposal
|
||||
co-authored by Ben Adida, Adam Barth, and Eran Hammer, which in turn was based on the OAuth 1.0 community specification.
|
||||
|
||||
Special thanks to Ben Laurie for his always insightful feedback and advice.
|
||||
|
||||
The **Hawk** logo was created by [Chris Carrasco](http://chriscarrasco.com).
|
77
node_modules/tabletop/node_modules/request/node_modules/hawk/example/usage.js
generated
vendored
Executable file
77
node_modules/tabletop/node_modules/request/node_modules/hawk/example/usage.js
generated
vendored
Executable file
@@ -0,0 +1,77 @@
|
||||
// Load modules
|
||||
|
||||
var Http = require('http');
|
||||
var Request = require('request');
|
||||
var Hawk = require('../lib');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {
|
||||
credentials: {
|
||||
dh37fgj492je: {
|
||||
id: 'dh37fgj492je', // Required by Hawk.client.header
|
||||
key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
|
||||
algorithm: 'sha256',
|
||||
user: 'Steve'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Credentials lookup function
|
||||
|
||||
var credentialsFunc = function (id, callback) {
|
||||
|
||||
return callback(null, internals.credentials[id]);
|
||||
};
|
||||
|
||||
|
||||
// Create HTTP server
|
||||
|
||||
var handler = function (req, res) {
|
||||
|
||||
Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
|
||||
|
||||
var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!');
|
||||
var headers = {
|
||||
'Content-Type': 'text/plain',
|
||||
'Server-Authorization': Hawk.server.header(artifacts, { payload: payload, contentType: 'text/plain' })
|
||||
};
|
||||
|
||||
res.writeHead(!err ? 200 : 401, headers);
|
||||
res.end(payload);
|
||||
});
|
||||
};
|
||||
|
||||
Http.createServer(handler).listen(8000, '127.0.0.1');
|
||||
|
||||
|
||||
// Send unauthenticated request
|
||||
|
||||
Request('http://127.0.0.1:8000/resource/1?b=1&a=2', function (error, response, body) {
|
||||
|
||||
console.log(response.statusCode + ': ' + body);
|
||||
});
|
||||
|
||||
|
||||
// Send authenticated request
|
||||
|
||||
var header = Hawk.client.header('http://127.0.0.1:8000/resource/1?b=1&a=2', 'GET', { credentials: internals.credentials.dh37fgj492je, ext: 'and welcome!' });
|
||||
var options = {
|
||||
uri: 'http://127.0.0.1:8000/resource/1?b=1&a=2',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
authorization: header.field
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Request(options, function (error, response, body) {
|
||||
|
||||
var isValid = Hawk.client.authenticate(response, header.artifacts, { payload: body });
|
||||
console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
|
BIN
node_modules/tabletop/node_modules/request/node_modules/hawk/images/hawk.png
generated
vendored
Executable file
BIN
node_modules/tabletop/node_modules/request/node_modules/hawk/images/hawk.png
generated
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
BIN
node_modules/tabletop/node_modules/request/node_modules/hawk/images/logo.png
generated
vendored
Executable file
BIN
node_modules/tabletop/node_modules/request/node_modules/hawk/images/logo.png
generated
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
1
node_modules/tabletop/node_modules/request/node_modules/hawk/index.js
generated
vendored
Executable file
1
node_modules/tabletop/node_modules/request/node_modules/hawk/index.js
generated
vendored
Executable file
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib');
|
200
node_modules/tabletop/node_modules/request/node_modules/hawk/lib/client.js
generated
vendored
Executable file
200
node_modules/tabletop/node_modules/request/node_modules/hawk/lib/client.js
generated
vendored
Executable file
@@ -0,0 +1,200 @@
|
||||
// Load modules
|
||||
|
||||
var Url = require('url');
|
||||
var Hoek = require('hoek');
|
||||
var Cryptiles = require('cryptiles');
|
||||
var Crypto = require('./crypto');
|
||||
var Utils = require('./utils');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
// Generate an Authorization header for a given request
|
||||
|
||||
/*
|
||||
uri: 'http://example.com/resource?a=b' or object from Url.parse()
|
||||
method: HTTP verb (e.g. 'GET', 'POST')
|
||||
options: {
|
||||
|
||||
// Required
|
||||
|
||||
credentials: {
|
||||
id: 'dh37fgj492je',
|
||||
key: 'aoijedoaijsdlaksjdl',
|
||||
algorithm: 'sha256' // 'sha1', 'sha256'
|
||||
},
|
||||
|
||||
// Optional
|
||||
|
||||
ext: 'application-specific', // Application specific data sent via the ext attribute
|
||||
timestamp: Date.now(), // A pre-calculated timestamp
|
||||
nonce: '2334f34f', // A pre-generated nonce
|
||||
localtimeOffsetMsec: 400, // Time offset to sync with server time (ignored if timestamp provided)
|
||||
payload: '{"some":"payload"}', // UTF-8 encoded string for body hash generation (ignored if hash provided)
|
||||
contentType: 'application/json', // Payload content-type (ignored if hash provided)
|
||||
hash: 'U4MKKSmiVxk37JCCrAVIjV=', // Pre-calculated payload hash
|
||||
app: '24s23423f34dx', // Oz application id
|
||||
dlg: '234sz34tww3sd' // Oz delegated-by application id
|
||||
}
|
||||
*/
|
||||
|
||||
exports.header = function (uri, method, options) {
|
||||
|
||||
var result = {
|
||||
field: '',
|
||||
artifacts: {}
|
||||
};
|
||||
|
||||
// Validate inputs
|
||||
|
||||
if (!uri || (typeof uri !== 'string' && typeof uri !== 'object') ||
|
||||
!method || typeof method !== 'string' ||
|
||||
!options || typeof options !== 'object') {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Application time
|
||||
|
||||
var timestamp = options.timestamp || Math.floor((Utils.now() + (options.localtimeOffsetMsec || 0)) / 1000)
|
||||
|
||||
// Validate credentials
|
||||
|
||||
var credentials = options.credentials;
|
||||
if (!credentials ||
|
||||
!credentials.id ||
|
||||
!credentials.key ||
|
||||
!credentials.algorithm) {
|
||||
|
||||
// Invalid credential object
|
||||
return result;
|
||||
}
|
||||
|
||||
if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Parse URI
|
||||
|
||||
if (typeof uri === 'string') {
|
||||
uri = Url.parse(uri);
|
||||
}
|
||||
|
||||
// Calculate signature
|
||||
|
||||
var artifacts = {
|
||||
credentials: credentials,
|
||||
ts: timestamp,
|
||||
nonce: options.nonce || Cryptiles.randomString(6),
|
||||
method: method,
|
||||
resource: uri.pathname + (uri.search || ''), // Maintain trailing '?'
|
||||
host: uri.hostname,
|
||||
port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
|
||||
hash: options.hash,
|
||||
ext: options.ext,
|
||||
app: options.app,
|
||||
dlg: options.dlg
|
||||
};
|
||||
|
||||
result.artifacts = artifacts;
|
||||
|
||||
// Calculate payload hash
|
||||
|
||||
if (!artifacts.hash &&
|
||||
options.hasOwnProperty('payload')) {
|
||||
|
||||
artifacts.hash = Crypto.calculateHash(options.payload, credentials.algorithm, options.contentType);
|
||||
}
|
||||
|
||||
var mac = Crypto.calculateMac('header', artifacts);
|
||||
|
||||
// Construct header
|
||||
|
||||
var hasExt = artifacts.ext !== null && artifacts.ext !== undefined && artifacts.ext !== ''; // Other falsey values allowed
|
||||
var header = 'Hawk id="' + credentials.id +
|
||||
'", ts="' + artifacts.ts +
|
||||
'", nonce="' + artifacts.nonce +
|
||||
(artifacts.hash ? '", hash="' + artifacts.hash : '') +
|
||||
(hasExt ? '", ext="' + Utils.escapeHeaderAttribute(artifacts.ext) : '') +
|
||||
'", mac="' + mac + '"';
|
||||
|
||||
if (artifacts.app) {
|
||||
header += ', app="' + artifacts.app +
|
||||
(artifacts.dlg ? '", dlg="' + artifacts.dlg : '') + '"';
|
||||
}
|
||||
|
||||
result.field = header;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
// Validate server response
|
||||
|
||||
/*
|
||||
res: node's response object
|
||||
artifacts: object recieved from header().artifacts
|
||||
options: {
|
||||
payload: optional payload received
|
||||
required: specifies if a Server-Authorization header is required. Defaults to 'false'
|
||||
}
|
||||
*/
|
||||
|
||||
exports.authenticate = function (res, artifacts, options) {
|
||||
|
||||
artifacts = Hoek.clone(artifacts);
|
||||
options = options || {};
|
||||
|
||||
if (res.headers['www-authenticate']) {
|
||||
|
||||
// Parse HTTP WWW-Authenticate header
|
||||
|
||||
var attributes = Utils.parseAuthorizationHeader(res.headers['www-authenticate'], ['ts', 'tsm', 'error']);
|
||||
if (attributes instanceof Error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (attributes.ts) {
|
||||
var tsm = Crypto.calculateTsMac(attributes.ts, artifacts.credentials);
|
||||
if (!Cryptiles.fixedTimeComparison(tsm, attributes.tsm)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse HTTP Server-Authorization header
|
||||
|
||||
if (!res.headers['server-authorization'] &&
|
||||
!options.required) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var attributes = Utils.parseAuthorizationHeader(res.headers['server-authorization'], ['mac', 'ext', 'hash']);
|
||||
if (attributes instanceof Error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
artifacts.ext = attributes.ext;
|
||||
artifacts.hash = attributes.hash;
|
||||
|
||||
var mac = Crypto.calculateMac('response', artifacts);
|
||||
if (!Cryptiles.fixedTimeComparison(mac, attributes.mac)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!options.hasOwnProperty('payload')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!attributes.hash) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var calculatedHash = Crypto.calculateHash(options.payload, artifacts.credentials.algorithm, res.headers['content-type']);
|
||||
return Cryptiles.fixedTimeComparison(calculatedHash, attributes.hash);
|
||||
};
|
||||
|
98
node_modules/tabletop/node_modules/request/node_modules/hawk/lib/crypto.js
generated
vendored
Executable file
98
node_modules/tabletop/node_modules/request/node_modules/hawk/lib/crypto.js
generated
vendored
Executable file
@@ -0,0 +1,98 @@
|
||||
// Load modules
|
||||
|
||||
var Crypto = require('crypto');
|
||||
var Url = require('url');
|
||||
var Utils = require('./utils');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
// MAC normalization format version
|
||||
|
||||
exports.headerVersion = '1'; // Prevent comparison of mac values generated with different normalized string formats
|
||||
|
||||
|
||||
// Supported HMAC algorithms
|
||||
|
||||
exports.algorithms = ['sha1', 'sha256'];
|
||||
|
||||
|
||||
// Calculate the request MAC
|
||||
|
||||
/*
|
||||
type: 'header' // 'header', 'bewit', 'response'
|
||||
options: {
|
||||
credentials: {
|
||||
key: 'aoijedoaijsdlaksjdl',
|
||||
algorithm: 'sha256' // 'sha1', 'sha256'
|
||||
},
|
||||
method: 'GET',
|
||||
resource: '/resource?a=1&b=2',
|
||||
host: 'example.com',
|
||||
port: 8080,
|
||||
ts: 1357718381034,
|
||||
nonce: 'd3d345f',
|
||||
hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=',
|
||||
ext: 'app-specific-data',
|
||||
app: 'hf48hd83qwkj', // Application id (Oz)
|
||||
dlg: 'd8djwekds9cj' // Delegated by application id (Oz), requires options.app
|
||||
}
|
||||
*/
|
||||
|
||||
exports.calculateMac = function (type, options) {
|
||||
|
||||
var normalized = exports.generateNormalizedString(type, options);
|
||||
|
||||
var hmac = Crypto.createHmac(options.credentials.algorithm, options.credentials.key).update(normalized);
|
||||
var digest = hmac.digest('base64');
|
||||
return digest;
|
||||
};
|
||||
|
||||
|
||||
exports.generateNormalizedString = function (type, options) {
|
||||
|
||||
var normalized = 'hawk.' + exports.headerVersion + '.' + type + '\n' +
|
||||
options.ts + '\n' +
|
||||
options.nonce + '\n' +
|
||||
options.method.toUpperCase() + '\n' +
|
||||
options.resource + '\n' +
|
||||
options.host.toLowerCase() + '\n' +
|
||||
options.port + '\n' +
|
||||
(options.hash || '') + '\n';
|
||||
|
||||
if (options.ext) {
|
||||
normalized += options.ext.replace('\\', '\\\\').replace('\n', '\\n');
|
||||
}
|
||||
|
||||
normalized += '\n';
|
||||
|
||||
if (options.app) {
|
||||
normalized += options.app + '\n' +
|
||||
(options.dlg || '') + '\n';
|
||||
}
|
||||
|
||||
return normalized;
|
||||
};
|
||||
|
||||
|
||||
exports.calculateHash = function (payload, algorithm, contentType) {
|
||||
|
||||
var hash = Crypto.createHash(algorithm);
|
||||
hash.update('hawk.' + exports.headerVersion + '.payload\n');
|
||||
hash.update(Utils.parseContentType(contentType) + '\n');
|
||||
hash.update(payload || '');
|
||||
hash.update('\n');
|
||||
return hash.digest('base64');
|
||||
};
|
||||
|
||||
|
||||
exports.calculateTsMac = function (ts, credentials) {
|
||||
|
||||
var hash = Crypto.createHash(credentials.algorithm);
|
||||
hash.update('hawk.' + exports.headerVersion + '.ts\n' + ts + '\n');
|
||||
return hash.digest('base64');
|
||||
};
|
||||
|
11
node_modules/tabletop/node_modules/request/node_modules/hawk/lib/index.js
generated
vendored
Executable file
11
node_modules/tabletop/node_modules/request/node_modules/hawk/lib/index.js
generated
vendored
Executable file
@@ -0,0 +1,11 @@
|
||||
// Export sub-modules
|
||||
|
||||
exports.error = exports.Error = require('boom');
|
||||
exports.sntp = require('sntp');
|
||||
exports.server = require('./server');
|
||||
exports.client = require('./client');
|
||||
exports.uri = require('./uri');
|
||||
exports.crypto = require('./crypto');
|
||||
exports.utils = require('./utils');
|
||||
|
||||
|
288
node_modules/tabletop/node_modules/request/node_modules/hawk/lib/server.js
generated
vendored
Executable file
288
node_modules/tabletop/node_modules/request/node_modules/hawk/lib/server.js
generated
vendored
Executable file
@@ -0,0 +1,288 @@
|
||||
// Load modules
|
||||
|
||||
var Boom = require('boom');
|
||||
var Hoek = require('hoek');
|
||||
var Cryptiles = require('cryptiles');
|
||||
var Crypto = require('./crypto');
|
||||
var Utils = require('./utils');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
// Hawk authentication
|
||||
|
||||
/*
|
||||
req: node's HTTP request object or an object as follows:
|
||||
|
||||
var request = {
|
||||
method: 'GET',
|
||||
url: '/resource/4?a=1&b=2',
|
||||
host: 'example.com',
|
||||
port: 8080,
|
||||
authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="'
|
||||
};
|
||||
|
||||
credentialsFunc: required function to lookup the set of Hawk credentials based on the provided credentials id.
|
||||
The credentials include the MAC key, MAC algorithm, and other attributes (such as username)
|
||||
needed by the application. This function is the equivalent of verifying the username and
|
||||
password in Basic authentication.
|
||||
|
||||
var credentialsFunc = function (id, callback) {
|
||||
|
||||
// Lookup credentials in database
|
||||
db.lookup(id, function (err, item) {
|
||||
|
||||
if (err || !item) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var credentials = {
|
||||
// Required
|
||||
key: item.key,
|
||||
algorithm: item.algorithm,
|
||||
// Application specific
|
||||
user: item.user
|
||||
};
|
||||
|
||||
return callback(null, credentials);
|
||||
});
|
||||
};
|
||||
|
||||
options: {
|
||||
|
||||
hostHeaderName: optional header field name, used to override the default 'Host' header when used
|
||||
behind a cache of a proxy. Apache2 changes the value of the 'Host' header while preserving
|
||||
the original (which is what the module must verify) in the 'x-forwarded-host' header field.
|
||||
Only used when passed a node Http.ServerRequest object.
|
||||
|
||||
nonceFunc: optional nonce validation function. The function signature is function(nonce, ts, callback)
|
||||
where 'callback' must be called using the signature function(err).
|
||||
|
||||
timestampSkewSec: optional number of seconds of permitted clock skew for incoming timestamps. Defaults to 60 seconds.
|
||||
Provides a +/- skew which means actual allowed window is double the number of seconds.
|
||||
|
||||
localtimeOffsetMsec: optional local clock time offset express in a number of milliseconds (positive or negative).
|
||||
Defaults to 0.
|
||||
|
||||
payload: optional payload for validation. The client calculates the hash value and includes it via the 'hash'
|
||||
header attribute. The server always ensures the value provided has been included in the request
|
||||
MAC. When this option is provided, it validates the hash value itself. Validation is done by calculating
|
||||
a hash value over the entire payload (assuming it has already be normalized to the same format and
|
||||
encoding used by the client to calculate the hash on request). If the payload is not available at the time
|
||||
of authentication, the authenticatePayload() method can be used by passing it the credentials and
|
||||
attributes.hash returned in the authenticate callback.
|
||||
}
|
||||
|
||||
callback: function (err, credentials, artifacts) { }
|
||||
*/
|
||||
|
||||
exports.authenticate = function (req, credentialsFunc, options, callback) {
|
||||
|
||||
// Default options
|
||||
|
||||
options.nonceFunc = options.nonceFunc || function (nonce, ts, callback) { return callback(); }; // No validation
|
||||
options.timestampSkewSec = options.timestampSkewSec || 60; // 60 seconds
|
||||
|
||||
// Application time
|
||||
|
||||
var now = Utils.now() + (options.localtimeOffsetMsec || 0); // Measure now before any other processing
|
||||
|
||||
// Convert node Http request object to a request configuration object
|
||||
|
||||
var request = Utils.parseRequest(req, options);
|
||||
if (request instanceof Error) {
|
||||
return callback(Boom.badRequest(request.message));
|
||||
}
|
||||
|
||||
// Parse HTTP Authorization header
|
||||
|
||||
var attributes = Utils.parseAuthorizationHeader(request.authorization);
|
||||
if (attributes instanceof Error) {
|
||||
return callback(attributes);
|
||||
}
|
||||
|
||||
// Construct artifacts container
|
||||
|
||||
var artifacts = {
|
||||
method: request.method,
|
||||
host: request.host,
|
||||
port: request.port,
|
||||
resource: request.url,
|
||||
ts: attributes.ts,
|
||||
nonce: attributes.nonce,
|
||||
hash: attributes.hash,
|
||||
ext: attributes.ext,
|
||||
app: attributes.app,
|
||||
dlg: attributes.dlg,
|
||||
mac: attributes.mac,
|
||||
id: attributes.id
|
||||
};
|
||||
|
||||
// Verify required header attributes
|
||||
|
||||
if (!attributes.id ||
|
||||
!attributes.ts ||
|
||||
!attributes.nonce ||
|
||||
!attributes.mac) {
|
||||
|
||||
return callback(Boom.badRequest('Missing attributes'), null, artifacts);
|
||||
}
|
||||
|
||||
// Fetch Hawk credentials
|
||||
|
||||
credentialsFunc(attributes.id, function (err, credentials) {
|
||||
|
||||
artifacts.credentials = credentials;
|
||||
|
||||
if (err) {
|
||||
return callback(err, credentials || null, artifacts);
|
||||
}
|
||||
|
||||
if (!credentials) {
|
||||
return callback(Boom.unauthorized('Unknown credentials', 'Hawk'), null, artifacts);
|
||||
}
|
||||
|
||||
if (!credentials.key ||
|
||||
!credentials.algorithm) {
|
||||
|
||||
return callback(Boom.internal('Invalid credentials'), credentials, artifacts);
|
||||
}
|
||||
|
||||
if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
|
||||
return callback(Boom.internal('Unknown algorithm'), credentials, artifacts);
|
||||
}
|
||||
|
||||
// Calculate MAC
|
||||
|
||||
var mac = Crypto.calculateMac('header', artifacts);
|
||||
if (!Cryptiles.fixedTimeComparison(mac, attributes.mac)) {
|
||||
return callback(Boom.unauthorized('Bad mac', 'Hawk'), credentials, artifacts);
|
||||
}
|
||||
|
||||
// Check payload hash
|
||||
|
||||
if (options.payload !== null &&
|
||||
options.payload !== undefined) { // '' is valid
|
||||
|
||||
if (!attributes.hash) {
|
||||
return callback(Boom.unauthorized('Missing required payload hash', 'Hawk'), credentials, artifacts);
|
||||
}
|
||||
|
||||
var hash = Crypto.calculateHash(options.payload, credentials.algorithm, request.contentType);
|
||||
if (!Cryptiles.fixedTimeComparison(hash, attributes.hash)) {
|
||||
return callback(Boom.unauthorized('Bad payload hash', 'Hawk'), credentials, artifacts);
|
||||
}
|
||||
}
|
||||
|
||||
// Check nonce
|
||||
|
||||
options.nonceFunc(attributes.nonce, attributes.ts, function (err) {
|
||||
|
||||
if (err) {
|
||||
return callback(Boom.unauthorized('Invalid nonce', 'Hawk'), credentials, artifacts);
|
||||
}
|
||||
|
||||
// Check timestamp staleness
|
||||
|
||||
if (Math.abs((attributes.ts * 1000) - now) > (options.timestampSkewSec * 1000)) {
|
||||
var fresh = Utils.now() + (options.localtimeOffsetMsec || 0); // Get fresh now
|
||||
var tsm = Crypto.calculateTsMac(fresh, credentials);
|
||||
return callback(Boom.unauthorized('Stale timestamp', 'Hawk', { ts: fresh, tsm: tsm }), credentials, artifacts);
|
||||
}
|
||||
|
||||
// Successful authentication
|
||||
|
||||
return callback(null, credentials, artifacts);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// Authenticate payload hash - used when payload cannot be provided during authenticate()
|
||||
|
||||
/*
|
||||
payload: raw request payload
|
||||
credentials: from authenticate callback
|
||||
hash: from authenticate callback (artifacts.hash)
|
||||
contentType: req.headers['content-type']
|
||||
*/
|
||||
|
||||
exports.authenticatePayload = function (payload, credentials, hash, contentType) {
|
||||
|
||||
var calculatedHash = Crypto.calculateHash(payload, credentials.algorithm, contentType);
|
||||
return Cryptiles.fixedTimeComparison(calculatedHash, hash);
|
||||
};
|
||||
|
||||
|
||||
// Generate a Server-Authorization header for a given response
|
||||
|
||||
/*
|
||||
artifacts: {} // Object received from authenticate(); 'mac', 'hash', and 'ext' - ignored
|
||||
options: {
|
||||
ext: 'application-specific', // Application specific data sent via the ext attribute
|
||||
payload: '{"some":"payload"}', // UTF-8 encoded string for body hash generation (ignored if hash provided)
|
||||
contentType: 'application/json', // Payload content-type (ignored if hash provided)
|
||||
hash: 'U4MKKSmiVxk37JCCrAVIjV=' // Pre-calculated payload hash
|
||||
}
|
||||
*/
|
||||
|
||||
exports.header = function (artifacts, options) {
|
||||
|
||||
// Prepare inputs
|
||||
|
||||
options = options || {};
|
||||
|
||||
if (!artifacts ||
|
||||
typeof artifacts !== 'object' ||
|
||||
typeof options !== 'object') {
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
artifacts = Hoek.clone(artifacts);
|
||||
delete artifacts.mac;
|
||||
artifacts.hash = options.hash;
|
||||
artifacts.ext = options.ext;
|
||||
|
||||
// Validate credentials
|
||||
|
||||
var credentials = artifacts.credentials;
|
||||
if (!credentials ||
|
||||
!credentials.key ||
|
||||
!credentials.algorithm) {
|
||||
|
||||
// Invalid credential object
|
||||
return '';
|
||||
}
|
||||
|
||||
if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Calculate payload hash
|
||||
|
||||
if (!artifacts.hash &&
|
||||
options.hasOwnProperty('payload')) {
|
||||
|
||||
artifacts.hash = Crypto.calculateHash(options.payload, credentials.algorithm, options.contentType);
|
||||
}
|
||||
|
||||
var mac = Crypto.calculateMac('response', artifacts);
|
||||
|
||||
// Construct header
|
||||
|
||||
var header = 'Hawk mac="' + mac + '"' +
|
||||
(artifacts.hash ? ', hash="' + artifacts.hash + '"' : '');
|
||||
|
||||
if (artifacts.ext !== null &&
|
||||
artifacts.ext !== undefined &&
|
||||
artifacts.ext !== '') { // Other falsey values allowed
|
||||
|
||||
header += ', ext="' + Utils.escapeHeaderAttribute(artifacts.ext) + '"';
|
||||
}
|
||||
|
||||
return header;
|
||||
};
|
238
node_modules/tabletop/node_modules/request/node_modules/hawk/lib/uri.js
generated
vendored
Executable file
238
node_modules/tabletop/node_modules/request/node_modules/hawk/lib/uri.js
generated
vendored
Executable file
@@ -0,0 +1,238 @@
|
||||
// Load modules
|
||||
|
||||
var Url = require('url');
|
||||
var Boom = require('boom');
|
||||
var Cryptiles = require('cryptiles');
|
||||
var Crypto = require('./crypto');
|
||||
var Utils = require('./utils');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
// Hawk authentication
|
||||
|
||||
/*
|
||||
* Arguments and options are the same as index.js with the exception that the only supported options are:
|
||||
* 'hostHeaderName', 'localtimeOffsetMsec'
|
||||
*/
|
||||
|
||||
exports.authenticate = function (req, credentialsFunc, options, callback) {
|
||||
|
||||
// Application time
|
||||
|
||||
var now = Utils.now() + (options.localtimeOffsetMsec || 0);
|
||||
|
||||
// Convert node Http request object to a request configuration object
|
||||
|
||||
var request = Utils.parseRequest(req, options);
|
||||
if (request instanceof Error) {
|
||||
return callback(Boom.badRequest(request.message));
|
||||
}
|
||||
|
||||
// Extract bewit
|
||||
|
||||
// 1 2 3 4
|
||||
var resource = request.url.match(/^(\/.*)([\?&])bewit\=([^&$]*)(?:&(.+))?$/);
|
||||
if (!resource) {
|
||||
return callback(Boom.unauthorized(null, 'Hawk'));
|
||||
}
|
||||
|
||||
// Bewit not empty
|
||||
|
||||
if (!resource[3]) {
|
||||
return callback(Boom.unauthorized('Empty bewit', 'Hawk'));
|
||||
}
|
||||
|
||||
// Verify method is GET
|
||||
|
||||
if (request.method !== 'GET' &&
|
||||
request.method !== 'HEAD') {
|
||||
|
||||
return callback(Boom.unauthorized('Invalid method', 'Hawk'));
|
||||
}
|
||||
|
||||
// No other authentication
|
||||
|
||||
if (request.authorization) {
|
||||
return callback(Boom.badRequest('Multiple authentications', 'Hawk'));
|
||||
}
|
||||
|
||||
// Parse bewit
|
||||
|
||||
var bewitString = Utils.base64urlDecode(resource[3]);
|
||||
if (bewitString instanceof Error) {
|
||||
return callback(Boom.badRequest('Invalid bewit encoding'));
|
||||
}
|
||||
|
||||
// Bewit format: id\exp\mac\ext ('\' is used because it is a reserved header attribute character)
|
||||
|
||||
var bewitParts = bewitString.split('\\');
|
||||
if (!bewitParts ||
|
||||
bewitParts.length !== 4) {
|
||||
|
||||
return callback(Boom.badRequest('Invalid bewit structure'));
|
||||
}
|
||||
|
||||
var bewit = {
|
||||
id: bewitParts[0],
|
||||
exp: parseInt(bewitParts[1], 10),
|
||||
mac: bewitParts[2],
|
||||
ext: bewitParts[3] || ''
|
||||
};
|
||||
|
||||
if (!bewit.id ||
|
||||
!bewit.exp ||
|
||||
!bewit.mac) {
|
||||
|
||||
return callback(Boom.badRequest('Missing bewit attributes'));
|
||||
}
|
||||
|
||||
// Construct URL without bewit
|
||||
|
||||
var url = resource[1];
|
||||
if (resource[4]) {
|
||||
url += resource[2] + resource[4];
|
||||
}
|
||||
|
||||
// Check expiration
|
||||
|
||||
if (bewit.exp * 1000 <= now) {
|
||||
return callback(Boom.unauthorized('Access expired', 'Hawk'), null, bewit);
|
||||
}
|
||||
|
||||
// Fetch Hawk credentials
|
||||
|
||||
credentialsFunc(bewit.id, function (err, credentials) {
|
||||
|
||||
if (err) {
|
||||
return callback(err, credentials || null, bewit.ext);
|
||||
}
|
||||
|
||||
if (!credentials) {
|
||||
return callback(Boom.unauthorized('Unknown credentials', 'Hawk'), null, bewit);
|
||||
}
|
||||
|
||||
if (!credentials.key ||
|
||||
!credentials.algorithm) {
|
||||
|
||||
return callback(Boom.internal('Invalid credentials'), credentials, bewit);
|
||||
}
|
||||
|
||||
if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
|
||||
return callback(Boom.internal('Unknown algorithm'), credentials, bewit);
|
||||
}
|
||||
|
||||
// Calculate MAC
|
||||
|
||||
var mac = Crypto.calculateMac('bewit', {
|
||||
credentials: credentials,
|
||||
ts: bewit.exp,
|
||||
nonce: '',
|
||||
method: 'GET',
|
||||
resource: url,
|
||||
host: request.host,
|
||||
port: request.port,
|
||||
ext: bewit.ext
|
||||
});
|
||||
|
||||
if (!Cryptiles.fixedTimeComparison(mac, bewit.mac)) {
|
||||
return callback(Boom.unauthorized('Bad mac', 'Hawk'), credentials, bewit);
|
||||
}
|
||||
|
||||
// Successful authentication
|
||||
|
||||
return callback(null, credentials, bewit);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// Generate a bewit value for a given URI
|
||||
|
||||
/*
|
||||
* credentials is an object with the following keys: 'id, 'key', 'algorithm'.
|
||||
* options is an object with the following optional keys: 'ext', 'localtimeOffsetMsec'
|
||||
*/
|
||||
/*
|
||||
uri: 'http://example.com/resource?a=b' or object from Url.parse()
|
||||
options: {
|
||||
|
||||
// Required
|
||||
|
||||
credentials: {
|
||||
id: 'dh37fgj492je',
|
||||
key: 'aoijedoaijsdlaksjdl',
|
||||
algorithm: 'sha256' // 'sha1', 'sha256'
|
||||
},
|
||||
ttlSec: 60 * 60, // TTL in seconds
|
||||
|
||||
// Optional
|
||||
|
||||
ext: 'application-specific', // Application specific data sent via the ext attribute
|
||||
localtimeOffsetMsec: 400 // Time offset to sync with server time
|
||||
};
|
||||
*/
|
||||
|
||||
exports.getBewit = function (uri, options) {
|
||||
|
||||
// Validate inputs
|
||||
|
||||
if (!uri ||
|
||||
(typeof uri !== 'string' && typeof uri !== 'object') ||
|
||||
!options ||
|
||||
typeof options !== 'object' ||
|
||||
!options.ttlSec) {
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
options.ext = (options.ext === null || options.ext === undefined ? '' : options.ext); // Zero is valid value
|
||||
|
||||
// Application time
|
||||
|
||||
var now = Utils.now() + (options.localtimeOffsetMsec || 0);
|
||||
|
||||
// Validate credentials
|
||||
|
||||
var credentials = options.credentials;
|
||||
if (!credentials ||
|
||||
!credentials.id ||
|
||||
!credentials.key ||
|
||||
!credentials.algorithm) {
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Parse URI
|
||||
|
||||
if (typeof uri === 'string') {
|
||||
uri = Url.parse(uri);
|
||||
}
|
||||
|
||||
// Calculate signature
|
||||
|
||||
var exp = Math.floor(now / 1000) + options.ttlSec;
|
||||
var mac = Crypto.calculateMac('bewit', {
|
||||
credentials: credentials,
|
||||
ts: exp,
|
||||
nonce: '',
|
||||
method: 'GET',
|
||||
resource: uri.pathname + (uri.search || ''), // Maintain trailing '?'
|
||||
host: uri.hostname,
|
||||
port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
|
||||
ext: options.ext
|
||||
});
|
||||
|
||||
// Construct bewit: id\exp\mac\ext
|
||||
|
||||
var bewit = credentials.id + '\\' + exp + '\\' + mac + '\\' + options.ext;
|
||||
return Utils.base64urlEncode(bewit);
|
||||
};
|
||||
|
||||
|
167
node_modules/tabletop/node_modules/request/node_modules/hawk/lib/utils.js
generated
vendored
Executable file
167
node_modules/tabletop/node_modules/request/node_modules/hawk/lib/utils.js
generated
vendored
Executable file
@@ -0,0 +1,167 @@
|
||||
// Load modules
|
||||
|
||||
var Hoek = require('hoek');
|
||||
var Sntp = require('sntp');
|
||||
var Boom = require('boom');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
// Import Hoek Utilities
|
||||
|
||||
internals.import = function () {
|
||||
|
||||
for (var i in Hoek) {
|
||||
if (Hoek.hasOwnProperty(i)) {
|
||||
exports[i] = Hoek[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
internals.import();
|
||||
|
||||
|
||||
// Hawk version
|
||||
|
||||
exports.version = function () {
|
||||
|
||||
return exports.loadPackage(__dirname + '/..').version;
|
||||
};
|
||||
|
||||
|
||||
// Extract host and port from request
|
||||
|
||||
exports.parseHost = function (req, hostHeaderName) {
|
||||
|
||||
hostHeaderName = (hostHeaderName ? hostHeaderName.toLowerCase() : 'host');
|
||||
var hostHeader = req.headers[hostHeaderName];
|
||||
if (!hostHeader) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var hostHeaderRegex = /^(?:(?:\r\n)?[\t ])*([^:]+)(?::(\d+))?(?:(?:\r\n)?[\t ])*$/; // Does not support IPv6
|
||||
var hostParts = hostHeader.match(hostHeaderRegex);
|
||||
|
||||
if (!hostParts ||
|
||||
hostParts.length !== 3 ||
|
||||
!hostParts[1]) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
name: hostParts[1],
|
||||
port: (hostParts[2] ? hostParts[2] : (req.connection && req.connection.encrypted ? 443 : 80))
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Parse Content-Type header content
|
||||
|
||||
exports.parseContentType = function (header) {
|
||||
|
||||
if (!header) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return header.split(';')[0].trim().toLowerCase();
|
||||
};
|
||||
|
||||
|
||||
// Convert node's to request configuration object
|
||||
|
||||
exports.parseRequest = function (req, options) {
|
||||
|
||||
if (!req.headers) {
|
||||
return req;
|
||||
}
|
||||
|
||||
// Obtain host and port information
|
||||
|
||||
var host = exports.parseHost(req, options.hostHeaderName);
|
||||
if (!host) {
|
||||
return new Error('Invalid Host header');
|
||||
}
|
||||
|
||||
var request = {
|
||||
method: req.method,
|
||||
url: req.url,
|
||||
host: host.name,
|
||||
port: host.port,
|
||||
authorization: req.headers.authorization,
|
||||
contentType: req.headers['content-type'] || ''
|
||||
};
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
|
||||
exports.now = function () {
|
||||
|
||||
return Sntp.now();
|
||||
};
|
||||
|
||||
|
||||
// Parse Hawk HTTP Authorization header
|
||||
|
||||
exports.parseAuthorizationHeader = function (header, keys) {
|
||||
|
||||
keys = keys || ['id', 'ts', 'nonce', 'hash', 'ext', 'mac', 'app', 'dlg'];
|
||||
|
||||
if (!header) {
|
||||
return Boom.unauthorized(null, 'Hawk');
|
||||
}
|
||||
|
||||
var headerParts = header.match(/^(\w+)(?:\s+(.*))?$/); // Header: scheme[ something]
|
||||
if (!headerParts) {
|
||||
return Boom.badRequest('Invalid header syntax');
|
||||
}
|
||||
|
||||
var scheme = headerParts[1];
|
||||
if (scheme.toLowerCase() !== 'hawk') {
|
||||
return Boom.unauthorized(null, 'Hawk');
|
||||
}
|
||||
|
||||
var attributesString = headerParts[2];
|
||||
if (!attributesString) {
|
||||
return Boom.badRequest('Invalid header syntax');
|
||||
}
|
||||
|
||||
var attributes = {};
|
||||
var errorMessage = '';
|
||||
var verify = attributesString.replace(/(\w+)="([^"\\]*)"\s*(?:,\s*|$)/g, function ($0, $1, $2) {
|
||||
|
||||
// Check valid attribute names
|
||||
|
||||
if (keys.indexOf($1) === -1) {
|
||||
errorMessage = 'Unknown attribute: ' + $1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Allowed attribute value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9
|
||||
|
||||
if ($2.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/) === null) {
|
||||
errorMessage = 'Bad attribute value: ' + $1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for duplicates
|
||||
|
||||
if (attributes.hasOwnProperty($1)) {
|
||||
errorMessage = 'Duplicate attribute: ' + $1;
|
||||
return;
|
||||
}
|
||||
|
||||
attributes[$1] = $2;
|
||||
return '';
|
||||
});
|
||||
|
||||
if (verify !== '') {
|
||||
return Boom.badRequest(errorMessage || 'Bad header format');
|
||||
}
|
||||
|
||||
return attributes;
|
||||
};
|
18
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/.npmignore
generated
vendored
Normal file
18
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
.idea
|
||||
*.iml
|
||||
npm-debug.log
|
||||
dump.rdb
|
||||
node_modules
|
||||
results.tap
|
||||
results.xml
|
||||
npm-shrinkwrap.json
|
||||
config.json
|
||||
.DS_Store
|
||||
*/.DS_Store
|
||||
*/*/.DS_Store
|
||||
._*
|
||||
*/._*
|
||||
*/*/._*
|
||||
coverage.*
|
||||
lib-cov
|
||||
|
5
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/.travis.yml
generated
vendored
Executable file
5
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/.travis.yml
generated
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- 0.8
|
||||
|
24
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/LICENSE
generated
vendored
Executable file
24
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/LICENSE
generated
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
Copyright (c) 2012-2013, Walmart.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Walmart nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL WALMART BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
11
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/Makefile
generated
vendored
Executable file
11
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/Makefile
generated
vendored
Executable file
@@ -0,0 +1,11 @@
|
||||
test:
|
||||
@./node_modules/.bin/lab
|
||||
test-cov:
|
||||
@./node_modules/.bin/lab -r threshold -t 100
|
||||
test-cov-html:
|
||||
@./node_modules/.bin/lab -r html -o coverage.html
|
||||
complexity:
|
||||
@./node_modules/.bin/cr -o complexity.md -f markdown lib
|
||||
|
||||
.PHONY: test test-cov test-cov-html complexity
|
||||
|
6
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/README.md
generated
vendored
Executable file
6
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/README.md
generated
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
<a href="https://github.com/spumko"><img src="https://raw.github.com/spumko/spumko/master/images/from.png" align="right" /></a>
|
||||

|
||||
|
||||
HTTP-friendly error objects
|
||||
|
||||
[](http://travis-ci.org/spumko/boom)
|
BIN
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/images/boom.png
generated
vendored
Executable file
BIN
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/images/boom.png
generated
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
1
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/index.js
generated
vendored
Executable file
1
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/index.js
generated
vendored
Executable file
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib');
|
207
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/lib/index.js
generated
vendored
Executable file
207
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/lib/index.js
generated
vendored
Executable file
@@ -0,0 +1,207 @@
|
||||
// Load modules
|
||||
|
||||
var Http = require('http');
|
||||
var NodeUtil = require('util');
|
||||
var Hoek = require('hoek');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
exports = module.exports = internals.Boom = function (/* (new Error) or (code, message) */) {
|
||||
|
||||
var self = this;
|
||||
|
||||
Hoek.assert(this.constructor === internals.Boom, 'Error must be instantiated using new');
|
||||
|
||||
Error.call(this);
|
||||
this.isBoom = true;
|
||||
|
||||
this.response = {
|
||||
code: 0,
|
||||
payload: {},
|
||||
headers: {}
|
||||
// type: 'content-type'
|
||||
};
|
||||
|
||||
if (arguments[0] instanceof Error) {
|
||||
|
||||
// Error
|
||||
|
||||
var error = arguments[0];
|
||||
|
||||
this.data = error;
|
||||
this.response.code = error.code || 500;
|
||||
if (error.message) {
|
||||
this.message = error.message;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// code, message
|
||||
|
||||
var code = arguments[0];
|
||||
var message = arguments[1];
|
||||
|
||||
Hoek.assert(!isNaN(parseFloat(code)) && isFinite(code) && code >= 400, 'First argument must be a number (400+)');
|
||||
|
||||
this.response.code = code;
|
||||
if (message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
// Response format
|
||||
|
||||
this.reformat();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
NodeUtil.inherits(internals.Boom, Error);
|
||||
|
||||
|
||||
internals.Boom.prototype.reformat = function () {
|
||||
|
||||
this.response.payload.code = this.response.code;
|
||||
this.response.payload.error = Http.STATUS_CODES[this.response.code] || 'Unknown';
|
||||
if (this.message) {
|
||||
this.response.payload.message = Hoek.escapeHtml(this.message); // Prevent XSS from error message
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Utilities
|
||||
|
||||
internals.Boom.badRequest = function (message) {
|
||||
|
||||
return new internals.Boom(400, message);
|
||||
};
|
||||
|
||||
|
||||
internals.Boom.unauthorized = function (error, scheme, attributes) { // Or function (error, wwwAuthenticate[])
|
||||
|
||||
var err = new internals.Boom(401, error);
|
||||
|
||||
if (!scheme) {
|
||||
return err;
|
||||
}
|
||||
|
||||
var wwwAuthenticate = '';
|
||||
|
||||
if (typeof scheme === 'string') {
|
||||
|
||||
// function (error, scheme, attributes)
|
||||
|
||||
wwwAuthenticate = scheme;
|
||||
if (attributes) {
|
||||
var names = Object.keys(attributes);
|
||||
for (var i = 0, il = names.length; i < il; ++i) {
|
||||
if (i) {
|
||||
wwwAuthenticate += ',';
|
||||
}
|
||||
|
||||
var value = attributes[names[i]];
|
||||
if (value === null ||
|
||||
value === undefined) { // Value can be zero
|
||||
|
||||
value = '';
|
||||
}
|
||||
wwwAuthenticate += ' ' + names[i] + '="' + Hoek.escapeHeaderAttribute(value.toString()) + '"';
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
if (attributes) {
|
||||
wwwAuthenticate += ',';
|
||||
}
|
||||
wwwAuthenticate += ' error="' + Hoek.escapeHeaderAttribute(error) + '"';
|
||||
}
|
||||
else {
|
||||
err.isMissing = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// function (error, wwwAuthenticate[])
|
||||
|
||||
var wwwArray = scheme;
|
||||
for (var i = 0, il = wwwArray.length; i < il; ++i) {
|
||||
if (i) {
|
||||
wwwAuthenticate += ', ';
|
||||
}
|
||||
|
||||
wwwAuthenticate += wwwArray[i];
|
||||
}
|
||||
}
|
||||
|
||||
err.response.headers['WWW-Authenticate'] = wwwAuthenticate;
|
||||
|
||||
return err;
|
||||
};
|
||||
|
||||
|
||||
internals.Boom.clientTimeout = function (message) {
|
||||
|
||||
return new internals.Boom(408, message);
|
||||
};
|
||||
|
||||
|
||||
internals.Boom.serverTimeout = function (message) {
|
||||
|
||||
return new internals.Boom(503, message);
|
||||
};
|
||||
|
||||
|
||||
internals.Boom.forbidden = function (message) {
|
||||
|
||||
return new internals.Boom(403, message);
|
||||
};
|
||||
|
||||
|
||||
internals.Boom.notFound = function (message) {
|
||||
|
||||
return new internals.Boom(404, message);
|
||||
};
|
||||
|
||||
|
||||
internals.Boom.internal = function (message, data) {
|
||||
|
||||
var err = new internals.Boom(500, message);
|
||||
|
||||
if (data && data.stack) {
|
||||
err.trace = data.stack.split('\n');
|
||||
err.outterTrace = Hoek.displayStack(1);
|
||||
}
|
||||
else {
|
||||
err.trace = Hoek.displayStack(1);
|
||||
}
|
||||
|
||||
err.data = data;
|
||||
err.response.payload.message = 'An internal server error occurred'; // Hide actual error from user
|
||||
|
||||
return err;
|
||||
};
|
||||
|
||||
|
||||
internals.Boom.passThrough = function (code, payload, contentType, headers) {
|
||||
|
||||
var err = new internals.Boom(500, 'Pass-through'); // 500 code is only used to initialize
|
||||
|
||||
err.data = {
|
||||
code: code,
|
||||
payload: payload,
|
||||
type: contentType
|
||||
};
|
||||
|
||||
err.response.code = code;
|
||||
err.response.type = contentType;
|
||||
err.response.headers = headers;
|
||||
err.response.payload = payload;
|
||||
|
||||
return err;
|
||||
};
|
||||
|
||||
|
43
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/package.json
generated
vendored
Executable file
43
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/package.json
generated
vendored
Executable file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "boom",
|
||||
"description": "HTTP-friendly error objects",
|
||||
"version": "0.3.8",
|
||||
"author": {
|
||||
"name": "Eran Hammer",
|
||||
"email": "eran@hueniverse.com",
|
||||
"url": "http://hueniverse.com"
|
||||
},
|
||||
"contributors": [],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/spumko/boom"
|
||||
},
|
||||
"main": "index",
|
||||
"keywords": [
|
||||
"error",
|
||||
"http"
|
||||
],
|
||||
"engines": {
|
||||
"node": "0.8.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"hoek": "0.7.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"lab": "0.0.x",
|
||||
"complexity-report": "0.x.x"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "make test-cov"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "BSD",
|
||||
"url": "http://github.com/spumko/boom/raw/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"readme": "<a href=\"https://github.com/spumko\"><img src=\"https://raw.github.com/spumko/spumko/master/images/from.png\" align=\"right\" /></a>\n\n\nHTTP-friendly error objects\n\n[](http://travis-ci.org/spumko/boom)\n",
|
||||
"readmeFilename": "README.md",
|
||||
"_id": "boom@0.3.8",
|
||||
"_from": "boom@0.3.x"
|
||||
}
|
245
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/test/index.js
generated
vendored
Executable file
245
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/boom/test/index.js
generated
vendored
Executable file
@@ -0,0 +1,245 @@
|
||||
// Load modules
|
||||
|
||||
var Lab = require('lab');
|
||||
var Boom = require('../lib');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
// Test shortcuts
|
||||
|
||||
var expect = Lab.expect;
|
||||
var before = Lab.before;
|
||||
var after = Lab.after;
|
||||
var describe = Lab.experiment;
|
||||
var it = Lab.test;
|
||||
|
||||
|
||||
describe('Boom', function () {
|
||||
|
||||
it('returns an error with info when constructed using another error', function (done) {
|
||||
|
||||
var error = new Error('ka-boom');
|
||||
error.xyz = 123;
|
||||
var err = new Boom(error);
|
||||
expect(err.data.xyz).to.equal(123);
|
||||
expect(err.message).to.equal('ka-boom');
|
||||
expect(err.response).to.deep.equal({
|
||||
code: 500,
|
||||
payload: {
|
||||
code: 500,
|
||||
error: 'Internal Server Error',
|
||||
message: 'ka-boom'
|
||||
},
|
||||
headers: {}
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
||||
describe('#isBoom', function () {
|
||||
|
||||
it('returns true for Boom object', function (done) {
|
||||
|
||||
expect(Boom.badRequest().isBoom).to.equal(true);
|
||||
done();
|
||||
});
|
||||
|
||||
it('returns false for Error object', function (done) {
|
||||
|
||||
expect(new Error().isBoom).to.not.exist;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#badRequest', function () {
|
||||
|
||||
it('returns a 400 error code', function (done) {
|
||||
|
||||
expect(Boom.badRequest().response.code).to.equal(400);
|
||||
done();
|
||||
});
|
||||
|
||||
it('sets the message with the passed in message', function (done) {
|
||||
|
||||
expect(Boom.badRequest('my message').message).to.equal('my message');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#unauthorized', function () {
|
||||
|
||||
it('returns a 401 error code', function (done) {
|
||||
|
||||
var err = Boom.unauthorized();
|
||||
expect(err.response.code).to.equal(401);
|
||||
expect(err.response.headers).to.deep.equal({});
|
||||
done();
|
||||
});
|
||||
|
||||
it('sets the message with the passed in message', function (done) {
|
||||
|
||||
expect(Boom.unauthorized('my message').message).to.equal('my message');
|
||||
done();
|
||||
});
|
||||
|
||||
it('returns a WWW-Authenticate header when passed a scheme', function (done) {
|
||||
|
||||
var err = Boom.unauthorized('boom', 'Test');
|
||||
expect(err.response.code).to.equal(401);
|
||||
expect(err.response.headers['WWW-Authenticate']).to.equal('Test error="boom"');
|
||||
done();
|
||||
});
|
||||
|
||||
it('returns a WWW-Authenticate header when passed a scheme and attributes', function (done) {
|
||||
|
||||
var err = Boom.unauthorized('boom', 'Test', { a: 1, b: 'something', c: null, d: 0 });
|
||||
expect(err.response.code).to.equal(401);
|
||||
expect(err.response.headers['WWW-Authenticate']).to.equal('Test a="1", b="something", c="", d="0", error="boom"');
|
||||
done();
|
||||
});
|
||||
|
||||
it('sets the isMissing flag when error message is empty', function (done) {
|
||||
|
||||
var err = Boom.unauthorized('', 'Basic');
|
||||
expect(err.isMissing).to.equal(true);
|
||||
done();
|
||||
});
|
||||
|
||||
it('does not set the isMissing flag when error message is not empty', function (done) {
|
||||
|
||||
var err = Boom.unauthorized('message', 'Basic');
|
||||
expect(err.isMissing).to.equal(undefined);
|
||||
done();
|
||||
});
|
||||
|
||||
it('sets a WWW-Authenticate when passed as an array', function (done) {
|
||||
|
||||
var err = Boom.unauthorized('message', ['Basic', 'Example e="1"', 'Another x="3", y="4"']);
|
||||
expect(err.response.headers['WWW-Authenticate']).to.equal('Basic, Example e="1", Another x="3", y="4"');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clientTimeout', function () {
|
||||
|
||||
it('returns a 408 error code', function (done) {
|
||||
|
||||
expect(Boom.clientTimeout().response.code).to.equal(408);
|
||||
done();
|
||||
});
|
||||
|
||||
it('sets the message with the passed in message', function (done) {
|
||||
|
||||
expect(Boom.clientTimeout('my message').message).to.equal('my message');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#serverTimeout', function () {
|
||||
|
||||
it('returns a 503 error code', function (done) {
|
||||
|
||||
expect(Boom.serverTimeout().response.code).to.equal(503);
|
||||
done();
|
||||
});
|
||||
|
||||
it('sets the message with the passed in message', function (done) {
|
||||
|
||||
expect(Boom.serverTimeout('my message').message).to.equal('my message');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#forbidden', function () {
|
||||
|
||||
it('returns a 403 error code', function (done) {
|
||||
|
||||
expect(Boom.forbidden().response.code).to.equal(403);
|
||||
done();
|
||||
});
|
||||
|
||||
it('sets the message with the passed in message', function (done) {
|
||||
|
||||
expect(Boom.forbidden('my message').message).to.equal('my message');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#notFound', function () {
|
||||
|
||||
it('returns a 404 error code', function (done) {
|
||||
|
||||
expect(Boom.notFound().response.code).to.equal(404);
|
||||
done();
|
||||
});
|
||||
|
||||
it('sets the message with the passed in message', function (done) {
|
||||
|
||||
expect(Boom.notFound('my message').message).to.equal('my message');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#internal', function () {
|
||||
|
||||
it('returns a 500 error code', function (done) {
|
||||
|
||||
expect(Boom.internal().response.code).to.equal(500);
|
||||
done();
|
||||
});
|
||||
|
||||
it('sets the message with the passed in message', function (done) {
|
||||
|
||||
var err = Boom.internal('my message');
|
||||
expect(err.message).to.equal('my message');
|
||||
expect(err.response.payload.message).to.equal('An internal server error occurred');
|
||||
done();
|
||||
});
|
||||
|
||||
it('passes data on the callback if its passed in', function (done) {
|
||||
|
||||
expect(Boom.internal('my message', { my: 'data' }).data.my).to.equal('data');
|
||||
done();
|
||||
});
|
||||
|
||||
it('uses passed in stack if its available', function (done) {
|
||||
|
||||
var error = new Error();
|
||||
error.stack = 'my stack line\nmy second stack line';
|
||||
expect(Boom.internal('my message', error).trace[0]).to.equal('my stack line');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#passThrough', function () {
|
||||
|
||||
it('returns a pass-through error', function (done) {
|
||||
|
||||
var err = Boom.passThrough(499, { a: 1 }, 'application/text', { 'X-Test': 'Boom' });
|
||||
expect(err.response.code).to.equal(499);
|
||||
expect(err.message).to.equal('Pass-through');
|
||||
expect(err.response).to.deep.equal({
|
||||
code: 499,
|
||||
payload: { a: 1 },
|
||||
headers: { 'X-Test': 'Boom' },
|
||||
type: 'application/text'
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#reformat', function () {
|
||||
|
||||
it('encodes any HTML markup in the response payload', function (done) {
|
||||
|
||||
var boom = new Boom(new Error('<script>alert(1)</script>'));
|
||||
expect(boom.response.payload.message).to.not.contain('<script>');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
18
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/.npmignore
generated
vendored
Normal file
18
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
.idea
|
||||
*.iml
|
||||
npm-debug.log
|
||||
dump.rdb
|
||||
node_modules
|
||||
results.tap
|
||||
results.xml
|
||||
npm-shrinkwrap.json
|
||||
config.json
|
||||
.DS_Store
|
||||
*/.DS_Store
|
||||
*/*/.DS_Store
|
||||
._*
|
||||
*/._*
|
||||
*/*/._*
|
||||
coverage.*
|
||||
lib-cov
|
||||
|
5
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/.travis.yml
generated
vendored
Executable file
5
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/.travis.yml
generated
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- 0.8
|
||||
|
24
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/LICENSE
generated
vendored
Executable file
24
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/LICENSE
generated
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
Copyright (c) 2012-2013, Eran Hammer.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Eran Hammer nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL ERAN HAMMER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
11
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/Makefile
generated
vendored
Executable file
11
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/Makefile
generated
vendored
Executable file
@@ -0,0 +1,11 @@
|
||||
test:
|
||||
@./node_modules/.bin/lab
|
||||
test-cov:
|
||||
@./node_modules/.bin/lab -r threshold -t 100
|
||||
test-cov-html:
|
||||
@./node_modules/.bin/lab -r html -o coverage.html
|
||||
complexity:
|
||||
@./node_modules/.bin/cr -o complexity.md -f markdown lib
|
||||
|
||||
.PHONY: test test-cov test-cov-html complexity
|
||||
|
6
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/README.md
generated
vendored
Normal file
6
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/README.md
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
cryptiles
|
||||
=========
|
||||
|
||||
General purpose crypto utilities
|
||||
|
||||
[](http://travis-ci.org/hueniverse/cryptiles)
|
1
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/index.js
generated
vendored
Executable file
1
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/index.js
generated
vendored
Executable file
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib');
|
62
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/lib/index.js
generated
vendored
Executable file
62
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/lib/index.js
generated
vendored
Executable file
@@ -0,0 +1,62 @@
|
||||
// Load modules
|
||||
|
||||
var Crypto = require('crypto');
|
||||
var Boom = require('boom');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
// Generate a cryptographically strong pseudo-random data
|
||||
|
||||
exports.randomString = function (size) {
|
||||
|
||||
var buffer = exports.randomBits((size + 1) * 6);
|
||||
if (buffer instanceof Error) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
var string = buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
|
||||
return string.slice(0, size);
|
||||
};
|
||||
|
||||
|
||||
exports.randomBits = function (bits) {
|
||||
|
||||
if (!bits ||
|
||||
bits < 0) {
|
||||
|
||||
return Boom.internal('Invalid random bits count');
|
||||
}
|
||||
|
||||
var bytes = Math.ceil(bits / 8);
|
||||
try {
|
||||
return Crypto.randomBytes(bytes);
|
||||
}
|
||||
catch (err) {
|
||||
return Boom.internal('Failed generating random bits: ' + err.message);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Compare two strings using fixed time algorithm (to prevent time-based analysis of MAC digest match)
|
||||
|
||||
exports.fixedTimeComparison = function (a, b) {
|
||||
|
||||
var mismatch = (a.length === b.length ? 0 : 1);
|
||||
if (mismatch) {
|
||||
b = a;
|
||||
}
|
||||
|
||||
for (var i = 0, il = a.length; i < il; ++i) {
|
||||
var ac = a.charCodeAt(i);
|
||||
var bc = b.charCodeAt(i);
|
||||
mismatch += (ac === bc ? 0 : 1);
|
||||
}
|
||||
|
||||
return (mismatch === 0);
|
||||
};
|
||||
|
||||
|
44
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/package.json
generated
vendored
Executable file
44
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/package.json
generated
vendored
Executable file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "cryptiles",
|
||||
"description": "General purpose crypto utilities",
|
||||
"version": "0.1.3",
|
||||
"author": {
|
||||
"name": "Eran Hammer",
|
||||
"email": "eran@hueniverse.com",
|
||||
"url": "http://hueniverse.com"
|
||||
},
|
||||
"contributors": [],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/hueniverse/cryptiles"
|
||||
},
|
||||
"main": "index",
|
||||
"keywords": [
|
||||
"cryptography",
|
||||
"security",
|
||||
"utilites"
|
||||
],
|
||||
"engines": {
|
||||
"node": "0.8.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"boom": "0.3.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"lab": "0.0.x",
|
||||
"complexity-report": "0.x.x"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "make test-cov"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "BSD",
|
||||
"url": "http://github.com/hueniverse/cryptiles/raw/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"readme": "cryptiles\n=========\n\nGeneral purpose crypto utilities\n\n[](http://travis-ci.org/hueniverse/cryptiles)\n",
|
||||
"readmeFilename": "README.md",
|
||||
"_id": "cryptiles@0.1.3",
|
||||
"_from": "cryptiles@0.1.x"
|
||||
}
|
95
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/test/index.js
generated
vendored
Executable file
95
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/cryptiles/test/index.js
generated
vendored
Executable file
@@ -0,0 +1,95 @@
|
||||
// Load modules
|
||||
|
||||
var Lab = require('lab');
|
||||
var Cryptiles = require('../lib');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
// Test shortcuts
|
||||
|
||||
var expect = Lab.expect;
|
||||
var before = Lab.before;
|
||||
var after = Lab.after;
|
||||
var describe = Lab.experiment;
|
||||
var it = Lab.test;
|
||||
|
||||
|
||||
describe('Cryptiles', function () {
|
||||
|
||||
describe('#randomString', function () {
|
||||
|
||||
it('should generate the right length string', function (done) {
|
||||
|
||||
for (var i = 1; i <= 1000; ++i) {
|
||||
expect(Cryptiles.randomString(i).length).to.equal(i);
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('returns an error on invalid bits size', function (done) {
|
||||
|
||||
expect(Cryptiles.randomString(99999999999999999999).message).to.equal('Failed generating random bits: Argument #1 must be number > 0');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#randomBits', function () {
|
||||
|
||||
it('returns an error on invalid input', function (done) {
|
||||
|
||||
expect(Cryptiles.randomBits(0).message).to.equal('Invalid random bits count');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#fixedTimeComparison', function () {
|
||||
|
||||
var a = Cryptiles.randomString(50000);
|
||||
var b = Cryptiles.randomString(150000);
|
||||
|
||||
it('should take the same amount of time comparing different string sizes', function (done) {
|
||||
|
||||
var now = Date.now();
|
||||
Cryptiles.fixedTimeComparison(b, a);
|
||||
var t1 = Date.now() - now;
|
||||
|
||||
now = Date.now();
|
||||
Cryptiles.fixedTimeComparison(b, b);
|
||||
var t2 = Date.now() - now;
|
||||
|
||||
expect(t2 - t1).to.be.within(-20, 20);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should return true for equal strings', function (done) {
|
||||
|
||||
expect(Cryptiles.fixedTimeComparison(a, a)).to.equal(true);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should return false for different strings (size, a < b)', function (done) {
|
||||
|
||||
expect(Cryptiles.fixedTimeComparison(a, a + 'x')).to.equal(false);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should return false for different strings (size, a > b)', function (done) {
|
||||
|
||||
expect(Cryptiles.fixedTimeComparison(a + 'x', a)).to.equal(false);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should return false for different strings (size, a = b)', function (done) {
|
||||
|
||||
expect(Cryptiles.fixedTimeComparison(a + 'x', a + 'y')).to.equal(false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
18
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/.npmignore
generated
vendored
Normal file
18
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
.idea
|
||||
*.iml
|
||||
npm-debug.log
|
||||
dump.rdb
|
||||
node_modules
|
||||
results.tap
|
||||
results.xml
|
||||
npm-shrinkwrap.json
|
||||
config.json
|
||||
.DS_Store
|
||||
*/.DS_Store
|
||||
*/*/.DS_Store
|
||||
._*
|
||||
*/._*
|
||||
*/*/._*
|
||||
coverage.*
|
||||
lib-cov
|
||||
complexity.md
|
5
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/.travis.yml
generated
vendored
Executable file
5
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/.travis.yml
generated
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- 0.8
|
||||
|
33
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE
generated
vendored
Executable file
33
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE
generated
vendored
Executable file
@@ -0,0 +1,33 @@
|
||||
Copyright (c) 2011-2013, Walmart.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Walmart nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL WALMART BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
|
||||
Portions of this project were initially based on Postmile, Copyright (c) 2011, Yahoo Inc.
|
||||
Postmile is published at https://github.com/yahoo/postmile and its licensing terms are
|
||||
published at https://github.com/yahoo/postmile/blob/master/LICENSE.
|
||||
|
10
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/Makefile
generated
vendored
Executable file
10
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/Makefile
generated
vendored
Executable file
@@ -0,0 +1,10 @@
|
||||
test:
|
||||
@./node_modules/.bin/lab
|
||||
test-cov:
|
||||
@./node_modules/.bin/lab -r threshold -t 100
|
||||
test-cov-html:
|
||||
@./node_modules/.bin/lab -r html -o coverage.html
|
||||
complexity:
|
||||
@./node_modules/.bin/cr -o complexity.md -f markdown lib
|
||||
|
||||
.PHONY: test test-cov test-cov-html complexity
|
436
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/README.md
generated
vendored
Executable file
436
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/README.md
generated
vendored
Executable file
@@ -0,0 +1,436 @@
|
||||
<a href="https://github.com/spumko"><img src="https://raw.github.com/spumko/spumko/master/images/from.png" align="right" /></a>
|
||||

|
||||
|
||||
General purpose node utilities
|
||||
|
||||
[](http://travis-ci.org/spumko/hoek)
|
||||
|
||||
# Table of Contents
|
||||
|
||||
* [Introduction](#introduction "Introduction")
|
||||
* [Object](#object "Object")
|
||||
* [clone](#cloneobj "clone")
|
||||
* [merge](#mergetarget-source-isnulloverride-ismergearrays "merge")
|
||||
* [applyToDefaults](#applytodefaultsdefaults-options "applyToDefaults")
|
||||
* [unique](#uniquearray-key "unique")
|
||||
* [mapToObject](#maptoobjectarray-key "mapToObject")
|
||||
* [intersect](#intersectarray1-array2 "intersect")
|
||||
* [matchKeys](#matchkeysobj-keys "matchKeys")
|
||||
* [flatten](#flattenarray-target "flatten")
|
||||
* [removeKeys](#removekeysobject-keys "removeKeys")
|
||||
* [reach](#reachobj-chain "reach")
|
||||
* [inheritAsync](#inheritasyncself-obj-keys "inheritAsync")
|
||||
* [rename](#renameobj-from-to "rename")
|
||||
* [Timer](#timer "Timer")
|
||||
* [Binary Encoding/Decoding](#binary "Binary Encoding/Decoding")
|
||||
* [base64urlEncode](#binary64urlEncodevalue "binary64urlEncode")
|
||||
* [base64urlDecode](#binary64urlDecodevalue "binary64urlDecode")
|
||||
* [Escaping Characters](#escaped "Escaping Characters")
|
||||
* [escapeHtml](#escapeHtmlstring "escapeHtml")
|
||||
* [escapeHeaderAttribute](#escapeHeaderAttributeattribute "escapeHeaderAttribute")
|
||||
* [escapeRegex](#escapeRegexstring "escapeRegex")
|
||||
* [Errors](#errors "Errors")
|
||||
* [assert](#assertmessage "assert")
|
||||
* [abort](#abortmessage "abort")
|
||||
* [displayStack](#displayStackslice "displayStack")
|
||||
* [callStack](#callStackslice "callStack")
|
||||
* [toss](#tosscondition "toss")
|
||||
* [Load files](#load-files "Load Files")
|
||||
* [loadPackage](#loadPackagedir "loadpackage")
|
||||
* [loadDirModules](#loadDirModulespath-excludefiles-target "loaddirmodules")
|
||||
|
||||
|
||||
|
||||
# Introduction
|
||||
|
||||
The *Hoek* general purpose node utilities library is used to aid in a variety of manners. It comes with useful methods for Ararys (clone, merge, applyToDefaults), Objects (removeKeys, copy), Asserting and more.
|
||||
|
||||
For example, to use Hoek to set configuration with default options:
|
||||
```javascript
|
||||
var Hoek = require('hoek');
|
||||
|
||||
var default = {url : "www.github.com", port : "8000", debug : true}
|
||||
|
||||
var config = Hoek.applyToDefaults(default, {port : "3000", admin : true});
|
||||
|
||||
// In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true }
|
||||
```
|
||||
|
||||
Under each of the sections (such as Array), there are subsections which correspond to Hoek methods. Each subsection will explain how to use the corresponding method. In each js excerpt below, the var Hoek = require('hoek') is omitted for brevity.
|
||||
|
||||
## Object
|
||||
|
||||
Hoek provides several helpful methods for objects and arrays.
|
||||
|
||||
### clone(obj)
|
||||
|
||||
This method is used to clone an object or an array. A *deep copy* is made (duplicates everything, including values that are objects).
|
||||
|
||||
```javascript
|
||||
|
||||
var nestedObj = {
|
||||
w: /^something$/ig,
|
||||
x: {
|
||||
a: [1, 2, 3],
|
||||
b: 123456,
|
||||
c: new Date()
|
||||
},
|
||||
y: 'y',
|
||||
z: new Date()
|
||||
};
|
||||
|
||||
var copy = Hoek.clone(nestedObj);
|
||||
|
||||
copy.x.b = 100;
|
||||
|
||||
console.log(copy.y) // results in 'y'
|
||||
console.log(nestedObj.x.b) // results in 123456
|
||||
console.log(copy.x.b) // results in 100
|
||||
```
|
||||
|
||||
### merge(target, source, isNullOverride, isMergeArrays)
|
||||
isNullOverride, isMergeArrays default to true
|
||||
|
||||
Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied
|
||||
|
||||
|
||||
```javascript
|
||||
|
||||
var target = {a: 1, b : 2}
|
||||
var source = {a: 0, c: 5}
|
||||
var source2 = {a: null, c: 5}
|
||||
|
||||
var targetArray = [1, 2, 3];
|
||||
var sourceArray = [4, 5];
|
||||
|
||||
var newTarget = Hoek.merge(target, source); // results in {a: 0, b: 2, c: 5}
|
||||
newTarget = Hoek.merge(target, source2); // results in {a: null, b: 2, c: 5}
|
||||
newTarget = Hoek.merge(target, source2, false); // results in {a: null, b:2, c: 5}
|
||||
|
||||
newTarget = Hoek.merge(targetArray, sourceArray) // results in [1, 2, 3, 4, 5]
|
||||
newTarget = Hoek.merge(targetArray, sourceArray, true, false) // results in [4, 5]
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
### applyToDefaults(defaults, options)
|
||||
|
||||
Apply options to a copy of the defaults
|
||||
|
||||
```javascript
|
||||
|
||||
var defaults = {host: "localhost", port: 8000};
|
||||
var options = {port: 8080};
|
||||
|
||||
var config = Hoek.applyToDefaults(defaults, options); // results in {host: "localhost", port: 8080};
|
||||
|
||||
|
||||
```
|
||||
|
||||
### unique(array, key)
|
||||
|
||||
Remove duplicate items from Array
|
||||
|
||||
```javascript
|
||||
|
||||
var array = [1, 2, 2, 3, 3, 4, 5, 6];
|
||||
|
||||
var newArray = Hoek.unique(array); // results in [1,2,3,4,5,6];
|
||||
|
||||
array = [{id: 1}, {id: 1}, {id: 2}];
|
||||
|
||||
newArray = Hoek.unique(array, "id") // results in [{id: 1}, {id: 2}]
|
||||
|
||||
```
|
||||
|
||||
### mapToObject(array, key)
|
||||
|
||||
Convert an Array into an Object
|
||||
|
||||
```javascript
|
||||
|
||||
var array = [1,2,3];
|
||||
var newObject = Hoek.mapToObject(array); // results in [{"1": true}, {"2": true}, {"3": true}]
|
||||
|
||||
array = [{id: 1}, {id: 2}];
|
||||
newObject = Hoek.mapToObject(array, "id") // results in [{"id": 1}, {"id": 2}]
|
||||
|
||||
```
|
||||
### intersect(array1, array2)
|
||||
|
||||
Find the common unique items in two arrays
|
||||
|
||||
```javascript
|
||||
|
||||
var array1 = [1, 2, 3];
|
||||
var array2 = [1, 4, 5];
|
||||
|
||||
var newArray = Hoek.intersect(array1, array2) // results in [1]
|
||||
|
||||
```
|
||||
|
||||
### matchKeys(obj, keys)
|
||||
|
||||
Find which keys are present
|
||||
|
||||
```javascript
|
||||
|
||||
var obj = {a: 1, b: 2, c: 3};
|
||||
var keys = ["a", "e"];
|
||||
|
||||
Hoek.matchKeys(obj, keys) // returns ["a"]
|
||||
|
||||
```
|
||||
|
||||
### flatten(array, target)
|
||||
|
||||
Flatten an array
|
||||
|
||||
```javascript
|
||||
|
||||
var array = [1, 2, 3];
|
||||
var target = [4, 5];
|
||||
|
||||
var flattenedArray = Hoek.flatten(array, target) // results in [4, 5, 1, 2, 3];
|
||||
|
||||
```
|
||||
|
||||
### removeKeys(object, keys)
|
||||
|
||||
Remove keys
|
||||
|
||||
```javascript
|
||||
|
||||
var object = {a: 1, b: 2, c: 3, d: 4};
|
||||
|
||||
var keys = ["a", "b"];
|
||||
|
||||
Hoek.removeKeys(object, keys) // object is now {c: 3, d: 4}
|
||||
|
||||
```
|
||||
|
||||
### reach(obj, chain)
|
||||
|
||||
Converts an object key chain string to reference
|
||||
|
||||
```javascript
|
||||
|
||||
var chain = 'a.b.c';
|
||||
var obj = {a : {b : { c : 1}}};
|
||||
|
||||
Hoek.reach(obj, chain) // returns 1
|
||||
|
||||
```
|
||||
|
||||
### inheritAsync(self, obj, keys)
|
||||
|
||||
Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors
|
||||
|
||||
```javascript
|
||||
|
||||
var targetFunc = function () { };
|
||||
|
||||
var proto = {
|
||||
a: function () {
|
||||
return 'a!';
|
||||
},
|
||||
b: function () {
|
||||
return 'b!';
|
||||
},
|
||||
c: function () {
|
||||
throw new Error('c!');
|
||||
}
|
||||
};
|
||||
|
||||
var keys = ['a', 'c'];
|
||||
|
||||
Hoek.inheritAsync(targetFunc, proto, ['a', 'c']);
|
||||
|
||||
var target = new targetFunc();
|
||||
|
||||
target.a(function(err, result){console.log(result)} // returns 'a!'
|
||||
|
||||
target.c(function(err, result){console.log(result)} // returns undefined
|
||||
|
||||
target.b(function(err, result){console.log(result)} // gives error: Object [object Object] has no method 'b'
|
||||
|
||||
```
|
||||
|
||||
### rename(obj, from, to)
|
||||
|
||||
Rename a key of an object
|
||||
|
||||
```javascript
|
||||
|
||||
var obj = {a : 1, b : 2};
|
||||
|
||||
Hoek.rename(obj, "a", "c"); // obj is now {c : 1, b : 2}
|
||||
|
||||
```
|
||||
|
||||
|
||||
# Timer
|
||||
|
||||
A Timer object. Initializing a new timer object sets the ts to the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.
|
||||
|
||||
```javascript
|
||||
|
||||
|
||||
example :
|
||||
|
||||
|
||||
var timerObj = new Hoek.Timer();
|
||||
console.log("Time is now: " + timerObj.ts)
|
||||
console.log("Elapsed time from initialization: " + timerObj.elapsed() + 'milliseconds')
|
||||
|
||||
```
|
||||
|
||||
# Binary Encoding/Decoding
|
||||
|
||||
### base64urlEncode(value)
|
||||
|
||||
Encodes value in Base64 or URL encoding
|
||||
|
||||
### base64urlDecode(value)
|
||||
|
||||
Decodes data in Base64 or URL encoding.
|
||||
# Escaping Characters
|
||||
|
||||
Hoek provides convenient methods for escaping html characters. The escaped characters are as followed:
|
||||
|
||||
```javascript
|
||||
|
||||
internals.htmlEscaped = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
'`': '`'
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### escapeHtml(string)
|
||||
|
||||
```javascript
|
||||
|
||||
var string = '<html> hey </html>';
|
||||
var escapedString = Hoek.escapeHtml(string); // returns <html> hey </html>
|
||||
|
||||
```
|
||||
|
||||
### escapeHeaderAttribute(attribute)
|
||||
|
||||
Escape attribute value for use in HTTP header
|
||||
|
||||
```javascript
|
||||
|
||||
var a = Hoek.escapeHeaderAttribute('I said "go w\\o me"'); //returns I said \"go w\\o me\"
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
### escapeRegex(string)
|
||||
|
||||
Escape string for Regex construction
|
||||
|
||||
```javascript
|
||||
|
||||
var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,'); // returns 4\^f\$s\.4\*5\+\-_\?%\=#\!\:@\|~\\\/`"\(>\)\[<\]d\{\}s\,
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
# Errors
|
||||
|
||||
### assert(message)
|
||||
|
||||
```javascript
|
||||
|
||||
var a = 1, b =2;
|
||||
|
||||
Hoek.assert(a === b, 'a should equal b'); // ABORT: a should equal b
|
||||
|
||||
```
|
||||
|
||||
### abort(message)
|
||||
|
||||
First checks if process.env.NODE_ENV === 'test', and if so, throws error message. Otherwise,
|
||||
displays most recent stack and then exits process.
|
||||
|
||||
|
||||
|
||||
### displayStack(slice)
|
||||
|
||||
Displays the trace stack
|
||||
|
||||
```javascript
|
||||
|
||||
var stack = Hoek.displayStack();
|
||||
console.log(stack) // returns something like:
|
||||
|
||||
[ 'null (/Users/user/Desktop/hoek/test.js:4:18)',
|
||||
'Module._compile (module.js:449:26)',
|
||||
'Module._extensions..js (module.js:467:10)',
|
||||
'Module.load (module.js:356:32)',
|
||||
'Module._load (module.js:312:12)',
|
||||
'Module.runMain (module.js:492:10)',
|
||||
'startup.processNextTick.process._tickCallback (node.js:244:9)' ]
|
||||
|
||||
```
|
||||
|
||||
### callStack(slice)
|
||||
|
||||
Returns a trace stack array.
|
||||
|
||||
```javascript
|
||||
|
||||
var stack = Hoek.callStack();
|
||||
console.log(stack) // returns something like:
|
||||
|
||||
[ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ],
|
||||
[ 'module.js', 449, 26, 'Module._compile', false ],
|
||||
[ 'module.js', 467, 10, 'Module._extensions..js', false ],
|
||||
[ 'module.js', 356, 32, 'Module.load', false ],
|
||||
[ 'module.js', 312, 12, 'Module._load', false ],
|
||||
[ 'module.js', 492, 10, 'Module.runMain', false ],
|
||||
[ 'node.js',
|
||||
244,
|
||||
9,
|
||||
'startup.processNextTick.process._tickCallback',
|
||||
false ] ]
|
||||
|
||||
|
||||
```
|
||||
|
||||
### toss(condition)
|
||||
|
||||
toss(condition /*, [message], callback */)
|
||||
|
||||
Return an error as first argument of a callback
|
||||
|
||||
|
||||
# Load Files
|
||||
|
||||
### loadPackage(dir)
|
||||
|
||||
Load and parse package.json process root or given directory
|
||||
|
||||
```javascript
|
||||
|
||||
var pack = Hoek.loadPackage(); // pack.name === 'hoek'
|
||||
|
||||
```
|
||||
|
||||
### loadDirModules(path, excludeFiles, target)
|
||||
|
||||
Loads modules from a given path; option to exclude files (array).
|
||||
|
||||
|
||||
|
||||
|
BIN
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/images/hoek.png
generated
vendored
Executable file
BIN
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/images/hoek.png
generated
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
1
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/index.js
generated
vendored
Executable file
1
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/index.js
generated
vendored
Executable file
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib');
|
132
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/lib/escape.js
generated
vendored
Executable file
132
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/lib/escape.js
generated
vendored
Executable file
@@ -0,0 +1,132 @@
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
exports.escapeJavaScript = function (input) {
|
||||
|
||||
if (!input) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var escaped = '';
|
||||
|
||||
for (var i = 0, il = input.length; i < il; ++i) {
|
||||
|
||||
var charCode = input.charCodeAt(i);
|
||||
|
||||
if (internals.isSafe(charCode)) {
|
||||
escaped += input[i];
|
||||
}
|
||||
else {
|
||||
escaped += internals.escapeJavaScriptChar(charCode);
|
||||
}
|
||||
}
|
||||
|
||||
return escaped;
|
||||
};
|
||||
|
||||
|
||||
exports.escapeHtml = function (input) {
|
||||
|
||||
if (!input) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var escaped = '';
|
||||
|
||||
for (var i = 0, il = input.length; i < il; ++i) {
|
||||
|
||||
var charCode = input.charCodeAt(i);
|
||||
|
||||
if (internals.isSafe(charCode)) {
|
||||
escaped += input[i];
|
||||
}
|
||||
else {
|
||||
escaped += internals.escapeHtmlChar(charCode);
|
||||
}
|
||||
}
|
||||
|
||||
return escaped;
|
||||
};
|
||||
|
||||
|
||||
internals.escapeJavaScriptChar = function (charCode) {
|
||||
|
||||
if (charCode >= 256) {
|
||||
return '\\u' + internals.padLeft('' + charCode, 4);
|
||||
}
|
||||
|
||||
var hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex');
|
||||
return '\\x' + internals.padLeft(hexValue, 2);
|
||||
};
|
||||
|
||||
|
||||
internals.escapeHtmlChar = function (charCode) {
|
||||
|
||||
var namedEscape = internals.namedHtml[charCode];
|
||||
if (typeof namedEscape !== 'undefined') {
|
||||
return namedEscape;
|
||||
}
|
||||
|
||||
if (charCode >= 256) {
|
||||
return '&#' + charCode + ';';
|
||||
}
|
||||
|
||||
var hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex');
|
||||
return '&#x' + internals.padLeft(hexValue, 2) + ';';
|
||||
};
|
||||
|
||||
|
||||
internals.padLeft = function (str, len) {
|
||||
|
||||
while (str.length < len) {
|
||||
str = '0' + str;
|
||||
}
|
||||
|
||||
return str;
|
||||
};
|
||||
|
||||
|
||||
internals.isSafe = function (charCode) {
|
||||
|
||||
return (typeof internals.safeCharCodes[charCode] !== 'undefined');
|
||||
};
|
||||
|
||||
|
||||
internals.namedHtml = {
|
||||
'38': '&',
|
||||
'60': '<',
|
||||
'62': '>',
|
||||
'34': '"',
|
||||
'160': ' ',
|
||||
'162': '¢',
|
||||
'163': '£',
|
||||
'164': '¤',
|
||||
'169': '©',
|
||||
'174': '®'
|
||||
};
|
||||
|
||||
|
||||
internals.safeCharCodes = (function () {
|
||||
|
||||
var safe = {};
|
||||
|
||||
for (var i = 32; i < 123; ++i) {
|
||||
|
||||
if ((i >= 97 && i <= 122) || // a-z
|
||||
(i >= 65 && i <= 90) || // A-Z
|
||||
(i >= 48 && i <= 57) || // 0-9
|
||||
i === 32 || // space
|
||||
i === 46 || // .
|
||||
i === 44 || // ,
|
||||
i === 45 || // -
|
||||
i === 58 || // :
|
||||
i === 95) { // _
|
||||
|
||||
safe[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return safe;
|
||||
}());
|
557
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js
generated
vendored
Executable file
557
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js
generated
vendored
Executable file
@@ -0,0 +1,557 @@
|
||||
// Load modules
|
||||
|
||||
var Fs = require('fs');
|
||||
var Escape = require('./escape');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
// Clone object or array
|
||||
|
||||
exports.clone = function (obj, seen) {
|
||||
|
||||
if (typeof obj !== 'object' ||
|
||||
obj === null) {
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
seen = seen || { orig: [], copy: [] };
|
||||
|
||||
var lookup = seen.orig.indexOf(obj);
|
||||
if (lookup !== -1) {
|
||||
return seen.copy[lookup];
|
||||
}
|
||||
|
||||
var newObj = (obj instanceof Array) ? [] : {};
|
||||
|
||||
seen.orig.push(obj);
|
||||
seen.copy.push(newObj);
|
||||
|
||||
for (var i in obj) {
|
||||
if (obj.hasOwnProperty(i)) {
|
||||
if (obj[i] instanceof Date) {
|
||||
newObj[i] = new Date(obj[i].getTime());
|
||||
}
|
||||
else if (obj[i] instanceof RegExp) {
|
||||
var flags = '' + (obj[i].global ? 'g' : '') + (obj[i].ignoreCase ? 'i' : '') + (obj[i].multiline ? 'm' : '');
|
||||
newObj[i] = new RegExp(obj[i].source, flags);
|
||||
}
|
||||
else {
|
||||
newObj[i] = exports.clone(obj[i], seen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newObj;
|
||||
};
|
||||
|
||||
|
||||
// Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied
|
||||
|
||||
exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) {
|
||||
|
||||
exports.assert(target && typeof target == 'object', 'Invalid target value: must be an object');
|
||||
exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object');
|
||||
|
||||
if (!source) {
|
||||
return target;
|
||||
}
|
||||
|
||||
if (source instanceof Array) {
|
||||
exports.assert(target instanceof Array, 'Cannot merge array onto an object');
|
||||
if (isMergeArrays === false) { // isMergeArrays defaults to true
|
||||
target.length = 0; // Must not change target assignment
|
||||
}
|
||||
|
||||
source.forEach(function (item) {
|
||||
|
||||
target.push(item);
|
||||
});
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
Object.keys(source).forEach(function (key) {
|
||||
|
||||
var value = source[key];
|
||||
if (value &&
|
||||
typeof value === 'object') {
|
||||
|
||||
if (!target[key] ||
|
||||
typeof target[key] !== 'object') {
|
||||
|
||||
target[key] = exports.clone(value);
|
||||
}
|
||||
else {
|
||||
exports.merge(target[key], source[key], isNullOverride, isMergeArrays);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (value !== null && value !== undefined) { // Explicit to preserve empty strings
|
||||
target[key] = value;
|
||||
}
|
||||
else if (isNullOverride !== false) { // Defaults to true
|
||||
target[key] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
|
||||
// Apply options to a copy of the defaults
|
||||
|
||||
exports.applyToDefaults = function (defaults, options) {
|
||||
|
||||
exports.assert(defaults && typeof defaults == 'object', 'Invalid defaults value: must be an object');
|
||||
exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object');
|
||||
|
||||
if (!options) { // If no options, return null
|
||||
return null;
|
||||
}
|
||||
|
||||
var copy = exports.clone(defaults);
|
||||
|
||||
if (options === true) { // If options is set to true, use defaults
|
||||
return copy;
|
||||
}
|
||||
|
||||
return exports.merge(copy, options, false, false);
|
||||
};
|
||||
|
||||
|
||||
// Remove duplicate items from array
|
||||
|
||||
exports.unique = function (array, key) {
|
||||
|
||||
var index = {};
|
||||
var result = [];
|
||||
|
||||
for (var i = 0, il = array.length; i < il; ++i) {
|
||||
var id = (key ? array[i][key] : array[i]);
|
||||
if (index[id] !== true) {
|
||||
|
||||
result.push(array[i]);
|
||||
index[id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
// Convert array into object
|
||||
|
||||
exports.mapToObject = function (array, key) {
|
||||
|
||||
if (!array) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var obj = {};
|
||||
for (var i = 0, il = array.length; i < il; ++i) {
|
||||
if (key) {
|
||||
if (array[i][key]) {
|
||||
obj[array[i][key]] = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
obj[array[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
|
||||
// Find the common unique items in two arrays
|
||||
|
||||
exports.intersect = function (array1, array2) {
|
||||
|
||||
if (!array1 || !array2) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var common = [];
|
||||
var hash = (array1 instanceof Array ? exports.mapToObject(array1) : array1);
|
||||
var found = {};
|
||||
for (var i = 0, il = array2.length; i < il; ++i) {
|
||||
if (hash[array2[i]] && !found[array2[i]]) {
|
||||
common.push(array2[i]);
|
||||
found[array2[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return common;
|
||||
};
|
||||
|
||||
|
||||
// Find which keys are present
|
||||
|
||||
exports.matchKeys = function (obj, keys) {
|
||||
|
||||
var matched = [];
|
||||
for (var i = 0, il = keys.length; i < il; ++i) {
|
||||
if (obj.hasOwnProperty(keys[i])) {
|
||||
matched.push(keys[i]);
|
||||
}
|
||||
}
|
||||
return matched;
|
||||
};
|
||||
|
||||
|
||||
// Flatten array
|
||||
|
||||
exports.flatten = function (array, target) {
|
||||
|
||||
var result = target || [];
|
||||
|
||||
for (var i = 0, il = array.length; i < il; ++i) {
|
||||
if (Array.isArray(array[i])) {
|
||||
exports.flatten(array[i], result);
|
||||
}
|
||||
else {
|
||||
result.push(array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
// Remove keys
|
||||
|
||||
exports.removeKeys = function (object, keys) {
|
||||
|
||||
for (var i = 0, il = keys.length; i < il; i++) {
|
||||
delete object[keys[i]];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Convert an object key chain string ('a.b.c') to reference (object[a][b][c])
|
||||
|
||||
exports.reach = function (obj, chain) {
|
||||
|
||||
var path = chain.split('.');
|
||||
var ref = obj;
|
||||
path.forEach(function (level) {
|
||||
|
||||
if (ref) {
|
||||
ref = ref[level];
|
||||
}
|
||||
});
|
||||
|
||||
return ref;
|
||||
};
|
||||
|
||||
|
||||
// Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors
|
||||
|
||||
exports.inheritAsync = function (self, obj, keys) {
|
||||
|
||||
keys = keys || null;
|
||||
|
||||
for (var i in obj) {
|
||||
if (obj.hasOwnProperty(i)) {
|
||||
if (keys instanceof Array &&
|
||||
keys.indexOf(i) < 0) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
self.prototype[i] = (function (fn) {
|
||||
|
||||
return function (callback) {
|
||||
|
||||
var result = null;
|
||||
try {
|
||||
result = fn();
|
||||
}
|
||||
catch (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
return callback(null, result);
|
||||
};
|
||||
})(obj[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.formatStack = function (stack) {
|
||||
|
||||
var trace = [];
|
||||
stack.forEach(function (item) {
|
||||
|
||||
trace.push([item.getFileName(), item.getLineNumber(), item.getColumnNumber(), item.getFunctionName(), item.isConstructor()]);
|
||||
});
|
||||
|
||||
return trace;
|
||||
};
|
||||
|
||||
|
||||
exports.formatTrace = function (trace) {
|
||||
|
||||
var display = [];
|
||||
trace.forEach(function (row) {
|
||||
|
||||
display.push((row[4] ? 'new ' : '') + row[3] + ' (' + row[0] + ':' + row[1] + ':' + row[2] + ')');
|
||||
});
|
||||
|
||||
return display;
|
||||
};
|
||||
|
||||
|
||||
exports.callStack = function (slice) {
|
||||
|
||||
// http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
|
||||
|
||||
var v8 = Error.prepareStackTrace;
|
||||
Error.prepareStackTrace = function (err, stack) {
|
||||
|
||||
return stack;
|
||||
};
|
||||
|
||||
var capture = {};
|
||||
Error.captureStackTrace(capture, arguments.callee);
|
||||
var stack = capture.stack;
|
||||
|
||||
Error.prepareStackTrace = v8;
|
||||
|
||||
var trace = exports.formatStack(stack);
|
||||
|
||||
if (slice) {
|
||||
return trace.slice(slice);
|
||||
}
|
||||
|
||||
return trace;
|
||||
};
|
||||
|
||||
|
||||
exports.displayStack = function (slice) {
|
||||
|
||||
var trace = exports.callStack(slice === undefined ? 1 : slice + 1);
|
||||
|
||||
return exports.formatTrace(trace);
|
||||
};
|
||||
|
||||
|
||||
exports.abortThrow = false;
|
||||
|
||||
|
||||
exports.abort = function (message, hideStack) {
|
||||
|
||||
if (process.env.NODE_ENV === 'test' || exports.abortThrow === true) {
|
||||
throw new Error(message || 'Unknown error');
|
||||
}
|
||||
|
||||
var stack = '';
|
||||
if (!hideStack) {
|
||||
stack = exports.displayStack(1).join('\n\t');
|
||||
}
|
||||
console.log('ABORT: ' + message + '\n\t' + stack);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
|
||||
exports.assert = function (condition, message) {
|
||||
|
||||
if (!condition) {
|
||||
throw new Error(message || 'Unknown error');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.loadDirModules = function (path, excludeFiles, target) { // target(filename, name, capName)
|
||||
|
||||
var exclude = {};
|
||||
for (var i = 0, il = excludeFiles.length; i < il; ++i) {
|
||||
exclude[excludeFiles[i] + '.js'] = true;
|
||||
}
|
||||
|
||||
Fs.readdirSync(path).forEach(function (filename) {
|
||||
|
||||
if (/\.js$/.test(filename) &&
|
||||
!exclude[filename]) {
|
||||
|
||||
var name = filename.substr(0, filename.lastIndexOf('.'));
|
||||
var capName = name.charAt(0).toUpperCase() + name.substr(1).toLowerCase();
|
||||
|
||||
if (typeof target !== 'function') {
|
||||
target[capName] = require(path + '/' + name);
|
||||
}
|
||||
else {
|
||||
target(path + '/' + name, name, capName);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
exports.rename = function (obj, from, to) {
|
||||
|
||||
obj[to] = obj[from];
|
||||
delete obj[from];
|
||||
};
|
||||
|
||||
|
||||
exports.Timer = function () {
|
||||
|
||||
this.reset();
|
||||
};
|
||||
|
||||
|
||||
exports.Timer.prototype.reset = function () {
|
||||
|
||||
this.ts = Date.now();
|
||||
};
|
||||
|
||||
|
||||
exports.Timer.prototype.elapsed = function () {
|
||||
|
||||
return Date.now() - this.ts;
|
||||
};
|
||||
|
||||
|
||||
// Load and parse package.json process root or given directory
|
||||
|
||||
exports.loadPackage = function (dir) {
|
||||
|
||||
var result = {};
|
||||
var filepath = (dir || process.env.PWD) + '/package.json';
|
||||
if (Fs.existsSync(filepath)) {
|
||||
try {
|
||||
result = JSON.parse(Fs.readFileSync(filepath));
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
// Escape string for Regex construction
|
||||
|
||||
exports.escapeRegex = function (string) {
|
||||
|
||||
// Escape ^$.*+-?=!:|\/()[]{},
|
||||
return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&');
|
||||
};
|
||||
|
||||
|
||||
// Return an error as first argument of a callback
|
||||
|
||||
exports.toss = function (condition /*, [message], callback */) {
|
||||
|
||||
var message = (arguments.length === 3 ? arguments[1] : '');
|
||||
var callback = (arguments.length === 3 ? arguments[2] : arguments[1]);
|
||||
|
||||
var err = (message instanceof Error ? message : (message ? new Error(message) : (condition instanceof Error ? condition : new Error())));
|
||||
|
||||
if (condition instanceof Error ||
|
||||
!condition) {
|
||||
|
||||
return callback(err);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Base64url (RFC 4648) encode
|
||||
|
||||
exports.base64urlEncode = function (value) {
|
||||
|
||||
return (new Buffer(value, 'binary')).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
|
||||
};
|
||||
|
||||
|
||||
// Base64url (RFC 4648) decode
|
||||
|
||||
exports.base64urlDecode = function (encoded) {
|
||||
|
||||
if (encoded &&
|
||||
!encoded.match(/^[\w\-]*$/)) {
|
||||
|
||||
return new Error('Invalid character');
|
||||
}
|
||||
|
||||
try {
|
||||
return (new Buffer(encoded.replace(/-/g, '+').replace(/:/g, '/'), 'base64')).toString('binary');
|
||||
}
|
||||
catch (err) {
|
||||
return err;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Escape attribute value for use in HTTP header
|
||||
|
||||
exports.escapeHeaderAttribute = function (attribute) {
|
||||
|
||||
// Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, "
|
||||
|
||||
exports.assert(attribute.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/), 'Bad attribute value (' + attribute + ')');
|
||||
|
||||
return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"'); // Escape quotes and slash
|
||||
};
|
||||
|
||||
|
||||
exports.escapeHtml = function (string) {
|
||||
|
||||
return Escape.escapeHtml(string);
|
||||
};
|
||||
|
||||
|
||||
exports.escapeJavaScript = function (string) {
|
||||
|
||||
return Escape.escapeJavaScript(string);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
var event = {
|
||||
timestamp: now.getTime(),
|
||||
tags: ['tag'],
|
||||
data: { some: 'data' }
|
||||
};
|
||||
*/
|
||||
|
||||
exports.consoleFunc = console.log;
|
||||
|
||||
exports.printEvent = function (event) {
|
||||
|
||||
var pad = function (value) {
|
||||
|
||||
return (value < 10 ? '0' : '') + value;
|
||||
};
|
||||
|
||||
var now = new Date(event.timestamp);
|
||||
var timestring = (now.getYear() - 100).toString() +
|
||||
pad(now.getMonth() + 1) +
|
||||
pad(now.getDate()) +
|
||||
'/' +
|
||||
pad(now.getHours()) +
|
||||
pad(now.getMinutes()) +
|
||||
pad(now.getSeconds()) +
|
||||
'.' +
|
||||
now.getMilliseconds();
|
||||
|
||||
var data = event.data;
|
||||
if (typeof event.data !== 'string') {
|
||||
try {
|
||||
data = JSON.stringify(event.data);
|
||||
}
|
||||
catch (e) {
|
||||
data = 'JSON Error: ' + e.message;
|
||||
}
|
||||
}
|
||||
|
||||
var output = timestring + ', ' + event.tags[0] + ', ' + data;
|
||||
exports.consoleFunc(output);
|
||||
};
|
45
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/package.json
generated
vendored
Executable file
45
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/package.json
generated
vendored
Executable file
File diff suppressed because one or more lines are too long
86
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js
generated
vendored
Normal file
86
node_modules/tabletop/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
// Load modules
|
||||
|
||||
var Lab = require('lab');
|
||||
var Hoek = require('../lib');
|
||||
|
||||
|
||||
// Declare internals
|
||||
|
||||
var internals = {};
|
||||
|
||||
|
||||
// Test shortcuts
|
||||
|
||||
var expect = Lab.expect;
|
||||
var before = Lab.before;
|
||||
var after = Lab.after;
|
||||
var describe = Lab.experiment;
|
||||
var it = Lab.test;
|
||||
|
||||
|
||||
describe('Hoek', function () {
|
||||
|
||||
describe('#escapeJavaScript', function () {
|
||||
|
||||
it('encodes / characters', function (done) {
|
||||
|
||||
var encoded = Hoek.escapeJavaScript('<script>alert(1)</script>');
|
||||
expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e');
|
||||
done();
|
||||
});
|
||||
|
||||
it('encodes \' characters', function (done) {
|
||||
|
||||
var encoded = Hoek.escapeJavaScript('something(\'param\')');
|
||||
expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29');
|
||||
done();
|
||||
});
|
||||
|
||||
it('encodes large unicode characters with the correct padding', function (done) {
|
||||
|
||||
var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000));
|
||||
expect(encoded).to.equal('\\u0500\\u1000');
|
||||
done();
|
||||
});
|
||||
|
||||
it('doesn\'t throw an exception when passed null', function (done) {
|
||||
|
||||
var encoded = Hoek.escapeJavaScript(null);
|
||||
expect(encoded).to.equal('');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#escapeHtml', function () {
|
||||
|
||||
it('encodes / characters', function (done) {
|
||||
|
||||
var encoded = Hoek.escapeHtml('<script>alert(1)</script>');
|
||||
expect(encoded).to.equal('<script>alert(1)</script>');
|
||||
done();
|
||||
});
|
||||
|
||||
it('encodes < and > as named characters', function (done) {
|
||||
|
||||
var encoded = Hoek.escapeHtml('<script><>');
|
||||
expect(encoded).to.equal('<script><>');
|
||||
done();
|
||||
});
|
||||
|
||||
it('encodes large unicode characters', function (done) {
|
||||
|
||||
var encoded = Hoek.escapeHtml(String.fromCharCode(500) + String.fromCharCode(1000));
|
||||
expect(encoded).to.equal('ǴϨ');
|
||||
done();
|
||||
});
|
||||
|
||||
it('doesn\'t throw an exception when passed null', function (done) {
|
||||
|
||||
var encoded = Hoek.escapeHtml(null);
|
||||
expect(encoded).to.equal('');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user