Skip to content
Snippets Groups Projects
index.js 7.56 MiB
Newer Older
  • Learn to ignore specific revisions
  • Romain CREY's avatar
    Romain CREY committed
          stream.Stream.prototype.pipe.call(self, dest, opts)
          self.pipeDest(dest)
          return dest
        }
      } else {
        self.dests.push(dest)
        stream.Stream.prototype.pipe.call(self, dest, opts)
        return dest
      }
    }
    Request.prototype.write = function () {
      var self = this
      if (self._aborted) { return }
    
      if (!self._started) {
        self.start()
      }
      if (self.req) {
        return self.req.write.apply(self.req, arguments)
      }
    }
    Request.prototype.end = function (chunk) {
      var self = this
      if (self._aborted) { return }
    
      if (chunk) {
        self.write(chunk)
      }
      if (!self._started) {
        self.start()
      }
      if (self.req) {
        self.req.end()
      }
    }
    Request.prototype.pause = function () {
      var self = this
      if (!self.responseContent) {
        self._paused = true
      } else {
        self.responseContent.pause.apply(self.responseContent, arguments)
      }
    }
    Request.prototype.resume = function () {
      var self = this
      if (!self.responseContent) {
        self._paused = false
      } else {
        self.responseContent.resume.apply(self.responseContent, arguments)
      }
    }
    Request.prototype.destroy = function () {
      var self = this
    
      this.clearTimeout()
    
    Romain CREY's avatar
    Romain CREY committed
      if (!self._ended) {
        self.end()
      } else if (self.response) {
        self.response.destroy()
      }
    }
    
    
    Request.prototype.clearTimeout = function () {
      if (this.timeoutTimer) {
        clearTimeout(this.timeoutTimer)
        this.timeoutTimer = null
      }
    }
    
    
    Romain CREY's avatar
    Romain CREY committed
    Request.defaultProxyHeaderWhiteList =
      Tunnel.defaultProxyHeaderWhiteList.slice()
    
    Request.defaultProxyHeaderExclusiveList =
      Tunnel.defaultProxyHeaderExclusiveList.slice()
    
    // Exports
    
    Request.prototype.toJSON = requestToJSON
    module.exports = Request
    
    
    /***/ }),
    
    /* 98 */
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports) {
    
    module.exports = require("http");
    
    /***/ }),
    
    /* 99 */
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports) {
    
    module.exports = require("https");
    
    /***/ }),
    
    /* 100 */
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports) {
    
    module.exports = require("stream");
    
    /***/ }),
    
    /* 101 */
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports) {
    
    module.exports = require("zlib");
    
    /***/ }),
    
    /* 102 */
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    
    /*!
     *  Copyright 2010 LearnBoost <dev@learnboost.com>
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    /**
     * Module dependencies.
     */
    
    
    var crypto = __webpack_require__(94)
      , parse = __webpack_require__(83).parse
    
    Romain CREY's avatar
    Romain CREY committed
      ;
    
    /**
     * 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 ? options.date.toUTCString() : ''
        , headers + options.resource
        ]
      return r.join('\n')
    }
    module.exports.stringToSign = 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
    
    
    /***/ }),
    
    /* 103 */
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    var aws4 = exports,
    
        url = __webpack_require__(83),
        querystring = __webpack_require__(104),
        crypto = __webpack_require__(94),
        lru = __webpack_require__(105),
    
    Romain CREY's avatar
    Romain CREY committed
        credentialsCache = lru(1000)
    
    // http://docs.amazonwebservices.com/general/latest/gr/signature-version-4.html
    
    function hmac(key, string, encoding) {
      return crypto.createHmac('sha256', key).update(string, 'utf8').digest(encoding)
    }
    
    function hash(string, encoding) {
      return crypto.createHash('sha256').update(string, 'utf8').digest(encoding)
    }
    
    // This function assumes the string has already been percent encoded
    function encodeRfc3986(urlEncodedString) {
      return urlEncodedString.replace(/[!'()*]/g, function(c) {
        return '%' + c.charCodeAt(0).toString(16).toUpperCase()
      })
    }
    
    
    function encodeRfc3986Full(str) {
      return encodeRfc3986(encodeURIComponent(str))
    }
    
    // A bit of a combination of:
    // https://github.com/aws/aws-sdk-java-v2/blob/dc695de6ab49ad03934e1b02e7263abbd2354be0/core/auth/src/main/java/software/amazon/awssdk/auth/signer/internal/AbstractAws4Signer.java#L59
    // https://github.com/aws/aws-sdk-js/blob/18cb7e5b463b46239f9fdd4a65e2ff8c81831e8f/lib/signers/v4.js#L191-L199
    // https://github.com/mhart/aws4fetch/blob/b3aed16b6f17384cf36ea33bcba3c1e9f3bdfefd/src/main.js#L25-L34
    var HEADERS_TO_IGNORE = {
      'authorization': true,
      'connection': true,
      'x-amzn-trace-id': true,
      'user-agent': true,
      'expect': true,
      'presigned-expires': true,
      'range': true,
    }
    
    
    Romain CREY's avatar
    Romain CREY committed
    // request: { path | body, [host], [method], [headers], [service], [region] }
    // credentials: { accessKeyId, secretAccessKey, [sessionToken] }
    function RequestSigner(request, credentials) {
    
      if (typeof request === 'string') request = url.parse(request)
    
      var headers = request.headers = (request.headers || {}),
    
          hostParts = (!this.service || !this.region) && this.matchHost(request.hostname || request.host || headers.Host || headers.host)
    
    Romain CREY's avatar
    Romain CREY committed
    
      this.request = request
      this.credentials = credentials || this.defaultCredentials()
    
      this.service = request.service || hostParts[0] || ''
      this.region = request.region || hostParts[1] || 'us-east-1'
    
      // SES uses a different domain from the service name
      if (this.service === 'email') this.service = 'ses'
    
      if (!request.method && request.body)
        request.method = 'POST'
    
      if (!headers.Host && !headers.host) {
        headers.Host = request.hostname || request.host || this.createHost()
    
        // If a port is specified explicitly, use it as is
        if (request.port)
          headers.Host += ':' + request.port
      }
      if (!request.hostname && !request.host)
        request.hostname = headers.Host || headers.host
    
      this.isCodeCommitGit = this.service === 'codecommit' && request.method === 'GIT'
    }
    
    RequestSigner.prototype.matchHost = function(host) {
      var match = (host || '').match(/([^\.]+)\.(?:([^\.]*)\.)?amazonaws\.com(\.cn)?$/)
      var hostParts = (match || []).slice(1, 3)
    
      // ES's hostParts are sometimes the other way round, if the value that is expected
      // to be region equals ‘es’ switch them back
      // e.g. search-cluster-name-aaaa00aaaa0aaa0aaaaaaa0aaa.us-east-1.es.amazonaws.com
      if (hostParts[1] === 'es')
        hostParts = hostParts.reverse()
    
    
      if (hostParts[1] == 's3') {
        hostParts[0] = 's3'
        hostParts[1] = 'us-east-1'
      } else {
        for (var i = 0; i < 2; i++) {
          if (/^s3-/.test(hostParts[i])) {
            hostParts[1] = hostParts[i].slice(3)
            hostParts[0] = 's3'
            break
          }
        }
      }
    
    
    Romain CREY's avatar
    Romain CREY committed
      return hostParts
    }
    
    // http://docs.aws.amazon.com/general/latest/gr/rande.html
    RequestSigner.prototype.isSingleRegion = function() {
      // Special case for S3 and SimpleDB in us-east-1
      if (['s3', 'sdb'].indexOf(this.service) >= 0 && this.region === 'us-east-1') return true
    
      return ['cloudfront', 'ls', 'route53', 'iam', 'importexport', 'sts']
        .indexOf(this.service) >= 0
    }
    
    RequestSigner.prototype.createHost = function() {
    
      var region = this.isSingleRegion() ? '' : '.' + this.region,
          subdomain = this.service === 'ses' ? 'email' : this.service
      return subdomain + region + '.amazonaws.com'
    
    Romain CREY's avatar
    Romain CREY committed
    }
    
    RequestSigner.prototype.prepareRequest = function() {
      this.parsePath()
    
      var request = this.request, headers = request.headers, query
    
      if (request.signQuery) {
    
        this.parsedPath.query = query = this.parsedPath.query || {}
    
        if (this.credentials.sessionToken)
          query['X-Amz-Security-Token'] = this.credentials.sessionToken
    
        if (this.service === 's3' && !query['X-Amz-Expires'])
          query['X-Amz-Expires'] = 86400
    
        if (query['X-Amz-Date'])
          this.datetime = query['X-Amz-Date']
        else
          query['X-Amz-Date'] = this.getDateTime()
    
        query['X-Amz-Algorithm'] = 'AWS4-HMAC-SHA256'
        query['X-Amz-Credential'] = this.credentials.accessKeyId + '/' + this.credentialString()
        query['X-Amz-SignedHeaders'] = this.signedHeaders()
    
      } else {
    
        if (!request.doNotModifyHeaders && !this.isCodeCommitGit) {
          if (request.body && !headers['Content-Type'] && !headers['content-type'])
            headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'
    
          if (request.body && !headers['Content-Length'] && !headers['content-length'])
            headers['Content-Length'] = Buffer.byteLength(request.body)
    
          if (this.credentials.sessionToken && !headers['X-Amz-Security-Token'] && !headers['x-amz-security-token'])
            headers['X-Amz-Security-Token'] = this.credentials.sessionToken
    
          if (this.service === 's3' && !headers['X-Amz-Content-Sha256'] && !headers['x-amz-content-sha256'])
            headers['X-Amz-Content-Sha256'] = hash(this.request.body || '', 'hex')
    
          if (headers['X-Amz-Date'] || headers['x-amz-date'])
            this.datetime = headers['X-Amz-Date'] || headers['x-amz-date']
          else
            headers['X-Amz-Date'] = this.getDateTime()
        }
    
        delete headers.Authorization
        delete headers.authorization
      }
    }
    
    RequestSigner.prototype.sign = function() {
      if (!this.parsedPath) this.prepareRequest()
    
      if (this.request.signQuery) {
        this.parsedPath.query['X-Amz-Signature'] = this.signature()
      } else {
        this.request.headers.Authorization = this.authHeader()
      }
    
      this.request.path = this.formatPath()
    
      return this.request
    }
    
    RequestSigner.prototype.getDateTime = function() {
      if (!this.datetime) {
        var headers = this.request.headers,
          date = new Date(headers.Date || headers.date || new Date)
    
        this.datetime = date.toISOString().replace(/[:\-]|\.\d{3}/g, '')
    
        // Remove the trailing 'Z' on the timestamp string for CodeCommit git access
        if (this.isCodeCommitGit) this.datetime = this.datetime.slice(0, -1)
      }
      return this.datetime
    }
    
    RequestSigner.prototype.getDate = function() {
      return this.getDateTime().substr(0, 8)
    }
    
    RequestSigner.prototype.authHeader = function() {
      return [
        'AWS4-HMAC-SHA256 Credential=' + this.credentials.accessKeyId + '/' + this.credentialString(),
        'SignedHeaders=' + this.signedHeaders(),
        'Signature=' + this.signature(),
      ].join(', ')
    }
    
    RequestSigner.prototype.signature = function() {
      var date = this.getDate(),
          cacheKey = [this.credentials.secretAccessKey, date, this.region, this.service].join(),
          kDate, kRegion, kService, kCredentials = credentialsCache.get(cacheKey)
      if (!kCredentials) {
        kDate = hmac('AWS4' + this.credentials.secretAccessKey, date)
        kRegion = hmac(kDate, this.region)
        kService = hmac(kRegion, this.service)
        kCredentials = hmac(kService, 'aws4_request')
        credentialsCache.set(cacheKey, kCredentials)
      }
      return hmac(kCredentials, this.stringToSign(), 'hex')
    }
    
    RequestSigner.prototype.stringToSign = function() {
      return [
        'AWS4-HMAC-SHA256',
        this.getDateTime(),
        this.credentialString(),
        hash(this.canonicalString(), 'hex'),
      ].join('\n')
    }
    
    RequestSigner.prototype.canonicalString = function() {
      if (!this.parsedPath) this.prepareRequest()
    
      var pathStr = this.parsedPath.path,
          query = this.parsedPath.query,
          headers = this.request.headers,
          queryStr = '',
          normalizePath = this.service !== 's3',
          decodePath = this.service === 's3' || this.request.doNotEncodePath,
          decodeSlashesInPath = this.service === 's3',
          firstValOnly = this.service === 's3',
          bodyHash
    
      if (this.service === 's3' && this.request.signQuery) {
        bodyHash = 'UNSIGNED-PAYLOAD'
      } else if (this.isCodeCommitGit) {
        bodyHash = ''
      } else {
        bodyHash = headers['X-Amz-Content-Sha256'] || headers['x-amz-content-sha256'] ||
          hash(this.request.body || '', 'hex')
      }
    
      if (query) {
    
        var reducedQuery = Object.keys(query).reduce(function(obj, key) {
    
    Romain CREY's avatar
    Romain CREY committed
          if (!key) return obj
    
          obj[encodeRfc3986Full(key)] = !Array.isArray(query[key]) ? query[key] :
            (firstValOnly ? query[key][0] : query[key])
    
    Romain CREY's avatar
    Romain CREY committed
          return obj
    
        }, {})
        var encodedQueryPieces = []
        Object.keys(reducedQuery).sort().forEach(function(key) {
          if (!Array.isArray(reducedQuery[key])) {
            encodedQueryPieces.push(key + '=' + encodeRfc3986Full(reducedQuery[key]))
          } else {
            reducedQuery[key].map(encodeRfc3986Full).sort()
              .forEach(function(val) { encodedQueryPieces.push(key + '=' + val) })
          }
        })
        queryStr = encodedQueryPieces.join('&')
    
    Romain CREY's avatar
    Romain CREY committed
      }
      if (pathStr !== '/') {
        if (normalizePath) pathStr = pathStr.replace(/\/{2,}/g, '/')
        pathStr = pathStr.split('/').reduce(function(path, piece) {
          if (normalizePath && piece === '..') {
            path.pop()
          } else if (!normalizePath || piece !== '.') {
    
            if (decodePath) piece = decodeURIComponent(piece.replace(/\+/g, ' '))
            path.push(encodeRfc3986Full(piece))
    
    Romain CREY's avatar
    Romain CREY committed
          }
          return path
        }, []).join('/')
        if (pathStr[0] !== '/') pathStr = '/' + pathStr
        if (decodeSlashesInPath) pathStr = pathStr.replace(/%2F/g, '/')
      }
    
      return [
        this.request.method || 'GET',
        pathStr,
        queryStr,
        this.canonicalHeaders() + '\n',
        this.signedHeaders(),
        bodyHash,
      ].join('\n')
    }
    
    RequestSigner.prototype.canonicalHeaders = function() {
      var headers = this.request.headers
      function trimAll(header) {
        return header.toString().trim().replace(/\s+/g, ' ')
      }
      return Object.keys(headers)
    
        .filter(function(key) { return HEADERS_TO_IGNORE[key.toLowerCase()] == null })
    
    Romain CREY's avatar
    Romain CREY committed
        .sort(function(a, b) { return a.toLowerCase() < b.toLowerCase() ? -1 : 1 })
        .map(function(key) { return key.toLowerCase() + ':' + trimAll(headers[key]) })
        .join('\n')
    }
    
    RequestSigner.prototype.signedHeaders = function() {
      return Object.keys(this.request.headers)
        .map(function(key) { return key.toLowerCase() })
    
        .filter(function(key) { return HEADERS_TO_IGNORE[key] == null })
    
    Romain CREY's avatar
    Romain CREY committed
        .sort()
        .join(';')
    }
    
    RequestSigner.prototype.credentialString = function() {
      return [
        this.getDate(),
        this.region,
        this.service,
        'aws4_request',
      ].join('/')
    }
    
    RequestSigner.prototype.defaultCredentials = function() {
      var env = process.env
      return {
        accessKeyId: env.AWS_ACCESS_KEY_ID || env.AWS_ACCESS_KEY,
        secretAccessKey: env.AWS_SECRET_ACCESS_KEY || env.AWS_SECRET_KEY,
        sessionToken: env.AWS_SESSION_TOKEN,
      }
    }
    
    RequestSigner.prototype.parsePath = function() {
    
      var path = this.request.path || '/'
    
      // S3 doesn't always encode characters > 127 correctly and
      // all services don't encode characters > 255 correctly
      // So if there are non-reserved chars (and it's not already all % encoded), just encode them all
      if (/[^0-9A-Za-z;,/?:@&=+$\-_.!~*'()#%]/.test(path)) {
        path = encodeURI(decodeURI(path))
      }
    
      var queryIx = path.indexOf('?'),
    
    Romain CREY's avatar
    Romain CREY committed
          query = null
    
      if (queryIx >= 0) {
        query = querystring.parse(path.slice(queryIx + 1))
        path = path.slice(0, queryIx)
      }
    
      this.parsedPath = {
        path: path,
        query: query,
      }
    }
    
    RequestSigner.prototype.formatPath = function() {
      var path = this.parsedPath.path,
          query = this.parsedPath.query
    
      if (!query) return path
    
      // Services don't support empty query string keys
      if (query[''] != null) delete query['']
    
      return path + '?' + encodeRfc3986(querystring.stringify(query))
    }
    
    aws4.RequestSigner = RequestSigner
    
    aws4.sign = function(request, credentials) {
      return new RequestSigner(request, credentials).sign()
    }
    
    
    /***/ }),
    
    /* 104 */
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports) {
    
    module.exports = require("querystring");
    
    /***/ }),
    
    /* 105 */
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports) {
    
    module.exports = function(size) {
      return new LruCache(size)
    }
    
    function LruCache(size) {
      this.capacity = size | 0
      this.map = Object.create(null)
      this.list = new DoublyLinkedList()
    }
    
    LruCache.prototype.get = function(key) {
      var node = this.map[key]
      if (node == null) return undefined
      this.used(node)
      return node.val
    }
    
    LruCache.prototype.set = function(key, val) {
      var node = this.map[key]
      if (node != null) {
        node.val = val
      } else {
        if (!this.capacity) this.prune()
        if (!this.capacity) return false
        node = new DoublyLinkedNode(key, val)
        this.map[key] = node
        this.capacity--
      }
      this.used(node)
      return true
    }
    
    LruCache.prototype.used = function(node) {
      this.list.moveToFront(node)
    }
    
    LruCache.prototype.prune = function() {
      var node = this.list.pop()
      if (node != null) {
        delete this.map[node.key]
        this.capacity++
      }
    }
    
    
    function DoublyLinkedList() {
      this.firstNode = null
      this.lastNode = null
    }
    
    DoublyLinkedList.prototype.moveToFront = function(node) {
      if (this.firstNode == node) return
    
      this.remove(node)
    
      if (this.firstNode == null) {
        this.firstNode = node
        this.lastNode = node
        node.prev = null
        node.next = null
      } else {
        node.prev = null
        node.next = this.firstNode
        node.next.prev = node
        this.firstNode = node
      }
    }
    
    DoublyLinkedList.prototype.pop = function() {
      var lastNode = this.lastNode
      if (lastNode != null) {
        this.remove(lastNode)
      }
      return lastNode
    }
    
    DoublyLinkedList.prototype.remove = function(node) {
      if (this.firstNode == node) {
        this.firstNode = node.next
      } else if (node.prev != null) {
        node.prev.next = node.next
      }
      if (this.lastNode == node) {
        this.lastNode = node.prev
      } else if (node.next != null) {
        node.next.prev = node.prev
      }
    }
    
    
    function DoublyLinkedNode(key, val) {
      this.key = key
      this.val = val
      this.prev = null
      this.next = null
    }
    
    
    /***/ }),
    
    /* 106 */
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    // Copyright 2015 Joyent, Inc.
    
    
    var parser = __webpack_require__(107);
    var signer = __webpack_require__(149);
    var verify = __webpack_require__(156);
    var utils = __webpack_require__(110);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    
    ///--- API
    
    module.exports = {
    
      parse: parser.parseRequest,
      parseRequest: parser.parseRequest,
    
      sign: signer.signRequest,
      signRequest: signer.signRequest,
      createSigner: signer.createSigner,
      isSigner: signer.isSigner,
    
      sshKeyToPEM: utils.sshKeyToPEM,
      sshKeyFingerprint: utils.fingerprint,
      pemToRsaSSHKey: utils.pemToRsaSSHKey,
    
      verify: verify.verifySignature,
      verifySignature: verify.verifySignature,
      verifyHMAC: verify.verifyHMAC
    };
    
    
    /***/ }),
    
    /* 107 */
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    // Copyright 2012 Joyent, Inc.  All rights reserved.
    
    
    var assert = __webpack_require__(108);
    var util = __webpack_require__(9);
    var utils = __webpack_require__(110);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    
    ///--- Globals
    
    var HASH_ALGOS = utils.HASH_ALGOS;
    var PK_ALGOS = utils.PK_ALGOS;
    var HttpSignatureError = utils.HttpSignatureError;
    var InvalidAlgorithmError = utils.InvalidAlgorithmError;
    var validateAlgorithm = utils.validateAlgorithm;
    
    var State = {
      New: 0,
      Params: 1
    };
    
    var ParamsState = {
      Name: 0,
      Quote: 1,
      Value: 2,
      Comma: 3
    };
    
    
    ///--- Specific Errors
    
    
    function ExpiredRequestError(message) {
      HttpSignatureError.call(this, message, ExpiredRequestError);
    }
    util.inherits(ExpiredRequestError, HttpSignatureError);
    
    
    function InvalidHeaderError(message) {
      HttpSignatureError.call(this, message, InvalidHeaderError);
    }
    util.inherits(InvalidHeaderError, HttpSignatureError);
    
    
    function InvalidParamsError(message) {
      HttpSignatureError.call(this, message, InvalidParamsError);
    }
    util.inherits(InvalidParamsError, HttpSignatureError);
    
    
    function MissingHeaderError(message) {
      HttpSignatureError.call(this, message, MissingHeaderError);
    }
    util.inherits(MissingHeaderError, HttpSignatureError);
    
    function StrictParsingError(message) {
      HttpSignatureError.call(this, message, StrictParsingError);
    }
    util.inherits(StrictParsingError, HttpSignatureError);
    
    ///--- Exported API
    
    module.exports = {
    
      /**
       * Parses the 'Authorization' header out of an http.ServerRequest object.
       *
       * Note that this API will fully validate the Authorization header, and throw
       * on any error.  It will not however check the signature, or the keyId format
       * as those are specific to your environment.  You can use the options object
       * to pass in extra constraints.
       *
       * As a response object you can expect this:
       *
       *     {
       *       "scheme": "Signature",
       *       "params": {
       *         "keyId": "foo",
       *         "algorithm": "rsa-sha256",
       *         "headers": [
       *           "date" or "x-date",
       *           "digest"
       *         ],
       *         "signature": "base64"
       *       },
       *       "signingString": "ready to be passed to crypto.verify()"
       *     }
       *
       * @param {Object} request an http.ServerRequest.
       * @param {Object} options an optional options object with:
       *                   - clockSkew: allowed clock skew in seconds (default 300).
       *                   - headers: required header names (def: date or x-date)
       *                   - algorithms: algorithms to support (default: all).
       *                   - strict: should enforce latest spec parsing
       *                             (default: false).
       * @return {Object} parsed out object (see above).
       * @throws {TypeError} on invalid input.
       * @throws {InvalidHeaderError} on an invalid Authorization header error.
       * @throws {InvalidParamsError} if the params in the scheme are invalid.
       * @throws {MissingHeaderError} if the params indicate a header not present,
       *                              either in the request headers from the params,
       *                              or not in the params from a required header
       *                              in options.
       * @throws {StrictParsingError} if old attributes are used in strict parsing
       *                              mode.
       * @throws {ExpiredRequestError} if the value of date or x-date exceeds skew.
       */
      parseRequest: function parseRequest(request, options) {
        assert.object(request, 'request');
        assert.object(request.headers, 'request.headers');
        if (options === undefined) {
          options = {};
        }
        if (options.headers === undefined) {
          options.headers = [request.headers['x-date'] ? 'x-date' : 'date'];
        }
        assert.object(options, 'options');
        assert.arrayOfString(options.headers, 'options.headers');
        assert.optionalFinite(options.clockSkew, 'options.clockSkew');
    
        var authzHeaderName = options.authorizationHeaderName || 'authorization';
    
        if (!request.headers[authzHeaderName]) {
          throw new MissingHeaderError('no ' + authzHeaderName + ' header ' +
                                       'present in the request');
        }
    
        options.clockSkew = options.clockSkew || 300;
    
    
        var i = 0;
        var state = State.New;
        var substate = ParamsState.Name;
        var tmpName = '';
        var tmpValue = '';
    
        var parsed = {
          scheme: '',
          params: {},
          signingString: ''
        };
    
        var authz = request.headers[authzHeaderName];
        for (i = 0; i < authz.length; i++) {
          var c = authz.charAt(i);
    
          switch (Number(state)) {
    
          case State.New:
            if (c !== ' ') parsed.scheme += c;
            else state = State.Params;
            break;