text: (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.autobahn = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  AutobahnJS - http://autobahn.ws, http://wamp.ws
  //
  //  A JavaScript library for WAMP ("The Web Application Messaging Protocol").
  //
  //  Copyright (c) Crossbar.io Technologies GmbH and contributors
  //
  //  Licensed under the MIT License.
  //  http://www.opensource.org/licenses/mit-license.php
  //
  ///////////////////////////////////////////////////////////////////////////////
  
  // require('assert') would be nice .. but it does not
  // work with Google Closure after Browserify
  
  var crypto = require('crypto-js');
  
  // PBKDF2-base key derivation function for salted WAMP-CRA
  //
  function derive_key (secret, salt, iterations, keylen) {
     var iterations = iterations || 1000;
     var keylen = keylen || 32;
     var config = {
        keySize: keylen / 4,
        iterations: iterations,
        hasher: crypto.algo.SHA256
     }
     var key = crypto.PBKDF2(secret, salt, config);
     return key.toString(crypto.enc.Base64);
  }
  
  
  function sign (key, challenge) {
     return crypto.HmacSHA256(challenge, key).toString(crypto.enc.Base64);
  }
  
  exports.sign = sign;
  exports.derive_key = derive_key;
  
  },{"crypto-js":40}],2:[function(require,module,exports){
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  AutobahnJS - http://autobahn.ws, http://wamp.ws
  //
  //  A JavaScript library for WAMP ("The Web Application Messaging Protocol").
  //
  //  Copyright (c) Crossbar.io Technologies GmbH and contributors
  //
  //  Licensed under the MIT License.
  //  http://www.opensource.org/licenses/mit-license.php
  //
  ///////////////////////////////////////////////////////////////////////////////
  
  var when = require('when');
  var when_fn = require("when/function");
  
  
  function auth(session, user, extra) {
  
     // Persona Issues:
     //
     // Chrome: https://github.com/mozilla/persona/issues/4083
     // IE11: https://groups.google.com/forum/#!topic/mozilla.dev.identity/keEkVpvfLA8
  
     var d = session.defer();
  
     navigator.id.watch({
        loggedInUser: user,
        onlogin: function (assertion) {
           // A user has logged in! Here you need to:
           // 1. Send the assertion to your backend for verification and to create a session.
           // 2. Update your UI.
           d.resolve(assertion);
        },
        onlogout: function() {
           // A user has logged out! Here you need to:
           // Tear down the user's session by redirecting the user or making a call to your backend.
           // Also, make sure loggedInUser will get set to null on the next page load.
           // (That's a literal JavaScript null. Not false, 0, or undefined. null.)
           session.leave("wamp.close.logout");
        }
     });
  
     if (d.promise.then) {
        // whenjs has the actual user promise in an attribute
        return d.promise;
     } else {
        return d;
     }
  }
  
  exports.auth = auth;
  
  },{"when":123,"when/function":99}],3:[function(require,module,exports){
  (function (global){
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  AutobahnJS - http://autobahn.ws, http://wamp.ws
  //
  //  A JavaScript library for WAMP ("The Web Application Messaging Protocol").
  //
  //  Copyright (c) Crossbar.io Technologies GmbH and contributors
  //
  //  Licensed under the MIT License.
  //  http://www.opensource.org/licenses/mit-license.php
  //
  ///////////////////////////////////////////////////////////////////////////////
  
  // Polyfills for <= IE9
  require('./polyfill.js');
  
  var pjson = require('../package.json');
  
  var when = require('when');
  //var fn = require("when/function");
  
  var msgpack = require('msgpack-lite');
  var cbor = require('cbor');
  
  if ('AUTOBAHN_DEBUG' in global && AUTOBAHN_DEBUG) {
     // https://github.com/cujojs/when/blob/master/docs/api.md#whenmonitor
     require('when/monitor/console');
     if ('console' in global) {
        console.log("AutobahnJS debug enabled");
     }
  }
  
  var util = require('./util.js');
  var log = require('./log.js');
  var session = require('./session.js');
  var connection = require('./connection.js');
  var configure = require('./configure.js');
  var serializer = require('./serializer.js');
  
  var persona = require('./auth/persona.js');
  var cra = require('./auth/cra.js');
  
  exports.version = pjson.version;
  
  exports.transports = configure.transports;
  
  exports.Connection = connection.Connection;
  
  exports.Session = session.Session;
  exports.Invocation = session.Invocation;
  exports.Event = session.Event;
  exports.Result = session.Result;
  exports.Error = session.Error;
  exports.Subscription = session.Subscription;
  exports.Registration = session.Registration;
  exports.Publication = session.Publication;
  
  exports.serializer = serializer;
  
  exports.auth_persona = persona.auth;
  exports.auth_cra = cra;
  
  exports.when = when;
  exports.msgpack = msgpack;
  exports.cbor = cbor;
  
  exports.util = util;
  exports.log = log;
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"../package.json":124,"./auth/cra.js":1,"./auth/persona.js":2,"./configure.js":4,"./connection.js":5,"./log.js":6,"./polyfill.js":7,"./serializer.js":15,"./session.js":16,"./util.js":20,"cbor":22,"msgpack-lite":70,"when":123,"when/monitor/console":121}],4:[function(require,module,exports){
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  AutobahnJS - http://autobahn.ws, http://wamp.ws
  //
  //  A JavaScript library for WAMP ("The Web Application Messaging Protocol").
  //
  //  Copyright (c) Crossbar.io Technologies GmbH and contributors
  //
  //  Licensed under the MIT License.
  //  http://www.opensource.org/licenses/mit-license.php
  //
  ///////////////////////////////////////////////////////////////////////////////
  
  
  function Transports() {
     this._repository = {};
  }
  
  
  Transports.prototype.register = function (name, factory) {
     this._repository[name] = factory;
  };
  
  
  Transports.prototype.isRegistered = function (name) {
     return this._repository[name] ? true : false;
  };
  
  
  Transports.prototype.get = function (name) {
     if (this._repository[name] !== undefined) {
        return this._repository[name];
     } else {
       throw "no such transport: " + name;
     }
  }
  
  
  Transports.prototype.list = function() {
     var items = [];
     for (var name in this._repository) {
        items.push(name);
     }
     return items;
  };
  
  
  var _transports = new Transports();
  
  
  // register default transports
  var websocket = require('./transport/websocket.js');
  _transports.register("websocket", websocket.Factory);
  
  var longpoll = require('./transport/longpoll.js');
  _transports.register("longpoll", longpoll.Factory);
  
  var rawsocket = require('./transport/rawsocket.js');
  _transports.register("rawsocket", rawsocket.Factory);
  
  exports.transports = _transports;
  
  },{"./transport/longpoll.js":17,"./transport/rawsocket.js":18,"./transport/websocket.js":19}],5:[function(require,module,exports){
  (function (global){
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  AutobahnJS - http://autobahn.ws, http://wamp.ws
  //
  //  A JavaScript library for WAMP ("The Web Application Messaging Protocol").
  //
  //  Copyright (c) Crossbar.io Technologies GmbH and contributors
  //
  //  Licensed under the MIT License.
  //  http://www.opensource.org/licenses/mit-license.php
  //
  ///////////////////////////////////////////////////////////////////////////////
  
  var when = require('when');
  
  var session = require('./session.js');
  var util = require('./util.js');
  var log = require('./log.js');
  var autobahn = require('./autobahn.js');
  
  
  var Connection = function (options) {
  
     var self = this;
  
     self._options = options;
  
  
     // Deferred factory
     //
     if (options && options.use_es6_promises) {
  
        if ('Promise' in global) {
           // ES6-based deferred factory
           //
           self._defer = function () {
              var deferred = {};
  
              deferred.promise = new Promise(function (resolve, reject) {
                 deferred.resolve = resolve;
                 deferred.reject = reject;
              });
  
              return deferred;
           };
        } else {
  
           log.debug("Warning: ES6 promises requested, but not found! Falling back to whenjs.");
  
           // whenjs-based deferred factory
           //
           self._defer = when.defer;
        }
  
     } else if (options && options.use_deferred) {
  
        // use explicit deferred factory, e.g. jQuery.Deferred or Q.defer
        //
        self._defer = options.use_deferred;
  
     } else {
  
        // whenjs-based deferred factory
        //
        self._defer = when.defer;
     }
  
  
     // WAMP transport
     //
     // backward compatiblity
     if (!self._options.transports) {
        self._options.transports = [
           {
              type: 'websocket',
              url: self._options.url
           }
        ];
     }
     self._transport_factories = [];
     self._init_transport_factories();
  
  
     // WAMP session
     //
     self._session = null;
     self._session_close_reason = null;
     self._session_close_message = null;
  
     // automatic reconnection configuration
     //
  
     // enable automatic reconnect if host is unreachable
     if (self._options.retry_if_unreachable !== undefined) {
        self._retry_if_unreachable = self._options.retry_if_unreachable;
     } else {
        self._retry_if_unreachable = true;
     }
  
     // maximum number of reconnection attempts
     self._max_retries = typeof self._options.max_retries !== 'undefined' ?  self._options.max_retries : 15;
  
     // initial retry delay in seconds
     self._initial_retry_delay = self._options.initial_retry_delay || 1.5;
  
     // maximum seconds between reconnection attempts
     self._max_retry_delay = self._options.max_retry_delay || 300;
  
     // the growth factor applied to the retry delay on each retry cycle
     self._retry_delay_growth = self._options.retry_delay_growth || 1.5;
  
     // the SD of a Gaussian to jitter the delay on each retry cycle
     // as a fraction of the mean
     self._retry_delay_jitter = self._options.retry_delay_jitter || 0.1;
  
     // reconnection tracking
     //
  
     // total number of successful connections
     self._connect_successes = 0;
  
     // controls if we should try to reconnect
     self._retry = false;
  
     // current number of reconnect cycles we went through
     self._retry_count = 0;
  
     // the current retry delay
     self._retry_delay = self._initial_retry_delay;
  
     // flag indicating if we are currently in a reconnect cycle
     self._is_retrying = false;
  
     // when retrying, this is the timer object returned from window.setTimeout()
     self._retry_timer = null;
  };
  
  
  
  Connection.prototype._create_transport = function () {
     for (var i = 0; i < this._transport_factories.length; ++i) {
        var transport_factory = this._transport_factories[i];
        log.debug("trying to create WAMP transport of type: " + transport_factory.type);
        try {
           var transport = transport_factory.create();
           if (transport) {
              log.debug("using WAMP transport type: " + transport_factory.type);
              return transport;
           }
        } catch (e) {
           // ignore
           log.warn("could not create WAMP transport '" + transport_factory.type + "': " + e);
        }
     }
  
     log.warn('could not create any WAMP transport');
     return null;
  };
  
  
  
  Connection.prototype._init_transport_factories = function () {
      // WAMP transport
      //
      var transports, transport_options, transport_factory, transport_factory_klass;
  
      util.assert(this._options.transports, "No transport.factory specified");
      transports = this._options.transports;
      //if(typeof transports === "object") {
      //    this._options.transports = [transports];
      //}
      for(var i = 0; i < this._options.transports.length; ++i) {
          // cascading transports until we find one which works
          transport_options =  this._options.transports[i];
  
          if (!transport_options.url) {
              // defaulting to options.url if none is provided
              transport_options.url = this._options.url;
          }
          if (!transport_options.serializers) {
              transport_options.serializers = this._options.serializers;
          }
          if (!transport_options.protocols) {
              transport_options.protocols = this._options.protocols;
          }
          util.assert(transport_options.type, "No transport.type specified");
          util.assert(typeof transport_options.type === "string", "transport.type must be a string");
          try {
              transport_factory_klass = autobahn.transports.get(transport_options.type);
              if (transport_factory_klass) {
                  transport_factory = new transport_factory_klass(transport_options);
                  this._transport_factories.push(transport_factory);
              }
          } catch (exc) {
              console.error(exc);
          }
      }
  };
  
  
  Connection.prototype._autoreconnect_reset_timer = function () {
  
     var self = this;
  
     if (self._retry_timer) {
        clearTimeout(self._retry_timer);
     }
     self._retry_timer = null;
  }
  
  
  Connection.prototype._autoreconnect_reset = function () {
  
     var self = this;
  
     self._autoreconnect_reset_timer();
  
     self._retry_count = 0;
     self._retry_delay = self._initial_retry_delay;
     self._is_retrying = false;
  }
  
  
  Connection.prototype._autoreconnect_advance = function () {
  
     var self = this;
  
     // jitter retry delay
     if (self._retry_delay_jitter) {
        self._retry_delay = util.rand_normal(self._retry_delay, self._retry_delay * self._retry_delay_jitter);
     }
  
     // cap the retry delay
     if (self._retry_delay > self._max_retry_delay) {
        self._retry_delay = self._max_retry_delay;
     }
  
     // count number of retries
     self._retry_count += 1;
  
     var res;
     if (self._retry && (self._max_retries === -1 || self._retry_count <= self._max_retries)) {
        res = {
           count: self._retry_count,
           delay: self._retry_delay,
           will_retry: true
        };
     } else {
        res = {
           count: null,
           delay: null,
           will_retry: false
        }
     }
  
     // retry delay growth for next retry cycle
     if (self._retry_delay_growth) {
        self._retry_delay = self._retry_delay * self._retry_delay_growth;
     }
  
     return res;
  }
  
  
  Connection.prototype.open = function () {
  
     var self = this;
  
     if (self._transport) {
        throw "connection already open (or opening)";
     }
  
     self._autoreconnect_reset();
     self._retry = true;
  
     function retry () {
  
        // create a WAMP transport
        try {
           self._transport = self._create_transport();
        } catch (e) {
           console.log(e);
        }
  
        if (!self._transport) {
           // failed to create a WAMP transport
           self._retry = false;
           if (self.onclose) {
              var details = {
                 reason: null,
                 message: null,
                 retry_delay: null,
                 retry_count: null,
                 will_retry: false
              };
              self.onclose("unsupported", details);
           }
           return;
        }
  
        // create a new WAMP session using the WebSocket connection as transport
        self._session = new session.Session(self._transport, self._defer, self._options.onchallenge);
        self._session_close_reason = null;
        self._session_close_message = null;
  
        self._transport.onopen = function () {
  
           // reset auto-reconnect timer and tracking
           self._autoreconnect_reset();
  
           // log successful connections
           self._connect_successes += 1;
  
           // start WAMP session
           self._session.join(self._options.realm, self._options.authmethods, self._options.authid, self._options.authextra);
        };
  
        self._session.onjoin = function (details) {
           if (self.onopen) {
              try {
                 // forward transport info ..
                 details.transport = self._transport.info;
                 self.onopen(self._session, details);
              } catch (e) {
                 log.debug("Exception raised from app code while firing Connection.onopen()", e);
              }
           }
        };
  
        //
        // ... WAMP session is now attached to realm.
        //
  
        self._session.onleave = function (reason, details) {
           self._session_close_reason = reason;
           self._session_close_message = details.message || "";
           self._retry = false;
           self._transport.close(1000);
        };
  
        self._transport.onclose = function (evt) {
  
           // remove any pending reconnect timer
           self._autoreconnect_reset_timer();
  
           self._transport = null;
  
           var reason = null;
           if (self._connect_successes === 0) {
              reason = "unreachable";
              if (!self._retry_if_unreachable) {
                 self._retry = false;
              }
  
           } else if (!evt.wasClean) {
              reason = "lost";
  
           } else {
              reason = "closed";
           }
  
           var next_retry = self._autoreconnect_advance();
  
           // fire app code handler
           //
           if (self.onclose) {
              var details = {
                 reason: self._session_close_reason,
                 message: self._session_close_message,
                 retry_delay: next_retry.delay,
                 retry_count: next_retry.count,
                 will_retry: next_retry.will_retry
              };
              try {
                 // Connection.onclose() allows to cancel any subsequent retry attempt
                 var stop_retrying = self.onclose(reason, details);
              } catch (e) {
                 log.debug("Exception raised from app code while firing Connection.onclose()", e);
              }
           }
  
           // reset session info
           //
           if (self._session) {
              self._session._id = null;
              self._session = null;
              self._session_close_reason = null;
              self._session_close_message = null;
           }
  
           // automatic reconnection
           //
           if (self._retry && !stop_retrying) {
  
              if (next_retry.will_retry) {
  
                 self._is_retrying = true;
  
                 log.debug("retrying in " + next_retry.delay + " s");
                 self._retry_timer = setTimeout(retry, next_retry.delay * 1000);
  
              } else {
                 log.debug("giving up trying to reconnect");
              }
           }
        }
     }
  
     retry();
  };
  
  
  Connection.prototype.close = function (reason, message) {
     var self = this;
  
     if (!self._transport && !self._is_retrying) {
        throw "connection already closed";
     }
  
     // the app wants to close .. don't retry
     self._retry = false;
  
     if (self._session && self._session.isOpen) {
        // if there is an open session, close that first.
        self._session.leave(reason, message);
     } else if (self._transport) {
        // no session active: just close the transport
        self._transport.close(1000);
     }
  };
  
  
  
  Object.defineProperty(Connection.prototype, "defer", {
     get: function () {
        return this._defer;
     }
  });
  
  
  
  Object.defineProperty(Connection.prototype, "session", {
     get: function () {
        return this._session;
     }
  });
  
  
  
  Object.defineProperty(Connection.prototype, "isOpen", {
     get: function () {
        if (this._session && this._session.isOpen) {
           return true;
        } else {
           return false;
        }
     }
  });
  
  
  
  Object.defineProperty(Connection.prototype, "isConnected", {
     get: function () {
        if (this._transport) {
           return true;
        } else {
           return false;
        }
     }
  });
  
  
  
  Object.defineProperty(Connection.prototype, "transport", {
     get: function () {
        if (this._transport) {
           return this._transport;
        } else {
           return {info: {type: 'none', url: null, protocol: null}};
        }
     }
  });
  
  
  
  Object.defineProperty(Connection.prototype, "isRetrying", {
     get: function () {
        return this._is_retrying;
     }
  });
  
  
  
  exports.Connection = Connection;
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"./autobahn.js":3,"./log.js":6,"./session.js":16,"./util.js":20,"when":123}],6:[function(require,module,exports){
  (function (global){
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  AutobahnJS - http://autobahn.ws, http://wamp.ws
  //
  //  A JavaScript library for WAMP ("The Web Application Messaging Protocol").
  //
  //  Copyright (c) Crossbar.io Technologies GmbH and contributors
  //
  //  Licensed under the MIT License.
  //  http://www.opensource.org/licenses/mit-license.php
  //
  ///////////////////////////////////////////////////////////////////////////////
  
  
  var debug = function () {};
  
  if ('AUTOBAHN_DEBUG' in global && AUTOBAHN_DEBUG && 'console' in global) {
     debug = function () {
        console.log.apply(console, arguments);
     }
  }
  
  var warn = console.warn;
  
  exports.debug = debug;
  exports.warn = warn;
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],7:[function(require,module,exports){
  require('./polyfill/object.js');
  require('./polyfill/array.js');
  require('./polyfill/string.js');
  require('./polyfill/function.js');
  require('./polyfill/console.js');
  require('./polyfill/typedarray.js');
  require('./polyfill/json.js');
  
  },{"./polyfill/array.js":8,"./polyfill/console.js":9,"./polyfill/function.js":10,"./polyfill/json.js":11,"./polyfill/object.js":12,"./polyfill/string.js":13,"./polyfill/typedarray.js":14}],8:[function(require,module,exports){
  if ( 'function' !== typeof Array.prototype.reduce ) {
    Array.prototype.reduce = function( callback /*, initialValue*/ ) {
      'use strict';
        var len, t, value, k;
      if ( null === this || 'undefined' === typeof this ) {
        throw new TypeError(
           'Array.prototype.reduce called on null or undefined' );
      }
      if ( 'function' !== typeof callback ) {
        throw new TypeError( callback + ' is not a function' );
      }
      t = Object( this );
      len = t.length >>> 0;
      k = 0;
      if ( arguments.length >= 2 ) {
        value = arguments[1];
      } else {
        while ( k < len && ! k in t ) k++;
        if ( k >= len )
          throw new TypeError('Reduce of empty array with no initial value');
        value = t[ k++ ];
      }
      for ( ; k < len ; k++ ) {
        if ( k in t ) {
           value = callback( value, t[k], k, t );
        }
      }
      return value;
    };
  }
  
  // Add ECMA262-5 Array methods if not supported natively
  //
  if (!('indexOf' in Array.prototype)) {
      Array.prototype.indexOf= function(find, i /*opt*/) {
          if (i===undefined) i= 0;
          if (i<0) i+= this.length;
          if (i<0) i= 0;
          for (var n= this.length; i<n; i++)
              if (i in this && this[i]===find)
                  return i;
          return -1;
      };
  }
  if (!('lastIndexOf' in Array.prototype)) {
      Array.prototype.lastIndexOf= function(find, i /*opt*/) {
          if (i===undefined) i= this.length-1;
          if (i<0) i+= this.length;
          if (i>this.length-1) i= this.length-1;
          for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */
              if (i in this && this[i]===find)
                  return i;
          return -1;
      };
  }
  if (!('forEach' in Array.prototype)) {
      Array.prototype.forEach= function(action, that /*opt*/) {
          for (var i= 0, n= this.length; i<n; i++)
              if (i in this)
                  action.call(that, this[i], i, this);
      };
  }
  if (!('map' in Array.prototype)) {
      Array.prototype.map= function(mapper, that /*opt*/) {
          var other= new Array(this.length);
          for (var i= 0, n= this.length; i<n; i++)
              if (i in this)
                  other[i]= mapper.call(that, this[i], i, this);
          return other;
      };
  }
  if (!('filter' in Array.prototype)) {
      Array.prototype.filter= function(filter, that /*opt*/) {
          var other= [], v;
          for (var i=0, n= this.length; i<n; i++)
              if (i in this && filter.call(that, v= this[i], i, this))
                  other.push(v);
          return other;
      };
  }
  if (!('every' in Array.prototype)) {
      Array.prototype.every= function(tester, that /*opt*/) {
          for (var i= 0, n= this.length; i<n; i++)
              if (i in this && !tester.call(that, this[i], i, this))
                  return false;
          return true;
      };
  }
  if (!('some' in Array.prototype)) {
      Array.prototype.some= function(tester, that /*opt*/) {
          for (var i= 0, n= this.length; i<n; i++)
              if (i in this && tester.call(that, this[i], i, this))
                  return true;
          return false;
      };
  }
  
  if ( 'function' !== typeof Array.prototype.reduceRight ) {
    Array.prototype.reduceRight = function( callback /*, initialValue*/ ) {
      'use strict';
      if ( null === this || 'undefined' === typeof this ) {
        throw new TypeError(
           'Array.prototype.reduce called on null or undefined' );
      }
      if ( 'function' !== typeof callback ) {
        throw new TypeError( callback + ' is not a function' );
      }
      var t = Object( this ), len = t.length >>> 0, k = len - 1, value;
      if ( arguments.length >= 2 ) {
        value = arguments[1];
      } else {
        while ( k >= 0 && ! k in t ) k--;
        if ( k < 0 )
          throw new TypeError('Reduce of empty array with no initial value');
        value = t[ k-- ];
      }
      for ( ; k >= 0 ; k-- ) {
        if ( k in t ) {
           value = callback( value, t[k], k, t );
        }
      }
      return value;
    };
  }
  },{}],9:[function(require,module,exports){
  
  (function(console) {
     /*********************************************************************************************
      * Make sure console exists because IE blows up if it's not open and you attempt to access it
      * Create some dummy functions if we need to, so we don't have to if/else everything
      *********************************************************************************************/
     console||(console = window.console = {
        // all this "a, b, c, d, e" garbage is to make the IDEs happy, since they can't do variable argument lists
        /**
         * @param a
         * @param [b]
         * @param [c]
         * @param [d]
         * @param [e]
         */
        log: function(a, b, c, d, e) {},
        /**
         * @param a
         * @param [b]
         * @param [c]
         * @param [d]
         * @param [e]
         */
        info: function(a, b, c, d, e) {},
        /**
         * @param a
         * @param [b]
         * @param [c]
         * @param [d]
         * @param [e]
         */
        warn: function(a, b, c, d, e) {},
        /**
         * @param a
         * @param [b]
         * @param [c]
         * @param [d]
         * @param [e]
         */
        error: function(a, b, c, d, e) {},
  
        assert: function(test, message) {}
     });
  
     // IE 9 won't allow us to call console.log.apply (WTF IE!) It also reports typeof(console.log) as 'object' (UNH!)
     // but together, those two errors can be useful in allowing us to fix stuff so it works right
     if( typeof(console.log) === 'object' ) {
        // Array.forEach doesn't work in IE 8 so don't try that :(
        console.log = Function.prototype.call.bind(console.log, console);
        console.info = Function.prototype.call.bind(console.info, console);
        console.warn = Function.prototype.call.bind(console.warn, console);
        console.error = Function.prototype.call.bind(console.error, console);
        console.debug = Function.prototype.call.bind(console.info, console);
     }
  
     /**
      * Support group and groupEnd functions
      */
     ('group' in console) ||
     (console.group = function(msg) {
        console.info("\n--- "+msg+" ---\n");
     });
     ('groupEnd' in console) ||
     (console.groupEnd = function() {
        console.log("\n");
     });
     ('assert' in console) ||
     (console.assert = function(test, message) {
              if (!test) {
          try {
            // attempt to preserve the stack
            throw new Error("assertion failed: " + message);
          } catch(error) {
            setTimeout(function(){
              throw error;
            }, 0);
          }
        }
         });
  
     /**
      * Support time and timeEnd functions
      */
     ('time' in console) ||
     (function() {
        var trackedTimes = {};
        console.time = function(msg) {
           trackedTimes[msg] = new Date().getTime();
        };
        console.timeEnd = function(msg) {
           var end = new Date().getTime(), time = (msg in trackedTimes)? end - trackedTimes[msg] : 0;
           console.info(msg+': '+time+'ms')
        };
     }());
  
  })(typeof console !== 'undefined' ? console : undefined);
  },{}],10:[function(require,module,exports){
  if (!Function.prototype.bind) {
    //credits: taken from bind_even_never in this discussion: https://prototype.lighthouseapp.com/projects/8886/tickets/215-optimize-bind-bindaseventlistener#ticket-215-9
    Function.prototype.bind = function(context) {
       var fn = this, args = Array.prototype.slice.call(arguments, 1);
       return function(){
          return fn.apply(context, Array.prototype.concat.apply(args, arguments));
       };
    };
  }
  },{}],11:[function(require,module,exports){
  /*
      json2.js
      2014-02-04
  
      Public Domain.
  
      NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
  
      See http://www.JSON.org/js.html
  
  
      This code should be minified before deployment.
      See http://javascript.crockford.com/jsmin.html
  
      USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
      NOT CONTROL.
  
  
      This file creates a global JSON object containing two methods: stringify
      and parse.
  
          JSON.stringify(value, replacer, space)
              value       any JavaScript value, usually an object or array.
  
              replacer    an optional parameter that determines how object
                          values are stringified for objects. It can be a
                          function or an array of strings.
  
              space       an optional parameter that specifies the indentation
                          of nested structures. If it is omitted, the text will
                          be packed without extra whitespace. If it is a number,
                          it will specify the number of spaces to indent at each
                          level. If it is a string (such as '\t' or '&nbsp;'),
                          it contains the characters used to indent at each level.
  
              This method produces a JSON text from a JavaScript value.
  
              When an object value is found, if the object contains a toJSON
              method, its toJSON method will be called and the result will be
              stringified. A toJSON method does not serialize: it returns the
              value represented by the name/value pair that should be serialized,
              or undefined if nothing should be serialized. The toJSON method
              will be passed the key associated with the value, and this will be
              bound to the value
  
              For example, this would serialize Dates as ISO strings.
  
                  Date.prototype.toJSON = function (key) {
                      function f(n) {
                          // Format integers to have at least two digits.
                          return n < 10 ? '0' + n : n;
                      }
  
                      return this.getUTCFullYear()   + '-' +
                           f(this.getUTCMonth() + 1) + '-' +
                           f(this.getUTCDate())      + 'T' +
                           f(this.getUTCHours())     + ':' +
                           f(this.getUTCMinutes())   + ':' +
                           f(this.getUTCSeconds())   + 'Z';
                  };
  
              You can provide an optional replacer method. It will be passed the
              key and value of each member, with this bound to the containing
              object. The value that is returned from your method will be
              serialized. If your method returns undefined, then the member will
              be excluded from the serialization.
  
              If the replacer parameter is an array of strings, then it will be
              used to select the members to be serialized. It filters the results
              such that only members with keys listed in the replacer array are
              stringified.
  
              Values that do not have JSON representations, such as undefined or
              functions, will not be serialized. Such values in objects will be
              dropped; in arrays they will be replaced with null. You can use
              a replacer function to replace those with JSON values.
              JSON.stringify(undefined) returns undefined.
  
              The optional space parameter produces a stringification of the
              value that is filled with line breaks and indentation to make it
              easier to read.
  
              If the space parameter is a non-empty string, then that string will
              be used for indentation. If the space parameter is a number, then
              the indentation will be that many spaces.
  
              Example:
  
              text = JSON.stringify(['e', {pluribus: 'unum'}]);
              // text is '["e",{"pluribus":"unum"}]'
  
  
              text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
              // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
  
              text = JSON.stringify([new Date()], function (key, value) {
                  return this[key] instanceof Date ?
                      'Date(' + this[key] + ')' : value;
              });
              // text is '["Date(---current time---)"]'
  
  
          JSON.parse(text, reviver)
              This method parses a JSON text to produce an object or array.
              It can throw a SyntaxError exception.
  
              The optional reviver parameter is a function that can filter and
              transform the results. It receives each of the keys and values,
              and its return value is used instead of the original value.
              If it returns what it received, then the structure is not modified.
              If it returns undefined then the member is deleted.
  
              Example:
  
              // Parse the text. Values that look like ISO date strings will
              // be converted to Date objects.
  
              myData = JSON.parse(text, function (key, value) {
                  var a;
                  if (typeof value === 'string') {
                      a =
  /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
                      if (a) {
                          return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
                              +a[5], +a[6]));
                      }
                  }
                  return value;
              });
  
              myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
                  var d;
                  if (typeof value === 'string' &&
                          value.slice(0, 5) === 'Date(' &&
                          value.slice(-1) === ')') {
                      d = new Date(value.slice(5, -1));
                      if (d) {
                          return d;
                      }
                  }
                  return value;
              });
  
  
      This is a reference implementation. You are free to copy, modify, or
      redistribute.
  */
  
  /*jslint evil: true, regexp: true */
  
  /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
      call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
      getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
      lastIndex, length, parse, prototype, push, replace, slice, stringify,
      test, toJSON, toString, valueOf
  */
  
  
  // Create a JSON object only if one does not already exist. We create the
  // methods in a closure to avoid creating global variables.
  
  if (typeof JSON !== 'object') {
      JSON = {};
  }
  
  (function () {
      'use strict';
  
      function f(n) {
          // Format integers to have at least two digits.
          return n < 10 ? '0' + n : n;
      }
  
      if (typeof Date.prototype.toJSON !== 'function') {
  
          Date.prototype.toJSON = function () {
  
              return isFinite(this.valueOf())
                  ? this.getUTCFullYear()     + '-' +
                      f(this.getUTCMonth() + 1) + '-' +
                      f(this.getUTCDate())      + 'T' +
                      f(this.getUTCHours())     + ':' +
                      f(this.getUTCMinutes())   + ':' +
                      f(this.getUTCSeconds())   + 'Z'
                  : null;
          };
  
          String.prototype.toJSON      =
              Number.prototype.toJSON  =
              Boolean.prototype.toJSON = function () {
                  return this.valueOf();
              };
      }
  
      var cx,
          escapable,
          gap,
          indent,
          meta,
          rep;
  
  
      function quote(string) {
  
  // If the string contains no control characters, no quote characters, and no
  // backslash characters, then we can safely slap some quotes around it.
  // Otherwise we must also replace the offending characters with safe escape
  // sequences.
  
          escapable.lastIndex = 0;
          return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
              var c = meta[a];
              return typeof c === 'string'
                  ? c
                  : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
          }) + '"' : '"' + string + '"';
      }
  
  
      function str(key, holder) {
  
  // Produce a string from holder[key].
  
          var i,          // The loop counter.
              k,          // The member key.
              v,          // The member value.
              length,
              mind = gap,
              partial,
              value = holder[key];
  
  // If the value has a toJSON method, call it to obtain a replacement value.
  
          if (value && typeof value === 'object' &&
                  typeof value.toJSON === 'function') {
              value = value.toJSON(key);
          }
  
  // If we were called with a replacer function, then call the replacer to
  // obtain a replacement value.
  
          if (typeof rep === 'function') {
              value = rep.call(holder, key, value);
          }
  
  // What happens next depends on the value's type.
  
          switch (typeof value) {
          case 'string':
              return quote(value);
  
          case 'number':
  
  // JSON numbers must be finite. Encode non-finite numbers as null.
  
              return isFinite(value) ? String(value) : 'null';
  
          case 'boolean':
          case 'null':
  
  // If the value is a boolean or null, convert it to a string. Note:
  // typeof null does not produce 'null'. The case is included here in
  // the remote chance that this gets fixed someday.
  
              return String(value);
  
  // If the type is 'object', we might be dealing with an object or an array or
  // null.
  
          case 'object':
  
  // Due to a specification blunder in ECMAScript, typeof null is 'object',
  // so watch out for that case.
  
              if (!value) {
                  return 'null';
              }
  
  // Make an array to hold the partial results of stringifying this object value.
  
              gap += indent;
              partial = [];
  
  // Is the value an array?
  
              if (Object.prototype.toString.apply(value) === '[object Array]') {
  
  // The value is an array. Stringify every element. Use null as a placeholder
  // for non-JSON values.
  
                  length = value.length;
                  for (i = 0; i < length; i += 1) {
                      partial[i] = str(i, value) || 'null';
                  }
  
  // Join all of the elements together, separated with commas, and wrap them in
  // brackets.
  
                  v = partial.length === 0
                      ? '[]'
                      : gap
                      ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
                      : '[' + partial.join(',') + ']';
                  gap = mind;
                  return v;
              }
  
  // If the replacer is an array, use it to select the members to be stringified.
  
              if (rep && typeof rep === 'object') {
                  length = rep.length;
                  for (i = 0; i < length; i += 1) {
                      if (typeof rep[i] === 'string') {
                          k = rep[i];
                          v = str(k, value);
                          if (v) {
                              partial.push(quote(k) + (gap ? ': ' : ':') + v);
                          }
                      }
                  }
              } else {
  
  // Otherwise, iterate through all of the keys in the object.
  
                  for (k in value) {
                      if (Object.prototype.hasOwnProperty.call(value, k)) {
                          v = str(k, value);
                          if (v) {
                              partial.push(quote(k) + (gap ? ': ' : ':') + v);
                          }
                      }
                  }
              }
  
  // Join all of the member texts together, separated with commas,
  // and wrap them in braces.
  
              v = partial.length === 0
                  ? '{}'
                  : gap
                  ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
                  : '{' + partial.join(',') + '}';
              gap = mind;
              return v;
          }
      }
  
  // If the JSON object does not yet have a stringify method, give it one.
  
      if (typeof JSON.stringify !== 'function') {
          escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
          meta = {    // table of character substitutions
              '\b': '\\b',
              '\t': '\\t',
              '\n': '\\n',
              '\f': '\\f',
              '\r': '\\r',
              '"' : '\\"',
              '\\': '\\\\'
          };
          JSON.stringify = function (value, replacer, space) {
  
  // The stringify method takes a value and an optional replacer, and an optional
  // space parameter, and returns a JSON text. The replacer can be a function
  // that can replace values, or an array of strings that will select the keys.
  // A default replacer method can be provided. Use of the space parameter can
  // produce text that is more easily readable.
  
              var i;
              gap = '';
              indent = '';
  
  // If the space parameter is a number, make an indent string containing that
  // many spaces.
  
              if (typeof space === 'number') {
                  for (i = 0; i < space; i += 1) {
                      indent += ' ';
                  }
  
  // If the space parameter is a string, it will be used as the indent string.
  
              } else if (typeof space === 'string') {
                  indent = space;
              }
  
  // If there is a replacer, it must be a function or an array.
  // Otherwise, throw an error.
  
              rep = replacer;
              if (replacer && typeof replacer !== 'function' &&
                      (typeof replacer !== 'object' ||
                      typeof replacer.length !== 'number')) {
                  throw new Error('JSON.stringify');
              }
  
  // Make a fake root object containing our value under the key of ''.
  // Return the result of stringifying the value.
  
              return str('', {'': value});
          };
      }
  
  
  // If the JSON object does not yet have a parse method, give it one.
  
      if (typeof JSON.parse !== 'function') {
          cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
          JSON.parse = function (text, reviver) {
  
  // The parse method takes a text and an optional reviver function, and returns
  // a JavaScript value if the text is a valid JSON text.
  
              var j;
  
              function walk(holder, key) {
  
  // The walk method is used to recursively walk the resulting structure so
  // that modifications can be made.
  
                  var k, v, value = holder[key];
                  if (value && typeof value === 'object') {
                      for (k in value) {
                          if (Object.prototype.hasOwnProperty.call(value, k)) {
                              v = walk(value, k);
                              if (v !== undefined) {
                                  value[k] = v;
                              } else {
                                  delete value[k];
                              }
                          }
                      }
                  }
                  return reviver.call(holder, key, value);
              }
  
  
  // Parsing happens in four stages. In the first stage, we replace certain
  // Unicode characters with escape sequences. JavaScript handles many characters
  // incorrectly, either silently deleting them, or treating them as line endings.
  
              text = String(text);
              cx.lastIndex = 0;
              if (cx.test(text)) {
                  text = text.replace(cx, function (a) {
                      return '\\u' +
                          ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                  });
              }
  
  // In the second stage, we run the text against regular expressions that look
  // for non-JSON patterns. We are especially concerned with '()' and 'new'
  // because they can cause invocation, and '=' because it can cause mutation.
  // But just to be safe, we want to reject all unexpected forms.
  
  // We split the second stage into 4 regexp operations in order to work around
  // crippling inefficiencies in IE's and Safari's regexp engines. First we
  // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
  // replace all simple value tokens with ']' characters. Third, we delete all
  // open brackets that follow a colon or comma or that begin the text. Finally,
  // we look to see that the remaining characters are only whitespace or ']' or
  // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
  
              if (/^[\],:{}\s]*$/
                      .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
                          .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
                          .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
  
  // In the third stage we use the eval function to compile the text into a
  // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
  // in JavaScript: it can begin a block or an object literal. We wrap the text
  // in parens to eliminate the ambiguity.
  
                  j = eval('(' + text + ')');
  
  // In the optional fourth stage, we recursively walk the new structure, passing
  // each name/value pair to a reviver function for possible transformation.
  
                  return typeof reviver === 'function'
                      ? walk({'': j}, '')
                      : j;
              }
  
  // If the text is not JSON parseable, then a SyntaxError is thrown.
  
              throw new SyntaxError('JSON.parse');
          };
      }
  }());
  
  exports.JSON = JSON;
  },{}],12:[function(require,module,exports){
  if (!Object.create) {
      Object.create = (function(){
          function F(){}
  
          return function(o){
              if (arguments.length != 1) {
                  throw new Error('Object.create implementation only accepts one parameter.');
              }
              F.prototype = o;
              return new F()
          }
      })()
  }
  // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
  if (!Object.keys) {
    Object.keys = (function () {
      'use strict';
      var hasOwnProperty = Object.prototype.hasOwnProperty,
          hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
          dontEnums = [
            'toString',
            'toLocaleString',
            'valueOf',
            'hasOwnProperty',
            'isPrototypeOf',
            'propertyIsEnumerable',
            'constructor'
          ],
          dontEnumsLength = dontEnums.length;
  
      return function (obj) {
        if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
          throw new TypeError('Object.keys called on non-object');
        }
  
        var result = [], prop, i;
  
        for (prop in obj) {
          if (hasOwnProperty.call(obj, prop)) {
            result.push(prop);
          }
        }
  
        if (hasDontEnumBug) {
          for (i = 0; i < dontEnumsLength; i++) {
            if (hasOwnProperty.call(obj, dontEnums[i])) {
              result.push(dontEnums[i]);
            }
          }
        }
        return result;
      };
    }());
  }
  },{}],13:[function(require,module,exports){
  // Add ECMA262-5 string trim if not supported natively
  //
  if (!('trim' in String.prototype)) {
      String.prototype.trim= function() {
          return this.replace(/^\s+/, '').replace(/\s+$/, '');
      };
  }
  },{}],14:[function(require,module,exports){
  /*
   Copyright (c) 2010, Linden Research, Inc.
   Copyright (c) 2014, Joshua Bell
  
   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.
   $/LicenseInfo$
   */
  
  // Original can be found at:
  //   https://bitbucket.org/lindenlab/llsd
  // Modifications by Joshua Bell inexorabletash@gmail.com
  //   https://github.com/inexorabletash/polyfill
  
  // ES3/ES5 implementation of the Krhonos Typed Array Specification
  //   Ref: http://www.khronos.org/registry/typedarray/specs/latest/
  //   Date: 2011-02-01
  //
  // Variations:
  //  * Allows typed_array.get/set() as alias for subscripts (typed_array[])
  //  * Gradually migrating structure from Khronos spec to ES6 spec
  if (typeof Uint8Array === "undefined") {
      (function (global, win) {
          'use strict';
  
          var undefined = (void 0); // Paranoia
  
          // Beyond this value, index getters/setters (i.e. array[0], array[1]) are so slow to
          // create, and consume so much memory, that the browser appears frozen.
          var MAX_ARRAY_LENGTH = 1e5;
  
          // Approximations of internal ECMAScript conversion functions
          function Type(v) {
              switch (typeof v) {
                  case 'undefined':
                      return 'undefined';
                  case 'boolean':
                      return 'boolean';
                  case 'number':
                      return 'number';
                  case 'string':
                      return 'string';
                  default:
                      return v === null ? 'null' : 'object';
              }
          }
  
          // Class returns internal [[Class]] property, used to avoid cross-frame instanceof issues:
          function Class(v) {
              return Object.prototype.toString.call(v).replace(/^\[object *|\]$/g, '');
          }
  
          function IsCallable(o) {
              return typeof o === 'function';
          }
  
          function ToObject(v) {
              if (v === null || v === undefined) throw TypeError();
              return Object(v);
          }
  
          function ToInt32(v) {
              return v >> 0;
          }
  
          function ToUint32(v) {
              return v >>> 0;
          }
  
          // Snapshot intrinsics
          var LN2 = Math.LN2,
              abs = Math.abs,
              floor = Math.floor,
              log = Math.log,
              max = Math.max,
              min = Math.min,
              pow = Math.pow,
              round = Math.round;
  
          // emulate ES5 getter/setter API using legacy APIs
          // http://blogs.msdn.com/b/ie/archive/2010/09/07/transitioning-existing-code-to-the-es5-getter-setter-apis.aspx
          // (second clause tests for Object.defineProperty() in IE<9 that only supports extending DOM prototypes, but
          // note that IE<9 does not support __defineGetter__ or __defineSetter__ so it just renders the method harmless)
  
          (function () {
              var orig = Object.defineProperty;
              var dom_only = !(function () {
                  try {
                      return Object.defineProperty({}, 'x', {});
                  } catch (_) {
                      return false;
                  }
              }());
  
              if (!orig || dom_only) {
                  Object.defineProperty = function (o, prop, desc) {
                      // In IE8 try built-in implementation for defining properties on DOM prototypes.
                      if (orig) {
                          try {
                              return orig(o, prop, desc);
                          } catch (_) {
                          }
                      }
  
                      if (o !== Object(o))
                          throw TypeError('Object.defineProperty called on non-object');
                      if (Object.prototype.__defineGetter__ && ('get' in desc))
                          Object.prototype.__defineGetter__.call(o, prop, desc.get);
                      if (Object.prototype.__defineSetter__ && ('set' in desc))
                          Object.prototype.__defineSetter__.call(o, prop, desc.set);
                      if ('value' in desc)
                          o[prop] = desc.value;
                      return o;
                  };
              }
          }());
  
          // ES5: Make obj[index] an alias for obj._getter(index)/obj._setter(index, value)
          // for index in 0 ... obj.length
          function makeArrayAccessors(obj) {
              if (obj.length > MAX_ARRAY_LENGTH) throw RangeError('Array too large for polyfill');
  
              function makeArrayAccessor(index) {
                  Object.defineProperty(obj, index, {
                      'get': function () {
                          return obj._getter(index);
                      },
                      'set': function (v) {
                          obj._setter(index, v);
                      },
                      enumerable: true,
                      configurable: false
                  });
              }
  
              var i;
              for (i = 0; i < obj.length; i += 1) {
                  makeArrayAccessor(i);
              }
          }
  
          // Internal conversion functions:
          //    pack<Type>()   - take a number (interpreted as Type), output a byte array
          //    unpack<Type>() - take a byte array, output a Type-like number
  
          function as_signed(value, bits) {
              var s = 32 - bits;
              return (value << s) >> s;
          }
  
          function as_unsigned(value, bits) {
              var s = 32 - bits;
              return (value << s) >>> s;
          }
  
          function packI8(n) {
              return [n & 0xff];
          }
  
          function unpackI8(bytes) {
              return as_signed(bytes[0], 8);
          }
  
          function packU8(n) {
              return [n & 0xff];
          }
  
          function unpackU8(bytes) {
              return as_unsigned(bytes[0], 8);
          }
  
          function packU8Clamped(n) {
              n = round(Number(n));
              return [n < 0 ? 0 : n > 0xff ? 0xff : n & 0xff];
          }
  
          function packI16(n) {
              return [(n >> 8) & 0xff, n & 0xff];
          }
  
          function unpackI16(bytes) {
              return as_signed(bytes[0] << 8 | bytes[1], 16);
          }
  
          function packU16(n) {
              return [(n >> 8) & 0xff, n & 0xff];
          }
  
          function unpackU16(bytes) {
              return as_unsigned(bytes[0] << 8 | bytes[1], 16);
          }
  
          function packI32(n) {
              return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff];
          }
  
          function unpackI32(bytes) {
              return as_signed(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32);
          }
  
          function packU32(n) {
              return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff];
          }
  
          function unpackU32(bytes) {
              return as_unsigned(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32);
          }
  
          function packIEEE754(v, ebits, fbits) {
  
              var bias = (1 << (ebits - 1)) - 1,
                  s, e, f, ln,
                  i, bits, str, bytes;
  
              function roundToEven(n) {
                  var w = floor(n), f = n - w;
                  if (f < 0.5)
                      return w;
                  if (f > 0.5)
                      return w + 1;
                  return w % 2 ? w + 1 : w;
              }
  
              // Compute sign, exponent, fraction
              if (v !== v) {
                  // NaN
                  // http://dev.w3.org/2006/webapi/WebIDL/#es-type-mapping
                  e = (1 << ebits) - 1;
                  f = pow(2, fbits - 1);
                  s = 0;
              } else if (v === Infinity || v === -Infinity) {
                  e = (1 << ebits) - 1;
                  f = 0;
                  s = (v < 0) ? 1 : 0;
              } else if (v === 0) {
                  e = 0;
                  f = 0;
                  s = (1 / v === -Infinity) ? 1 : 0;
              } else {
                  s = v < 0;
                  v = abs(v);
  
                  if (v >= pow(2, 1 - bias)) {
                      e = min(floor(log(v) / LN2), 1023);
                      f = roundToEven(v / pow(2, e) * pow(2, fbits));
                      if (f / pow(2, fbits) >= 2) {
                          e = e + 1;
                          f = 1;
                      }
                      if (e > bias) {
                          // Overflow
                          e = (1 << ebits) - 1;
                          f = 0;
                      } else {
                          // Normalized
                          e = e + bias;
                          f = f - pow(2, fbits);
                      }
                  } else {
                      // Denormalized
                      e = 0;
                      f = roundToEven(v / pow(2, 1 - bias - fbits));
                  }
              }
  
              // Pack sign, exponent, fraction
              bits = [];
              for (i = fbits; i; i -= 1) {
                  bits.push(f % 2 ? 1 : 0);
                  f = floor(f / 2);
              }
              for (i = ebits; i; i -= 1) {
                  bits.push(e % 2 ? 1 : 0);
                  e = floor(e / 2);
              }
              bits.push(s ? 1 : 0);
              bits.reverse();
              str = bits.join('');
  
              // Bits to bytes
              bytes = [];
              while (str.length) {
                  bytes.push(parseInt(str.substring(0, 8), 2));
                  str = str.substring(8);
              }
              return bytes;
          }
  
          function unpackIEEE754(bytes, ebits, fbits) {
              // Bytes to bits
              var bits = [], i, j, b, str,
                  bias, s, e, f;
  
              for (i = bytes.length; i; i -= 1) {
                  b = bytes[i - 1];
                  for (j = 8; j; j -= 1) {
                      bits.push(b % 2 ? 1 : 0);
                      b = b >> 1;
                  }
              }
              bits.reverse();
              str = bits.join('');
  
              // Unpack sign, exponent, fraction
              bias = (1 << (ebits - 1)) - 1;
              s = parseInt(str.substring(0, 1), 2) ? -1 : 1;
              e = parseInt(str.substring(1, 1 + ebits), 2);
              f = parseInt(str.substring(1 + ebits), 2);
  
              // Produce number
              if (e === (1 << ebits) - 1) {
                  return f !== 0 ? NaN : s * Infinity;
              } else if (e > 0) {
                  // Normalized
                  return s * pow(2, e - bias) * (1 + f / pow(2, fbits));
              } else if (f !== 0) {
                  // Denormalized
                  return s * pow(2, -(bias - 1)) * (f / pow(2, fbits));
              } else {
                  return s < 0 ? -0 : 0;
              }
          }
  
          function unpackF64(b) {
              return unpackIEEE754(b, 11, 52);
          }
  
          function packF64(v) {
              return packIEEE754(v, 11, 52);
          }
  
          function unpackF32(b) {
              return unpackIEEE754(b, 8, 23);
          }
  
          function packF32(v) {
              return packIEEE754(v, 8, 23);
          }
  
          //
          // 3 The ArrayBuffer Type
          //
  
          (function () {
  
              function ArrayBuffer(length) {
                  length = ToInt32(length);
                  if (length < 0) throw RangeError('ArrayBuffer size is not a small enough positive integer.');
                  Object.defineProperty(this, 'byteLength', {value: length});
                  Object.defineProperty(this, '_bytes', {value: Array(length)});
  
                  for (var i = 0; i < length; i += 1)
                      this._bytes[i] = 0;
              }
  
              global.ArrayBuffer = global.ArrayBuffer || ArrayBuffer;
  
              //
              // 5 The Typed Array View Types
              //
  
              function $TypedArray$() {
  
                  // %TypedArray% ( length )
                  if (!arguments.length || typeof arguments[0] !== 'object') {
                      return (function (length) {
                          length = ToInt32(length);
                          if (length < 0) throw RangeError('length is not a small enough positive integer.');
                          Object.defineProperty(this, 'length', {value: length});
                          Object.defineProperty(this, 'byteLength', {value: length * this.BYTES_PER_ELEMENT});
                          Object.defineProperty(this, 'buffer', {value: new ArrayBuffer(this.byteLength)});
                          Object.defineProperty(this, 'byteOffset', {value: 0});
  
                      }).apply(this, arguments);
                  }
  
                  // %TypedArray% ( typedArray )
                  if (arguments.length >= 1 &&
                      Type(arguments[0]) === 'object' &&
                      arguments[0] instanceof $TypedArray$) {
                      return (function (typedArray) {
                          if (this.constructor !== typedArray.constructor) throw TypeError();
  
                          var byteLength = typedArray.length * this.BYTES_PER_ELEMENT;
                          Object.defineProperty(this, 'buffer', {value: new ArrayBuffer(byteLength)});
                          Object.defineProperty(this, 'byteLength', {value: byteLength});
                          Object.defineProperty(this, 'byteOffset', {value: 0});
                          Object.defineProperty(this, 'length', {value: typedArray.length});
  
                          for (var i = 0; i < this.length; i += 1)
                              this._setter(i, typedArray._getter(i));
  
                      }).apply(this, arguments);
                  }
  
                  // %TypedArray% ( array )
                  if (arguments.length >= 1 &&
                      Type(arguments[0]) === 'object' && !(arguments[0] instanceof $TypedArray$) && !(arguments[0] instanceof ArrayBuffer || Class(arguments[0]) === 'ArrayBuffer')) {
                      return (function (array) {
  
                          var byteLength = array.length * this.BYTES_PER_ELEMENT;
                          Object.defineProperty(this, 'buffer', {value: new ArrayBuffer(byteLength)});
                          Object.defineProperty(this, 'byteLength', {value: byteLength});
                          Object.defineProperty(this, 'byteOffset', {value: 0});
                          Object.defineProperty(this, 'length', {value: array.length});
  
                          for (var i = 0; i < this.length; i += 1) {
                              var s = array[i];
                              this._setter(i, Number(s));
                          }
                      }).apply(this, arguments);
                  }
  
                  // %TypedArray% ( buffer, byteOffset=0, length=undefined )
                  if (arguments.length >= 1 &&
                      Type(arguments[0]) === 'object' &&
                      (arguments[0] instanceof ArrayBuffer || Class(arguments[0]) === 'ArrayBuffer')) {
                      return (function (buffer, byteOffset, length) {
  
                          byteOffset = ToUint32(byteOffset);
                          if (byteOffset > buffer.byteLength)
                              throw RangeError('byteOffset out of range');
  
                          // The given byteOffset must be a multiple of the element
                          // size of the specific type, otherwise an exception is raised.
                          if (byteOffset % this.BYTES_PER_ELEMENT)
                              throw RangeError('buffer length minus the byteOffset is not a multiple of the element size.');
  
                          if (length === undefined) {
                              var byteLength = buffer.byteLength - byteOffset;
                              if (byteLength % this.BYTES_PER_ELEMENT)
                                  throw RangeError('length of buffer minus byteOffset not a multiple of the element size');
                              length = byteLength / this.BYTES_PER_ELEMENT;
  
                          } else {
                              length = ToUint32(length);
                              byteLength = length * this.BYTES_PER_ELEMENT;
                          }
  
                          if ((byteOffset + byteLength) > buffer.byteLength)
                              throw RangeError('byteOffset and length reference an area beyond the end of the buffer');
  
                          Object.defineProperty(this, 'buffer', {value: buffer});
                          Object.defineProperty(this, 'byteLength', {value: byteLength});
                          Object.defineProperty(this, 'byteOffset', {value: byteOffset});
                          Object.defineProperty(this, 'length', {value: length});
  
                      }).apply(this, arguments);
                  }
  
                  // %TypedArray% ( all other argument combinations )
                  throw TypeError();
              }
  
              // Properties of the %TypedArray Instrinsic Object
  
              // %TypedArray%.from ( source , mapfn=undefined, thisArg=undefined )
              Object.defineProperty($TypedArray$, 'from', {value: function (iterable) {
                  return new this(iterable);
              }});
  
              // %TypedArray%.of ( ...items )
              Object.defineProperty($TypedArray$, 'of', {value: function (/*...items*/) {
                  return new this(arguments);
              }});
  
              // %TypedArray%.prototype
              var $TypedArrayPrototype$ = {};
              $TypedArray$.prototype = $TypedArrayPrototype$;
  
              // WebIDL: getter type (unsigned long index);
              Object.defineProperty($TypedArray$.prototype, '_getter', {value: function (index) {
                  if (arguments.length < 1) throw SyntaxError('Not enough arguments');
  
                  index = ToUint32(index);
                  if (index >= this.length)
                      return undefined;
  
                  var bytes = [], i, o;
                  for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT;
                       i < this.BYTES_PER_ELEMENT;
                       i += 1, o += 1) {
                      bytes.push(this.buffer._bytes[o]);
                  }
                  return this._unpack(bytes);
              }});
  
              // NONSTANDARD: convenience alias for getter: type get(unsigned long index);
              Object.defineProperty($TypedArray$.prototype, 'get', {value: $TypedArray$.prototype._getter});
  
              // WebIDL: setter void (unsigned long index, type value);
              Object.defineProperty($TypedArray$.prototype, '_setter', {value: function (index, value) {
                  if (arguments.length < 2) throw SyntaxError('Not enough arguments');
  
                  index = ToUint32(index);
                  if (index >= this.length)
                      return;
  
                  var bytes = this._pack(value), i, o;
                  for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT;
                       i < this.BYTES_PER_ELEMENT;
                       i += 1, o += 1) {
                      this.buffer._bytes[o] = bytes[i];
                  }
              }});
  
              // get %TypedArray%.prototype.buffer
              // get %TypedArray%.prototype.byteLength
              // get %TypedArray%.prototype.byteOffset
              // -- applied directly to the object in the constructor
  
              // %TypedArray%.prototype.constructor
              Object.defineProperty($TypedArray$.prototype, 'constructor', {value: $TypedArray$});
  
              // %TypedArray%.prototype.copyWithin (target, start, end = this.length )
              Object.defineProperty($TypedArray$.prototype, 'copyWithin', {value: function (m_target, m_start) {
                  var m_end = arguments[2];
  
                  var m_o = ToObject(this);
                  var lenVal = m_o.length;
                  var m_len = ToUint32(lenVal);
                  m_len = max(m_len, 0);
                  var relativeTarget = ToInt32(m_target);
                  var m_to;
                  if (relativeTarget < 0)
                  {
                      m_to = max(m_len + relativeTarget, 0);
                  }
                  else
                  {
                      m_to = min(relativeTarget, m_len);
                  }
                  var relativeStart = ToInt32(m_start);
                  var m_from;
                  if (relativeStart < 0)
                  {
                      m_from = max(m_len + relativeStart, 0);
                  }
                  else
                  {
                      m_from = min(relativeStart, m_len);
                  }
                  var relativeEnd;
                  if (m_end === undefined)
                  {
                      relativeEnd = m_len;
                  }
                  else
                  {
                      relativeEnd = ToInt32(m_end);
                  }
                  var m_final;
                  if (relativeEnd < 0) {
                       m_final = max(m_len + relativeEnd, 0);
                  } else {
                       m_final = min(relativeEnd, m_len);
                  }
  
                  var m_count = min(m_final - m_from, m_len - m_to);
                  var direction;
                  if (from < m_to && m_to < m_from + m_count) {
                      direction = -1;
                      m_from = m_from + m_count - 1;
                      m_to = m_to + m_count - 1;
                  } else {
                      direction = 1;
                  }
                  while (count > 0) {
                      m_o._setter(m_to, m_o._getter(m_from));
                      m_from = m_from + direction;
                      m_to = m_to + direction;
                      m_count = m_count - 1;
                  }
                  return m_o;
              }});
  
              // %TypedArray%.prototype.entries ( )
              // -- defined in es6.js to shim browsers w/ native TypedArrays
  
              // %TypedArray%.prototype.every ( callbackfn, thisArg = undefined )
              Object.defineProperty($TypedArray$.prototype, 'every', {value: function (callbackfn) {
                  if (this === undefined || this === null) throw TypeError();
                  var t = Object(this);
                  var len = ToUint32(t.length);
                  if (!IsCallable(callbackfn)) throw TypeError();
                  var thisArg = arguments[1];
                  for (var i = 0; i < len; i++) {
                      if (!callbackfn.call(thisArg, t._getter(i), i, t))
                          return false;
                  }
                  return true;
              }});
  
              // %TypedArray%.prototype.fill (value, start = 0, end = this.length )
              Object.defineProperty($TypedArray$.prototype, 'fill', {value: function (value) {
                  var m_start = arguments[1],
                      m_end = arguments[2];
  
                  var m_o = ToObject(this);
                  var lenVal = m_o.length;
                  var m_len = ToUint32(lenVal);
                  m_len = max(m_len, 0);
                  var relativeStart = ToInt32(m_start);
                  var m_k;
                  if (relativeStart < 0)
                  {
                      m_k = max((m_len + relativeStart), 0);
                  }
                  else
                  {
                      m_k = min(relativeStart, m_len);
                  }
                  var relativeEnd;
                  if (m_end === undefined)
                  {
                      relativeEnd = m_len;
                  }
                  else
                  {
                      relativeEnd = ToInt32(m_end);
                  }
                  var m_final;
                  if (relativeEnd < 0)
                  {
                      m_final = max((m_len + relativeEnd), 0);
                  }
                  else
                  {
                      m_final = min(relativeEnd, m_len);
                  }
                  while (m_k < m_final) {
                      m_o._setter(m_k, value);
                      m_k += 1;
                  }
                  return m_o;
              }});
  
              // %TypedArray%.prototype.filter ( callbackfn, thisArg = undefined )
              Object.defineProperty($TypedArray$.prototype, 'filter', {value: function (callbackfn) {
                  if (this === undefined || this === null) throw TypeError();
                  var t = Object(this);
                  var len = ToUint32(t.length);
                  if (!IsCallable(callbackfn)) throw TypeError();
                  var res = [];
                  var thisp = arguments[1];
                  for (var i = 0; i < len; i++) {
                      var val = t._getter(i); // in case fun mutates this
                      if (callbackfn.call(thisp, val, i, t))
                          res.push(val);
                  }
                  return new this.constructor(res);
              }});
  
              // %TypedArray%.prototype.find (predicate, thisArg = undefined)
              Object.defineProperty($TypedArray$.prototype, 'find', {value: function (predicate) {
                  var o = ToObject(this);
                  var lenValue = o.length;
                  var len = ToUint32(lenValue);
                  if (!IsCallable(predicate)) throw TypeError();
                  var t = arguments.length > 1 ? arguments[1] : undefined;
                  var k = 0;
                  while (k < len) {
                      var kValue = o._getter(k);
                      var testResult = predicate.call(t, kValue, k, o);
                      if (Boolean(testResult))
                          return kValue;
                      ++k;
                  }
                  return undefined;
              }});
  
              // %TypedArray%.prototype.findIndex ( predicate, thisArg = undefined )
              Object.defineProperty($TypedArray$.prototype, 'findIndex', {value: function (predicate) {
                  var o = ToObject(this);
                  var lenValue = o.length;
                  var len = ToUint32(lenValue);
                  if (!IsCallable(predicate)) throw TypeError();
                  var t = arguments.length > 1 ? arguments[1] : undefined;
                  var k = 0;
                  while (k < len) {
                      var kValue = o._getter(k);
                      var testResult = predicate.call(t, kValue, k, o);
                      if (Boolean(testResult))
                          return k;
                      ++k;
                  }
                  return -1;
              }});
  
              // %TypedArray%.prototype.forEach ( callbackfn, thisArg = undefined )
              Object.defineProperty($TypedArray$.prototype, 'forEach', {value: function (callbackfn) {
                  if (this === undefined || this === null) throw TypeError();
                  var t = Object(this);
                  var len = ToUint32(t.length);
                  if (!IsCallable(callbackfn)) throw TypeError();
                  var thisp = arguments[1];
                  for (var i = 0; i < len; i++)
                      callbackfn.call(thisp, t._getter(i), i, t);
              }});
  
              // %TypedArray%.prototype.indexOf (searchElement, fromIndex = 0 )
              Object.defineProperty($TypedArray$.prototype, 'indexOf', {value: function (searchElement) {
                  if (this === undefined || this === null) throw TypeError();
                  var t = Object(this);
                  var len = ToUint32(t.length);
                  if (len === 0) return -1;
                  var no = 0;
                  var na;
                  if (arguments.length > 0) {
                      na = Number(arguments[1]);
                      if (na !== no) {
                          no = 0;
                      } else if (na !== 0 && na !== (1 / 0) && na !== -(1 / 0)) {
                          no = (na > 0 || -1) * floor(abs(na));
                      }
                  }
                  if (no >= len) return -1;
                  var k = no >= 0 ? no : max(len - abs(no), 0);
                  for (; k < len; k++) {
                      if (t._getter(k) === searchElement) {
                          return k;
                      }
                  }
                  return -1;
              }});
  
              // %TypedArray%.prototype.join ( separator )
              Object.defineProperty($TypedArray$.prototype, 'join', {value: function (separator) {
                  if (this === undefined || this === null) throw TypeError();
                  var t = Object(this);
                  var len = ToUint32(t.length);
                  var tmp = Array(len);
                  for (var i = 0; i < len; ++i)
                      tmp[i] = t._getter(i);
                  return tmp.join(separator === undefined ? ',' : separator); // Hack for IE7
              }});
  
              // %TypedArray%.prototype.keys ( )
              // -- defined in es6.js to shim browsers w/ native TypedArrays
  
              // %TypedArray%.prototype.lastIndexOf ( searchElement, fromIndex = this.length-1 )
              Object.defineProperty($TypedArray$.prototype, 'lastIndexOf', {value: function (searchElement) {
                  if (this === undefined || this === null) throw TypeError();
                  var t = Object(this);
                  var len = ToUint32(t.length);
                  if (len === 0) return -1;
                  var n = len;
                  if (arguments.length > 1) {
                      n = Number(arguments[1]);
                      if (n !== n) {
                          n = 0;
                      } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
                          n = (n > 0 || -1) * floor(abs(n));
                      }
                  }
                  var k = n >= 0 ? min(n, len - 1) : len - abs(n);
                  for (; k >= 0; k--) {
                      if (t._getter(k) === searchElement)
                          return k;
                  }
                  return -1;
              }});
  
              // get %TypedArray%.prototype.length
              // -- applied directly to the object in the constructor
  
              // %TypedArray%.prototype.map ( callbackfn, thisArg = undefined )
              Object.defineProperty($TypedArray$.prototype, 'map', {value: function (callbackfn) {
                  if (this === undefined || this === null) throw TypeError();
                  var t = Object(this);
                  var len = ToUint32(t.length);
                  if (!IsCallable(callbackfn)) throw TypeError();
                  var res = [];
                  res.length = len;
                  var thisp = arguments[1];
                  for (var i = 0; i < len; i++)
                      res[i] = callbackfn.call(thisp, t._getter(i), i, t);
                  return new this.constructor(res);
              }});
  
              // %TypedArray%.prototype.reduce ( callbackfn [, initialValue] )
              Object.defineProperty($TypedArray$.prototype, 'reduce', {value: function (callbackfn) {
                  if (this === undefined || this === null) throw TypeError();
                  var t = Object(this);
                  var len = ToUint32(t.length);
                  if (!IsCallable(callbackfn)) throw TypeError();
                  // no value to return if no initial value and an empty array
                  if (len === 0 && arguments.length === 1) throw TypeError();
                  var k = 0;
                  var accumulator;
                  if (arguments.length >= 2) {
                      accumulator = arguments[1];
                  } else {
                      accumulator = t._getter(k++);
                  }
                  while (k < len) {
                      accumulator = callbackfn.call(undefined, accumulator, t._getter(k), k, t);
                      k++;
                  }
                  return accumulator;
              }});
  
              // %TypedArray%.prototype.reduceRight ( callbackfn [, initialValue] )
              Object.defineProperty($TypedArray$.prototype, 'reduceRight', {value: function (callbackfn) {
                  if (this === undefined || this === null) throw TypeError();
                  var t = Object(this);
                  var len = ToUint32(t.length);
                  if (!IsCallable(callbackfn)) throw TypeError();
                  // no value to return if no initial value, empty array
                  if (len === 0 && arguments.length === 1) throw TypeError();
                  var k = len - 1;
                  var accumulator;
                  if (arguments.length >= 2) {
                      accumulator = arguments[1];
                  } else {
                      accumulator = t._getter(k--);
                  }
                  while (k >= 0) {
                      accumulator = callbackfn.call(undefined, accumulator, t._getter(k), k, t);
                      k--;
                  }
                  return accumulator;
              }});
  
              // %TypedArray%.prototype.reverse ( )
              Object.defineProperty($TypedArray$.prototype, 'reverse', {value: function () {
                  if (this === undefined || this === null) throw TypeError();
                  var t = Object(this);
                  var len = ToUint32(t.length);
                  var half = floor(len / 2);
                  for (var i = 0, j = len - 1; i < half; ++i, --j) {
                      var tmp = t._getter(i);
                      t._setter(i, t._getter(j));
                      t._setter(j, tmp);
                  }
                  return t;
              }});
  
              // %TypedArray%.prototype.set(array, offset = 0 )
              // %TypedArray%.prototype.set(typedArray, offset = 0 )
              // WebIDL: void set(TypedArray array, optional unsigned long offset);
              // WebIDL: void set(sequence<type> array, optional unsigned long offset);
              Object.defineProperty($TypedArray$.prototype, 'set', {value: function (index, value) {
                  if (arguments.length < 1) throw SyntaxError('Not enough arguments');
                  var array, sequence, offset, len,
                      i, s, d,
                      byteOffset, byteLength, tmp;
  
                  if (typeof arguments[0] === 'object' && arguments[0].constructor === this.constructor) {
                      // void set(TypedArray array, optional unsigned long offset);
                      array = arguments[0];
                      offset = ToUint32(arguments[1]);
  
                      if (offset + array.length > this.length) {
                          throw RangeError('Offset plus length of array is out of range');
                      }
  
                      byteOffset = this.byteOffset + offset * this.BYTES_PER_ELEMENT;
                      byteLength = array.length * this.BYTES_PER_ELEMENT;
  
                      if (array.buffer === this.buffer) {
                          tmp = [];
                          for (i = 0, s = array.byteOffset; i < byteLength; i += 1, s += 1) {
                              tmp[i] = array.buffer._bytes[s];
                          }
                          for (i = 0, d = byteOffset; i < byteLength; i += 1, d += 1) {
                              this.buffer._bytes[d] = tmp[i];
                          }
                      } else {
                          for (i = 0, s = array.byteOffset, d = byteOffset;
                               i < byteLength; i += 1, s += 1, d += 1) {
                              this.buffer._bytes[d] = array.buffer._bytes[s];
                          }
                      }
                  } else if (typeof arguments[0] === 'object' && typeof arguments[0].length !== 'undefined') {
                      // void set(sequence<type> array, optional unsigned long offset);
                      sequence = arguments[0];
                      len = ToUint32(sequence.length);
                      offset = ToUint32(arguments[1]);
  
                      if (offset + len > this.length) {
                          throw RangeError('Offset plus length of array is out of range');
                      }
  
                      for (i = 0; i < len; i += 1) {
                          s = sequence[i];
                          this._setter(offset + i, Number(s));
                      }
                  } else {
                      throw TypeError('Unexpected argument type(s)');
                  }
              }});
  
              // %TypedArray%.prototype.slice ( start, end )
              Object.defineProperty($TypedArray$.prototype, 'slice', {value: function (m_start, m_end) {
                  var m_o = ToObject(this);
                  var lenVal = m_o.length;
                  var m_len = ToUint32(lenVal);
                  var relativeStart = ToInt32(m_start);
                  var m_k = (relativeStart < 0) ? max(m_len + relativeStart, 0) : min(relativeStart, m_len);
                  var relativeEnd = (m_end === undefined) ? m_len : ToInt32(m_end);
                  var m_final = (relativeEnd < 0) ? max(m_len + relativeEnd, 0) : min(relativeEnd, m_len);
                  var m_count = m_final - m_k;
                  var m_c = m_o.constructor;
                  var m_a = new m_c(m_count);
                  var m_n = 0;
                  while (m_k < m_final) {
                      var kValue = m_o._getter(m_k);
                      m_a._setter(m_n, kValue);
                      ++m_k;
                      ++m_n;
                  }
                  return m_a;
              }});
  
              // %TypedArray%.prototype.some ( callbackfn, thisArg = undefined )
              Object.defineProperty($TypedArray$.prototype, 'some', {value: function (callbackfn) {
                  if (this === undefined || this === null) throw TypeError();
                  var t = Object(this);
                  var len = ToUint32(t.length);
                  if (!IsCallable(callbackfn)) throw TypeError();
                  var thisp = arguments[1];
                  for (var i = 0; i < len; i++) {
                      if (callbackfn.call(thisp, t._getter(i), i, t)) {
                          return true;
                      }
                  }
                  return false;
              }});
  
              // %TypedArray%.prototype.sort ( comparefn )
              Object.defineProperty($TypedArray$.prototype, 'sort', {value: function (comparefn) {
                  if (this === undefined || this === null) throw TypeError();
                  var t = Object(this);
                  var len = ToUint32(t.length);
                  var tmp = Array(len);
                  for (var i = 0; i < len; ++i)
                      tmp[i] = t._getter(i);
                  if (comparefn) tmp.sort(comparefn); else tmp.sort(); // Hack for IE8/9
                  for (i = 0; i < len; ++i)
                      t._setter(i, tmp[i]);
                  return t;
              }});
  
              // %TypedArray%.prototype.subarray(begin = 0, end = this.length )
              // WebIDL: TypedArray subarray(long begin, optional long end);
              Object.defineProperty($TypedArray$.prototype, 'subarray', {value: function (start, end) {
                  function clamp(v, min, max) {
                      return v < min ? min : v > max ? max : v;
                  }
  
                  start = ToInt32(start);
                  end = ToInt32(end);
  
                  if (arguments.length < 1) {
                      start = 0;
                  }
                  if (arguments.length < 2) {
                      end = this.length;
                  }
  
                  if (start < 0) {
                      start = this.length + start;
                  }
                  if (end < 0) {
                      end = this.length + end;
                  }
  
                  start = clamp(start, 0, this.length);
                  end = clamp(end, 0, this.length);
  
                  var len = end - start;
                  if (len < 0) {
                      len = 0;
                  }
  
                  return new this.constructor(
                      this.buffer, this.byteOffset + start * this.BYTES_PER_ELEMENT, len);
              }});
  
              // %TypedArray%.prototype.toLocaleString ( )
              // %TypedArray%.prototype.toString ( )
              // %TypedArray%.prototype.values ( )
              // %TypedArray%.prototype [ @@iterator ] ( )
              // get %TypedArray%.prototype [ @@toStringTag ]
              // -- defined in es6.js to shim browsers w/ native TypedArrays
  
              function makeTypedArray(elementSize, pack, unpack) {
                  // Each TypedArray type requires a distinct constructor instance with
                  // identical logic, which this produces.
                  var TypedArray = function () {
                      Object.defineProperty(this, 'constructor', {value: TypedArray});
                      $TypedArray$.apply(this, arguments);
                      makeArrayAccessors(this);
                  };
                  if ('__proto__' in TypedArray) {
                      TypedArray.__proto__ = $TypedArray$;
                  } else {
                      TypedArray.from = $TypedArray$.from;
                      TypedArray.of = $TypedArray$.of;
                  }
  
                  TypedArray.BYTES_PER_ELEMENT = elementSize;
  
                  var TypedArrayPrototype = function () {
                  };
                  TypedArrayPrototype.prototype = $TypedArrayPrototype$;
  
                  TypedArray.prototype = new TypedArrayPrototype();
  
                  Object.defineProperty(TypedArray.prototype, 'BYTES_PER_ELEMENT', {value: elementSize});
                  Object.defineProperty(TypedArray.prototype, '_pack', {value: pack});
                  Object.defineProperty(TypedArray.prototype, '_unpack', {value: unpack});
  
                  return TypedArray;
              }
  
              var Int8Array = makeTypedArray(1, packI8, unpackI8);
              var Uint8Array = makeTypedArray(1, packU8, unpackU8);
              var Uint8ClampedArray = makeTypedArray(1, packU8Clamped, unpackU8);
              var Int16Array = makeTypedArray(2, packI16, unpackI16);
              var Uint16Array = makeTypedArray(2, packU16, unpackU16);
              var Int32Array = makeTypedArray(4, packI32, unpackI32);
              var Uint32Array = makeTypedArray(4, packU32, unpackU32);
              var Float32Array = makeTypedArray(4, packF32, unpackF32);
              var Float64Array = makeTypedArray(8, packF64, unpackF64);
  
              global.Int8Array = win.Int8Array = global.Int8Array || Int8Array;
              global.Uint8Array = win.Uint8Array = global.Uint8Array || Uint8Array;
              global.Uint8ClampedArray = win.Uint8ClampedArray = global.Uint8ClampedArray || Uint8ClampedArray;
              global.Int16Array = win.Int16Array = global.Int16Array || Int16Array;
              global.Uint16Array = win.Uint16Array = global.Uint16Array || Uint16Array;
              global.Int32Array = win.Int32Array = global.Int32Array || Int32Array;
              global.Uint32Array = win.Uint32Array = global.Uint32Array || Uint32Array;
              global.Float32Array = win.Float32Array = global.Float32Array || Float32Array;
              global.Float64Array = win.Float64Array = global.Float64Array || Float64Array;
          }());
  
          //
          // 6 The DataView View Type
          //
  
          (function () {
              function r(array, index) {
                  return IsCallable(array.get) ? array.get(index) : array[index];
              }
  
              var IS_BIG_ENDIAN = (function () {
                  var u16array = new global.Uint16Array([0x1234]),
                      u8array = new global.Uint8Array(u16array.buffer);
                  return r(u8array, 0) === 0x12;
              }());
  
              // DataView(buffer, byteOffset=0, byteLength=undefined)
              // WebIDL: Constructor(ArrayBuffer buffer,
              //                     optional unsigned long byteOffset,
              //                     optional unsigned long byteLength)
              function DataView(buffer, byteOffset, byteLength) {
                  if (!(buffer instanceof ArrayBuffer || Class(buffer) === 'ArrayBuffer')) throw TypeError();
  
                  byteOffset = ToUint32(byteOffset);
                  if (byteOffset > buffer.byteLength)
                      throw RangeError('byteOffset out of range');
  
                  if (byteLength === undefined)
                      byteLength = buffer.byteLength - byteOffset;
                  else
                      byteLength = ToUint32(byteLength);
  
                  if ((byteOffset + byteLength) > buffer.byteLength)
                      throw RangeError('byteOffset and length reference an area beyond the end of the buffer');
  
                  Object.defineProperty(this, 'buffer', {value: buffer});
                  Object.defineProperty(this, 'byteLength', {value: byteLength});
                  Object.defineProperty(this, 'byteOffset', {value: byteOffset});
              };
  
              // get DataView.prototype.buffer
              // get DataView.prototype.byteLength
              // get DataView.prototype.byteOffset
              // -- applied directly to instances by the constructor
  
              function makeGetter(arrayType) {
                  return function GetViewValue(byteOffset, littleEndian) {
                      byteOffset = ToUint32(byteOffset);
  
                      if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength)
                          throw RangeError('Array index out of range');
  
                      byteOffset += this.byteOffset;
  
                      var uint8Array = new global.Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT),
                          bytes = [];
                      for (var i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1)
                          bytes.push(r(uint8Array, i));
  
                      if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN))
                          bytes.reverse();
  
                      return r(new arrayType(new global.Uint8Array(bytes).buffer), 0);
                  };
              }
  
              Object.defineProperty(DataView.prototype, 'getUint8', {value: makeGetter(global.Uint8Array)});
              Object.defineProperty(DataView.prototype, 'getInt8', {value: makeGetter(global.Int8Array)});
              Object.defineProperty(DataView.prototype, 'getUint16', {value: makeGetter(global.Uint16Array)});
              Object.defineProperty(DataView.prototype, 'getInt16', {value: makeGetter(global.Int16Array)});
              Object.defineProperty(DataView.prototype, 'getUint32', {value: makeGetter(global.Uint32Array)});
              Object.defineProperty(DataView.prototype, 'getInt32', {value: makeGetter(global.Int32Array)});
              Object.defineProperty(DataView.prototype, 'getFloat32', {value: makeGetter(global.Float32Array)});
              Object.defineProperty(DataView.prototype, 'getFloat64', {value: makeGetter(global.Float64Array)});
  
              function makeSetter(arrayType) {
                  return function SetViewValue(byteOffset, value, littleEndian) {
                      byteOffset = ToUint32(byteOffset);
                      if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength)
                          throw RangeError('Array index out of range');
  
                      // Get bytes
                      var typeArray = new arrayType([value]),
                          byteArray = new global.Uint8Array(typeArray.buffer),
                          bytes = [], i, byteView;
  
                      for (i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1)
                          bytes.push(r(byteArray, i));
  
                      // Flip if necessary
                      if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN))
                          bytes.reverse();
  
                      // Write them
                      byteView = new Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT);
                      byteView.set(bytes);
                  };
              }
  
              Object.defineProperty(DataView.prototype, 'setUint8', {value: makeSetter(global.Uint8Array)});
              Object.defineProperty(DataView.prototype, 'setInt8', {value: makeSetter(global.Int8Array)});
              Object.defineProperty(DataView.prototype, 'setUint16', {value: makeSetter(global.Uint16Array)});
              Object.defineProperty(DataView.prototype, 'setInt16', {value: makeSetter(global.Int16Array)});
              Object.defineProperty(DataView.prototype, 'setUint32', {value: makeSetter(global.Uint32Array)});
              Object.defineProperty(DataView.prototype, 'setInt32', {value: makeSetter(global.Int32Array)});
              Object.defineProperty(DataView.prototype, 'setFloat32', {value: makeSetter(global.Float32Array)});
              Object.defineProperty(DataView.prototype, 'setFloat64', {value: makeSetter(global.Float64Array)});
  
              global.DataView = global.DataView || DataView;
  
          }());
  
      }(exports, window)
          );
  }
  // workaround for crypto-js on IE11
  // http://code.google.com/p/crypto-js/issues/detail?id=81
  if (typeof window !== "undefined") {
      if (!('Uint8ClampedArray' in window)) {
          window.Uint8ClampedArray = window.Uint8Array;
      }
  }
  },{}],15:[function(require,module,exports){
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  AutobahnJS - http://autobahn.ws, http://wamp.ws
  //
  //  A JavaScript library for WAMP ("The Web Application Messaging Protocol").
  //
  //  Copyright (c) Crossbar.io Technologies GmbH and contributors
  //
  //  Licensed under the MIT License.
  //  http://www.opensource.org/licenses/mit-license.php
  //
  ///////////////////////////////////////////////////////////////////////////////
  
  var log = require('./log.js');
  
  
  // generate a WAMP ID: this might be serializer specific, as
  // we need to enforce encoding into an integer, not float
  // eg we need to do some extra stuff for msgpack (json and
  // cbor are fine "as is")
  function newid () {
     return Math.floor(Math.random() * 9007199254740992);
  }
  
  
  function JSONSerializer(replacer, reviver) {
     this.replacer = replacer;
     this.reviver = reviver;
     this.SERIALIZER_ID = 'json';
     this.BINARY = false;
  
     // JSON encoder does not need anything special here
     this.newid = newid;
  }
  
  JSONSerializer.prototype.serialize = function (obj) {
     try {
        var payload = JSON.stringify(obj, this.replacer);
        return payload;
     } catch (e) {
        log.warn('JSON encoding error', e);
        throw e;
     }
  };
  
  JSONSerializer.prototype.unserialize = function (payload) {
     try {
        var obj = JSON.parse(payload, this.reviver);
        return obj;
     } catch (e) {
        log.warn('JSON decoding error', e);
        throw e;
     }
  };
  
  exports.JSONSerializer = JSONSerializer;
  
  
  // https://github.com/kawanet/msgpack-lite/
  // https://github.com/kawanet/int64-buffer
  var msgpack = require('msgpack-lite');
  
  // this is needed for correct msgpack serialization of WAMP session IDs
  var Uint64BE = require('int64-buffer').Uint64BE;
  
  function MsgpackSerializer() {
     this.SERIALIZER_ID = 'msgpack';
     this.BINARY = true;
     this.codec = msgpack.createCodec();
  
     // msgpack: Uint64BE ensures that ID is encoded as int instead of double
     this.newid = function () { return new Uint64BE(newid()); };
  }
  
  MsgpackSerializer.prototype.serialize = function (obj) {
     try {
        var payload = msgpack.encode(obj, {codec: this.codec});
        return payload;
     } catch (e) {
        log.warn('MessagePack encoding error', e);
        throw e;
     }
  };
  
  MsgpackSerializer.prototype.unserialize = function (payload) {
     try {
        // need to encapsulate ArrayBuffer into Uint8Array for msgpack decoding
        // https://github.com/kawanet/msgpack-lite/issues/44
        var obj = msgpack.decode(new Uint8Array(payload), {codec: this.codec});
        return obj;
     } catch (e) {
        log.warn('MessagePack decoding error', e);
        throw e;
     }
  };
  
  /**
   * Register a packer and/or unpacker functions for a given type.
   *
   * The msgpack specification allows applications to register up to 128 extension
   * types.
   *
   * @param code numeric extension code (between 0-127)
   * @param type constructor for the given type (only required when packer is defined)
   * @param packer a function that takes an object and returns a Buffer
   * @param unpacker a function that takes a Buffer and returns an instance of the given type
   */
  MsgpackSerializer.prototype.registerExtType = function (code, type, packer, unpacker) {
     if (packer && type) {
        this.codec.addExtPacker(code, type, packer);
     }
     if (unpacker) {
        this.codec.addExtUnpacker(code, unpacker);
     }
  };
  
  exports.MsgpackSerializer = MsgpackSerializer;
  
  
  // http://hildjj.github.io/node-cbor/
  var cbor = require('cbor');
  
  function CBORSerializer() {
     this.SERIALIZER_ID = 'cbor';
     this.BINARY = true;
  
     // CBOR encoder does not need anything special here
     this.newid = newid;
  }
  
  CBORSerializer.prototype.serialize = function (obj) {
     try {
        var payload = cbor.encode(obj);
        return payload;
     } catch (e) {
        log.warn('CBOR encoding error', e);
        throw e;
     }
  };
  
  CBORSerializer.prototype.unserialize = function (payload) {
     try {
        //var obj = cbor.decodeAllSync(payload)[0];
        var obj = cbor.decodeFirstSync(payload);
        return obj;
     } catch (e) {
        log.warn('CBOR decoding error', e);
        throw e;
     }
  };
  
  exports.CBORSerializer = CBORSerializer;
  
  },{"./log.js":6,"cbor":22,"int64-buffer":68,"msgpack-lite":70}],16:[function(require,module,exports){
  (function (global){
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  AutobahnJS - http://autobahn.ws, http://wamp.ws
  //
  //  A JavaScript library for WAMP ("The Web Application Messaging Protocol").
  //
  //  Copyright (c) Crossbar.io Technologies GmbH and contributors
  //
  //  Licensed under the MIT License.
  //  http://www.opensource.org/licenses/mit-license.php
  //
  ///////////////////////////////////////////////////////////////////////////////
  
  // require('assert') would be nice .. but it does not
  // work with Google Closure after Browserify
  
  var when = require('when');
  var when_fn = require("when/function");
  
  var log = require('./log.js');
  var util = require('./util.js');
  
  // IE fallback (http://afuchs.tumblr.com/post/23550124774/date-now-in-ie8)
  Date.now = Date.now || function() { return +new Date; };
  
  
  // WAMP "Advanced Profile" support in AutobahnJS per role
  //
  var WAMP_FEATURES = {
     caller: {
        features: {
           caller_identification: true,
           //call_timeout: true,
           //call_canceling: true,
           progressive_call_results: true
        }
     },
     callee: {
        features: {
           caller_identification: true,
           //call_trustlevels: true,
           pattern_based_registration: true,
           shared_registration: true,
           //call_timeout: true,
           //call_canceling: true,
           progressive_call_results: true,
           registration_revocation: true
        }
     },
     publisher: {
        features: {
           publisher_identification: true,
           subscriber_blackwhite_listing: true,
           publisher_exclusion: true
        }
     },
     subscriber: {
        features: {
           publisher_identification: true,
           //publication_trustlevels: true,
           pattern_based_subscription: true,
           subscription_revocation: true
           //event_history: true,
        }
     }
  };
  
  
  var Invocation = function (procedure,
                             progress,
                             caller,
                             caller_authid,
                             caller_authrole) {
  
     var self = this;
  
     self.procedure = procedure;
     self.progress = progress;
     self.caller = caller;
     self.caller_authid = caller_authid;
     self.caller_authrole = caller_authrole;
  };
  
  
  var Event = function (publication,
                        topic,
                        publisher,
                        publisher_authid,
                        publisher_authrole) {
  
     var self = this;
  
     self.publication = publication;
     self.topic = topic;
     self.publisher = publisher;
     self.publisher_authid = publisher_authid;
     self.publisher_authrole = publisher_authrole;
  };
  
  
  var Result = function (args, kwargs) {
  
     var self = this;
  
     self.args = args || [];
     self.kwargs = kwargs || {};
  };
  
  
  var Error = function (error, args, kwargs) {
  
     var self = this;
  
     self.error = error;
     self.args = args || [];
     self.kwargs = kwargs || {};
  };
  
  
  var Subscription = function (topic, handler, options, session, id) {
  
     var self = this;
  
     self.topic = topic;
     self.handler = handler;
     self.options = options || {};
     self.session = session;
     self.id = id;
  
     self.active = true;
  
     // this will fire when the handler is unsubscribed
     self._on_unsubscribe = session._defer();
  
     if (self._on_unsubscribe.promise.then) {
        // whenjs has the actual user promise in an attribute
        self.on_unsubscribe = self._on_unsubscribe.promise;
     } else {
        self.on_unsubscribe = self._on_unsubscribe;
     }
  };
  
  
  Subscription.prototype.unsubscribe = function () {
  
     var self = this;
     return self.session.unsubscribe(self);
  };
  
  
  var Registration = function (procedure, endpoint, options, session, id) {
  
     var self = this;
  
     self.procedure = procedure;
     self.endpoint = endpoint;
     self.options = options || {};
     self.session = session;
     self.id = id;
  
     self.active = true;
  
     // this will fire when the endpoint is unregistered
     self._on_unregister = session._defer();
  
     if (self._on_unregister.promise.then) {
        // whenjs has the actual user promise in an attribute
        self.on_unregister = self._on_unregister.promise;
     } else {
        self.on_unregister = self._on_unregister;
     }
  };
  
  
  Registration.prototype.unregister = function () {
  
     var self = this;
     return self.session.unregister(self);
  };
  
  
  var Publication = function (id) {
  
     var self = this;
     self.id = id;
  };
  
  
  var MSG_TYPE = {
     HELLO: 1,
     WELCOME: 2,
     ABORT: 3,
     CHALLENGE: 4,
     AUTHENTICATE: 5,
     GOODBYE: 6,
     HEARTBEAT: 7,
     ERROR: 8,
     PUBLISH: 16,
     PUBLISHED: 17,
     SUBSCRIBE: 32,
     SUBSCRIBED: 33,
     UNSUBSCRIBE: 34,
     UNSUBSCRIBED: 35,
     EVENT: 36,
     CALL: 48,
     CANCEL: 49,
     RESULT: 50,
     REGISTER: 64,
     REGISTERED: 65,
     UNREGISTER: 66,
     UNREGISTERED: 67,
     INVOCATION: 68,
     INTERRUPT: 69,
     YIELD: 70
  };
  
  
  
  var Session = function (socket, defer, onchallenge) {
  
     var self = this;
  
     // the transport connection (WebSocket object)
     self._socket = socket;
  
     // the Deferred factory to use
     self._defer = defer;
  
     // the WAMP authentication challenge handler
     self._onchallenge = onchallenge;
  
     // the WAMP session ID
     self._id = null;
  
     // the WAMP realm joined
     self._realm = null;
  
     // the WAMP features in use
     self._features = null;
  
     // closing state
     self._goodbye_sent = false;
     self._transport_is_closing = false;
  
     // outstanding requests;
     self._publish_reqs = {};
     self._subscribe_reqs = {};
     self._unsubscribe_reqs = {};
     self._call_reqs = {};
     self._register_reqs = {};
     self._unregister_reqs = {};
  
     // subscriptions in place;
     self._subscriptions = {};
  
     // registrations in place;
     self._registrations = {};
  
     // incoming invocations;
     self._invocations = {};
  
     // prefix shortcuts for URIs
     self._prefixes = {};
  
     // the defaults for 'disclose_me'
     self._caller_disclose_me = false;
     self._publisher_disclose_me = false;
  
     self._send_wamp = function (msg) {
        log.debug(msg);
        // forward WAMP message to be sent to WAMP transport
        self._socket.send(msg);
     };
  
  
     self._protocol_violation = function (reason) {
        log.warn("failing transport due to protocol violation: " + reason);
        self._socket.close(1002, "protocol violation: " + reason);
     };
  
     self._MESSAGE_MAP = {};
     self._MESSAGE_MAP[MSG_TYPE.ERROR] = {};
  
  
     self._process_SUBSCRIBED = function (msg) {
        //
        // process SUBSCRIBED reply to SUBSCRIBE
        //
        var request = msg[1];
        var subscription = msg[2];
  
        if (request in self._subscribe_reqs) {
  
           var r = self._subscribe_reqs[request];
  
           var d = r[0];
           var topic = r[1];
           var handler = r[2];
           var options = r[3];
  
           if (!(subscription in self._subscriptions)) {
              self._subscriptions[subscription] = [];
           }
           var sub = new Subscription(topic, handler, options, self, subscription);
           self._subscriptions[subscription].push(sub);
  
           d.resolve(sub);
  
           delete self._subscribe_reqs[request];
  
        } else {
           self._protocol_violation("SUBSCRIBED received for non-pending request ID " + request);
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.SUBSCRIBED] = self._process_SUBSCRIBED;
  
  
     self._process_SUBSCRIBE_ERROR = function (msg) {
        //
        // process ERROR reply to SUBSCRIBE
        //
        var request = msg[2];
        if (request in self._subscribe_reqs) {
  
           var details = msg[3];
           var error = new Error(msg[4], msg[5], msg[6]);
  
           var r = self._subscribe_reqs[request];
  
           var d = r[0];
  
           d.reject(error);
  
           delete self._subscribe_reqs[request];
  
        } else {
           self._protocol_violation("SUBSCRIBE-ERROR received for non-pending request ID " + request);
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.ERROR][MSG_TYPE.SUBSCRIBE] = self._process_SUBSCRIBE_ERROR;
  
  
     self._process_UNSUBSCRIBED = function (msg) {
        //
        // process UNSUBSCRIBED reply to UNSUBSCRIBE
        //
        var request = msg[1];
  
        if (request in self._unsubscribe_reqs) {
  
           var r = self._unsubscribe_reqs[request];
  
           var d = r[0];
           var subscription_id = r[1];
  
           if (subscription_id in self._subscriptions) {
              var subs = self._subscriptions[subscription_id];
              // the following should actually be NOP, since UNSUBSCRIBE was
              // only sent when subs got empty
              for (var i = 0; i < subs.length; ++i) {
                 subs[i].active = false;
                 subs[i].on_unsubscribe.resolve();
              }
              delete self._subscriptions[subscription_id];
           }
  
           d.resolve(true);
  
           delete self._unsubscribe_reqs[request];
  
        } else {
  
           if (request === 0) {
  
              // router actively revoked our subscription
              //
              var details = msg[2];
              var subscription_id = details.subscription;
              var reason = details.reason;
  
              if (subscription_id in self._subscriptions) {
                 var subs = self._subscriptions[subscription_id];
                 for (var i = 0; i < subs.length; ++i) {
                    subs[i].active = false;
                    subs[i]._on_unsubscribe.resolve(reason);
                 }
                 delete self._subscriptions[subscription_id];
              } else {
                 self._protocol_violation("non-voluntary UNSUBSCRIBED received for non-existing subscription ID " + subscription_id);
              }
  
           } else {
              self._protocol_violation("UNSUBSCRIBED received for non-pending request ID " + request);
           }
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.UNSUBSCRIBED] = self._process_UNSUBSCRIBED;
  
  
     self._process_UNSUBSCRIBE_ERROR = function (msg) {
        //
        // process ERROR reply to UNSUBSCRIBE
        //
        var request = msg[2];
        if (request in self._unsubscribe_reqs) {
  
           var details = msg[3];
           var error = new Error(msg[4], msg[5], msg[6]);
  
           var r = self._unsubscribe_reqs[request];
  
           var d = r[0];
           var subscription = r[1];
  
           d.reject(error);
  
           delete self._unsubscribe_reqs[request];
  
        } else {
           self._protocol_violation("UNSUBSCRIBE-ERROR received for non-pending request ID " + request);
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.ERROR][MSG_TYPE.UNSUBSCRIBE] = self._process_UNSUBSCRIBE_ERROR;
  
  
     self._process_PUBLISHED = function (msg) {
        //
        // process PUBLISHED reply to PUBLISH
        //
        var request = msg[1];
        var publication = msg[2];
  
        if (request in self._publish_reqs) {
  
           var r = self._publish_reqs[request];
  
           var d = r[0];
           var options = r[1];
  
           var pub = new Publication(publication);
           d.resolve(pub);
  
           delete self._publish_reqs[request];
  
        } else {
           self._protocol_violation("PUBLISHED received for non-pending request ID " + request);
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.PUBLISHED] = self._process_PUBLISHED;
  
  
     self._process_PUBLISH_ERROR = function (msg) {
        //
        // process ERROR reply to PUBLISH
        //
        var request = msg[2];
        if (request in self._publish_reqs) {
  
           var details = msg[3];
           var error = new Error(msg[4], msg[5], msg[6]);
  
           var r = self._publish_reqs[request];
  
           var d = r[0];
           var options = r[1];
  
           d.reject(error);
  
           delete self._publish_reqs[request];
  
        } else {
           self._protocol_violation("PUBLISH-ERROR received for non-pending request ID " + request);
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.ERROR][MSG_TYPE.PUBLISH] = self._process_PUBLISH_ERROR;
  
  
     self._process_EVENT = function (msg) {
        //
        // process EVENT message
        //
        // [EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, Details|dict, PUBLISH.Arguments|list, PUBLISH.ArgumentsKw|dict]
  
        var subscription = msg[1];
  
        if (subscription in self._subscriptions) {
  
           var publication = msg[2];
           var details = msg[3];
  
           var args = msg[4] || [];
           var kwargs = msg[5] || {};
  
           var subs = self._subscriptions[subscription];
  
           // we want to provide the subscription topic to the handler, and may need to get this
           // from one of the subscription handler objects attached to the subscription
           // since for non-pattern subscriptions this is not sent over the wire
           var ed = new Event(publication,
                              details.topic || (subs[0] && subs[0].topic),
                              details.publisher,
                              details.publisher_authid,
                              details.publisher_authrole
                        );
  
           for (var i = 0; i < subs.length; ++i) {
              try {
                 subs[i].handler(args, kwargs, ed);
              } catch (e) {
                 log.debug("Exception raised in event handler", e);
              }
           }
  
        } else {
           self._protocol_violation("EVENT received for non-subscribed subscription ID " + subscription);
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.EVENT] = self._process_EVENT;
  
  
     self._process_REGISTERED = function (msg) {
        //
        // process REGISTERED reply to REGISTER
        //
        var request = msg[1];
        var registration = msg[2];
  
        if (request in self._register_reqs) {
  
           var r = self._register_reqs[request];
  
           var d = r[0];
           var procedure = r[1];
           var endpoint = r[2];
           var options = r[3];
  
           var reg = new Registration(procedure, endpoint, options, self, registration);
  
           self._registrations[registration] = reg;
  
           d.resolve(reg);
  
           delete self._register_reqs[request];
  
        } else {
           self._protocol_violation("REGISTERED received for non-pending request ID " + request);
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.REGISTERED] = self._process_REGISTERED;
  
  
     self._process_REGISTER_ERROR = function (msg) {
        //
        // process ERROR reply to REGISTER
        //
        var request = msg[2];
        if (request in self._register_reqs) {
  
           var details = msg[3];
           var error = new Error(msg[4], msg[5], msg[6]);
  
           var r = self._register_reqs[request];
  
           var d = r[0];
  
           d.reject(error);
  
           delete self._register_reqs[request];
  
        } else {
           self._protocol_violation("REGISTER-ERROR received for non-pending request ID " + request);
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.ERROR][MSG_TYPE.REGISTER] = self._process_REGISTER_ERROR;
  
  
     self._process_UNREGISTERED = function (msg) {
        //
        // process UNREGISTERED reply to UNREGISTER
        //
        var request = msg[1];
  
        if (request in self._unregister_reqs) {
  
           var r = self._unregister_reqs[request];
  
           var d = r[0];
           var registration = r[1];
  
           if (registration.id in self._registrations) {
              delete self._registrations[registration.id];
           }
  
           registration.active = false;
           d.resolve();
  
           delete self._unregister_reqs[request];
  
        } else {
  
           if (request === 0) {
  
              // the router actively revoked our registration
              //
              var details = msg[2];
              var registration_id = details.registration;
              var reason = details.reason;
  
              if (registration_id in self._registrations) {
                 var registration = self._registrations[registration_id];
                 registration.active = false;
                 registration._on_unregister.resolve(reason);
                 delete self._registrations[registration_id];
              } else {
                 self._protocol_violation("non-voluntary UNREGISTERED received for non-existing registration ID " + registration_id);
              }
  
           } else {
              self._protocol_violation("UNREGISTERED received for non-pending request ID " + request);
           }
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.UNREGISTERED] = self._process_UNREGISTERED;
  
  
     self._process_UNREGISTER_ERROR = function (msg) {
        //
        // process ERROR reply to UNREGISTER
        //
        var request = msg[2];
        if (request in self._unregister_reqs) {
  
           var details = msg[3];
           var error = new Error(msg[4], msg[5], msg[6]);
  
           var r = self._unregister_reqs[request];
  
           var d = r[0];
           var registration = r[1];
  
           d.reject(error);
  
           delete self._unregister_reqs[request];
  
        } else {
           self._protocol_violation("UNREGISTER-ERROR received for non-pending request ID " + request);
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.ERROR][MSG_TYPE.UNREGISTER] = self._process_UNREGISTER_ERROR;
  
  
     self._process_RESULT = function (msg) {
        //
        // process RESULT reply to CALL
        //
        var request = msg[1];
        if (request in self._call_reqs) {
  
           var details = msg[2];
  
           var args = msg[3] || [];
           var kwargs = msg[4] || {};
  
           // maybe wrap complex result:
           var result = null;
           if (args.length > 1 || Object.keys(kwargs).length > 0) {
              // wrap complex result is more than 1 positional result OR
              // non-empty keyword result
              result = new Result(args, kwargs);
           } else if (args.length > 0) {
              // single positional result
              result = args[0];
           }
  
           var r = self._call_reqs[request];
  
           var d = r[0];
           var options = r[1];
  
           if (details.progress) {
              if (options && options.receive_progress) {
                 d.notify(result);
              }
           } else {
              d.resolve(result);
              delete self._call_reqs[request];
           }
        } else {
           self._protocol_violation("CALL-RESULT received for non-pending request ID " + request);
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.RESULT] = self._process_RESULT;
  
  
     self._process_CALL_ERROR = function (msg) {
        //
        // process ERROR reply to CALL
        //
        var request = msg[2];
        if (request in self._call_reqs) {
  
           var details = msg[3];
           var error = new Error(msg[4], msg[5], msg[6]);
  
           var r = self._call_reqs[request];
  
           var d = r[0];
           var options = r[1];
  
           d.reject(error);
  
           delete self._call_reqs[request];
  
        } else {
           self._protocol_violation("CALL-ERROR received for non-pending request ID " + request);
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.ERROR][MSG_TYPE.CALL] = self._process_CALL_ERROR;
  
  
     self._process_INVOCATION = function (msg) {
        //
        // process INVOCATION message
        //
        // [INVOCATION, Request|id, REGISTERED.Registration|id, Details|dict, CALL.Arguments|list, CALL.ArgumentsKw|dict]
        //
        var request = msg[1];
        var registration = msg[2];
  
        var details = msg[3];
        // receive_progress
        // timeout
        // caller
  
        if (registration in self._registrations) {
  
           var reg = self._registrations[registration];
  
           var args = msg[4] || [];
           var kwargs = msg[5] || {};
  
           // create progress function for invocation
           //
           var progress = null;
           if (details.receive_progress) {
  
              progress = function (args, kwargs) {
                 var progress_msg = [MSG_TYPE.YIELD, request, {progress: true}];
  
                 args = args || [];
                 kwargs = kwargs || {};
  
                 var kwargs_len = Object.keys(kwargs).length;
                 if (args.length || kwargs_len) {
                    progress_msg.push(args);
                    if (kwargs_len) {
                       progress_msg.push(kwargs);
                    }
                 }
                 self._send_wamp(progress_msg);
              }
           };
  
           // we want to provide the regitration procedure to the handler and may
           // need to get this from the registration object attached to the registration
           // since for non-pattern registrations this is not sent over the wire
           var cd = new Invocation(details.procedure || reg.procedure,
                                   progress,
                                   details.caller,
                                   details.caller_authid,
                                   details.caller_authrole
                        );
  
           // We use the following whenjs call wrapper, which automatically
           // wraps a plain, non-promise value in a (immediately resolved) promise
           //
           // See: https://github.com/cujojs/when/blob/master/docs/api.md#fncall
           //
           when_fn.call(reg.endpoint, args, kwargs, cd).then(
  
              function (res) {
                 // construct YIELD message
                 // FIXME: Options
                 //
                 var reply = [MSG_TYPE.YIELD, request, {}];
  
                 if (res instanceof Result) {
                    var kwargs_len = Object.keys(res.kwargs).length;
                    if (res.args.length || kwargs_len) {
                       reply.push(res.args);
                       if (kwargs_len) {
                          reply.push(res.kwargs);
                       }
                    }
                 } else {
                    reply.push([res]);
                 }
  
                 // send WAMP message
                 //
                 self._send_wamp(reply);
              },
  
              function (err) {
                 // construct ERROR message
                 // [ERROR, REQUEST.Type|int, REQUEST.Request|id, Details|dict, Error|uri, Arguments|list, ArgumentsKw|dict]
  
                 var reply = [MSG_TYPE.ERROR, MSG_TYPE.INVOCATION, request, {}];
  
                 if (err instanceof Error) {
  
                    reply.push(err.error);
  
                    var kwargs_len = Object.keys(err.kwargs).length;
                    if (err.args.length || kwargs_len) {
                       reply.push(err.args);
                       if (kwargs_len) {
                          reply.push(err.kwargs);
                       }
                    }
                 } else {
                    reply.push('wamp.error.runtime_error');
                    reply.push([err]);
                 }
  
                 // send WAMP message
                 //
                 self._send_wamp(reply);
              }
           );
  
        } else {
           self._protocol_violation("INVOCATION received for non-registered registration ID " + request);
        }
     };
     self._MESSAGE_MAP[MSG_TYPE.INVOCATION] = self._process_INVOCATION;
  
  
     // callback fired by WAMP transport on receiving a WAMP message
     //
     self._socket.onmessage = function (msg) {
  
        var msg_type = msg[0];
  
        // WAMP session not yet open
        //
        if (!self._id) {
  
           // the first message must be WELCOME, ABORT or CHALLENGE ..
           //
           if (msg_type === MSG_TYPE.WELCOME) {
  
              self._id = msg[1];
  
              // determine actual set of advanced features that can be used
              //
              var rf = msg[2];
              self._features = {};
  
              if (rf.roles.broker) {
                 // "Basic Profile" is mandatory
                 self._features.subscriber = {};
                 self._features.publisher = {};
  
                 // fill in features that both peers support
                 if (rf.roles.broker.features) {
  
                    for (var att in WAMP_FEATURES.publisher.features) {
                       self._features.publisher[att] = WAMP_FEATURES.publisher.features[att] &&
                                                       rf.roles.broker.features[att];
                    }
  
                    for (var att in WAMP_FEATURES.subscriber.features) {
                       self._features.subscriber[att] = WAMP_FEATURES.subscriber.features[att] &&
                                                        rf.roles.broker.features[att];
                    }
                 }
              }
  
              if (rf.roles.dealer) {
                 // "Basic Profile" is mandatory
                 self._features.caller = {};
                 self._features.callee = {};
  
                 // fill in features that both peers support
                 if (rf.roles.dealer.features) {
  
                    for (var att in WAMP_FEATURES.caller.features) {
                       self._features.caller[att] = WAMP_FEATURES.caller.features[att] &&
                                                    rf.roles.dealer.features[att];
                    }
  
                    for (var att in WAMP_FEATURES.callee.features) {
                       self._features.callee[att] = WAMP_FEATURES.callee.features[att] &&
                                                    rf.roles.dealer.features[att];
                    }
                 }
              }
  
              if (self.onjoin) {
                 self.onjoin(msg[2]);
              }
  
           } else if (msg_type === MSG_TYPE.ABORT) {
  
              var details = msg[1];
              var reason = msg[2];
  
              if (self.onleave) {
                 self.onleave(reason, details);
              }
  
           } else if (msg_type === MSG_TYPE.CHALLENGE) {
  
              if (self._onchallenge) {
  
                 var method = msg[1];
                 var extra = msg[2];
  
                 when_fn.call(self._onchallenge, self, method, extra).then(
                    function (signature) {
                       var msg = [MSG_TYPE.AUTHENTICATE, signature, {}];
                       self._send_wamp(msg);
                    },
                    function (err) {
                       log.debug("onchallenge() raised:", err);
  
                       var msg = [MSG_TYPE.ABORT, {message: "sorry, I cannot authenticate (onchallenge handler raised an exception)"}, "wamp.error.cannot_authenticate"];
                       self._send_wamp(msg);
                       self._socket.close(1000);
                    }
                 );
              } else {
                 log.debug("received WAMP challenge, but no onchallenge() handler set");
  
                 var msg = [MSG_TYPE.ABORT, {message: "sorry, I cannot authenticate (no onchallenge handler set)"}, "wamp.error.cannot_authenticate"];
                 self._send_wamp(msg);
                 self._socket.close(1000);
              }
  
           } else {
              self._protocol_violation("unexpected message type " + msg_type);
           }
  
        // WAMP session is open
        //
        } else {
  
           if (msg_type === MSG_TYPE.GOODBYE) {
  
              if (!self._goodbye_sent) {
  
                 var reply = [MSG_TYPE.GOODBYE, {}, "wamp.error.goodbye_and_out"];
                 self._send_wamp(reply);
              }
  
              self._id = null;
              self._realm = null;
              self._features = null;
  
              var details = msg[1];
              var reason = msg[2];
  
              if (self.onleave) {
                 self.onleave(reason, details);
              }
  
           } else {
  
              if (msg_type === MSG_TYPE.ERROR) {
  
                 var request_type = msg[1];
                 if (request_type in self._MESSAGE_MAP[MSG_TYPE.ERROR]) {
  
                    self._MESSAGE_MAP[msg_type][request_type](msg);
  
                 } else {
  
                    self._protocol_violation("unexpected ERROR message with request_type " + request_type);
                 }
  
              } else {
  
                 if (msg_type in self._MESSAGE_MAP) {
  
                    self._MESSAGE_MAP[msg_type](msg);
  
                 } else {
  
                    self._protocol_violation("unexpected message type " + msg_type);
                 }
              }
           }
        }
     };
  
     // session object constructed .. track creation time
     //
     if ('performance' in global && 'now' in performance) {
        self._created = performance.now();
     } else {
        self._created = Date.now();
     }
  };
  
  
  Object.defineProperty(Session.prototype, "defer", {
     get: function () {
        return this._defer;
     }
  });
  
  
  Object.defineProperty(Session.prototype, "id", {
     get: function () {
        return this._id;
     }
  });
  
  
  Object.defineProperty(Session.prototype, "realm", {
     get: function () {
        return this._realm;
     }
  });
  
  
  Object.defineProperty(Session.prototype, "isOpen", {
     get: function () {
        return this.id !== null;
     }
  });
  
  
  Object.defineProperty(Session.prototype, "features", {
     get: function () {
        return this._features;
     }
  });
  
  
  Object.defineProperty(Session.prototype, "caller_disclose_me", {
     get: function () {
        return this._caller_disclose_me;
     },
     set: function (newValue) {
        this._caller_disclose_me = newValue;
     }
  });
  
  
  Object.defineProperty(Session.prototype, "publisher_disclose_me", {
     get: function () {
        return this._publisher_disclose_me;
     },
     set: function (newValue) {
        this._publisher_disclose_me = newValue;
     }
  });
  
  
  Object.defineProperty(Session.prototype, "subscriptions", {
     get: function () {
        var keys = Object.keys(this._subscriptions);
        var vals = [];
        for (var i = 0; i < keys.length; ++i) {
           vals.push(this._subscriptions[keys[i]]);
        }
        return vals;
     }
  });
  
  
  Object.defineProperty(Session.prototype, "registrations", {
     get: function () {
        var keys = Object.keys(this._registrations);
        var vals = [];
        for (var i = 0; i < keys.length; ++i) {
           vals.push(this._registrations[keys[i]]);
        }
        return vals;
     }
  });
  
  
  Session.prototype.log = function () {
     var self = this;
  
     if ('console' in global) {
  
        var header = null;
        if (self._id && self._created) {
  
           var now = null;
           if ('performance' in global && 'now' in performance) {
              now = performance.now() - self._created;
           } else {
              now = Date.now() - self._created;
           }
  
           header = "WAMP session " + self._id + " on '" + self._realm + "' at " + Math.round(now * 1000) / 1000 + " ms";
        } else {
           header = "WAMP session";
        }
  
        if ('group' in console) {
           console.group(header);
           for (var i = 0; i < arguments.length; i += 1) {
              console.log(arguments[i]);
           }
           console.groupEnd();
        } else {
           var items = [header + ": "];
           for (var i = 0; i < arguments.length; i += 1) {
              items.push(arguments[i]);
           }
           console.log.apply(console, items);
        }
     }
  };
  
  
  Session.prototype.join = function (realm, authmethods, authid, authextra) {
  
     util.assert(typeof realm === 'string', "Session.join: <realm> must be a string");
     util.assert(!authmethods || Array.isArray(authmethods), "Session.join: <authmethods> must be an array []");
     util.assert(!authid || typeof authid === 'string', "Session.join: <authid> must be a string");
  
     var self = this;
  
     if (self.isOpen) {
        throw "session already open";
     }
  
     self._goodbye_sent = false;
     self._realm = realm;
  
     var details = {};
     details.roles = WAMP_FEATURES;
  
     if (authmethods) {
        details.authmethods = authmethods;
     }
     if (authid) {
        details.authid = authid;
     }
     if (authextra) {
        details.authextra = authextra;
     }
  
     var msg = [MSG_TYPE.HELLO, realm, details];
     self._send_wamp(msg);
  };
  
  
  Session.prototype.leave = function (reason, message) {
  
     util.assert(!reason || typeof reason === 'string', "Session.leave: <reason> must be a string");
     util.assert(!message || typeof message === 'string', "Session.leave: <message> must be a string");
  
     var self = this;
  
     if (!self.isOpen) {
        throw "session not open";
     }
  
     if (!reason) {
        reason = "wamp.close.normal";
     }
  
     var details = {};
     if (message) {
        details.message = message;
     }
  
     var msg = [MSG_TYPE.GOODBYE, details, reason];
     self._send_wamp(msg);
     self._goodbye_sent = true;
  };
  
  
  Session.prototype.call = function (procedure, args, kwargs, options) {
  
     util.assert(typeof procedure === 'string', "Session.call: <procedure> must be a string");
     util.assert(!args || Array.isArray(args), "Session.call: <args> must be an array []");
     util.assert(!kwargs || kwargs instanceof Object, "Session.call: <kwargs> must be an object {}");
     util.assert(!options || options instanceof Object, "Session.call: <options> must be an object {}");
  
     var self = this;
  
     if (!self.isOpen) {
        throw "session not open";
     }
  
     options = options || {};
  
     // only set option if user hasn't set a value and global option is "on"
     if (options.disclose_me === undefined && self._caller_disclose_me) {
        options.disclose_me = true;
     }
  
     // create and remember new CALL request
     //
     var d = self._defer();
     var request = self._socket.serializer.newid();
     self._call_reqs[request] = [d, options];
  
     // construct CALL message
     //
     var msg = [MSG_TYPE.CALL, request, options, self.resolve(procedure)];
     if (args) {
        msg.push(args);
        if (kwargs) {
           msg.push(kwargs);
        }
     } else if (kwargs) {
        msg.push([]);
        msg.push(kwargs);
     }
  
     // send WAMP message
     //
     self._send_wamp(msg);
  
     if (d.promise.then) {
        // whenjs has the actual user promise in an attribute
        return d.promise;
     } else {
        return d;
     }
  };
  
  
  Session.prototype.publish = function (topic, args, kwargs, options) {
  
     util.assert(typeof topic === 'string', "Session.publish: <topic> must be a string");
     util.assert(!args || Array.isArray(args), "Session.publish: <args> must be an array []");
     util.assert(!kwargs || kwargs instanceof Object, "Session.publish: <kwargs> must be an object {}");
     util.assert(!options || options instanceof Object, "Session.publish: <options> must be an object {}");
  
     var self = this;
  
     if (!self.isOpen) {
        throw "session not open";
     }
  
     options = options || {};
  
     // only set option if user hasn't set a value and global option is "on"
     if (options.disclose_me === undefined && self._publisher_disclose_me) {
        options.disclose_me = true;
     }
  
     // create and remember new PUBLISH request
     //
     var d = null;
     var request = self._socket.serializer.newid();
     if (options.acknowledge) {
        d = self._defer();
        self._publish_reqs[request] = [d, options];
     }
  
     // construct PUBLISH message
     //
     var msg = [MSG_TYPE.PUBLISH, request, options, self.resolve(topic)];
     if (args) {
        msg.push(args);
        if (kwargs) {
           msg.push(kwargs);
        }
     } else if (kwargs) {
        msg.push([]);
        msg.push(kwargs);
     }
  
     // send WAMP message
     //
     self._send_wamp(msg);
  
     if (d) {
        if (d.promise.then) {
           // whenjs has the actual user promise in an attribute
           return d.promise;
        } else {
           return d;
        }
     }
  };
  
  
  Session.prototype.subscribe = function (topic, handler, options) {
  
     util.assert(typeof topic === 'string', "Session.subscribe: <topic> must be a string");
     util.assert(typeof handler === 'function', "Session.subscribe: <handler> must be a function");
     util.assert(!options || options instanceof Object, "Session.subscribe: <options> must be an object {}");
  
     var self = this;
  
     if (!self.isOpen) {
        throw "session not open";
     }
  
     // create an remember new SUBSCRIBE request
     //
     var request = self._socket.serializer.newid();
     var d = self._defer();
     self._subscribe_reqs[request] = [d, topic, handler, options];
  
     // construct SUBSCRIBE message
     //
     var msg = [MSG_TYPE.SUBSCRIBE, request];
     if (options) {
        msg.push(options);
     } else {
        msg.push({});
     }
     msg.push(self.resolve(topic));
  
     // send WAMP message
     //
     self._send_wamp(msg);
  
     if (d.promise.then) {
        // whenjs has the actual user promise in an attribute
        return d.promise;
     } else {
        return d;
     }
  };
  
  
  Session.prototype.register = function (procedure, endpoint, options) {
  
     util.assert(typeof procedure === 'string', "Session.register: <procedure> must be a string");
     util.assert(typeof endpoint === 'function', "Session.register: <endpoint> must be a function");
     util.assert(!options || options instanceof Object, "Session.register: <options> must be an object {}");
  
     var self = this;
  
     if (!self.isOpen) {
        throw "session not open";
     }
  
     // create an remember new REGISTER request
     //
     var request = self._socket.serializer.newid();
     var d = self._defer();
     self._register_reqs[request] = [d, procedure, endpoint, options];
  
     // construct REGISTER message
     //
     var msg = [MSG_TYPE.REGISTER, request];
     if (options) {
        msg.push(options);
     } else {
        msg.push({});
     }
     msg.push(self.resolve(procedure));
  
     // send WAMP message
     //
     self._send_wamp(msg);
  
     if (d.promise.then) {
        // whenjs has the actual user promise in an attribute
        return d.promise;
     } else {
        return d;
     }
  };
  
  
  Session.prototype.unsubscribe = function (subscription) {
  
     util.assert(subscription instanceof Subscription, "Session.unsubscribe: <subscription> must be an instance of class autobahn.Subscription");
  
     var self = this;
  
     if (!self.isOpen) {
        throw "session not open";
     }
  
     if (!subscription.active || !(subscription.id in self._subscriptions)) {
        throw "subscription not active";
     }
  
     var subs = self._subscriptions[subscription.id];
     var i = subs.indexOf(subscription);
  
     if (i === -1) {
        throw "subscription not active";
     }
  
     // remove handler subscription
     subs.splice(i, 1);
     subscription.active = false;
  
     var d = self._defer();
  
     if (subs.length) {
        // there are still handlers on the subscription ..
        d.resolve(false);
  
     } else {
  
        // no handlers left ..
  
        // create and remember new UNSUBSCRIBE request
        //
        var request = self._socket.serializer.newid();
        self._unsubscribe_reqs[request] = [d, subscription.id];
  
        // construct UNSUBSCRIBE message
        //
        var msg = [MSG_TYPE.UNSUBSCRIBE, request, subscription.id];
  
        // send WAMP message
        //
        self._send_wamp(msg);
     }
  
     if (d.promise.then) {
        // whenjs has the actual user promise in an attribute
        return d.promise;
     } else {
        return d;
     }
  };
  
  
  Session.prototype.unregister = function (registration) {
  
     util.assert(registration instanceof Registration, "Session.unregister: <registration> must be an instance of class autobahn.Registration");
  
     var self = this;
  
     if (!self.isOpen) {
        throw "session not open";
     }
  
     if (!registration.active || !(registration.id in self._registrations)) {
        throw "registration not active";
     }
  
     // create and remember new UNREGISTER request
     //
     var request = self._socket.serializer.newid();
     var d = self._defer();
     self._unregister_reqs[request] = [d, registration];
  
     // construct UNREGISTER message
     //
     var msg = [MSG_TYPE.UNREGISTER, request, registration.id];
  
     // send WAMP message
     //
     self._send_wamp(msg);
  
     if (d.promise.then) {
        // whenjs has the actual user promise in an attribute
        return d.promise;
     } else {
        return d;
     }
  };
  
  
  Session.prototype.prefix = function (prefix, uri) {
  
     util.assert(typeof prefix === 'string', "Session.prefix: <prefix> must be a string");
     util.assert(!uri || typeof uri === 'string', "Session.prefix: <uri> must be a string or falsy");
  
     var self = this;
  
     if (uri) {
        self._prefixes[prefix] = uri;
     } else {
        if (prefix in self._prefixes) {
           delete self._prefixes[prefix];
        }
     }
  };
  
  
  Session.prototype.resolve = function (curie) {
  
     util.assert(typeof curie === 'string', "Session.resolve: <curie> must be a string");
  
     var self = this;
  
     // skip if not a CURIE
     var i = curie.indexOf(":");
     if (i >= 0) {
        var prefix = curie.substring(0, i);
        if (prefix in self._prefixes) {
           return self._prefixes[prefix] + '.' + curie.substring(i + 1);
        } else {
           return curie;
        }
     } else {
        return curie;
     }
  };
  
  
  exports.Session = Session;
  
  exports.Invocation = Invocation;
  exports.Event = Event;
  exports.Result = Result;
  exports.Error = Error;
  exports.Subscription = Subscription;
  exports.Registration = Registration;
  exports.Publication = Publication;
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"./log.js":6,"./util.js":20,"when":123,"when/function":99}],17:[function(require,module,exports){
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  AutobahnJS - http://autobahn.ws, http://wamp.ws
  //
  //  A JavaScript library for WAMP ("The Web Application Messaging Protocol").
  //
  //  Copyright (c) Crossbar.io Technologies GmbH and contributors
  //
  //  Licensed under the MIT License.
  //  http://www.opensource.org/licenses/mit-license.php
  //
  ///////////////////////////////////////////////////////////////////////////////
  
  
  var when = require('when');
  var util = require('../util.js');
  var log = require('../log.js');
  var serializer = require('../serializer.js');
  
  
  function Factory (options) {
     var self = this;
  
     util.assert(options.url !== undefined, "options.url missing");
     util.assert(typeof options.url === "string", "options.url must be a string");
  
     self._options = options;
  };
  
  
  Factory.prototype.type = "longpoll";
  
  
  Factory.prototype.create = function () {
  
     var self = this;
  
     log.debug("longpoll.Factory.create");
  
     // the WAMP transport we create
     var transport = {};
  
     // these will get defined further below
     transport.protocol = undefined;
     transport.serializer = new serializer.JSONSerializer();
     transport.send = undefined;
     transport.close = undefined;
  
     // these will get overridden by the WAMP session using this transport
     transport.onmessage = function () {};
     transport.onopen = function () {};
     transport.onclose = function () {};
  
     transport.info = {
        type: 'longpoll',
        url: null,
        protocol: 'wamp.2.json'
     };
  
     transport._run = function () {
  
        var session_info = null;
        var send_buffer = [];
        var is_closing = false;
  
        var txseq = 0;
        var rxseq = 0;
  
        var options = {'protocols': ['wamp.2.json']};
        var request_timeout = self._options.request_timeout || 12000; // timeout here > than the 10s default in Crossbar.io
  
        util.http_post(self._options.url + '/open', JSON.stringify(options), request_timeout).then(
  
           function (payload) {
  
              session_info = JSON.parse(payload);
              var base_url = self._options.url + '/' + session_info.transport;
  
              transport.info.url = base_url;
  
              log.debug("longpoll.Transport: open", session_info);
  
              transport.close = function (code, reason) {
  
                 if (is_closing) {
                    throw "transport is already closing";
                 }
  
                 is_closing = true;
  
                 util.http_post(base_url + '/close', null, request_timeout).then(
  
                    function () {
                       log.debug("longpoll.Transport: transport closed");
                       var details = {
                          code: 1000,
                          reason: "transport closed",
                          wasClean: true
                       }
                       transport.onclose(details);
                    },
  
                    function (err) {
                       log.debug("longpoll.Transport: could not close transport", err.code, err.text);
                    }
                 );
              }
  
              transport.send = function (msg) {
  
                 if (is_closing) {
                    throw "transport is closing or closed already";
                 }
  
                 txseq += 1;
  
                 log.debug("longpoll.Transport: sending message ...", msg);
  
                 var payload = JSON.stringify(msg);
  
                 util.http_post(base_url + '/send', payload, request_timeout).then(
  
                    function () {
                       // ok, message sent
                       log.debug("longpoll.Transport: message sent");
                    },
  
                    function (err) {
                       log.debug("longpoll.Transport: could not send message", err.code, err.text);
  
                       is_closing = true;
                       var details = {
                          code: 1001,
                          reason: "transport send failure (HTTP/POST status " + err.code + " - '" + err.text + "')",
                          wasClean: false
                       }
                       transport.onclose(details);
                    }
                 );
              };
  
              function receive() {
  
                 rxseq += 1;
  
                 log.debug("longpoll.Transport: polling for message ...");
  
                 util.http_post(base_url + '/receive', null, request_timeout).then(
  
                    function (payload) {
  
                       if (payload) {
  
                          var msg = JSON.parse(payload);
  
                          log.debug("longpoll.Transport: message received", msg);
  
                          transport.onmessage(msg);
                       }
  
                       if (!is_closing) {
                          receive();
                       }
                    },
  
                    function (err) {
                       log.debug("longpoll.Transport: could not receive message", err.code, err.text);
  
                       is_closing = true;
                       var details = {
                          code: 1001,
                          reason: "transport receive failure (HTTP/POST status " + err.code + " - '" + err.text + "')",
                          wasClean: false
                       }
                       transport.onclose(details);
                    }
                 );
              }
  
              receive();
  
              transport.onopen();
           },
  
           function (err) {
              log.debug("longpoll.Transport: could not open transport", err.code, err.text);
  
              is_closing = true;
              var details = {
                 code: 1001,
                 reason: "transport open failure (HTTP/POST status " + err.code + " - '" + err.text + "')",
                 wasClean: false
              }
              transport.onclose(details);
           }
        );
     }
  
     transport._run();
  
     return transport;
  };
  
  
  exports.Factory = Factory;
  
  },{"../log.js":6,"../serializer.js":15,"../util.js":20,"when":123}],18:[function(require,module,exports){
  (function (global,Buffer){
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  AutobahnJS - http://autobahn.ws, http://wamp.ws
  //
  //  A JavaScript library for WAMP ("The Web Application Messaging Protocol").
  //
  //  Copyright (c) Crossbar.io Technologies GmbH and contributors
  //
  //  Licensed under the MIT License.
  //  http://www.opensource.org/licenses/mit-license.php
  //
  ///////////////////////////////////////////////////////////////////////////////
  
  
  var util = require('../util.js');
  var log = require('../log.js');
  var serializer = require('../serializer.js');
  
  var EventEmitter = require('events').EventEmitter;
  
  
  function Factory (options) {
     var self = this;
  
     if (!options.protocols) {
        options.protocols = ['wamp.2.json'];
     } else {
        util.assert(Array.isArray(options.protocols), "options.protocols must be an array");
     }
  
     options.rawsocket_max_len_exp = options.rawsocket_max_len_exp || 24;
  
     self._options = options;
  }
  
  
  Factory.prototype.type = "rawsocket";
  
  
  Factory.prototype.create = function () {
  
     var self = this;
  
     // the WAMP transport we create
     var transport = {};
  
     // these will get defined further below
     transport.protocol = undefined;
     transport.serializer = new serializer.JSONSerializer();
     transport.send = undefined;
     transport.close = undefined;
  
     // these will get overridden by the WAMP session using this transport
     transport.onmessage = function () {};
     transport.onopen = function () {};
     transport.onclose = function () {};
  
     transport.info = {
        type: 'rawsocket',
        url: null,
        protocol: 'wamp.2.json'
     };
  
  
     // Test below used to be via the 'window' object in the browser.
     // This fails when running in a Web worker.
     //
     // running in Node.js
     //
     if (global.process && global.process.versions.node) {
  
        (function () {
           var net = require('net');
           var socket, protocol;
  
           // Create the options object to initiate the connection
           if (self._options.path) {
              connectionOptions = {
                 path: self._options.path,
                 allowHalfOpen: true
              };
           } else if (self._options.port) {
              connectionOptions = {
                 port: self._options.port || 8000,
                 host: self._options.host || 'localhost',
                 allowHalfOpen: true
              };
           } else {
              throw "You must specify a host/port combination or a unix socket path to connect to";
           }
  
           // Open a TCP socket and setup the protocol
           socket = net.connect(connectionOptions);
           protocol = new Protocol(socket, {
              serializer: 'json',
              max_len_exp: self._options.rawsocket_max_len_exp
           });
  
           // Relay connect event to the onopen transport handler
           protocol.on('connect', function (msg) {
              log.debug('RawSocket transport negociated');
              transport.onopen(msg);
           });
  
           // Relay data event to the onmessage transport handler
           protocol.on('data', function (msg) {
              log.debug('RawSocket transport received', msg);
              transport.onmessage(msg);
           });
  
           // Relay the close event to the onclose transport handler
           protocol.on('close', function (had_error) {
              log.debug('RawSocket transport closed');
              transport.onclose({
                 code: 999,
                 reason: '',
                 wasClean: !had_error
              });
           });
  
           // Log errors
           protocol.on('error', function (error) {
              log.debug('RawSocket transport error', error);
           });
  
           // Relay close call
           transport.close = function (code, reason) {
              log.debug('RawSocket transport closing', code, reason);
              protocol.close();
           };
  
           // Relay send call
           transport.send = function (msg) {
              log.debug('RawSocket transport sending', msg);
              protocol.write(msg);
           };
  
        })();
     //
     // running in the browser
     //
     } else {
        throw "No RawSocket support in browser";
     }
  
     return transport;
  };
  
  /**
   *  Protocol constructor
   *
   * @param {Stream} stream    Source stream object
   * @param {Object} [options] Protocol options
   *
   * @param {String} [options.serializer] The serializer to use (default: json)
   * @param {Integer} [options.max_len_exp] The maximum allowed frame length as
   *        2^x(default: 24)
   * @param {Integer|False} [options.ping_timeout] Maximum duration in ms to wait
   *        for an answer to a PING packet (default: 2000)
   * @param {Integer|False} [options.autoping] If an integer, send a PING packet*
   *        every `x`ms (default: false)
   * @param {Boolean} [options.fail_on_ping_timeout] Whether to close the
   *        underlying connection when the peer fails to answer to a PING within
   *        the `ping_timeout` window (default: true)
   * @param {Integer|False} [options.packet_timeout] The maximum amount of time to
   *        wait for a packet !!NOT IMPLEMENTED!! (default: 2000)
   *
   * @see https://github.com/wamp-proto/wamp-proto
   */
  function Protocol (stream, options) {
     this._options = {
        _peer_serializer: null, // Will hold the serializer declared by the peer
        _peer_max_len_exp: 0    // Will hold the maximum frame length declared by
                                // the peer
     };
  
     this._options = util.defaults(this._options, options, this.DEFAULT_OPTIONS);
  
     // Check valid options
     util.assert(this._options.serializer in this.SERIALIZERS,
        'Unsupported serializer: ' + this._options.serializer);
  
     util.assert(this._options.max_len_exp >= 9 &&
        this._options.max_len_exp <= 36,
        'Message length out of bounds [9, 36]: '+ this._options.max_len_exp);
  
     util.assert(!this._options.autoping ||
        (Number.isInteger(this._options.autoping) && this._options.autoping >= 0),
        'Autoping interval must be positive');
  
     util.assert(!this._options.ping_timeout ||
        (Number.isInteger(this._options.ping_timeout) &&
           this._options.ping_timeout >= 0),
        'Ping timeout duration must be positive');
  
     util.assert(!this._options.packet_timeout ||
        (Number.isInteger(this._options.packet_timeout) &&
           this._options.packet_timeout >= 0),
        'Packet timeout duration must be positive');
  
     util.assert((!this._options.autoping || !this._options.ping_timeout) ||
        this._options.autoping > this._options.ping_timeout,
        'Autoping interval (' + this._options.autoping + ') must be lower ' +
        'than ping timeout (' + this._options.ping_timeout + ')');
  
     // Will store a reference to the timeout function associated with the last
     // PING packet
     this._ping_timeout = null;
  
     // Will store the payload of the last PING packet
     this._ping_payload = null;
  
     // Will store the autoping setInterval reference
     this._ping_interval = null;
  
     // Protocol status (see Protocol.prototype.STATUS)
     this._status = this.STATUS.UNINITIATED;
  
     this._stream = stream;
     this._emitter = new EventEmitter();
  
     // Frame buffer
     this._buffer = new Buffer(4);
     this._bufferLen = 0;
     this._msgLen = 0;
  
     // Hook events
     var self = this;
     this._stream.on('data', function (data) {
        self._read(data);
     });
  
     this._stream.on('connect', function () {
        self._handshake();
     });
  
     // Proxy these events from the stream as we don't need to handle them
     var proxyEvents = [
        'close',
        'drain',
        'end',
        'error',
        'timeout'
     ];
     proxyEvents.forEach(function (evt) {
        self._stream.on(evt, function (data) {
           self._emitter.emit(evt, data);
        });
     });
  }
  
  /* Protocol magic byte */
  Protocol.prototype._MAGIC_BYTE = 0x7f;
  
  /* Supported serializers */
  Protocol.prototype.SERIALIZERS = {
     json: 1
  };
  
  /* Protocol states */
  Protocol.prototype.STATUS = {
     CLOSED:     -1,
     UNINITIATED: 0,
     NEGOCIATING: 1,
     NEGOCIATED:  2,
     RXHEAD:      3,
     RXDATA:      4,
     RXPING:      5,
     RXPONG:      6
  };
  
  /* RawSocket error codes */
  Protocol.prototype.ERRORS = {
     0: "illegal (must not be used)",
     1: "serializer unsupported",
     2: "maximum message length unacceptable",
     3: "use of reserved bits (unsupported feature)",
     4: "maximum connection count reached"
  };
  
  /* RawSocket message types */
  Protocol.prototype.MSGTYPES = {
     WAMP: 0x0,
     PING: 0x1,
     PONG: 0x2
  };
  
  /* Default protocol options */
  Protocol.prototype.DEFAULT_OPTIONS = {
     fail_on_ping_timeout: true,
     strict_pong: true,
     ping_timeout: 2000,
     autoping: 0,
     max_len_exp: 24,
     serializer: 'json',
     packet_timeout: 2000
  };
  
  /**
   * Close transport
   *
   * @returns {Integer} Closed state code
   */
  Protocol.prototype.close = function () {
     this._status = this.STATUS.CLOSED;
     this._stream.end();
  
     return this.STATUS.CLOSED;
  };
  
  /**
   * Write a frame to the transport
   *
   * @param   {Oject}    msg      The frame to send
   * @param   {Integer}  type     The frame type
   * @param   {Function} callback Callback function called when frame is sent
   */
  Protocol.prototype.write = function (msg, type, callback) {
     type = type === undefined ? 0 : type;
  
     // If WAMP frame, serialize the object passed
     // Otherwise send as-is
     if (type === this.MSGTYPES.WAMP) {
        msg = JSON.stringify(msg);
     }
  
     // Get the frame size
     var msgLen = Buffer.byteLength(msg, 'utf8');
  
     // Check frame size against negociated max size
     if (msgLen > Math.pow(2, this._options._peer_max_len_exp)) {
        this._emitter.emit('error', new ProtocolError('Frame too big'));
        return;
     }
  
     // Create the frame
     var frame = new Buffer(msgLen + 4);
  
     // Message type
     frame.writeUInt8(type, 0);
     // Prefix by frame size as a 24 bit integer
     frame.writeUIntBE(msgLen, 1, 3);
     frame.write(msg, 4);
  
     this._stream.write(frame, callback);
  };
  
  Protocol.prototype.ping = function (payload) {
     payload = payload || 255;
  
     // Generate a random payload if none provided
     if (Number.isInteger(payload)) {
        var base = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'+
                   '0123456789&~"#\'{([-|`_\\^@)]=},?;.:/!*$<>';
        var len = Math.max(1, payload);
  
        for (var i = 0; i < len; i++)
           payload += base.charAt((Math.random() * base.length) | 0);
     }
  
     // Store the payload for checking against PONG packet
     this._ping_payload = payload;
  
     // Send the packet and register the ping timeout once done
     return this.write(payload, this.MSGTYPES.PING, this._setupPingTimeout.bind(this));
  };
  
  Protocol.prototype._setupPingTimeout = function () {
     if (this._options.ping_timeout) {
        this._ping_timeout = setTimeout(this._onPingTimeout.bind(this), this._options.ping_timeout);
     }
  };
  
  Protocol.prototype._clearPingTimeout = function () {
     if (this._ping_timeout) {
        clearTimeout(this._ping_timeout);
        this._ping_timeout = null;
     }
  };
  
  Protocol.prototype._setupAutoPing = function () {
     this._clearAutoPing();
  
     if (this._options.autoping) {
        this._autoping_interval = setInterval(this.ping.bind(this), this._options.autoping);
     }
  };
  
  Protocol.prototype._clearAutoPing = function () {
     if (this._autoping_interval) {
        clearInterval(this._autoping_interval);
        this._autoping_interval = null;
     }
  };
  
  Protocol.prototype._onPingTimeout = function () {
     this._emitter.emit('error', new ProtocolError('PING timeout'));
  
     if (this._options.fail_on_ping_timeout) {
        this.close();
     }
  };
  
  /**
   * Handle incoming data
   *
   * @param {Buffer} data Incoming data
   */
  Protocol.prototype._read = function (data) {
     var handler, frame;
  
     switch (this._status) {
        case this.STATUS.CLOSED:
        case this.STATUS.UNINITIATED:
           this._emitter.emit('error', ProtocolError('Unexpected packet'));
           break;
  
        case this.STATUS.NEGOCIATING:
           handler = this._handleHandshake;
           frame = 4;
           break;
  
        case this.STATUS.NEGOCIATED:
        case this.STATUS.RXHEAD:
           this._status = this.STATUS.RXHEAD;
  
           handler = this._handleHeaderPacket;
           frame = 4;
           break;
  
        case this.STATUS.RXDATA:
           handler = this._handleDataPacket;
           frame = this._msgLen;
           break;
  
        case this.STATUS.RXPING:
           handler = this._handlePingPacket;
           frame = this._msgLen;
           break;
  
        case this.STATUS.RXPONG:
           handler = this._handlePongPacket;
           frame = this._msgLen;
           break;
     }
  
     // Get a frame of the expected size
     var chunks = this._splitBytes(data, frame);
  
     // Protocol#_splitBytes returns null if there isn't enough data to fill the
     // requested frame yet. Wait for more
     if (!chunks) return;
  
     // Call the packet handler with the frame
     this._status = handler.call(this, chunks[0]);
  
     // If there is more data, handle it
     if (chunks[1].length > 0) {
        this._read(chunks[1]);
     }
  };
  
  /**
   * Send the handshake packet to the peer
   */
  Protocol.prototype._handshake = function () {
     if (this._status !== this.STATUS.UNINITIATED) {
        throw 'Handshake packet already sent';
     }
  
     // Compose handshake message
     var gday = new Buffer(4);
  
     // Protocol magic byte
     gday.writeUInt8(this._MAGIC_BYTE, 0);
     // Announce message max length and serializer
     gday.writeUInt8((this._options.max_len_exp - 9) << 4 | this.SERIALIZERS[this._options.serializer], 1);
     // Reserved bytes
     gday.writeUInt8(0x00, 2);
     gday.writeUInt8(0x00, 3);
  
     this._stream.write(gday);
  
     this._status = this.STATUS.NEGOCIATING;
  };
  
  /**
   * Make a frame of the requested length using the data already buffered and the
   * passed incoming data
   *
   * @param   {Buffer}  data Incoming data
   * @param   {Integer} len  Frame size
   *
   * @returns {null|Array(2)} Returns null if there is'nt enough data to fill the
   *                          frame yet, or an array containing the frame at
   *                          index 0 and the leftover bytes at index 1 otherwise.
   */
  Protocol.prototype._splitBytes = function (data, len) {
     // If the buffer we have already isn't the right size, throw the data away
     // and make a new one
     if (len !== this._buffer.length) {
        this._buffer = new Buffer(len);
        this._bufferLen = 0;
     }
  
     // Push the data to the buffer
     data.copy(this._buffer, this._bufferLen);
  
     // If there still isn't enough data, increment the counter and return null
     if (this._bufferLen + data.length < len) {
        this._bufferLen += data.length;
        return null;
     // Otherwise, return the requested frame and the leftover data
     } else {
        var bytes = this._buffer.slice();
        var extra = data.slice(len - this._bufferLen);
  
        this._bufferLen = 0;
  
        return [ bytes, extra ];
     }
  };
  
  /**
   * Handle the handshake response packet
   *
   * @param   {Buffer} int32 A 4 byte buffer containing the handshake packet
   *
   * @returns {Integer} The new protocol state
   */
  Protocol.prototype._handleHandshake = function (int32) {
     // Check magic byte
     if (int32[0] !== this._MAGIC_BYTE) {
        this._emitter.emit('error',  new ProtocolError(
           'Invalid magic byte. Expected 0x' +
           this._MAGIC_BYTE.toString(16) + ', got 0x' +
           int32[0].toString(16))
        );
        return this.close();
     }
  
     // Check for error
     if ((int32[1] & 0x0f) === 0) {
        var errcode = int32[1] >> 4;
        this._emitter.emit('error',  new ProtocolError('Peer failed handshake: ' +
           (this.ERRORS[errcode] || '0x' + errcode.toString(16))));
        return this.close();
     }
  
     // Extract max message length and serializer
     this._options._peer_max_len_exp = (int32[1] >> 4) + 9;
     this._options._peer_serializer = int32[1] & 0x0f;
  
     // We only support JSON so far
     // TODO: Support more serializers
     if (this._options._peer_serializer !== this.SERIALIZERS.json) {
        this._emitter.emit('error', new ProtocolError(
           'Unsupported serializer: 0x' +
           this._options._peer_serializer.toString(16))
        );
        return this.close();
     }
  
     // Protocol negociation complete, we're connected to the peer and ready to
     // talk
     this._emitter.emit('connect');
  
     // Setup the autoping
     this._setupAutoPing();
  
     return this.STATUS.NEGOCIATED;
  };
  
  /**
   * Handle a frame header
   *
   * @param   {Buffer} int32 A 4 byte buffer representing the packet length
   *
   * @returns {Integer} The new protocol state
   */
  Protocol.prototype._handleHeaderPacket = function (int32) {
     var type = int32[0] & 0x0f;
  
     // Decode integer and store it
     this._msgLen = int32.readUIntBE(1, 3);
  
     switch (type) {
        case this.MSGTYPES.WAMP: // WAMP frame
           return this.STATUS.RXDATA;
  
        case this.MSGTYPES.PING: // PING frame
           return this.STATUS.RXPING;
  
        case this.MSGTYPES.PONG: // PONG frame
           return this.STATUS.RXPONG;
  
        default:
           this._emitter.emit('error', new ProtocolError(
              'Invalid frame type: 0x' + type.toString(16))
           );
           return this.close();
     }
  };
  
  /**
   * Handle a data packet
   *
   * @param   {Buffer} buffer The received data
   *
   * @returns {Integer} The new protocol state
   */
  Protocol.prototype._handleDataPacket = function (buffer) {
     var msg;
     // Attempt to deserialize the frame
     // TODO: Support other serializers
     try {
        msg = JSON.parse(buffer.toString('utf8'));
     } catch (e) {
        this._emitter.emit('error',
           new ProtocolError('Invalid JSON frame')
        );
        return this.STATUS.RXHEAD;
     }
  
     // Emit a data event for consumers
     this._emitter.emit('data', msg);
  
     return this.STATUS.RXHEAD;
  };
  
  /**
   * Handle a ping packet - Reply with a  PONG and the same payload
   *
   * @param   {Buffer} buffer The received data
   *
   * @returns {Integer} The new protocol state
   */
  Protocol.prototype._handlePingPacket = function (buffer) {
     this.write(buffer.toString('utf8'), this.MSGTYPES.PONG);
     return this.STATUS.RXHEAD;
  };
  
  /**
   * Handle a pong packet
   *
   * @param   {Buffer} buffer The received data
   *
   * @returns {Integer} The new protocol state
   */
  Protocol.prototype._handlePongPacket = function (buffer) {
     // Clear the ping timeout (if any)
     this._clearPingTimeout();
  
     // If strict PONG checking is activated and the payloads don't match, throw
     // an error and close the connection
     if (this._options.strict_pong
        && this._ping_payload !== buffer.toString('utf8')) {
        this._emitter.emit('error', new ProtocolError(
           'PONG response payload doesn\'t match PING.'
        ));
  
        return this.close();
     }
  
     return this.STATUS.RXHEAD;
  };
  
  Protocol.prototype.on = function (evt, handler) {
     return this._emitter.on(evt, handler);
  };
  
  Protocol.prototype.once = function (evt, handler) {
     return this._emitter.once(evt, handler);
  };
  
  Protocol.prototype.removeListener = function (evt, handler) {
     return this._emitter.removeListener(evt, handler);
  };
  
  
  /**
   * ProtocolError type
   */
  var ProtocolError = exports.ProtocolError = function (msg) {
     Error.apply(this, Array.prototype.splice.call(arguments));
  
     Error.captureStackTrace(this, this.constructor);
  
     this.message = msg;
     this.name = 'ProtocolError';
  };
  ProtocolError.prototype = Object.create(Error.prototype);
  
  
  exports.Factory = Factory;
  exports.Protocol = Protocol;
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
  },{"../log.js":6,"../serializer.js":15,"../util.js":20,"buffer":129,"events":131,"net":125}],19:[function(require,module,exports){
  (function (global){
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  AutobahnJS - http://autobahn.ws, http://wamp.ws
  //
  //  A JavaScript library for WAMP ("The Web Application Messaging Protocol").
  //
  //  Copyright (c) Crossbar.io Technologies GmbH and contributors
  //
  //  Licensed under the MIT License.
  //  http://www.opensource.org/licenses/mit-license.php
  //
  ///////////////////////////////////////////////////////////////////////////////
  
  
  var util = require('../util.js');
  var log = require('../log.js');
  var serializer = require('../serializer.js');
  
  
  function Factory (options) {
     var self = this;
  
     util.assert(options.url !== undefined, "options.url missing");
     util.assert(typeof options.url === "string", "options.url must be a string");
  
     if (!options.serializers) {
        options.serializers = [new serializer.JSONSerializer()];
        if (serializer.MsgpackSerializer) {
           options.serializers.push(new serializer.MsgpackSerializer());
        }
     } else {
        util.assert(Array.isArray(options.serializers), "options.serializers must be an array");
     }
  
     if (!options.protocols) {
        options.protocols = [];
        options.serializers.forEach(function (ser) {
           options.protocols.push("wamp.2." + ser.SERIALIZER_ID);
        });
     } else {
        util.assert(Array.isArray(options.protocols), "options.protocols must be an array");
     }
  
     self._options = options;
  }
  
  
  Factory.prototype.type = "websocket";
  
  
  Factory.prototype.create = function () {
  
     var self = this;
  
     // the WAMP transport we create
     var transport = {};
  
     // these will get defined further below
     transport.protocol = undefined;
     transport.serializer = undefined;
     transport.send = undefined;
     transport.close = undefined;
  
     // these will get overridden by the WAMP session using this transport
     transport.onmessage = function () {};
     transport.onopen = function () {};
     transport.onclose = function () {};
  
     transport.info = {
        type: 'websocket',
        url: self._options.url,
        protocol: null
     };
  
  
     // Test below used to be via the 'window' object in the browser.
     // This fails when running in a Web worker.
     //
     // running in Node.js
     //
     if (global.process && global.process.versions.node) {
  
        (function () {
  
           var WebSocket = require('ws'); // https://github.com/einaros/ws
           var websocket;
  
           var protocols;
           if (self._options.protocols) {
              protocols = self._options.protocols;
              if (Array.isArray(protocols)) {
                 protocols = protocols.join(',');
              }
              websocket = new WebSocket(self._options.url, {protocol: protocols});
           } else {
              websocket = new WebSocket(self._options.url);
           }
  
           transport.send = function (msg) {
              var payload = transport.serializer.serialize(msg);
              websocket.send(payload, {binary: transport.serializer.BINARY});
           };
  
           transport.close = function (code, reason) {
              websocket.close();
           };
  
           websocket.on('open', function () {
              var serializer_part = websocket.protocol.split('.')[2];
              for (var index in self._options.serializers) {
                 var serializer = self._options.serializers[index];
                 if (serializer.SERIALIZER_ID == serializer_part) {
                    transport.serializer = serializer;
                    break;
                 }
              }
  
              transport.info.protocol = websocket.protocol;
              transport.onopen();
           });
  
           websocket.on('message', function (data, flags) {
              var msg = transport.serializer.unserialize(data);
              transport.onmessage(msg);
           });
  
           // FIXME: improve mapping to WS API for the following
           // https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Close_codes
           //
           websocket.on('close', function (code, message) {
              var details = {
                 code: code,
                 reason: message,
                 wasClean: code === 1000
              }
              transport.onclose(details);
           });
  
           websocket.on('error', function (error) {
              var details = {
                 code: 1006,
                 reason: '',
                 wasClean: false
              }
              transport.onclose(details);
           });
  
        })();
     //
     // running in the browser
     //
     } else {
  
        (function () {
  
           var websocket;
  
           // Chrome, MSIE, newer Firefox
           if ("WebSocket" in global) {
  
              if (self._options.protocols) {
                 websocket = new global.WebSocket(self._options.url, self._options.protocols);
              } else {
                 websocket = new global.WebSocket(self._options.url);
              }
              websocket.binaryType = 'arraybuffer';
  
           // older versions of Firefox prefix the WebSocket object
           } else if ("MozWebSocket" in global) {
  
              if (self._options.protocols) {
                 websocket = new global.MozWebSocket(self._options.url, self._options.protocols);
              } else {
                 websocket = new global.MozWebSocket(self._options.url);
              }
           } else {
              throw "browser does not support WebSocket or WebSocket in Web workers";
           }
  
           websocket.onmessage = function (evt) {
              log.debug("WebSocket transport receive", evt.data);
  
              var msg = transport.serializer.unserialize(evt.data);
              transport.onmessage(msg);
           }
  
           websocket.onopen = function () {
              var serializer_part = websocket.protocol.split('.')[2];
              for (var index in self._options.serializers) {
                 var serializer = self._options.serializers[index];
                 if (serializer.SERIALIZER_ID == serializer_part) {
                    transport.serializer = serializer;
                    break;
                 }
              }
  
              transport.info.protocol = websocket.protocol;
              transport.onopen();
           }
  
           websocket.onclose = function (evt) {
              var details = {
                 code: evt.code,
                 reason: evt.message,
                 wasClean: evt.wasClean
              }
              transport.onclose(details);
           }
  
           // do NOT do the following, since that will make
           // transport.onclose() fire twice (browsers already fire
           // websocket.onclose() for errors also)
           //websocket.onerror = websocket.onclose;
  
           transport.send = function (msg) {
              var payload = transport.serializer.serialize(msg);
              log.debug("WebSocket transport send", payload);
              websocket.send(payload);
           }
  
           transport.close = function (code, reason) {
              websocket.close(code, reason);
           };
  
        })();
     }
  
     return transport;
  };
  
  
  exports.Factory = Factory;
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"../log.js":6,"../serializer.js":15,"../util.js":20,"ws":127}],20:[function(require,module,exports){
  (function (global){
  ///////////////////////////////////////////////////////////////////////////////
  //
  //  AutobahnJS - http://autobahn.ws, http://wamp.ws
  //
  //  A JavaScript library for WAMP ("The Web Application Messaging Protocol").
  //
  //  Copyright (c) Crossbar.io Technologies GmbH and contributors
  //
  //  Licensed under the MIT License.
  //  http://www.opensource.org/licenses/mit-license.php
  //
  ///////////////////////////////////////////////////////////////////////////////
  
  var log = require('./log.js');
  
  var when = require('when');
  
  
  
  var rand_normal = function (mean, sd) {
     // Derive a Gaussian from Uniform random variables
     // http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
     var x1, x2, rad;
  
     do {
        x1 = 2 * Math.random() - 1;
        x2 = 2 * Math.random() - 1;
        rad = x1 * x1 + x2 * x2;
     } while (rad >= 1 || rad == 0);
  
     var c = Math.sqrt(-2 * Math.log(rad) / rad);
  
     return (mean || 0) + (x1 * c) * (sd || 1);
  };
  
  
  
  var assert = function (cond, text) {
  	if (cond) {
        return;
     }
  	if (assert.useDebugger || ('AUTOBAHN_DEBUG' in global && AUTOBAHN_DEBUG)) {
        debugger;
     }
  
  	throw new Error(text || "Assertion failed!");
  };
  
  
  
  // Helper to do HTTP/POST requests returning deferreds. This function is
  // supposed to work on IE8, IE9 and old Android WebKit browsers. We don't care
  // if it works with other browsers.
  //
  var http_post = function (url, data, timeout) {
  
     log.debug("new http_post request", url, data, timeout);
  
     var d = when.defer();
     var req = new XMLHttpRequest();
     req.withCredentials = true; // pass along cookies
     req.onreadystatechange = function () {
  
        if (req.readyState === 4) {
  
           // Normalize IE's response to HTTP 204 when Win error 1223.
           // http://stackoverflow.com/a/10047236/884770
           //
           var status = (req.status === 1223) ? 204 : req.status;
  
           if (status === 200) {
  
              // response with content
              //
              d.resolve(req.responseText);
  
           } if (status === 204) {
  
              // empty response
              //
              d.resolve();
  
           } else {
  
              // anything else is a fail
              //
              var statusText = null;
              try {
                 statusText = req.statusText;
              } catch (e) {
                 // IE8 fucks up on this
              }
              d.reject({code: status, text: statusText});
           }
        }
     }
  
     req.open("POST", url, true);
     req.setRequestHeader("Content-type", "application/json; charset=utf-8");
  
     if (timeout > 0) {
        req.timeout = timeout; // request timeout in ms
  
        req.ontimeout = function () {
           d.reject({code: 501, text: "request timeout"});
        }
     }
  
     if (data) {
        req.send(data);
     } else {
        req.send();
     }
  
     if (d.promise.then) {
        // whenjs has the actual user promise in an attribute
        return d.promise;
     } else {
        return d;
     }
  };
  
  /**
   * Merge a list of objects from left to right
   *
   * For each object passed to the function, add to the previous object the keys
   *     that are present in the former but not the latter. If the last argument
   *     is a boolean, it sets whether or not to recursively merge objects.
   *
   * This function mutates the first passed object. To avopid this, you can pass
   *     a new empty object as the first arg:
   *
   *     defaults({}, obj1, obj2, ...)
   *
   * @example
   *     defaults({ a: 1 }, { a: 2, b: 2 }, { b: 3, c: 3 })
   *     // { a: 1, b: 2, c: 3 }
   *
   *     defaults({ a: { k1: 1 } }, { a: { k2: 2 } })
   *     // { a: { k1: 1 } }
   *
   *     defaults({ a: { k1: 1 } }, { a: { k2: 2 } })
   *     // { a: { k1: 1 } }
   *
   * @param {Object} base The object to merge defaults to
   * @param {Object} source[, ...] The default values source
   * @param {Boolean} [recursive] Whether to recurse fro object values*
   *     (default: false)
   * @returns {Object} The mutated `base` object
   */
  var defaults = function () {
     // Return an empty object if no arguments are passed
     if (arguments.length === 0) return {};
  
     var base = arguments[0];
     var recursive = false;
     var len = arguments.length;
  
     // Check for recursive mode param
     if (typeof arguments[len - 1] === 'boolean') {
        recursive = arguments[len - 1];
        len -= 1; // Ignore the last arg
     }
  
     // Merging function used by Array#forEach()
     var do_merge = function (key) {
        var val = obj[key];
  
        // Set if unset
        if (!(key in base)) {
           base[key] = val;
        // If the value is an object and we use recursive mode, use defaults on
        // the value
        } else if (recursive && typeof val === 'object' &&
                   typeof base[key] === 'object') {
           defaults(base[key], val);
        }
        // Otherwise ignore the value
     };
  
     // Iterate over source objects
     for (var i=1; i < len; i++) {
        var obj = arguments[i];
  
        // Ignore falsy values
        if (!obj) continue;
  
        // Require object
        if (typeof obj !== 'object') {
           throw new Error('Expected argument at index ' + i +
                           ' to be an object');
        }
  
        // Merge keys
        Object.keys(obj).forEach(do_merge);
     }
  
     // Return the mutated base object
     return base;
  };
  
  
  
  exports.rand_normal = rand_normal;
  exports.assert = assert;
  exports.http_post = http_post;
  exports.defaults = defaults;
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"./log.js":6,"when":123}],21:[function(require,module,exports){
  /*! bignumber.js v3.0.1 https://github.com/MikeMcl/bignumber.js/LICENCE */
  
  ;(function (globalObj) {
      'use strict';
  
      /*
        bignumber.js v3.0.1
        A JavaScript library for arbitrary-precision arithmetic.
        https://github.com/MikeMcl/bignumber.js
        Copyright (c) 2016 Michael Mclaughlin <M8ch88l@gmail.com>
        MIT Expat Licence
      */
  
  
      var BigNumber, parseNumeric,
          isNumeric = /^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,
          mathceil = Math.ceil,
          mathfloor = Math.floor,
          notBool = ' not a boolean or binary digit',
          roundingMode = 'rounding mode',
          tooManyDigits = 'number type has more than 15 significant digits',
          ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_',
          BASE = 1e14,
          LOG_BASE = 14,
          MAX_SAFE_INTEGER = 0x1fffffffffffff,         // 2^53 - 1
          // MAX_INT32 = 0x7fffffff,                   // 2^31 - 1
          POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13],
          SQRT_BASE = 1e7,
  
          /*
           * The limit on the value of DECIMAL_PLACES, TO_EXP_NEG, TO_EXP_POS, MIN_EXP, MAX_EXP, and
           * the arguments to toExponential, toFixed, toFormat, and toPrecision, beyond which an
           * exception is thrown (if ERRORS is true).
           */
          MAX = 1E9;                                   // 0 to MAX_INT32
  
  
      /*
       * Create and return a BigNumber constructor.
       */
      function constructorFactory(configObj) {
          var div,
  
              // id tracks the caller function, so its name can be included in error messages.
              id = 0,
              P = BigNumber.prototype,
              ONE = new BigNumber(1),
  
  
              /********************************* EDITABLE DEFAULTS **********************************/
  
  
              /*
               * The default values below must be integers within the inclusive ranges stated.
               * The values can also be changed at run-time using BigNumber.config.
               */
  
              // The maximum number of decimal places for operations involving division.
              DECIMAL_PLACES = 20,                     // 0 to MAX
  
              /*
               * The rounding mode used when rounding to the above decimal places, and when using
               * toExponential, toFixed, toFormat and toPrecision, and round (default value).
               * UP         0 Away from zero.
               * DOWN       1 Towards zero.
               * CEIL       2 Towards +Infinity.
               * FLOOR      3 Towards -Infinity.
               * HALF_UP    4 Towards nearest neighbour. If equidistant, up.
               * HALF_DOWN  5 Towards nearest neighbour. If equidistant, down.
               * HALF_EVEN  6 Towards nearest neighbour. If equidistant, towards even neighbour.
               * HALF_CEIL  7 Towards nearest neighbour. If equidistant, towards +Infinity.
               * HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity.
               */
              ROUNDING_MODE = 4,                       // 0 to 8
  
              // EXPONENTIAL_AT : [TO_EXP_NEG , TO_EXP_POS]
  
              // The exponent value at and beneath which toString returns exponential notation.
              // Number type: -7
              TO_EXP_NEG = -7,                         // 0 to -MAX
  
              // The exponent value at and above which toString returns exponential notation.
              // Number type: 21
              TO_EXP_POS = 21,                         // 0 to MAX
  
              // RANGE : [MIN_EXP, MAX_EXP]
  
              // The minimum exponent value, beneath which underflow to zero occurs.
              // Number type: -324  (5e-324)
              MIN_EXP = -1e7,                          // -1 to -MAX
  
              // The maximum exponent value, above which overflow to Infinity occurs.
              // Number type:  308  (1.7976931348623157e+308)
              // For MAX_EXP > 1e7, e.g. new BigNumber('1e100000000').plus(1) may be slow.
              MAX_EXP = 1e7,                           // 1 to MAX
  
              // Whether BigNumber Errors are ever thrown.
              ERRORS = true,                           // true or false
  
              // Change to intValidatorNoErrors if ERRORS is false.
              isValidInt = intValidatorWithErrors,     // intValidatorWithErrors/intValidatorNoErrors
  
              // Whether to use cryptographically-secure random number generation, if available.
              CRYPTO = false,                          // true or false
  
              /*
               * The modulo mode used when calculating the modulus: a mod n.
               * The quotient (q = a / n) is calculated according to the corresponding rounding mode.
               * The remainder (r) is calculated as: r = a - n * q.
               *
               * UP        0 The remainder is positive if the dividend is negative, else is negative.
               * DOWN      1 The remainder has the same sign as the dividend.
               *             This modulo mode is commonly known as 'truncated division' and is
               *             equivalent to (a % n) in JavaScript.
               * FLOOR     3 The remainder has the same sign as the divisor (Python %).
               * HALF_EVEN 6 This modulo mode implements the IEEE 754 remainder function.
               * EUCLID    9 Euclidian division. q = sign(n) * floor(a / abs(n)).
               *             The remainder is always positive.
               *
               * The truncated division, floored division, Euclidian division and IEEE 754 remainder
               * modes are commonly used for the modulus operation.
               * Although the other rounding modes can also be used, they may not give useful results.
               */
              MODULO_MODE = 1,                         // 0 to 9
  
              // The maximum number of significant digits of the result of the toPower operation.
              // If POW_PRECISION is 0, there will be unlimited significant digits.
              POW_PRECISION = 0,                       // 0 to MAX
  
              // The format specification used by the BigNumber.prototype.toFormat method.
              FORMAT = {
                  decimalSeparator: '.',
                  groupSeparator: ',',
                  groupSize: 3,
                  secondaryGroupSize: 0,
                  fractionGroupSeparator: '\xA0',      // non-breaking space
                  fractionGroupSize: 0
              };
  
  
          /******************************************************************************************/
  
  
          // CONSTRUCTOR
  
  
          /*
           * The BigNumber constructor and exported function.
           * Create and return a new instance of a BigNumber object.
           *
           * n {number|string|BigNumber} A numeric value.
           * [b] {number} The base of n. Integer, 2 to 64 inclusive.
           */
          function BigNumber( n, b ) {
              var c, e, i, num, len, str,
                  x = this;
  
              // Enable constructor usage without new.
              if ( !( x instanceof BigNumber ) ) {
  
                  // 'BigNumber() constructor call without new: {n}'
                  if (ERRORS) raise( 26, 'constructor call without new', n );
                  return new BigNumber( n, b );
              }
  
              // 'new BigNumber() base not an integer: {b}'
              // 'new BigNumber() base out of range: {b}'
              if ( b == null || !isValidInt( b, 2, 64, id, 'base' ) ) {
  
                  // Duplicate.
                  if ( n instanceof BigNumber ) {
                      x.s = n.s;
                      x.e = n.e;
                      x.c = ( n = n.c ) ? n.slice() : n;
                      id = 0;
                      return;
                  }
  
                  if ( ( num = typeof n == 'number' ) && n * 0 == 0 ) {
                      x.s = 1 / n < 0 ? ( n = -n, -1 ) : 1;
  
                      // Fast path for integers.
                      if ( n === ~~n ) {
                          for ( e = 0, i = n; i >= 10; i /= 10, e++ );
                          x.e = e;
                          x.c = [n];
                          id = 0;
                          return;
                      }
  
                      str = n + '';
                  } else {
                      if ( !isNumeric.test( str = n + '' ) ) return parseNumeric( x, str, num );
                      x.s = str.charCodeAt(0) === 45 ? ( str = str.slice(1), -1 ) : 1;
                  }
              } else {
                  b = b | 0;
                  str = n + '';
  
                  // Ensure return value is rounded to DECIMAL_PLACES as with other bases.
                  // Allow exponential notation to be used with base 10 argument.
                  if ( b == 10 ) {
                      x = new BigNumber( n instanceof BigNumber ? n : str );
                      return round( x, DECIMAL_PLACES + x.e + 1, ROUNDING_MODE );
                  }
  
                  // Avoid potential interpretation of Infinity and NaN as base 44+ values.
                  // Any number in exponential form will fail due to the [Ee][+-].
                  if ( ( num = typeof n == 'number' ) && n * 0 != 0 ||
                    !( new RegExp( '^-?' + ( c = '[' + ALPHABET.slice( 0, b ) + ']+' ) +
                      '(?:\\.' + c + ')?$',b < 37 ? 'i' : '' ) ).test(str) ) {
                      return parseNumeric( x, str, num, b );
                  }
  
                  if (num) {
                      x.s = 1 / n < 0 ? ( str = str.slice(1), -1 ) : 1;
  
                      if ( ERRORS && str.replace( /^0\.0*|\./, '' ).length > 15 ) {
  
                          // 'new BigNumber() number type has more than 15 significant digits: {n}'
                          raise( id, tooManyDigits, n );
                      }
  
                      // Prevent later check for length on converted number.
                      num = false;
                  } else {
                      x.s = str.charCodeAt(0) === 45 ? ( str = str.slice(1), -1 ) : 1;
                  }
  
                  str = convertBase( str, 10, b, x.s );
              }
  
              // Decimal point?
              if ( ( e = str.indexOf('.') ) > -1 ) str = str.replace( '.', '' );
  
              // Exponential form?
              if ( ( i = str.search( /e/i ) ) > 0 ) {
  
                  // Determine exponent.
                  if ( e < 0 ) e = i;
                  e += +str.slice( i + 1 );
                  str = str.substring( 0, i );
              } else if ( e < 0 ) {
  
                  // Integer.
                  e = str.length;
              }
  
              // Determine leading zeros.
              for ( i = 0; str.charCodeAt(i) === 48; i++ );
  
              // Determine trailing zeros.
              for ( len = str.length; str.charCodeAt(--len) === 48; );
              str = str.slice( i, len + 1 );
  
              if (str) {
                  len = str.length;
  
                  // Disallow numbers with over 15 significant digits if number type.
                  // 'new BigNumber() number type has more than 15 significant digits: {n}'
                  if ( num && ERRORS && len > 15 && ( n > MAX_SAFE_INTEGER || n !== mathfloor(n) ) ) {
                      raise( id, tooManyDigits, x.s * n );
                  }
  
                  e = e - i - 1;
  
                   // Overflow?
                  if ( e > MAX_EXP ) {
  
                      // Infinity.
                      x.c = x.e = null;
  
                  // Underflow?
                  } else if ( e < MIN_EXP ) {
  
                      // Zero.
                      x.c = [ x.e = 0 ];
                  } else {
                      x.e = e;
                      x.c = [];
  
                      // Transform base
  
                      // e is the base 10 exponent.
                      // i is where to slice str to get the first element of the coefficient array.
                      i = ( e + 1 ) % LOG_BASE;
                      if ( e < 0 ) i += LOG_BASE;
  
                      if ( i < len ) {
                          if (i) x.c.push( +str.slice( 0, i ) );
  
                          for ( len -= LOG_BASE; i < len; ) {
                              x.c.push( +str.slice( i, i += LOG_BASE ) );
                          }
  
                          str = str.slice(i);
                          i = LOG_BASE - str.length;
                      } else {
                          i -= len;
                      }
  
                      for ( ; i--; str += '0' );
                      x.c.push( +str );
                  }
              } else {
  
                  // Zero.
                  x.c = [ x.e = 0 ];
              }
  
              id = 0;
          }
  
  
          // CONSTRUCTOR PROPERTIES
  
  
          BigNumber.another = constructorFactory;
  
          BigNumber.ROUND_UP = 0;
          BigNumber.ROUND_DOWN = 1;
          BigNumber.ROUND_CEIL = 2;
          BigNumber.ROUND_FLOOR = 3;
          BigNumber.ROUND_HALF_UP = 4;
          BigNumber.ROUND_HALF_DOWN = 5;
          BigNumber.ROUND_HALF_EVEN = 6;
          BigNumber.ROUND_HALF_CEIL = 7;
          BigNumber.ROUND_HALF_FLOOR = 8;
          BigNumber.EUCLID = 9;
  
  
          /*
           * Configure infrequently-changing library-wide settings.
           *
           * Accept an object or an argument list, with one or many of the following properties or
           * parameters respectively:
           *
           *   DECIMAL_PLACES  {number}  Integer, 0 to MAX inclusive
           *   ROUNDING_MODE   {number}  Integer, 0 to 8 inclusive
           *   EXPONENTIAL_AT  {number|number[]}  Integer, -MAX to MAX inclusive or
           *                                      [integer -MAX to 0 incl., 0 to MAX incl.]
           *   RANGE           {number|number[]}  Non-zero integer, -MAX to MAX inclusive or
           *                                      [integer -MAX to -1 incl., integer 1 to MAX incl.]
           *   ERRORS          {boolean|number}   true, false, 1 or 0
           *   CRYPTO          {boolean|number}   true, false, 1 or 0
           *   MODULO_MODE     {number}           0 to 9 inclusive
           *   POW_PRECISION   {number}           0 to MAX inclusive
           *   FORMAT          {object}           See BigNumber.prototype.toFormat
           *      decimalSeparator       {string}
           *      groupSeparator         {string}
           *      groupSize              {number}
           *      secondaryGroupSize     {number}
           *      fractionGroupSeparator {string}
           *      fractionGroupSize      {number}
           *
           * (The values assigned to the above FORMAT object properties are not checked for validity.)
           *
           * E.g.
           * BigNumber.config(20, 4) is equivalent to
           * BigNumber.config({ DECIMAL_PLACES : 20, ROUNDING_MODE : 4 })
           *
           * Ignore properties/parameters set to null or undefined.
           * Return an object with the properties current values.
           */
          BigNumber.config = BigNumber.set = function () {
              var v, p,
                  i = 0,
                  r = {},
                  a = arguments,
                  o = a[0],
                  has = o && typeof o == 'object'
                    ? function () { if ( o.hasOwnProperty(p) ) return ( v = o[p] ) != null; }
                    : function () { if ( a.length > i ) return ( v = a[i++] ) != null; };
  
              // DECIMAL_PLACES {number} Integer, 0 to MAX inclusive.
              // 'config() DECIMAL_PLACES not an integer: {v}'
              // 'config() DECIMAL_PLACES out of range: {v}'
              if ( has( p = 'DECIMAL_PLACES' ) && isValidInt( v, 0, MAX, 2, p ) ) {
                  DECIMAL_PLACES = v | 0;
              }
              r[p] = DECIMAL_PLACES;
  
              // ROUNDING_MODE {number} Integer, 0 to 8 inclusive.
              // 'config() ROUNDING_MODE not an integer: {v}'
              // 'config() ROUNDING_MODE out of range: {v}'
              if ( has( p = 'ROUNDING_MODE' ) && isValidInt( v, 0, 8, 2, p ) ) {
                  ROUNDING_MODE = v | 0;
              }
              r[p] = ROUNDING_MODE;
  
              // EXPONENTIAL_AT {number|number[]}
              // Integer, -MAX to MAX inclusive or [integer -MAX to 0 inclusive, 0 to MAX inclusive].
              // 'config() EXPONENTIAL_AT not an integer: {v}'
              // 'config() EXPONENTIAL_AT out of range: {v}'
              if ( has( p = 'EXPONENTIAL_AT' ) ) {
  
                  if ( isArray(v) ) {
                      if ( isValidInt( v[0], -MAX, 0, 2, p ) && isValidInt( v[1], 0, MAX, 2, p ) ) {
                          TO_EXP_NEG = v[0] | 0;
                          TO_EXP_POS = v[1] | 0;
                      }
                  } else if ( isValidInt( v, -MAX, MAX, 2, p ) ) {
                      TO_EXP_NEG = -( TO_EXP_POS = ( v < 0 ? -v : v ) | 0 );
                  }
              }
              r[p] = [ TO_EXP_NEG, TO_EXP_POS ];
  
              // RANGE {number|number[]} Non-zero integer, -MAX to MAX inclusive or
              // [integer -MAX to -1 inclusive, integer 1 to MAX inclusive].
              // 'config() RANGE not an integer: {v}'
              // 'config() RANGE cannot be zero: {v}'
              // 'config() RANGE out of range: {v}'
              if ( has( p = 'RANGE' ) ) {
  
                  if ( isArray(v) ) {
                      if ( isValidInt( v[0], -MAX, -1, 2, p ) && isValidInt( v[1], 1, MAX, 2, p ) ) {
                          MIN_EXP = v[0] | 0;
                          MAX_EXP = v[1] | 0;
                      }
                  } else if ( isValidInt( v, -MAX, MAX, 2, p ) ) {
                      if ( v | 0 ) MIN_EXP = -( MAX_EXP = ( v < 0 ? -v : v ) | 0 );
                      else if (ERRORS) raise( 2, p + ' cannot be zero', v );
                  }
              }
              r[p] = [ MIN_EXP, MAX_EXP ];
  
              // ERRORS {boolean|number} true, false, 1 or 0.
              // 'config() ERRORS not a boolean or binary digit: {v}'
              if ( has( p = 'ERRORS' ) ) {
  
                  if ( v === !!v || v === 1 || v === 0 ) {
                      id = 0;
                      isValidInt = ( ERRORS = !!v ) ? intValidatorWithErrors : intValidatorNoErrors;
                  } else if (ERRORS) {
                      raise( 2, p + notBool, v );
                  }
              }
              r[p] = ERRORS;
  
              // CRYPTO {boolean|number} true, false, 1 or 0.
              // 'config() CRYPTO not a boolean or binary digit: {v}'
              // 'config() crypto unavailable: {crypto}'
              if ( has( p = 'CRYPTO' ) ) {
  
                  if ( v === true || v === false || v === 1 || v === 0 ) {
                      if (v) {
                          v = typeof crypto == 'undefined';
                          if ( !v && crypto && (crypto.getRandomValues || crypto.randomBytes)) {
                              CRYPTO = true;
                          } else if (ERRORS) {
                              raise( 2, 'crypto unavailable', v ? void 0 : crypto );
                          } else {
                              CRYPTO = false;
                          }
                      } else {
                          CRYPTO = false;
                      }
                  } else if (ERRORS) {
                      raise( 2, p + notBool, v );
                  }
              }
              r[p] = CRYPTO;
  
              // MODULO_MODE {number} Integer, 0 to 9 inclusive.
              // 'config() MODULO_MODE not an integer: {v}'
              // 'config() MODULO_MODE out of range: {v}'
              if ( has( p = 'MODULO_MODE' ) && isValidInt( v, 0, 9, 2, p ) ) {
                  MODULO_MODE = v | 0;
              }
              r[p] = MODULO_MODE;
  
              // POW_PRECISION {number} Integer, 0 to MAX inclusive.
              // 'config() POW_PRECISION not an integer: {v}'
              // 'config() POW_PRECISION out of range: {v}'
              if ( has( p = 'POW_PRECISION' ) && isValidInt( v, 0, MAX, 2, p ) ) {
                  POW_PRECISION = v | 0;
              }
              r[p] = POW_PRECISION;
  
              // FORMAT {object}
              // 'config() FORMAT not an object: {v}'
              if ( has( p = 'FORMAT' ) ) {
  
                  if ( typeof v == 'object' ) {
                      FORMAT = v;
                  } else if (ERRORS) {
                      raise( 2, p + ' not an object', v );
                  }
              }
              r[p] = FORMAT;
  
              return r;
          };
  
  
          /*
           * Return a new BigNumber whose value is the maximum of the arguments.
           *
           * arguments {number|string|BigNumber}
           */
          BigNumber.max = function () { return maxOrMin( arguments, P.lt ); };
  
  
          /*
           * Return a new BigNumber whose value is the minimum of the arguments.
           *
           * arguments {number|string|BigNumber}
           */
          BigNumber.min = function () { return maxOrMin( arguments, P.gt ); };
  
  
          /*
           * Return a new BigNumber with a random value equal to or greater than 0 and less than 1,
           * and with dp, or DECIMAL_PLACES if dp is omitted, decimal places (or less if trailing
           * zeros are produced).
           *
           * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.
           *
           * 'random() decimal places not an integer: {dp}'
           * 'random() decimal places out of range: {dp}'
           * 'random() crypto unavailable: {crypto}'
           */
          BigNumber.random = (function () {
              var pow2_53 = 0x20000000000000;
  
              // Return a 53 bit integer n, where 0 <= n < 9007199254740992.
              // Check if Math.random() produces more than 32 bits of randomness.
              // If it does, assume at least 53 bits are produced, otherwise assume at least 30 bits.
              // 0x40000000 is 2^30, 0x800000 is 2^23, 0x1fffff is 2^21 - 1.
              var random53bitInt = (Math.random() * pow2_53) & 0x1fffff
                ? function () { return mathfloor( Math.random() * pow2_53 ); }
                : function () { return ((Math.random() * 0x40000000 | 0) * 0x800000) +
                    (Math.random() * 0x800000 | 0); };
  
              return function (dp) {
                  var a, b, e, k, v,
                      i = 0,
                      c = [],
                      rand = new BigNumber(ONE);
  
                  dp = dp == null || !isValidInt( dp, 0, MAX, 14 ) ? DECIMAL_PLACES : dp | 0;
                  k = mathceil( dp / LOG_BASE );
  
                  if (CRYPTO) {
  
                      // Browsers supporting crypto.getRandomValues.
                      if (crypto.getRandomValues) {
  
                          a = crypto.getRandomValues( new Uint32Array( k *= 2 ) );
  
                          for ( ; i < k; ) {
  
                              // 53 bits:
                              // ((Math.pow(2, 32) - 1) * Math.pow(2, 21)).toString(2)
                              // 11111 11111111 11111111 11111111 11100000 00000000 00000000
                              // ((Math.pow(2, 32) - 1) >>> 11).toString(2)
                              //                                     11111 11111111 11111111
                              // 0x20000 is 2^21.
                              v = a[i] * 0x20000 + (a[i + 1] >>> 11);
  
                              // Rejection sampling:
                              // 0 <= v < 9007199254740992
                              // Probability that v >= 9e15, is
                              // 7199254740992 / 9007199254740992 ~= 0.0008, i.e. 1 in 1251
                              if ( v >= 9e15 ) {
                                  b = crypto.getRandomValues( new Uint32Array(2) );
                                  a[i] = b[0];
                                  a[i + 1] = b[1];
                              } else {
  
                                  // 0 <= v <= 8999999999999999
                                  // 0 <= (v % 1e14) <= 99999999999999
                                  c.push( v % 1e14 );
                                  i += 2;
                              }
                          }
                          i = k / 2;
  
                      // Node.js supporting crypto.randomBytes.
                      } else if (crypto.randomBytes) {
  
                          // buffer
                          a = crypto.randomBytes( k *= 7 );
  
                          for ( ; i < k; ) {
  
                              // 0x1000000000000 is 2^48, 0x10000000000 is 2^40
                              // 0x100000000 is 2^32, 0x1000000 is 2^24
                              // 11111 11111111 11111111 11111111 11111111 11111111 11111111
                              // 0 <= v < 9007199254740992
                              v = ( ( a[i] & 31 ) * 0x1000000000000 ) + ( a[i + 1] * 0x10000000000 ) +
                                    ( a[i + 2] * 0x100000000 ) + ( a[i + 3] * 0x1000000 ) +
                                    ( a[i + 4] << 16 ) + ( a[i + 5] << 8 ) + a[i + 6];
  
                              if ( v >= 9e15 ) {
                                  crypto.randomBytes(7).copy( a, i );
                              } else {
  
                                  // 0 <= (v % 1e14) <= 99999999999999
                                  c.push( v % 1e14 );
                                  i += 7;
                              }
                          }
                          i = k / 7;
                      } else {
                          CRYPTO = false;
                          if (ERRORS) raise( 14, 'crypto unavailable', crypto );
                      }
                  }
  
                  // Use Math.random.
                  if (!CRYPTO) {
  
                      for ( ; i < k; ) {
                          v = random53bitInt();
                          if ( v < 9e15 ) c[i++] = v % 1e14;
                      }
                  }
  
                  k = c[--i];
                  dp %= LOG_BASE;
  
                  // Convert trailing digits to zeros according to dp.
                  if ( k && dp ) {
                      v = POWS_TEN[LOG_BASE - dp];
                      c[i] = mathfloor( k / v ) * v;
                  }
  
                  // Remove trailing elements which are zero.
                  for ( ; c[i] === 0; c.pop(), i-- );
  
                  // Zero?
                  if ( i < 0 ) {
                      c = [ e = 0 ];
                  } else {
  
                      // Remove leading elements which are zero and adjust exponent accordingly.
                      for ( e = -1 ; c[0] === 0; c.shift(), e -= LOG_BASE);
  
                      // Count the digits of the first element of c to determine leading zeros, and...
                      for ( i = 1, v = c[0]; v >= 10; v /= 10, i++);
  
                      // adjust the exponent accordingly.
                      if ( i < LOG_BASE ) e -= LOG_BASE - i;
                  }
  
                  rand.e = e;
                  rand.c = c;
                  return rand;
              };
          })();
  
  
          // PRIVATE FUNCTIONS
  
  
          // Convert a numeric string of baseIn to a numeric string of baseOut.
          function convertBase( str, baseOut, baseIn, sign ) {
              var d, e, k, r, x, xc, y,
                  i = str.indexOf( '.' ),
                  dp = DECIMAL_PLACES,
                  rm = ROUNDING_MODE;
  
              if ( baseIn < 37 ) str = str.toLowerCase();
  
              // Non-integer.
              if ( i >= 0 ) {
                  k = POW_PRECISION;
  
                  // Unlimited precision.
                  POW_PRECISION = 0;
                  str = str.replace( '.', '' );
                  y = new BigNumber(baseIn);
                  x = y.pow( str.length - i );
                  POW_PRECISION = k;
  
                  // Convert str as if an integer, then restore the fraction part by dividing the
                  // result by its base raised to a power.
                  y.c = toBaseOut( toFixedPoint( coeffToString( x.c ), x.e ), 10, baseOut );
                  y.e = y.c.length;
              }
  
              // Convert the number as integer.
              xc = toBaseOut( str, baseIn, baseOut );
              e = k = xc.length;
  
              // Remove trailing zeros.
              for ( ; xc[--k] == 0; xc.pop() );
              if ( !xc[0] ) return '0';
  
              if ( i < 0 ) {
                  --e;
              } else {
                  x.c = xc;
                  x.e = e;
  
                  // sign is needed for correct rounding.
                  x.s = sign;
                  x = div( x, y, dp, rm, baseOut );
                  xc = x.c;
                  r = x.r;
                  e = x.e;
              }
  
              d = e + dp + 1;
  
              // The rounding digit, i.e. the digit to the right of the digit that may be rounded up.
              i = xc[d];
              k = baseOut / 2;
              r = r || d < 0 || xc[d + 1] != null;
  
              r = rm < 4 ? ( i != null || r ) && ( rm == 0 || rm == ( x.s < 0 ? 3 : 2 ) )
                         : i > k || i == k &&( rm == 4 || r || rm == 6 && xc[d - 1] & 1 ||
                           rm == ( x.s < 0 ? 8 : 7 ) );
  
              if ( d < 1 || !xc[0] ) {
  
                  // 1^-dp or 0.
                  str = r ? toFixedPoint( '1', -dp ) : '0';
              } else {
                  xc.length = d;
  
                  if (r) {
  
                      // Rounding up may mean the previous digit has to be rounded up and so on.
                      for ( --baseOut; ++xc[--d] > baseOut; ) {
                          xc[d] = 0;
  
                          if ( !d ) {
                              ++e;
                              xc.unshift(1);
                          }
                      }
                  }
  
                  // Determine trailing zeros.
                  for ( k = xc.length; !xc[--k]; );
  
                  // E.g. [4, 11, 15] becomes 4bf.
                  for ( i = 0, str = ''; i <= k; str += ALPHABET.charAt( xc[i++] ) );
                  str = toFixedPoint( str, e );
              }
  
              // The caller will add the sign.
              return str;
          }
  
  
          // Perform division in the specified base. Called by div and convertBase.
          div = (function () {
  
              // Assume non-zero x and k.
              function multiply( x, k, base ) {
                  var m, temp, xlo, xhi,
                      carry = 0,
                      i = x.length,
                      klo = k % SQRT_BASE,
                      khi = k / SQRT_BASE | 0;
  
                  for ( x = x.slice(); i--; ) {
                      xlo = x[i] % SQRT_BASE;
                      xhi = x[i] / SQRT_BASE | 0;
                      m = khi * xlo + xhi * klo;
                      temp = klo * xlo + ( ( m % SQRT_BASE ) * SQRT_BASE ) + carry;
                      carry = ( temp / base | 0 ) + ( m / SQRT_BASE | 0 ) + khi * xhi;
                      x[i] = temp % base;
                  }
  
                  if (carry) x.unshift(carry);
  
                  return x;
              }
  
              function compare( a, b, aL, bL ) {
                  var i, cmp;
  
                  if ( aL != bL ) {
                      cmp = aL > bL ? 1 : -1;
                  } else {
  
                      for ( i = cmp = 0; i < aL; i++ ) {
  
                          if ( a[i] != b[i] ) {
                              cmp = a[i] > b[i] ? 1 : -1;
                              break;
                          }
                      }
                  }
                  return cmp;
              }
  
              function subtract( a, b, aL, base ) {
                  var i = 0;
  
                  // Subtract b from a.
                  for ( ; aL--; ) {
                      a[aL] -= i;
                      i = a[aL] < b[aL] ? 1 : 0;
                      a[aL] = i * base + a[aL] - b[aL];
                  }
  
                  // Remove leading zeros.
                  for ( ; !a[0] && a.length > 1; a.shift() );
              }
  
              // x: dividend, y: divisor.
              return function ( x, y, dp, rm, base ) {
                  var cmp, e, i, more, n, prod, prodL, q, qc, rem, remL, rem0, xi, xL, yc0,
                      yL, yz,
                      s = x.s == y.s ? 1 : -1,
                      xc = x.c,
                      yc = y.c;
  
                  // Either NaN, Infinity or 0?
                  if ( !xc || !xc[0] || !yc || !yc[0] ) {
  
                      return new BigNumber(
  
                        // Return NaN if either NaN, or both Infinity or 0.
                        !x.s || !y.s || ( xc ? yc && xc[0] == yc[0] : !yc ) ? NaN :
  
                          // Return ±0 if x is ±0 or y is ±Infinity, or return ±Infinity as y is ±0.
                          xc && xc[0] == 0 || !yc ? s * 0 : s / 0
                      );
                  }
  
                  q = new BigNumber(s);
                  qc = q.c = [];
                  e = x.e - y.e;
                  s = dp + e + 1;
  
                  if ( !base ) {
                      base = BASE;
                      e = bitFloor( x.e / LOG_BASE ) - bitFloor( y.e / LOG_BASE );
                      s = s / LOG_BASE | 0;
                  }
  
                  // Result exponent may be one less then the current value of e.
                  // The coefficients of the BigNumbers from convertBase may have trailing zeros.
                  for ( i = 0; yc[i] == ( xc[i] || 0 ); i++ );
                  if ( yc[i] > ( xc[i] || 0 ) ) e--;
  
                  if ( s < 0 ) {
                      qc.push(1);
                      more = true;
                  } else {
                      xL = xc.length;
                      yL = yc.length;
                      i = 0;
                      s += 2;
  
                      // Normalise xc and yc so highest order digit of yc is >= base / 2.
  
                      n = mathfloor( base / ( yc[0] + 1 ) );
  
                      // Not necessary, but to handle odd bases where yc[0] == ( base / 2 ) - 1.
                      // if ( n > 1 || n++ == 1 && yc[0] < base / 2 ) {
                      if ( n > 1 ) {
                          yc = multiply( yc, n, base );
                          xc = multiply( xc, n, base );
                          yL = yc.length;
                          xL = xc.length;
                      }
  
                      xi = yL;
                      rem = xc.slice( 0, yL );
                      remL = rem.length;
  
                      // Add zeros to make remainder as long as divisor.
                      for ( ; remL < yL; rem[remL++] = 0 );
                      yz = yc.slice();
                      yz.unshift(0);
                      yc0 = yc[0];
                      if ( yc[1] >= base / 2 ) yc0++;
                      // Not necessary, but to prevent trial digit n > base, when using base 3.
                      // else if ( base == 3 && yc0 == 1 ) yc0 = 1 + 1e-15;
  
                      do {
                          n = 0;
  
                          // Compare divisor and remainder.
                          cmp = compare( yc, rem, yL, remL );
  
                          // If divisor < remainder.
                          if ( cmp < 0 ) {
  
                              // Calculate trial digit, n.
  
                              rem0 = rem[0];
                              if ( yL != remL ) rem0 = rem0 * base + ( rem[1] || 0 );
  
                              // n is how many times the divisor goes into the current remainder.
                              n = mathfloor( rem0 / yc0 );
  
                              //  Algorithm:
                              //  1. product = divisor * trial digit (n)
                              //  2. if product > remainder: product -= divisor, n--
                              //  3. remainder -= product
                              //  4. if product was < remainder at 2:
                              //    5. compare new remainder and divisor
                              //    6. If remainder > divisor: remainder -= divisor, n++
  
                              if ( n > 1 ) {
  
                                  // n may be > base only when base is 3.
                                  if (n >= base) n = base - 1;
  
                                  // product = divisor * trial digit.
                                  prod = multiply( yc, n, base );
                                  prodL = prod.length;
                                  remL = rem.length;
  
                                  // Compare product and remainder.
                                  // If product > remainder.
                                  // Trial digit n too high.
                                  // n is 1 too high about 5% of the time, and is not known to have
                                  // ever been more than 1 too high.
                                  while ( compare( prod, rem, prodL, remL ) == 1 ) {
                                      n--;
  
                                      // Subtract divisor from product.
                                      subtract( prod, yL < prodL ? yz : yc, prodL, base );
                                      prodL = prod.length;
                                      cmp = 1;
                                  }
                              } else {
  
                                  // n is 0 or 1, cmp is -1.
                                  // If n is 0, there is no need to compare yc and rem again below,
                                  // so change cmp to 1 to avoid it.
                                  // If n is 1, leave cmp as -1, so yc and rem are compared again.
                                  if ( n == 0 ) {
  
                                      // divisor < remainder, so n must be at least 1.
                                      cmp = n = 1;
                                  }
  
                                  // product = divisor
                                  prod = yc.slice();
                                  prodL = prod.length;
                              }
  
                              if ( prodL < remL ) prod.unshift(0);
  
                              // Subtract product from remainder.
                              subtract( rem, prod, remL, base );
                              remL = rem.length;
  
                               // If product was < remainder.
                              if ( cmp == -1 ) {
  
                                  // Compare divisor and new remainder.
                                  // If divisor < new remainder, subtract divisor from remainder.
                                  // Trial digit n too low.
                                  // n is 1 too low about 5% of the time, and very rarely 2 too low.
                                  while ( compare( yc, rem, yL, remL ) < 1 ) {
                                      n++;
  
                                      // Subtract divisor from remainder.
                                      subtract( rem, yL < remL ? yz : yc, remL, base );
                                      remL = rem.length;
                                  }
                              }
                          } else if ( cmp === 0 ) {
                              n++;
                              rem = [0];
                          } // else cmp === 1 and n will be 0
  
                          // Add the next digit, n, to the result array.
                          qc[i++] = n;
  
                          // Update the remainder.
                          if ( rem[0] ) {
                              rem[remL++] = xc[xi] || 0;
                          } else {
                              rem = [ xc[xi] ];
                              remL = 1;
                          }
                      } while ( ( xi++ < xL || rem[0] != null ) && s-- );
  
                      more = rem[0] != null;
  
                      // Leading zero?
                      if ( !qc[0] ) qc.shift();
                  }
  
                  if ( base == BASE ) {
  
                      // To calculate q.e, first get the number of digits of qc[0].
                      for ( i = 1, s = qc[0]; s >= 10; s /= 10, i++ );
                      round( q, dp + ( q.e = i + e * LOG_BASE - 1 ) + 1, rm, more );
  
                  // Caller is convertBase.
                  } else {
                      q.e = e;
                      q.r = +more;
                  }
  
                  return q;
              };
          })();
  
  
          /*
           * Return a string representing the value of BigNumber n in fixed-point or exponential
           * notation rounded to the specified decimal places or significant digits.
           *
           * n is a BigNumber.
           * i is the index of the last digit required (i.e. the digit that may be rounded up).
           * rm is the rounding mode.
           * caller is caller id: toExponential 19, toFixed 20, toFormat 21, toPrecision 24.
           */
          function format( n, i, rm, caller ) {
              var c0, e, ne, len, str;
  
              rm = rm != null && isValidInt( rm, 0, 8, caller, roundingMode )
                ? rm | 0 : ROUNDING_MODE;
  
              if ( !n.c ) return n.toString();
              c0 = n.c[0];
              ne = n.e;
  
              if ( i == null ) {
                  str = coeffToString( n.c );
                  str = caller == 19 || caller == 24 && ne <= TO_EXP_NEG
                    ? toExponential( str, ne )
                    : toFixedPoint( str, ne );
              } else {
                  n = round( new BigNumber(n), i, rm );
  
                  // n.e may have changed if the value was rounded up.
                  e = n.e;
  
                  str = coeffToString( n.c );
                  len = str.length;
  
                  // toPrecision returns exponential notation if the number of significant digits
                  // specified is less than the number of digits necessary to represent the integer
                  // part of the value in fixed-point notation.
  
                  // Exponential notation.
                  if ( caller == 19 || caller == 24 && ( i <= e || e <= TO_EXP_NEG ) ) {
  
                      // Append zeros?
                      for ( ; len < i; str += '0', len++ );
                      str = toExponential( str, e );
  
                  // Fixed-point notation.
                  } else {
                      i -= ne;
                      str = toFixedPoint( str, e );
  
                      // Append zeros?
                      if ( e + 1 > len ) {
                          if ( --i > 0 ) for ( str += '.'; i--; str += '0' );
                      } else {
                          i += e - len;
                          if ( i > 0 ) {
                              if ( e + 1 == len ) str += '.';
                              for ( ; i--; str += '0' );
                          }
                      }
                  }
              }
  
              return n.s < 0 && c0 ? '-' + str : str;
          }
  
  
          // Handle BigNumber.max and BigNumber.min.
          function maxOrMin( args, method ) {
              var m, n,
                  i = 0;
  
              if ( isArray( args[0] ) ) args = args[0];
              m = new BigNumber( args[0] );
  
              for ( ; ++i < args.length; ) {
                  n = new BigNumber( args[i] );
  
                  // If any number is NaN, return NaN.
                  if ( !n.s ) {
                      m = n;
                      break;
                  } else if ( method.call( m, n ) ) {
                      m = n;
                  }
              }
  
              return m;
          }
  
  
          /*
           * Return true if n is an integer in range, otherwise throw.
           * Use for argument validation when ERRORS is true.
           */
          function intValidatorWithErrors( n, min, max, caller, name ) {
              if ( n < min || n > max || n != truncate(n) ) {
                  raise( caller, ( name || 'decimal places' ) +
                    ( n < min || n > max ? ' out of range' : ' not an integer' ), n );
              }
  
              return true;
          }
  
  
          /*
           * Strip trailing zeros, calculate base 10 exponent and check against MIN_EXP and MAX_EXP.
           * Called by minus, plus and times.
           */
          function normalise( n, c, e ) {
              var i = 1,
                  j = c.length;
  
               // Remove trailing zeros.
              for ( ; !c[--j]; c.pop() );
  
              // Calculate the base 10 exponent. First get the number of digits of c[0].
              for ( j = c[0]; j >= 10; j /= 10, i++ );
  
              // Overflow?
              if ( ( e = i + e * LOG_BASE - 1 ) > MAX_EXP ) {
  
                  // Infinity.
                  n.c = n.e = null;
  
              // Underflow?
              } else if ( e < MIN_EXP ) {
  
                  // Zero.
                  n.c = [ n.e = 0 ];
              } else {
                  n.e = e;
                  n.c = c;
              }
  
              return n;
          }
  
  
          // Handle values that fail the validity test in BigNumber.
          parseNumeric = (function () {
              var basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i,
                  dotAfter = /^([^.]+)\.$/,
                  dotBefore = /^\.([^.]+)$/,
                  isInfinityOrNaN = /^-?(Infinity|NaN)$/,
                  whitespaceOrPlus = /^\s*\+(?=[\w.])|^\s+|\s+$/g;
  
              return function ( x, str, num, b ) {
                  var base,
                      s = num ? str : str.replace( whitespaceOrPlus, '' );
  
                  // No exception on ±Infinity or NaN.
                  if ( isInfinityOrNaN.test(s) ) {
                      x.s = isNaN(s) ? null : s < 0 ? -1 : 1;
                  } else {
                      if ( !num ) {
  
                          // basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i
                          s = s.replace( basePrefix, function ( m, p1, p2 ) {
                              base = ( p2 = p2.toLowerCase() ) == 'x' ? 16 : p2 == 'b' ? 2 : 8;
                              return !b || b == base ? p1 : m;
                          });
  
                          if (b) {
                              base = b;
  
                              // E.g. '1.' to '1', '.1' to '0.1'
                              s = s.replace( dotAfter, '$1' ).replace( dotBefore, '0.$1' );
                          }
  
                          if ( str != s ) return new BigNumber( s, base );
                      }
  
                      // 'new BigNumber() not a number: {n}'
                      // 'new BigNumber() not a base {b} number: {n}'
                      if (ERRORS) raise( id, 'not a' + ( b ? ' base ' + b : '' ) + ' number', str );
                      x.s = null;
                  }
  
                  x.c = x.e = null;
                  id = 0;
              }
          })();
  
  
          // Throw a BigNumber Error.
          function raise( caller, msg, val ) {
              var error = new Error( [
                  'new BigNumber',     // 0
                  'cmp',               // 1
                  'config',            // 2
                  'div',               // 3
                  'divToInt',          // 4
                  'eq',                // 5
                  'gt',                // 6
                  'gte',               // 7
                  'lt',                // 8
                  'lte',               // 9
                  'minus',             // 10
                  'mod',               // 11
                  'plus',              // 12
                  'precision',         // 13
                  'random',            // 14
                  'round',             // 15
                  'shift',             // 16
                  'times',             // 17
                  'toDigits',          // 18
                  'toExponential',     // 19
                  'toFixed',           // 20
                  'toFormat',          // 21
                  'toFraction',        // 22
                  'pow',               // 23
                  'toPrecision',       // 24
                  'toString',          // 25
                  'BigNumber'          // 26
              ][caller] + '() ' + msg + ': ' + val );
  
              error.name = 'BigNumber Error';
              id = 0;
              throw error;
          }
  
  
          /*
           * Round x to sd significant digits using rounding mode rm. Check for over/under-flow.
           * If r is truthy, it is known that there are more digits after the rounding digit.
           */
          function round( x, sd, rm, r ) {
              var d, i, j, k, n, ni, rd,
                  xc = x.c,
                  pows10 = POWS_TEN;
  
              // if x is not Infinity or NaN...
              if (xc) {
  
                  // rd is the rounding digit, i.e. the digit after the digit that may be rounded up.
                  // n is a base 1e14 number, the value of the element of array x.c containing rd.
                  // ni is the index of n within x.c.
                  // d is the number of digits of n.
                  // i is the index of rd within n including leading zeros.
                  // j is the actual index of rd within n (if < 0, rd is a leading zero).
                  out: {
  
                      // Get the number of digits of the first element of xc.
                      for ( d = 1, k = xc[0]; k >= 10; k /= 10, d++ );
                      i = sd - d;
  
                      // If the rounding digit is in the first element of xc...
                      if ( i < 0 ) {
                          i += LOG_BASE;
                          j = sd;
                          n = xc[ ni = 0 ];
  
                          // Get the rounding digit at index j of n.
                          rd = n / pows10[ d - j - 1 ] % 10 | 0;
                      } else {
                          ni = mathceil( ( i + 1 ) / LOG_BASE );
  
                          if ( ni >= xc.length ) {
  
                              if (r) {
  
                                  // Needed by sqrt.
                                  for ( ; xc.length <= ni; xc.push(0) );
                                  n = rd = 0;
                                  d = 1;
                                  i %= LOG_BASE;
                                  j = i - LOG_BASE + 1;
                              } else {
                                  break out;
                              }
                          } else {
                              n = k = xc[ni];
  
                              // Get the number of digits of n.
                              for ( d = 1; k >= 10; k /= 10, d++ );
  
                              // Get the index of rd within n.
                              i %= LOG_BASE;
  
                              // Get the index of rd within n, adjusted for leading zeros.
                              // The number of leading zeros of n is given by LOG_BASE - d.
                              j = i - LOG_BASE + d;
  
                              // Get the rounding digit at index j of n.
                              rd = j < 0 ? 0 : n / pows10[ d - j - 1 ] % 10 | 0;
                          }
                      }
  
                      r = r || sd < 0 ||
  
                      // Are there any non-zero digits after the rounding digit?
                      // The expression  n % pows10[ d - j - 1 ]  returns all digits of n to the right
                      // of the digit at j, e.g. if n is 908714 and j is 2, the expression gives 714.
                        xc[ni + 1] != null || ( j < 0 ? n : n % pows10[ d - j - 1 ] );
  
                      r = rm < 4
                        ? ( rd || r ) && ( rm == 0 || rm == ( x.s < 0 ? 3 : 2 ) )
                        : rd > 5 || rd == 5 && ( rm == 4 || r || rm == 6 &&
  
                          // Check whether the digit to the left of the rounding digit is odd.
                          ( ( i > 0 ? j > 0 ? n / pows10[ d - j ] : 0 : xc[ni - 1] ) % 10 ) & 1 ||
                            rm == ( x.s < 0 ? 8 : 7 ) );
  
                      if ( sd < 1 || !xc[0] ) {
                          xc.length = 0;
  
                          if (r) {
  
                              // Convert sd to decimal places.
                              sd -= x.e + 1;
  
                              // 1, 0.1, 0.01, 0.001, 0.0001 etc.
                              xc[0] = pows10[ ( LOG_BASE - sd % LOG_BASE ) % LOG_BASE ];
                              x.e = -sd || 0;
                          } else {
  
                              // Zero.
                              xc[0] = x.e = 0;
                          }
  
                          return x;
                      }
  
                      // Remove excess digits.
                      if ( i == 0 ) {
                          xc.length = ni;
                          k = 1;
                          ni--;
                      } else {
                          xc.length = ni + 1;
                          k = pows10[ LOG_BASE - i ];
  
                          // E.g. 56700 becomes 56000 if 7 is the rounding digit.
                          // j > 0 means i > number of leading zeros of n.
                          xc[ni] = j > 0 ? mathfloor( n / pows10[ d - j ] % pows10[j] ) * k : 0;
                      }
  
                      // Round up?
                      if (r) {
  
                          for ( ; ; ) {
  
                              // If the digit to be rounded up is in the first element of xc...
                              if ( ni == 0 ) {
  
                                  // i will be the length of xc[0] before k is added.
                                  for ( i = 1, j = xc[0]; j >= 10; j /= 10, i++ );
                                  j = xc[0] += k;
                                  for ( k = 1; j >= 10; j /= 10, k++ );
  
                                  // if i != k the length has increased.
                                  if ( i != k ) {
                                      x.e++;
                                      if ( xc[0] == BASE ) xc[0] = 1;
                                  }
  
                                  break;
                              } else {
                                  xc[ni] += k;
                                  if ( xc[ni] != BASE ) break;
                                  xc[ni--] = 0;
                                  k = 1;
                              }
                          }
                      }
  
                      // Remove trailing zeros.
                      for ( i = xc.length; xc[--i] === 0; xc.pop() );
                  }
  
                  // Overflow? Infinity.
                  if ( x.e > MAX_EXP ) {
                      x.c = x.e = null;
  
                  // Underflow? Zero.
                  } else if ( x.e < MIN_EXP ) {
                      x.c = [ x.e = 0 ];
                  }
              }
  
              return x;
          }
  
  
          // PROTOTYPE/INSTANCE METHODS
  
  
          /*
           * Return a new BigNumber whose value is the absolute value of this BigNumber.
           */
          P.absoluteValue = P.abs = function () {
              var x = new BigNumber(this);
              if ( x.s < 0 ) x.s = 1;
              return x;
          };
  
  
          /*
           * Return a new BigNumber whose value is the value of this BigNumber rounded to a whole
           * number in the direction of Infinity.
           */
          P.ceil = function () {
              return round( new BigNumber(this), this.e + 1, 2 );
          };
  
  
          /*
           * Return
           * 1 if the value of this BigNumber is greater than the value of BigNumber(y, b),
           * -1 if the value of this BigNumber is less than the value of BigNumber(y, b),
           * 0 if they have the same value,
           * or null if the value of either is NaN.
           */
          P.comparedTo = P.cmp = function ( y, b ) {
              id = 1;
              return compare( this, new BigNumber( y, b ) );
          };
  
  
          /*
           * Return the number of decimal places of the value of this BigNumber, or null if the value
           * of this BigNumber is ±Infinity or NaN.
           */
          P.decimalPlaces = P.dp = function () {
              var n, v,
                  c = this.c;
  
              if ( !c ) return null;
              n = ( ( v = c.length - 1 ) - bitFloor( this.e / LOG_BASE ) ) * LOG_BASE;
  
              // Subtract the number of trailing zeros of the last number.
              if ( v = c[v] ) for ( ; v % 10 == 0; v /= 10, n-- );
              if ( n < 0 ) n = 0;
  
              return n;
          };
  
  
          /*
           *  n / 0 = I
           *  n / N = N
           *  n / I = 0
           *  0 / n = 0
           *  0 / 0 = N
           *  0 / N = N
           *  0 / I = 0
           *  N / n = N
           *  N / 0 = N
           *  N / N = N
           *  N / I = N
           *  I / n = I
           *  I / 0 = I
           *  I / N = N
           *  I / I = N
           *
           * Return a new BigNumber whose value is the value of this BigNumber divided by the value of
           * BigNumber(y, b), rounded according to DECIMAL_PLACES and ROUNDING_MODE.
           */
          P.dividedBy = P.div = function ( y, b ) {
              id = 3;
              return div( this, new BigNumber( y, b ), DECIMAL_PLACES, ROUNDING_MODE );
          };
  
  
          /*
           * Return a new BigNumber whose value is the integer part of dividing the value of this
           * BigNumber by the value of BigNumber(y, b).
           */
          P.dividedToIntegerBy = P.divToInt = function ( y, b ) {
              id = 4;
              return div( this, new BigNumber( y, b ), 0, 1 );
          };
  
  
          /*
           * Return true if the value of this BigNumber is equal to the value of BigNumber(y, b),
           * otherwise returns false.
           */
          P.equals = P.eq = function ( y, b ) {
              id = 5;
              return compare( this, new BigNumber( y, b ) ) === 0;
          };
  
  
          /*
           * Return a new BigNumber whose value is the value of this BigNumber rounded to a whole
           * number in the direction of -Infinity.
           */
          P.floor = function () {
              return round( new BigNumber(this), this.e + 1, 3 );
          };
  
  
          /*
           * Return true if the value of this BigNumber is greater than the value of BigNumber(y, b),
           * otherwise returns false.
           */
          P.greaterThan = P.gt = function ( y, b ) {
              id = 6;
              return compare( this, new BigNumber( y, b ) ) > 0;
          };
  
  
          /*
           * Return true if the value of this BigNumber is greater than or equal to the value of
           * BigNumber(y, b), otherwise returns false.
           */
          P.greaterThanOrEqualTo = P.gte = function ( y, b ) {
              id = 7;
              return ( b = compare( this, new BigNumber( y, b ) ) ) === 1 || b === 0;
  
          };
  
  
          /*
           * Return true if the value of this BigNumber is a finite number, otherwise returns false.
           */
          P.isFinite = function () {
              return !!this.c;
          };
  
  
          /*
           * Return true if the value of this BigNumber is an integer, otherwise return false.
           */
          P.isInteger = P.isInt = function () {
              return !!this.c && bitFloor( this.e / LOG_BASE ) > this.c.length - 2;
          };
  
  
          /*
           * Return true if the value of this BigNumber is NaN, otherwise returns false.
           */
          P.isNaN = function () {
              return !this.s;
          };
  
  
          /*
           * Return true if the value of this BigNumber is negative, otherwise returns false.
           */
          P.isNegative = P.isNeg = function () {
              return this.s < 0;
          };
  
  
          /*
           * Return true if the value of this BigNumber is 0 or -0, otherwise returns false.
           */
          P.isZero = function () {
              return !!this.c && this.c[0] == 0;
          };
  
  
          /*
           * Return true if the value of this BigNumber is less than the value of BigNumber(y, b),
           * otherwise returns false.
           */
          P.lessThan = P.lt = function ( y, b ) {
              id = 8;
              return compare( this, new BigNumber( y, b ) ) < 0;
          };
  
  
          /*
           * Return true if the value of this BigNumber is less than or equal to the value of
           * BigNumber(y, b), otherwise returns false.
           */
          P.lessThanOrEqualTo = P.lte = function ( y, b ) {
              id = 9;
              return ( b = compare( this, new BigNumber( y, b ) ) ) === -1 || b === 0;
          };
  
  
          /*
           *  n - 0 = n
           *  n - N = N
           *  n - I = -I
           *  0 - n = -n
           *  0 - 0 = 0
           *  0 - N = N
           *  0 - I = -I
           *  N - n = N
           *  N - 0 = N
           *  N - N = N
           *  N - I = N
           *  I - n = I
           *  I - 0 = I
           *  I - N = N
           *  I - I = N
           *
           * Return a new BigNumber whose value is the value of this BigNumber minus the value of
           * BigNumber(y, b).
           */
          P.minus = P.sub = function ( y, b ) {
              var i, j, t, xLTy,
                  x = this,
                  a = x.s;
  
              id = 10;
              y = new BigNumber( y, b );
              b = y.s;
  
              // Either NaN?
              if ( !a || !b ) return new BigNumber(NaN);
  
              // Signs differ?
              if ( a != b ) {
                  y.s = -b;
                  return x.plus(y);
              }
  
              var xe = x.e / LOG_BASE,
                  ye = y.e / LOG_BASE,
                  xc = x.c,
                  yc = y.c;
  
              if ( !xe || !ye ) {
  
                  // Either Infinity?
                  if ( !xc || !yc ) return xc ? ( y.s = -b, y ) : new BigNumber( yc ? x : NaN );
  
                  // Either zero?
                  if ( !xc[0] || !yc[0] ) {
  
                      // Return y if y is non-zero, x if x is non-zero, or zero if both are zero.
                      return yc[0] ? ( y.s = -b, y ) : new BigNumber( xc[0] ? x :
  
                        // IEEE 754 (2008) 6.3: n - n = -0 when rounding to -Infinity
                        ROUNDING_MODE == 3 ? -0 : 0 );
                  }
              }
  
              xe = bitFloor(xe);
              ye = bitFloor(ye);
              xc = xc.slice();
  
              // Determine which is the bigger number.
              if ( a = xe - ye ) {
  
                  if ( xLTy = a < 0 ) {
                      a = -a;
                      t = xc;
                  } else {
                      ye = xe;
                      t = yc;
                  }
  
                  t.reverse();
  
                  // Prepend zeros to equalise exponents.
                  for ( b = a; b--; t.push(0) );
                  t.reverse();
              } else {
  
                  // Exponents equal. Check digit by digit.
                  j = ( xLTy = ( a = xc.length ) < ( b = yc.length ) ) ? a : b;
  
                  for ( a = b = 0; b < j; b++ ) {
  
                      if ( xc[b] != yc[b] ) {
                          xLTy = xc[b] < yc[b];
                          break;
                      }
                  }
              }
  
              // x < y? Point xc to the array of the bigger number.
              if (xLTy) t = xc, xc = yc, yc = t, y.s = -y.s;
  
              b = ( j = yc.length ) - ( i = xc.length );
  
              // Append zeros to xc if shorter.
              // No need to add zeros to yc if shorter as subtract only needs to start at yc.length.
              if ( b > 0 ) for ( ; b--; xc[i++] = 0 );
              b = BASE - 1;
  
              // Subtract yc from xc.
              for ( ; j > a; ) {
  
                  if ( xc[--j] < yc[j] ) {
                      for ( i = j; i && !xc[--i]; xc[i] = b );
                      --xc[i];
                      xc[j] += BASE;
                  }
  
                  xc[j] -= yc[j];
              }
  
              // Remove leading zeros and adjust exponent accordingly.
              for ( ; xc[0] == 0; xc.shift(), --ye );
  
              // Zero?
              if ( !xc[0] ) {
  
                  // Following IEEE 754 (2008) 6.3,
                  // n - n = +0  but  n - n = -0  when rounding towards -Infinity.
                  y.s = ROUNDING_MODE == 3 ? -1 : 1;
                  y.c = [ y.e = 0 ];
                  return y;
              }
  
              // No need to check for Infinity as +x - +y != Infinity && -x - -y != Infinity
              // for finite x and y.
              return normalise( y, xc, ye );
          };
  
  
          /*
           *   n % 0 =  N
           *   n % N =  N
           *   n % I =  n
           *   0 % n =  0
           *  -0 % n = -0
           *   0 % 0 =  N
           *   0 % N =  N
           *   0 % I =  0
           *   N % n =  N
           *   N % 0 =  N
           *   N % N =  N
           *   N % I =  N
           *   I % n =  N
           *   I % 0 =  N
           *   I % N =  N
           *   I % I =  N
           *
           * Return a new BigNumber whose value is the value of this BigNumber modulo the value of
           * BigNumber(y, b). The result depends on the value of MODULO_MODE.
           */
          P.modulo = P.mod = function ( y, b ) {
              var q, s,
                  x = this;
  
              id = 11;
              y = new BigNumber( y, b );
  
              // Return NaN if x is Infinity or NaN, or y is NaN or zero.
              if ( !x.c || !y.s || y.c && !y.c[0] ) {
                  return new BigNumber(NaN);
  
              // Return x if y is Infinity or x is zero.
              } else if ( !y.c || x.c && !x.c[0] ) {
                  return new BigNumber(x);
              }
  
              if ( MODULO_MODE == 9 ) {
  
                  // Euclidian division: q = sign(y) * floor(x / abs(y))
                  // r = x - qy    where  0 <= r < abs(y)
                  s = y.s;
                  y.s = 1;
                  q = div( x, y, 0, 3 );
                  y.s = s;
                  q.s *= s;
              } else {
                  q = div( x, y, 0, MODULO_MODE );
              }
  
              return x.minus( q.times(y) );
          };
  
  
          /*
           * Return a new BigNumber whose value is the value of this BigNumber negated,
           * i.e. multiplied by -1.
           */
          P.negated = P.neg = function () {
              var x = new BigNumber(this);
              x.s = -x.s || null;
              return x;
          };
  
  
          /*
           *  n + 0 = n
           *  n + N = N
           *  n + I = I
           *  0 + n = n
           *  0 + 0 = 0
           *  0 + N = N
           *  0 + I = I
           *  N + n = N
           *  N + 0 = N
           *  N + N = N
           *  N + I = N
           *  I + n = I
           *  I + 0 = I
           *  I + N = N
           *  I + I = I
           *
           * Return a new BigNumber whose value is the value of this BigNumber plus the value of
           * BigNumber(y, b).
           */
          P.plus = P.add = function ( y, b ) {
              var t,
                  x = this,
                  a = x.s;
  
              id = 12;
              y = new BigNumber( y, b );
              b = y.s;
  
              // Either NaN?
              if ( !a || !b ) return new BigNumber(NaN);
  
              // Signs differ?
               if ( a != b ) {
                  y.s = -b;
                  return x.minus(y);
              }
  
              var xe = x.e / LOG_BASE,
                  ye = y.e / LOG_BASE,
                  xc = x.c,
                  yc = y.c;
  
              if ( !xe || !ye ) {
  
                  // Return ±Infinity if either ±Infinity.
                  if ( !xc || !yc ) return new BigNumber( a / 0 );
  
                  // Either zero?
                  // Return y if y is non-zero, x if x is non-zero, or zero if both are zero.
                  if ( !xc[0] || !yc[0] ) return yc[0] ? y : new BigNumber( xc[0] ? x : a * 0 );
              }
  
              xe = bitFloor(xe);
              ye = bitFloor(ye);
              xc = xc.slice();
  
              // Prepend zeros to equalise exponents. Faster to use reverse then do unshifts.
              if ( a = xe - ye ) {
                  if ( a > 0 ) {
                      ye = xe;
                      t = yc;
                  } else {
                      a = -a;
                      t = xc;
                  }
  
                  t.reverse();
                  for ( ; a--; t.push(0) );
                  t.reverse();
              }
  
              a = xc.length;
              b = yc.length;
  
              // Point xc to the longer array, and b to the shorter length.
              if ( a - b < 0 ) t = yc, yc = xc, xc = t, b = a;
  
              // Only start adding at yc.length - 1 as the further digits of xc can be ignored.
              for ( a = 0; b; ) {
                  a = ( xc[--b] = xc[b] + yc[b] + a ) / BASE | 0;
                  xc[b] = BASE === xc[b] ? 0 : xc[b] % BASE;
              }
  
              if (a) {
                  xc.unshift(a);
                  ++ye;
              }
  
              // No need to check for zero, as +x + +y != 0 && -x + -y != 0
              // ye = MAX_EXP + 1 possible
              return normalise( y, xc, ye );
          };
  
  
          /*
           * Return the number of significant digits of the value of this BigNumber.
           *
           * [z] {boolean|number} Whether to count integer-part trailing zeros: true, false, 1 or 0.
           */
          P.precision = P.sd = function (z) {
              var n, v,
                  x = this,
                  c = x.c;
  
              // 'precision() argument not a boolean or binary digit: {z}'
              if ( z != null && z !== !!z && z !== 1 && z !== 0 ) {
                  if (ERRORS) raise( 13, 'argument' + notBool, z );
                  if ( z != !!z ) z = null;
              }
  
              if ( !c ) return null;
              v = c.length - 1;
              n = v * LOG_BASE + 1;
  
              if ( v = c[v] ) {
  
                  // Subtract the number of trailing zeros of the last element.
                  for ( ; v % 10 == 0; v /= 10, n-- );
  
                  // Add the number of digits of the first element.
                  for ( v = c[0]; v >= 10; v /= 10, n++ );
              }
  
              if ( z && x.e + 1 > n ) n = x.e + 1;
  
              return n;
          };
  
  
          /*
           * Return a new BigNumber whose value is the value of this BigNumber rounded to a maximum of
           * dp decimal places using rounding mode rm, or to 0 and ROUNDING_MODE respectively if
           * omitted.
           *
           * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.
           * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
           *
           * 'round() decimal places out of range: {dp}'
           * 'round() decimal places not an integer: {dp}'
           * 'round() rounding mode not an integer: {rm}'
           * 'round() rounding mode out of range: {rm}'
           */
          P.round = function ( dp, rm ) {
              var n = new BigNumber(this);
  
              if ( dp == null || isValidInt( dp, 0, MAX, 15 ) ) {
                  round( n, ~~dp + this.e + 1, rm == null ||
                    !isValidInt( rm, 0, 8, 15, roundingMode ) ? ROUNDING_MODE : rm | 0 );
              }
  
              return n;
          };
  
  
          /*
           * Return a new BigNumber whose value is the value of this BigNumber shifted by k places
           * (powers of 10). Shift to the right if n > 0, and to the left if n < 0.
           *
           * k {number} Integer, -MAX_SAFE_INTEGER to MAX_SAFE_INTEGER inclusive.
           *
           * If k is out of range and ERRORS is false, the result will be ±0 if k < 0, or ±Infinity
           * otherwise.
           *
           * 'shift() argument not an integer: {k}'
           * 'shift() argument out of range: {k}'
           */
          P.shift = function (k) {
              var n = this;
              return isValidInt( k, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER, 16, 'argument' )
  
                // k < 1e+21, or truncate(k) will produce exponential notation.
                ? n.times( '1e' + truncate(k) )
                : new BigNumber( n.c && n.c[0] && ( k < -MAX_SAFE_INTEGER || k > MAX_SAFE_INTEGER )
                  ? n.s * ( k < 0 ? 0 : 1 / 0 )
                  : n );
          };
  
  
          /*
           *  sqrt(-n) =  N
           *  sqrt( N) =  N
           *  sqrt(-I) =  N
           *  sqrt( I) =  I
           *  sqrt( 0) =  0
           *  sqrt(-0) = -0
           *
           * Return a new BigNumber whose value is the square root of the value of this BigNumber,
           * rounded according to DECIMAL_PLACES and ROUNDING_MODE.
           */
          P.squareRoot = P.sqrt = function () {
              var m, n, r, rep, t,
                  x = this,
                  c = x.c,
                  s = x.s,
                  e = x.e,
                  dp = DECIMAL_PLACES + 4,
                  half = new BigNumber('0.5');
  
              // Negative/NaN/Infinity/zero?
              if ( s !== 1 || !c || !c[0] ) {
                  return new BigNumber( !s || s < 0 && ( !c || c[0] ) ? NaN : c ? x : 1 / 0 );
              }
  
              // Initial estimate.
              s = Math.sqrt( +x );
  
              // Math.sqrt underflow/overflow?
              // Pass x to Math.sqrt as integer, then adjust the exponent of the result.
              if ( s == 0 || s == 1 / 0 ) {
                  n = coeffToString(c);
                  if ( ( n.length + e ) % 2 == 0 ) n += '0';
                  s = Math.sqrt(n);
                  e = bitFloor( ( e + 1 ) / 2 ) - ( e < 0 || e % 2 );
  
                  if ( s == 1 / 0 ) {
                      n = '1e' + e;
                  } else {
                      n = s.toExponential();
                      n = n.slice( 0, n.indexOf('e') + 1 ) + e;
                  }
  
                  r = new BigNumber(n);
              } else {
                  r = new BigNumber( s + '' );
              }
  
              // Check for zero.
              // r could be zero if MIN_EXP is changed after the this value was created.
              // This would cause a division by zero (x/t) and hence Infinity below, which would cause
              // coeffToString to throw.
              if ( r.c[0] ) {
                  e = r.e;
                  s = e + dp;
                  if ( s < 3 ) s = 0;
  
                  // Newton-Raphson iteration.
                  for ( ; ; ) {
                      t = r;
                      r = half.times( t.plus( div( x, t, dp, 1 ) ) );
  
                      if ( coeffToString( t.c   ).slice( 0, s ) === ( n =
                           coeffToString( r.c ) ).slice( 0, s ) ) {
  
                          // The exponent of r may here be one less than the final result exponent,
                          // e.g 0.0009999 (e-4) --> 0.001 (e-3), so adjust s so the rounding digits
                          // are indexed correctly.
                          if ( r.e < e ) --s;
                          n = n.slice( s - 3, s + 1 );
  
                          // The 4th rounding digit may be in error by -1 so if the 4 rounding digits
                          // are 9999 or 4999 (i.e. approaching a rounding boundary) continue the
                          // iteration.
                          if ( n == '9999' || !rep && n == '4999' ) {
  
                              // On the first iteration only, check to see if rounding up gives the
                              // exact result as the nines may infinitely repeat.
                              if ( !rep ) {
                                  round( t, t.e + DECIMAL_PLACES + 2, 0 );
  
                                  if ( t.times(t).eq(x) ) {
                                      r = t;
                                      break;
                                  }
                              }
  
                              dp += 4;
                              s += 4;
                              rep = 1;
                          } else {
  
                              // If rounding digits are null, 0{0,4} or 50{0,3}, check for exact
                              // result. If not, then there are further digits and m will be truthy.
                              if ( !+n || !+n.slice(1) && n.charAt(0) == '5' ) {
  
                                  // Truncate to the first rounding digit.
                                  round( r, r.e + DECIMAL_PLACES + 2, 1 );
                                  m = !r.times(r).eq(x);
                              }
  
                              break;
                          }
                      }
                  }
              }
  
              return round( r, r.e + DECIMAL_PLACES + 1, ROUNDING_MODE, m );
          };
  
  
          /*
           *  n * 0 = 0
           *  n * N = N
           *  n * I = I
           *  0 * n = 0
           *  0 * 0 = 0
           *  0 * N = N
           *  0 * I = N
           *  N * n = N
           *  N * 0 = N
           *  N * N = N
           *  N * I = N
           *  I * n = I
           *  I * 0 = N
           *  I * N = N
           *  I * I = I
           *
           * Return a new BigNumber whose value is the value of this BigNumber times the value of
           * BigNumber(y, b).
           */
          P.times = P.mul = function ( y, b ) {
              var c, e, i, j, k, m, xcL, xlo, xhi, ycL, ylo, yhi, zc,
                  base, sqrtBase,
                  x = this,
                  xc = x.c,
                  yc = ( id = 17, y = new BigNumber( y, b ) ).c;
  
              // Either NaN, ±Infinity or ±0?
              if ( !xc || !yc || !xc[0] || !yc[0] ) {
  
                  // Return NaN if either is NaN, or one is 0 and the other is Infinity.
                  if ( !x.s || !y.s || xc && !xc[0] && !yc || yc && !yc[0] && !xc ) {
                      y.c = y.e = y.s = null;
                  } else {
                      y.s *= x.s;
  
                      // Return ±Infinity if either is ±Infinity.
                      if ( !xc || !yc ) {
                          y.c = y.e = null;
  
                      // Return ±0 if either is ±0.
                      } else {
                          y.c = [0];
                          y.e = 0;
                      }
                  }
  
                  return y;
              }
  
              e = bitFloor( x.e / LOG_BASE ) + bitFloor( y.e / LOG_BASE );
              y.s *= x.s;
              xcL = xc.length;
              ycL = yc.length;
  
              // Ensure xc points to longer array and xcL to its length.
              if ( xcL < ycL ) zc = xc, xc = yc, yc = zc, i = xcL, xcL = ycL, ycL = i;
  
              // Initialise the result array with zeros.
              for ( i = xcL + ycL, zc = []; i--; zc.push(0) );
  
              base = BASE;
              sqrtBase = SQRT_BASE;
  
              for ( i = ycL; --i >= 0; ) {
                  c = 0;
                  ylo = yc[i] % sqrtBase;
                  yhi = yc[i] / sqrtBase | 0;
  
                  for ( k = xcL, j = i + k; j > i; ) {
                      xlo = xc[--k] % sqrtBase;
                      xhi = xc[k] / sqrtBase | 0;
                      m = yhi * xlo + xhi * ylo;
                      xlo = ylo * xlo + ( ( m % sqrtBase ) * sqrtBase ) + zc[j] + c;
                      c = ( xlo / base | 0 ) + ( m / sqrtBase | 0 ) + yhi * xhi;
                      zc[j--] = xlo % base;
                  }
  
                  zc[j] = c;
              }
  
              if (c) {
                  ++e;
              } else {
                  zc.shift();
              }
  
              return normalise( y, zc, e );
          };
  
  
          /*
           * Return a new BigNumber whose value is the value of this BigNumber rounded to a maximum of
           * sd significant digits using rounding mode rm, or ROUNDING_MODE if rm is omitted.
           *
           * [sd] {number} Significant digits. Integer, 1 to MAX inclusive.
           * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
           *
           * 'toDigits() precision out of range: {sd}'
           * 'toDigits() precision not an integer: {sd}'
           * 'toDigits() rounding mode not an integer: {rm}'
           * 'toDigits() rounding mode out of range: {rm}'
           */
          P.toDigits = function ( sd, rm ) {
              var n = new BigNumber(this);
              sd = sd == null || !isValidInt( sd, 1, MAX, 18, 'precision' ) ? null : sd | 0;
              rm = rm == null || !isValidInt( rm, 0, 8, 18, roundingMode ) ? ROUNDING_MODE : rm | 0;
              return sd ? round( n, sd, rm ) : n;
          };
  
  
          /*
           * Return a string representing the value of this BigNumber in exponential notation and
           * rounded using ROUNDING_MODE to dp fixed decimal places.
           *
           * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.
           * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
           *
           * 'toExponential() decimal places not an integer: {dp}'
           * 'toExponential() decimal places out of range: {dp}'
           * 'toExponential() rounding mode not an integer: {rm}'
           * 'toExponential() rounding mode out of range: {rm}'
           */
          P.toExponential = function ( dp, rm ) {
              return format( this,
                dp != null && isValidInt( dp, 0, MAX, 19 ) ? ~~dp + 1 : null, rm, 19 );
          };
  
  
          /*
           * Return a string representing the value of this BigNumber in fixed-point notation rounding
           * to dp fixed decimal places using rounding mode rm, or ROUNDING_MODE if rm is omitted.
           *
           * Note: as with JavaScript's number type, (-0).toFixed(0) is '0',
           * but e.g. (-0.00001).toFixed(0) is '-0'.
           *
           * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.
           * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
           *
           * 'toFixed() decimal places not an integer: {dp}'
           * 'toFixed() decimal places out of range: {dp}'
           * 'toFixed() rounding mode not an integer: {rm}'
           * 'toFixed() rounding mode out of range: {rm}'
           */
          P.toFixed = function ( dp, rm ) {
              return format( this, dp != null && isValidInt( dp, 0, MAX, 20 )
                ? ~~dp + this.e + 1 : null, rm, 20 );
          };
  
  
          /*
           * Return a string representing the value of this BigNumber in fixed-point notation rounded
           * using rm or ROUNDING_MODE to dp decimal places, and formatted according to the properties
           * of the FORMAT object (see BigNumber.config).
           *
           * FORMAT = {
           *      decimalSeparator : '.',
           *      groupSeparator : ',',
           *      groupSize : 3,
           *      secondaryGroupSize : 0,
           *      fractionGroupSeparator : '\xA0',    // non-breaking space
           *      fractionGroupSize : 0
           * };
           *
           * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.
           * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
           *
           * 'toFormat() decimal places not an integer: {dp}'
           * 'toFormat() decimal places out of range: {dp}'
           * 'toFormat() rounding mode not an integer: {rm}'
           * 'toFormat() rounding mode out of range: {rm}'
           */
          P.toFormat = function ( dp, rm ) {
              var str = format( this, dp != null && isValidInt( dp, 0, MAX, 21 )
                ? ~~dp + this.e + 1 : null, rm, 21 );
  
              if ( this.c ) {
                  var i,
                      arr = str.split('.'),
                      g1 = +FORMAT.groupSize,
                      g2 = +FORMAT.secondaryGroupSize,
                      groupSeparator = FORMAT.groupSeparator,
                      intPart = arr[0],
                      fractionPart = arr[1],
                      isNeg = this.s < 0,
                      intDigits = isNeg ? intPart.slice(1) : intPart,
                      len = intDigits.length;
  
                  if (g2) i = g1, g1 = g2, g2 = i, len -= i;
  
                  if ( g1 > 0 && len > 0 ) {
                      i = len % g1 || g1;
                      intPart = intDigits.substr( 0, i );
  
                      for ( ; i < len; i += g1 ) {
                          intPart += groupSeparator + intDigits.substr( i, g1 );
                      }
  
                      if ( g2 > 0 ) intPart += groupSeparator + intDigits.slice(i);
                      if (isNeg) intPart = '-' + intPart;
                  }
  
                  str = fractionPart
                    ? intPart + FORMAT.decimalSeparator + ( ( g2 = +FORMAT.fractionGroupSize )
                      ? fractionPart.replace( new RegExp( '\\d{' + g2 + '}\\B', 'g' ),
                        '$&' + FORMAT.fractionGroupSeparator )
                      : fractionPart )
                    : intPart;
              }
  
              return str;
          };
  
  
          /*
           * Return a string array representing the value of this BigNumber as a simple fraction with
           * an integer numerator and an integer denominator. The denominator will be a positive
           * non-zero value less than or equal to the specified maximum denominator. If a maximum
           * denominator is not specified, the denominator will be the lowest value necessary to
           * represent the number exactly.
           *
           * [md] {number|string|BigNumber} Integer >= 1 and < Infinity. The maximum denominator.
           *
           * 'toFraction() max denominator not an integer: {md}'
           * 'toFraction() max denominator out of range: {md}'
           */
          P.toFraction = function (md) {
              var arr, d0, d2, e, exp, n, n0, q, s,
                  k = ERRORS,
                  x = this,
                  xc = x.c,
                  d = new BigNumber(ONE),
                  n1 = d0 = new BigNumber(ONE),
                  d1 = n0 = new BigNumber(ONE);
  
              if ( md != null ) {
                  ERRORS = false;
                  n = new BigNumber(md);
                  ERRORS = k;
  
                  if ( !( k = n.isInt() ) || n.lt(ONE) ) {
  
                      if (ERRORS) {
                          raise( 22,
                            'max denominator ' + ( k ? 'out of range' : 'not an integer' ), md );
                      }
  
                      // ERRORS is false:
                      // If md is a finite non-integer >= 1, round it to an integer and use it.
                      md = !k && n.c && round( n, n.e + 1, 1 ).gte(ONE) ? n : null;
                  }
              }
  
              if ( !xc ) return x.toString();
              s = coeffToString(xc);
  
              // Determine initial denominator.
              // d is a power of 10 and the minimum max denominator that specifies the value exactly.
              e = d.e = s.length - x.e - 1;
              d.c[0] = POWS_TEN[ ( exp = e % LOG_BASE ) < 0 ? LOG_BASE + exp : exp ];
              md = !md || n.cmp(d) > 0 ? ( e > 0 ? d : n1 ) : n;
  
              exp = MAX_EXP;
              MAX_EXP = 1 / 0;
              n = new BigNumber(s);
  
              // n0 = d1 = 0
              n0.c[0] = 0;
  
              for ( ; ; )  {
                  q = div( n, d, 0, 1 );
                  d2 = d0.plus( q.times(d1) );
                  if ( d2.cmp(md) == 1 ) break;
                  d0 = d1;
                  d1 = d2;
                  n1 = n0.plus( q.times( d2 = n1 ) );
                  n0 = d2;
                  d = n.minus( q.times( d2 = d ) );
                  n = d2;
              }
  
              d2 = div( md.minus(d0), d1, 0, 1 );
              n0 = n0.plus( d2.times(n1) );
              d0 = d0.plus( d2.times(d1) );
              n0.s = n1.s = x.s;
              e *= 2;
  
              // Determine which fraction is closer to x, n0/d0 or n1/d1
              arr = div( n1, d1, e, ROUNDING_MODE ).minus(x).abs().cmp(
                    div( n0, d0, e, ROUNDING_MODE ).minus(x).abs() ) < 1
                      ? [ n1.toString(), d1.toString() ]
                      : [ n0.toString(), d0.toString() ];
  
              MAX_EXP = exp;
              return arr;
          };
  
  
          /*
           * Return the value of this BigNumber converted to a number primitive.
           */
          P.toNumber = function () {
              return +this;
          };
  
  
          /*
           * Return a BigNumber whose value is the value of this BigNumber raised to the power n.
           * If m is present, return the result modulo m.
           * If n is negative round according to DECIMAL_PLACES and ROUNDING_MODE.
           * If POW_PRECISION is non-zero and m is not present, round to POW_PRECISION using
           * ROUNDING_MODE.
           *
           * The modular power operation works efficiently when x, n, and m are positive integers,
           * otherwise it is equivalent to calculating x.toPower(n).modulo(m) (with POW_PRECISION 0).
           *
           * n {number} Integer, -MAX_SAFE_INTEGER to MAX_SAFE_INTEGER inclusive.
           * [m] {number|string|BigNumber} The modulus.
           *
           * 'pow() exponent not an integer: {n}'
           * 'pow() exponent out of range: {n}'
           *
           * Performs 54 loop iterations for n of 9007199254740991.
           */
          P.toPower = P.pow = function ( n, m ) {
              var k, y, z,
                  i = mathfloor( n < 0 ? -n : +n ),
                  x = this;
  
              if ( m != null ) {
                  id = 23;
                  m = new BigNumber(m);
              }
  
              // Pass ±Infinity to Math.pow if exponent is out of range.
              if ( !isValidInt( n, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER, 23, 'exponent' ) &&
                ( !isFinite(n) || i > MAX_SAFE_INTEGER && ( n /= 0 ) ||
                  parseFloat(n) != n && !( n = NaN ) ) || n == 0 ) {
                  k = Math.pow( +x, n );
                  return new BigNumber( m ? k % m : k );
              }
  
              if (m) {
                  if ( n > 1 && x.gt(ONE) && x.isInt() && m.gt(ONE) && m.isInt() ) {
                      x = x.mod(m);
                  } else {
                      z = m;
  
                      // Nullify m so only a single mod operation is performed at the end.
                      m = null;
                  }
              } else if (POW_PRECISION) {
  
                  // Truncating each coefficient array to a length of k after each multiplication
                  // equates to truncating significant digits to POW_PRECISION + [28, 41],
                  // i.e. there will be a minimum of 28 guard digits retained.
                  // (Using + 1.5 would give [9, 21] guard digits.)
                  k = mathceil( POW_PRECISION / LOG_BASE + 2 );
              }
  
              y = new BigNumber(ONE);
  
              for ( ; ; ) {
                  if ( i % 2 ) {
                      y = y.times(x);
                      if ( !y.c ) break;
                      if (k) {
                          if ( y.c.length > k ) y.c.length = k;
                      } else if (m) {
                          y = y.mod(m);
                      }
                  }
  
                  i = mathfloor( i / 2 );
                  if ( !i ) break;
                  x = x.times(x);
                  if (k) {
                      if ( x.c && x.c.length > k ) x.c.length = k;
                  } else if (m) {
                      x = x.mod(m);
                  }
              }
  
              if (m) return y;
              if ( n < 0 ) y = ONE.div(y);
  
              return z ? y.mod(z) : k ? round( y, POW_PRECISION, ROUNDING_MODE ) : y;
          };
  
  
          /*
           * Return a string representing the value of this BigNumber rounded to sd significant digits
           * using rounding mode rm or ROUNDING_MODE. If sd is less than the number of digits
           * necessary to represent the integer part of the value in fixed-point notation, then use
           * exponential notation.
           *
           * [sd] {number} Significant digits. Integer, 1 to MAX inclusive.
           * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
           *
           * 'toPrecision() precision not an integer: {sd}'
           * 'toPrecision() precision out of range: {sd}'
           * 'toPrecision() rounding mode not an integer: {rm}'
           * 'toPrecision() rounding mode out of range: {rm}'
           */
          P.toPrecision = function ( sd, rm ) {
              return format( this, sd != null && isValidInt( sd, 1, MAX, 24, 'precision' )
                ? sd | 0 : null, rm, 24 );
          };
  
  
          /*
           * Return a string representing the value of this BigNumber in base b, or base 10 if b is
           * omitted. If a base is specified, including base 10, round according to DECIMAL_PLACES and
           * ROUNDING_MODE. If a base is not specified, and this BigNumber has a positive exponent
           * that is equal to or greater than TO_EXP_POS, or a negative exponent equal to or less than
           * TO_EXP_NEG, return exponential notation.
           *
           * [b] {number} Integer, 2 to 64 inclusive.
           *
           * 'toString() base not an integer: {b}'
           * 'toString() base out of range: {b}'
           */
          P.toString = function (b) {
              var str,
                  n = this,
                  s = n.s,
                  e = n.e;
  
              // Infinity or NaN?
              if ( e === null ) {
  
                  if (s) {
                      str = 'Infinity';
                      if ( s < 0 ) str = '-' + str;
                  } else {
                      str = 'NaN';
                  }
              } else {
                  str = coeffToString( n.c );
  
                  if ( b == null || !isValidInt( b, 2, 64, 25, 'base' ) ) {
                      str = e <= TO_EXP_NEG || e >= TO_EXP_POS
                        ? toExponential( str, e )
                        : toFixedPoint( str, e );
                  } else {
                      str = convertBase( toFixedPoint( str, e ), b | 0, 10, s );
                  }
  
                  if ( s < 0 && n.c[0] ) str = '-' + str;
              }
  
              return str;
          };
  
  
          /*
           * Return a new BigNumber whose value is the value of this BigNumber truncated to a whole
           * number.
           */
          P.truncated = P.trunc = function () {
              return round( new BigNumber(this), this.e + 1, 1 );
          };
  
  
  
          /*
           * Return as toString, but do not accept a base argument, and include the minus sign for
           * negative zero.
           */
          P.valueOf = P.toJSON = function () {
              var str,
                  n = this,
                  e = n.e;
  
              if ( e === null ) return n.toString();
  
              str = coeffToString( n.c );
  
              str = e <= TO_EXP_NEG || e >= TO_EXP_POS
                  ? toExponential( str, e )
                  : toFixedPoint( str, e );
  
              return n.s < 0 ? '-' + str : str;
          };
  
  
          // Aliases for BigDecimal methods.
          //P.add = P.plus;         // P.add included above
          //P.subtract = P.minus;   // P.sub included above
          //P.multiply = P.times;   // P.mul included above
          //P.divide = P.div;
          //P.remainder = P.mod;
          //P.compareTo = P.cmp;
          //P.negate = P.neg;
  
  
          if ( configObj != null ) BigNumber.config(configObj);
  
          return BigNumber;
      }
  
  
      // PRIVATE HELPER FUNCTIONS
  
  
      function bitFloor(n) {
          var i = n | 0;
          return n > 0 || n === i ? i : i - 1;
      }
  
  
      // Return a coefficient array as a string of base 10 digits.
      function coeffToString(a) {
          var s, z,
              i = 1,
              j = a.length,
              r = a[0] + '';
  
          for ( ; i < j; ) {
              s = a[i++] + '';
              z = LOG_BASE - s.length;
              for ( ; z--; s = '0' + s );
              r += s;
          }
  
          // Determine trailing zeros.
          for ( j = r.length; r.charCodeAt(--j) === 48; );
          return r.slice( 0, j + 1 || 1 );
      }
  
  
      // Compare the value of BigNumbers x and y.
      function compare( x, y ) {
          var a, b,
              xc = x.c,
              yc = y.c,
              i = x.s,
              j = y.s,
              k = x.e,
              l = y.e;
  
          // Either NaN?
          if ( !i || !j ) return null;
  
          a = xc && !xc[0];
          b = yc && !yc[0];
  
          // Either zero?
          if ( a || b ) return a ? b ? 0 : -j : i;
  
          // Signs differ?
          if ( i != j ) return i;
  
          a = i < 0;
          b = k == l;
  
          // Either Infinity?
          if ( !xc || !yc ) return b ? 0 : !xc ^ a ? 1 : -1;
  
          // Compare exponents.
          if ( !b ) return k > l ^ a ? 1 : -1;
  
          j = ( k = xc.length ) < ( l = yc.length ) ? k : l;
  
          // Compare digit by digit.
          for ( i = 0; i < j; i++ ) if ( xc[i] != yc[i] ) return xc[i] > yc[i] ^ a ? 1 : -1;
  
          // Compare lengths.
          return k == l ? 0 : k > l ^ a ? 1 : -1;
      }
  
  
      /*
       * Return true if n is a valid number in range, otherwise false.
       * Use for argument validation when ERRORS is false.
       * Note: parseInt('1e+1') == 1 but parseFloat('1e+1') == 10.
       */
      function intValidatorNoErrors( n, min, max ) {
          return ( n = truncate(n) ) >= min && n <= max;
      }
  
  
      function isArray(obj) {
          return Object.prototype.toString.call(obj) == '[object Array]';
      }
  
  
      /*
       * Convert string of baseIn to an array of numbers of baseOut.
       * Eg. convertBase('255', 10, 16) returns [15, 15].
       * Eg. convertBase('ff', 16, 10) returns [2, 5, 5].
       */
      function toBaseOut( str, baseIn, baseOut ) {
          var j,
              arr = [0],
              arrL,
              i = 0,
              len = str.length;
  
          for ( ; i < len; ) {
              for ( arrL = arr.length; arrL--; arr[arrL] *= baseIn );
              arr[ j = 0 ] += ALPHABET.indexOf( str.charAt( i++ ) );
  
              for ( ; j < arr.length; j++ ) {
  
                  if ( arr[j] > baseOut - 1 ) {
                      if ( arr[j + 1] == null ) arr[j + 1] = 0;
                      arr[j + 1] += arr[j] / baseOut | 0;
                      arr[j] %= baseOut;
                  }
              }
          }
  
          return arr.reverse();
      }
  
  
      function toExponential( str, e ) {
          return ( str.length > 1 ? str.charAt(0) + '.' + str.slice(1) : str ) +
            ( e < 0 ? 'e' : 'e+' ) + e;
      }
  
  
      function toFixedPoint( str, e ) {
          var len, z;
  
          // Negative exponent?
          if ( e < 0 ) {
  
              // Prepend zeros.
              for ( z = '0.'; ++e; z += '0' );
              str = z + str;
  
          // Positive exponent
          } else {
              len = str.length;
  
              // Append zeros.
              if ( ++e > len ) {
                  for ( z = '0', e -= len; --e; z += '0' );
                  str += z;
              } else if ( e < len ) {
                  str = str.slice( 0, e ) + '.' + str.slice(e);
              }
          }
  
          return str;
      }
  
  
      function truncate(n) {
          n = parseFloat(n);
          return n < 0 ? mathceil(n) : mathfloor(n);
      }
  
  
      // EXPORT
  
  
      BigNumber = constructorFactory();
      BigNumber.default = BigNumber.BigNumber = BigNumber;
  
  
      // AMD.
      if ( typeof define == 'function' && define.amd ) {
          define( function () { return BigNumber; } );
  
      // Node.js and other environments that support module.exports.
      } else if ( typeof module != 'undefined' && module.exports ) {
          module.exports = BigNumber;
  
      // Browser.
      } else {
          if ( !globalObj ) globalObj = typeof self != 'undefined' ? self : Function('return this')();
          globalObj.BigNumber = BigNumber;
      }
  })(this);
  
  },{}],22:[function(require,module,exports){
  'use strict'
  
  exports.Commented = require('./commented')
  exports.Diagnose = require('./diagnose')
  exports.Decoder = require('./decoder')
  exports.Encoder = require('./encoder')
  exports.Simple = require('./simple')
  exports.Tagged = require('./tagged')
  
  exports.comment = exports.Commented.comment
  exports.decodeAll = exports.Decoder.decodeAll
  exports.decodeFirst = exports.Decoder.decodeFirst
  exports.decodeAllSync = exports.Decoder.decodeAllSync
  exports.decodeFirstSync = exports.Decoder.decodeFirstSync
  exports.diagnose = exports.Diagnose.diagnose
  exports.encode = exports.Encoder.encode
  exports.decode = exports.Decoder.decodeFirstSync
  
  exports.leveldb = {
    decode: exports.Decoder.decodeAllSync,
    encode: exports.Encoder.encode,
    buffer: true,
    name: 'cbor'
  }
  
  },{"./commented":23,"./decoder":25,"./diagnose":26,"./encoder":27,"./simple":28,"./tagged":29}],23:[function(require,module,exports){
  (function (Buffer){
  'use strict'
  
  const stream = require('stream')
  const util = require('util')
  const utils = require('./utils')
  const Simple = require('./simple')
  const Decoder = require('./decoder')
  const constants = require('./constants')
  const bignumber = require('bignumber.js')
  const NoFilter = require('nofilter')
  
  const MT = constants.MT,
        NUMBYTES = constants.NUMBYTES,
        SYMS = constants.SYMS
  
  function plural (c) {
    if (c > 1) {
      return 's'
    } else {
      return ''
    }
  }
  
  /**
   * Generate the expanded format of RFC 7049, section 2.2.1
   *
   * @extends {stream.Transform}
   */
  class Commented extends stream.Transform {
    /**
     * Create a CBOR commenter.
     *
     * @param {any} [options={}] - Stream options
     * @param {bool} [options.max_depth=10] - how many times to indent the dashes
     */
    constructor (options) {
      options = options || {}
      options.readableObjectMode = false
      options.writableObjectMode = false
      const max_depth = (options.max_depth != null) ? options.max_depth : 10
      delete options.max_depth
      super(options)
  
      this.depth = 1
      this.max_depth = max_depth
      this.all = new NoFilter
      this.parser = new Decoder(options)
      this.parser.on('value', this._on_value.bind(this))
      this.parser.on('start', this._on_start.bind(this))
      this.parser.on('start-string', this._on_start_string.bind(this))
      this.parser.on('stop', this._on_stop.bind(this))
      this.parser.on('more-bytes', this._on_more.bind(this))
      this.parser.on('error', this._on_error.bind(this))
      this.parser.on('data', this._on_data.bind(this))
      this.parser.bs.on('read', this._on_read.bind(this))
    }
  
    /**
     * @private
     */
    _transform (fresh, encoding, cb) {
      this.parser.write(fresh, encoding, function (er) {
        cb(er)
      })
    }
  
    /**
     * @private
     */
    _flush (cb) {
      // TODO: find the test that covers this, and look at the return value
      return this.parser._flush(cb)
    }
  
    /**
     * @callback commentCallback
     * @param {Error} error - if one was generated
     * @param {string} commented - the comment string
     */
  
    /**
     * Comment on an input Buffer or string, creating a string passed to the
     * callback.  If callback not specified, a promise is returned.
     *
     * @static
     * @param {(string|Buffer|NoFilter)} input
     * @param {(string|object|function)} options
     * @param {number} [options.max_depth=10] - how many times to indent the dashes
     * @param {commentCallback=} cb
     * @returns {Promise} if cb not specified
     */
    static comment (input, options, cb) {
      if (input == null) {
        throw new Error('input required')
      }
      let encoding = (typeof input === 'string') ? 'hex' : void 0
      let max_depth = 10
      switch (typeof options) {
        case 'function':
          cb = options
          break
        case 'string':
          encoding = options
          break
        case 'number':
          max_depth = options
          break
        case 'object':
          let ref1, ref2
          encoding = (ref1 = options.encoding) != null ? ref1 : encoding
          max_depth = (ref2 = options.max_depth) != null ? ref2 : max_depth
          break
        case 'undefined':
          break
        default:
          throw new Error('Unknown option type')
      }
      const bs = new NoFilter
      const d = new Commented({
        max_depth: max_depth
      })
      let p = null
      if (typeof cb === 'function') {
        d.on('end', function () {
          return cb(null, bs.toString('utf8'))
        })
        d.on('error', cb)
      } else {
        p = new Promise(function (resolve, reject) {
          d.on('end', function () {
            return resolve(bs.toString('utf8'))
          })
          return d.on('error', reject)
        })
      }
      d.pipe(bs)
      d.end(input, encoding)
      return p
    }
  
    /**
     * @private
     */
    _on_error (er) {
      return this.push('ERROR: ') &&
        this.push(er.toString()) &&
        this.push('\n')
    }
  
    /**
     * @private
     */
    _on_read (buf) {
      this.all.write(buf)
      const hex = buf.toString('hex')
      this.push(new Array(this.depth + 1).join('  '))
      this.push(hex)
      let ind = (this.max_depth - this.depth) * 2
      ind -= hex.length
      if (ind < 1) {
        ind = 1
      }
      this.push(new Array(ind + 1).join(' '))
      return this.push('-- ')
    }
  
    /**
     * @private
     */
    _on_more (mt, len, parent_mt, pos) {
      this.depth++
      let desc = ''
      switch (mt) {
        case MT.POS_INT:
          desc = 'Positive number,'
          break
        case MT.NEG_INT:
          desc = 'Negative number,'
          break
        case MT.ARRAY:
          desc = 'Array, length'
          break
        case MT.MAP:
          desc = 'Map, count'
          break
        case MT.BYTE_STRING:
          desc = 'Bytes, length'
          break
        case MT.UTF8_STRING:
          desc = 'String, length'
          break
        case MT.SIMPLE_FLOAT:
          if (len === 1) {
            desc = 'Simple value,'
          } else {
            desc = 'Float,'
          }
          break
      }
      return this.push(desc + ' next ' + len + ' byte' + (plural(len)) + '\n')
    }
  
    /**
     * @private
     */
    _on_start_string (mt, tag, parent_mt, pos) {
      this.depth++
      let desc = ''
      switch (mt) {
        case MT.BYTE_STRING:
          desc = 'Bytes, length: ' + tag
          break
        case MT.UTF8_STRING:
          desc = 'String, length: ' + (tag.toString())
          break
      }
      return this.push(desc + '\n')
    }
  
    /**
     * @private
     */
    _on_start (mt, tag, parent_mt, pos) {
      this.depth++
      if (tag !== SYMS.BREAK) {
        this.push((function () {
          switch (parent_mt) {
            case MT.ARRAY:
              return '[' + pos + '], '
            case MT.MAP:
              if (pos % 2) {
                return '{Val:' + (Math.floor(pos / 2)) + '}, '
              } else {
                return '{Key:' + (Math.floor(pos / 2)) + '}, '
              }
          }
        })())
      }
      this.push((function () {
        switch (mt) {
          case MT.TAG:
            return 'Tag #' + tag
          case MT.ARRAY:
            if (tag === SYMS.STREAM) {
              return 'Array (streaming)'
            } else {
              return 'Array, ' + tag + ' item' + (plural(tag))
            }
          case MT.MAP:
            if (tag === SYMS.STREAM) {
              return 'Map (streaming)'
            } else {
              return 'Map, ' + tag + ' pair' + (plural(tag))
            }
          case MT.BYTE_STRING:
            return 'Bytes (streaming)'
          case MT.UTF8_STRING:
            return 'String (streaming)'
        }
      })())
      return this.push('\n')
    }
  
    /**
     * @private
     */
    _on_stop (mt) {
      return this.depth--
    }
  
    /**
     * @private
     */
    _on_value (val, parent_mt, pos, ai) {
      if (val !== SYMS.BREAK) {
        this.push((function () {
          switch (parent_mt) {
            case MT.ARRAY:
              return '[' + pos + '], '
            case MT.MAP:
              if (pos % 2) {
                return '{Val:' + (Math.floor(pos / 2)) + '}, '
              } else {
                return '{Key:' + (Math.floor(pos / 2)) + '}, '
              }
          }
        })())
      }
  
      if (val === SYMS.BREAK) {
        this.push('BREAK\n')
      } else if (val === SYMS.NULL) {
        this.push('null\n')
      } else if (val === SYMS.UNDEFINED) {
        this.push('undefined\n')
      } else if (typeof val === 'string') {
        this.depth--
        if (val.length > 0 ) {
          this.push(JSON.stringify(val))
          this.push('\n')
        }
      } else if (Buffer.isBuffer(val)) {
        this.depth--
        if (val.length > 0) {
          this.push(val.toString('hex'))
          this.push('\n')
        }
      } else if (val instanceof bignumber) {
        this.push(val.toString())
        this.push('\n')
      } else {
        this.push(util.inspect(val))
        this.push('\n')
      }
  
      switch (ai) {
        case NUMBYTES.ONE:
        case NUMBYTES.TWO:
        case NUMBYTES.FOUR:
        case NUMBYTES.EIGHT:
          this.depth--
      }
    }
  
    /**
     * @private
     */
    _on_data () {
      this.push('0x')
      this.push(this.all.read().toString('hex'))
      return this.push('\n')
    }
  }
  
  module.exports = Commented
  
  }).call(this,{"isBuffer":require("../../../../../../../../usr/local/lib/node_modules/browserify/node_modules/is-buffer/index.js")})
  },{"../../../../../../../../usr/local/lib/node_modules/browserify/node_modules/is-buffer/index.js":134,"./constants":24,"./decoder":25,"./simple":28,"./utils":30,"bignumber.js":21,"nofilter":98,"stream":153,"util":160}],24:[function(require,module,exports){
  'use strict'
  
  exports.MT = {
    POS_INT: 0,
    NEG_INT: 1,
    BYTE_STRING: 2,
    UTF8_STRING: 3,
    ARRAY: 4,
    MAP: 5,
    TAG: 6,
    SIMPLE_FLOAT: 7
  }
  
  exports.TAG = {
    DATE_STRING: 0,
    DATE_EPOCH: 1,
    POS_BIGINT: 2,
    NEG_BIGINT: 3,
    DECIMAL_FRAC: 4,
    BIGFLOAT: 5,
    BASE64URL_EXPECTED: 21,
    BASE64_EXPECTED: 22,
    BASE16_EXPECTED: 23,
    CBOR: 24,
    URI: 32,
    BASE64URL: 33,
    BASE64: 34,
    REGEXP: 35,
    MIME: 36
  }
  
  exports.NUMBYTES = {
    ZERO: 0,
    ONE: 24,
    TWO: 25,
    FOUR: 26,
    EIGHT: 27,
    INDEFINITE: 31
  }
  
  exports.SIMPLE = {
    FALSE: 20,
    TRUE: 21,
    NULL: 22,
    UNDEFINED: 23
  }
  
  exports.SYMS = {
    NULL: Symbol('null'),
    UNDEFINED: Symbol('undef'),
    PARENT: Symbol('parent'),
    BREAK: Symbol('break'),
    STREAM: Symbol('stream')
  }
  
  exports.SHIFT32 = Math.pow(2, 32)
  
  },{}],25:[function(require,module,exports){
  (function (Buffer){
  'use strict'
  
  const BinaryParseStream = require('../vendor/binary-parse-stream')
  const Tagged = require('./tagged')
  const Simple = require('./simple')
  const utils = require('./utils')
  const bignumber = require('bignumber.js')
  const NoFilter = require('nofilter')
  const constants = require('./constants')
  const MT = constants.MT, NUMBYTES = constants.NUMBYTES, SIMPLE = constants.SIMPLE, SYMS = constants.SYMS
  
  const NEG_ONE = new bignumber(-1)
  const NEG_MAX = NEG_ONE.sub(new bignumber(Number.MAX_SAFE_INTEGER.toString(16), 16))
  const COUNT = Symbol('count')
  const PENDING_KEY = Symbol('pending_key')
  const MAJOR = Symbol('major type')
  const ERROR = Symbol('error')
  const NOT_FOUND = Symbol('not found')
  
  function parentArray (parent, typ, count) {
    const a = []
    a[COUNT] = count
    a[SYMS.PARENT] = parent
    a[MAJOR] = typ
    return a
  }
  
  function parentBufferStream (parent, typ) {
    const b = new NoFilter
    b[SYMS.PARENT] = parent
    b[MAJOR] = typ
    return b
  }
  
  
  /**
   * Decode a stream of CBOR bytes by transforming them into equivalent
   * JavaScript data.  Because of the limitations of Node object streams,
   * special symbols are emitted instead of NULL or UNDEFINED.  Fix those
   * up by calling {@link Decoder.nullcheck}.
   *
   * @extends {BinaryParseStream}
   */
  class Decoder extends BinaryParseStream {
  
    /**
     * Create a parsing stream.
     *
     * @param {object} [options={}]
     * @param {number} [options.max_depth=-1] - the maximum depth to parse.  Use -1 for
     *   "until you run out of memory".  Set this to a finite positive number for
     *   un-trusted inputs.  Most standard inputs won't nest more than
     *   100 or so levels; I've tested into the millions before running out of
     *   memory.
     * @param {object=} options.tags - mapping from tag number to function(v),
     *   where v is the decoded value that comes after the tag, and where the
     *   function returns the correctly-created value for that tag.
     */
    constructor (options) {
      options = options || {}
      const tags = options.tags
      delete options.tags
      const max_depth = (options.max_depth != null) ? options.max_depth : -1
      delete options.max_depth
      super(options)
  
      this.running = true
      this.max_depth = max_depth
      this.tags = tags
    }
  
    /**
     * Check the given value for a symbol encoding a NULL or UNDEFINED value in
     * the CBOR stream.
     *
     * @static
     * @param {any} val - the value to check
     * @returns {any} the corrected value
     *
     * @example
     * myDecoder.on('data', function(val) {
     *   val = Decoder.nullcheck(val);
     *   ...
     * });
     */
    static nullcheck (val) {
      switch (val) {
        case SYMS.NULL:
          return null
        case SYMS.UNDEFINED:
          return undefined
        case NOT_FOUND:
          throw new Error('Value not found')
        default:
          return val
      }
    }
  
    /**
     * Decode the first CBOR item in the input, synchronously.  This will throw an
     * exception if the input is not valid CBOR.
     *
     * @static
     * @param {(string|Buffer)} input
     * @param {object} [options={encoding: 'hex'}]
     * @param {string} [options.encoding: 'hex'] - The encoding of the input.
     *   Ignored if input is a Buffer.
     * @returns {any} - the decoded value
     */
    static decodeFirstSync (input, options) {
      options = options || { encoding: 'hex' }
      let opts = {}
      let encod
      switch (typeof options) {
        case 'string':
          encod = options
          break
        case 'object':
          opts = utils.extend({}, options)
          encod = opts.encoding
          delete opts.encoding
          break
      }
      const c = new Decoder(opts)
      const s = new NoFilter(input, encod != null ? encod : utils.guessEncoding(input))
      const parser = c._parse()
      let state = parser.next()
      while (!state.done) {
        const b = s.read(state.value)
        if ((b == null) || (b.length !== state.value)) {
          throw new Error('Insufficient data')
        }
        state = parser.next(b)
      }
      return Decoder.nullcheck(state.value)
    }
  
    /**
     * Decode all of the CBOR items in the input into an array.  This will throw
     * an exception if the input is not valid CBOR; a zero-length input will
     * return an empty array.
     *
     * @static
     * @param {(string|Buffer)} input
     * @param {(string|Object)} [options={encoding: 'hex'}]
     * @param {string} [options.encoding: 'hex'] - The encoding of the input.
     *   Ignored if input is a Buffer.
     * @returns {Array} - Array of all found items
     */
    static decodeAllSync (input, options) {
      options = options || { encoding: 'hex' }
      let opts = {}
      let encod
      switch (typeof options) {
        case 'string':
          encod = options
          break
        case 'object':
          opts = utils.extend({}, options)
          encod = opts.encoding
          delete opts.encoding
      }
      const c = new Decoder(opts)
      const s = new NoFilter(input, encod != null ? encod : utils.guessEncoding(input))
      const res = []
      while (s.length > 0) {
        const parser = c._parse()
        let state = parser.next()
        while (!state.done) {
          const b = s.read(state.value)
          if ((b == null) || (b.length !== state.value)) {
            throw new Error('Insufficient data')
          }
          state = parser.next(b)
        }
        res.push(Decoder.nullcheck(state.value))
      }
      return res
    }
  
    /**
     * @callback decodeCallback
     * @param {Error} error - if one was generated
     * @param {any} value - the decoded value
     */
  
    /**
     * Decode the first CBOR item in the input.  This will error if there are more
     * bytes left over at the end, and optionally if there were no valid CBOR
     * bytes in the input.  Emits the {Decoder.NOT_FOUND} Symbol in the callback
     * if no data was found and the `required` option is false.
     *
     * @static
     * @param {(string|Buffer)} input - the input to parse
     * @param {(function|string|Object)} options
     * @param {string} [options.encoding: 'hex'] - The encoding of the input.
     *   Ignored if input is a Buffer.
     * @param {decodeCallback} cb
     * @returns {Promise} if no cb specified
     */
    static decodeFirst (input, options, cb) {
      let opts = {}
      let required = false
      let encod = 'hex'
      switch (typeof options) {
        case 'function':
          cb = options
          encod = utils.guessEncoding(input)
          break
        case 'string':
          encod = options
          break
        case 'object':
          opts = utils.extend({}, options)
          encod = (opts.encoding != null) ? opts.encoding : utils.guessEncoding(input)
          delete opts.encoding
          required = (opts.required != null) ? opts.required : false
          delete opts.required
      }
      const c = new Decoder(opts)
      let p
      let v = NOT_FOUND
      c.on('data', (val) => {
        v = Decoder.nullcheck(val)
        c.close()
      })
      if (typeof cb === 'function') {
        c.once('error', function (er) {
          const u = v
          v = ERROR
          c.close()
          return cb(er, u)
        })
        c.once('end', () => {
          switch (v) {
            case NOT_FOUND:
              if (required) {
                return cb(new Error('No CBOR found'))
              } else {
                return cb(null, v)
              }
            case ERROR:
              return void 0
            default:
              return cb(null, v)
          }
        })
      } else {
        p = new Promise(function (resolve, reject) {
          c.once('error', (er) => {
            v = ERROR
            c.close()
            return reject(er)
          })
          return c.once('end', () => {
            switch (v) {
              case NOT_FOUND:
                if (required) {
                  return reject(new Error('No CBOR found'))
                } else {
                  return resolve(v)
                }
              case ERROR:
                return void 0
              default:
                return resolve(v)
            }
          })
        })
      }
      c.end(input, encod)
      return p
    }
  
    /**
     * @callback decodeAllCallback
     * @param {Error} error - if one was generated
     * @param {Array} value - all of the decoded values, wrapped in an Array
     */
  
    /**
     * Decode all of the CBOR items in the input.  This will error if there are
     * more bytes left over at the end.
     *
     * @static
     * @param {(string|Buffer)} input - the input to parse
     * @param {(string|Object)} options - Decoding options.
     *   If string, the input encoding.
     * @param {decodeAllCallback} cb
     * @returns {Promise} if no callback
     */
    static decodeAll (input, options, cb) {
      let opts = {}
      let encod = 'hex'
      switch (typeof options) {
        case 'function':
          cb = options
          encod = utils.guessEncoding(input)
          break
        case 'string':
          encod = options
          break
        case 'object':
          opts = utils.extend({}, options)
          encod = (opts.encoding != null) ? opts.encoding : utils.guessEncoding(input)
          delete opts.encoding
      }
      const c = new Decoder(opts)
      let p
      const vals = []
      c.on('data', function (val) {
        return vals.push(Decoder.nullcheck(val))
      })
      if (typeof cb === 'function') {
        c.on('error', function (er) {
          return cb(er)
        })
        c.on('end', function () {
          return cb(null, vals)
        })
      } else {
        p = new Promise(function (resolve, reject) {
          c.on('error', function (er) {
            return reject(er)
          })
          return c.on('end', function () {
            return resolve(vals)
          })
        })
      }
      c.end(input, encod)
      return p
    }
  
    /**
     * Stop processing
     */
    close () {
      this.running = false
      this.__fresh = true
    }
  
    * _parse () {
      let parent = null
      let depth = 0
      let val = null
      while (true) {
        if ((this.max_depth >= 0) && (depth > this.max_depth)) {
          throw new Error('Maximum depth ' + this.max_depth + ' exceeded')
        }
        const octet = (yield 1)[0]
        if (!this.running) {
          throw new Error('Unexpected data: 0x' + (octet.toString(16)))
        }
        const mt = octet >> 5
        const ai = octet & 0x1f
        const parent_major = (parent != null) ? parent[MAJOR] : undefined
        const parent_length = (parent != null) ? parent.length : undefined
        switch (ai) {
          case NUMBYTES.ONE:
            this.emit('more-bytes', mt, 1, parent_major, parent_length)
            val = (yield 1)[0]
            break
          case NUMBYTES.TWO:
          case NUMBYTES.FOUR:
          case NUMBYTES.EIGHT:
            const numbytes = 1 << (ai - 24)
            this.emit('more-bytes', mt, numbytes, parent_major, parent_length)
            const buf = yield numbytes
            val = (mt === MT.SIMPLE_FLOAT) ? buf : utils.parseCBORint(ai, buf)
            break
          case 28:
          case 29:
          case 30:
            this.running = false
            throw new Error('Additional info not implemented: ' + ai)
          case NUMBYTES.INDEFINITE:
            val = -1
            break
          default:
            val = ai
        }
        switch (mt) {
          case MT.POS_INT:
            // val already decoded
            break
          case MT.NEG_INT:
            if (val === Number.MAX_SAFE_INTEGER) {
              val = NEG_MAX
            } else if (val instanceof bignumber) {
              val = NEG_ONE.sub(val)
            } else {
              val = -1 - val
            }
            break
          case MT.BYTE_STRING:
          case MT.UTF8_STRING:
            switch (val) {
              case 0:
                this.emit('start-string', mt, val, parent_major, parent_length)
                val = (mt === MT.BYTE_STRING) ? new Buffer(0) : ''
                break
              case -1:
                this.emit('start', mt, SYMS.STREAM, parent_major, parent_length)
                parent = parentBufferStream(parent, mt)
                depth++
                continue
              default:
                this.emit('start-string', mt, val, parent_major, parent_length)
                val = yield val
                if (mt === MT.UTF8_STRING) {
                  val = val.toString('utf-8')
                }
            }
            break
          case MT.ARRAY:
          case MT.MAP:
            switch (val) {
              case 0:
                val = (mt === MT.MAP) ? {} : []
                val[SYMS.PARENT] = parent
                break
              case -1:
                this.emit('start', mt, SYMS.STREAM, parent_major, parent_length)
                parent = parentArray(parent, mt, -1)
                depth++
                continue
              default:
                this.emit('start', mt, val, parent_major, parent_length)
                parent = parentArray(parent, mt, val * (mt - 3))
                depth++
                continue
            }
            break
          case MT.TAG:
            this.emit('start', mt, val, parent_major, parent_length)
            parent = parentArray(parent, mt, 1)
            parent.push(val)
            depth++
            continue
          case MT.SIMPLE_FLOAT:
            if (typeof val === 'number') {
              val = Simple.decode(val, parent != null)
            } else {
              val = utils.parseCBORfloat(val)
            }
        }
        this.emit('value', val, parent_major, parent_length, ai)
        let again = false
        while (parent != null) {
          switch (false) {
            case val !== SYMS.BREAK:
              parent[COUNT] = 1
              break
            case !Array.isArray(parent):
              parent.push(val)
              break
            case !(parent instanceof NoFilter):
              const pm = parent[MAJOR]
              if ((pm != null) && (pm !== mt)) {
                this.running = false
                throw new Error('Invalid major type in indefinite encoding')
              }
              parent.write(val)
          }
          if ((--parent[COUNT]) !== 0) {
            again = true
            break
          }
          --depth
          delete parent[COUNT]
          this.emit('stop', parent[MAJOR])
  
          if (Array.isArray(parent)) {
            switch (parent[MAJOR]) {
              case MT.ARRAY:
                val = parent
                break
              case MT.MAP:
                let allstrings = true
                if ((parent.length % 2) !== 0) {
                  throw new Error('Invalid map length: ' + parent.length)
                }
                for (let i = 0, len = parent.length; i < len; i += 2) {
                  if (typeof parent[i] !== 'string') {
                    allstrings = false
                    break
                  }
                }
                if (allstrings) {
                  val = {}
                  for (let i = 0, len = parent.length; i < len; i += 2) {
                    val[parent[i]] = parent[i + 1]
                  }
                } else {
                  val = new Map
                  for (let i = 0, len = parent.length; i < len; i += 2) {
                    val.set(parent[i], parent[i + 1])
                  }
                }
                break
              case MT.TAG:
                const t = new Tagged(parent[0], parent[1])
                val = t.convert(this.tags)
                break
            }
          } else if (parent instanceof NoFilter) {
            switch (parent[MAJOR]) {
              case MT.BYTE_STRING:
                val = parent.slice()
              case MT.UTF8_STRING:
                val = parent.toString('utf-8')
            }
          }
  
          parent = parent[SYMS.PARENT]
        }
        if (!again) {
          return val
        }
      }
    }
  }
  
  Decoder.NOT_FOUND = NOT_FOUND
  module.exports = Decoder
  
  }).call(this,require("buffer").Buffer)
  },{"../vendor/binary-parse-stream":31,"./constants":24,"./simple":28,"./tagged":29,"./utils":30,"bignumber.js":21,"buffer":129,"nofilter":98}],26:[function(require,module,exports){
  (function (Buffer){
  'use strict'
  
  const stream = require('stream')
  const util = require('util')
  const Decoder = require('./decoder')
  const Simple = require('./simple')
  const utils = require('./utils')
  const constants = require('./constants')
  const bignumber = require('bignumber.js')
  const NoFilter = require('nofilter')
  
  const MT = constants.MT, SYMS = constants.SYMS
  
  /**
   * Output the diagnostic format from a stream of CBOR bytes.
   *
   * @extends {stream.Transform}
   */
  class Diagnose extends stream.Transform {
  
    /**
     * Creates an instance of Diagnose.
     *
     * @param {Object} [options={}] - options for creation
     * @param {string} [options.separator='\n'] - output between detected objects
     * @param {bool} [options.stream_errors=false] - put error info into the
     *   output stream
     * @param {number} [options.max_depth=-1] - -1 for "until you run out of
     *   memory".  Set this to a finite positive number for un-trusted inputs.  Most
     *   standard inputs won't nest more than 100 or so levels; I've tested into the
     *   millions before running out of memory.
     */
    constructor (options) {
      options = options || {}
      const separator = (options.separator != null) ? options.separator : '\n'
      delete options.separator
      const stream_errors = (options.stream_errors != null) ? options.stream_errors : false
      delete options.stream_errors
      options.readableObjectMode = false
      options.writableObjectMode = false
      super(options)
  
      this.float_bytes = -1
      this.separator = separator
      this.stream_errors = stream_errors
      this.parser = new Decoder(options)
      this.parser.on('more-bytes', this._on_more.bind(this))
      this.parser.on('value', this._on_value.bind(this))
      this.parser.on('start', this._on_start.bind(this))
      this.parser.on('stop', this._on_stop.bind(this))
      this.parser.on('data', this._on_data.bind(this))
      this.parser.on('error', this._on_error.bind(this))
    }
  
    _transform (fresh, encoding, cb) {
      return this.parser.write(fresh, encoding, cb)
    }
  
    _flush (cb) {
      return this.parser._flush((er) => {
        if (this.stream_errors) {
          this._on_error(er)
          return cb()
        } else {
          return cb(er)
        }
      })
    }
  
    /**
     * Convenience function to return a string in diagnostic format.
     *
     * @param {(Buffer|string)} input - the CBOR bytes to format
     * @param {string} [encoding='hex'] - the encoding of input, ignored if input is Buffer
     * @param {commentCallback} cb - callback
     * @returns {Promise} if callback not specified
     */
    static diagnose (input, encoding, cb) {
      if (input == null) {
        throw new Error('input required')
      }
      let opts = {}
      let encod = 'hex'
      switch (typeof encoding) {
        case 'function':
          cb = encoding
          encod = utils.guessEncoding(input)
          break
        case 'object':
          opts = utils.extend({}, encoding)
          encod = (opts.encoding != null) ? opts.encoding : utils.guessEncoding(input)
          delete opts.encoding
          break
        default:
          encod = (encoding != null) ? encoding : 'hex'
      }
      const bs = new NoFilter
      const d = new Diagnose(opts)
      let p = null
      if (typeof cb === 'function') {
        d.on('end', function () {
          return cb(null, bs.toString('utf8'))
        })
        d.on('error', cb)
      } else {
        p = new Promise(function (resolve, reject) {
          d.on('end', function () {
            return resolve(bs.toString('utf8'))
          })
          return d.on('error', reject)
        })
      }
      d.pipe(bs)
      d.end(input, encod)
      return p
    }
  
    _on_error (er) {
      if (this.stream_errors) {
        return this.push(er.toString())
      } else {
        return this.emit('error', er)
      }
    }
  
    _on_more (mt, len, parent_mt, pos) {
      if (mt === MT.SIMPLE_FLOAT) {
        return this.float_bytes = (function () {
          switch (len) {
            case 2:
              return 1
            case 4:
              return 2
            case 8:
              return 3
          }
        })()
      }
    }
  
    _fore (parent_mt, pos) {
      switch (parent_mt) {
        case MT.BYTE_STRING:
        case MT.UTF8_STRING:
        case MT.ARRAY:
          if (pos > 0) {
            return this.push(', ')
          }
          break
        case MT.MAP:
          if (pos > 0) {
            if (pos % 2) {
              return this.push(': ')
            } else {
              return this.push(', ')
            }
          }
      }
    }
  
    _on_value (val, parent_mt, pos) {
      if (val === SYMS.BREAK) {
        return
      }
      this._fore(parent_mt, pos)
      return this.push((function () {
        switch (false) {
          case val !== SYMS.NULL:
            return 'null'
          case val !== SYMS.UNDEFINED:
            return 'undefined'
          case typeof val !== 'string':
            return JSON.stringify(val)
          case !(this.float_bytes > 0):
            const fb = this.float_bytes
            this.float_bytes = -1
            return (util.inspect(val)) + '_' + fb
          case !Buffer.isBuffer(val):
            return "h'" + (val.toString('hex')) + "'"
          case !(val instanceof bignumber):
            return val.toString()
          default:
            return util.inspect(val)
        }
      }).call(this))
    }
  
    _on_start (mt, tag, parent_mt, pos) {
      this._fore(parent_mt, pos)
      this.push((function () {
        switch (mt) {
          case MT.TAG:
            return tag + '('
          case MT.ARRAY:
            return '['
          case MT.MAP:
            return '{'
          case MT.BYTE_STRING:
          case MT.UTF8_STRING:
            return '('
          default:
            // istanbul ignore next
            throw new Error('Unknown diagnostic type: ' + mt)
        }
      })())
      if (tag === SYMS.STREAM) {
        return this.push('_ ')
      }
    }
  
    _on_stop (mt) {
      return this.push((function () {
        switch (mt) {
          case MT.TAG:
            return ')'
          case MT.ARRAY:
            return ']'
          case MT.MAP:
            return '}'
          case MT.BYTE_STRING:
          case MT.UTF8_STRING:
            return ')'
          default:
            // istanbul ignore next
            throw new Error('Unknown diagnostic type: ' + mt)
        }
      })())
    }
  
    _on_data () {
      return this.push(this.separator)
    }
  }
  
  module.exports = Diagnose
  
  }).call(this,{"isBuffer":require("../../../../../../../../usr/local/lib/node_modules/browserify/node_modules/is-buffer/index.js")})
  },{"../../../../../../../../usr/local/lib/node_modules/browserify/node_modules/is-buffer/index.js":134,"./constants":24,"./decoder":25,"./simple":28,"./utils":30,"bignumber.js":21,"nofilter":98,"stream":153,"util":160}],27:[function(require,module,exports){
  (function (Buffer){
  'use strict'
  
  const stream = require('stream')
  const url = require('url')
  const bignumber = require('bignumber.js')
  const NoFilter = require('nofilter')
  const Tagged = require('./tagged')
  const Simple = require('./simple')
  const utils = require('./utils')
  
  const constants = require('./constants')
  const MT = constants.MT, NUMBYTES = constants.NUMBYTES, SHIFT32 = constants.SHIFT32, SYMS = constants.SYMS, TAG = constants.TAG
  const HALF = (constants.MT.SIMPLE_FLOAT << 5) | constants.NUMBYTES.TWO
  const FLOAT = (constants.MT.SIMPLE_FLOAT << 5) | constants.NUMBYTES.FOUR
  const DOUBLE = (constants.MT.SIMPLE_FLOAT << 5) | constants.NUMBYTES.EIGHT
  const TRUE = (constants.MT.SIMPLE_FLOAT << 5) | constants.SIMPLE.TRUE
  const FALSE = (constants.MT.SIMPLE_FLOAT << 5) | constants.SIMPLE.FALSE
  const UNDEFINED = (constants.MT.SIMPLE_FLOAT << 5) | constants.SIMPLE.UNDEFINED
  const NULL = (constants.MT.SIMPLE_FLOAT << 5) | constants.SIMPLE.NULL
  
  const MAXINT_BN = new bignumber('0x20000000000000')
  const BUF_NAN = new Buffer('f97e00', 'hex')
  const BUF_INF_NEG = new Buffer('f9fc00', 'hex')
  const BUF_INF_POS = new Buffer('f97c00', 'hex')
  
  /**
   * Transform JavaScript values into CBOR bytes.  The `Writable` side of
   * the stream is in object mode.
   *
   * @extends {stream.Transform}
   */
  class Encoder extends stream.Transform {
  
    /**
     * Creates an instance of Encoder.
     *
     * @param {Object} [options={}] - options for the encoder
     * @param {any[]} [options.genTypes=[]] - array of pairs of `type`,
     *   `function(Encoder)` for semantic types to be encoded.  Not needed
     *   for Array, Date, Buffer, Map, RegExp, Set, Url, or bignumber.
     * @param {boolean} [options.canonical=false] - should the output be
     *   canonicalized
     */
    constructor (options) {
      options = options || {}
      options.readableObjectMode = false
      options.writableObjectMode = true
      super(options)
  
      this.canonical = options.canonical
      this.semanticTypes = [
        Array, this._pushArray,
        Date, this._pushDate,
        Buffer, this._pushBuffer,
        Map, this._pushMap,
        NoFilter, this._pushNoFilter,
        RegExp, this._pushRegexp,
        Set, this._pushSet,
        url.Url, this._pushUrl,
        bignumber, this._pushBigNumber
      ]
  
      const addTypes = options.genTypes || []
      for (let i = 0, len = addTypes.length; i < len; i += 2) {
        this.addSemanticType(addTypes[i], addTypes[i + 1])
      }
    }
  
    _transform (fresh, encoding, cb) {
      const ret = this.pushAny(fresh)
      // Old transformers might not return bool.  undefined !== false
      return cb((ret === false) ? new Error('Push Error') : undefined)
    }
  
    _flush (cb) {
      return cb()
    }
  
    /**
     * @callback encodeFunction
     * @param {Encoder} encoder - the encoder to serialize into.  Call "write"
     *   on the encoder as needed.
     * @return {bool} - true on success, else false
     */
  
    /**
     * Add an encoding function to the list of supported semantic types.  This is
     * useful for objects for which you can't add an encodeCBOR method
     *
     * @param {any} type
     * @param {any} fun
     * @returns {encodeFunction}
     */
    addSemanticType (type, fun) {
      for (let i = 0, len = this.semanticTypes.length; i < len; i += 2) {
        const typ = this.semanticTypes[i]
        if (typ === type) {
          const old = this.semanticTypes[i + 1]
          this.semanticTypes[i + 1] = fun
          return old
        }
      }
      this.semanticTypes.push(type, fun)
      return null
    }
  
    _pushUInt8 (val) {
      const b = new Buffer(1)
      b.writeUInt8(val)
      return this.push(b)
    }
  
    _pushUInt16BE (val) {
      const b = new Buffer(2)
      b.writeUInt16BE(val)
      return this.push(b)
    }
  
    _pushUInt32BE (val) {
      const b = new Buffer(4)
      b.writeUInt32BE(val)
      return this.push(b)
    }
  
    _pushDoubleBE (val) {
      const b = new Buffer(8)
      b.writeDoubleBE(val)
      return this.push(b)
    }
  
    _pushNaN () {
      return this.push(BUF_NAN)
    }
  
    _pushInfinity (obj) {
      const half = (obj < 0) ? BUF_INF_NEG : BUF_INF_POS
      return this.push(half)
    }
  
    _pushFloat (obj) {
      if (this.canonical) {
        // TODO: is this enough slower to hide behind canonical?
        // It's certainly enough of a hack (see utils.parseHalf)
  
        // From section 3.9:
        // If a protocol allows for IEEE floats, then additional canonicalization
        // rules might need to be added.  One example rule might be to have all
        // floats start as a 64-bit float, then do a test conversion to a 32-bit
        // float; if the result is the same numeric value, use the shorter value
        // and repeat the process with a test conversion to a 16-bit float.  (This
        // rule selects 16-bit float for positive and negative Infinity as well.)
  
        // which seems pretty much backwards to me.
        const b2 = new Buffer(2)
        if (utils.writeHalf(b2, obj)) {
          if (utils.parseHalf(b2) === obj) {
            return this._pushUInt8(HALF) && this.push(b2)
          }
        }
        const b4 = new Buffer(4)
        b4.writeFloatBE(obj)
        if (b4.readFloatBE() === obj) {
          return this._pushUInt8(FLOAT) && this.push(b4)
        }
      }
  
      return this._pushUInt8(DOUBLE) && this._pushDoubleBE(obj)
    }
  
    _pushInt (obj, mt, orig) {
      const m = mt << 5
      switch (false) {
        case !(obj < 24):
          return this._pushUInt8(m | obj)
        case !(obj <= 0xff):
          return this._pushUInt8(m | NUMBYTES.ONE) && this._pushUInt8(obj)
        case !(obj <= 0xffff):
          return this._pushUInt8(m | NUMBYTES.TWO) && this._pushUInt16BE(obj)
        case !(obj <= 0xffffffff):
          return this._pushUInt8(m | NUMBYTES.FOUR) && this._pushUInt32BE(obj)
        case !(obj <= Number.MAX_SAFE_INTEGER):
          return this._pushUInt8(m | NUMBYTES.EIGHT) &&
            this._pushUInt32BE(Math.floor(obj / SHIFT32)) &&
            this._pushUInt32BE(obj % SHIFT32)
        default:
          if (mt === MT.NEG_INT) {
            return this._pushFloat(orig)
          } else {
            return this._pushFloat(obj)
          }
      }
    }
  
    _pushIntNum (obj) {
      if (obj < 0) {
        return this._pushInt(-obj - 1, MT.NEG_INT, obj)
      } else {
        return this._pushInt(obj, MT.POS_INT)
      }
    }
  
    _pushNumber (obj) {
      switch (false) {
        case !isNaN(obj):
          return this._pushNaN(obj)
        case isFinite(obj):
          return this._pushInfinity(obj)
        case Math.round(obj) !== obj:
          return this._pushIntNum(obj)
        default:
          return this._pushFloat(obj)
      }
    }
  
    _pushString (obj) {
      const len = Buffer.byteLength(obj, 'utf8')
      return this._pushInt(len, MT.UTF8_STRING) && this.push(obj, 'utf8')
    }
  
    _pushBoolean (obj) {
      return this._pushUInt8(obj ? TRUE : FALSE)
    }
  
    _pushUndefined (obj) {
      return this._pushUInt8(UNDEFINED)
    }
  
    _pushNull (obj) {
      return this._pushUInt8(NULL)
    }
  
    _pushArray (gen, obj) {
      const len = obj.length
      if (!gen._pushInt(len, MT.ARRAY)) {
        return false
      }
      for (let j = 0; j < len; j++) {
        if (!gen.pushAny(obj[j])) {
          return false
        }
      }
      return true
    }
  
    _pushTag (tag) {
      return this._pushInt(tag, MT.TAG)
    }
  
    _pushDate (gen, obj) {
      return gen._pushTag(TAG.DATE_EPOCH) && gen.pushAny(obj / 1000)
    }
  
    _pushBuffer (gen, obj) {
      return gen._pushInt(obj.length, MT.BYTE_STRING) && gen.push(obj)
    }
  
    _pushNoFilter (gen, obj) {
      return gen._pushBuffer(gen, obj.slice())
    }
  
    _pushRegexp (gen, obj) {
      return gen._pushTag(TAG.REGEXP) && gen.pushAny(obj.source)
    }
  
    _pushSet (gen, obj) {
      if (!gen._pushInt(obj.size, MT.ARRAY)) {
        return false
      }
      for (let x of obj) {
        if (!gen.pushAny(x)) {
          return false
        }
      }
      return true
    }
  
    _pushUrl (gen, obj) {
      return gen._pushTag(TAG.URI) && gen.pushAny(obj.format())
    }
  
    _pushBigint (obj) {
      let tag = TAG.POS_BIGINT
      if (obj.isNegative()) {
        obj = obj.negated().minus(1)
        tag = TAG.NEG_BIGINT
      }
      let str = obj.toString(16)
      if (str.length % 2) {
        str = '0' + str
      }
      const buf = new Buffer(str, 'hex')
      return this._pushTag(tag) && this._pushBuffer(this, buf)
    }
  
    _pushBigNumber (gen, obj) {
      if (obj.isNaN()) {
        return gen._pushNaN()
      }
      if (!obj.isFinite()) {
        return gen._pushInfinity(obj.isNegative() ? -Infinity : Infinity)
      }
      if (obj.isInteger()) {
        return gen._pushBigint(obj)
      }
      if (!(gen._pushTag(TAG.DECIMAL_FRAC) &&
        gen._pushInt(2, MT.ARRAY))) {
        return false
      }
  
      const dec = obj.decimalPlaces()
      const slide = obj.mul(new bignumber(10).pow(dec))
      if (!gen._pushIntNum(-dec)) {
        return false
      }
      if (slide.abs().lessThan(MAXINT_BN)) {
        return gen._pushIntNum(slide.toNumber())
      } else {
        return gen._pushBigint(slide)
      }
    }
  
    _pushMap (gen, obj) {
      if (!gen._pushInt(obj.size, MT.MAP)) {
        return false
      }
      // memoizing the cbor only helps in certain cases, and hurts in most
      // others.  Just avoid it.
      if (gen.canonical) {
        // keep the key/value pairs together, so we don't have to do odd
        // gets with object keys later
        const entries = []
        // iterator.  If we drop support for node4, use ...
        for (const e of obj.entries()) {
          entries.push(e)
        }
        entries.sort((a,b) => {
          // a, b are both entries of [key, value]
          const a_cbor = Encoder.encode(a[0])
          const b_cbor = Encoder.encode(b[0])
          return a_cbor.compare(b_cbor)
        })
        for (const kv of entries) {
          if (!(gen.pushAny(kv[0]) && gen.pushAny(kv[1]))) {
            return false
          }
        }
      } else {
        for (const kv of obj) {
          if (!(gen.pushAny(kv[0]) && gen.pushAny(kv[1]))) {
            return false
          }
        }
      }
      return true
    }
  
    _pushObject (obj) {
      if (!obj) {
        return this._pushNull(obj)
      }
      for (let i = 0, len1 = this.semanticTypes.length; i < len1; i += 2) {
        const typ = this.semanticTypes[i]
        if (obj instanceof typ) {
          return this.semanticTypes[i + 1].call(obj, this, obj)
        }
      }
      const f = obj.encodeCBOR
      if (typeof f === 'function') {
        return f.call(obj, this)
      }
      const keys = Object.keys(obj)
      const cbor_keys = {}
      if (this.canonical) {
        // note: this can't be a normal sort, because 'b' needs to sort before
        // 'aa'
        keys.sort((a, b) => {
          // Always strings, so don't bother to pass options.
          // hold on to the cbor versions, since there's no need
          // to encode more than once
          const a_cbor = cbor_keys[a] || (cbor_keys[a] = Encoder.encode(a))
          const b_cbor = cbor_keys[b] || (cbor_keys[b] = Encoder.encode(b))
  
          return a_cbor.compare(b_cbor)
        })
      }
      if (!this._pushInt(keys.length, MT.MAP)) {
        return false
      }
      let ck
      for (let j = 0, len2 = keys.length; j < len2; j++) {
        const k = keys[j]
        if (this.canonical && ((ck = cbor_keys[k]))) {
          if (!this.push(ck)) { // already a Buffer
            return false
          }
        } else {
          if (!this._pushString(k)) {
            return false
          }
        }
        if (!this.pushAny(obj[k])) {
          return false
        }
      }
  
      return true
    }
  
    /**
     * Push any supported type onto the encoded stream
     *
     * @param {any} obj
     * @returns {boolean} true on success
     */
    pushAny (obj) {
      switch (typeof obj) {
        case 'number':
          return this._pushNumber(obj)
        case 'string':
          return this._pushString(obj)
        case 'boolean':
          return this._pushBoolean(obj)
        case 'undefined':
          return this._pushUndefined(obj)
        case 'object':
          return this._pushObject(obj)
        case 'symbol':
          switch (obj) {
            case SYMS.NULL:
              return this._pushNull(null)
            case SYMS.UNDEFINED:
              return this._pushUndefined(void 0)
            // TODO: Add pluggable support for other symbols
            default:
              throw new Error('Unknown symbol: ' + obj.toString())
          }
        default:
          throw new Error('Unknown type: ' + typeof obj + ', ' + (!!obj ? obj.toString() : ''))
      }
    }
  
    /* backwards-compat wrapper */
    _pushAny (obj) {
      // TODO: write deprecation warning
      return this.pushAny(obj)
    }
  
    /**
     * Encode one or more JavaScript objects, and return a Buffer containing the
     * CBOR bytes.
     *
     * @param {...any} objs - the objects to encode
     * @returns {Buffer} - the encoded objects
     */
    static encode () {
      const objs = Array.prototype.slice.apply(arguments)
      const enc = new Encoder()
      const bs = new NoFilter()
      enc.pipe(bs)
      for (let o of objs) {
        if (typeof o === 'undefined') {
          enc._pushUndefined()
        } else if (o === null) {
          enc._pushNull(null)
        } else {
          enc.write(o)
        }
      }
      enc.end()
      return bs.read()
    }
  }
  
  module.exports = Encoder
  
  }).call(this,require("buffer").Buffer)
  },{"./constants":24,"./simple":28,"./tagged":29,"./utils":30,"bignumber.js":21,"buffer":129,"nofilter":98,"stream":153,"url":155}],28:[function(require,module,exports){
  'use strict'
  
  const constants = require('./constants')
  const MT = constants.MT, SIMPLE = constants.SIMPLE, SYMS = constants.SYMS
  
  /**
   * A CBOR Simple Value that does not map onto a known constant.
   */
  class Simple {
    /**
     * Creates an instance of Simple.
     *
     * @param {integer} value - the simple value's integer value
     */
    constructor (value) {
      if (typeof value !== 'number') {
        throw new Error('Invalid Simple type: ' + (typeof value))
      }
      if ((value < 0) || (value > 255) || ((value|0) !== value)) {
        throw new Error('value must be a small positive integer: ' + value)
      }
      this.value = value
    }
  
    /**
     * Debug string for simple value
     *
     * @returns {string} simple(value)
     */
    toString () {
      return 'simple(' + this.value + ')'
    }
  
    /**
     * Debug string for simple value
     *
     * @returns {string} simple(value)
     */
    inspect (depth, opts) {
      return 'simple(' + this.value + ')'
    }
  
    /**
     * Push the simple value onto the CBOR stream
     *
     * @param {cbor.Encoder} gen The generator to push onto
     */
    encodeCBOR (gen) {
      return gen._pushInt(this.value, MT.SIMPLE_FLOAT)
    }
  
    /**
     * Is the given object a Simple?
     *
     * @param {any} obj - object to test
     * @returns {bool} - is it Simple?
     */
    static isSimple (obj) {
      return obj instanceof Simple
    }
  
    /**
     * Decode from the CBOR additional information into a JavaScript value.
     * If the CBOR item has no parent, return a "safe" symbol instead of
     * `null` or `undefined`, so that the value can be passed through a
     * stream in object mode.
     *
     * @param {Number} val - the CBOR additional info to convert
     * @param {bool} has_parent - Does the CBOR item have a parent?
     * @returns {(null|undefined|Boolean|Symbol)} - the decoded value
     */
    static decode (val, has_parent) {
      if (has_parent == null) {
        has_parent = true
      }
      switch (val) {
        case SIMPLE.FALSE:
          return false
        case SIMPLE.TRUE:
          return true
        case SIMPLE.NULL:
          if (has_parent) {
            return null
          } else {
            return SYMS.NULL
          }
        case SIMPLE.UNDEFINED:
          if (has_parent) {
            return void 0
          } else {
            return SYMS.UNDEFINED
          }
        case -1:
          if (!has_parent) {
            throw new Error('Invalid BREAK')
          }
          return SYMS.BREAK
        default:
          return new Simple(val)
      }
    }
  }
  
  module.exports = Simple
  
  },{"./constants":24}],29:[function(require,module,exports){
  'use strict'
  
  const bignumber = require('bignumber.js')
  const utils = require('./utils')
  const url = require('url')
  
  const MINUS_ONE = new bignumber(-1)
  const TEN = new bignumber(10)
  const TWO = new bignumber(2)
  
  
  /**
   * A CBOR tagged item, where the tag does not have semantics specified at the
   * moment, or those semantics threw an error during parsing. Typically this will
   * be an extension point you're not yet expecting.
   */
  class Tagged {
  
    /**
     * Creates an instance of Tagged.
     *
     * @param {Number} tag - the number of the tag
     * @param {any} value - the value inside the tag
     * @param {Error} err - the error that was thrown parsing the tag, or null
     */
    constructor (tag, value, err) {
      this.tag = tag
      this.value = value
      this.err = err
      if (typeof this.tag !== 'number') {
        throw new Error('Invalid tag type (' + (typeof this.tag) + ')')
      }
      if ((this.tag < 0) || ((this.tag | 0) !== this.tag)) {
        throw new Error('Tag must be a positive integer: ' + this.tag)
      }
    }
  
    /**
     * Convert to a String
     *
     * @returns {String} string of the form '1(2)'
     */
    toString () {
      return `${this.tag}(${JSON.stringify(this.value)})`
    }
  
    /**
     * Push the simple value onto the CBOR stream
     *
     * @param {cbor.Encoder} gen The generator to push onto
     */
    encodeCBOR (gen) {
      gen._pushTag(this.tag)
      return gen.pushAny(this.value)
    }
  
    /**
     * If we have a converter for this type, do the conversion.  Some converters
     * are built-in.  Additional ones can be passed in.  If you want to remove
     * a built-in converter, pass a converter in whose value is 'null' instead
     * of a function.
     *
     * @param {Object} converters - keys in the object are a tag number, the value
     *   is a function that takes the decoded CBOR and returns a JavaScript value
     *   of the appropriate type.  Throw an exception in the function on errors.
     * @returns {any} - the converted item
     */
    convert (converters) {
      var er, f
      f = converters != null ? converters[this.tag] : void 0
      if (typeof f !== 'function') {
        f = Tagged['_tag_' + this.tag]
        if (typeof f !== 'function') {
          return this
        }
      }
      try {
        return f.call(Tagged, this.value)
      } catch (error) {
        er = error
        this.err = er
        return this
      }
    }
  
    static _tag_0 (v) {
      return new Date(v)
    }
  
    static _tag_1 (v) {
      return new Date(v * 1000)
    }
  
    static _tag_2 (v) {
      return utils.bufferToBignumber(v)
    }
  
    static _tag_3 (v) {
      return MINUS_ONE.minus(utils.bufferToBignumber(v))
    }
  
    static _tag_4 (v) {
      return TEN.pow(v[0]).times(v[1])
    }
  
    static _tag_5 (v) {
      return TWO.pow(v[0]).times(v[1])
    }
  
    static _tag_32 (v) {
      return url.parse(v)
    }
  
    static _tag_35 (v) {
      return new RegExp(v)
    }
  }
  
  module.exports = Tagged
  
  },{"./utils":30,"bignumber.js":21,"url":155}],30:[function(require,module,exports){
  (function (process,Buffer){
  'use strict'
  
  const fs = require('fs')
  const stream = require('stream')
  const bignumber = require('bignumber.js')
  
  const constants = require('./constants')
  const NUMBYTES = constants.NUMBYTES, SHIFT32 = constants.SHIFT32
  const MAX_SAFE_HIGH = 0x1fffff
  
  exports.parseCBORint = function (ai, buf) {
    var f, g
    switch (ai) {
      case NUMBYTES.ONE:
        return buf.readUInt8(0, true)
      case NUMBYTES.TWO:
        return buf.readUInt16BE(0, true)
      case NUMBYTES.FOUR:
        return buf.readUInt32BE(0, true)
      case NUMBYTES.EIGHT:
        f = buf.readUInt32BE(0)
        g = buf.readUInt32BE(4)
        if (f > MAX_SAFE_HIGH) {
          return new bignumber(f).times(SHIFT32).plus(g)
        } else {
          return (f * SHIFT32) + g
        }
      default:
        throw new Error('Invalid additional info for int: ' + ai)
    }
  }
  
  exports.writeHalf = function writeHalf (buf, half) {
    // assume 0, -0, NaN, Infinity, and -Infinity have already been caught
  
    // HACK: everyone settle in.  This isn't going to be pretty.
    // Translate cn-cbor's C code (from Carsten Borman):
  
    // uint32_t be32;
    // uint16_t be16, u16;
    // union {
    //   float f;
    //   uint32_t u;
    // } u32;
    // u32.f = float_val;
  
    const u32 = new Buffer(4)
    u32.writeFloatBE(half)
    const u = u32.readUInt32BE()
  
    // if ((u32.u & 0x1FFF) == 0) { /* worth trying half */
  
    // hildjj: If the lower 13 bits are 0, we won't lose anything in the conversion
    if ((u & 0x1FFF) !== 0) {
      return false
    }
  
    //   int s16 = (u32.u >> 16) & 0x8000;
    //   int exp = (u32.u >> 23) & 0xff;
    //   int mant = u32.u & 0x7fffff;
  
    let s16 = (u >> 16) & 0x8000 // top bit is sign
    const exp = (u >> 23) & 0xff // then 5 bits of exponent
    const mant = u & 0x7fffff
  
    //   if (exp == 0 && mant == 0)
    //     ;              /* 0.0, -0.0 */
  
    // hildjj: zeros already handled.  Assert if you don't believe me.
  
    //   else if (exp >= 113 && exp <= 142) /* normalized */
    //     s16 += ((exp - 112) << 10) + (mant >> 13);
  
    if ((exp >= 113) && (exp <= 142)) {
      s16 += ((exp - 112) << 10) + (mant >> 13)
    }
  
    //   else if (exp >= 103 && exp < 113) { /* denorm, exp16 = 0 */
    //     if (mant & ((1 << (126 - exp)) - 1))
    //       goto float32;         /* loss of precision */
    //     s16 += ((mant + 0x800000) >> (126 - exp));
  
    else if ((exp >= 103) && (exp < 113)) {
      if (mant & ((1 << (126 - exp)) - 1)) {
        return false
      }
      s16 += ((mant + 0x800000) >> (126 - exp))
    }
  
    //   } else if (exp == 255 && mant == 0) { /* Inf */
    //     s16 += 0x7c00;
  
    // hildjj: Infinity already handled
  
    //   } else
    //     goto float32;           /* loss of range */
  
    else {
      return false
    }
  
    //   ensure_writable(3);
    //   u16 = s16;
    //   be16 = hton16p((const uint8_t*)&u16);
    buf.writeUInt16BE(s16)
    return true
  }
  
  exports.parseHalf = function parseHalf (buf) {
    var exp, mant, sign
    sign = buf[0] & 0x80 ? -1 : 1
    exp = (buf[0] & 0x7C) >> 2
    mant = ((buf[0] & 0x03) << 8) | buf[1]
    if (!exp) {
      return sign * 5.9604644775390625e-8 * mant
    } else if (exp === 0x1f) {
      return sign * (mant ? 0 / 0 : 2e308)
    } else {
      return sign * Math.pow(2, exp - 25) * (1024 + mant)
    }
  }
  
  exports.parseCBORfloat = function (buf) {
    switch (buf.length) {
      case 2:
        return exports.parseHalf(buf)
      case 4:
        return buf.readFloatBE(0, true)
      case 8:
        return buf.readDoubleBE(0, true)
      default:
        throw new Error('Invalid float size: ' + buf.length)
    }
  }
  
  exports.hex = function (s) {
    return new Buffer(s.replace(/^0x/, ''), 'hex')
  }
  
  exports.bin = function (s) {
    var chunks, end, start
    s = s.replace(/\s/g, '')
    start = 0
    end = (s.length % 8) || 8
    chunks = []
    while (end <= s.length) {
      chunks.push(parseInt(s.slice(start, end), 2))
      start = end
      end += 8
    }
    return new Buffer(chunks)
  }
  
  exports.extend = function () {
    var a, adds, j, k, len, old, v
    old = arguments[0], adds = 2 <= arguments.length ? Array.prototype.slice.call(arguments, 1) : []
    if (old == null) {
      old = {}
    }
    for (j = 0, len = adds.length; j < len; j++) {
      a = adds[j]
      for (k in a) {
        v = a[k]
        old[k] = v
      }
    }
    return old
  }
  
  exports.arrayEqual = function (a, b) {
    if ((a == null) && (b == null)) {
      return true
    }
    if ((a == null) || (b == null)) {
      return false
    }
    return (a.length === b.length) && a.every(function (elem, i) {
        return elem === b[i]
      })
  }
  
  exports.bufferEqual = function (a, b) {
    var byte, i, j, len, ret
    if ((a == null) && (b == null)) {
      return true
    }
    if ((a == null) || (b == null)) {
      return false
    }
    if (!(Buffer.isBuffer(a) && Buffer.isBuffer(b) && (a.length === b.length))) {
      return false
    }
    ret = true
    for (i = j = 0, len = a.length; j < len; i = ++j) {
      byte = a[i]
      ret &= b[i] === byte
    }
    return !!ret
  }
  
  exports.bufferToBignumber = function (buf) {
    return new bignumber(buf.toString('hex'), 16)
  }
  
  exports.DeHexStream = class DeHexStream extends stream.Readable {
    constructor (hex) {
      super()
      hex = hex.replace(/^0x/, '')
      if (hex) {
        this.push(new Buffer(hex, 'hex'))
      }
      this.push(null)
    }
  }
  
  exports.HexStream = class HexStream extends stream.Transform {
    constructor (options) {
      super(options)
    }
  
    _transform (fresh, encoding, cb) {
      this.push(fresh.toString('hex'))
      return cb()
    }
  }
  
  function printError (er) {
    if (er != null) {
      return console.log(er)
    }
  }
  
  exports.streamFiles = function (files, streamFunc, cb) {
    if (cb == null) {
      cb = printError
    }
    const f = files.shift()
    if (!f) {
      return cb()
    }
    const sf = streamFunc()
    sf.on('end', function () {
      return exports.streamFiles(files, streamFunc, cb)
    })
    sf.on('error', cb)
    const s = (f === '-') ? process.stdin : (f instanceof stream.Stream) ? f : fs.createReadStream(f)
    s.on('error', cb)
    return s.pipe(sf)
  }
  
  exports.guessEncoding = function (input) {
    switch (false) {
      case typeof input !== 'string':
        return 'hex'
      case !Buffer.isBuffer(input):
        return undefined
      default:
        throw new Error('Unknown input type')
    }
  }
  
  }).call(this,require('_process'),require("buffer").Buffer)
  },{"./constants":24,"_process":137,"bignumber.js":21,"buffer":129,"fs":127,"stream":153}],31:[function(require,module,exports){
  // Tweaked version of nathan7's binary-parse-stream
  // (see https://github.com/nathan7/binary-parse-stream)
  // Uses NoFilter instead of the readable in the original.  Removes
  // the ability to read -1, which was odd and un-needed.
  // License for binary-parse-stream: MIT
  
  'use strict';
  exports = module.exports = BinaryParseStream
  var Stream = require('stream')
    , TransformStream = Stream.Transform
    , inherits = require('util').inherits
    , NoFilter = require('nofilter')
  
  exports.One = -1
  
  inherits(BinaryParseStream, TransformStream)
  function BinaryParseStream(options) {
    TransformStream.call(this, options)
    this._writableState.objectMode = false
    this._readableState.objectMode = true
  
    this.bs = new NoFilter()
    this.__restart()
  }
  
  BinaryParseStream.prototype._transform = function(fresh, encoding, cb) { var self = this
    this.bs.write(fresh)
  
    while (this.bs.length >= this.__needed) {
      var ret
        , chunk = this.__needed === null
          ? undefined
          : this.bs.read(this.__needed)
  
      try { ret = this.__parser.next(chunk) }
      catch (e) {
        return cb(e) }
  
      if (this.__needed)
        this.__fresh = false
  
      if (!ret.done)
        this.__needed = ret.value | 0
      else {
        this.push(ret.value)
        this.__restart()
      }
    }
  
    return cb()
  }
  
  BinaryParseStream.prototype.__restart = function() {
    this.__needed = null
    this.__parser = this._parse()
    this.__fresh = true
  }
  
  BinaryParseStream.prototype._flush = function(cb) {
    cb(this.__fresh
      ? null
      : new Error('unexpected end of input'))
  }
  
  },{"nofilter":98,"stream":153,"util":160}],32:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var BlockCipher = C_lib.BlockCipher;
  	    var C_algo = C.algo;
  
  	    // Lookup tables
  	    var SBOX = [];
  	    var INV_SBOX = [];
  	    var SUB_MIX_0 = [];
  	    var SUB_MIX_1 = [];
  	    var SUB_MIX_2 = [];
  	    var SUB_MIX_3 = [];
  	    var INV_SUB_MIX_0 = [];
  	    var INV_SUB_MIX_1 = [];
  	    var INV_SUB_MIX_2 = [];
  	    var INV_SUB_MIX_3 = [];
  
  	    // Compute lookup tables
  	    (function () {
  	        // Compute double table
  	        var d = [];
  	        for (var i = 0; i < 256; i++) {
  	            if (i < 128) {
  	                d[i] = i << 1;
  	            } else {
  	                d[i] = (i << 1) ^ 0x11b;
  	            }
  	        }
  
  	        // Walk GF(2^8)
  	        var x = 0;
  	        var xi = 0;
  	        for (var i = 0; i < 256; i++) {
  	            // Compute sbox
  	            var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
  	            sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
  	            SBOX[x] = sx;
  	            INV_SBOX[sx] = x;
  
  	            // Compute multiplication
  	            var x2 = d[x];
  	            var x4 = d[x2];
  	            var x8 = d[x4];
  
  	            // Compute sub bytes, mix columns tables
  	            var t = (d[sx] * 0x101) ^ (sx * 0x1010100);
  	            SUB_MIX_0[x] = (t << 24) | (t >>> 8);
  	            SUB_MIX_1[x] = (t << 16) | (t >>> 16);
  	            SUB_MIX_2[x] = (t << 8)  | (t >>> 24);
  	            SUB_MIX_3[x] = t;
  
  	            // Compute inv sub bytes, inv mix columns tables
  	            var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
  	            INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8);
  	            INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16);
  	            INV_SUB_MIX_2[sx] = (t << 8)  | (t >>> 24);
  	            INV_SUB_MIX_3[sx] = t;
  
  	            // Compute next counter
  	            if (!x) {
  	                x = xi = 1;
  	            } else {
  	                x = x2 ^ d[d[d[x8 ^ x2]]];
  	                xi ^= d[d[xi]];
  	            }
  	        }
  	    }());
  
  	    // Precomputed Rcon lookup
  	    var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
  
  	    /**
  	     * AES block cipher algorithm.
  	     */
  	    var AES = C_algo.AES = BlockCipher.extend({
  	        _doReset: function () {
  	            // Skip reset of nRounds has been set before and key did not change
  	            if (this._nRounds && this._keyPriorReset === this._key) {
  	                return;
  	            }
  
  	            // Shortcuts
  	            var key = this._keyPriorReset = this._key;
  	            var keyWords = key.words;
  	            var keySize = key.sigBytes / 4;
  
  	            // Compute number of rounds
  	            var nRounds = this._nRounds = keySize + 6;
  
  	            // Compute number of key schedule rows
  	            var ksRows = (nRounds + 1) * 4;
  
  	            // Compute key schedule
  	            var keySchedule = this._keySchedule = [];
  	            for (var ksRow = 0; ksRow < ksRows; ksRow++) {
  	                if (ksRow < keySize) {
  	                    keySchedule[ksRow] = keyWords[ksRow];
  	                } else {
  	                    var t = keySchedule[ksRow - 1];
  
  	                    if (!(ksRow % keySize)) {
  	                        // Rot word
  	                        t = (t << 8) | (t >>> 24);
  
  	                        // Sub word
  	                        t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
  
  	                        // Mix Rcon
  	                        t ^= RCON[(ksRow / keySize) | 0] << 24;
  	                    } else if (keySize > 6 && ksRow % keySize == 4) {
  	                        // Sub word
  	                        t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
  	                    }
  
  	                    keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t;
  	                }
  	            }
  
  	            // Compute inv key schedule
  	            var invKeySchedule = this._invKeySchedule = [];
  	            for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) {
  	                var ksRow = ksRows - invKsRow;
  
  	                if (invKsRow % 4) {
  	                    var t = keySchedule[ksRow];
  	                } else {
  	                    var t = keySchedule[ksRow - 4];
  	                }
  
  	                if (invKsRow < 4 || ksRow <= 4) {
  	                    invKeySchedule[invKsRow] = t;
  	                } else {
  	                    invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^
  	                                               INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]];
  	                }
  	            }
  	        },
  
  	        encryptBlock: function (M, offset) {
  	            this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX);
  	        },
  
  	        decryptBlock: function (M, offset) {
  	            // Swap 2nd and 4th rows
  	            var t = M[offset + 1];
  	            M[offset + 1] = M[offset + 3];
  	            M[offset + 3] = t;
  
  	            this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX);
  
  	            // Inv swap 2nd and 4th rows
  	            var t = M[offset + 1];
  	            M[offset + 1] = M[offset + 3];
  	            M[offset + 3] = t;
  	        },
  
  	        _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {
  	            // Shortcut
  	            var nRounds = this._nRounds;
  
  	            // Get input, add round key
  	            var s0 = M[offset]     ^ keySchedule[0];
  	            var s1 = M[offset + 1] ^ keySchedule[1];
  	            var s2 = M[offset + 2] ^ keySchedule[2];
  	            var s3 = M[offset + 3] ^ keySchedule[3];
  
  	            // Key schedule row counter
  	            var ksRow = 4;
  
  	            // Rounds
  	            for (var round = 1; round < nRounds; round++) {
  	                // Shift rows, sub bytes, mix columns, add round key
  	                var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++];
  	                var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++];
  	                var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++];
  	                var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++];
  
  	                // Update state
  	                s0 = t0;
  	                s1 = t1;
  	                s2 = t2;
  	                s3 = t3;
  	            }
  
  	            // Shift rows, sub bytes, add round key
  	            var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++];
  	            var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++];
  	            var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++];
  	            var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++];
  
  	            // Set output
  	            M[offset]     = t0;
  	            M[offset + 1] = t1;
  	            M[offset + 2] = t2;
  	            M[offset + 3] = t3;
  	        },
  
  	        keySize: 256/32
  	    });
  
  	    /**
  	     * Shortcut functions to the cipher's object interface.
  	     *
  	     * @example
  	     *
  	     *     var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);
  	     *     var plaintext  = CryptoJS.AES.decrypt(ciphertext, key, cfg);
  	     */
  	    C.AES = BlockCipher._createHelper(AES);
  	}());
  
  
  	return CryptoJS.AES;
  
  }));
  },{"./cipher-core":33,"./core":34,"./enc-base64":35,"./evpkdf":37,"./md5":42}],33:[function(require,module,exports){
  ;(function (root, factory) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	/**
  	 * Cipher core components.
  	 */
  	CryptoJS.lib.Cipher || (function (undefined) {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var Base = C_lib.Base;
  	    var WordArray = C_lib.WordArray;
  	    var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm;
  	    var C_enc = C.enc;
  	    var Utf8 = C_enc.Utf8;
  	    var Base64 = C_enc.Base64;
  	    var C_algo = C.algo;
  	    var EvpKDF = C_algo.EvpKDF;
  
  	    /**
  	     * Abstract base cipher template.
  	     *
  	     * @property {number} keySize This cipher's key size. Default: 4 (128 bits)
  	     * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits)
  	     * @property {number} _ENC_XFORM_MODE A constant representing encryption mode.
  	     * @property {number} _DEC_XFORM_MODE A constant representing decryption mode.
  	     */
  	    var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({
  	        /**
  	         * Configuration options.
  	         *
  	         * @property {WordArray} iv The IV to use for this operation.
  	         */
  	        cfg: Base.extend(),
  
  	        /**
  	         * Creates this cipher in encryption mode.
  	         *
  	         * @param {WordArray} key The key.
  	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
  	         *
  	         * @return {Cipher} A cipher instance.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray });
  	         */
  	        createEncryptor: function (key, cfg) {
  	            return this.create(this._ENC_XFORM_MODE, key, cfg);
  	        },
  
  	        /**
  	         * Creates this cipher in decryption mode.
  	         *
  	         * @param {WordArray} key The key.
  	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
  	         *
  	         * @return {Cipher} A cipher instance.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray });
  	         */
  	        createDecryptor: function (key, cfg) {
  	            return this.create(this._DEC_XFORM_MODE, key, cfg);
  	        },
  
  	        /**
  	         * Initializes a newly created cipher.
  	         *
  	         * @param {number} xformMode Either the encryption or decryption transormation mode constant.
  	         * @param {WordArray} key The key.
  	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
  	         *
  	         * @example
  	         *
  	         *     var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray });
  	         */
  	        init: function (xformMode, key, cfg) {
  	            // Apply config defaults
  	            this.cfg = this.cfg.extend(cfg);
  
  	            // Store transform mode and key
  	            this._xformMode = xformMode;
  	            this._key = key;
  
  	            // Set initial values
  	            this.reset();
  	        },
  
  	        /**
  	         * Resets this cipher to its initial state.
  	         *
  	         * @example
  	         *
  	         *     cipher.reset();
  	         */
  	        reset: function () {
  	            // Reset data buffer
  	            BufferedBlockAlgorithm.reset.call(this);
  
  	            // Perform concrete-cipher logic
  	            this._doReset();
  	        },
  
  	        /**
  	         * Adds data to be encrypted or decrypted.
  	         *
  	         * @param {WordArray|string} dataUpdate The data to encrypt or decrypt.
  	         *
  	         * @return {WordArray} The data after processing.
  	         *
  	         * @example
  	         *
  	         *     var encrypted = cipher.process('data');
  	         *     var encrypted = cipher.process(wordArray);
  	         */
  	        process: function (dataUpdate) {
  	            // Append
  	            this._append(dataUpdate);
  
  	            // Process available blocks
  	            return this._process();
  	        },
  
  	        /**
  	         * Finalizes the encryption or decryption process.
  	         * Note that the finalize operation is effectively a destructive, read-once operation.
  	         *
  	         * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt.
  	         *
  	         * @return {WordArray} The data after final processing.
  	         *
  	         * @example
  	         *
  	         *     var encrypted = cipher.finalize();
  	         *     var encrypted = cipher.finalize('data');
  	         *     var encrypted = cipher.finalize(wordArray);
  	         */
  	        finalize: function (dataUpdate) {
  	            // Final data update
  	            if (dataUpdate) {
  	                this._append(dataUpdate);
  	            }
  
  	            // Perform concrete-cipher logic
  	            var finalProcessedData = this._doFinalize();
  
  	            return finalProcessedData;
  	        },
  
  	        keySize: 128/32,
  
  	        ivSize: 128/32,
  
  	        _ENC_XFORM_MODE: 1,
  
  	        _DEC_XFORM_MODE: 2,
  
  	        /**
  	         * Creates shortcut functions to a cipher's object interface.
  	         *
  	         * @param {Cipher} cipher The cipher to create a helper for.
  	         *
  	         * @return {Object} An object with encrypt and decrypt shortcut functions.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES);
  	         */
  	        _createHelper: (function () {
  	            function selectCipherStrategy(key) {
  	                if (typeof key == 'string') {
  	                    return PasswordBasedCipher;
  	                } else {
  	                    return SerializableCipher;
  	                }
  	            }
  
  	            return function (cipher) {
  	                return {
  	                    encrypt: function (message, key, cfg) {
  	                        return selectCipherStrategy(key).encrypt(cipher, message, key, cfg);
  	                    },
  
  	                    decrypt: function (ciphertext, key, cfg) {
  	                        return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg);
  	                    }
  	                };
  	            };
  	        }())
  	    });
  
  	    /**
  	     * Abstract base stream cipher template.
  	     *
  	     * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
  	     */
  	    var StreamCipher = C_lib.StreamCipher = Cipher.extend({
  	        _doFinalize: function () {
  	            // Process partial blocks
  	            var finalProcessedBlocks = this._process(!!'flush');
  
  	            return finalProcessedBlocks;
  	        },
  
  	        blockSize: 1
  	    });
  
  	    /**
  	     * Mode namespace.
  	     */
  	    var C_mode = C.mode = {};
  
  	    /**
  	     * Abstract base block cipher mode template.
  	     */
  	    var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({
  	        /**
  	         * Creates this mode for encryption.
  	         *
  	         * @param {Cipher} cipher A block cipher instance.
  	         * @param {Array} iv The IV words.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
  	         */
  	        createEncryptor: function (cipher, iv) {
  	            return this.Encryptor.create(cipher, iv);
  	        },
  
  	        /**
  	         * Creates this mode for decryption.
  	         *
  	         * @param {Cipher} cipher A block cipher instance.
  	         * @param {Array} iv The IV words.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words);
  	         */
  	        createDecryptor: function (cipher, iv) {
  	            return this.Decryptor.create(cipher, iv);
  	        },
  
  	        /**
  	         * Initializes a newly created mode.
  	         *
  	         * @param {Cipher} cipher A block cipher instance.
  	         * @param {Array} iv The IV words.
  	         *
  	         * @example
  	         *
  	         *     var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words);
  	         */
  	        init: function (cipher, iv) {
  	            this._cipher = cipher;
  	            this._iv = iv;
  	        }
  	    });
  
  	    /**
  	     * Cipher Block Chaining mode.
  	     */
  	    var CBC = C_mode.CBC = (function () {
  	        /**
  	         * Abstract base CBC mode.
  	         */
  	        var CBC = BlockCipherMode.extend();
  
  	        /**
  	         * CBC encryptor.
  	         */
  	        CBC.Encryptor = CBC.extend({
  	            /**
  	             * Processes the data block at offset.
  	             *
  	             * @param {Array} words The data words to operate on.
  	             * @param {number} offset The offset where the block starts.
  	             *
  	             * @example
  	             *
  	             *     mode.processBlock(data.words, offset);
  	             */
  	            processBlock: function (words, offset) {
  	                // Shortcuts
  	                var cipher = this._cipher;
  	                var blockSize = cipher.blockSize;
  
  	                // XOR and encrypt
  	                xorBlock.call(this, words, offset, blockSize);
  	                cipher.encryptBlock(words, offset);
  
  	                // Remember this block to use with next block
  	                this._prevBlock = words.slice(offset, offset + blockSize);
  	            }
  	        });
  
  	        /**
  	         * CBC decryptor.
  	         */
  	        CBC.Decryptor = CBC.extend({
  	            /**
  	             * Processes the data block at offset.
  	             *
  	             * @param {Array} words The data words to operate on.
  	             * @param {number} offset The offset where the block starts.
  	             *
  	             * @example
  	             *
  	             *     mode.processBlock(data.words, offset);
  	             */
  	            processBlock: function (words, offset) {
  	                // Shortcuts
  	                var cipher = this._cipher;
  	                var blockSize = cipher.blockSize;
  
  	                // Remember this block to use with next block
  	                var thisBlock = words.slice(offset, offset + blockSize);
  
  	                // Decrypt and XOR
  	                cipher.decryptBlock(words, offset);
  	                xorBlock.call(this, words, offset, blockSize);
  
  	                // This block becomes the previous block
  	                this._prevBlock = thisBlock;
  	            }
  	        });
  
  	        function xorBlock(words, offset, blockSize) {
  	            // Shortcut
  	            var iv = this._iv;
  
  	            // Choose mixing block
  	            if (iv) {
  	                var block = iv;
  
  	                // Remove IV for subsequent blocks
  	                this._iv = undefined;
  	            } else {
  	                var block = this._prevBlock;
  	            }
  
  	            // XOR blocks
  	            for (var i = 0; i < blockSize; i++) {
  	                words[offset + i] ^= block[i];
  	            }
  	        }
  
  	        return CBC;
  	    }());
  
  	    /**
  	     * Padding namespace.
  	     */
  	    var C_pad = C.pad = {};
  
  	    /**
  	     * PKCS #5/7 padding strategy.
  	     */
  	    var Pkcs7 = C_pad.Pkcs7 = {
  	        /**
  	         * Pads data using the algorithm defined in PKCS #5/7.
  	         *
  	         * @param {WordArray} data The data to pad.
  	         * @param {number} blockSize The multiple that the data should be padded to.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     CryptoJS.pad.Pkcs7.pad(wordArray, 4);
  	         */
  	        pad: function (data, blockSize) {
  	            // Shortcut
  	            var blockSizeBytes = blockSize * 4;
  
  	            // Count padding bytes
  	            var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;
  
  	            // Create padding word
  	            var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes;
  
  	            // Create padding
  	            var paddingWords = [];
  	            for (var i = 0; i < nPaddingBytes; i += 4) {
  	                paddingWords.push(paddingWord);
  	            }
  	            var padding = WordArray.create(paddingWords, nPaddingBytes);
  
  	            // Add padding
  	            data.concat(padding);
  	        },
  
  	        /**
  	         * Unpads data that had been padded using the algorithm defined in PKCS #5/7.
  	         *
  	         * @param {WordArray} data The data to unpad.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     CryptoJS.pad.Pkcs7.unpad(wordArray);
  	         */
  	        unpad: function (data) {
  	            // Get number of padding bytes from last byte
  	            var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
  
  	            // Remove padding
  	            data.sigBytes -= nPaddingBytes;
  	        }
  	    };
  
  	    /**
  	     * Abstract base block cipher template.
  	     *
  	     * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
  	     */
  	    var BlockCipher = C_lib.BlockCipher = Cipher.extend({
  	        /**
  	         * Configuration options.
  	         *
  	         * @property {Mode} mode The block mode to use. Default: CBC
  	         * @property {Padding} padding The padding strategy to use. Default: Pkcs7
  	         */
  	        cfg: Cipher.cfg.extend({
  	            mode: CBC,
  	            padding: Pkcs7
  	        }),
  
  	        reset: function () {
  	            // Reset cipher
  	            Cipher.reset.call(this);
  
  	            // Shortcuts
  	            var cfg = this.cfg;
  	            var iv = cfg.iv;
  	            var mode = cfg.mode;
  
  	            // Reset block mode
  	            if (this._xformMode == this._ENC_XFORM_MODE) {
  	                var modeCreator = mode.createEncryptor;
  	            } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
  	                var modeCreator = mode.createDecryptor;
  
  	                // Keep at least one block in the buffer for unpadding
  	                this._minBufferSize = 1;
  	            }
  	            this._mode = modeCreator.call(mode, this, iv && iv.words);
  	        },
  
  	        _doProcessBlock: function (words, offset) {
  	            this._mode.processBlock(words, offset);
  	        },
  
  	        _doFinalize: function () {
  	            // Shortcut
  	            var padding = this.cfg.padding;
  
  	            // Finalize
  	            if (this._xformMode == this._ENC_XFORM_MODE) {
  	                // Pad data
  	                padding.pad(this._data, this.blockSize);
  
  	                // Process final blocks
  	                var finalProcessedBlocks = this._process(!!'flush');
  	            } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
  	                // Process final blocks
  	                var finalProcessedBlocks = this._process(!!'flush');
  
  	                // Unpad data
  	                padding.unpad(finalProcessedBlocks);
  	            }
  
  	            return finalProcessedBlocks;
  	        },
  
  	        blockSize: 128/32
  	    });
  
  	    /**
  	     * A collection of cipher parameters.
  	     *
  	     * @property {WordArray} ciphertext The raw ciphertext.
  	     * @property {WordArray} key The key to this ciphertext.
  	     * @property {WordArray} iv The IV used in the ciphering operation.
  	     * @property {WordArray} salt The salt used with a key derivation function.
  	     * @property {Cipher} algorithm The cipher algorithm.
  	     * @property {Mode} mode The block mode used in the ciphering operation.
  	     * @property {Padding} padding The padding scheme used in the ciphering operation.
  	     * @property {number} blockSize The block size of the cipher.
  	     * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string.
  	     */
  	    var CipherParams = C_lib.CipherParams = Base.extend({
  	        /**
  	         * Initializes a newly created cipher params object.
  	         *
  	         * @param {Object} cipherParams An object with any of the possible cipher parameters.
  	         *
  	         * @example
  	         *
  	         *     var cipherParams = CryptoJS.lib.CipherParams.create({
  	         *         ciphertext: ciphertextWordArray,
  	         *         key: keyWordArray,
  	         *         iv: ivWordArray,
  	         *         salt: saltWordArray,
  	         *         algorithm: CryptoJS.algo.AES,
  	         *         mode: CryptoJS.mode.CBC,
  	         *         padding: CryptoJS.pad.PKCS7,
  	         *         blockSize: 4,
  	         *         formatter: CryptoJS.format.OpenSSL
  	         *     });
  	         */
  	        init: function (cipherParams) {
  	            this.mixIn(cipherParams);
  	        },
  
  	        /**
  	         * Converts this cipher params object to a string.
  	         *
  	         * @param {Format} formatter (Optional) The formatting strategy to use.
  	         *
  	         * @return {string} The stringified cipher params.
  	         *
  	         * @throws Error If neither the formatter nor the default formatter is set.
  	         *
  	         * @example
  	         *
  	         *     var string = cipherParams + '';
  	         *     var string = cipherParams.toString();
  	         *     var string = cipherParams.toString(CryptoJS.format.OpenSSL);
  	         */
  	        toString: function (formatter) {
  	            return (formatter || this.formatter).stringify(this);
  	        }
  	    });
  
  	    /**
  	     * Format namespace.
  	     */
  	    var C_format = C.format = {};
  
  	    /**
  	     * OpenSSL formatting strategy.
  	     */
  	    var OpenSSLFormatter = C_format.OpenSSL = {
  	        /**
  	         * Converts a cipher params object to an OpenSSL-compatible string.
  	         *
  	         * @param {CipherParams} cipherParams The cipher params object.
  	         *
  	         * @return {string} The OpenSSL-compatible string.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams);
  	         */
  	        stringify: function (cipherParams) {
  	            // Shortcuts
  	            var ciphertext = cipherParams.ciphertext;
  	            var salt = cipherParams.salt;
  
  	            // Format
  	            if (salt) {
  	                var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);
  	            } else {
  	                var wordArray = ciphertext;
  	            }
  
  	            return wordArray.toString(Base64);
  	        },
  
  	        /**
  	         * Converts an OpenSSL-compatible string to a cipher params object.
  	         *
  	         * @param {string} openSSLStr The OpenSSL-compatible string.
  	         *
  	         * @return {CipherParams} The cipher params object.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString);
  	         */
  	        parse: function (openSSLStr) {
  	            // Parse base64
  	            var ciphertext = Base64.parse(openSSLStr);
  
  	            // Shortcut
  	            var ciphertextWords = ciphertext.words;
  
  	            // Test for salt
  	            if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) {
  	                // Extract salt
  	                var salt = WordArray.create(ciphertextWords.slice(2, 4));
  
  	                // Remove salt from ciphertext
  	                ciphertextWords.splice(0, 4);
  	                ciphertext.sigBytes -= 16;
  	            }
  
  	            return CipherParams.create({ ciphertext: ciphertext, salt: salt });
  	        }
  	    };
  
  	    /**
  	     * A cipher wrapper that returns ciphertext as a serializable cipher params object.
  	     */
  	    var SerializableCipher = C_lib.SerializableCipher = Base.extend({
  	        /**
  	         * Configuration options.
  	         *
  	         * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL
  	         */
  	        cfg: Base.extend({
  	            format: OpenSSLFormatter
  	        }),
  
  	        /**
  	         * Encrypts a message.
  	         *
  	         * @param {Cipher} cipher The cipher algorithm to use.
  	         * @param {WordArray|string} message The message to encrypt.
  	         * @param {WordArray} key The key.
  	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
  	         *
  	         * @return {CipherParams} A cipher params object.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key);
  	         *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
  	         *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
  	         */
  	        encrypt: function (cipher, message, key, cfg) {
  	            // Apply config defaults
  	            cfg = this.cfg.extend(cfg);
  
  	            // Encrypt
  	            var encryptor = cipher.createEncryptor(key, cfg);
  	            var ciphertext = encryptor.finalize(message);
  
  	            // Shortcut
  	            var cipherCfg = encryptor.cfg;
  
  	            // Create and return serializable cipher params
  	            return CipherParams.create({
  	                ciphertext: ciphertext,
  	                key: key,
  	                iv: cipherCfg.iv,
  	                algorithm: cipher,
  	                mode: cipherCfg.mode,
  	                padding: cipherCfg.padding,
  	                blockSize: cipher.blockSize,
  	                formatter: cfg.format
  	            });
  	        },
  
  	        /**
  	         * Decrypts serialized ciphertext.
  	         *
  	         * @param {Cipher} cipher The cipher algorithm to use.
  	         * @param {CipherParams|string} ciphertext The ciphertext to decrypt.
  	         * @param {WordArray} key The key.
  	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
  	         *
  	         * @return {WordArray} The plaintext.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL });
  	         *     var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL });
  	         */
  	        decrypt: function (cipher, ciphertext, key, cfg) {
  	            // Apply config defaults
  	            cfg = this.cfg.extend(cfg);
  
  	            // Convert string to CipherParams
  	            ciphertext = this._parse(ciphertext, cfg.format);
  
  	            // Decrypt
  	            var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext);
  
  	            return plaintext;
  	        },
  
  	        /**
  	         * Converts serialized ciphertext to CipherParams,
  	         * else assumed CipherParams already and returns ciphertext unchanged.
  	         *
  	         * @param {CipherParams|string} ciphertext The ciphertext.
  	         * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext.
  	         *
  	         * @return {CipherParams} The unserialized ciphertext.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format);
  	         */
  	        _parse: function (ciphertext, format) {
  	            if (typeof ciphertext == 'string') {
  	                return format.parse(ciphertext, this);
  	            } else {
  	                return ciphertext;
  	            }
  	        }
  	    });
  
  	    /**
  	     * Key derivation function namespace.
  	     */
  	    var C_kdf = C.kdf = {};
  
  	    /**
  	     * OpenSSL key derivation function.
  	     */
  	    var OpenSSLKdf = C_kdf.OpenSSL = {
  	        /**
  	         * Derives a key and IV from a password.
  	         *
  	         * @param {string} password The password to derive from.
  	         * @param {number} keySize The size in words of the key to generate.
  	         * @param {number} ivSize The size in words of the IV to generate.
  	         * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly.
  	         *
  	         * @return {CipherParams} A cipher params object with the key, IV, and salt.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
  	         *     var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
  	         */
  	        execute: function (password, keySize, ivSize, salt) {
  	            // Generate random salt
  	            if (!salt) {
  	                salt = WordArray.random(64/8);
  	            }
  
  	            // Derive key and IV
  	            var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
  
  	            // Separate key and IV
  	            var iv = WordArray.create(key.words.slice(keySize), ivSize * 4);
  	            key.sigBytes = keySize * 4;
  
  	            // Return params
  	            return CipherParams.create({ key: key, iv: iv, salt: salt });
  	        }
  	    };
  
  	    /**
  	     * A serializable cipher wrapper that derives the key from a password,
  	     * and returns ciphertext as a serializable cipher params object.
  	     */
  	    var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({
  	        /**
  	         * Configuration options.
  	         *
  	         * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL
  	         */
  	        cfg: SerializableCipher.cfg.extend({
  	            kdf: OpenSSLKdf
  	        }),
  
  	        /**
  	         * Encrypts a message using a password.
  	         *
  	         * @param {Cipher} cipher The cipher algorithm to use.
  	         * @param {WordArray|string} message The message to encrypt.
  	         * @param {string} password The password.
  	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
  	         *
  	         * @return {CipherParams} A cipher params object.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password');
  	         *     var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
  	         */
  	        encrypt: function (cipher, message, password, cfg) {
  	            // Apply config defaults
  	            cfg = this.cfg.extend(cfg);
  
  	            // Derive key and other params
  	            var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize);
  
  	            // Add IV to config
  	            cfg.iv = derivedParams.iv;
  
  	            // Encrypt
  	            var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg);
  
  	            // Mix in derived params
  	            ciphertext.mixIn(derivedParams);
  
  	            return ciphertext;
  	        },
  
  	        /**
  	         * Decrypts serialized ciphertext using a password.
  	         *
  	         * @param {Cipher} cipher The cipher algorithm to use.
  	         * @param {CipherParams|string} ciphertext The ciphertext to decrypt.
  	         * @param {string} password The password.
  	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
  	         *
  	         * @return {WordArray} The plaintext.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL });
  	         *     var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL });
  	         */
  	        decrypt: function (cipher, ciphertext, password, cfg) {
  	            // Apply config defaults
  	            cfg = this.cfg.extend(cfg);
  
  	            // Convert string to CipherParams
  	            ciphertext = this._parse(ciphertext, cfg.format);
  
  	            // Derive key and other params
  	            var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt);
  
  	            // Add IV to config
  	            cfg.iv = derivedParams.iv;
  
  	            // Decrypt
  	            var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg);
  
  	            return plaintext;
  	        }
  	    });
  	}());
  
  
  }));
  },{"./core":34}],34:[function(require,module,exports){
  ;(function (root, factory) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory();
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define([], factory);
  	}
  	else {
  		// Global (browser)
  		root.CryptoJS = factory();
  	}
  }(this, function () {
  
  	/**
  	 * CryptoJS core components.
  	 */
  	var CryptoJS = CryptoJS || (function (Math, undefined) {
  	    /*
  	     * Local polyfil of Object.create
  	     */
  	    var create = Object.create || (function () {
  	        function F() {};
  
  	        return function (obj) {
  	            var subtype;
  
  	            F.prototype = obj;
  
  	            subtype = new F();
  
  	            F.prototype = null;
  
  	            return subtype;
  	        };
  	    }())
  
  	    /**
  	     * CryptoJS namespace.
  	     */
  	    var C = {};
  
  	    /**
  	     * Library namespace.
  	     */
  	    var C_lib = C.lib = {};
  
  	    /**
  	     * Base object for prototypal inheritance.
  	     */
  	    var Base = C_lib.Base = (function () {
  
  
  	        return {
  	            /**
  	             * Creates a new object that inherits from this object.
  	             *
  	             * @param {Object} overrides Properties to copy into the new object.
  	             *
  	             * @return {Object} The new object.
  	             *
  	             * @static
  	             *
  	             * @example
  	             *
  	             *     var MyType = CryptoJS.lib.Base.extend({
  	             *         field: 'value',
  	             *
  	             *         method: function () {
  	             *         }
  	             *     });
  	             */
  	            extend: function (overrides) {
  	                // Spawn
  	                var subtype = create(this);
  
  	                // Augment
  	                if (overrides) {
  	                    subtype.mixIn(overrides);
  	                }
  
  	                // Create default initializer
  	                if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {
  	                    subtype.init = function () {
  	                        subtype.$super.init.apply(this, arguments);
  	                    };
  	                }
  
  	                // Initializer's prototype is the subtype object
  	                subtype.init.prototype = subtype;
  
  	                // Reference supertype
  	                subtype.$super = this;
  
  	                return subtype;
  	            },
  
  	            /**
  	             * Extends this object and runs the init method.
  	             * Arguments to create() will be passed to init().
  	             *
  	             * @return {Object} The new object.
  	             *
  	             * @static
  	             *
  	             * @example
  	             *
  	             *     var instance = MyType.create();
  	             */
  	            create: function () {
  	                var instance = this.extend();
  	                instance.init.apply(instance, arguments);
  
  	                return instance;
  	            },
  
  	            /**
  	             * Initializes a newly created object.
  	             * Override this method to add some logic when your objects are created.
  	             *
  	             * @example
  	             *
  	             *     var MyType = CryptoJS.lib.Base.extend({
  	             *         init: function () {
  	             *             // ...
  	             *         }
  	             *     });
  	             */
  	            init: function () {
  	            },
  
  	            /**
  	             * Copies properties into this object.
  	             *
  	             * @param {Object} properties The properties to mix in.
  	             *
  	             * @example
  	             *
  	             *     MyType.mixIn({
  	             *         field: 'value'
  	             *     });
  	             */
  	            mixIn: function (properties) {
  	                for (var propertyName in properties) {
  	                    if (properties.hasOwnProperty(propertyName)) {
  	                        this[propertyName] = properties[propertyName];
  	                    }
  	                }
  
  	                // IE won't copy toString using the loop above
  	                if (properties.hasOwnProperty('toString')) {
  	                    this.toString = properties.toString;
  	                }
  	            },
  
  	            /**
  	             * Creates a copy of this object.
  	             *
  	             * @return {Object} The clone.
  	             *
  	             * @example
  	             *
  	             *     var clone = instance.clone();
  	             */
  	            clone: function () {
  	                return this.init.prototype.extend(this);
  	            }
  	        };
  	    }());
  
  	    /**
  	     * An array of 32-bit words.
  	     *
  	     * @property {Array} words The array of 32-bit words.
  	     * @property {number} sigBytes The number of significant bytes in this word array.
  	     */
  	    var WordArray = C_lib.WordArray = Base.extend({
  	        /**
  	         * Initializes a newly created word array.
  	         *
  	         * @param {Array} words (Optional) An array of 32-bit words.
  	         * @param {number} sigBytes (Optional) The number of significant bytes in the words.
  	         *
  	         * @example
  	         *
  	         *     var wordArray = CryptoJS.lib.WordArray.create();
  	         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
  	         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
  	         */
  	        init: function (words, sigBytes) {
  	            words = this.words = words || [];
  
  	            if (sigBytes != undefined) {
  	                this.sigBytes = sigBytes;
  	            } else {
  	                this.sigBytes = words.length * 4;
  	            }
  	        },
  
  	        /**
  	         * Converts this word array to a string.
  	         *
  	         * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
  	         *
  	         * @return {string} The stringified word array.
  	         *
  	         * @example
  	         *
  	         *     var string = wordArray + '';
  	         *     var string = wordArray.toString();
  	         *     var string = wordArray.toString(CryptoJS.enc.Utf8);
  	         */
  	        toString: function (encoder) {
  	            return (encoder || Hex).stringify(this);
  	        },
  
  	        /**
  	         * Concatenates a word array to this word array.
  	         *
  	         * @param {WordArray} wordArray The word array to append.
  	         *
  	         * @return {WordArray} This word array.
  	         *
  	         * @example
  	         *
  	         *     wordArray1.concat(wordArray2);
  	         */
  	        concat: function (wordArray) {
  	            // Shortcuts
  	            var thisWords = this.words;
  	            var thatWords = wordArray.words;
  	            var thisSigBytes = this.sigBytes;
  	            var thatSigBytes = wordArray.sigBytes;
  
  	            // Clamp excess bits
  	            this.clamp();
  
  	            // Concat
  	            if (thisSigBytes % 4) {
  	                // Copy one byte at a time
  	                for (var i = 0; i < thatSigBytes; i++) {
  	                    var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
  	                    thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
  	                }
  	            } else {
  	                // Copy one word at a time
  	                for (var i = 0; i < thatSigBytes; i += 4) {
  	                    thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
  	                }
  	            }
  	            this.sigBytes += thatSigBytes;
  
  	            // Chainable
  	            return this;
  	        },
  
  	        /**
  	         * Removes insignificant bits.
  	         *
  	         * @example
  	         *
  	         *     wordArray.clamp();
  	         */
  	        clamp: function () {
  	            // Shortcuts
  	            var words = this.words;
  	            var sigBytes = this.sigBytes;
  
  	            // Clamp
  	            words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
  	            words.length = Math.ceil(sigBytes / 4);
  	        },
  
  	        /**
  	         * Creates a copy of this word array.
  	         *
  	         * @return {WordArray} The clone.
  	         *
  	         * @example
  	         *
  	         *     var clone = wordArray.clone();
  	         */
  	        clone: function () {
  	            var clone = Base.clone.call(this);
  	            clone.words = this.words.slice(0);
  
  	            return clone;
  	        },
  
  	        /**
  	         * Creates a word array filled with random bytes.
  	         *
  	         * @param {number} nBytes The number of random bytes to generate.
  	         *
  	         * @return {WordArray} The random word array.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var wordArray = CryptoJS.lib.WordArray.random(16);
  	         */
  	        random: function (nBytes) {
  	            var words = [];
  
  	            var r = (function (m_w) {
  	                var m_w = m_w;
  	                var m_z = 0x3ade68b1;
  	                var mask = 0xffffffff;
  
  	                return function () {
  	                    m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask;
  	                    m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask;
  	                    var result = ((m_z << 0x10) + m_w) & mask;
  	                    result /= 0x100000000;
  	                    result += 0.5;
  	                    return result * (Math.random() > .5 ? 1 : -1);
  	                }
  	            });
  
  	            for (var i = 0, rcache; i < nBytes; i += 4) {
  	                var _r = r((rcache || Math.random()) * 0x100000000);
  
  	                rcache = _r() * 0x3ade67b7;
  	                words.push((_r() * 0x100000000) | 0);
  	            }
  
  	            return new WordArray.init(words, nBytes);
  	        }
  	    });
  
  	    /**
  	     * Encoder namespace.
  	     */
  	    var C_enc = C.enc = {};
  
  	    /**
  	     * Hex encoding strategy.
  	     */
  	    var Hex = C_enc.Hex = {
  	        /**
  	         * Converts a word array to a hex string.
  	         *
  	         * @param {WordArray} wordArray The word array.
  	         *
  	         * @return {string} The hex string.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var hexString = CryptoJS.enc.Hex.stringify(wordArray);
  	         */
  	        stringify: function (wordArray) {
  	            // Shortcuts
  	            var words = wordArray.words;
  	            var sigBytes = wordArray.sigBytes;
  
  	            // Convert
  	            var hexChars = [];
  	            for (var i = 0; i < sigBytes; i++) {
  	                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
  	                hexChars.push((bite >>> 4).toString(16));
  	                hexChars.push((bite & 0x0f).toString(16));
  	            }
  
  	            return hexChars.join('');
  	        },
  
  	        /**
  	         * Converts a hex string to a word array.
  	         *
  	         * @param {string} hexStr The hex string.
  	         *
  	         * @return {WordArray} The word array.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var wordArray = CryptoJS.enc.Hex.parse(hexString);
  	         */
  	        parse: function (hexStr) {
  	            // Shortcut
  	            var hexStrLength = hexStr.length;
  
  	            // Convert
  	            var words = [];
  	            for (var i = 0; i < hexStrLength; i += 2) {
  	                words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
  	            }
  
  	            return new WordArray.init(words, hexStrLength / 2);
  	        }
  	    };
  
  	    /**
  	     * Latin1 encoding strategy.
  	     */
  	    var Latin1 = C_enc.Latin1 = {
  	        /**
  	         * Converts a word array to a Latin1 string.
  	         *
  	         * @param {WordArray} wordArray The word array.
  	         *
  	         * @return {string} The Latin1 string.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
  	         */
  	        stringify: function (wordArray) {
  	            // Shortcuts
  	            var words = wordArray.words;
  	            var sigBytes = wordArray.sigBytes;
  
  	            // Convert
  	            var latin1Chars = [];
  	            for (var i = 0; i < sigBytes; i++) {
  	                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
  	                latin1Chars.push(String.fromCharCode(bite));
  	            }
  
  	            return latin1Chars.join('');
  	        },
  
  	        /**
  	         * Converts a Latin1 string to a word array.
  	         *
  	         * @param {string} latin1Str The Latin1 string.
  	         *
  	         * @return {WordArray} The word array.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
  	         */
  	        parse: function (latin1Str) {
  	            // Shortcut
  	            var latin1StrLength = latin1Str.length;
  
  	            // Convert
  	            var words = [];
  	            for (var i = 0; i < latin1StrLength; i++) {
  	                words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
  	            }
  
  	            return new WordArray.init(words, latin1StrLength);
  	        }
  	    };
  
  	    /**
  	     * UTF-8 encoding strategy.
  	     */
  	    var Utf8 = C_enc.Utf8 = {
  	        /**
  	         * Converts a word array to a UTF-8 string.
  	         *
  	         * @param {WordArray} wordArray The word array.
  	         *
  	         * @return {string} The UTF-8 string.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
  	         */
  	        stringify: function (wordArray) {
  	            try {
  	                return decodeURIComponent(escape(Latin1.stringify(wordArray)));
  	            } catch (e) {
  	                throw new Error('Malformed UTF-8 data');
  	            }
  	        },
  
  	        /**
  	         * Converts a UTF-8 string to a word array.
  	         *
  	         * @param {string} utf8Str The UTF-8 string.
  	         *
  	         * @return {WordArray} The word array.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
  	         */
  	        parse: function (utf8Str) {
  	            return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
  	        }
  	    };
  
  	    /**
  	     * Abstract buffered block algorithm template.
  	     *
  	     * The property blockSize must be implemented in a concrete subtype.
  	     *
  	     * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
  	     */
  	    var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
  	        /**
  	         * Resets this block algorithm's data buffer to its initial state.
  	         *
  	         * @example
  	         *
  	         *     bufferedBlockAlgorithm.reset();
  	         */
  	        reset: function () {
  	            // Initial values
  	            this._data = new WordArray.init();
  	            this._nDataBytes = 0;
  	        },
  
  	        /**
  	         * Adds new data to this block algorithm's buffer.
  	         *
  	         * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
  	         *
  	         * @example
  	         *
  	         *     bufferedBlockAlgorithm._append('data');
  	         *     bufferedBlockAlgorithm._append(wordArray);
  	         */
  	        _append: function (data) {
  	            // Convert string to WordArray, else assume WordArray already
  	            if (typeof data == 'string') {
  	                data = Utf8.parse(data);
  	            }
  
  	            // Append
  	            this._data.concat(data);
  	            this._nDataBytes += data.sigBytes;
  	        },
  
  	        /**
  	         * Processes available data blocks.
  	         *
  	         * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
  	         *
  	         * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
  	         *
  	         * @return {WordArray} The processed data.
  	         *
  	         * @example
  	         *
  	         *     var processedData = bufferedBlockAlgorithm._process();
  	         *     var processedData = bufferedBlockAlgorithm._process(!!'flush');
  	         */
  	        _process: function (doFlush) {
  	            // Shortcuts
  	            var data = this._data;
  	            var dataWords = data.words;
  	            var dataSigBytes = data.sigBytes;
  	            var blockSize = this.blockSize;
  	            var blockSizeBytes = blockSize * 4;
  
  	            // Count blocks ready
  	            var nBlocksReady = dataSigBytes / blockSizeBytes;
  	            if (doFlush) {
  	                // Round up to include partial blocks
  	                nBlocksReady = Math.ceil(nBlocksReady);
  	            } else {
  	                // Round down to include only full blocks,
  	                // less the number of blocks that must remain in the buffer
  	                nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
  	            }
  
  	            // Count words ready
  	            var nWordsReady = nBlocksReady * blockSize;
  
  	            // Count bytes ready
  	            var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
  
  	            // Process blocks
  	            if (nWordsReady) {
  	                for (var offset = 0; offset < nWordsReady; offset += blockSize) {
  	                    // Perform concrete-algorithm logic
  	                    this._doProcessBlock(dataWords, offset);
  	                }
  
  	                // Remove processed words
  	                var processedWords = dataWords.splice(0, nWordsReady);
  	                data.sigBytes -= nBytesReady;
  	            }
  
  	            // Return processed words
  	            return new WordArray.init(processedWords, nBytesReady);
  	        },
  
  	        /**
  	         * Creates a copy of this object.
  	         *
  	         * @return {Object} The clone.
  	         *
  	         * @example
  	         *
  	         *     var clone = bufferedBlockAlgorithm.clone();
  	         */
  	        clone: function () {
  	            var clone = Base.clone.call(this);
  	            clone._data = this._data.clone();
  
  	            return clone;
  	        },
  
  	        _minBufferSize: 0
  	    });
  
  	    /**
  	     * Abstract hasher template.
  	     *
  	     * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
  	     */
  	    var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
  	        /**
  	         * Configuration options.
  	         */
  	        cfg: Base.extend(),
  
  	        /**
  	         * Initializes a newly created hasher.
  	         *
  	         * @param {Object} cfg (Optional) The configuration options to use for this hash computation.
  	         *
  	         * @example
  	         *
  	         *     var hasher = CryptoJS.algo.SHA256.create();
  	         */
  	        init: function (cfg) {
  	            // Apply config defaults
  	            this.cfg = this.cfg.extend(cfg);
  
  	            // Set initial values
  	            this.reset();
  	        },
  
  	        /**
  	         * Resets this hasher to its initial state.
  	         *
  	         * @example
  	         *
  	         *     hasher.reset();
  	         */
  	        reset: function () {
  	            // Reset data buffer
  	            BufferedBlockAlgorithm.reset.call(this);
  
  	            // Perform concrete-hasher logic
  	            this._doReset();
  	        },
  
  	        /**
  	         * Updates this hasher with a message.
  	         *
  	         * @param {WordArray|string} messageUpdate The message to append.
  	         *
  	         * @return {Hasher} This hasher.
  	         *
  	         * @example
  	         *
  	         *     hasher.update('message');
  	         *     hasher.update(wordArray);
  	         */
  	        update: function (messageUpdate) {
  	            // Append
  	            this._append(messageUpdate);
  
  	            // Update the hash
  	            this._process();
  
  	            // Chainable
  	            return this;
  	        },
  
  	        /**
  	         * Finalizes the hash computation.
  	         * Note that the finalize operation is effectively a destructive, read-once operation.
  	         *
  	         * @param {WordArray|string} messageUpdate (Optional) A final message update.
  	         *
  	         * @return {WordArray} The hash.
  	         *
  	         * @example
  	         *
  	         *     var hash = hasher.finalize();
  	         *     var hash = hasher.finalize('message');
  	         *     var hash = hasher.finalize(wordArray);
  	         */
  	        finalize: function (messageUpdate) {
  	            // Final message update
  	            if (messageUpdate) {
  	                this._append(messageUpdate);
  	            }
  
  	            // Perform concrete-hasher logic
  	            var hash = this._doFinalize();
  
  	            return hash;
  	        },
  
  	        blockSize: 512/32,
  
  	        /**
  	         * Creates a shortcut function to a hasher's object interface.
  	         *
  	         * @param {Hasher} hasher The hasher to create a helper for.
  	         *
  	         * @return {Function} The shortcut function.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
  	         */
  	        _createHelper: function (hasher) {
  	            return function (message, cfg) {
  	                return new hasher.init(cfg).finalize(message);
  	            };
  	        },
  
  	        /**
  	         * Creates a shortcut function to the HMAC's object interface.
  	         *
  	         * @param {Hasher} hasher The hasher to use in this HMAC helper.
  	         *
  	         * @return {Function} The shortcut function.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
  	         */
  	        _createHmacHelper: function (hasher) {
  	            return function (message, key) {
  	                return new C_algo.HMAC.init(hasher, key).finalize(message);
  	            };
  	        }
  	    });
  
  	    /**
  	     * Algorithm namespace.
  	     */
  	    var C_algo = C.algo = {};
  
  	    return C;
  	}(Math));
  
  
  	return CryptoJS;
  
  }));
  },{}],35:[function(require,module,exports){
  ;(function (root, factory) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var WordArray = C_lib.WordArray;
  	    var C_enc = C.enc;
  
  	    /**
  	     * Base64 encoding strategy.
  	     */
  	    var Base64 = C_enc.Base64 = {
  	        /**
  	         * Converts a word array to a Base64 string.
  	         *
  	         * @param {WordArray} wordArray The word array.
  	         *
  	         * @return {string} The Base64 string.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var base64String = CryptoJS.enc.Base64.stringify(wordArray);
  	         */
  	        stringify: function (wordArray) {
  	            // Shortcuts
  	            var words = wordArray.words;
  	            var sigBytes = wordArray.sigBytes;
  	            var map = this._map;
  
  	            // Clamp excess bits
  	            wordArray.clamp();
  
  	            // Convert
  	            var base64Chars = [];
  	            for (var i = 0; i < sigBytes; i += 3) {
  	                var byte1 = (words[i >>> 2]       >>> (24 - (i % 4) * 8))       & 0xff;
  	                var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
  	                var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
  
  	                var triplet = (byte1 << 16) | (byte2 << 8) | byte3;
  
  	                for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
  	                    base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
  	                }
  	            }
  
  	            // Add padding
  	            var paddingChar = map.charAt(64);
  	            if (paddingChar) {
  	                while (base64Chars.length % 4) {
  	                    base64Chars.push(paddingChar);
  	                }
  	            }
  
  	            return base64Chars.join('');
  	        },
  
  	        /**
  	         * Converts a Base64 string to a word array.
  	         *
  	         * @param {string} base64Str The Base64 string.
  	         *
  	         * @return {WordArray} The word array.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var wordArray = CryptoJS.enc.Base64.parse(base64String);
  	         */
  	        parse: function (base64Str) {
  	            // Shortcuts
  	            var base64StrLength = base64Str.length;
  	            var map = this._map;
  	            var reverseMap = this._reverseMap;
  
  	            if (!reverseMap) {
  	                    reverseMap = this._reverseMap = [];
  	                    for (var j = 0; j < map.length; j++) {
  	                        reverseMap[map.charCodeAt(j)] = j;
  	                    }
  	            }
  
  	            // Ignore padding
  	            var paddingChar = map.charAt(64);
  	            if (paddingChar) {
  	                var paddingIndex = base64Str.indexOf(paddingChar);
  	                if (paddingIndex !== -1) {
  	                    base64StrLength = paddingIndex;
  	                }
  	            }
  
  	            // Convert
  	            return parseLoop(base64Str, base64StrLength, reverseMap);
  
  	        },
  
  	        _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
  	    };
  
  	    function parseLoop(base64Str, base64StrLength, reverseMap) {
  	      var words = [];
  	      var nBytes = 0;
  	      for (var i = 0; i < base64StrLength; i++) {
  	          if (i % 4) {
  	              var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2);
  	              var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2);
  	              words[nBytes >>> 2] |= (bits1 | bits2) << (24 - (nBytes % 4) * 8);
  	              nBytes++;
  	          }
  	      }
  	      return WordArray.create(words, nBytes);
  	    }
  	}());
  
  
  	return CryptoJS.enc.Base64;
  
  }));
  },{"./core":34}],36:[function(require,module,exports){
  ;(function (root, factory) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var WordArray = C_lib.WordArray;
  	    var C_enc = C.enc;
  
  	    /**
  	     * UTF-16 BE encoding strategy.
  	     */
  	    var Utf16BE = C_enc.Utf16 = C_enc.Utf16BE = {
  	        /**
  	         * Converts a word array to a UTF-16 BE string.
  	         *
  	         * @param {WordArray} wordArray The word array.
  	         *
  	         * @return {string} The UTF-16 BE string.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var utf16String = CryptoJS.enc.Utf16.stringify(wordArray);
  	         */
  	        stringify: function (wordArray) {
  	            // Shortcuts
  	            var words = wordArray.words;
  	            var sigBytes = wordArray.sigBytes;
  
  	            // Convert
  	            var utf16Chars = [];
  	            for (var i = 0; i < sigBytes; i += 2) {
  	                var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff;
  	                utf16Chars.push(String.fromCharCode(codePoint));
  	            }
  
  	            return utf16Chars.join('');
  	        },
  
  	        /**
  	         * Converts a UTF-16 BE string to a word array.
  	         *
  	         * @param {string} utf16Str The UTF-16 BE string.
  	         *
  	         * @return {WordArray} The word array.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var wordArray = CryptoJS.enc.Utf16.parse(utf16String);
  	         */
  	        parse: function (utf16Str) {
  	            // Shortcut
  	            var utf16StrLength = utf16Str.length;
  
  	            // Convert
  	            var words = [];
  	            for (var i = 0; i < utf16StrLength; i++) {
  	                words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16);
  	            }
  
  	            return WordArray.create(words, utf16StrLength * 2);
  	        }
  	    };
  
  	    /**
  	     * UTF-16 LE encoding strategy.
  	     */
  	    C_enc.Utf16LE = {
  	        /**
  	         * Converts a word array to a UTF-16 LE string.
  	         *
  	         * @param {WordArray} wordArray The word array.
  	         *
  	         * @return {string} The UTF-16 LE string.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray);
  	         */
  	        stringify: function (wordArray) {
  	            // Shortcuts
  	            var words = wordArray.words;
  	            var sigBytes = wordArray.sigBytes;
  
  	            // Convert
  	            var utf16Chars = [];
  	            for (var i = 0; i < sigBytes; i += 2) {
  	                var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff);
  	                utf16Chars.push(String.fromCharCode(codePoint));
  	            }
  
  	            return utf16Chars.join('');
  	        },
  
  	        /**
  	         * Converts a UTF-16 LE string to a word array.
  	         *
  	         * @param {string} utf16Str The UTF-16 LE string.
  	         *
  	         * @return {WordArray} The word array.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str);
  	         */
  	        parse: function (utf16Str) {
  	            // Shortcut
  	            var utf16StrLength = utf16Str.length;
  
  	            // Convert
  	            var words = [];
  	            for (var i = 0; i < utf16StrLength; i++) {
  	                words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16));
  	            }
  
  	            return WordArray.create(words, utf16StrLength * 2);
  	        }
  	    };
  
  	    function swapEndian(word) {
  	        return ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff);
  	    }
  	}());
  
  
  	return CryptoJS.enc.Utf16;
  
  }));
  },{"./core":34}],37:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./sha1", "./hmac"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var Base = C_lib.Base;
  	    var WordArray = C_lib.WordArray;
  	    var C_algo = C.algo;
  	    var MD5 = C_algo.MD5;
  
  	    /**
  	     * This key derivation function is meant to conform with EVP_BytesToKey.
  	     * www.openssl.org/docs/crypto/EVP_BytesToKey.html
  	     */
  	    var EvpKDF = C_algo.EvpKDF = Base.extend({
  	        /**
  	         * Configuration options.
  	         *
  	         * @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
  	         * @property {Hasher} hasher The hash algorithm to use. Default: MD5
  	         * @property {number} iterations The number of iterations to perform. Default: 1
  	         */
  	        cfg: Base.extend({
  	            keySize: 128/32,
  	            hasher: MD5,
  	            iterations: 1
  	        }),
  
  	        /**
  	         * Initializes a newly created key derivation function.
  	         *
  	         * @param {Object} cfg (Optional) The configuration options to use for the derivation.
  	         *
  	         * @example
  	         *
  	         *     var kdf = CryptoJS.algo.EvpKDF.create();
  	         *     var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 });
  	         *     var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 });
  	         */
  	        init: function (cfg) {
  	            this.cfg = this.cfg.extend(cfg);
  	        },
  
  	        /**
  	         * Derives a key from a password.
  	         *
  	         * @param {WordArray|string} password The password.
  	         * @param {WordArray|string} salt A salt.
  	         *
  	         * @return {WordArray} The derived key.
  	         *
  	         * @example
  	         *
  	         *     var key = kdf.compute(password, salt);
  	         */
  	        compute: function (password, salt) {
  	            // Shortcut
  	            var cfg = this.cfg;
  
  	            // Init hasher
  	            var hasher = cfg.hasher.create();
  
  	            // Initial values
  	            var derivedKey = WordArray.create();
  
  	            // Shortcuts
  	            var derivedKeyWords = derivedKey.words;
  	            var keySize = cfg.keySize;
  	            var iterations = cfg.iterations;
  
  	            // Generate key
  	            while (derivedKeyWords.length < keySize) {
  	                if (block) {
  	                    hasher.update(block);
  	                }
  	                var block = hasher.update(password).finalize(salt);
  	                hasher.reset();
  
  	                // Iterations
  	                for (var i = 1; i < iterations; i++) {
  	                    block = hasher.finalize(block);
  	                    hasher.reset();
  	                }
  
  	                derivedKey.concat(block);
  	            }
  	            derivedKey.sigBytes = keySize * 4;
  
  	            return derivedKey;
  	        }
  	    });
  
  	    /**
  	     * Derives a key from a password.
  	     *
  	     * @param {WordArray|string} password The password.
  	     * @param {WordArray|string} salt A salt.
  	     * @param {Object} cfg (Optional) The configuration options to use for this computation.
  	     *
  	     * @return {WordArray} The derived key.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var key = CryptoJS.EvpKDF(password, salt);
  	     *     var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 });
  	     *     var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 });
  	     */
  	    C.EvpKDF = function (password, salt, cfg) {
  	        return EvpKDF.create(cfg).compute(password, salt);
  	    };
  	}());
  
  
  	return CryptoJS.EvpKDF;
  
  }));
  },{"./core":34,"./hmac":39,"./sha1":58}],38:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function (undefined) {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var CipherParams = C_lib.CipherParams;
  	    var C_enc = C.enc;
  	    var Hex = C_enc.Hex;
  	    var C_format = C.format;
  
  	    var HexFormatter = C_format.Hex = {
  	        /**
  	         * Converts the ciphertext of a cipher params object to a hexadecimally encoded string.
  	         *
  	         * @param {CipherParams} cipherParams The cipher params object.
  	         *
  	         * @return {string} The hexadecimally encoded string.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var hexString = CryptoJS.format.Hex.stringify(cipherParams);
  	         */
  	        stringify: function (cipherParams) {
  	            return cipherParams.ciphertext.toString(Hex);
  	        },
  
  	        /**
  	         * Converts a hexadecimally encoded ciphertext string to a cipher params object.
  	         *
  	         * @param {string} input The hexadecimally encoded string.
  	         *
  	         * @return {CipherParams} The cipher params object.
  	         *
  	         * @static
  	         *
  	         * @example
  	         *
  	         *     var cipherParams = CryptoJS.format.Hex.parse(hexString);
  	         */
  	        parse: function (input) {
  	            var ciphertext = Hex.parse(input);
  	            return CipherParams.create({ ciphertext: ciphertext });
  	        }
  	    };
  	}());
  
  
  	return CryptoJS.format.Hex;
  
  }));
  },{"./cipher-core":33,"./core":34}],39:[function(require,module,exports){
  ;(function (root, factory) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var Base = C_lib.Base;
  	    var C_enc = C.enc;
  	    var Utf8 = C_enc.Utf8;
  	    var C_algo = C.algo;
  
  	    /**
  	     * HMAC algorithm.
  	     */
  	    var HMAC = C_algo.HMAC = Base.extend({
  	        /**
  	         * Initializes a newly created HMAC.
  	         *
  	         * @param {Hasher} hasher The hash algorithm to use.
  	         * @param {WordArray|string} key The secret key.
  	         *
  	         * @example
  	         *
  	         *     var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
  	         */
  	        init: function (hasher, key) {
  	            // Init hasher
  	            hasher = this._hasher = new hasher.init();
  
  	            // Convert string to WordArray, else assume WordArray already
  	            if (typeof key == 'string') {
  	                key = Utf8.parse(key);
  	            }
  
  	            // Shortcuts
  	            var hasherBlockSize = hasher.blockSize;
  	            var hasherBlockSizeBytes = hasherBlockSize * 4;
  
  	            // Allow arbitrary length keys
  	            if (key.sigBytes > hasherBlockSizeBytes) {
  	                key = hasher.finalize(key);
  	            }
  
  	            // Clamp excess bits
  	            key.clamp();
  
  	            // Clone key for inner and outer pads
  	            var oKey = this._oKey = key.clone();
  	            var iKey = this._iKey = key.clone();
  
  	            // Shortcuts
  	            var oKeyWords = oKey.words;
  	            var iKeyWords = iKey.words;
  
  	            // XOR keys with pad constants
  	            for (var i = 0; i < hasherBlockSize; i++) {
  	                oKeyWords[i] ^= 0x5c5c5c5c;
  	                iKeyWords[i] ^= 0x36363636;
  	            }
  	            oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes;
  
  	            // Set initial values
  	            this.reset();
  	        },
  
  	        /**
  	         * Resets this HMAC to its initial state.
  	         *
  	         * @example
  	         *
  	         *     hmacHasher.reset();
  	         */
  	        reset: function () {
  	            // Shortcut
  	            var hasher = this._hasher;
  
  	            // Reset
  	            hasher.reset();
  	            hasher.update(this._iKey);
  	        },
  
  	        /**
  	         * Updates this HMAC with a message.
  	         *
  	         * @param {WordArray|string} messageUpdate The message to append.
  	         *
  	         * @return {HMAC} This HMAC instance.
  	         *
  	         * @example
  	         *
  	         *     hmacHasher.update('message');
  	         *     hmacHasher.update(wordArray);
  	         */
  	        update: function (messageUpdate) {
  	            this._hasher.update(messageUpdate);
  
  	            // Chainable
  	            return this;
  	        },
  
  	        /**
  	         * Finalizes the HMAC computation.
  	         * Note that the finalize operation is effectively a destructive, read-once operation.
  	         *
  	         * @param {WordArray|string} messageUpdate (Optional) A final message update.
  	         *
  	         * @return {WordArray} The HMAC.
  	         *
  	         * @example
  	         *
  	         *     var hmac = hmacHasher.finalize();
  	         *     var hmac = hmacHasher.finalize('message');
  	         *     var hmac = hmacHasher.finalize(wordArray);
  	         */
  	        finalize: function (messageUpdate) {
  	            // Shortcut
  	            var hasher = this._hasher;
  
  	            // Compute HMAC
  	            var innerHash = hasher.finalize(messageUpdate);
  	            hasher.reset();
  	            var hmac = hasher.finalize(this._oKey.clone().concat(innerHash));
  
  	            return hmac;
  	        }
  	    });
  	}());
  
  
  }));
  },{"./core":34}],40:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./x64-core"), require("./lib-typedarrays"), require("./enc-utf16"), require("./enc-base64"), require("./md5"), require("./sha1"), require("./sha256"), require("./sha224"), require("./sha512"), require("./sha384"), require("./sha3"), require("./ripemd160"), require("./hmac"), require("./pbkdf2"), require("./evpkdf"), require("./cipher-core"), require("./mode-cfb"), require("./mode-ctr"), require("./mode-ctr-gladman"), require("./mode-ofb"), require("./mode-ecb"), require("./pad-ansix923"), require("./pad-iso10126"), require("./pad-iso97971"), require("./pad-zeropadding"), require("./pad-nopadding"), require("./format-hex"), require("./aes"), require("./tripledes"), require("./rc4"), require("./rabbit"), require("./rabbit-legacy"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./x64-core", "./lib-typedarrays", "./enc-utf16", "./enc-base64", "./md5", "./sha1", "./sha256", "./sha224", "./sha512", "./sha384", "./sha3", "./ripemd160", "./hmac", "./pbkdf2", "./evpkdf", "./cipher-core", "./mode-cfb", "./mode-ctr", "./mode-ctr-gladman", "./mode-ofb", "./mode-ecb", "./pad-ansix923", "./pad-iso10126", "./pad-iso97971", "./pad-zeropadding", "./pad-nopadding", "./format-hex", "./aes", "./tripledes", "./rc4", "./rabbit", "./rabbit-legacy"], factory);
  	}
  	else {
  		// Global (browser)
  		root.CryptoJS = factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	return CryptoJS;
  
  }));
  },{"./aes":32,"./cipher-core":33,"./core":34,"./enc-base64":35,"./enc-utf16":36,"./evpkdf":37,"./format-hex":38,"./hmac":39,"./lib-typedarrays":41,"./md5":42,"./mode-cfb":43,"./mode-ctr":45,"./mode-ctr-gladman":44,"./mode-ecb":46,"./mode-ofb":47,"./pad-ansix923":48,"./pad-iso10126":49,"./pad-iso97971":50,"./pad-nopadding":51,"./pad-zeropadding":52,"./pbkdf2":53,"./rabbit":55,"./rabbit-legacy":54,"./rc4":56,"./ripemd160":57,"./sha1":58,"./sha224":59,"./sha256":60,"./sha3":61,"./sha384":62,"./sha512":63,"./tripledes":64,"./x64-core":65}],41:[function(require,module,exports){
  ;(function (root, factory) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Check if typed arrays are supported
  	    if (typeof ArrayBuffer != 'function') {
  	        return;
  	    }
  
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var WordArray = C_lib.WordArray;
  
  	    // Reference original init
  	    var superInit = WordArray.init;
  
  	    // Augment WordArray.init to handle typed arrays
  	    var subInit = WordArray.init = function (typedArray) {
  	        // Convert buffers to uint8
  	        if (typedArray instanceof ArrayBuffer) {
  	            typedArray = new Uint8Array(typedArray);
  	        }
  
  	        // Convert other array views to uint8
  	        if (
  	            typedArray instanceof Int8Array ||
  	            (typeof Uint8ClampedArray !== "undefined" && typedArray instanceof Uint8ClampedArray) ||
  	            typedArray instanceof Int16Array ||
  	            typedArray instanceof Uint16Array ||
  	            typedArray instanceof Int32Array ||
  	            typedArray instanceof Uint32Array ||
  	            typedArray instanceof Float32Array ||
  	            typedArray instanceof Float64Array
  	        ) {
  	            typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);
  	        }
  
  	        // Handle Uint8Array
  	        if (typedArray instanceof Uint8Array) {
  	            // Shortcut
  	            var typedArrayByteLength = typedArray.byteLength;
  
  	            // Extract bytes
  	            var words = [];
  	            for (var i = 0; i < typedArrayByteLength; i++) {
  	                words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8);
  	            }
  
  	            // Initialize this word array
  	            superInit.call(this, words, typedArrayByteLength);
  	        } else {
  	            // Else call normal init
  	            superInit.apply(this, arguments);
  	        }
  	    };
  
  	    subInit.prototype = WordArray;
  	}());
  
  
  	return CryptoJS.lib.WordArray;
  
  }));
  },{"./core":34}],42:[function(require,module,exports){
  ;(function (root, factory) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function (Math) {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var WordArray = C_lib.WordArray;
  	    var Hasher = C_lib.Hasher;
  	    var C_algo = C.algo;
  
  	    // Constants table
  	    var T = [];
  
  	    // Compute constants
  	    (function () {
  	        for (var i = 0; i < 64; i++) {
  	            T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0;
  	        }
  	    }());
  
  	    /**
  	     * MD5 hash algorithm.
  	     */
  	    var MD5 = C_algo.MD5 = Hasher.extend({
  	        _doReset: function () {
  	            this._hash = new WordArray.init([
  	                0x67452301, 0xefcdab89,
  	                0x98badcfe, 0x10325476
  	            ]);
  	        },
  
  	        _doProcessBlock: function (M, offset) {
  	            // Swap endian
  	            for (var i = 0; i < 16; i++) {
  	                // Shortcuts
  	                var offset_i = offset + i;
  	                var M_offset_i = M[offset_i];
  
  	                M[offset_i] = (
  	                    (((M_offset_i << 8)  | (M_offset_i >>> 24)) & 0x00ff00ff) |
  	                    (((M_offset_i << 24) | (M_offset_i >>> 8))  & 0xff00ff00)
  	                );
  	            }
  
  	            // Shortcuts
  	            var H = this._hash.words;
  
  	            var M_offset_0  = M[offset + 0];
  	            var M_offset_1  = M[offset + 1];
  	            var M_offset_2  = M[offset + 2];
  	            var M_offset_3  = M[offset + 3];
  	            var M_offset_4  = M[offset + 4];
  	            var M_offset_5  = M[offset + 5];
  	            var M_offset_6  = M[offset + 6];
  	            var M_offset_7  = M[offset + 7];
  	            var M_offset_8  = M[offset + 8];
  	            var M_offset_9  = M[offset + 9];
  	            var M_offset_10 = M[offset + 10];
  	            var M_offset_11 = M[offset + 11];
  	            var M_offset_12 = M[offset + 12];
  	            var M_offset_13 = M[offset + 13];
  	            var M_offset_14 = M[offset + 14];
  	            var M_offset_15 = M[offset + 15];
  
  	            // Working varialbes
  	            var a = H[0];
  	            var b = H[1];
  	            var c = H[2];
  	            var d = H[3];
  
  	            // Computation
  	            a = FF(a, b, c, d, M_offset_0,  7,  T[0]);
  	            d = FF(d, a, b, c, M_offset_1,  12, T[1]);
  	            c = FF(c, d, a, b, M_offset_2,  17, T[2]);
  	            b = FF(b, c, d, a, M_offset_3,  22, T[3]);
  	            a = FF(a, b, c, d, M_offset_4,  7,  T[4]);
  	            d = FF(d, a, b, c, M_offset_5,  12, T[5]);
  	            c = FF(c, d, a, b, M_offset_6,  17, T[6]);
  	            b = FF(b, c, d, a, M_offset_7,  22, T[7]);
  	            a = FF(a, b, c, d, M_offset_8,  7,  T[8]);
  	            d = FF(d, a, b, c, M_offset_9,  12, T[9]);
  	            c = FF(c, d, a, b, M_offset_10, 17, T[10]);
  	            b = FF(b, c, d, a, M_offset_11, 22, T[11]);
  	            a = FF(a, b, c, d, M_offset_12, 7,  T[12]);
  	            d = FF(d, a, b, c, M_offset_13, 12, T[13]);
  	            c = FF(c, d, a, b, M_offset_14, 17, T[14]);
  	            b = FF(b, c, d, a, M_offset_15, 22, T[15]);
  
  	            a = GG(a, b, c, d, M_offset_1,  5,  T[16]);
  	            d = GG(d, a, b, c, M_offset_6,  9,  T[17]);
  	            c = GG(c, d, a, b, M_offset_11, 14, T[18]);
  	            b = GG(b, c, d, a, M_offset_0,  20, T[19]);
  	            a = GG(a, b, c, d, M_offset_5,  5,  T[20]);
  	            d = GG(d, a, b, c, M_offset_10, 9,  T[21]);
  	            c = GG(c, d, a, b, M_offset_15, 14, T[22]);
  	            b = GG(b, c, d, a, M_offset_4,  20, T[23]);
  	            a = GG(a, b, c, d, M_offset_9,  5,  T[24]);
  	            d = GG(d, a, b, c, M_offset_14, 9,  T[25]);
  	            c = GG(c, d, a, b, M_offset_3,  14, T[26]);
  	            b = GG(b, c, d, a, M_offset_8,  20, T[27]);
  	            a = GG(a, b, c, d, M_offset_13, 5,  T[28]);
  	            d = GG(d, a, b, c, M_offset_2,  9,  T[29]);
  	            c = GG(c, d, a, b, M_offset_7,  14, T[30]);
  	            b = GG(b, c, d, a, M_offset_12, 20, T[31]);
  
  	            a = HH(a, b, c, d, M_offset_5,  4,  T[32]);
  	            d = HH(d, a, b, c, M_offset_8,  11, T[33]);
  	            c = HH(c, d, a, b, M_offset_11, 16, T[34]);
  	            b = HH(b, c, d, a, M_offset_14, 23, T[35]);
  	            a = HH(a, b, c, d, M_offset_1,  4,  T[36]);
  	            d = HH(d, a, b, c, M_offset_4,  11, T[37]);
  	            c = HH(c, d, a, b, M_offset_7,  16, T[38]);
  	            b = HH(b, c, d, a, M_offset_10, 23, T[39]);
  	            a = HH(a, b, c, d, M_offset_13, 4,  T[40]);
  	            d = HH(d, a, b, c, M_offset_0,  11, T[41]);
  	            c = HH(c, d, a, b, M_offset_3,  16, T[42]);
  	            b = HH(b, c, d, a, M_offset_6,  23, T[43]);
  	            a = HH(a, b, c, d, M_offset_9,  4,  T[44]);
  	            d = HH(d, a, b, c, M_offset_12, 11, T[45]);
  	            c = HH(c, d, a, b, M_offset_15, 16, T[46]);
  	            b = HH(b, c, d, a, M_offset_2,  23, T[47]);
  
  	            a = II(a, b, c, d, M_offset_0,  6,  T[48]);
  	            d = II(d, a, b, c, M_offset_7,  10, T[49]);
  	            c = II(c, d, a, b, M_offset_14, 15, T[50]);
  	            b = II(b, c, d, a, M_offset_5,  21, T[51]);
  	            a = II(a, b, c, d, M_offset_12, 6,  T[52]);
  	            d = II(d, a, b, c, M_offset_3,  10, T[53]);
  	            c = II(c, d, a, b, M_offset_10, 15, T[54]);
  	            b = II(b, c, d, a, M_offset_1,  21, T[55]);
  	            a = II(a, b, c, d, M_offset_8,  6,  T[56]);
  	            d = II(d, a, b, c, M_offset_15, 10, T[57]);
  	            c = II(c, d, a, b, M_offset_6,  15, T[58]);
  	            b = II(b, c, d, a, M_offset_13, 21, T[59]);
  	            a = II(a, b, c, d, M_offset_4,  6,  T[60]);
  	            d = II(d, a, b, c, M_offset_11, 10, T[61]);
  	            c = II(c, d, a, b, M_offset_2,  15, T[62]);
  	            b = II(b, c, d, a, M_offset_9,  21, T[63]);
  
  	            // Intermediate hash value
  	            H[0] = (H[0] + a) | 0;
  	            H[1] = (H[1] + b) | 0;
  	            H[2] = (H[2] + c) | 0;
  	            H[3] = (H[3] + d) | 0;
  	        },
  
  	        _doFinalize: function () {
  	            // Shortcuts
  	            var data = this._data;
  	            var dataWords = data.words;
  
  	            var nBitsTotal = this._nDataBytes * 8;
  	            var nBitsLeft = data.sigBytes * 8;
  
  	            // Add padding
  	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
  
  	            var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
  	            var nBitsTotalL = nBitsTotal;
  	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = (
  	                (((nBitsTotalH << 8)  | (nBitsTotalH >>> 24)) & 0x00ff00ff) |
  	                (((nBitsTotalH << 24) | (nBitsTotalH >>> 8))  & 0xff00ff00)
  	            );
  	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
  	                (((nBitsTotalL << 8)  | (nBitsTotalL >>> 24)) & 0x00ff00ff) |
  	                (((nBitsTotalL << 24) | (nBitsTotalL >>> 8))  & 0xff00ff00)
  	            );
  
  	            data.sigBytes = (dataWords.length + 1) * 4;
  
  	            // Hash final blocks
  	            this._process();
  
  	            // Shortcuts
  	            var hash = this._hash;
  	            var H = hash.words;
  
  	            // Swap endian
  	            for (var i = 0; i < 4; i++) {
  	                // Shortcut
  	                var H_i = H[i];
  
  	                H[i] = (((H_i << 8)  | (H_i >>> 24)) & 0x00ff00ff) |
  	                       (((H_i << 24) | (H_i >>> 8))  & 0xff00ff00);
  	            }
  
  	            // Return final computed hash
  	            return hash;
  	        },
  
  	        clone: function () {
  	            var clone = Hasher.clone.call(this);
  	            clone._hash = this._hash.clone();
  
  	            return clone;
  	        }
  	    });
  
  	    function FF(a, b, c, d, x, s, t) {
  	        var n = a + ((b & c) | (~b & d)) + x + t;
  	        return ((n << s) | (n >>> (32 - s))) + b;
  	    }
  
  	    function GG(a, b, c, d, x, s, t) {
  	        var n = a + ((b & d) | (c & ~d)) + x + t;
  	        return ((n << s) | (n >>> (32 - s))) + b;
  	    }
  
  	    function HH(a, b, c, d, x, s, t) {
  	        var n = a + (b ^ c ^ d) + x + t;
  	        return ((n << s) | (n >>> (32 - s))) + b;
  	    }
  
  	    function II(a, b, c, d, x, s, t) {
  	        var n = a + (c ^ (b | ~d)) + x + t;
  	        return ((n << s) | (n >>> (32 - s))) + b;
  	    }
  
  	    /**
  	     * Shortcut function to the hasher's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     *
  	     * @return {WordArray} The hash.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hash = CryptoJS.MD5('message');
  	     *     var hash = CryptoJS.MD5(wordArray);
  	     */
  	    C.MD5 = Hasher._createHelper(MD5);
  
  	    /**
  	     * Shortcut function to the HMAC's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     * @param {WordArray|string} key The secret key.
  	     *
  	     * @return {WordArray} The HMAC.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hmac = CryptoJS.HmacMD5(message, key);
  	     */
  	    C.HmacMD5 = Hasher._createHmacHelper(MD5);
  	}(Math));
  
  
  	return CryptoJS.MD5;
  
  }));
  },{"./core":34}],43:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	/**
  	 * Cipher Feedback block mode.
  	 */
  	CryptoJS.mode.CFB = (function () {
  	    var CFB = CryptoJS.lib.BlockCipherMode.extend();
  
  	    CFB.Encryptor = CFB.extend({
  	        processBlock: function (words, offset) {
  	            // Shortcuts
  	            var cipher = this._cipher;
  	            var blockSize = cipher.blockSize;
  
  	            generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher);
  
  	            // Remember this block to use with next block
  	            this._prevBlock = words.slice(offset, offset + blockSize);
  	        }
  	    });
  
  	    CFB.Decryptor = CFB.extend({
  	        processBlock: function (words, offset) {
  	            // Shortcuts
  	            var cipher = this._cipher;
  	            var blockSize = cipher.blockSize;
  
  	            // Remember this block to use with next block
  	            var thisBlock = words.slice(offset, offset + blockSize);
  
  	            generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher);
  
  	            // This block becomes the previous block
  	            this._prevBlock = thisBlock;
  	        }
  	    });
  
  	    function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) {
  	        // Shortcut
  	        var iv = this._iv;
  
  	        // Generate keystream
  	        if (iv) {
  	            var keystream = iv.slice(0);
  
  	            // Remove IV for subsequent blocks
  	            this._iv = undefined;
  	        } else {
  	            var keystream = this._prevBlock;
  	        }
  	        cipher.encryptBlock(keystream, 0);
  
  	        // Encrypt
  	        for (var i = 0; i < blockSize; i++) {
  	            words[offset + i] ^= keystream[i];
  	        }
  	    }
  
  	    return CFB;
  	}());
  
  
  	return CryptoJS.mode.CFB;
  
  }));
  },{"./cipher-core":33,"./core":34}],44:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	/** @preserve
  	 * Counter block mode compatible with  Dr Brian Gladman fileenc.c
  	 * derived from CryptoJS.mode.CTR
  	 * Jan Hruby jhruby.web@gmail.com
  	 */
  	CryptoJS.mode.CTRGladman = (function () {
  	    var CTRGladman = CryptoJS.lib.BlockCipherMode.extend();
  
  		function incWord(word)
  		{
  			if (((word >> 24) & 0xff) === 0xff) { //overflow
  			var b1 = (word >> 16)&0xff;
  			var b2 = (word >> 8)&0xff;
  			var b3 = word & 0xff;
  
  			if (b1 === 0xff) // overflow b1
  			{
  			b1 = 0;
  			if (b2 === 0xff)
  			{
  				b2 = 0;
  				if (b3 === 0xff)
  				{
  					b3 = 0;
  				}
  				else
  				{
  					++b3;
  				}
  			}
  			else
  			{
  				++b2;
  			}
  			}
  			else
  			{
  			++b1;
  			}
  
  			word = 0;
  			word += (b1 << 16);
  			word += (b2 << 8);
  			word += b3;
  			}
  			else
  			{
  			word += (0x01 << 24);
  			}
  			return word;
  		}
  
  		function incCounter(counter)
  		{
  			if ((counter[0] = incWord(counter[0])) === 0)
  			{
  				// encr_data in fileenc.c from  Dr Brian Gladman's counts only with DWORD j < 8
  				counter[1] = incWord(counter[1]);
  			}
  			return counter;
  		}
  
  	    var Encryptor = CTRGladman.Encryptor = CTRGladman.extend({
  	        processBlock: function (words, offset) {
  	            // Shortcuts
  	            var cipher = this._cipher
  	            var blockSize = cipher.blockSize;
  	            var iv = this._iv;
  	            var counter = this._counter;
  
  	            // Generate keystream
  	            if (iv) {
  	                counter = this._counter = iv.slice(0);
  
  	                // Remove IV for subsequent blocks
  	                this._iv = undefined;
  	            }
  
  				incCounter(counter);
  
  				var keystream = counter.slice(0);
  	            cipher.encryptBlock(keystream, 0);
  
  	            // Encrypt
  	            for (var i = 0; i < blockSize; i++) {
  	                words[offset + i] ^= keystream[i];
  	            }
  	        }
  	    });
  
  	    CTRGladman.Decryptor = Encryptor;
  
  	    return CTRGladman;
  	}());
  
  
  
  
  	return CryptoJS.mode.CTRGladman;
  
  }));
  },{"./cipher-core":33,"./core":34}],45:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	/**
  	 * Counter block mode.
  	 */
  	CryptoJS.mode.CTR = (function () {
  	    var CTR = CryptoJS.lib.BlockCipherMode.extend();
  
  	    var Encryptor = CTR.Encryptor = CTR.extend({
  	        processBlock: function (words, offset) {
  	            // Shortcuts
  	            var cipher = this._cipher
  	            var blockSize = cipher.blockSize;
  	            var iv = this._iv;
  	            var counter = this._counter;
  
  	            // Generate keystream
  	            if (iv) {
  	                counter = this._counter = iv.slice(0);
  
  	                // Remove IV for subsequent blocks
  	                this._iv = undefined;
  	            }
  	            var keystream = counter.slice(0);
  	            cipher.encryptBlock(keystream, 0);
  
  	            // Increment counter
  	            counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0
  
  	            // Encrypt
  	            for (var i = 0; i < blockSize; i++) {
  	                words[offset + i] ^= keystream[i];
  	            }
  	        }
  	    });
  
  	    CTR.Decryptor = Encryptor;
  
  	    return CTR;
  	}());
  
  
  	return CryptoJS.mode.CTR;
  
  }));
  },{"./cipher-core":33,"./core":34}],46:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	/**
  	 * Electronic Codebook block mode.
  	 */
  	CryptoJS.mode.ECB = (function () {
  	    var ECB = CryptoJS.lib.BlockCipherMode.extend();
  
  	    ECB.Encryptor = ECB.extend({
  	        processBlock: function (words, offset) {
  	            this._cipher.encryptBlock(words, offset);
  	        }
  	    });
  
  	    ECB.Decryptor = ECB.extend({
  	        processBlock: function (words, offset) {
  	            this._cipher.decryptBlock(words, offset);
  	        }
  	    });
  
  	    return ECB;
  	}());
  
  
  	return CryptoJS.mode.ECB;
  
  }));
  },{"./cipher-core":33,"./core":34}],47:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	/**
  	 * Output Feedback block mode.
  	 */
  	CryptoJS.mode.OFB = (function () {
  	    var OFB = CryptoJS.lib.BlockCipherMode.extend();
  
  	    var Encryptor = OFB.Encryptor = OFB.extend({
  	        processBlock: function (words, offset) {
  	            // Shortcuts
  	            var cipher = this._cipher
  	            var blockSize = cipher.blockSize;
  	            var iv = this._iv;
  	            var keystream = this._keystream;
  
  	            // Generate keystream
  	            if (iv) {
  	                keystream = this._keystream = iv.slice(0);
  
  	                // Remove IV for subsequent blocks
  	                this._iv = undefined;
  	            }
  	            cipher.encryptBlock(keystream, 0);
  
  	            // Encrypt
  	            for (var i = 0; i < blockSize; i++) {
  	                words[offset + i] ^= keystream[i];
  	            }
  	        }
  	    });
  
  	    OFB.Decryptor = Encryptor;
  
  	    return OFB;
  	}());
  
  
  	return CryptoJS.mode.OFB;
  
  }));
  },{"./cipher-core":33,"./core":34}],48:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	/**
  	 * ANSI X.923 padding strategy.
  	 */
  	CryptoJS.pad.AnsiX923 = {
  	    pad: function (data, blockSize) {
  	        // Shortcuts
  	        var dataSigBytes = data.sigBytes;
  	        var blockSizeBytes = blockSize * 4;
  
  	        // Count padding bytes
  	        var nPaddingBytes = blockSizeBytes - dataSigBytes % blockSizeBytes;
  
  	        // Compute last byte position
  	        var lastBytePos = dataSigBytes + nPaddingBytes - 1;
  
  	        // Pad
  	        data.clamp();
  	        data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8);
  	        data.sigBytes += nPaddingBytes;
  	    },
  
  	    unpad: function (data) {
  	        // Get number of padding bytes from last byte
  	        var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
  
  	        // Remove padding
  	        data.sigBytes -= nPaddingBytes;
  	    }
  	};
  
  
  	return CryptoJS.pad.Ansix923;
  
  }));
  },{"./cipher-core":33,"./core":34}],49:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	/**
  	 * ISO 10126 padding strategy.
  	 */
  	CryptoJS.pad.Iso10126 = {
  	    pad: function (data, blockSize) {
  	        // Shortcut
  	        var blockSizeBytes = blockSize * 4;
  
  	        // Count padding bytes
  	        var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;
  
  	        // Pad
  	        data.concat(CryptoJS.lib.WordArray.random(nPaddingBytes - 1)).
  	             concat(CryptoJS.lib.WordArray.create([nPaddingBytes << 24], 1));
  	    },
  
  	    unpad: function (data) {
  	        // Get number of padding bytes from last byte
  	        var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
  
  	        // Remove padding
  	        data.sigBytes -= nPaddingBytes;
  	    }
  	};
  
  
  	return CryptoJS.pad.Iso10126;
  
  }));
  },{"./cipher-core":33,"./core":34}],50:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	/**
  	 * ISO/IEC 9797-1 Padding Method 2.
  	 */
  	CryptoJS.pad.Iso97971 = {
  	    pad: function (data, blockSize) {
  	        // Add 0x80 byte
  	        data.concat(CryptoJS.lib.WordArray.create([0x80000000], 1));
  
  	        // Zero pad the rest
  	        CryptoJS.pad.ZeroPadding.pad(data, blockSize);
  	    },
  
  	    unpad: function (data) {
  	        // Remove zero padding
  	        CryptoJS.pad.ZeroPadding.unpad(data);
  
  	        // Remove one more byte -- the 0x80 byte
  	        data.sigBytes--;
  	    }
  	};
  
  
  	return CryptoJS.pad.Iso97971;
  
  }));
  },{"./cipher-core":33,"./core":34}],51:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	/**
  	 * A noop padding strategy.
  	 */
  	CryptoJS.pad.NoPadding = {
  	    pad: function () {
  	    },
  
  	    unpad: function () {
  	    }
  	};
  
  
  	return CryptoJS.pad.NoPadding;
  
  }));
  },{"./cipher-core":33,"./core":34}],52:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	/**
  	 * Zero padding strategy.
  	 */
  	CryptoJS.pad.ZeroPadding = {
  	    pad: function (data, blockSize) {
  	        // Shortcut
  	        var blockSizeBytes = blockSize * 4;
  
  	        // Pad
  	        data.clamp();
  	        data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes);
  	    },
  
  	    unpad: function (data) {
  	        // Shortcut
  	        var dataWords = data.words;
  
  	        // Unpad
  	        var i = data.sigBytes - 1;
  	        while (!((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) {
  	            i--;
  	        }
  	        data.sigBytes = i + 1;
  	    }
  	};
  
  
  	return CryptoJS.pad.ZeroPadding;
  
  }));
  },{"./cipher-core":33,"./core":34}],53:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./sha1", "./hmac"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var Base = C_lib.Base;
  	    var WordArray = C_lib.WordArray;
  	    var C_algo = C.algo;
  	    var SHA1 = C_algo.SHA1;
  	    var HMAC = C_algo.HMAC;
  
  	    /**
  	     * Password-Based Key Derivation Function 2 algorithm.
  	     */
  	    var PBKDF2 = C_algo.PBKDF2 = Base.extend({
  	        /**
  	         * Configuration options.
  	         *
  	         * @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
  	         * @property {Hasher} hasher The hasher to use. Default: SHA1
  	         * @property {number} iterations The number of iterations to perform. Default: 1
  	         */
  	        cfg: Base.extend({
  	            keySize: 128/32,
  	            hasher: SHA1,
  	            iterations: 1
  	        }),
  
  	        /**
  	         * Initializes a newly created key derivation function.
  	         *
  	         * @param {Object} cfg (Optional) The configuration options to use for the derivation.
  	         *
  	         * @example
  	         *
  	         *     var kdf = CryptoJS.algo.PBKDF2.create();
  	         *     var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 });
  	         *     var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 });
  	         */
  	        init: function (cfg) {
  	            this.cfg = this.cfg.extend(cfg);
  	        },
  
  	        /**
  	         * Computes the Password-Based Key Derivation Function 2.
  	         *
  	         * @param {WordArray|string} password The password.
  	         * @param {WordArray|string} salt A salt.
  	         *
  	         * @return {WordArray} The derived key.
  	         *
  	         * @example
  	         *
  	         *     var key = kdf.compute(password, salt);
  	         */
  	        compute: function (password, salt) {
  	            // Shortcut
  	            var cfg = this.cfg;
  
  	            // Init HMAC
  	            var hmac = HMAC.create(cfg.hasher, password);
  
  	            // Initial values
  	            var derivedKey = WordArray.create();
  	            var blockIndex = WordArray.create([0x00000001]);
  
  	            // Shortcuts
  	            var derivedKeyWords = derivedKey.words;
  	            var blockIndexWords = blockIndex.words;
  	            var keySize = cfg.keySize;
  	            var iterations = cfg.iterations;
  
  	            // Generate key
  	            while (derivedKeyWords.length < keySize) {
  	                var block = hmac.update(salt).finalize(blockIndex);
  	                hmac.reset();
  
  	                // Shortcuts
  	                var blockWords = block.words;
  	                var blockWordsLength = blockWords.length;
  
  	                // Iterations
  	                var intermediate = block;
  	                for (var i = 1; i < iterations; i++) {
  	                    intermediate = hmac.finalize(intermediate);
  	                    hmac.reset();
  
  	                    // Shortcut
  	                    var intermediateWords = intermediate.words;
  
  	                    // XOR intermediate with block
  	                    for (var j = 0; j < blockWordsLength; j++) {
  	                        blockWords[j] ^= intermediateWords[j];
  	                    }
  	                }
  
  	                derivedKey.concat(block);
  	                blockIndexWords[0]++;
  	            }
  	            derivedKey.sigBytes = keySize * 4;
  
  	            return derivedKey;
  	        }
  	    });
  
  	    /**
  	     * Computes the Password-Based Key Derivation Function 2.
  	     *
  	     * @param {WordArray|string} password The password.
  	     * @param {WordArray|string} salt A salt.
  	     * @param {Object} cfg (Optional) The configuration options to use for this computation.
  	     *
  	     * @return {WordArray} The derived key.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var key = CryptoJS.PBKDF2(password, salt);
  	     *     var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 });
  	     *     var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 });
  	     */
  	    C.PBKDF2 = function (password, salt, cfg) {
  	        return PBKDF2.create(cfg).compute(password, salt);
  	    };
  	}());
  
  
  	return CryptoJS.PBKDF2;
  
  }));
  },{"./core":34,"./hmac":39,"./sha1":58}],54:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var StreamCipher = C_lib.StreamCipher;
  	    var C_algo = C.algo;
  
  	    // Reusable objects
  	    var S  = [];
  	    var C_ = [];
  	    var G  = [];
  
  	    /**
  	     * Rabbit stream cipher algorithm.
  	     *
  	     * This is a legacy version that neglected to convert the key to little-endian.
  	     * This error doesn't affect the cipher's security,
  	     * but it does affect its compatibility with other implementations.
  	     */
  	    var RabbitLegacy = C_algo.RabbitLegacy = StreamCipher.extend({
  	        _doReset: function () {
  	            // Shortcuts
  	            var K = this._key.words;
  	            var iv = this.cfg.iv;
  
  	            // Generate initial state values
  	            var X = this._X = [
  	                K[0], (K[3] << 16) | (K[2] >>> 16),
  	                K[1], (K[0] << 16) | (K[3] >>> 16),
  	                K[2], (K[1] << 16) | (K[0] >>> 16),
  	                K[3], (K[2] << 16) | (K[1] >>> 16)
  	            ];
  
  	            // Generate initial counter values
  	            var C = this._C = [
  	                (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff),
  	                (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff),
  	                (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff),
  	                (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff)
  	            ];
  
  	            // Carry bit
  	            this._b = 0;
  
  	            // Iterate the system four times
  	            for (var i = 0; i < 4; i++) {
  	                nextState.call(this);
  	            }
  
  	            // Modify the counters
  	            for (var i = 0; i < 8; i++) {
  	                C[i] ^= X[(i + 4) & 7];
  	            }
  
  	            // IV setup
  	            if (iv) {
  	                // Shortcuts
  	                var IV = iv.words;
  	                var IV_0 = IV[0];
  	                var IV_1 = IV[1];
  
  	                // Generate four subvectors
  	                var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00);
  	                var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00);
  	                var i1 = (i0 >>> 16) | (i2 & 0xffff0000);
  	                var i3 = (i2 << 16)  | (i0 & 0x0000ffff);
  
  	                // Modify counter values
  	                C[0] ^= i0;
  	                C[1] ^= i1;
  	                C[2] ^= i2;
  	                C[3] ^= i3;
  	                C[4] ^= i0;
  	                C[5] ^= i1;
  	                C[6] ^= i2;
  	                C[7] ^= i3;
  
  	                // Iterate the system four times
  	                for (var i = 0; i < 4; i++) {
  	                    nextState.call(this);
  	                }
  	            }
  	        },
  
  	        _doProcessBlock: function (M, offset) {
  	            // Shortcut
  	            var X = this._X;
  
  	            // Iterate the system
  	            nextState.call(this);
  
  	            // Generate four keystream words
  	            S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16);
  	            S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16);
  	            S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16);
  	            S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16);
  
  	            for (var i = 0; i < 4; i++) {
  	                // Swap endian
  	                S[i] = (((S[i] << 8)  | (S[i] >>> 24)) & 0x00ff00ff) |
  	                       (((S[i] << 24) | (S[i] >>> 8))  & 0xff00ff00);
  
  	                // Encrypt
  	                M[offset + i] ^= S[i];
  	            }
  	        },
  
  	        blockSize: 128/32,
  
  	        ivSize: 64/32
  	    });
  
  	    function nextState() {
  	        // Shortcuts
  	        var X = this._X;
  	        var C = this._C;
  
  	        // Save old counter values
  	        for (var i = 0; i < 8; i++) {
  	            C_[i] = C[i];
  	        }
  
  	        // Calculate new counter values
  	        C[0] = (C[0] + 0x4d34d34d + this._b) | 0;
  	        C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0;
  	        C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0;
  	        C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0;
  	        C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0;
  	        C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0;
  	        C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0;
  	        C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0;
  	        this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0;
  
  	        // Calculate the g-values
  	        for (var i = 0; i < 8; i++) {
  	            var gx = X[i] + C[i];
  
  	            // Construct high and low argument for squaring
  	            var ga = gx & 0xffff;
  	            var gb = gx >>> 16;
  
  	            // Calculate high and low result of squaring
  	            var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb;
  	            var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0);
  
  	            // High XOR low
  	            G[i] = gh ^ gl;
  	        }
  
  	        // Calculate new state values
  	        X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0;
  	        X[1] = (G[1] + ((G[0] << 8)  | (G[0] >>> 24)) + G[7]) | 0;
  	        X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0;
  	        X[3] = (G[3] + ((G[2] << 8)  | (G[2] >>> 24)) + G[1]) | 0;
  	        X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0;
  	        X[5] = (G[5] + ((G[4] << 8)  | (G[4] >>> 24)) + G[3]) | 0;
  	        X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0;
  	        X[7] = (G[7] + ((G[6] << 8)  | (G[6] >>> 24)) + G[5]) | 0;
  	    }
  
  	    /**
  	     * Shortcut functions to the cipher's object interface.
  	     *
  	     * @example
  	     *
  	     *     var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg);
  	     *     var plaintext  = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg);
  	     */
  	    C.RabbitLegacy = StreamCipher._createHelper(RabbitLegacy);
  	}());
  
  
  	return CryptoJS.RabbitLegacy;
  
  }));
  },{"./cipher-core":33,"./core":34,"./enc-base64":35,"./evpkdf":37,"./md5":42}],55:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var StreamCipher = C_lib.StreamCipher;
  	    var C_algo = C.algo;
  
  	    // Reusable objects
  	    var S  = [];
  	    var C_ = [];
  	    var G  = [];
  
  	    /**
  	     * Rabbit stream cipher algorithm
  	     */
  	    var Rabbit = C_algo.Rabbit = StreamCipher.extend({
  	        _doReset: function () {
  	            // Shortcuts
  	            var K = this._key.words;
  	            var iv = this.cfg.iv;
  
  	            // Swap endian
  	            for (var i = 0; i < 4; i++) {
  	                K[i] = (((K[i] << 8)  | (K[i] >>> 24)) & 0x00ff00ff) |
  	                       (((K[i] << 24) | (K[i] >>> 8))  & 0xff00ff00);
  	            }
  
  	            // Generate initial state values
  	            var X = this._X = [
  	                K[0], (K[3] << 16) | (K[2] >>> 16),
  	                K[1], (K[0] << 16) | (K[3] >>> 16),
  	                K[2], (K[1] << 16) | (K[0] >>> 16),
  	                K[3], (K[2] << 16) | (K[1] >>> 16)
  	            ];
  
  	            // Generate initial counter values
  	            var C = this._C = [
  	                (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff),
  	                (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff),
  	                (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff),
  	                (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff)
  	            ];
  
  	            // Carry bit
  	            this._b = 0;
  
  	            // Iterate the system four times
  	            for (var i = 0; i < 4; i++) {
  	                nextState.call(this);
  	            }
  
  	            // Modify the counters
  	            for (var i = 0; i < 8; i++) {
  	                C[i] ^= X[(i + 4) & 7];
  	            }
  
  	            // IV setup
  	            if (iv) {
  	                // Shortcuts
  	                var IV = iv.words;
  	                var IV_0 = IV[0];
  	                var IV_1 = IV[1];
  
  	                // Generate four subvectors
  	                var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00);
  	                var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00);
  	                var i1 = (i0 >>> 16) | (i2 & 0xffff0000);
  	                var i3 = (i2 << 16)  | (i0 & 0x0000ffff);
  
  	                // Modify counter values
  	                C[0] ^= i0;
  	                C[1] ^= i1;
  	                C[2] ^= i2;
  	                C[3] ^= i3;
  	                C[4] ^= i0;
  	                C[5] ^= i1;
  	                C[6] ^= i2;
  	                C[7] ^= i3;
  
  	                // Iterate the system four times
  	                for (var i = 0; i < 4; i++) {
  	                    nextState.call(this);
  	                }
  	            }
  	        },
  
  	        _doProcessBlock: function (M, offset) {
  	            // Shortcut
  	            var X = this._X;
  
  	            // Iterate the system
  	            nextState.call(this);
  
  	            // Generate four keystream words
  	            S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16);
  	            S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16);
  	            S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16);
  	            S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16);
  
  	            for (var i = 0; i < 4; i++) {
  	                // Swap endian
  	                S[i] = (((S[i] << 8)  | (S[i] >>> 24)) & 0x00ff00ff) |
  	                       (((S[i] << 24) | (S[i] >>> 8))  & 0xff00ff00);
  
  	                // Encrypt
  	                M[offset + i] ^= S[i];
  	            }
  	        },
  
  	        blockSize: 128/32,
  
  	        ivSize: 64/32
  	    });
  
  	    function nextState() {
  	        // Shortcuts
  	        var X = this._X;
  	        var C = this._C;
  
  	        // Save old counter values
  	        for (var i = 0; i < 8; i++) {
  	            C_[i] = C[i];
  	        }
  
  	        // Calculate new counter values
  	        C[0] = (C[0] + 0x4d34d34d + this._b) | 0;
  	        C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0;
  	        C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0;
  	        C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0;
  	        C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0;
  	        C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0;
  	        C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0;
  	        C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0;
  	        this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0;
  
  	        // Calculate the g-values
  	        for (var i = 0; i < 8; i++) {
  	            var gx = X[i] + C[i];
  
  	            // Construct high and low argument for squaring
  	            var ga = gx & 0xffff;
  	            var gb = gx >>> 16;
  
  	            // Calculate high and low result of squaring
  	            var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb;
  	            var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0);
  
  	            // High XOR low
  	            G[i] = gh ^ gl;
  	        }
  
  	        // Calculate new state values
  	        X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0;
  	        X[1] = (G[1] + ((G[0] << 8)  | (G[0] >>> 24)) + G[7]) | 0;
  	        X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0;
  	        X[3] = (G[3] + ((G[2] << 8)  | (G[2] >>> 24)) + G[1]) | 0;
  	        X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0;
  	        X[5] = (G[5] + ((G[4] << 8)  | (G[4] >>> 24)) + G[3]) | 0;
  	        X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0;
  	        X[7] = (G[7] + ((G[6] << 8)  | (G[6] >>> 24)) + G[5]) | 0;
  	    }
  
  	    /**
  	     * Shortcut functions to the cipher's object interface.
  	     *
  	     * @example
  	     *
  	     *     var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg);
  	     *     var plaintext  = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg);
  	     */
  	    C.Rabbit = StreamCipher._createHelper(Rabbit);
  	}());
  
  
  	return CryptoJS.Rabbit;
  
  }));
  },{"./cipher-core":33,"./core":34,"./enc-base64":35,"./evpkdf":37,"./md5":42}],56:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var StreamCipher = C_lib.StreamCipher;
  	    var C_algo = C.algo;
  
  	    /**
  	     * RC4 stream cipher algorithm.
  	     */
  	    var RC4 = C_algo.RC4 = StreamCipher.extend({
  	        _doReset: function () {
  	            // Shortcuts
  	            var key = this._key;
  	            var keyWords = key.words;
  	            var keySigBytes = key.sigBytes;
  
  	            // Init sbox
  	            var S = this._S = [];
  	            for (var i = 0; i < 256; i++) {
  	                S[i] = i;
  	            }
  
  	            // Key setup
  	            for (var i = 0, j = 0; i < 256; i++) {
  	                var keyByteIndex = i % keySigBytes;
  	                var keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff;
  
  	                j = (j + S[i] + keyByte) % 256;
  
  	                // Swap
  	                var t = S[i];
  	                S[i] = S[j];
  	                S[j] = t;
  	            }
  
  	            // Counters
  	            this._i = this._j = 0;
  	        },
  
  	        _doProcessBlock: function (M, offset) {
  	            M[offset] ^= generateKeystreamWord.call(this);
  	        },
  
  	        keySize: 256/32,
  
  	        ivSize: 0
  	    });
  
  	    function generateKeystreamWord() {
  	        // Shortcuts
  	        var S = this._S;
  	        var i = this._i;
  	        var j = this._j;
  
  	        // Generate keystream word
  	        var keystreamWord = 0;
  	        for (var n = 0; n < 4; n++) {
  	            i = (i + 1) % 256;
  	            j = (j + S[i]) % 256;
  
  	            // Swap
  	            var t = S[i];
  	            S[i] = S[j];
  	            S[j] = t;
  
  	            keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8);
  	        }
  
  	        // Update counters
  	        this._i = i;
  	        this._j = j;
  
  	        return keystreamWord;
  	    }
  
  	    /**
  	     * Shortcut functions to the cipher's object interface.
  	     *
  	     * @example
  	     *
  	     *     var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg);
  	     *     var plaintext  = CryptoJS.RC4.decrypt(ciphertext, key, cfg);
  	     */
  	    C.RC4 = StreamCipher._createHelper(RC4);
  
  	    /**
  	     * Modified RC4 stream cipher algorithm.
  	     */
  	    var RC4Drop = C_algo.RC4Drop = RC4.extend({
  	        /**
  	         * Configuration options.
  	         *
  	         * @property {number} drop The number of keystream words to drop. Default 192
  	         */
  	        cfg: RC4.cfg.extend({
  	            drop: 192
  	        }),
  
  	        _doReset: function () {
  	            RC4._doReset.call(this);
  
  	            // Drop
  	            for (var i = this.cfg.drop; i > 0; i--) {
  	                generateKeystreamWord.call(this);
  	            }
  	        }
  	    });
  
  	    /**
  	     * Shortcut functions to the cipher's object interface.
  	     *
  	     * @example
  	     *
  	     *     var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg);
  	     *     var plaintext  = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg);
  	     */
  	    C.RC4Drop = StreamCipher._createHelper(RC4Drop);
  	}());
  
  
  	return CryptoJS.RC4;
  
  }));
  },{"./cipher-core":33,"./core":34,"./enc-base64":35,"./evpkdf":37,"./md5":42}],57:[function(require,module,exports){
  ;(function (root, factory) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	/** @preserve
  	(c) 2012 by Cédric Mesnil. 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.
  
  	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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
  	*/
  
  	(function (Math) {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var WordArray = C_lib.WordArray;
  	    var Hasher = C_lib.Hasher;
  	    var C_algo = C.algo;
  
  	    // Constants table
  	    var _zl = WordArray.create([
  	        0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
  	        7,  4, 13,  1, 10,  6, 15,  3, 12,  0,  9,  5,  2, 14, 11,  8,
  	        3, 10, 14,  4,  9, 15,  8,  1,  2,  7,  0,  6, 13, 11,  5, 12,
  	        1,  9, 11, 10,  0,  8, 12,  4, 13,  3,  7, 15, 14,  5,  6,  2,
  	        4,  0,  5,  9,  7, 12,  2, 10, 14,  1,  3,  8, 11,  6, 15, 13]);
  	    var _zr = WordArray.create([
  	        5, 14,  7,  0,  9,  2, 11,  4, 13,  6, 15,  8,  1, 10,  3, 12,
  	        6, 11,  3,  7,  0, 13,  5, 10, 14, 15,  8, 12,  4,  9,  1,  2,
  	        15,  5,  1,  3,  7, 14,  6,  9, 11,  8, 12,  2, 10,  0,  4, 13,
  	        8,  6,  4,  1,  3, 11, 15,  0,  5, 12,  2, 13,  9,  7, 10, 14,
  	        12, 15, 10,  4,  1,  5,  8,  7,  6,  2, 13, 14,  0,  3,  9, 11]);
  	    var _sl = WordArray.create([
  	         11, 14, 15, 12,  5,  8,  7,  9, 11, 13, 14, 15,  6,  7,  9,  8,
  	        7, 6,   8, 13, 11,  9,  7, 15,  7, 12, 15,  9, 11,  7, 13, 12,
  	        11, 13,  6,  7, 14,  9, 13, 15, 14,  8, 13,  6,  5, 12,  7,  5,
  	          11, 12, 14, 15, 14, 15,  9,  8,  9, 14,  5,  6,  8,  6,  5, 12,
  	        9, 15,  5, 11,  6,  8, 13, 12,  5, 12, 13, 14, 11,  8,  5,  6 ]);
  	    var _sr = WordArray.create([
  	        8,  9,  9, 11, 13, 15, 15,  5,  7,  7,  8, 11, 14, 14, 12,  6,
  	        9, 13, 15,  7, 12,  8,  9, 11,  7,  7, 12,  7,  6, 15, 13, 11,
  	        9,  7, 15, 11,  8,  6,  6, 14, 12, 13,  5, 14, 13, 13,  7,  5,
  	        15,  5,  8, 11, 14, 14,  6, 14,  6,  9, 12,  9, 12,  5, 15,  8,
  	        8,  5, 12,  9, 12,  5, 14,  6,  8, 13,  6,  5, 15, 13, 11, 11 ]);
  
  	    var _hl =  WordArray.create([ 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]);
  	    var _hr =  WordArray.create([ 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]);
  
  	    /**
  	     * RIPEMD160 hash algorithm.
  	     */
  	    var RIPEMD160 = C_algo.RIPEMD160 = Hasher.extend({
  	        _doReset: function () {
  	            this._hash  = WordArray.create([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]);
  	        },
  
  	        _doProcessBlock: function (M, offset) {
  
  	            // Swap endian
  	            for (var i = 0; i < 16; i++) {
  	                // Shortcuts
  	                var offset_i = offset + i;
  	                var M_offset_i = M[offset_i];
  
  	                // Swap
  	                M[offset_i] = (
  	                    (((M_offset_i << 8)  | (M_offset_i >>> 24)) & 0x00ff00ff) |
  	                    (((M_offset_i << 24) | (M_offset_i >>> 8))  & 0xff00ff00)
  	                );
  	            }
  	            // Shortcut
  	            var H  = this._hash.words;
  	            var hl = _hl.words;
  	            var hr = _hr.words;
  	            var zl = _zl.words;
  	            var zr = _zr.words;
  	            var sl = _sl.words;
  	            var sr = _sr.words;
  
  	            // Working variables
  	            var al, bl, cl, dl, el;
  	            var ar, br, cr, dr, er;
  
  	            ar = al = H[0];
  	            br = bl = H[1];
  	            cr = cl = H[2];
  	            dr = dl = H[3];
  	            er = el = H[4];
  	            // Computation
  	            var t;
  	            for (var i = 0; i < 80; i += 1) {
  	                t = (al +  M[offset+zl[i]])|0;
  	                if (i<16){
  		            t +=  f1(bl,cl,dl) + hl[0];
  	                } else if (i<32) {
  		            t +=  f2(bl,cl,dl) + hl[1];
  	                } else if (i<48) {
  		            t +=  f3(bl,cl,dl) + hl[2];
  	                } else if (i<64) {
  		            t +=  f4(bl,cl,dl) + hl[3];
  	                } else {// if (i<80) {
  		            t +=  f5(bl,cl,dl) + hl[4];
  	                }
  	                t = t|0;
  	                t =  rotl(t,sl[i]);
  	                t = (t+el)|0;
  	                al = el;
  	                el = dl;
  	                dl = rotl(cl, 10);
  	                cl = bl;
  	                bl = t;
  
  	                t = (ar + M[offset+zr[i]])|0;
  	                if (i<16){
  		            t +=  f5(br,cr,dr) + hr[0];
  	                } else if (i<32) {
  		            t +=  f4(br,cr,dr) + hr[1];
  	                } else if (i<48) {
  		            t +=  f3(br,cr,dr) + hr[2];
  	                } else if (i<64) {
  		            t +=  f2(br,cr,dr) + hr[3];
  	                } else {// if (i<80) {
  		            t +=  f1(br,cr,dr) + hr[4];
  	                }
  	                t = t|0;
  	                t =  rotl(t,sr[i]) ;
  	                t = (t+er)|0;
  	                ar = er;
  	                er = dr;
  	                dr = rotl(cr, 10);
  	                cr = br;
  	                br = t;
  	            }
  	            // Intermediate hash value
  	            t    = (H[1] + cl + dr)|0;
  	            H[1] = (H[2] + dl + er)|0;
  	            H[2] = (H[3] + el + ar)|0;
  	            H[3] = (H[4] + al + br)|0;
  	            H[4] = (H[0] + bl + cr)|0;
  	            H[0] =  t;
  	        },
  
  	        _doFinalize: function () {
  	            // Shortcuts
  	            var data = this._data;
  	            var dataWords = data.words;
  
  	            var nBitsTotal = this._nDataBytes * 8;
  	            var nBitsLeft = data.sigBytes * 8;
  
  	            // Add padding
  	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
  	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
  	                (((nBitsTotal << 8)  | (nBitsTotal >>> 24)) & 0x00ff00ff) |
  	                (((nBitsTotal << 24) | (nBitsTotal >>> 8))  & 0xff00ff00)
  	            );
  	            data.sigBytes = (dataWords.length + 1) * 4;
  
  	            // Hash final blocks
  	            this._process();
  
  	            // Shortcuts
  	            var hash = this._hash;
  	            var H = hash.words;
  
  	            // Swap endian
  	            for (var i = 0; i < 5; i++) {
  	                // Shortcut
  	                var H_i = H[i];
  
  	                // Swap
  	                H[i] = (((H_i << 8)  | (H_i >>> 24)) & 0x00ff00ff) |
  	                       (((H_i << 24) | (H_i >>> 8))  & 0xff00ff00);
  	            }
  
  	            // Return final computed hash
  	            return hash;
  	        },
  
  	        clone: function () {
  	            var clone = Hasher.clone.call(this);
  	            clone._hash = this._hash.clone();
  
  	            return clone;
  	        }
  	    });
  
  
  	    function f1(x, y, z) {
  	        return ((x) ^ (y) ^ (z));
  
  	    }
  
  	    function f2(x, y, z) {
  	        return (((x)&(y)) | ((~x)&(z)));
  	    }
  
  	    function f3(x, y, z) {
  	        return (((x) | (~(y))) ^ (z));
  	    }
  
  	    function f4(x, y, z) {
  	        return (((x) & (z)) | ((y)&(~(z))));
  	    }
  
  	    function f5(x, y, z) {
  	        return ((x) ^ ((y) |(~(z))));
  
  	    }
  
  	    function rotl(x,n) {
  	        return (x<<n) | (x>>>(32-n));
  	    }
  
  
  	    /**
  	     * Shortcut function to the hasher's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     *
  	     * @return {WordArray} The hash.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hash = CryptoJS.RIPEMD160('message');
  	     *     var hash = CryptoJS.RIPEMD160(wordArray);
  	     */
  	    C.RIPEMD160 = Hasher._createHelper(RIPEMD160);
  
  	    /**
  	     * Shortcut function to the HMAC's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     * @param {WordArray|string} key The secret key.
  	     *
  	     * @return {WordArray} The HMAC.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hmac = CryptoJS.HmacRIPEMD160(message, key);
  	     */
  	    C.HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160);
  	}(Math));
  
  
  	return CryptoJS.RIPEMD160;
  
  }));
  },{"./core":34}],58:[function(require,module,exports){
  ;(function (root, factory) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var WordArray = C_lib.WordArray;
  	    var Hasher = C_lib.Hasher;
  	    var C_algo = C.algo;
  
  	    // Reusable object
  	    var W = [];
  
  	    /**
  	     * SHA-1 hash algorithm.
  	     */
  	    var SHA1 = C_algo.SHA1 = Hasher.extend({
  	        _doReset: function () {
  	            this._hash = new WordArray.init([
  	                0x67452301, 0xefcdab89,
  	                0x98badcfe, 0x10325476,
  	                0xc3d2e1f0
  	            ]);
  	        },
  
  	        _doProcessBlock: function (M, offset) {
  	            // Shortcut
  	            var H = this._hash.words;
  
  	            // Working variables
  	            var a = H[0];
  	            var b = H[1];
  	            var c = H[2];
  	            var d = H[3];
  	            var e = H[4];
  
  	            // Computation
  	            for (var i = 0; i < 80; i++) {
  	                if (i < 16) {
  	                    W[i] = M[offset + i] | 0;
  	                } else {
  	                    var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
  	                    W[i] = (n << 1) | (n >>> 31);
  	                }
  
  	                var t = ((a << 5) | (a >>> 27)) + e + W[i];
  	                if (i < 20) {
  	                    t += ((b & c) | (~b & d)) + 0x5a827999;
  	                } else if (i < 40) {
  	                    t += (b ^ c ^ d) + 0x6ed9eba1;
  	                } else if (i < 60) {
  	                    t += ((b & c) | (b & d) | (c & d)) - 0x70e44324;
  	                } else /* if (i < 80) */ {
  	                    t += (b ^ c ^ d) - 0x359d3e2a;
  	                }
  
  	                e = d;
  	                d = c;
  	                c = (b << 30) | (b >>> 2);
  	                b = a;
  	                a = t;
  	            }
  
  	            // Intermediate hash value
  	            H[0] = (H[0] + a) | 0;
  	            H[1] = (H[1] + b) | 0;
  	            H[2] = (H[2] + c) | 0;
  	            H[3] = (H[3] + d) | 0;
  	            H[4] = (H[4] + e) | 0;
  	        },
  
  	        _doFinalize: function () {
  	            // Shortcuts
  	            var data = this._data;
  	            var dataWords = data.words;
  
  	            var nBitsTotal = this._nDataBytes * 8;
  	            var nBitsLeft = data.sigBytes * 8;
  
  	            // Add padding
  	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
  	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
  	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
  	            data.sigBytes = dataWords.length * 4;
  
  	            // Hash final blocks
  	            this._process();
  
  	            // Return final computed hash
  	            return this._hash;
  	        },
  
  	        clone: function () {
  	            var clone = Hasher.clone.call(this);
  	            clone._hash = this._hash.clone();
  
  	            return clone;
  	        }
  	    });
  
  	    /**
  	     * Shortcut function to the hasher's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     *
  	     * @return {WordArray} The hash.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hash = CryptoJS.SHA1('message');
  	     *     var hash = CryptoJS.SHA1(wordArray);
  	     */
  	    C.SHA1 = Hasher._createHelper(SHA1);
  
  	    /**
  	     * Shortcut function to the HMAC's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     * @param {WordArray|string} key The secret key.
  	     *
  	     * @return {WordArray} The HMAC.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hmac = CryptoJS.HmacSHA1(message, key);
  	     */
  	    C.HmacSHA1 = Hasher._createHmacHelper(SHA1);
  	}());
  
  
  	return CryptoJS.SHA1;
  
  }));
  },{"./core":34}],59:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./sha256"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./sha256"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var WordArray = C_lib.WordArray;
  	    var C_algo = C.algo;
  	    var SHA256 = C_algo.SHA256;
  
  	    /**
  	     * SHA-224 hash algorithm.
  	     */
  	    var SHA224 = C_algo.SHA224 = SHA256.extend({
  	        _doReset: function () {
  	            this._hash = new WordArray.init([
  	                0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
  	                0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
  	            ]);
  	        },
  
  	        _doFinalize: function () {
  	            var hash = SHA256._doFinalize.call(this);
  
  	            hash.sigBytes -= 4;
  
  	            return hash;
  	        }
  	    });
  
  	    /**
  	     * Shortcut function to the hasher's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     *
  	     * @return {WordArray} The hash.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hash = CryptoJS.SHA224('message');
  	     *     var hash = CryptoJS.SHA224(wordArray);
  	     */
  	    C.SHA224 = SHA256._createHelper(SHA224);
  
  	    /**
  	     * Shortcut function to the HMAC's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     * @param {WordArray|string} key The secret key.
  	     *
  	     * @return {WordArray} The HMAC.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hmac = CryptoJS.HmacSHA224(message, key);
  	     */
  	    C.HmacSHA224 = SHA256._createHmacHelper(SHA224);
  	}());
  
  
  	return CryptoJS.SHA224;
  
  }));
  },{"./core":34,"./sha256":60}],60:[function(require,module,exports){
  ;(function (root, factory) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function (Math) {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var WordArray = C_lib.WordArray;
  	    var Hasher = C_lib.Hasher;
  	    var C_algo = C.algo;
  
  	    // Initialization and round constants tables
  	    var H = [];
  	    var K = [];
  
  	    // Compute constants
  	    (function () {
  	        function isPrime(n) {
  	            var sqrtN = Math.sqrt(n);
  	            for (var factor = 2; factor <= sqrtN; factor++) {
  	                if (!(n % factor)) {
  	                    return false;
  	                }
  	            }
  
  	            return true;
  	        }
  
  	        function getFractionalBits(n) {
  	            return ((n - (n | 0)) * 0x100000000) | 0;
  	        }
  
  	        var n = 2;
  	        var nPrime = 0;
  	        while (nPrime < 64) {
  	            if (isPrime(n)) {
  	                if (nPrime < 8) {
  	                    H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
  	                }
  	                K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));
  
  	                nPrime++;
  	            }
  
  	            n++;
  	        }
  	    }());
  
  	    // Reusable object
  	    var W = [];
  
  	    /**
  	     * SHA-256 hash algorithm.
  	     */
  	    var SHA256 = C_algo.SHA256 = Hasher.extend({
  	        _doReset: function () {
  	            this._hash = new WordArray.init(H.slice(0));
  	        },
  
  	        _doProcessBlock: function (M, offset) {
  	            // Shortcut
  	            var H = this._hash.words;
  
  	            // Working variables
  	            var a = H[0];
  	            var b = H[1];
  	            var c = H[2];
  	            var d = H[3];
  	            var e = H[4];
  	            var f = H[5];
  	            var g = H[6];
  	            var h = H[7];
  
  	            // Computation
  	            for (var i = 0; i < 64; i++) {
  	                if (i < 16) {
  	                    W[i] = M[offset + i] | 0;
  	                } else {
  	                    var gamma0x = W[i - 15];
  	                    var gamma0  = ((gamma0x << 25) | (gamma0x >>> 7))  ^
  	                                  ((gamma0x << 14) | (gamma0x >>> 18)) ^
  	                                   (gamma0x >>> 3);
  
  	                    var gamma1x = W[i - 2];
  	                    var gamma1  = ((gamma1x << 15) | (gamma1x >>> 17)) ^
  	                                  ((gamma1x << 13) | (gamma1x >>> 19)) ^
  	                                   (gamma1x >>> 10);
  
  	                    W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
  	                }
  
  	                var ch  = (e & f) ^ (~e & g);
  	                var maj = (a & b) ^ (a & c) ^ (b & c);
  
  	                var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
  	                var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7)  | (e >>> 25));
  
  	                var t1 = h + sigma1 + ch + K[i] + W[i];
  	                var t2 = sigma0 + maj;
  
  	                h = g;
  	                g = f;
  	                f = e;
  	                e = (d + t1) | 0;
  	                d = c;
  	                c = b;
  	                b = a;
  	                a = (t1 + t2) | 0;
  	            }
  
  	            // Intermediate hash value
  	            H[0] = (H[0] + a) | 0;
  	            H[1] = (H[1] + b) | 0;
  	            H[2] = (H[2] + c) | 0;
  	            H[3] = (H[3] + d) | 0;
  	            H[4] = (H[4] + e) | 0;
  	            H[5] = (H[5] + f) | 0;
  	            H[6] = (H[6] + g) | 0;
  	            H[7] = (H[7] + h) | 0;
  	        },
  
  	        _doFinalize: function () {
  	            // Shortcuts
  	            var data = this._data;
  	            var dataWords = data.words;
  
  	            var nBitsTotal = this._nDataBytes * 8;
  	            var nBitsLeft = data.sigBytes * 8;
  
  	            // Add padding
  	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
  	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
  	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
  	            data.sigBytes = dataWords.length * 4;
  
  	            // Hash final blocks
  	            this._process();
  
  	            // Return final computed hash
  	            return this._hash;
  	        },
  
  	        clone: function () {
  	            var clone = Hasher.clone.call(this);
  	            clone._hash = this._hash.clone();
  
  	            return clone;
  	        }
  	    });
  
  	    /**
  	     * Shortcut function to the hasher's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     *
  	     * @return {WordArray} The hash.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hash = CryptoJS.SHA256('message');
  	     *     var hash = CryptoJS.SHA256(wordArray);
  	     */
  	    C.SHA256 = Hasher._createHelper(SHA256);
  
  	    /**
  	     * Shortcut function to the HMAC's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     * @param {WordArray|string} key The secret key.
  	     *
  	     * @return {WordArray} The HMAC.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hmac = CryptoJS.HmacSHA256(message, key);
  	     */
  	    C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
  	}(Math));
  
  
  	return CryptoJS.SHA256;
  
  }));
  },{"./core":34}],61:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./x64-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./x64-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function (Math) {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var WordArray = C_lib.WordArray;
  	    var Hasher = C_lib.Hasher;
  	    var C_x64 = C.x64;
  	    var X64Word = C_x64.Word;
  	    var C_algo = C.algo;
  
  	    // Constants tables
  	    var RHO_OFFSETS = [];
  	    var PI_INDEXES  = [];
  	    var ROUND_CONSTANTS = [];
  
  	    // Compute Constants
  	    (function () {
  	        // Compute rho offset constants
  	        var x = 1, y = 0;
  	        for (var t = 0; t < 24; t++) {
  	            RHO_OFFSETS[x + 5 * y] = ((t + 1) * (t + 2) / 2) % 64;
  
  	            var newX = y % 5;
  	            var newY = (2 * x + 3 * y) % 5;
  	            x = newX;
  	            y = newY;
  	        }
  
  	        // Compute pi index constants
  	        for (var x = 0; x < 5; x++) {
  	            for (var y = 0; y < 5; y++) {
  	                PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5;
  	            }
  	        }
  
  	        // Compute round constants
  	        var LFSR = 0x01;
  	        for (var i = 0; i < 24; i++) {
  	            var roundConstantMsw = 0;
  	            var roundConstantLsw = 0;
  
  	            for (var j = 0; j < 7; j++) {
  	                if (LFSR & 0x01) {
  	                    var bitPosition = (1 << j) - 1;
  	                    if (bitPosition < 32) {
  	                        roundConstantLsw ^= 1 << bitPosition;
  	                    } else /* if (bitPosition >= 32) */ {
  	                        roundConstantMsw ^= 1 << (bitPosition - 32);
  	                    }
  	                }
  
  	                // Compute next LFSR
  	                if (LFSR & 0x80) {
  	                    // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1
  	                    LFSR = (LFSR << 1) ^ 0x71;
  	                } else {
  	                    LFSR <<= 1;
  	                }
  	            }
  
  	            ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw);
  	        }
  	    }());
  
  	    // Reusable objects for temporary values
  	    var T = [];
  	    (function () {
  	        for (var i = 0; i < 25; i++) {
  	            T[i] = X64Word.create();
  	        }
  	    }());
  
  	    /**
  	     * SHA-3 hash algorithm.
  	     */
  	    var SHA3 = C_algo.SHA3 = Hasher.extend({
  	        /**
  	         * Configuration options.
  	         *
  	         * @property {number} outputLength
  	         *   The desired number of bits in the output hash.
  	         *   Only values permitted are: 224, 256, 384, 512.
  	         *   Default: 512
  	         */
  	        cfg: Hasher.cfg.extend({
  	            outputLength: 512
  	        }),
  
  	        _doReset: function () {
  	            var state = this._state = []
  	            for (var i = 0; i < 25; i++) {
  	                state[i] = new X64Word.init();
  	            }
  
  	            this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32;
  	        },
  
  	        _doProcessBlock: function (M, offset) {
  	            // Shortcuts
  	            var state = this._state;
  	            var nBlockSizeLanes = this.blockSize / 2;
  
  	            // Absorb
  	            for (var i = 0; i < nBlockSizeLanes; i++) {
  	                // Shortcuts
  	                var M2i  = M[offset + 2 * i];
  	                var M2i1 = M[offset + 2 * i + 1];
  
  	                // Swap endian
  	                M2i = (
  	                    (((M2i << 8)  | (M2i >>> 24)) & 0x00ff00ff) |
  	                    (((M2i << 24) | (M2i >>> 8))  & 0xff00ff00)
  	                );
  	                M2i1 = (
  	                    (((M2i1 << 8)  | (M2i1 >>> 24)) & 0x00ff00ff) |
  	                    (((M2i1 << 24) | (M2i1 >>> 8))  & 0xff00ff00)
  	                );
  
  	                // Absorb message into state
  	                var lane = state[i];
  	                lane.high ^= M2i1;
  	                lane.low  ^= M2i;
  	            }
  
  	            // Rounds
  	            for (var round = 0; round < 24; round++) {
  	                // Theta
  	                for (var x = 0; x < 5; x++) {
  	                    // Mix column lanes
  	                    var tMsw = 0, tLsw = 0;
  	                    for (var y = 0; y < 5; y++) {
  	                        var lane = state[x + 5 * y];
  	                        tMsw ^= lane.high;
  	                        tLsw ^= lane.low;
  	                    }
  
  	                    // Temporary values
  	                    var Tx = T[x];
  	                    Tx.high = tMsw;
  	                    Tx.low  = tLsw;
  	                }
  	                for (var x = 0; x < 5; x++) {
  	                    // Shortcuts
  	                    var Tx4 = T[(x + 4) % 5];
  	                    var Tx1 = T[(x + 1) % 5];
  	                    var Tx1Msw = Tx1.high;
  	                    var Tx1Lsw = Tx1.low;
  
  	                    // Mix surrounding columns
  	                    var tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31));
  	                    var tLsw = Tx4.low  ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31));
  	                    for (var y = 0; y < 5; y++) {
  	                        var lane = state[x + 5 * y];
  	                        lane.high ^= tMsw;
  	                        lane.low  ^= tLsw;
  	                    }
  	                }
  
  	                // Rho Pi
  	                for (var laneIndex = 1; laneIndex < 25; laneIndex++) {
  	                    // Shortcuts
  	                    var lane = state[laneIndex];
  	                    var laneMsw = lane.high;
  	                    var laneLsw = lane.low;
  	                    var rhoOffset = RHO_OFFSETS[laneIndex];
  
  	                    // Rotate lanes
  	                    if (rhoOffset < 32) {
  	                        var tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset));
  	                        var tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset));
  	                    } else /* if (rhoOffset >= 32) */ {
  	                        var tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset));
  	                        var tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset));
  	                    }
  
  	                    // Transpose lanes
  	                    var TPiLane = T[PI_INDEXES[laneIndex]];
  	                    TPiLane.high = tMsw;
  	                    TPiLane.low  = tLsw;
  	                }
  
  	                // Rho pi at x = y = 0
  	                var T0 = T[0];
  	                var state0 = state[0];
  	                T0.high = state0.high;
  	                T0.low  = state0.low;
  
  	                // Chi
  	                for (var x = 0; x < 5; x++) {
  	                    for (var y = 0; y < 5; y++) {
  	                        // Shortcuts
  	                        var laneIndex = x + 5 * y;
  	                        var lane = state[laneIndex];
  	                        var TLane = T[laneIndex];
  	                        var Tx1Lane = T[((x + 1) % 5) + 5 * y];
  	                        var Tx2Lane = T[((x + 2) % 5) + 5 * y];
  
  	                        // Mix rows
  	                        lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high);
  	                        lane.low  = TLane.low  ^ (~Tx1Lane.low  & Tx2Lane.low);
  	                    }
  	                }
  
  	                // Iota
  	                var lane = state[0];
  	                var roundConstant = ROUND_CONSTANTS[round];
  	                lane.high ^= roundConstant.high;
  	                lane.low  ^= roundConstant.low;;
  	            }
  	        },
  
  	        _doFinalize: function () {
  	            // Shortcuts
  	            var data = this._data;
  	            var dataWords = data.words;
  	            var nBitsTotal = this._nDataBytes * 8;
  	            var nBitsLeft = data.sigBytes * 8;
  	            var blockSizeBits = this.blockSize * 32;
  
  	            // Add padding
  	            dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32);
  	            dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80;
  	            data.sigBytes = dataWords.length * 4;
  
  	            // Hash final blocks
  	            this._process();
  
  	            // Shortcuts
  	            var state = this._state;
  	            var outputLengthBytes = this.cfg.outputLength / 8;
  	            var outputLengthLanes = outputLengthBytes / 8;
  
  	            // Squeeze
  	            var hashWords = [];
  	            for (var i = 0; i < outputLengthLanes; i++) {
  	                // Shortcuts
  	                var lane = state[i];
  	                var laneMsw = lane.high;
  	                var laneLsw = lane.low;
  
  	                // Swap endian
  	                laneMsw = (
  	                    (((laneMsw << 8)  | (laneMsw >>> 24)) & 0x00ff00ff) |
  	                    (((laneMsw << 24) | (laneMsw >>> 8))  & 0xff00ff00)
  	                );
  	                laneLsw = (
  	                    (((laneLsw << 8)  | (laneLsw >>> 24)) & 0x00ff00ff) |
  	                    (((laneLsw << 24) | (laneLsw >>> 8))  & 0xff00ff00)
  	                );
  
  	                // Squeeze state to retrieve hash
  	                hashWords.push(laneLsw);
  	                hashWords.push(laneMsw);
  	            }
  
  	            // Return final computed hash
  	            return new WordArray.init(hashWords, outputLengthBytes);
  	        },
  
  	        clone: function () {
  	            var clone = Hasher.clone.call(this);
  
  	            var state = clone._state = this._state.slice(0);
  	            for (var i = 0; i < 25; i++) {
  	                state[i] = state[i].clone();
  	            }
  
  	            return clone;
  	        }
  	    });
  
  	    /**
  	     * Shortcut function to the hasher's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     *
  	     * @return {WordArray} The hash.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hash = CryptoJS.SHA3('message');
  	     *     var hash = CryptoJS.SHA3(wordArray);
  	     */
  	    C.SHA3 = Hasher._createHelper(SHA3);
  
  	    /**
  	     * Shortcut function to the HMAC's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     * @param {WordArray|string} key The secret key.
  	     *
  	     * @return {WordArray} The HMAC.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hmac = CryptoJS.HmacSHA3(message, key);
  	     */
  	    C.HmacSHA3 = Hasher._createHmacHelper(SHA3);
  	}(Math));
  
  
  	return CryptoJS.SHA3;
  
  }));
  },{"./core":34,"./x64-core":65}],62:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./x64-core", "./sha512"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_x64 = C.x64;
  	    var X64Word = C_x64.Word;
  	    var X64WordArray = C_x64.WordArray;
  	    var C_algo = C.algo;
  	    var SHA512 = C_algo.SHA512;
  
  	    /**
  	     * SHA-384 hash algorithm.
  	     */
  	    var SHA384 = C_algo.SHA384 = SHA512.extend({
  	        _doReset: function () {
  	            this._hash = new X64WordArray.init([
  	                new X64Word.init(0xcbbb9d5d, 0xc1059ed8), new X64Word.init(0x629a292a, 0x367cd507),
  	                new X64Word.init(0x9159015a, 0x3070dd17), new X64Word.init(0x152fecd8, 0xf70e5939),
  	                new X64Word.init(0x67332667, 0xffc00b31), new X64Word.init(0x8eb44a87, 0x68581511),
  	                new X64Word.init(0xdb0c2e0d, 0x64f98fa7), new X64Word.init(0x47b5481d, 0xbefa4fa4)
  	            ]);
  	        },
  
  	        _doFinalize: function () {
  	            var hash = SHA512._doFinalize.call(this);
  
  	            hash.sigBytes -= 16;
  
  	            return hash;
  	        }
  	    });
  
  	    /**
  	     * Shortcut function to the hasher's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     *
  	     * @return {WordArray} The hash.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hash = CryptoJS.SHA384('message');
  	     *     var hash = CryptoJS.SHA384(wordArray);
  	     */
  	    C.SHA384 = SHA512._createHelper(SHA384);
  
  	    /**
  	     * Shortcut function to the HMAC's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     * @param {WordArray|string} key The secret key.
  	     *
  	     * @return {WordArray} The HMAC.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hmac = CryptoJS.HmacSHA384(message, key);
  	     */
  	    C.HmacSHA384 = SHA512._createHmacHelper(SHA384);
  	}());
  
  
  	return CryptoJS.SHA384;
  
  }));
  },{"./core":34,"./sha512":63,"./x64-core":65}],63:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./x64-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./x64-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var Hasher = C_lib.Hasher;
  	    var C_x64 = C.x64;
  	    var X64Word = C_x64.Word;
  	    var X64WordArray = C_x64.WordArray;
  	    var C_algo = C.algo;
  
  	    function X64Word_create() {
  	        return X64Word.create.apply(X64Word, arguments);
  	    }
  
  	    // Constants
  	    var K = [
  	        X64Word_create(0x428a2f98, 0xd728ae22), X64Word_create(0x71374491, 0x23ef65cd),
  	        X64Word_create(0xb5c0fbcf, 0xec4d3b2f), X64Word_create(0xe9b5dba5, 0x8189dbbc),
  	        X64Word_create(0x3956c25b, 0xf348b538), X64Word_create(0x59f111f1, 0xb605d019),
  	        X64Word_create(0x923f82a4, 0xaf194f9b), X64Word_create(0xab1c5ed5, 0xda6d8118),
  	        X64Word_create(0xd807aa98, 0xa3030242), X64Word_create(0x12835b01, 0x45706fbe),
  	        X64Word_create(0x243185be, 0x4ee4b28c), X64Word_create(0x550c7dc3, 0xd5ffb4e2),
  	        X64Word_create(0x72be5d74, 0xf27b896f), X64Word_create(0x80deb1fe, 0x3b1696b1),
  	        X64Word_create(0x9bdc06a7, 0x25c71235), X64Word_create(0xc19bf174, 0xcf692694),
  	        X64Word_create(0xe49b69c1, 0x9ef14ad2), X64Word_create(0xefbe4786, 0x384f25e3),
  	        X64Word_create(0x0fc19dc6, 0x8b8cd5b5), X64Word_create(0x240ca1cc, 0x77ac9c65),
  	        X64Word_create(0x2de92c6f, 0x592b0275), X64Word_create(0x4a7484aa, 0x6ea6e483),
  	        X64Word_create(0x5cb0a9dc, 0xbd41fbd4), X64Word_create(0x76f988da, 0x831153b5),
  	        X64Word_create(0x983e5152, 0xee66dfab), X64Word_create(0xa831c66d, 0x2db43210),
  	        X64Word_create(0xb00327c8, 0x98fb213f), X64Word_create(0xbf597fc7, 0xbeef0ee4),
  	        X64Word_create(0xc6e00bf3, 0x3da88fc2), X64Word_create(0xd5a79147, 0x930aa725),
  	        X64Word_create(0x06ca6351, 0xe003826f), X64Word_create(0x14292967, 0x0a0e6e70),
  	        X64Word_create(0x27b70a85, 0x46d22ffc), X64Word_create(0x2e1b2138, 0x5c26c926),
  	        X64Word_create(0x4d2c6dfc, 0x5ac42aed), X64Word_create(0x53380d13, 0x9d95b3df),
  	        X64Word_create(0x650a7354, 0x8baf63de), X64Word_create(0x766a0abb, 0x3c77b2a8),
  	        X64Word_create(0x81c2c92e, 0x47edaee6), X64Word_create(0x92722c85, 0x1482353b),
  	        X64Word_create(0xa2bfe8a1, 0x4cf10364), X64Word_create(0xa81a664b, 0xbc423001),
  	        X64Word_create(0xc24b8b70, 0xd0f89791), X64Word_create(0xc76c51a3, 0x0654be30),
  	        X64Word_create(0xd192e819, 0xd6ef5218), X64Word_create(0xd6990624, 0x5565a910),
  	        X64Word_create(0xf40e3585, 0x5771202a), X64Word_create(0x106aa070, 0x32bbd1b8),
  	        X64Word_create(0x19a4c116, 0xb8d2d0c8), X64Word_create(0x1e376c08, 0x5141ab53),
  	        X64Word_create(0x2748774c, 0xdf8eeb99), X64Word_create(0x34b0bcb5, 0xe19b48a8),
  	        X64Word_create(0x391c0cb3, 0xc5c95a63), X64Word_create(0x4ed8aa4a, 0xe3418acb),
  	        X64Word_create(0x5b9cca4f, 0x7763e373), X64Word_create(0x682e6ff3, 0xd6b2b8a3),
  	        X64Word_create(0x748f82ee, 0x5defb2fc), X64Word_create(0x78a5636f, 0x43172f60),
  	        X64Word_create(0x84c87814, 0xa1f0ab72), X64Word_create(0x8cc70208, 0x1a6439ec),
  	        X64Word_create(0x90befffa, 0x23631e28), X64Word_create(0xa4506ceb, 0xde82bde9),
  	        X64Word_create(0xbef9a3f7, 0xb2c67915), X64Word_create(0xc67178f2, 0xe372532b),
  	        X64Word_create(0xca273ece, 0xea26619c), X64Word_create(0xd186b8c7, 0x21c0c207),
  	        X64Word_create(0xeada7dd6, 0xcde0eb1e), X64Word_create(0xf57d4f7f, 0xee6ed178),
  	        X64Word_create(0x06f067aa, 0x72176fba), X64Word_create(0x0a637dc5, 0xa2c898a6),
  	        X64Word_create(0x113f9804, 0xbef90dae), X64Word_create(0x1b710b35, 0x131c471b),
  	        X64Word_create(0x28db77f5, 0x23047d84), X64Word_create(0x32caab7b, 0x40c72493),
  	        X64Word_create(0x3c9ebe0a, 0x15c9bebc), X64Word_create(0x431d67c4, 0x9c100d4c),
  	        X64Word_create(0x4cc5d4be, 0xcb3e42b6), X64Word_create(0x597f299c, 0xfc657e2a),
  	        X64Word_create(0x5fcb6fab, 0x3ad6faec), X64Word_create(0x6c44198c, 0x4a475817)
  	    ];
  
  	    // Reusable objects
  	    var W = [];
  	    (function () {
  	        for (var i = 0; i < 80; i++) {
  	            W[i] = X64Word_create();
  	        }
  	    }());
  
  	    /**
  	     * SHA-512 hash algorithm.
  	     */
  	    var SHA512 = C_algo.SHA512 = Hasher.extend({
  	        _doReset: function () {
  	            this._hash = new X64WordArray.init([
  	                new X64Word.init(0x6a09e667, 0xf3bcc908), new X64Word.init(0xbb67ae85, 0x84caa73b),
  	                new X64Word.init(0x3c6ef372, 0xfe94f82b), new X64Word.init(0xa54ff53a, 0x5f1d36f1),
  	                new X64Word.init(0x510e527f, 0xade682d1), new X64Word.init(0x9b05688c, 0x2b3e6c1f),
  	                new X64Word.init(0x1f83d9ab, 0xfb41bd6b), new X64Word.init(0x5be0cd19, 0x137e2179)
  	            ]);
  	        },
  
  	        _doProcessBlock: function (M, offset) {
  	            // Shortcuts
  	            var H = this._hash.words;
  
  	            var H0 = H[0];
  	            var H1 = H[1];
  	            var H2 = H[2];
  	            var H3 = H[3];
  	            var H4 = H[4];
  	            var H5 = H[5];
  	            var H6 = H[6];
  	            var H7 = H[7];
  
  	            var H0h = H0.high;
  	            var H0l = H0.low;
  	            var H1h = H1.high;
  	            var H1l = H1.low;
  	            var H2h = H2.high;
  	            var H2l = H2.low;
  	            var H3h = H3.high;
  	            var H3l = H3.low;
  	            var H4h = H4.high;
  	            var H4l = H4.low;
  	            var H5h = H5.high;
  	            var H5l = H5.low;
  	            var H6h = H6.high;
  	            var H6l = H6.low;
  	            var H7h = H7.high;
  	            var H7l = H7.low;
  
  	            // Working variables
  	            var ah = H0h;
  	            var al = H0l;
  	            var bh = H1h;
  	            var bl = H1l;
  	            var ch = H2h;
  	            var cl = H2l;
  	            var dh = H3h;
  	            var dl = H3l;
  	            var eh = H4h;
  	            var el = H4l;
  	            var fh = H5h;
  	            var fl = H5l;
  	            var gh = H6h;
  	            var gl = H6l;
  	            var hh = H7h;
  	            var hl = H7l;
  
  	            // Rounds
  	            for (var i = 0; i < 80; i++) {
  	                // Shortcut
  	                var Wi = W[i];
  
  	                // Extend message
  	                if (i < 16) {
  	                    var Wih = Wi.high = M[offset + i * 2]     | 0;
  	                    var Wil = Wi.low  = M[offset + i * 2 + 1] | 0;
  	                } else {
  	                    // Gamma0
  	                    var gamma0x  = W[i - 15];
  	                    var gamma0xh = gamma0x.high;
  	                    var gamma0xl = gamma0x.low;
  	                    var gamma0h  = ((gamma0xh >>> 1) | (gamma0xl << 31)) ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) ^ (gamma0xh >>> 7);
  	                    var gamma0l  = ((gamma0xl >>> 1) | (gamma0xh << 31)) ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) ^ ((gamma0xl >>> 7) | (gamma0xh << 25));
  
  	                    // Gamma1
  	                    var gamma1x  = W[i - 2];
  	                    var gamma1xh = gamma1x.high;
  	                    var gamma1xl = gamma1x.low;
  	                    var gamma1h  = ((gamma1xh >>> 19) | (gamma1xl << 13)) ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) ^ (gamma1xh >>> 6);
  	                    var gamma1l  = ((gamma1xl >>> 19) | (gamma1xh << 13)) ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) ^ ((gamma1xl >>> 6) | (gamma1xh << 26));
  
  	                    // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]
  	                    var Wi7  = W[i - 7];
  	                    var Wi7h = Wi7.high;
  	                    var Wi7l = Wi7.low;
  
  	                    var Wi16  = W[i - 16];
  	                    var Wi16h = Wi16.high;
  	                    var Wi16l = Wi16.low;
  
  	                    var Wil = gamma0l + Wi7l;
  	                    var Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0);
  	                    var Wil = Wil + gamma1l;
  	                    var Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0);
  	                    var Wil = Wil + Wi16l;
  	                    var Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0);
  
  	                    Wi.high = Wih;
  	                    Wi.low  = Wil;
  	                }
  
  	                var chh  = (eh & fh) ^ (~eh & gh);
  	                var chl  = (el & fl) ^ (~el & gl);
  	                var majh = (ah & bh) ^ (ah & ch) ^ (bh & ch);
  	                var majl = (al & bl) ^ (al & cl) ^ (bl & cl);
  
  	                var sigma0h = ((ah >>> 28) | (al << 4))  ^ ((ah << 30)  | (al >>> 2)) ^ ((ah << 25) | (al >>> 7));
  	                var sigma0l = ((al >>> 28) | (ah << 4))  ^ ((al << 30)  | (ah >>> 2)) ^ ((al << 25) | (ah >>> 7));
  	                var sigma1h = ((eh >>> 14) | (el << 18)) ^ ((eh >>> 18) | (el << 14)) ^ ((eh << 23) | (el >>> 9));
  	                var sigma1l = ((el >>> 14) | (eh << 18)) ^ ((el >>> 18) | (eh << 14)) ^ ((el << 23) | (eh >>> 9));
  
  	                // t1 = h + sigma1 + ch + K[i] + W[i]
  	                var Ki  = K[i];
  	                var Kih = Ki.high;
  	                var Kil = Ki.low;
  
  	                var t1l = hl + sigma1l;
  	                var t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0);
  	                var t1l = t1l + chl;
  	                var t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0);
  	                var t1l = t1l + Kil;
  	                var t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0);
  	                var t1l = t1l + Wil;
  	                var t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0);
  
  	                // t2 = sigma0 + maj
  	                var t2l = sigma0l + majl;
  	                var t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0);
  
  	                // Update working variables
  	                hh = gh;
  	                hl = gl;
  	                gh = fh;
  	                gl = fl;
  	                fh = eh;
  	                fl = el;
  	                el = (dl + t1l) | 0;
  	                eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0;
  	                dh = ch;
  	                dl = cl;
  	                ch = bh;
  	                cl = bl;
  	                bh = ah;
  	                bl = al;
  	                al = (t1l + t2l) | 0;
  	                ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0;
  	            }
  
  	            // Intermediate hash value
  	            H0l = H0.low  = (H0l + al);
  	            H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0));
  	            H1l = H1.low  = (H1l + bl);
  	            H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0));
  	            H2l = H2.low  = (H2l + cl);
  	            H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0));
  	            H3l = H3.low  = (H3l + dl);
  	            H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0));
  	            H4l = H4.low  = (H4l + el);
  	            H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0));
  	            H5l = H5.low  = (H5l + fl);
  	            H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0));
  	            H6l = H6.low  = (H6l + gl);
  	            H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0));
  	            H7l = H7.low  = (H7l + hl);
  	            H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0));
  	        },
  
  	        _doFinalize: function () {
  	            // Shortcuts
  	            var data = this._data;
  	            var dataWords = data.words;
  
  	            var nBitsTotal = this._nDataBytes * 8;
  	            var nBitsLeft = data.sigBytes * 8;
  
  	            // Add padding
  	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
  	            dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000);
  	            dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal;
  	            data.sigBytes = dataWords.length * 4;
  
  	            // Hash final blocks
  	            this._process();
  
  	            // Convert hash to 32-bit word array before returning
  	            var hash = this._hash.toX32();
  
  	            // Return final computed hash
  	            return hash;
  	        },
  
  	        clone: function () {
  	            var clone = Hasher.clone.call(this);
  	            clone._hash = this._hash.clone();
  
  	            return clone;
  	        },
  
  	        blockSize: 1024/32
  	    });
  
  	    /**
  	     * Shortcut function to the hasher's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     *
  	     * @return {WordArray} The hash.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hash = CryptoJS.SHA512('message');
  	     *     var hash = CryptoJS.SHA512(wordArray);
  	     */
  	    C.SHA512 = Hasher._createHelper(SHA512);
  
  	    /**
  	     * Shortcut function to the HMAC's object interface.
  	     *
  	     * @param {WordArray|string} message The message to hash.
  	     * @param {WordArray|string} key The secret key.
  	     *
  	     * @return {WordArray} The HMAC.
  	     *
  	     * @static
  	     *
  	     * @example
  	     *
  	     *     var hmac = CryptoJS.HmacSHA512(message, key);
  	     */
  	    C.HmacSHA512 = Hasher._createHmacHelper(SHA512);
  	}());
  
  
  	return CryptoJS.SHA512;
  
  }));
  },{"./core":34,"./x64-core":65}],64:[function(require,module,exports){
  ;(function (root, factory, undef) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function () {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var WordArray = C_lib.WordArray;
  	    var BlockCipher = C_lib.BlockCipher;
  	    var C_algo = C.algo;
  
  	    // Permuted Choice 1 constants
  	    var PC1 = [
  	        57, 49, 41, 33, 25, 17, 9,  1,
  	        58, 50, 42, 34, 26, 18, 10, 2,
  	        59, 51, 43, 35, 27, 19, 11, 3,
  	        60, 52, 44, 36, 63, 55, 47, 39,
  	        31, 23, 15, 7,  62, 54, 46, 38,
  	        30, 22, 14, 6,  61, 53, 45, 37,
  	        29, 21, 13, 5,  28, 20, 12, 4
  	    ];
  
  	    // Permuted Choice 2 constants
  	    var PC2 = [
  	        14, 17, 11, 24, 1,  5,
  	        3,  28, 15, 6,  21, 10,
  	        23, 19, 12, 4,  26, 8,
  	        16, 7,  27, 20, 13, 2,
  	        41, 52, 31, 37, 47, 55,
  	        30, 40, 51, 45, 33, 48,
  	        44, 49, 39, 56, 34, 53,
  	        46, 42, 50, 36, 29, 32
  	    ];
  
  	    // Cumulative bit shift constants
  	    var BIT_SHIFTS = [1,  2,  4,  6,  8,  10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28];
  
  	    // SBOXes and round permutation constants
  	    var SBOX_P = [
  	        {
  	            0x0: 0x808200,
  	            0x10000000: 0x8000,
  	            0x20000000: 0x808002,
  	            0x30000000: 0x2,
  	            0x40000000: 0x200,
  	            0x50000000: 0x808202,
  	            0x60000000: 0x800202,
  	            0x70000000: 0x800000,
  	            0x80000000: 0x202,
  	            0x90000000: 0x800200,
  	            0xa0000000: 0x8200,
  	            0xb0000000: 0x808000,
  	            0xc0000000: 0x8002,
  	            0xd0000000: 0x800002,
  	            0xe0000000: 0x0,
  	            0xf0000000: 0x8202,
  	            0x8000000: 0x0,
  	            0x18000000: 0x808202,
  	            0x28000000: 0x8202,
  	            0x38000000: 0x8000,
  	            0x48000000: 0x808200,
  	            0x58000000: 0x200,
  	            0x68000000: 0x808002,
  	            0x78000000: 0x2,
  	            0x88000000: 0x800200,
  	            0x98000000: 0x8200,
  	            0xa8000000: 0x808000,
  	            0xb8000000: 0x800202,
  	            0xc8000000: 0x800002,
  	            0xd8000000: 0x8002,
  	            0xe8000000: 0x202,
  	            0xf8000000: 0x800000,
  	            0x1: 0x8000,
  	            0x10000001: 0x2,
  	            0x20000001: 0x808200,
  	            0x30000001: 0x800000,
  	            0x40000001: 0x808002,
  	            0x50000001: 0x8200,
  	            0x60000001: 0x200,
  	            0x70000001: 0x800202,
  	            0x80000001: 0x808202,
  	            0x90000001: 0x808000,
  	            0xa0000001: 0x800002,
  	            0xb0000001: 0x8202,
  	            0xc0000001: 0x202,
  	            0xd0000001: 0x800200,
  	            0xe0000001: 0x8002,
  	            0xf0000001: 0x0,
  	            0x8000001: 0x808202,
  	            0x18000001: 0x808000,
  	            0x28000001: 0x800000,
  	            0x38000001: 0x200,
  	            0x48000001: 0x8000,
  	            0x58000001: 0x800002,
  	            0x68000001: 0x2,
  	            0x78000001: 0x8202,
  	            0x88000001: 0x8002,
  	            0x98000001: 0x800202,
  	            0xa8000001: 0x202,
  	            0xb8000001: 0x808200,
  	            0xc8000001: 0x800200,
  	            0xd8000001: 0x0,
  	            0xe8000001: 0x8200,
  	            0xf8000001: 0x808002
  	        },
  	        {
  	            0x0: 0x40084010,
  	            0x1000000: 0x4000,
  	            0x2000000: 0x80000,
  	            0x3000000: 0x40080010,
  	            0x4000000: 0x40000010,
  	            0x5000000: 0x40084000,
  	            0x6000000: 0x40004000,
  	            0x7000000: 0x10,
  	            0x8000000: 0x84000,
  	            0x9000000: 0x40004010,
  	            0xa000000: 0x40000000,
  	            0xb000000: 0x84010,
  	            0xc000000: 0x80010,
  	            0xd000000: 0x0,
  	            0xe000000: 0x4010,
  	            0xf000000: 0x40080000,
  	            0x800000: 0x40004000,
  	            0x1800000: 0x84010,
  	            0x2800000: 0x10,
  	            0x3800000: 0x40004010,
  	            0x4800000: 0x40084010,
  	            0x5800000: 0x40000000,
  	            0x6800000: 0x80000,
  	            0x7800000: 0x40080010,
  	            0x8800000: 0x80010,
  	            0x9800000: 0x0,
  	            0xa800000: 0x4000,
  	            0xb800000: 0x40080000,
  	            0xc800000: 0x40000010,
  	            0xd800000: 0x84000,
  	            0xe800000: 0x40084000,
  	            0xf800000: 0x4010,
  	            0x10000000: 0x0,
  	            0x11000000: 0x40080010,
  	            0x12000000: 0x40004010,
  	            0x13000000: 0x40084000,
  	            0x14000000: 0x40080000,
  	            0x15000000: 0x10,
  	            0x16000000: 0x84010,
  	            0x17000000: 0x4000,
  	            0x18000000: 0x4010,
  	            0x19000000: 0x80000,
  	            0x1a000000: 0x80010,
  	            0x1b000000: 0x40000010,
  	            0x1c000000: 0x84000,
  	            0x1d000000: 0x40004000,
  	            0x1e000000: 0x40000000,
  	            0x1f000000: 0x40084010,
  	            0x10800000: 0x84010,
  	            0x11800000: 0x80000,
  	            0x12800000: 0x40080000,
  	            0x13800000: 0x4000,
  	            0x14800000: 0x40004000,
  	            0x15800000: 0x40084010,
  	            0x16800000: 0x10,
  	            0x17800000: 0x40000000,
  	            0x18800000: 0x40084000,
  	            0x19800000: 0x40000010,
  	            0x1a800000: 0x40004010,
  	            0x1b800000: 0x80010,
  	            0x1c800000: 0x0,
  	            0x1d800000: 0x4010,
  	            0x1e800000: 0x40080010,
  	            0x1f800000: 0x84000
  	        },
  	        {
  	            0x0: 0x104,
  	            0x100000: 0x0,
  	            0x200000: 0x4000100,
  	            0x300000: 0x10104,
  	            0x400000: 0x10004,
  	            0x500000: 0x4000004,
  	            0x600000: 0x4010104,
  	            0x700000: 0x4010000,
  	            0x800000: 0x4000000,
  	            0x900000: 0x4010100,
  	            0xa00000: 0x10100,
  	            0xb00000: 0x4010004,
  	            0xc00000: 0x4000104,
  	            0xd00000: 0x10000,
  	            0xe00000: 0x4,
  	            0xf00000: 0x100,
  	            0x80000: 0x4010100,
  	            0x180000: 0x4010004,
  	            0x280000: 0x0,
  	            0x380000: 0x4000100,
  	            0x480000: 0x4000004,
  	            0x580000: 0x10000,
  	            0x680000: 0x10004,
  	            0x780000: 0x104,
  	            0x880000: 0x4,
  	            0x980000: 0x100,
  	            0xa80000: 0x4010000,
  	            0xb80000: 0x10104,
  	            0xc80000: 0x10100,
  	            0xd80000: 0x4000104,
  	            0xe80000: 0x4010104,
  	            0xf80000: 0x4000000,
  	            0x1000000: 0x4010100,
  	            0x1100000: 0x10004,
  	            0x1200000: 0x10000,
  	            0x1300000: 0x4000100,
  	            0x1400000: 0x100,
  	            0x1500000: 0x4010104,
  	            0x1600000: 0x4000004,
  	            0x1700000: 0x0,
  	            0x1800000: 0x4000104,
  	            0x1900000: 0x4000000,
  	            0x1a00000: 0x4,
  	            0x1b00000: 0x10100,
  	            0x1c00000: 0x4010000,
  	            0x1d00000: 0x104,
  	            0x1e00000: 0x10104,
  	            0x1f00000: 0x4010004,
  	            0x1080000: 0x4000000,
  	            0x1180000: 0x104,
  	            0x1280000: 0x4010100,
  	            0x1380000: 0x0,
  	            0x1480000: 0x10004,
  	            0x1580000: 0x4000100,
  	            0x1680000: 0x100,
  	            0x1780000: 0x4010004,
  	            0x1880000: 0x10000,
  	            0x1980000: 0x4010104,
  	            0x1a80000: 0x10104,
  	            0x1b80000: 0x4000004,
  	            0x1c80000: 0x4000104,
  	            0x1d80000: 0x4010000,
  	            0x1e80000: 0x4,
  	            0x1f80000: 0x10100
  	        },
  	        {
  	            0x0: 0x80401000,
  	            0x10000: 0x80001040,
  	            0x20000: 0x401040,
  	            0x30000: 0x80400000,
  	            0x40000: 0x0,
  	            0x50000: 0x401000,
  	            0x60000: 0x80000040,
  	            0x70000: 0x400040,
  	            0x80000: 0x80000000,
  	            0x90000: 0x400000,
  	            0xa0000: 0x40,
  	            0xb0000: 0x80001000,
  	            0xc0000: 0x80400040,
  	            0xd0000: 0x1040,
  	            0xe0000: 0x1000,
  	            0xf0000: 0x80401040,
  	            0x8000: 0x80001040,
  	            0x18000: 0x40,
  	            0x28000: 0x80400040,
  	            0x38000: 0x80001000,
  	            0x48000: 0x401000,
  	            0x58000: 0x80401040,
  	            0x68000: 0x0,
  	            0x78000: 0x80400000,
  	            0x88000: 0x1000,
  	            0x98000: 0x80401000,
  	            0xa8000: 0x400000,
  	            0xb8000: 0x1040,
  	            0xc8000: 0x80000000,
  	            0xd8000: 0x400040,
  	            0xe8000: 0x401040,
  	            0xf8000: 0x80000040,
  	            0x100000: 0x400040,
  	            0x110000: 0x401000,
  	            0x120000: 0x80000040,
  	            0x130000: 0x0,
  	            0x140000: 0x1040,
  	            0x150000: 0x80400040,
  	            0x160000: 0x80401000,
  	            0x170000: 0x80001040,
  	            0x180000: 0x80401040,
  	            0x190000: 0x80000000,
  	            0x1a0000: 0x80400000,
  	            0x1b0000: 0x401040,
  	            0x1c0000: 0x80001000,
  	            0x1d0000: 0x400000,
  	            0x1e0000: 0x40,
  	            0x1f0000: 0x1000,
  	            0x108000: 0x80400000,
  	            0x118000: 0x80401040,
  	            0x128000: 0x0,
  	            0x138000: 0x401000,
  	            0x148000: 0x400040,
  	            0x158000: 0x80000000,
  	            0x168000: 0x80001040,
  	            0x178000: 0x40,
  	            0x188000: 0x80000040,
  	            0x198000: 0x1000,
  	            0x1a8000: 0x80001000,
  	            0x1b8000: 0x80400040,
  	            0x1c8000: 0x1040,
  	            0x1d8000: 0x80401000,
  	            0x1e8000: 0x400000,
  	            0x1f8000: 0x401040
  	        },
  	        {
  	            0x0: 0x80,
  	            0x1000: 0x1040000,
  	            0x2000: 0x40000,
  	            0x3000: 0x20000000,
  	            0x4000: 0x20040080,
  	            0x5000: 0x1000080,
  	            0x6000: 0x21000080,
  	            0x7000: 0x40080,
  	            0x8000: 0x1000000,
  	            0x9000: 0x20040000,
  	            0xa000: 0x20000080,
  	            0xb000: 0x21040080,
  	            0xc000: 0x21040000,
  	            0xd000: 0x0,
  	            0xe000: 0x1040080,
  	            0xf000: 0x21000000,
  	            0x800: 0x1040080,
  	            0x1800: 0x21000080,
  	            0x2800: 0x80,
  	            0x3800: 0x1040000,
  	            0x4800: 0x40000,
  	            0x5800: 0x20040080,
  	            0x6800: 0x21040000,
  	            0x7800: 0x20000000,
  	            0x8800: 0x20040000,
  	            0x9800: 0x0,
  	            0xa800: 0x21040080,
  	            0xb800: 0x1000080,
  	            0xc800: 0x20000080,
  	            0xd800: 0x21000000,
  	            0xe800: 0x1000000,
  	            0xf800: 0x40080,
  	            0x10000: 0x40000,
  	            0x11000: 0x80,
  	            0x12000: 0x20000000,
  	            0x13000: 0x21000080,
  	            0x14000: 0x1000080,
  	            0x15000: 0x21040000,
  	            0x16000: 0x20040080,
  	            0x17000: 0x1000000,
  	            0x18000: 0x21040080,
  	            0x19000: 0x21000000,
  	            0x1a000: 0x1040000,
  	            0x1b000: 0x20040000,
  	            0x1c000: 0x40080,
  	            0x1d000: 0x20000080,
  	            0x1e000: 0x0,
  	            0x1f000: 0x1040080,
  	            0x10800: 0x21000080,
  	            0x11800: 0x1000000,
  	            0x12800: 0x1040000,
  	            0x13800: 0x20040080,
  	            0x14800: 0x20000000,
  	            0x15800: 0x1040080,
  	            0x16800: 0x80,
  	            0x17800: 0x21040000,
  	            0x18800: 0x40080,
  	            0x19800: 0x21040080,
  	            0x1a800: 0x0,
  	            0x1b800: 0x21000000,
  	            0x1c800: 0x1000080,
  	            0x1d800: 0x40000,
  	            0x1e800: 0x20040000,
  	            0x1f800: 0x20000080
  	        },
  	        {
  	            0x0: 0x10000008,
  	            0x100: 0x2000,
  	            0x200: 0x10200000,
  	            0x300: 0x10202008,
  	            0x400: 0x10002000,
  	            0x500: 0x200000,
  	            0x600: 0x200008,
  	            0x700: 0x10000000,
  	            0x800: 0x0,
  	            0x900: 0x10002008,
  	            0xa00: 0x202000,
  	            0xb00: 0x8,
  	            0xc00: 0x10200008,
  	            0xd00: 0x202008,
  	            0xe00: 0x2008,
  	            0xf00: 0x10202000,
  	            0x80: 0x10200000,
  	            0x180: 0x10202008,
  	            0x280: 0x8,
  	            0x380: 0x200000,
  	            0x480: 0x202008,
  	            0x580: 0x10000008,
  	            0x680: 0x10002000,
  	            0x780: 0x2008,
  	            0x880: 0x200008,
  	            0x980: 0x2000,
  	            0xa80: 0x10002008,
  	            0xb80: 0x10200008,
  	            0xc80: 0x0,
  	            0xd80: 0x10202000,
  	            0xe80: 0x202000,
  	            0xf80: 0x10000000,
  	            0x1000: 0x10002000,
  	            0x1100: 0x10200008,
  	            0x1200: 0x10202008,
  	            0x1300: 0x2008,
  	            0x1400: 0x200000,
  	            0x1500: 0x10000000,
  	            0x1600: 0x10000008,
  	            0x1700: 0x202000,
  	            0x1800: 0x202008,
  	            0x1900: 0x0,
  	            0x1a00: 0x8,
  	            0x1b00: 0x10200000,
  	            0x1c00: 0x2000,
  	            0x1d00: 0x10002008,
  	            0x1e00: 0x10202000,
  	            0x1f00: 0x200008,
  	            0x1080: 0x8,
  	            0x1180: 0x202000,
  	            0x1280: 0x200000,
  	            0x1380: 0x10000008,
  	            0x1480: 0x10002000,
  	            0x1580: 0x2008,
  	            0x1680: 0x10202008,
  	            0x1780: 0x10200000,
  	            0x1880: 0x10202000,
  	            0x1980: 0x10200008,
  	            0x1a80: 0x2000,
  	            0x1b80: 0x202008,
  	            0x1c80: 0x200008,
  	            0x1d80: 0x0,
  	            0x1e80: 0x10000000,
  	            0x1f80: 0x10002008
  	        },
  	        {
  	            0x0: 0x100000,
  	            0x10: 0x2000401,
  	            0x20: 0x400,
  	            0x30: 0x100401,
  	            0x40: 0x2100401,
  	            0x50: 0x0,
  	            0x60: 0x1,
  	            0x70: 0x2100001,
  	            0x80: 0x2000400,
  	            0x90: 0x100001,
  	            0xa0: 0x2000001,
  	            0xb0: 0x2100400,
  	            0xc0: 0x2100000,
  	            0xd0: 0x401,
  	            0xe0: 0x100400,
  	            0xf0: 0x2000000,
  	            0x8: 0x2100001,
  	            0x18: 0x0,
  	            0x28: 0x2000401,
  	            0x38: 0x2100400,
  	            0x48: 0x100000,
  	            0x58: 0x2000001,
  	            0x68: 0x2000000,
  	            0x78: 0x401,
  	            0x88: 0x100401,
  	            0x98: 0x2000400,
  	            0xa8: 0x2100000,
  	            0xb8: 0x100001,
  	            0xc8: 0x400,
  	            0xd8: 0x2100401,
  	            0xe8: 0x1,
  	            0xf8: 0x100400,
  	            0x100: 0x2000000,
  	            0x110: 0x100000,
  	            0x120: 0x2000401,
  	            0x130: 0x2100001,
  	            0x140: 0x100001,
  	            0x150: 0x2000400,
  	            0x160: 0x2100400,
  	            0x170: 0x100401,
  	            0x180: 0x401,
  	            0x190: 0x2100401,
  	            0x1a0: 0x100400,
  	            0x1b0: 0x1,
  	            0x1c0: 0x0,
  	            0x1d0: 0x2100000,
  	            0x1e0: 0x2000001,
  	            0x1f0: 0x400,
  	            0x108: 0x100400,
  	            0x118: 0x2000401,
  	            0x128: 0x2100001,
  	            0x138: 0x1,
  	            0x148: 0x2000000,
  	            0x158: 0x100000,
  	            0x168: 0x401,
  	            0x178: 0x2100400,
  	            0x188: 0x2000001,
  	            0x198: 0x2100000,
  	            0x1a8: 0x0,
  	            0x1b8: 0x2100401,
  	            0x1c8: 0x100401,
  	            0x1d8: 0x400,
  	            0x1e8: 0x2000400,
  	            0x1f8: 0x100001
  	        },
  	        {
  	            0x0: 0x8000820,
  	            0x1: 0x20000,
  	            0x2: 0x8000000,
  	            0x3: 0x20,
  	            0x4: 0x20020,
  	            0x5: 0x8020820,
  	            0x6: 0x8020800,
  	            0x7: 0x800,
  	            0x8: 0x8020000,
  	            0x9: 0x8000800,
  	            0xa: 0x20800,
  	            0xb: 0x8020020,
  	            0xc: 0x820,
  	            0xd: 0x0,
  	            0xe: 0x8000020,
  	            0xf: 0x20820,
  	            0x80000000: 0x800,
  	            0x80000001: 0x8020820,
  	            0x80000002: 0x8000820,
  	            0x80000003: 0x8000000,
  	            0x80000004: 0x8020000,
  	            0x80000005: 0x20800,
  	            0x80000006: 0x20820,
  	            0x80000007: 0x20,
  	            0x80000008: 0x8000020,
  	            0x80000009: 0x820,
  	            0x8000000a: 0x20020,
  	            0x8000000b: 0x8020800,
  	            0x8000000c: 0x0,
  	            0x8000000d: 0x8020020,
  	            0x8000000e: 0x8000800,
  	            0x8000000f: 0x20000,
  	            0x10: 0x20820,
  	            0x11: 0x8020800,
  	            0x12: 0x20,
  	            0x13: 0x800,
  	            0x14: 0x8000800,
  	            0x15: 0x8000020,
  	            0x16: 0x8020020,
  	            0x17: 0x20000,
  	            0x18: 0x0,
  	            0x19: 0x20020,
  	            0x1a: 0x8020000,
  	            0x1b: 0x8000820,
  	            0x1c: 0x8020820,
  	            0x1d: 0x20800,
  	            0x1e: 0x820,
  	            0x1f: 0x8000000,
  	            0x80000010: 0x20000,
  	            0x80000011: 0x800,
  	            0x80000012: 0x8020020,
  	            0x80000013: 0x20820,
  	            0x80000014: 0x20,
  	            0x80000015: 0x8020000,
  	            0x80000016: 0x8000000,
  	            0x80000017: 0x8000820,
  	            0x80000018: 0x8020820,
  	            0x80000019: 0x8000020,
  	            0x8000001a: 0x8000800,
  	            0x8000001b: 0x0,
  	            0x8000001c: 0x20800,
  	            0x8000001d: 0x820,
  	            0x8000001e: 0x20020,
  	            0x8000001f: 0x8020800
  	        }
  	    ];
  
  	    // Masks that select the SBOX input
  	    var SBOX_MASK = [
  	        0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000,
  	        0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f
  	    ];
  
  	    /**
  	     * DES block cipher algorithm.
  	     */
  	    var DES = C_algo.DES = BlockCipher.extend({
  	        _doReset: function () {
  	            // Shortcuts
  	            var key = this._key;
  	            var keyWords = key.words;
  
  	            // Select 56 bits according to PC1
  	            var keyBits = [];
  	            for (var i = 0; i < 56; i++) {
  	                var keyBitPos = PC1[i] - 1;
  	                keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - keyBitPos % 32)) & 1;
  	            }
  
  	            // Assemble 16 subkeys
  	            var subKeys = this._subKeys = [];
  	            for (var nSubKey = 0; nSubKey < 16; nSubKey++) {
  	                // Create subkey
  	                var subKey = subKeys[nSubKey] = [];
  
  	                // Shortcut
  	                var bitShift = BIT_SHIFTS[nSubKey];
  
  	                // Select 48 bits according to PC2
  	                for (var i = 0; i < 24; i++) {
  	                    // Select from the left 28 key bits
  	                    subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - i % 6);
  
  	                    // Select from the right 28 key bits
  	                    subKey[4 + ((i / 6) | 0)] |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] << (31 - i % 6);
  	                }
  
  	                // Since each subkey is applied to an expanded 32-bit input,
  	                // the subkey can be broken into 8 values scaled to 32-bits,
  	                // which allows the key to be used without expansion
  	                subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31);
  	                for (var i = 1; i < 7; i++) {
  	                    subKey[i] = subKey[i] >>> ((i - 1) * 4 + 3);
  	                }
  	                subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27);
  	            }
  
  	            // Compute inverse subkeys
  	            var invSubKeys = this._invSubKeys = [];
  	            for (var i = 0; i < 16; i++) {
  	                invSubKeys[i] = subKeys[15 - i];
  	            }
  	        },
  
  	        encryptBlock: function (M, offset) {
  	            this._doCryptBlock(M, offset, this._subKeys);
  	        },
  
  	        decryptBlock: function (M, offset) {
  	            this._doCryptBlock(M, offset, this._invSubKeys);
  	        },
  
  	        _doCryptBlock: function (M, offset, subKeys) {
  	            // Get input
  	            this._lBlock = M[offset];
  	            this._rBlock = M[offset + 1];
  
  	            // Initial permutation
  	            exchangeLR.call(this, 4,  0x0f0f0f0f);
  	            exchangeLR.call(this, 16, 0x0000ffff);
  	            exchangeRL.call(this, 2,  0x33333333);
  	            exchangeRL.call(this, 8,  0x00ff00ff);
  	            exchangeLR.call(this, 1,  0x55555555);
  
  	            // Rounds
  	            for (var round = 0; round < 16; round++) {
  	                // Shortcuts
  	                var subKey = subKeys[round];
  	                var lBlock = this._lBlock;
  	                var rBlock = this._rBlock;
  
  	                // Feistel function
  	                var f = 0;
  	                for (var i = 0; i < 8; i++) {
  	                    f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0];
  	                }
  	                this._lBlock = rBlock;
  	                this._rBlock = lBlock ^ f;
  	            }
  
  	            // Undo swap from last round
  	            var t = this._lBlock;
  	            this._lBlock = this._rBlock;
  	            this._rBlock = t;
  
  	            // Final permutation
  	            exchangeLR.call(this, 1,  0x55555555);
  	            exchangeRL.call(this, 8,  0x00ff00ff);
  	            exchangeRL.call(this, 2,  0x33333333);
  	            exchangeLR.call(this, 16, 0x0000ffff);
  	            exchangeLR.call(this, 4,  0x0f0f0f0f);
  
  	            // Set output
  	            M[offset] = this._lBlock;
  	            M[offset + 1] = this._rBlock;
  	        },
  
  	        keySize: 64/32,
  
  	        ivSize: 64/32,
  
  	        blockSize: 64/32
  	    });
  
  	    // Swap bits across the left and right words
  	    function exchangeLR(offset, mask) {
  	        var t = ((this._lBlock >>> offset) ^ this._rBlock) & mask;
  	        this._rBlock ^= t;
  	        this._lBlock ^= t << offset;
  	    }
  
  	    function exchangeRL(offset, mask) {
  	        var t = ((this._rBlock >>> offset) ^ this._lBlock) & mask;
  	        this._lBlock ^= t;
  	        this._rBlock ^= t << offset;
  	    }
  
  	    /**
  	     * Shortcut functions to the cipher's object interface.
  	     *
  	     * @example
  	     *
  	     *     var ciphertext = CryptoJS.DES.encrypt(message, key, cfg);
  	     *     var plaintext  = CryptoJS.DES.decrypt(ciphertext, key, cfg);
  	     */
  	    C.DES = BlockCipher._createHelper(DES);
  
  	    /**
  	     * Triple-DES block cipher algorithm.
  	     */
  	    var TripleDES = C_algo.TripleDES = BlockCipher.extend({
  	        _doReset: function () {
  	            // Shortcuts
  	            var key = this._key;
  	            var keyWords = key.words;
  
  	            // Create DES instances
  	            this._des1 = DES.createEncryptor(WordArray.create(keyWords.slice(0, 2)));
  	            this._des2 = DES.createEncryptor(WordArray.create(keyWords.slice(2, 4)));
  	            this._des3 = DES.createEncryptor(WordArray.create(keyWords.slice(4, 6)));
  	        },
  
  	        encryptBlock: function (M, offset) {
  	            this._des1.encryptBlock(M, offset);
  	            this._des2.decryptBlock(M, offset);
  	            this._des3.encryptBlock(M, offset);
  	        },
  
  	        decryptBlock: function (M, offset) {
  	            this._des3.decryptBlock(M, offset);
  	            this._des2.encryptBlock(M, offset);
  	            this._des1.decryptBlock(M, offset);
  	        },
  
  	        keySize: 192/32,
  
  	        ivSize: 64/32,
  
  	        blockSize: 64/32
  	    });
  
  	    /**
  	     * Shortcut functions to the cipher's object interface.
  	     *
  	     * @example
  	     *
  	     *     var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg);
  	     *     var plaintext  = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg);
  	     */
  	    C.TripleDES = BlockCipher._createHelper(TripleDES);
  	}());
  
  
  	return CryptoJS.TripleDES;
  
  }));
  },{"./cipher-core":33,"./core":34,"./enc-base64":35,"./evpkdf":37,"./md5":42}],65:[function(require,module,exports){
  ;(function (root, factory) {
  	if (typeof exports === "object") {
  		// CommonJS
  		module.exports = exports = factory(require("./core"));
  	}
  	else if (typeof define === "function" && define.amd) {
  		// AMD
  		define(["./core"], factory);
  	}
  	else {
  		// Global (browser)
  		factory(root.CryptoJS);
  	}
  }(this, function (CryptoJS) {
  
  	(function (undefined) {
  	    // Shortcuts
  	    var C = CryptoJS;
  	    var C_lib = C.lib;
  	    var Base = C_lib.Base;
  	    var X32WordArray = C_lib.WordArray;
  
  	    /**
  	     * x64 namespace.
  	     */
  	    var C_x64 = C.x64 = {};
  
  	    /**
  	     * A 64-bit word.
  	     */
  	    var X64Word = C_x64.Word = Base.extend({
  	        /**
  	         * Initializes a newly created 64-bit word.
  	         *
  	         * @param {number} high The high 32 bits.
  	         * @param {number} low The low 32 bits.
  	         *
  	         * @example
  	         *
  	         *     var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607);
  	         */
  	        init: function (high, low) {
  	            this.high = high;
  	            this.low = low;
  	        }
  
  	        /**
  	         * Bitwise NOTs this word.
  	         *
  	         * @return {X64Word} A new x64-Word object after negating.
  	         *
  	         * @example
  	         *
  	         *     var negated = x64Word.not();
  	         */
  	        // not: function () {
  	            // var high = ~this.high;
  	            // var low = ~this.low;
  
  	            // return X64Word.create(high, low);
  	        // },
  
  	        /**
  	         * Bitwise ANDs this word with the passed word.
  	         *
  	         * @param {X64Word} word The x64-Word to AND with this word.
  	         *
  	         * @return {X64Word} A new x64-Word object after ANDing.
  	         *
  	         * @example
  	         *
  	         *     var anded = x64Word.and(anotherX64Word);
  	         */
  	        // and: function (word) {
  	            // var high = this.high & word.high;
  	            // var low = this.low & word.low;
  
  	            // return X64Word.create(high, low);
  	        // },
  
  	        /**
  	         * Bitwise ORs this word with the passed word.
  	         *
  	         * @param {X64Word} word The x64-Word to OR with this word.
  	         *
  	         * @return {X64Word} A new x64-Word object after ORing.
  	         *
  	         * @example
  	         *
  	         *     var ored = x64Word.or(anotherX64Word);
  	         */
  	        // or: function (word) {
  	            // var high = this.high | word.high;
  	            // var low = this.low | word.low;
  
  	            // return X64Word.create(high, low);
  	        // },
  
  	        /**
  	         * Bitwise XORs this word with the passed word.
  	         *
  	         * @param {X64Word} word The x64-Word to XOR with this word.
  	         *
  	         * @return {X64Word} A new x64-Word object after XORing.
  	         *
  	         * @example
  	         *
  	         *     var xored = x64Word.xor(anotherX64Word);
  	         */
  	        // xor: function (word) {
  	            // var high = this.high ^ word.high;
  	            // var low = this.low ^ word.low;
  
  	            // return X64Word.create(high, low);
  	        // },
  
  	        /**
  	         * Shifts this word n bits to the left.
  	         *
  	         * @param {number} n The number of bits to shift.
  	         *
  	         * @return {X64Word} A new x64-Word object after shifting.
  	         *
  	         * @example
  	         *
  	         *     var shifted = x64Word.shiftL(25);
  	         */
  	        // shiftL: function (n) {
  	            // if (n < 32) {
  	                // var high = (this.high << n) | (this.low >>> (32 - n));
  	                // var low = this.low << n;
  	            // } else {
  	                // var high = this.low << (n - 32);
  	                // var low = 0;
  	            // }
  
  	            // return X64Word.create(high, low);
  	        // },
  
  	        /**
  	         * Shifts this word n bits to the right.
  	         *
  	         * @param {number} n The number of bits to shift.
  	         *
  	         * @return {X64Word} A new x64-Word object after shifting.
  	         *
  	         * @example
  	         *
  	         *     var shifted = x64Word.shiftR(7);
  	         */
  	        // shiftR: function (n) {
  	            // if (n < 32) {
  	                // var low = (this.low >>> n) | (this.high << (32 - n));
  	                // var high = this.high >>> n;
  	            // } else {
  	                // var low = this.high >>> (n - 32);
  	                // var high = 0;
  	            // }
  
  	            // return X64Word.create(high, low);
  	        // },
  
  	        /**
  	         * Rotates this word n bits to the left.
  	         *
  	         * @param {number} n The number of bits to rotate.
  	         *
  	         * @return {X64Word} A new x64-Word object after rotating.
  	         *
  	         * @example
  	         *
  	         *     var rotated = x64Word.rotL(25);
  	         */
  	        // rotL: function (n) {
  	            // return this.shiftL(n).or(this.shiftR(64 - n));
  	        // },
  
  	        /**
  	         * Rotates this word n bits to the right.
  	         *
  	         * @param {number} n The number of bits to rotate.
  	         *
  	         * @return {X64Word} A new x64-Word object after rotating.
  	         *
  	         * @example
  	         *
  	         *     var rotated = x64Word.rotR(7);
  	         */
  	        // rotR: function (n) {
  	            // return this.shiftR(n).or(this.shiftL(64 - n));
  	        // },
  
  	        /**
  	         * Adds this word with the passed word.
  	         *
  	         * @param {X64Word} word The x64-Word to add with this word.
  	         *
  	         * @return {X64Word} A new x64-Word object after adding.
  	         *
  	         * @example
  	         *
  	         *     var added = x64Word.add(anotherX64Word);
  	         */
  	        // add: function (word) {
  	            // var low = (this.low + word.low) | 0;
  	            // var carry = (low >>> 0) < (this.low >>> 0) ? 1 : 0;
  	            // var high = (this.high + word.high + carry) | 0;
  
  	            // return X64Word.create(high, low);
  	        // }
  	    });
  
  	    /**
  	     * An array of 64-bit words.
  	     *
  	     * @property {Array} words The array of CryptoJS.x64.Word objects.
  	     * @property {number} sigBytes The number of significant bytes in this word array.
  	     */
  	    var X64WordArray = C_x64.WordArray = Base.extend({
  	        /**
  	         * Initializes a newly created word array.
  	         *
  	         * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects.
  	         * @param {number} sigBytes (Optional) The number of significant bytes in the words.
  	         *
  	         * @example
  	         *
  	         *     var wordArray = CryptoJS.x64.WordArray.create();
  	         *
  	         *     var wordArray = CryptoJS.x64.WordArray.create([
  	         *         CryptoJS.x64.Word.create(0x00010203, 0x04050607),
  	         *         CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
  	         *     ]);
  	         *
  	         *     var wordArray = CryptoJS.x64.WordArray.create([
  	         *         CryptoJS.x64.Word.create(0x00010203, 0x04050607),
  	         *         CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
  	         *     ], 10);
  	         */
  	        init: function (words, sigBytes) {
  	            words = this.words = words || [];
  
  	            if (sigBytes != undefined) {
  	                this.sigBytes = sigBytes;
  	            } else {
  	                this.sigBytes = words.length * 8;
  	            }
  	        },
  
  	        /**
  	         * Converts this 64-bit word array to a 32-bit word array.
  	         *
  	         * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array.
  	         *
  	         * @example
  	         *
  	         *     var x32WordArray = x64WordArray.toX32();
  	         */
  	        toX32: function () {
  	            // Shortcuts
  	            var x64Words = this.words;
  	            var x64WordsLength = x64Words.length;
  
  	            // Convert
  	            var x32Words = [];
  	            for (var i = 0; i < x64WordsLength; i++) {
  	                var x64Word = x64Words[i];
  	                x32Words.push(x64Word.high);
  	                x32Words.push(x64Word.low);
  	            }
  
  	            return X32WordArray.create(x32Words, this.sigBytes);
  	        },
  
  	        /**
  	         * Creates a copy of this word array.
  	         *
  	         * @return {X64WordArray} The clone.
  	         *
  	         * @example
  	         *
  	         *     var clone = x64WordArray.clone();
  	         */
  	        clone: function () {
  	            var clone = Base.clone.call(this);
  
  	            // Clone "words" array
  	            var words = clone.words = this.words.slice(0);
  
  	            // Clone each X64Word object
  	            var wordsLength = words.length;
  	            for (var i = 0; i < wordsLength; i++) {
  	                words[i] = words[i].clone();
  	            }
  
  	            return clone;
  	        }
  	    });
  	}());
  
  
  	return CryptoJS;
  
  }));
  },{"./core":34}],66:[function(require,module,exports){
  /**
   * event-lite.js - Light-weight EventEmitter (less than 1KB when gzipped)
   *
   * @copyright Yusuke Kawasaki
   * @license MIT
   * @constructor
   * @see https://github.com/kawanet/event-lite
   * @see http://kawanet.github.io/event-lite/EventLite.html
   * @example
   * var EventLite = require("event-lite");
   *
   * function MyClass() {...}             // your class
   *
   * EventLite.mixin(MyClass.prototype);  // import event methods
   *
   * var obj = new MyClass();
   * obj.on("foo", function() {...});     // add event listener
   * obj.once("bar", function() {...});   // add one-time event listener
   * obj.emit("foo");                     // dispatch event
   * obj.emit("bar");                     // dispatch another event
   * obj.off("foo");                      // remove event listener
   */
  
  function EventLite() {
    if (!(this instanceof EventLite)) return new EventLite();
  }
  
  (function(EventLite) {
    // export the class for node.js
    if ("undefined" !== typeof module) module.exports = EventLite;
  
    // property name to hold listeners
    var LISTENERS = "listeners";
  
    // methods to export
    var methods = {
      on: on,
      once: once,
      off: off,
      emit: emit
    };
  
    // mixin to self
    mixin(EventLite.prototype);
  
    // export mixin function
    EventLite.mixin = mixin;
  
    /**
     * Import on(), once(), off() and emit() methods into target object.
     *
     * @function EventLite.mixin
     * @param target {Prototype}
     */
  
    function mixin(target) {
      for (var key in methods) {
        target[key] = methods[key];
      }
      return target;
    }
  
    /**
     * Add an event listener.
     *
     * @function EventLite.prototype.on
     * @param type {string}
     * @param func {Function}
     * @returns {EventLite} Self for method chaining
     */
  
    function on(type, func) {
      getListeners(this, type).push(func);
      return this;
    }
  
    /**
     * Add one-time event listener.
     *
     * @function EventLite.prototype.once
     * @param type {string}
     * @param func {Function}
     * @returns {EventLite} Self for method chaining
     */
  
    function once(type, func) {
      var that = this;
      wrap.originalListener = func;
      getListeners(that, type).push(wrap);
      return that;
  
      function wrap() {
        off.call(that, type, wrap);
        func.apply(this, arguments);
      }
    }
  
    /**
     * Remove an event listener.
     *
     * @function EventLite.prototype.off
     * @param [type] {string}
     * @param [func] {Function}
     * @returns {EventLite} Self for method chaining
     */
  
    function off(type, func) {
      var that = this;
      var listners;
      if (!arguments.length) {
        delete that[LISTENERS];
      } else if (!func) {
        listners = that[LISTENERS];
        if (listners) {
          delete listners[type];
          if (!Object.keys(listners).length) return off.call(that);
        }
      } else {
        listners = getListeners(that, type, true);
        if (listners) {
          listners = listners.filter(ne);
          if (!listners.length) return off.call(that, type);
          that[LISTENERS][type] = listners;
        }
      }
      return that;
  
      function ne(test) {
        return test !== func && test.originalListener !== func;
      }
    }
  
    /**
     * Dispatch (trigger) an event.
     *
     * @function EventLite.prototype.emit
     * @param type {string}
     * @param [value] {*}
     * @returns {boolean} True when a listener received the event
     */
  
    function emit(type, value) {
      var that = this;
      var listeners = getListeners(that, type, true);
      if (!listeners) return false;
      var arglen = arguments.length;
      if (arglen === 1) {
        listeners.forEach(zeroarg);
      } else if (arglen === 2) {
        listeners.forEach(onearg);
      } else {
        var args = Array.prototype.slice.call(arguments, 1);
        listeners.forEach(moreargs);
      }
      return !!listeners.length;
  
      function zeroarg(func) {
        func.call(that);
      }
  
      function onearg(func) {
        func.call(that, value);
      }
  
      function moreargs(func) {
        func.apply(that, args);
      }
    }
  
    /**
     * @ignore
     */
  
    function getListeners(that, type, readonly) {
      if (readonly && !that[LISTENERS]) return;
      var listeners = that[LISTENERS] || (that[LISTENERS] = {});
      return listeners[type] || (listeners[type] = []);
    }
  
  })(EventLite);
  
  },{}],67:[function(require,module,exports){
  exports.read = function (buffer, offset, isLE, mLen, nBytes) {
    var e, m
    var eLen = nBytes * 8 - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var nBits = -7
    var i = isLE ? (nBytes - 1) : 0
    var d = isLE ? -1 : 1
    var s = buffer[offset + i]
  
    i += d
  
    e = s & ((1 << (-nBits)) - 1)
    s >>= (-nBits)
    nBits += eLen
    for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  
    m = e & ((1 << (-nBits)) - 1)
    e >>= (-nBits)
    nBits += mLen
    for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  
    if (e === 0) {
      e = 1 - eBias
    } else if (e === eMax) {
      return m ? NaN : ((s ? -1 : 1) * Infinity)
    } else {
      m = m + Math.pow(2, mLen)
      e = e - eBias
    }
    return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
  }
  
  exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
    var e, m, c
    var eLen = nBytes * 8 - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
    var i = isLE ? 0 : (nBytes - 1)
    var d = isLE ? 1 : -1
    var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
  
    value = Math.abs(value)
  
    if (isNaN(value) || value === Infinity) {
      m = isNaN(value) ? 1 : 0
      e = eMax
    } else {
      e = Math.floor(Math.log(value) / Math.LN2)
      if (value * (c = Math.pow(2, -e)) < 1) {
        e--
        c *= 2
      }
      if (e + eBias >= 1) {
        value += rt / c
      } else {
        value += rt * Math.pow(2, 1 - eBias)
      }
      if (value * c >= 2) {
        e++
        c /= 2
      }
  
      if (e + eBias >= eMax) {
        m = 0
        e = eMax
      } else if (e + eBias >= 1) {
        m = (value * c - 1) * Math.pow(2, mLen)
        e = e + eBias
      } else {
        m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
        e = 0
      }
    }
  
    for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
  
    e = (e << mLen) | m
    eLen += mLen
    for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
  
    buffer[offset + i - d] |= s * 128
  }
  
  },{}],68:[function(require,module,exports){
  (function (Buffer){
  // int64-buffer.js
  
  /*jshint -W018 */ // Confusing use of '!'.
  /*jshint -W030 */ // Expected an assignment or function call and instead saw an expression.
  /*jshint -W093 */ // Did you mean to return a conditional instead of an assignment?
  
  var Uint64BE, Int64BE, Uint64LE, Int64LE;
  
  !function(exports) {
    // constants
  
    var UNDEFINED = "undefined";
    var BUFFER = (UNDEFINED !== typeof Buffer) && Buffer;
    var UINT8ARRAY = (UNDEFINED !== typeof Uint8Array) && Uint8Array;
    var ARRAYBUFFER = (UNDEFINED !== typeof ArrayBuffer) && ArrayBuffer;
    var ZERO = [0, 0, 0, 0, 0, 0, 0, 0];
    var isArray = Array.isArray || _isArray;
    var BIT32 = 4294967296;
    var BIT24 = 16777216;
  
    // storage class
  
    var storage; // Array;
  
    // generate classes
  
    Uint64BE = factory("Uint64BE", true, true);
    Int64BE = factory("Int64BE", true, false);
    Uint64LE = factory("Uint64LE", false, true);
    Int64LE = factory("Int64LE", false, false);
  
    // class factory
  
    function factory(name, bigendian, unsigned) {
      var posH = bigendian ? 0 : 4;
      var posL = bigendian ? 4 : 0;
      var pos0 = bigendian ? 0 : 3;
      var pos1 = bigendian ? 1 : 2;
      var pos2 = bigendian ? 2 : 1;
      var pos3 = bigendian ? 3 : 0;
      var fromPositive = bigendian ? fromPositiveBE : fromPositiveLE;
      var fromNegative = bigendian ? fromNegativeBE : fromNegativeLE;
      var proto = Int64.prototype;
      var isName = "is" + name;
      var _isInt64 = "_" + isName;
  
      // properties
      proto.buffer = void 0;
      proto.offset = 0;
      proto[_isInt64] = true;
  
      // methods
      proto.toNumber = toNumber;
      proto.toString = toString;
      proto.toJSON = toNumber;
      proto.toArray = toArray;
  
      // add .toBuffer() method only when Buffer available
      if (BUFFER) proto.toBuffer = toBuffer;
  
      // add .toArrayBuffer() method only when Uint8Array available
      if (UINT8ARRAY) proto.toArrayBuffer = toArrayBuffer;
  
      // isUint64BE, isInt64BE
      Int64[isName] = isInt64;
  
      // CommonJS
      exports[name] = Int64;
  
      return Int64;
  
      // constructor
      function Int64(buffer, offset, value, raddix) {
        if (!(this instanceof Int64)) return new Int64(buffer, offset, value, raddix);
        return init(this, buffer, offset, value, raddix);
      }
  
      // isUint64BE, isInt64BE
      function isInt64(b) {
        return !!(b && b[_isInt64]);
      }
  
      // initializer
      function init(that, buffer, offset, value, raddix) {
        if (UINT8ARRAY && ARRAYBUFFER) {
          if (buffer instanceof ARRAYBUFFER) buffer = new UINT8ARRAY(buffer);
          if (value instanceof ARRAYBUFFER) value = new UINT8ARRAY(value);
        }
  
        // Int64BE() style
        if (!buffer && !offset && !value && !storage) {
          // shortcut to initialize with zero
          that.buffer = newArray(ZERO, 0);
          return;
        }
  
        // Int64BE(value, raddix) style
        if (!isValidBuffer(buffer, offset)) {
          var _storage = storage || Array;
          raddix = offset;
          value = buffer;
          offset = 0;
          buffer = new _storage(8);
        }
  
        that.buffer = buffer;
        that.offset = offset |= 0;
  
        // Int64BE(buffer, offset) style
        if (UNDEFINED === typeof value) return;
  
        // Int64BE(buffer, offset, value, raddix) style
        if ("string" === typeof value) {
          fromString(buffer, offset, value, raddix || 10);
        } else if (isValidBuffer(value, raddix)) {
          fromArray(buffer, offset, value, raddix);
        } else if ("number" === typeof raddix) {
          writeInt32(buffer, offset + posH, value); // high
          writeInt32(buffer, offset + posL, raddix); // low
        } else if (value > 0) {
          fromPositive(buffer, offset, value); // positive
        } else if (value < 0) {
          fromNegative(buffer, offset, value); // negative
        } else {
          fromArray(buffer, offset, ZERO, 0); // zero, NaN and others
        }
      }
  
      function fromString(buffer, offset, str, raddix) {
        var pos = 0;
        var len = str.length;
        var high = 0;
        var low = 0;
        if (str[0] === "-") pos++;
        var sign = pos;
        while (pos < len) {
          var chr = parseInt(str[pos++], raddix);
          if (!(chr >= 0)) break; // NaN
          low = low * raddix + chr;
          high = high * raddix + Math.floor(low / BIT32);
          low %= BIT32;
        }
        if (sign) {
          high = ~high;
          if (low) {
            low = BIT32 - low;
          } else {
            high++;
          }
        }
        writeInt32(buffer, offset + posH, high);
        writeInt32(buffer, offset + posL, low);
      }
  
      function toNumber() {
        var buffer = this.buffer;
        var offset = this.offset;
        var high = readInt32(buffer, offset + posH);
        var low = readInt32(buffer, offset + posL);
        if (!unsigned) high |= 0; // a trick to get signed
        return high ? (high * BIT32 + low) : low;
      }
  
      function toString(radix) {
        var buffer = this.buffer;
        var offset = this.offset;
        var high = readInt32(buffer, offset + posH);
        var low = readInt32(buffer, offset + posL);
        var str = "";
        var sign = !unsigned && (high & 0x80000000);
        if (sign) {
          high = ~high;
          low = BIT32 - low;
        }
        radix = radix || 10;
        while (1) {
          var mod = (high % radix) * BIT32 + low;
          high = Math.floor(high / radix);
          low = Math.floor(mod / radix);
          str = (mod % radix).toString(radix) + str;
          if (!high && !low) break;
        }
        if (sign) {
          str = "-" + str;
        }
        return str;
      }
  
      function writeInt32(buffer, offset, value) {
        buffer[offset + pos3] = value & 255;
        value = value >> 8;
        buffer[offset + pos2] = value & 255;
        value = value >> 8;
        buffer[offset + pos1] = value & 255;
        value = value >> 8;
        buffer[offset + pos0] = value & 255;
      }
  
      function readInt32(buffer, offset) {
        return (buffer[offset + pos0] * BIT24) +
          (buffer[offset + pos1] << 16) +
          (buffer[offset + pos2] << 8) +
          buffer[offset + pos3];
      }
    }
  
    function toArray(raw) {
      var buffer = this.buffer;
      var offset = this.offset;
      storage = null; // Array
      if (raw !== false && offset === 0 && buffer.length === 8 && isArray(buffer)) return buffer;
      return newArray(buffer, offset);
    }
  
    function toBuffer(raw) {
      var buffer = this.buffer;
      var offset = this.offset;
      storage = BUFFER;
      if (raw !== false && offset === 0 && buffer.length === 8 && Buffer.isBuffer(buffer)) return buffer;
      var dest = new BUFFER(8);
      fromArray(dest, 0, buffer, offset);
      return dest;
    }
  
    function toArrayBuffer(raw) {
      var buffer = this.buffer;
      var offset = this.offset;
      var arrbuf = buffer.buffer;
      storage = UINT8ARRAY;
      if (raw !== false && offset === 0 && (arrbuf instanceof ARRAYBUFFER) && arrbuf.byteLength === 8) return arrbuf;
      var dest = new UINT8ARRAY(8);
      fromArray(dest, 0, buffer, offset);
      return dest.buffer;
    }
  
    function isValidBuffer(buffer, offset) {
      var len = buffer && buffer.length;
      offset |= 0;
      return len && (offset + 8 <= len) && ("string" !== typeof buffer[offset]);
    }
  
    function fromArray(destbuf, destoff, srcbuf, srcoff) {
      destoff |= 0;
      srcoff |= 0;
      for (var i = 0; i < 8; i++) {
        destbuf[destoff++] = srcbuf[srcoff++] & 255;
      }
    }
  
    function newArray(buffer, offset) {
      return Array.prototype.slice.call(buffer, offset, offset + 8);
    }
  
    function fromPositiveBE(buffer, offset, value) {
      var pos = offset + 8;
      while (pos > offset) {
        buffer[--pos] = value & 255;
        value /= 256;
      }
    }
  
    function fromNegativeBE(buffer, offset, value) {
      var pos = offset + 8;
      value++;
      while (pos > offset) {
        buffer[--pos] = ((-value) & 255) ^ 255;
        value /= 256;
      }
    }
  
    function fromPositiveLE(buffer, offset, value) {
      var end = offset + 8;
      while (offset < end) {
        buffer[offset++] = value & 255;
        value /= 256;
      }
    }
  
    function fromNegativeLE(buffer, offset, value) {
      var end = offset + 8;
      value++;
      while (offset < end) {
        buffer[offset++] = ((-value) & 255) ^ 255;
        value /= 256;
      }
    }
  
    // https://github.com/retrofox/is-array
    function _isArray(val) {
      return !!val && "[object Array]" == Object.prototype.toString.call(val);
    }
  
  }(typeof exports === 'object' && typeof exports.nodeName !== 'string' ? exports : (this || {}));
  
  }).call(this,require("buffer").Buffer)
  },{"buffer":129}],69:[function(require,module,exports){
  var toString = {}.toString;
  
  module.exports = Array.isArray || function (arr) {
    return toString.call(arr) == '[object Array]';
  };
  
  },{}],70:[function(require,module,exports){
  // browser.js
  
  exports.encode = require("./encode").encode;
  exports.decode = require("./decode").decode;
  
  exports.Encoder = require("./encoder").Encoder;
  exports.Decoder = require("./decoder").Decoder;
  
  exports.createCodec = require("./ext").createCodec;
  exports.codec = require("./codec").codec;
  
  },{"./codec":79,"./decode":81,"./decoder":82,"./encode":84,"./encoder":85,"./ext":89}],71:[function(require,module,exports){
  (function (Buffer){
  /* globals Buffer */
  
  module.exports =
    c(("undefined" !== typeof Buffer) && Buffer) ||
    c(this.Buffer) ||
    c(("undefined" !== typeof window) && window.Buffer) ||
    this.Buffer;
  
  function c(B) {
    return B && B.isBuffer && B;
  }
  }).call(this,require("buffer").Buffer)
  },{"buffer":129}],72:[function(require,module,exports){
  // buffer-lite.js
  
  var MAXBUFLEN = 8192;
  
  exports.copy = copy;
  exports.toString = toString;
  exports.write = write;
  
  /**
   * Buffer.prototype.write()
   *
   * @param string {String}
   * @param [offset] {Number}
   * @returns {Number}
   */
  
  function write(string, offset) {
    var buffer = this;
    var index = offset || (offset |= 0);
    var length = string.length;
    var chr = 0;
    var i = 0;
    while (i < length) {
      chr = string.charCodeAt(i++);
  
      if (chr < 128) {
        buffer[index++] = chr;
      } else if (chr < 0x800) {
        // 2 bytes
        buffer[index++] = 0xC0 | (chr >>> 6);
        buffer[index++] = 0x80 | (chr & 0x3F);
      } else if (chr < 0xD800 || chr > 0xDFFF) {
        // 3 bytes
        buffer[index++] = 0xE0 | (chr  >>> 12);
        buffer[index++] = 0x80 | ((chr >>> 6)  & 0x3F);
        buffer[index++] = 0x80 | (chr          & 0x3F);
      } else {
        // 4 bytes - surrogate pair
        chr = (((chr - 0xD800) << 10) | (string.charCodeAt(i++) - 0xDC00)) + 0x10000;
        buffer[index++] = 0xF0 | (chr >>> 18);
        buffer[index++] = 0x80 | ((chr >>> 12) & 0x3F);
        buffer[index++] = 0x80 | ((chr >>> 6)  & 0x3F);
        buffer[index++] = 0x80 | (chr          & 0x3F);
      }
    }
    return index - offset;
  }
  
  /**
   * Buffer.prototype.toString()
   *
   * @param [encoding] {String} ignored
   * @param [start] {Number}
   * @param [end] {Number}
   * @returns {String}
   */
  
  function toString(encoding, start, end) {
    var buffer = this;
    var index = start|0;
    if (!end) end = buffer.length;
    var string = '';
    var chr = 0;
  
    while (index < end) {
      chr = buffer[index++];
      if (chr < 128) {
        string += String.fromCharCode(chr);
        continue;
      }
  
      if ((chr & 0xE0) === 0xC0) {
        // 2 bytes
        chr = (chr & 0x1F) << 6 |
              (buffer[index++] & 0x3F);
  
      } else if ((chr & 0xF0) === 0xE0) {
        // 3 bytes
        chr = (chr & 0x0F)             << 12 |
              (buffer[index++] & 0x3F) << 6  |
              (buffer[index++] & 0x3F);
  
      } else if ((chr & 0xF8) === 0xF0) {
        // 4 bytes
        chr = (chr & 0x07)             << 18 |
              (buffer[index++] & 0x3F) << 12 |
              (buffer[index++] & 0x3F) << 6  |
              (buffer[index++] & 0x3F);
      }
  
      if (chr >= 0x010000) {
        // A surrogate pair
        chr -= 0x010000;
  
        string += String.fromCharCode((chr >>> 10) + 0xD800, (chr & 0x3FF) + 0xDC00);
      } else {
        string += String.fromCharCode(chr);
      }
    }
  
    return string;
  }
  
  /**
   * Buffer.prototype.copy()
   *
   * @param target {Buffer}
   * @param [targetStart] {Number}
   * @param [start] {Number}
   * @param [end] {Number}
   * @returns {number}
   */
  
  function copy(target, targetStart, start, end) {
    var i;
    if (!start) start = 0;
    if (!end && end !== 0) end = this.length;
    if (!targetStart) targetStart = 0;
    var len = end - start;
  
    if (target === this && start < targetStart && targetStart < end) {
      // descending
      for (i = len - 1; i >= 0; i--) {
        target[i + targetStart] = this[i + start];
      }
    } else {
      // ascending
      for (i = 0; i < len; i++) {
        target[i + targetStart] = this[i + start];
      }
    }
  
    return len;
  }
  
  },{}],73:[function(require,module,exports){
  // bufferish-array.js
  
  var Bufferish = require("./bufferish");
  
  var exports = module.exports = alloc(0);
  
  exports.alloc = alloc;
  exports.concat = Bufferish.concat;
  exports.from = from;
  
  /**
   * @param size {Number}
   * @returns {Buffer|Uint8Array|Array}
   */
  
  function alloc(size) {
    return new Array(size);
  }
  
  /**
   * @param value {Array|ArrayBuffer|Buffer|String}
   * @returns {Array}
   */
  
  function from(value) {
    if (!Bufferish.isBuffer(value) && Bufferish.isView(value)) {
      // TypedArray to Uint8Array
      value = Bufferish.Uint8Array.from(value);
    } else if (Bufferish.isArrayBuffer(value)) {
      // ArrayBuffer to Uint8Array
      value = new Uint8Array(value);
    } else if (typeof value === "string") {
      // String to Array
      return Bufferish.from.call(exports, value);
    } else if (typeof value === "number") {
      throw new TypeError('"value" argument must not be a number');
    }
  
    // Array-like to Array
    return Array.prototype.slice.call(value);
  }
  
  },{"./bufferish":77}],74:[function(require,module,exports){
  // bufferish-buffer.js
  
  var Bufferish = require("./bufferish");
  var Buffer = Bufferish.global;
  
  var exports = module.exports = Bufferish.hasBuffer ? alloc(0) : [];
  
  exports.alloc = Bufferish.hasBuffer && Buffer.alloc || alloc;
  exports.concat = Bufferish.concat;
  exports.from = from;
  
  /**
   * @param size {Number}
   * @returns {Buffer|Uint8Array|Array}
   */
  
  function alloc(size) {
    return new Buffer(size);
  }
  
  /**
   * @param value {Array|ArrayBuffer|Buffer|String}
   * @returns {Buffer}
   */
  
  function from(value) {
    if (!Bufferish.isBuffer(value) && Bufferish.isView(value)) {
      // TypedArray to Uint8Array
      value = Bufferish.Uint8Array.from(value);
    } else if (Bufferish.isArrayBuffer(value)) {
      // ArrayBuffer to Uint8Array
      value = new Uint8Array(value);
    } else if (typeof value === "string") {
      // String to Buffer
      return Bufferish.from.call(exports, value);
    } else if (typeof value === "number") {
      throw new TypeError('"value" argument must not be a number');
    }
  
    // Array-like to Buffer
    if (Buffer.from && Buffer.from.length !== 1) {
      return Buffer.from(value); // node v6+
    } else {
      return new Buffer(value); // node v4
    }
  }
  
  },{"./bufferish":77}],75:[function(require,module,exports){
  // bufferish-proto.js
  
  /* jshint eqnull:true */
  
  var BufferLite = require("./buffer-lite");
  
  exports.copy = copy;
  exports.slice = slice;
  exports.toString = toString;
  exports.write = gen("write");
  
  var Bufferish = require("./bufferish");
  var Buffer = Bufferish.global;
  
  var isBufferShim = Bufferish.hasBuffer && ("TYPED_ARRAY_SUPPORT" in Buffer);
  var brokenTypedArray = isBufferShim && !Buffer.TYPED_ARRAY_SUPPORT;
  
  /**
   * @param target {Buffer|Uint8Array|Array}
   * @param [targetStart] {Number}
   * @param [start] {Number}
   * @param [end] {Number}
   * @returns {Buffer|Uint8Array|Array}
   */
  
  function copy(target, targetStart, start, end) {
    var thisIsBuffer = Bufferish.isBuffer(this);
    var targetIsBuffer = Bufferish.isBuffer(target);
    if (thisIsBuffer && targetIsBuffer) {
      // Buffer to Buffer
      return this.copy(target, targetStart, start, end);
    } else if (!brokenTypedArray && !thisIsBuffer && !targetIsBuffer &&
      Bufferish.isView(this) && Bufferish.isView(target)) {
      // Uint8Array to Uint8Array (except for minor some browsers)
      var buffer = (start || end != null) ? slice.call(this, start, end) : this;
      target.set(buffer, targetStart);
      return buffer.length;
    } else {
      // other cases
      return BufferLite.copy.call(this, target, targetStart, start, end);
    }
  }
  
  /**
   * @param [start] {Number}
   * @param [end] {Number}
   * @returns {Buffer|Uint8Array|Array}
   */
  
  function slice(start, end) {
    // for Buffer, Uint8Array (except for minor some browsers) and Array
    var f = this.slice || (!brokenTypedArray && this.subarray);
    if (f) return f.call(this, start, end);
  
    // Uint8Array (for minor some browsers)
    var target = Bufferish.alloc.call(this, end - start);
    copy.call(this, target, 0, start, end);
    return target;
  }
  
  /**
   * Buffer.prototype.toString()
   *
   * @param [encoding] {String} ignored
   * @param [start] {Number}
   * @param [end] {Number}
   * @returns {String}
   */
  
  function toString(encoding, start, end) {
    var f = (!isBufferShim && Bufferish.isBuffer(this)) ? this.toString : BufferLite.toString;
    return f.apply(this, arguments);
  }
  
  /**
   * @private
   */
  
  function gen(method) {
    return wrap;
  
    function wrap() {
      var f = this[method] || BufferLite[method];
      return f.apply(this, arguments);
    }
  }
  
  },{"./buffer-lite":72,"./bufferish":77}],76:[function(require,module,exports){
  // bufferish-uint8array.js
  
  var Bufferish = require("./bufferish");
  
  var exports = module.exports = Bufferish.hasArrayBuffer ? alloc(0) : [];
  
  exports.alloc = alloc;
  exports.concat = Bufferish.concat;
  exports.from = from;
  
  /**
   * @param size {Number}
   * @returns {Buffer|Uint8Array|Array}
   */
  
  function alloc(size) {
    return new Uint8Array(size);
  }
  
  /**
   * @param value {Array|ArrayBuffer|Buffer|String}
   * @returns {Uint8Array}
   */
  
  function from(value) {
    if (Bufferish.isView(value)) {
      // TypedArray to ArrayBuffer
      var byteOffset = value.byteOffset;
      var byteLength = value.byteLength;
      value = value.buffer;
      if (value.byteLength !== byteLength) {
        if (value.slice) {
          value = value.slice(byteOffset, byteOffset + byteLength);
        } else {
          // Android 4.1 does not have ArrayBuffer.prototype.slice
          value = new Uint8Array(value);
          if (value.byteLength !== byteLength) {
            // TypedArray to ArrayBuffer to Uint8Array to Array
            value = Array.prototype.slice.call(value, byteOffset, byteOffset + byteLength);
          }
        }
      }
    } else if (typeof value === "string") {
      // String to Uint8Array
      return Bufferish.from.call(exports, value);
    } else if (typeof value === "number") {
      throw new TypeError('"value" argument must not be a number');
    }
  
    return new Uint8Array(value);
  }
  
  },{"./bufferish":77}],77:[function(require,module,exports){
  // bufferish.js
  
  var Buffer = exports.global = require("./buffer-global");
  var hasBuffer = exports.hasBuffer = Buffer && !!Buffer.isBuffer;
  var hasArrayBuffer = exports.hasArrayBuffer = ("undefined" !== typeof ArrayBuffer);
  
  var isArray = exports.isArray = require("isarray");
  exports.isArrayBuffer = hasArrayBuffer ? isArrayBuffer : _false;
  var isBuffer = exports.isBuffer = hasBuffer ? Buffer.isBuffer : _false;
  var isView = exports.isView = hasArrayBuffer ? (ArrayBuffer.isView || _is("ArrayBuffer", "buffer")) : _false;
  
  exports.alloc = alloc;
  exports.concat = concat;
  exports.from = from;
  
  var BufferArray = exports.Array = require("./bufferish-array");
  var BufferBuffer = exports.Buffer = require("./bufferish-buffer");
  var BufferUint8Array = exports.Uint8Array = require("./bufferish-uint8array");
  var BufferProto = exports.prototype = require("./bufferish-proto");
  
  /**
   * @param value {Array|ArrayBuffer|Buffer|String}
   * @returns {Buffer|Uint8Array|Array}
   */
  
  function from(value) {
    if (typeof value === "string") {
      return fromString.call(this, value);
    } else {
      return auto(this).from(value);
    }
  }
  
  /**
   * @param size {Number}
   * @returns {Buffer|Uint8Array|Array}
   */
  
  function alloc(size) {
    return auto(this).alloc(size);
  }
  
  /**
   * @param list {Array} array of (Buffer|Uint8Array|Array)s
   * @param [length]
   * @returns {Buffer|Uint8Array|Array}
   */
  
  function concat(list, length) {
    if (!length) {
      length = 0;
      Array.prototype.forEach.call(list, dryrun);
    }
    var ref = (this !== exports) && this || list[0];
    var result = alloc.call(ref, length);
    var offset = 0;
    Array.prototype.forEach.call(list, append);
    return result;
  
    function dryrun(buffer) {
      length += buffer.length;
    }
  
    function append(buffer) {
      offset += BufferProto.copy.call(buffer, result, offset);
    }
  }
  
  var _isArrayBuffer = _is("ArrayBuffer");
  
  function isArrayBuffer(value) {
    return (value instanceof ArrayBuffer) || _isArrayBuffer(value);
  }
  
  /**
   * @private
   */
  
  function fromString(value) {
    var expected = value.length * 3;
    var that = alloc.call(this, expected);
    var actual = BufferProto.write.call(that, value);
    if (expected !== actual) {
      that = BufferProto.slice.call(that, 0, actual);
    }
    return that;
  }
  
  function auto(that) {
    return isBuffer(that) ? BufferBuffer
      : isView(that) ? BufferUint8Array
      : isArray(that) ? BufferArray
      : hasBuffer ? BufferBuffer
      : hasArrayBuffer ? BufferUint8Array
      : BufferArray;
  }
  
  function _false() {
    return false;
  }
  
  function _is(name, key) {
    /* jshint eqnull:true */
    name = "[object " + name + "]";
    return function(value) {
      return (value != null) && {}.toString.call(key ? value[key] : value) === name;
    };
  }
  },{"./buffer-global":71,"./bufferish-array":73,"./bufferish-buffer":74,"./bufferish-proto":75,"./bufferish-uint8array":76,"isarray":69}],78:[function(require,module,exports){
  // codec-base.js
  
  var IS_ARRAY = require("isarray");
  
  exports.createCodec = createCodec;
  exports.install = install;
  exports.filter = filter;
  
  var Bufferish = require("./bufferish");
  
  function Codec(options) {
    if (!(this instanceof Codec)) return new Codec(options);
    this.options = options;
    this.init();
  }
  
  Codec.prototype.init = function() {
    var options = this.options;
  
    if (options && options.uint8array) {
      this.bufferish = Bufferish.Uint8Array;
    }
  
    return this;
  };
  
  function install(props) {
    for (var key in props) {
      Codec.prototype[key] = add(Codec.prototype[key], props[key]);
    }
  }
  
  function add(a, b) {
    return (a && b) ? ab : (a || b);
  
    function ab() {
      a.apply(this, arguments);
      return b.apply(this, arguments);
    }
  }
  
  function join(filters) {
    filters = filters.slice();
  
    return function(value) {
      return filters.reduce(iterator, value);
    };
  
    function iterator(value, filter) {
      return filter(value);
    }
  }
  
  function filter(filter) {
    return IS_ARRAY(filter) ? join(filter) : filter;
  }
  
  // @public
  // msgpack.createCodec()
  
  function createCodec(options) {
    return new Codec(options);
  }
  
  // default shared codec
  
  exports.preset = createCodec({preset: true});
  
  },{"./bufferish":77,"isarray":69}],79:[function(require,module,exports){
  // codec.js
  
  // load both interfaces
  require("./read-core");
  require("./write-core");
  
  // @public
  // msgpack.codec.preset
  
  exports.codec = {
    preset: require("./codec-base").preset
  };
  
  },{"./codec-base":78,"./read-core":91,"./write-core":94}],80:[function(require,module,exports){
  // decode-buffer.js
  
  exports.DecodeBuffer = DecodeBuffer;
  
  var preset = require("./read-core").preset;
  
  var FlexDecoder = require("./flex-buffer").FlexDecoder;
  
  FlexDecoder.mixin(DecodeBuffer.prototype);
  
  function DecodeBuffer(options) {
    if (!(this instanceof DecodeBuffer)) return new DecodeBuffer(options);
  
    if (options) {
      this.options = options;
      if (options.codec) {
        var codec = this.codec = options.codec;
        if (codec.bufferish) this.bufferish = codec.bufferish;
      }
    }
  }
  
  DecodeBuffer.prototype.codec = preset;
  
  DecodeBuffer.prototype.fetch = function() {
    return this.codec.decode(this);
  };
  
  },{"./flex-buffer":90,"./read-core":91}],81:[function(require,module,exports){
  // decode.js
  
  exports.decode = decode;
  
  var DecodeBuffer = require("./decode-buffer").DecodeBuffer;
  
  function decode(input, options) {
    var decoder = new DecodeBuffer(options);
    decoder.write(input);
    return decoder.read();
  }
  },{"./decode-buffer":80}],82:[function(require,module,exports){
  // decoder.js
  
  exports.Decoder = Decoder;
  
  var EventLite = require("event-lite");
  var DecodeBuffer = require("./decode-buffer").DecodeBuffer;
  
  function Decoder(options) {
    if (!(this instanceof Decoder)) return new Decoder(options);
    DecodeBuffer.call(this, options);
  }
  
  Decoder.prototype = new DecodeBuffer();
  
  EventLite.mixin(Decoder.prototype);
  
  Decoder.prototype.decode = function(chunk) {
    if (arguments.length) this.write(chunk);
    this.flush();
  };
  
  Decoder.prototype.push = function(chunk) {
    this.emit("data", chunk);
  };
  
  Decoder.prototype.end = function(chunk) {
    this.decode(chunk);
    this.emit("end");
  };
  
  },{"./decode-buffer":80,"event-lite":66}],83:[function(require,module,exports){
  // encode-buffer.js
  
  exports.EncodeBuffer = EncodeBuffer;
  
  var preset = require("./write-core").preset;
  
  var FlexEncoder = require("./flex-buffer").FlexEncoder;
  
  FlexEncoder.mixin(EncodeBuffer.prototype);
  
  function EncodeBuffer(options) {
    if (!(this instanceof EncodeBuffer)) return new EncodeBuffer(options);
  
    if (options) {
      this.options = options;
      if (options.codec) {
        var codec = this.codec = options.codec;
        if (codec.bufferish) this.bufferish = codec.bufferish;
      }
    }
  }
  
  EncodeBuffer.prototype.codec = preset;
  
  EncodeBuffer.prototype.write = function(input) {
    this.codec.encode(this, input);
  };
  
  },{"./flex-buffer":90,"./write-core":94}],84:[function(require,module,exports){
  // encode.js
  
  exports.encode = encode;
  
  var EncodeBuffer = require("./encode-buffer").EncodeBuffer;
  
  function encode(input, options) {
    var encoder = new EncodeBuffer(options);
    encoder.write(input);
    return encoder.read();
  }
  
  },{"./encode-buffer":83}],85:[function(require,module,exports){
  // encoder.js
  
  exports.Encoder = Encoder;
  
  var EventLite = require("event-lite");
  var EncodeBuffer = require("./encode-buffer").EncodeBuffer;
  
  function Encoder(options) {
    if (!(this instanceof Encoder)) return new Encoder(options);
    EncodeBuffer.call(this, options);
  }
  
  Encoder.prototype = new EncodeBuffer();
  
  EventLite.mixin(Encoder.prototype);
  
  Encoder.prototype.encode = function(chunk) {
    this.write(chunk);
    this.emit("data", this.read());
  };
  
  Encoder.prototype.end = function(chunk) {
    if (arguments.length) this.encode(chunk);
    this.flush();
    this.emit("end");
  };
  
  },{"./encode-buffer":83,"event-lite":66}],86:[function(require,module,exports){
  // ext-buffer.js
  
  exports.ExtBuffer = ExtBuffer;
  
  var Bufferish = require("./bufferish");
  
  function ExtBuffer(buffer, type) {
    if (!(this instanceof ExtBuffer)) return new ExtBuffer(buffer, type);
    this.buffer = Bufferish.from(buffer);
    this.type = type;
  }
  
  },{"./bufferish":77}],87:[function(require,module,exports){
  // ext-packer.js
  
  exports.setExtPackers = setExtPackers;
  
  var Bufferish = require("./bufferish");
  var Buffer = Bufferish.global;
  var packTypedArray = Bufferish.Uint8Array.from;
  var _encode;
  
  var ERROR_COLUMNS = {name: 1, message: 1, stack: 1, columnNumber: 1, fileName: 1, lineNumber: 1};
  
  function setExtPackers(codec) {
    codec.addExtPacker(0x0E, Error, [packError, encode]);
    codec.addExtPacker(0x01, EvalError, [packError, encode]);
    codec.addExtPacker(0x02, RangeError, [packError, encode]);
    codec.addExtPacker(0x03, ReferenceError, [packError, encode]);
    codec.addExtPacker(0x04, SyntaxError, [packError, encode]);
    codec.addExtPacker(0x05, TypeError, [packError, encode]);
    codec.addExtPacker(0x06, URIError, [packError, encode]);
  
    codec.addExtPacker(0x0A, RegExp, [packRegExp, encode]);
    codec.addExtPacker(0x0B, Boolean, [packValueOf, encode]);
    codec.addExtPacker(0x0C, String, [packValueOf, encode]);
    codec.addExtPacker(0x0D, Date, [Number, encode]);
    codec.addExtPacker(0x0F, Number, [packValueOf, encode]);
  
    if ("undefined" !== typeof Uint8Array) {
      codec.addExtPacker(0x11, Int8Array, packTypedArray);
      codec.addExtPacker(0x12, Uint8Array, packTypedArray);
      codec.addExtPacker(0x13, Int16Array, packTypedArray);
      codec.addExtPacker(0x14, Uint16Array, packTypedArray);
      codec.addExtPacker(0x15, Int32Array, packTypedArray);
      codec.addExtPacker(0x16, Uint32Array, packTypedArray);
      codec.addExtPacker(0x17, Float32Array, packTypedArray);
  
      // PhantomJS/1.9.7 doesn't have Float64Array
      if ("undefined" !== typeof Float64Array) {
        codec.addExtPacker(0x18, Float64Array, packTypedArray);
      }
  
      // IE10 doesn't have Uint8ClampedArray
      if ("undefined" !== typeof Uint8ClampedArray) {
        codec.addExtPacker(0x19, Uint8ClampedArray, packTypedArray);
      }
  
      codec.addExtPacker(0x1A, ArrayBuffer, packTypedArray);
      codec.addExtPacker(0x1D, DataView, packTypedArray);
    }
  
    if (Bufferish.hasBuffer) {
      codec.addExtPacker(0x1B, Buffer, Bufferish.from);
    }
  }
  
  function encode(input) {
    if (!_encode) _encode = require("./encode").encode; // lazy load
    return _encode(input);
  }
  
  function packValueOf(value) {
    return (value).valueOf();
  }
  
  function packRegExp(value) {
    value = RegExp.prototype.toString.call(value).split("/");
    value.shift();
    var out = [value.pop()];
    out.unshift(value.join("/"));
    return out;
  }
  
  function packError(value) {
    var out = {};
    for (var key in ERROR_COLUMNS) {
      out[key] = value[key];
    }
    return out;
  }
  
  },{"./bufferish":77,"./encode":84}],88:[function(require,module,exports){
  // ext-unpacker.js
  
  exports.setExtUnpackers = setExtUnpackers;
  
  var Bufferish = require("./bufferish");
  var Buffer = Bufferish.global;
  var _decode;
  
  var ERROR_COLUMNS = {name: 1, message: 1, stack: 1, columnNumber: 1, fileName: 1, lineNumber: 1};
  
  function setExtUnpackers(codec) {
    codec.addExtUnpacker(0x0E, [decode, unpackError(Error)]);
    codec.addExtUnpacker(0x01, [decode, unpackError(EvalError)]);
    codec.addExtUnpacker(0x02, [decode, unpackError(RangeError)]);
    codec.addExtUnpacker(0x03, [decode, unpackError(ReferenceError)]);
    codec.addExtUnpacker(0x04, [decode, unpackError(SyntaxError)]);
    codec.addExtUnpacker(0x05, [decode, unpackError(TypeError)]);
    codec.addExtUnpacker(0x06, [decode, unpackError(URIError)]);
  
    codec.addExtUnpacker(0x0A, [decode, unpackRegExp]);
    codec.addExtUnpacker(0x0B, [decode, unpackClass(Boolean)]);
    codec.addExtUnpacker(0x0C, [decode, unpackClass(String)]);
    codec.addExtUnpacker(0x0D, [decode, unpackClass(Date)]);
    codec.addExtUnpacker(0x0F, [decode, unpackClass(Number)]);
  
    if ("undefined" !== typeof Uint8Array) {
      codec.addExtUnpacker(0x11, unpackClass(Int8Array));
      codec.addExtUnpacker(0x12, unpackClass(Uint8Array));
      codec.addExtUnpacker(0x13, [unpackArrayBuffer, unpackClass(Int16Array)]);
      codec.addExtUnpacker(0x14, [unpackArrayBuffer, unpackClass(Uint16Array)]);
      codec.addExtUnpacker(0x15, [unpackArrayBuffer, unpackClass(Int32Array)]);
      codec.addExtUnpacker(0x16, [unpackArrayBuffer, unpackClass(Uint32Array)]);
      codec.addExtUnpacker(0x17, [unpackArrayBuffer, unpackClass(Float32Array)]);
  
      // PhantomJS/1.9.7 doesn't have Float64Array
      if ("undefined" !== typeof Float64Array) {
        codec.addExtUnpacker(0x18, [unpackArrayBuffer, unpackClass(Float64Array)]);
      }
  
      // IE10 doesn't have Uint8ClampedArray
      if ("undefined" !== typeof Uint8ClampedArray) {
        codec.addExtUnpacker(0x19, unpackClass(Uint8ClampedArray));
      }
  
      codec.addExtUnpacker(0x1A, unpackArrayBuffer);
      codec.addExtUnpacker(0x1D, [unpackArrayBuffer, unpackClass(DataView)]);
    }
  
    if (Bufferish.hasBuffer) {
      codec.addExtUnpacker(0x1B, unpackClass(Buffer));
    }
  }
  
  function decode(input) {
    if (!_decode) _decode = require("./decode").decode; // lazy load
    return _decode(input);
  }
  
  function unpackRegExp(value) {
    return RegExp.apply(null, value);
  }
  
  function unpackError(Class) {
    return function(value) {
      var out = new Class();
      for (var key in ERROR_COLUMNS) {
        out[key] = value[key];
      }
      return out;
    };
  }
  
  function unpackClass(Class) {
    return function(value) {
      return new Class(value);
    };
  }
  
  function unpackArrayBuffer(value) {
    return (new Uint8Array(value)).buffer;
  }
  
  },{"./bufferish":77,"./decode":81}],89:[function(require,module,exports){
  // ext.js
  
  // load both interfaces
  require("./read-core");
  require("./write-core");
  
  exports.createCodec = require("./codec-base").createCodec;
  
  },{"./codec-base":78,"./read-core":91,"./write-core":94}],90:[function(require,module,exports){
  // flex-buffer.js
  
  exports.FlexDecoder = FlexDecoder;
  exports.FlexEncoder = FlexEncoder;
  
  var Bufferish = require("./bufferish");
  
  var MIN_BUFFER_SIZE = 2048;
  var MAX_BUFFER_SIZE = 65536;
  var BUFFER_SHORTAGE = "BUFFER_SHORTAGE";
  
  function FlexDecoder() {
    if (!(this instanceof FlexDecoder)) return new FlexDecoder();
  }
  
  function FlexEncoder() {
    if (!(this instanceof FlexEncoder)) return new FlexEncoder();
  }
  
  FlexDecoder.mixin = mixinFactory(getDecoderMethods());
  FlexDecoder.mixin(FlexDecoder.prototype);
  
  FlexEncoder.mixin = mixinFactory(getEncoderMethods());
  FlexEncoder.mixin(FlexEncoder.prototype);
  
  function getDecoderMethods() {
    return {
      bufferish: Bufferish,
      write: write,
      fetch: fetch,
      flush: flush,
      push: push,
      pull: pull,
      read: read,
      reserve: reserve,
      offset: 0
    };
  
    function write(chunk) {
      var prev = this.offset ? Bufferish.prototype.slice.call(this.buffer, this.offset) : this.buffer;
      this.buffer = prev ? (chunk ? this.bufferish.concat([prev, chunk]) : prev) : chunk;
      this.offset = 0;
    }
  
    function flush() {
      while (this.offset < this.buffer.length) {
        var start = this.offset;
        var value;
        try {
          value = this.fetch();
        } catch (e) {
          if (e && e.message != BUFFER_SHORTAGE) throw e;
          // rollback
          this.offset = start;
          break;
        }
        this.push(value);
      }
    }
  
    function reserve(length) {
      var start = this.offset;
      var end = start + length;
      if (end > this.buffer.length) throw new Error(BUFFER_SHORTAGE);
      this.offset = end;
      return start;
    }
  }
  
  function getEncoderMethods() {
    return {
      bufferish: Bufferish,
      write: write,
      fetch: fetch,
      flush: flush,
      push: push,
      pull: pull,
      read: read,
      reserve: reserve,
      send: send,
      maxBufferSize: MAX_BUFFER_SIZE,
      minBufferSize: MIN_BUFFER_SIZE,
      offset: 0,
      start: 0
    };
  
    function fetch() {
      var start = this.start;
      if (start < this.offset) {
        var end = this.start = this.offset;
        return Bufferish.prototype.slice.call(this.buffer, start, end);
      }
    }
  
    function flush() {
      while (this.start < this.offset) {
        var value = this.fetch();
        if (value) this.push(value);
      }
    }
  
    function pull() {
      var buffers = this.buffers || (this.buffers = []);
      var chunk = buffers.length > 1 ? this.bufferish.concat(buffers) : buffers[0];
      buffers.length = 0; // buffer exhausted
      return chunk;
    }
  
    function reserve(length) {
      var req = length | 0;
  
      if (this.buffer) {
        var size = this.buffer.length;
        var start = this.offset | 0;
        var end = start + req;
  
        // is it long enough?
        if (end < size) {
          this.offset = end;
          return start;
        }
  
        // flush current buffer
        this.flush();
  
        // resize it to 2x current length
        length = Math.max(length, Math.min(size * 2, this.maxBufferSize));
      }
  
      // minimum buffer size
      length = Math.max(length, this.minBufferSize);
  
      // allocate new buffer
      this.buffer = this.bufferish.alloc(length);
      this.start = 0;
      this.offset = req;
      return 0;
    }
  
    function send(buffer) {
      var length = buffer.length;
      if (length > this.minBufferSize) {
        this.flush();
        this.push(buffer);
      } else {
        var offset = this.reserve(length);
        Bufferish.prototype.copy.call(buffer, this.buffer, offset);
      }
    }
  }
  
  // common methods
  
  function write() {
    throw new Error("method not implemented: write()");
  }
  
  function fetch() {
    throw new Error("method not implemented: fetch()");
  }
  
  function read() {
    var length = this.buffers && this.buffers.length;
  
    // fetch the first result
    if (!length) return this.fetch();
  
    // flush current buffer
    this.flush();
  
    // read from the results
    return this.pull();
  }
  
  function push(chunk) {
    var buffers = this.buffers || (this.buffers = []);
    buffers.push(chunk);
  }
  
  function pull() {
    var buffers = this.buffers || (this.buffers = []);
    return buffers.shift();
  }
  
  function mixinFactory(source) {
    return mixin;
  
    function mixin(target) {
      for (var key in source) {
        target[key] = source[key];
      }
      return target;
    }
  }
  
  },{"./bufferish":77}],91:[function(require,module,exports){
  // read-core.js
  
  var ExtBuffer = require("./ext-buffer").ExtBuffer;
  var ExtUnpacker = require("./ext-unpacker");
  var readUint8 = require("./read-format").readUint8;
  var ReadToken = require("./read-token");
  var CodecBase = require("./codec-base");
  
  CodecBase.install({
    addExtUnpacker: addExtUnpacker,
    getExtUnpacker: getExtUnpacker,
    init: init
  });
  
  exports.preset = init.call(CodecBase.preset);
  
  function getDecoder(options) {
    var readToken = ReadToken.getReadToken(options);
    return decode;
  
    function decode(decoder) {
      var type = readUint8(decoder);
      var func = readToken[type];
      if (!func) throw new Error("Invalid type: " + (type ? ("0x" + type.toString(16)) : type));
      return func(decoder);
    }
  }
  
  function init() {
    var options = this.options;
    this.decode = getDecoder(options);
  
    if (options && options.preset) {
      ExtUnpacker.setExtUnpackers(this);
    }
  
    return this;
  }
  
  function addExtUnpacker(etype, unpacker) {
    var unpackers = this.extUnpackers || (this.extUnpackers = []);
    unpackers[etype] = CodecBase.filter(unpacker);
  }
  
  function getExtUnpacker(type) {
    var unpackers = this.extUnpackers || (this.extUnpackers = []);
    return unpackers[type] || extUnpacker;
  
    function extUnpacker(buffer) {
      return new ExtBuffer(buffer, type);
    }
  }
  
  },{"./codec-base":78,"./ext-buffer":86,"./ext-unpacker":88,"./read-format":92,"./read-token":93}],92:[function(require,module,exports){
  // read-format.js
  
  var ieee754 = require("ieee754");
  var Int64Buffer = require("int64-buffer");
  var Uint64BE = Int64Buffer.Uint64BE;
  var Int64BE = Int64Buffer.Int64BE;
  
  exports.getReadFormat = getReadFormat;
  exports.readUint8 = uint8;
  
  var Bufferish = require("./bufferish");
  var BufferProto = require("./bufferish-proto");
  
  var HAS_MAP = ("undefined" !== typeof Map);
  var NO_ASSERT = true;
  
  function getReadFormat(options) {
    var binarraybuffer = Bufferish.hasArrayBuffer && options && options.binarraybuffer;
    var int64 = options && options.int64;
    var usemap = HAS_MAP && options && options.usemap;
  
    var readFormat = {
      map: (usemap ? map_to_map : map_to_obj),
      array: array,
      str: str,
      bin: (binarraybuffer ? bin_arraybuffer : bin_buffer),
      ext: ext,
      uint8: uint8,
      uint16: uint16,
      uint32: uint32,
      uint64: read(8, int64 ? readUInt64BE_int64 : readUInt64BE),
      int8: int8,
      int16: int16,
      int32: int32,
      int64: read(8, int64 ? readInt64BE_int64 : readInt64BE),
      float32: read(4, readFloatBE),
      float64: read(8, readDoubleBE)
    };
  
    return readFormat;
  }
  
  function map_to_obj(decoder, len) {
    var value = {};
    var i;
    var k = new Array(len);
    var v = new Array(len);
  
    var decode = decoder.codec.decode;
    for (i = 0; i < len; i++) {
      k[i] = decode(decoder);
      v[i] = decode(decoder);
    }
    for (i = 0; i < len; i++) {
      value[k[i]] = v[i];
    }
    return value;
  }
  
  function map_to_map(decoder, len) {
    var value = new Map();
    var i;
    var k = new Array(len);
    var v = new Array(len);
  
    var decode = decoder.codec.decode;
    for (i = 0; i < len; i++) {
      k[i] = decode(decoder);
      v[i] = decode(decoder);
    }
    for (i = 0; i < len; i++) {
      value.set(k[i], v[i]);
    }
    return value;
  }
  
  function array(decoder, len) {
    var value = new Array(len);
    var decode = decoder.codec.decode;
    for (var i = 0; i < len; i++) {
      value[i] = decode(decoder);
    }
    return value;
  }
  
  function str(decoder, len) {
    var start = decoder.reserve(len);
    var end = start + len;
    return BufferProto.toString.call(decoder.buffer, "utf-8", start, end);
  }
  
  function bin_buffer(decoder, len) {
    var start = decoder.reserve(len);
    var end = start + len;
    var buf = BufferProto.slice.call(decoder.buffer, start, end);
    return Bufferish.from(buf);
  }
  
  function bin_arraybuffer(decoder, len) {
    var start = decoder.reserve(len);
    var end = start + len;
    var buf = BufferProto.slice.call(decoder.buffer, start, end);
    return Bufferish.Uint8Array.from(buf).buffer;
  }
  
  function ext(decoder, len) {
    var start = decoder.reserve(len+1);
    var type = decoder.buffer[start++];
    var end = start + len;
    var unpack = decoder.codec.getExtUnpacker(type);
    if (!unpack) throw new Error("Invalid ext type: " + (type ? ("0x" + type.toString(16)) : type));
    var buf = BufferProto.slice.call(decoder.buffer, start, end);
    return unpack(buf);
  }
  
  function uint8(decoder) {
    var start = decoder.reserve(1);
    return decoder.buffer[start];
  }
  
  function int8(decoder) {
    var start = decoder.reserve(1);
    var value = decoder.buffer[start];
    return (value & 0x80) ? value - 0x100 : value;
  }
  
  function uint16(decoder) {
    var start = decoder.reserve(2);
    var buffer = decoder.buffer;
    return (buffer[start++] << 8) | buffer[start];
  }
  
  function int16(decoder) {
    var start = decoder.reserve(2);
    var buffer = decoder.buffer;
    var value = (buffer[start++] << 8) | buffer[start];
    return (value & 0x8000) ? value - 0x10000 : value;
  }
  
  function uint32(decoder) {
    var start = decoder.reserve(4);
    var buffer = decoder.buffer;
    return (buffer[start++] * 16777216) + (buffer[start++] << 16) + (buffer[start++] << 8) + buffer[start];
  }
  
  function int32(decoder) {
    var start = decoder.reserve(4);
    var buffer = decoder.buffer;
    return (buffer[start++] << 24) | (buffer[start++] << 16) | (buffer[start++] << 8) | buffer[start];
  }
  
  function read(len, method) {
    return function(decoder) {
      var start = decoder.reserve(len);
      return method.call(decoder.buffer, start, NO_ASSERT);
    };
  }
  
  function readUInt64BE(start) {
    return new Uint64BE(this, start).toNumber();
  }
  
  function readInt64BE(start) {
    return new Int64BE(this, start).toNumber();
  }
  
  function readUInt64BE_int64(start) {
    return new Uint64BE(this, start);
  }
  
  function readInt64BE_int64(start) {
    return new Int64BE(this, start);
  }
  
  function readFloatBE(start) {
    return ieee754.read(this, start, false, 23, 4);
  }
  
  function readDoubleBE(start) {
    return ieee754.read(this, start, false, 52, 8);
  }
  },{"./bufferish":77,"./bufferish-proto":75,"ieee754":67,"int64-buffer":68}],93:[function(require,module,exports){
  // read-token.js
  
  var ReadFormat = require("./read-format");
  
  exports.getReadToken = getReadToken;
  
  function getReadToken(options) {
    var format = ReadFormat.getReadFormat(options);
  
    if (options && options.useraw) {
      return init_useraw(format);
    } else {
      return init_token(format);
    }
  }
  
  function init_token(format) {
    var i;
    var token = new Array(256);
  
    // positive fixint -- 0x00 - 0x7f
    for (i = 0x00; i <= 0x7f; i++) {
      token[i] = constant(i);
    }
  
    // fixmap -- 0x80 - 0x8f
    for (i = 0x80; i <= 0x8f; i++) {
      token[i] = fix(i - 0x80, format.map);
    }
  
    // fixarray -- 0x90 - 0x9f
    for (i = 0x90; i <= 0x9f; i++) {
      token[i] = fix(i - 0x90, format.array);
    }
  
    // fixstr -- 0xa0 - 0xbf
    for (i = 0xa0; i <= 0xbf; i++) {
      token[i] = fix(i - 0xa0, format.str);
    }
  
    // nil -- 0xc0
    token[0xc0] = constant(null);
  
    // (never used) -- 0xc1
    token[0xc1] = null;
  
    // false -- 0xc2
    // true -- 0xc3
    token[0xc2] = constant(false);
    token[0xc3] = constant(true);
  
    // bin 8 -- 0xc4
    // bin 16 -- 0xc5
    // bin 32 -- 0xc6
    token[0xc4] = flex(format.uint8, format.bin);
    token[0xc5] = flex(format.uint16, format.bin);
    token[0xc6] = flex(format.uint32, format.bin);
  
    // ext 8 -- 0xc7
    // ext 16 -- 0xc8
    // ext 32 -- 0xc9
    token[0xc7] = flex(format.uint8, format.ext);
    token[0xc8] = flex(format.uint16, format.ext);
    token[0xc9] = flex(format.uint32, format.ext);
  
    // float 32 -- 0xca
    // float 64 -- 0xcb
    token[0xca] = format.float32;
    token[0xcb] = format.float64;
  
    // uint 8 -- 0xcc
    // uint 16 -- 0xcd
    // uint 32 -- 0xce
    // uint 64 -- 0xcf
    token[0xcc] = format.uint8;
    token[0xcd] = format.uint16;
    token[0xce] = format.uint32;
    token[0xcf] = format.uint64;
  
    // int 8 -- 0xd0
    // int 16 -- 0xd1
    // int 32 -- 0xd2
    // int 64 -- 0xd3
    token[0xd0] = format.int8;
    token[0xd1] = format.int16;
    token[0xd2] = format.int32;
    token[0xd3] = format.int64;
  
    // fixext 1 -- 0xd4
    // fixext 2 -- 0xd5
    // fixext 4 -- 0xd6
    // fixext 8 -- 0xd7
    // fixext 16 -- 0xd8
    token[0xd4] = fix(1, format.ext);
    token[0xd5] = fix(2, format.ext);
    token[0xd6] = fix(4, format.ext);
    token[0xd7] = fix(8, format.ext);
    token[0xd8] = fix(16, format.ext);
  
    // str 8 -- 0xd9
    // str 16 -- 0xda
    // str 32 -- 0xdb
    token[0xd9] = flex(format.uint8, format.str);
    token[0xda] = flex(format.uint16, format.str);
    token[0xdb] = flex(format.uint32, format.str);
  
    // array 16 -- 0xdc
    // array 32 -- 0xdd
    token[0xdc] = flex(format.uint16, format.array);
    token[0xdd] = flex(format.uint32, format.array);
  
    // map 16 -- 0xde
    // map 32 -- 0xdf
    token[0xde] = flex(format.uint16, format.map);
    token[0xdf] = flex(format.uint32, format.map);
  
    // negative fixint -- 0xe0 - 0xff
    for (i = 0xe0; i <= 0xff; i++) {
      token[i] = constant(i - 0x100);
    }
  
    return token;
  }
  
  function init_useraw(format) {
    var i;
    var token = init_token(format).slice();
  
    // raw 8 -- 0xd9
    // raw 16 -- 0xda
    // raw 32 -- 0xdb
    token[0xd9] = token[0xc4];
    token[0xda] = token[0xc5];
    token[0xdb] = token[0xc6];
  
    // fixraw -- 0xa0 - 0xbf
    for (i = 0xa0; i <= 0xbf; i++) {
      token[i] = fix(i - 0xa0, format.bin);
    }
  
    return token;
  }
  
  function constant(value) {
    return function() {
      return value;
    };
  }
  
  function flex(lenFunc, decodeFunc) {
    return function(decoder) {
      var len = lenFunc(decoder);
      return decodeFunc(decoder, len);
    };
  }
  
  function fix(len, method) {
    return function(decoder) {
      return method(decoder, len);
    };
  }
  
  },{"./read-format":92}],94:[function(require,module,exports){
  // write-core.js
  
  var ExtBuffer = require("./ext-buffer").ExtBuffer;
  var ExtPacker = require("./ext-packer");
  var WriteType = require("./write-type");
  var CodecBase = require("./codec-base");
  
  CodecBase.install({
    addExtPacker: addExtPacker,
    getExtPacker: getExtPacker,
    init: init
  });
  
  exports.preset = init.call(CodecBase.preset);
  
  function getEncoder(options) {
    var writeType = WriteType.getWriteType(options);
    return encode;
  
    function encode(encoder, value) {
      var func = writeType[typeof value];
      if (!func) throw new Error("Unsupported type \"" + (typeof value) + "\": " + value);
      func(encoder, value);
    }
  }
  
  function init() {
    var options = this.options;
    this.encode = getEncoder(options);
  
    if (options && options.preset) {
      ExtPacker.setExtPackers(this);
    }
  
    return this;
  }
  
  function addExtPacker(etype, Class, packer) {
    packer = CodecBase.filter(packer);
    var name = Class.name;
    if (name && name !== "Object") {
      var packers = this.extPackers || (this.extPackers = {});
      packers[name] = extPacker;
    } else {
      // fallback for IE
      var list = this.extEncoderList || (this.extEncoderList = []);
      list.unshift([Class, extPacker]);
    }
  
    function extPacker(value) {
      if (packer) value = packer(value);
      return new ExtBuffer(value, etype);
    }
  }
  
  function getExtPacker(value) {
    var packers = this.extPackers || (this.extPackers = {});
    var c = value.constructor;
    var e = c && c.name && packers[c.name];
    if (e) return e;
  
    // fallback for IE
    var list = this.extEncoderList || (this.extEncoderList = []);
    var len = list.length;
    for (var i = 0; i < len; i++) {
      var pair = list[i];
      if (c === pair[0]) return pair[1];
    }
  }
  
  },{"./codec-base":78,"./ext-buffer":86,"./ext-packer":87,"./write-type":96}],95:[function(require,module,exports){
  // write-token.js
  
  var ieee754 = require("ieee754");
  var Int64Buffer = require("int64-buffer");
  var Uint64BE = Int64Buffer.Uint64BE;
  var Int64BE = Int64Buffer.Int64BE;
  
  var uint8 = require("./write-uint8").uint8;
  var Bufferish = require("./bufferish");
  var Buffer = Bufferish.global;
  var IS_BUFFER_SHIM = Bufferish.hasBuffer && ("TYPED_ARRAY_SUPPORT" in Buffer);
  var NO_TYPED_ARRAY = IS_BUFFER_SHIM && !Buffer.TYPED_ARRAY_SUPPORT;
  var Buffer_prototype = Bufferish.hasBuffer && Buffer.prototype || {};
  
  exports.getWriteToken = getWriteToken;
  
  function getWriteToken(options) {
    if (options && options.uint8array) {
      return init_uint8array();
    } else if (NO_TYPED_ARRAY || (Bufferish.hasBuffer && options && options.safe)) {
      return init_safe();
    } else {
      return init_token();
    }
  }
  
  function init_uint8array() {
    var token = init_token();
  
    // float 32 -- 0xca
    // float 64 -- 0xcb
    token[0xca] = writeN(0xca, 4, writeFloatBE);
    token[0xcb] = writeN(0xcb, 8, writeDoubleBE);
  
    return token;
  }
  
  // Node.js and browsers with TypedArray
  
  function init_token() {
    // (immediate values)
    // positive fixint -- 0x00 - 0x7f
    // nil -- 0xc0
    // false -- 0xc2
    // true -- 0xc3
    // negative fixint -- 0xe0 - 0xff
    var token = uint8.slice();
  
    // bin 8 -- 0xc4
    // bin 16 -- 0xc5
    // bin 32 -- 0xc6
    token[0xc4] = write1(0xc4);
    token[0xc5] = write2(0xc5);
    token[0xc6] = write4(0xc6);
  
    // ext 8 -- 0xc7
    // ext 16 -- 0xc8
    // ext 32 -- 0xc9
    token[0xc7] = write1(0xc7);
    token[0xc8] = write2(0xc8);
    token[0xc9] = write4(0xc9);
  
    // float 32 -- 0xca
    // float 64 -- 0xcb
    token[0xca] = writeN(0xca, 4, (Buffer_prototype.writeFloatBE || writeFloatBE), true);
    token[0xcb] = writeN(0xcb, 8, (Buffer_prototype.writeDoubleBE || writeDoubleBE), true);
  
    // uint 8 -- 0xcc
    // uint 16 -- 0xcd
    // uint 32 -- 0xce
    // uint 64 -- 0xcf
    token[0xcc] = write1(0xcc);
    token[0xcd] = write2(0xcd);
    token[0xce] = write4(0xce);
    token[0xcf] = writeN(0xcf, 8, writeUInt64BE);
  
    // int 8 -- 0xd0
    // int 16 -- 0xd1
    // int 32 -- 0xd2
    // int 64 -- 0xd3
    token[0xd0] = write1(0xd0);
    token[0xd1] = write2(0xd1);
    token[0xd2] = write4(0xd2);
    token[0xd3] = writeN(0xd3, 8, writeInt64BE);
  
    // str 8 -- 0xd9
    // str 16 -- 0xda
    // str 32 -- 0xdb
    token[0xd9] = write1(0xd9);
    token[0xda] = write2(0xda);
    token[0xdb] = write4(0xdb);
  
    // array 16 -- 0xdc
    // array 32 -- 0xdd
    token[0xdc] = write2(0xdc);
    token[0xdd] = write4(0xdd);
  
    // map 16 -- 0xde
    // map 32 -- 0xdf
    token[0xde] = write2(0xde);
    token[0xdf] = write4(0xdf);
  
    return token;
  }
  
  // safe mode: for old browsers and who needs asserts
  
  function init_safe() {
    // (immediate values)
    // positive fixint -- 0x00 - 0x7f
    // nil -- 0xc0
    // false -- 0xc2
    // true -- 0xc3
    // negative fixint -- 0xe0 - 0xff
    var token = uint8.slice();
  
    // bin 8 -- 0xc4
    // bin 16 -- 0xc5
    // bin 32 -- 0xc6
    token[0xc4] = writeN(0xc4, 1, Buffer.prototype.writeUInt8);
    token[0xc5] = writeN(0xc5, 2, Buffer.prototype.writeUInt16BE);
    token[0xc6] = writeN(0xc6, 4, Buffer.prototype.writeUInt32BE);
  
    // ext 8 -- 0xc7
    // ext 16 -- 0xc8
    // ext 32 -- 0xc9
    token[0xc7] = writeN(0xc7, 1, Buffer.prototype.writeUInt8);
    token[0xc8] = writeN(0xc8, 2, Buffer.prototype.writeUInt16BE);
    token[0xc9] = writeN(0xc9, 4, Buffer.prototype.writeUInt32BE);
  
    // float 32 -- 0xca
    // float 64 -- 0xcb
    token[0xca] = writeN(0xca, 4, Buffer.prototype.writeFloatBE);
    token[0xcb] = writeN(0xcb, 8, Buffer.prototype.writeDoubleBE);
  
    // uint 8 -- 0xcc
    // uint 16 -- 0xcd
    // uint 32 -- 0xce
    // uint 64 -- 0xcf
    token[0xcc] = writeN(0xcc, 1, Buffer.prototype.writeUInt8);
    token[0xcd] = writeN(0xcd, 2, Buffer.prototype.writeUInt16BE);
    token[0xce] = writeN(0xce, 4, Buffer.prototype.writeUInt32BE);
    token[0xcf] = writeN(0xcf, 8, writeUInt64BE);
  
    // int 8 -- 0xd0
    // int 16 -- 0xd1
    // int 32 -- 0xd2
    // int 64 -- 0xd3
    token[0xd0] = writeN(0xd0, 1, Buffer.prototype.writeInt8);
    token[0xd1] = writeN(0xd1, 2, Buffer.prototype.writeInt16BE);
    token[0xd2] = writeN(0xd2, 4, Buffer.prototype.writeInt32BE);
    token[0xd3] = writeN(0xd3, 8, writeInt64BE);
  
    // str 8 -- 0xd9
    // str 16 -- 0xda
    // str 32 -- 0xdb
    token[0xd9] = writeN(0xd9, 1, Buffer.prototype.writeUInt8);
    token[0xda] = writeN(0xda, 2, Buffer.prototype.writeUInt16BE);
    token[0xdb] = writeN(0xdb, 4, Buffer.prototype.writeUInt32BE);
  
    // array 16 -- 0xdc
    // array 32 -- 0xdd
    token[0xdc] = writeN(0xdc, 2, Buffer.prototype.writeUInt16BE);
    token[0xdd] = writeN(0xdd, 4, Buffer.prototype.writeUInt32BE);
  
    // map 16 -- 0xde
    // map 32 -- 0xdf
    token[0xde] = writeN(0xde, 2, Buffer.prototype.writeUInt16BE);
    token[0xdf] = writeN(0xdf, 4, Buffer.prototype.writeUInt32BE);
  
    return token;
  }
  
  function write1(type) {
    return function(encoder, value) {
      var offset = encoder.reserve(2);
      var buffer = encoder.buffer;
      buffer[offset++] = type;
      buffer[offset] = value;
    };
  }
  
  function write2(type) {
    return function(encoder, value) {
      var offset = encoder.reserve(3);
      var buffer = encoder.buffer;
      buffer[offset++] = type;
      buffer[offset++] = value >>> 8;
      buffer[offset] = value;
    };
  }
  
  function write4(type) {
    return function(encoder, value) {
      var offset = encoder.reserve(5);
      var buffer = encoder.buffer;
      buffer[offset++] = type;
      buffer[offset++] = value >>> 24;
      buffer[offset++] = value >>> 16;
      buffer[offset++] = value >>> 8;
      buffer[offset] = value;
    };
  }
  
  function writeN(type, len, method, noAssert) {
    return function(encoder, value) {
      var offset = encoder.reserve(len + 1);
      encoder.buffer[offset++] = type;
      method.call(encoder.buffer, value, offset, noAssert);
    };
  }
  
  function writeUInt64BE(value, offset) {
    new Uint64BE(this, offset, value);
  }
  
  function writeInt64BE(value, offset) {
    new Int64BE(this, offset, value);
  }
  
  function writeFloatBE(value, offset) {
    ieee754.write(this, value, offset, false, 23, 4);
  }
  
  function writeDoubleBE(value, offset) {
    ieee754.write(this, value, offset, false, 52, 8);
  }
  
  },{"./bufferish":77,"./write-uint8":97,"ieee754":67,"int64-buffer":68}],96:[function(require,module,exports){
  // write-type.js
  
  var IS_ARRAY = require("isarray");
  var Int64Buffer = require("int64-buffer");
  var Uint64BE = Int64Buffer.Uint64BE;
  var Int64BE = Int64Buffer.Int64BE;
  
  var Bufferish = require("./bufferish");
  var BufferProto = require("./bufferish-proto");
  var WriteToken = require("./write-token");
  var uint8 = require("./write-uint8").uint8;
  var ExtBuffer = require("./ext-buffer").ExtBuffer;
  
  var HAS_UINT8ARRAY = ("undefined" !== typeof Uint8Array);
  var HAS_MAP = ("undefined" !== typeof Map);
  
  var extmap = [];
  extmap[1] = 0xd4;
  extmap[2] = 0xd5;
  extmap[4] = 0xd6;
  extmap[8] = 0xd7;
  extmap[16] = 0xd8;
  
  exports.getWriteType = getWriteType;
  
  function getWriteType(options) {
    var token = WriteToken.getWriteToken(options);
    var useraw = options && options.useraw;
    var binarraybuffer = HAS_UINT8ARRAY && options && options.binarraybuffer;
    var isBuffer = binarraybuffer ? Bufferish.isArrayBuffer : Bufferish.isBuffer;
    var bin = binarraybuffer ? bin_arraybuffer : bin_buffer;
    var usemap = HAS_MAP && options && options.usemap;
    var map = usemap ? map_to_map : obj_to_map;
  
    var writeType = {
      "boolean": bool,
      "function": nil,
      "number": number,
      "object": (useraw ? object_raw : object),
      "string": _string(useraw ? raw_head_size : str_head_size),
      "symbol": nil,
      "undefined": nil
    };
  
    return writeType;
  
    // false -- 0xc2
    // true -- 0xc3
    function bool(encoder, value) {
      var type = value ? 0xc3 : 0xc2;
      token[type](encoder, value);
    }
  
    function number(encoder, value) {
      var ivalue = value | 0;
      var type;
      if (value !== ivalue) {
        // float 64 -- 0xcb
        type = 0xcb;
        token[type](encoder, value);
        return;
      } else if (-0x20 <= ivalue && ivalue <= 0x7F) {
        // positive fixint -- 0x00 - 0x7f
        // negative fixint -- 0xe0 - 0xff
        type = ivalue & 0xFF;
      } else if (0 <= ivalue) {
        // uint 8 -- 0xcc
        // uint 16 -- 0xcd
        // uint 32 -- 0xce
        type = (ivalue <= 0xFF) ? 0xcc : (ivalue <= 0xFFFF) ? 0xcd : 0xce;
      } else {
        // int 8 -- 0xd0
        // int 16 -- 0xd1
        // int 32 -- 0xd2
        type = (-0x80 <= ivalue) ? 0xd0 : (-0x8000 <= ivalue) ? 0xd1 : 0xd2;
      }
      token[type](encoder, ivalue);
    }
  
    // uint 64 -- 0xcf
    function uint64(encoder, value) {
      var type = 0xcf;
      token[type](encoder, value.toArray());
    }
  
    // int 64 -- 0xd3
    function int64(encoder, value) {
      var type = 0xd3;
      token[type](encoder, value.toArray());
    }
  
    // str 8 -- 0xd9
    // str 16 -- 0xda
    // str 32 -- 0xdb
    // fixstr -- 0xa0 - 0xbf
    function str_head_size(length) {
      return (length < 32) ? 1 : (length <= 0xFF) ? 2 : (length <= 0xFFFF) ? 3 : 5;
    }
  
    // raw 16 -- 0xda
    // raw 32 -- 0xdb
    // fixraw -- 0xa0 - 0xbf
    function raw_head_size(length) {
      return (length < 32) ? 1 : (length <= 0xFFFF) ? 3 : 5;
    }
  
    function _string(head_size) {
      return string;
  
      function string(encoder, value) {
        // prepare buffer
        var length = value.length;
        var maxsize = 5 + length * 3;
        encoder.offset = encoder.reserve(maxsize);
        var buffer = encoder.buffer;
  
        // expected header size
        var expected = head_size(length);
  
        // expected start point
        var start = encoder.offset + expected;
  
        // write string
        length = BufferProto.write.call(buffer, value, start);
  
        // actual header size
        var actual = head_size(length);
  
        // move content when needed
        if (expected !== actual) {
          var targetStart = start + actual - expected;
          var end = start + length;
          BufferProto.copy.call(buffer, buffer, targetStart, start, end);
        }
  
        // write header
        var type = (actual === 1) ? (0xa0 + length) : (actual <= 3) ? (0xd7 + actual) : 0xdb;
        token[type](encoder, length);
  
        // move cursor
        encoder.offset += length;
      }
    }
  
    function object(encoder, value) {
      // null
      if (value === null) return nil(encoder, value);
  
      // Buffer
      if (isBuffer(value)) return bin(encoder, value);
  
      // Array
      if (IS_ARRAY(value)) return array(encoder, value);
  
      // int64-buffer objects
      if (Uint64BE.isUint64BE(value)) return uint64(encoder, value);
      if (Int64BE.isInt64BE(value)) return int64(encoder, value);
  
      // ext formats
      var packer = encoder.codec.getExtPacker(value);
      if (packer) value = packer(value);
      if (value instanceof ExtBuffer) return ext(encoder, value);
  
      // plain old Objects or Map
      map(encoder, value);
    }
  
    function object_raw(encoder, value) {
      // Buffer
      if (isBuffer(value)) return raw(encoder, value);
  
      // others
      object(encoder, value);
    }
  
    // nil -- 0xc0
    function nil(encoder, value) {
      var type = 0xc0;
      token[type](encoder, value);
    }
  
    // fixarray -- 0x90 - 0x9f
    // array 16 -- 0xdc
    // array 32 -- 0xdd
    function array(encoder, value) {
      var length = value.length;
      var type = (length < 16) ? (0x90 + length) : (length <= 0xFFFF) ? 0xdc : 0xdd;
      token[type](encoder, length);
  
      var encode = encoder.codec.encode;
      for (var i = 0; i < length; i++) {
        encode(encoder, value[i]);
      }
    }
  
    // bin 8 -- 0xc4
    // bin 16 -- 0xc5
    // bin 32 -- 0xc6
    function bin_buffer(encoder, value) {
      var length = value.length;
      var type = (length < 0xFF) ? 0xc4 : (length <= 0xFFFF) ? 0xc5 : 0xc6;
      token[type](encoder, length);
      encoder.send(value);
    }
  
    function bin_arraybuffer(encoder, value) {
      bin_buffer(encoder, new Uint8Array(value));
    }
  
    // fixext 1 -- 0xd4
    // fixext 2 -- 0xd5
    // fixext 4 -- 0xd6
    // fixext 8 -- 0xd7
    // fixext 16 -- 0xd8
    // ext 8 -- 0xc7
    // ext 16 -- 0xc8
    // ext 32 -- 0xc9
    function ext(encoder, value) {
      var buffer = value.buffer;
      var length = buffer.length;
      var type = extmap[length] || ((length < 0xFF) ? 0xc7 : (length <= 0xFFFF) ? 0xc8 : 0xc9);
      token[type](encoder, length);
      uint8[value.type](encoder);
      encoder.send(buffer);
    }
  
    // fixmap -- 0x80 - 0x8f
    // map 16 -- 0xde
    // map 32 -- 0xdf
    function obj_to_map(encoder, value) {
      var keys = Object.keys(value);
      var length = keys.length;
      var type = (length < 16) ? (0x80 + length) : (length <= 0xFFFF) ? 0xde : 0xdf;
      token[type](encoder, length);
  
      var encode = encoder.codec.encode;
      keys.forEach(function(key) {
        encode(encoder, key);
        encode(encoder, value[key]);
      });
    }
  
    // fixmap -- 0x80 - 0x8f
    // map 16 -- 0xde
    // map 32 -- 0xdf
    function map_to_map(encoder, value) {
      if (!(value instanceof Map)) return obj_to_map(encoder, value);
  
      var length = value.size;
      var type = (length < 16) ? (0x80 + length) : (length <= 0xFFFF) ? 0xde : 0xdf;
      token[type](encoder, length);
  
      var encode = encoder.codec.encode;
      value.forEach(function(val, key, m) {
        encode(encoder, key);
        encode(encoder, val);
      });
    }
  
    // raw 16 -- 0xda
    // raw 32 -- 0xdb
    // fixraw -- 0xa0 - 0xbf
    function raw(encoder, value) {
      var length = value.length;
      var type = (length < 32) ? (0xa0 + length) : (length <= 0xFFFF) ? 0xda : 0xdb;
      token[type](encoder, length);
      encoder.send(value);
    }
  }
  
  },{"./bufferish":77,"./bufferish-proto":75,"./ext-buffer":86,"./write-token":95,"./write-uint8":97,"int64-buffer":68,"isarray":69}],97:[function(require,module,exports){
  // write-unit8.js
  
  var constant = exports.uint8 = new Array(256);
  
  for (var i = 0x00; i <= 0xFF; i++) {
    constant[i] = write0(i);
  }
  
  function write0(type) {
    return function(encoder) {
      var offset = encoder.reserve(1);
      encoder.buffer[offset] = type;
    };
  }
  
  },{}],98:[function(require,module,exports){
  (function (Buffer){
  // Generated by CoffeeScript 1.10.0
  (function() {
    var NoFilter, stream, util,
      extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
      hasProp = {}.hasOwnProperty;
  
    stream = require('stream');
  
    util = require('util');
  
    module.exports = NoFilter = (function(superClass) {
      var _read_gen, _write_gen, get;
  
      extend(NoFilter, superClass);
  
      function NoFilter(input, inputEncoding, options) {
        var inp, inpE, ref, watchPipe;
        if (options == null) {
          options = {};
        }
        inp = void 0;
        inpE = void 0;
        switch (typeof input) {
          case 'object':
            if (Buffer.isBuffer(input)) {
              inp = input;
              if ((inputEncoding != null) && (typeof inputEncoding === 'object')) {
                options = inputEncoding;
              }
            } else {
              options = input;
            }
            break;
          case 'string':
            inp = input;
            if ((inputEncoding != null) && (typeof inputEncoding === 'object')) {
              options = inputEncoding;
            } else {
              inpE = inputEncoding;
            }
        }
        if (options == null) {
          options = {};
        }
        if (inp == null) {
          inp = options.input;
        }
        if (inpE == null) {
          inpE = options.inputEncoding;
        }
        delete options.input;
        delete options.inputEncoding;
        watchPipe = (ref = options.watchPipe) != null ? ref : true;
        delete options.watchPipe;
        NoFilter.__super__.constructor.call(this, options);
        if (watchPipe) {
          this.on('pipe', (function(_this) {
            return function(readable) {
              var om;
              om = readable._readableState.objectMode;
              if ((_this.length > 0) && (om !== _this._readableState.objectMode)) {
                throw new Error('Do not switch objectMode in the middle of the stream');
              }
              _this._readableState.objectMode = om;
              return _this._writableState.objectMode = om;
            };
          })(this));
        }
        if (inp != null) {
          this.end(inp, inpE);
        }
      }
  
      NoFilter.isNoFilter = function(obj) {
        return obj instanceof this;
      };
  
      NoFilter.compare = function(nf1, nf2) {
        if (!(nf1 instanceof this)) {
          throw new TypeError('Arguments must be NoFilters');
        }
        if (nf1 === nf2) {
          return 0;
        } else {
          return nf1.compare(nf2);
        }
      };
  
      NoFilter.concat = function(list, length) {
        var bufs;
        if (!Array.isArray(list)) {
          throw new TypeError('list argument must be an Array of NoFilters');
        }
        if ((list.length === 0) || (length === 0)) {
          return new Buffer(0);
        }
        if (length == null) {
          length = list.reduce(function(tot, nf) {
            if (!(nf instanceof NoFilter)) {
              throw new TypeError('list argument must be an Array of NoFilters');
            }
            return tot + nf.length;
          }, 0);
        }
        bufs = list.map(function(nf) {
          if (!(nf instanceof NoFilter)) {
            throw new TypeError('list argument must be an Array of NoFilters');
          }
          if (nf._readableState.objectMode) {
            throw new Error('NoFilter may not be in object mode for concat');
          }
          return nf.slice();
        });
        return Buffer.concat(bufs, length);
      };
  
      NoFilter.prototype._transform = function(chunk, encoding, callback) {
        if (!this._readableState.objectMode && !Buffer.isBuffer(chunk)) {
          chunk = new Buffer(chunk, encoding);
        }
        this.push(chunk);
        return callback();
      };
  
      NoFilter.prototype._bufArray = function() {
        var b, bufs;
        bufs = this._readableState.buffer;
        if (!Array.isArray(bufs)) {
          b = bufs.head;
          bufs = [];
          while (b != null) {
            bufs.push(b.data);
            b = b.next;
          }
        }
        return bufs;
      };
  
      NoFilter.prototype.read = function(size) {
        var buf;
        buf = NoFilter.__super__.read.call(this, size);
        if (buf != null) {
          this.emit('read', buf);
        }
        return buf;
      };
  
      NoFilter.prototype.promise = function(cb) {
        var done;
        done = false;
        return new Promise((function(_this) {
          return function(resolve, reject) {
            _this.on('finish', function() {
              var data;
              data = _this.read();
              if ((cb != null) && !done) {
                done = true;
                cb(null, data);
              }
              return resolve(data);
            });
            return _this.on('error', function(er) {
              if ((cb != null) && !done) {
                done = true;
                cb(er);
              }
              return reject(er);
            });
          };
        })(this));
      };
  
      NoFilter.prototype.compare = function(other) {
        if (!(other instanceof NoFilter)) {
          throw new TypeError('Arguments must be NoFilters');
        }
        if (this._readableState.objectMode || other._readableState.objectMode) {
          throw new Error('Must not be in object mode to compare');
        }
        if (this === other) {
          return 0;
        } else {
          return this.slice().compare(other.slice());
        }
      };
  
      NoFilter.prototype.equals = function(other) {
        return this.compare(other) === 0;
      };
  
      NoFilter.prototype.slice = function(start, end) {
        var b, bufs;
        if (this._readableState.objectMode) {
          return this._bufArray().slice(start, end);
        } else {
          bufs = this._bufArray();
          switch (bufs.length) {
            case 0:
              return new Buffer(0);
            case 1:
              return bufs[0].slice(start, end);
            default:
              b = Buffer.concat(bufs);
              return b.slice(start, end);
          }
        }
      };
  
      NoFilter.prototype.get = function(index) {
        return this.slice()[index];
      };
  
      NoFilter.prototype.toJSON = function() {
        var b;
        b = this.slice();
        if (Buffer.isBuffer(b)) {
          return b.toJSON();
        } else {
          return b;
        }
      };
  
      NoFilter.prototype.toString = function(encoding, start, end) {
        return this.slice().toString(encoding, start, end);
      };
  
      NoFilter.prototype.inspect = function(depth, options) {
        var bufs, hex;
        bufs = this._bufArray();
        hex = bufs.map(function(b) {
          if (Buffer.isBuffer(b)) {
            if (options != null ? options.stylize : void 0) {
              return options.stylize(b.toString('hex'), 'string');
            } else {
              return b.toString('hex');
            }
          } else {
            return util.inspect(b, options);
          }
        }).join(', ');
        return this.constructor.name + " [" + hex + "]";
      };
  
      _read_gen = function(meth, len) {
        return function(val) {
          var b;
          b = this.read(len);
          if (!Buffer.isBuffer(b)) {
            return null;
          }
          return b[meth].call(b, 0, true);
        };
      };
  
      _write_gen = function(meth, len) {
        return function(val) {
          var b;
          b = new Buffer(len);
          b[meth].call(b, val, 0, true);
          return this.push(b);
        };
      };
  
      NoFilter.prototype.writeUInt8 = _write_gen('writeUInt8', 1);
  
      NoFilter.prototype.writeUInt16LE = _write_gen('writeUInt16LE', 2);
  
      NoFilter.prototype.writeUInt16BE = _write_gen('writeUInt16BE', 2);
  
      NoFilter.prototype.writeUInt32LE = _write_gen('writeUInt32LE', 4);
  
      NoFilter.prototype.writeUInt32BE = _write_gen('writeUInt32BE', 4);
  
      NoFilter.prototype.writeInt8 = _write_gen('writeInt8', 1);
  
      NoFilter.prototype.writeInt16LE = _write_gen('writeInt16LE', 2);
  
      NoFilter.prototype.writeInt16BE = _write_gen('writeInt16BE', 2);
  
      NoFilter.prototype.writeInt32LE = _write_gen('writeInt32LE', 4);
  
      NoFilter.prototype.writeInt32BE = _write_gen('writeInt32BE', 4);
  
      NoFilter.prototype.writeFloatLE = _write_gen('writeFloatLE', 4);
  
      NoFilter.prototype.writeFloatBE = _write_gen('writeFloatBE', 4);
  
      NoFilter.prototype.writeDoubleLE = _write_gen('writeDoubleLE', 8);
  
      NoFilter.prototype.writeDoubleBE = _write_gen('writeDoubleBE', 8);
  
      NoFilter.prototype.readUInt8 = _read_gen('readUInt8', 1);
  
      NoFilter.prototype.readUInt16LE = _read_gen('readUInt16LE', 2);
  
      NoFilter.prototype.readUInt16BE = _read_gen('readUInt16BE', 2);
  
      NoFilter.prototype.readUInt32LE = _read_gen('readUInt32LE', 4);
  
      NoFilter.prototype.readUInt32BE = _read_gen('readUInt32BE', 4);
  
      NoFilter.prototype.readInt8 = _read_gen('readInt8', 1);
  
      NoFilter.prototype.readInt16LE = _read_gen('readInt16LE', 2);
  
      NoFilter.prototype.readInt16BE = _read_gen('readInt16BE', 2);
  
      NoFilter.prototype.readInt32LE = _read_gen('readInt32LE', 4);
  
      NoFilter.prototype.readInt32BE = _read_gen('readInt32BE', 4);
  
      NoFilter.prototype.readFloatLE = _read_gen('readFloatLE', 4);
  
      NoFilter.prototype.readFloatBE = _read_gen('readFloatBE', 4);
  
      NoFilter.prototype.readDoubleLE = _read_gen('readDoubleLE', 8);
  
      NoFilter.prototype.readDoubleBE = _read_gen('readDoubleBE', 8);
  
      get = function(props) {
        var getter, name, results;
        results = [];
        for (name in props) {
          getter = props[name];
          results.push(NoFilter.prototype.__defineGetter__(name, getter));
        }
        return results;
      };
  
      get({
        length: function() {
          return this._readableState.length;
        }
      });
  
      return NoFilter;
  
    })(stream.Transform);
  
  }).call(this);
  
  
  
  }).call(this,require("buffer").Buffer)
  },{"buffer":129,"stream":153,"util":160}],99:[function(require,module,exports){
  /** @license MIT License (c) copyright 2013-2014 original author or authors */
  
  /**
   * Collection of helper functions for wrapping and executing 'traditional'
   * synchronous functions in a promise interface.
   *
   * @author Brian Cavalier
   * @contributor Renato Zannon
   */
  
  (function(define) {
  define(function(require) {
  
  	var when = require('./when');
  	var attempt = when['try'];
  	var _liftAll = require('./lib/liftAll');
  	var _apply = require('./lib/apply')(when.Promise);
  	var slice = Array.prototype.slice;
  
  	return {
  		lift: lift,
  		liftAll: liftAll,
  		call: attempt,
  		apply: apply,
  		compose: compose
  	};
  
  	/**
  	 * Takes a function and an optional array of arguments (that might be promises),
  	 * and calls the function. The return value is a promise whose resolution
  	 * depends on the value returned by the function.
  	 * @param {function} f function to be called
  	 * @param {Array} [args] array of arguments to func
  	 * @returns {Promise} promise for the return value of func
  	 */
  	function apply(f, args) {
  		// slice args just in case the caller passed an Arguments instance
  		return _apply(f, this, args == null ? [] : slice.call(args));
  	}
  
  	/**
  	 * Takes a 'regular' function and returns a version of that function that
  	 * returns a promise instead of a plain value, and handles thrown errors by
  	 * returning a rejected promise. Also accepts a list of arguments to be
  	 * prepended to the new function, as does Function.prototype.bind.
  	 *
  	 * The resulting function is promise-aware, in the sense that it accepts
  	 * promise arguments, and waits for their resolution.
  	 * @param {Function} f function to be bound
  	 * @param {...*} [args] arguments to be prepended for the new function @deprecated
  	 * @returns {Function} a promise-returning function
  	 */
  	function lift(f /*, args... */) {
  		var args = arguments.length > 1 ? slice.call(arguments, 1) : [];
  		return function() {
  			return _apply(f, this, args.concat(slice.call(arguments)));
  		};
  	}
  
  	/**
  	 * Lift all the functions/methods on src
  	 * @param {object|function} src source whose functions will be lifted
  	 * @param {function?} combine optional function for customizing the lifting
  	 *  process. It is passed dst, the lifted function, and the property name of
  	 *  the original function on src.
  	 * @param {(object|function)?} dst option destination host onto which to place lifted
  	 *  functions. If not provided, liftAll returns a new object.
  	 * @returns {*} If dst is provided, returns dst with lifted functions as
  	 *  properties.  If dst not provided, returns a new object with lifted functions.
  	 */
  	function liftAll(src, combine, dst) {
  		return _liftAll(lift, combine, dst, src);
  	}
  
  	/**
  	 * Composes multiple functions by piping their return values. It is
  	 * transparent to whether the functions return 'regular' values or promises:
  	 * the piped argument is always a resolved value. If one of the functions
  	 * throws or returns a rejected promise, the composed promise will be also
  	 * rejected.
  	 *
  	 * The arguments (or promises to arguments) given to the returned function (if
  	 * any), are passed directly to the first function on the 'pipeline'.
  	 * @param {Function} f the function to which the arguments will be passed
  	 * @param {...Function} [funcs] functions that will be composed, in order
  	 * @returns {Function} a promise-returning composition of the functions
  	 */
  	function compose(f /*, funcs... */) {
  		var funcs = slice.call(arguments, 1);
  
  		return function() {
  			var thisArg = this;
  			var args = slice.call(arguments);
  			var firstPromise = attempt.apply(thisArg, [f].concat(args));
  
  			return when.reduce(funcs, function(arg, func) {
  				return func.call(thisArg, arg);
  			}, firstPromise);
  		};
  	}
  });
  })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });
  
  
  
  },{"./lib/apply":103,"./lib/liftAll":115,"./when":123}],100:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function (require) {
  
  	var makePromise = require('./makePromise');
  	var Scheduler = require('./Scheduler');
  	var async = require('./env').asap;
  
  	return makePromise({
  		scheduler: new Scheduler(async)
  	});
  
  });
  })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });
  
  },{"./Scheduler":101,"./env":113,"./makePromise":116}],101:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function() {
  
  	// Credit to Twisol (https://github.com/Twisol) for suggesting
  	// this type of extensible queue + trampoline approach for next-tick conflation.
  
  	/**
  	 * Async task scheduler
  	 * @param {function} async function to schedule a single async function
  	 * @constructor
  	 */
  	function Scheduler(async) {
  		this._async = async;
  		this._running = false;
  
  		this._queue = this;
  		this._queueLen = 0;
  		this._afterQueue = {};
  		this._afterQueueLen = 0;
  
  		var self = this;
  		this.drain = function() {
  			self._drain();
  		};
  	}
  
  	/**
  	 * Enqueue a task
  	 * @param {{ run:function }} task
  	 */
  	Scheduler.prototype.enqueue = function(task) {
  		this._queue[this._queueLen++] = task;
  		this.run();
  	};
  
  	/**
  	 * Enqueue a task to run after the main task queue
  	 * @param {{ run:function }} task
  	 */
  	Scheduler.prototype.afterQueue = function(task) {
  		this._afterQueue[this._afterQueueLen++] = task;
  		this.run();
  	};
  
  	Scheduler.prototype.run = function() {
  		if (!this._running) {
  			this._running = true;
  			this._async(this.drain);
  		}
  	};
  
  	/**
  	 * Drain the handler queue entirely, and then the after queue
  	 */
  	Scheduler.prototype._drain = function() {
  		var i = 0;
  		for (; i < this._queueLen; ++i) {
  			this._queue[i].run();
  			this._queue[i] = void 0;
  		}
  
  		this._queueLen = 0;
  		this._running = false;
  
  		for (i = 0; i < this._afterQueueLen; ++i) {
  			this._afterQueue[i].run();
  			this._afterQueue[i] = void 0;
  		}
  
  		this._afterQueueLen = 0;
  	};
  
  	return Scheduler;
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  
  },{}],102:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function() {
  
  	/**
  	 * Custom error type for promises rejected by promise.timeout
  	 * @param {string} message
  	 * @constructor
  	 */
  	function TimeoutError (message) {
  		Error.call(this);
  		this.message = message;
  		this.name = TimeoutError.name;
  		if (typeof Error.captureStackTrace === 'function') {
  			Error.captureStackTrace(this, TimeoutError);
  		}
  	}
  
  	TimeoutError.prototype = Object.create(Error.prototype);
  	TimeoutError.prototype.constructor = TimeoutError;
  
  	return TimeoutError;
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  },{}],103:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function() {
  
  	makeApply.tryCatchResolve = tryCatchResolve;
  
  	return makeApply;
  
  	function makeApply(Promise, call) {
  		if(arguments.length < 2) {
  			call = tryCatchResolve;
  		}
  
  		return apply;
  
  		function apply(f, thisArg, args) {
  			var p = Promise._defer();
  			var l = args.length;
  			var params = new Array(l);
  			callAndResolve({ f:f, thisArg:thisArg, args:args, params:params, i:l-1, call:call }, p._handler);
  
  			return p;
  		}
  
  		function callAndResolve(c, h) {
  			if(c.i < 0) {
  				return call(c.f, c.thisArg, c.params, h);
  			}
  
  			var handler = Promise._handler(c.args[c.i]);
  			handler.fold(callAndResolveNext, c, void 0, h);
  		}
  
  		function callAndResolveNext(c, x, h) {
  			c.params[c.i] = x;
  			c.i -= 1;
  			callAndResolve(c, h);
  		}
  	}
  
  	function tryCatchResolve(f, thisArg, args, resolver) {
  		try {
  			resolver.resolve(f.apply(thisArg, args));
  		} catch(e) {
  			resolver.reject(e);
  		}
  	}
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  
  
  
  },{}],104:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function(require) {
  
  	var state = require('../state');
  	var applier = require('../apply');
  
  	return function array(Promise) {
  
  		var applyFold = applier(Promise);
  		var toPromise = Promise.resolve;
  		var all = Promise.all;
  
  		var ar = Array.prototype.reduce;
  		var arr = Array.prototype.reduceRight;
  		var slice = Array.prototype.slice;
  
  		// Additional array combinators
  
  		Promise.any = any;
  		Promise.some = some;
  		Promise.settle = settle;
  
  		Promise.map = map;
  		Promise.filter = filter;
  		Promise.reduce = reduce;
  		Promise.reduceRight = reduceRight;
  
  		/**
  		 * When this promise fulfills with an array, do
  		 * onFulfilled.apply(void 0, array)
  		 * @param {function} onFulfilled function to apply
  		 * @returns {Promise} promise for the result of applying onFulfilled
  		 */
  		Promise.prototype.spread = function(onFulfilled) {
  			return this.then(all).then(function(array) {
  				return onFulfilled.apply(this, array);
  			});
  		};
  
  		return Promise;
  
  		/**
  		 * One-winner competitive race.
  		 * Return a promise that will fulfill when one of the promises
  		 * in the input array fulfills, or will reject when all promises
  		 * have rejected.
  		 * @param {array} promises
  		 * @returns {Promise} promise for the first fulfilled value
  		 */
  		function any(promises) {
  			var p = Promise._defer();
  			var resolver = p._handler;
  			var l = promises.length>>>0;
  
  			var pending = l;
  			var errors = [];
  
  			for (var h, x, i = 0; i < l; ++i) {
  				x = promises[i];
  				if(x === void 0 && !(i in promises)) {
  					--pending;
  					continue;
  				}
  
  				h = Promise._handler(x);
  				if(h.state() > 0) {
  					resolver.become(h);
  					Promise._visitRemaining(promises, i, h);
  					break;
  				} else {
  					h.visit(resolver, handleFulfill, handleReject);
  				}
  			}
  
  			if(pending === 0) {
  				resolver.reject(new RangeError('any(): array must not be empty'));
  			}
  
  			return p;
  
  			function handleFulfill(x) {
  				/*jshint validthis:true*/
  				errors = null;
  				this.resolve(x); // this === resolver
  			}
  
  			function handleReject(e) {
  				/*jshint validthis:true*/
  				if(this.resolved) { // this === resolver
  					return;
  				}
  
  				errors.push(e);
  				if(--pending === 0) {
  					this.reject(errors);
  				}
  			}
  		}
  
  		/**
  		 * N-winner competitive race
  		 * Return a promise that will fulfill when n input promises have
  		 * fulfilled, or will reject when it becomes impossible for n
  		 * input promises to fulfill (ie when promises.length - n + 1
  		 * have rejected)
  		 * @param {array} promises
  		 * @param {number} n
  		 * @returns {Promise} promise for the earliest n fulfillment values
  		 *
  		 * @deprecated
  		 */
  		function some(promises, n) {
  			/*jshint maxcomplexity:7*/
  			var p = Promise._defer();
  			var resolver = p._handler;
  
  			var results = [];
  			var errors = [];
  
  			var l = promises.length>>>0;
  			var nFulfill = 0;
  			var nReject;
  			var x, i; // reused in both for() loops
  
  			// First pass: count actual array items
  			for(i=0; i<l; ++i) {
  				x = promises[i];
  				if(x === void 0 && !(i in promises)) {
  					continue;
  				}
  				++nFulfill;
  			}
  
  			// Compute actual goals
  			n = Math.max(n, 0);
  			nReject = (nFulfill - n + 1);
  			nFulfill = Math.min(n, nFulfill);
  
  			if(n > nFulfill) {
  				resolver.reject(new RangeError('some(): array must contain at least '
  				+ n + ' item(s), but had ' + nFulfill));
  			} else if(nFulfill === 0) {
  				resolver.resolve(results);
  			}
  
  			// Second pass: observe each array item, make progress toward goals
  			for(i=0; i<l; ++i) {
  				x = promises[i];
  				if(x === void 0 && !(i in promises)) {
  					continue;
  				}
  
  				Promise._handler(x).visit(resolver, fulfill, reject, resolver.notify);
  			}
  
  			return p;
  
  			function fulfill(x) {
  				/*jshint validthis:true*/
  				if(this.resolved) { // this === resolver
  					return;
  				}
  
  				results.push(x);
  				if(--nFulfill === 0) {
  					errors = null;
  					this.resolve(results);
  				}
  			}
  
  			function reject(e) {
  				/*jshint validthis:true*/
  				if(this.resolved) { // this === resolver
  					return;
  				}
  
  				errors.push(e);
  				if(--nReject === 0) {
  					results = null;
  					this.reject(errors);
  				}
  			}
  		}
  
  		/**
  		 * Apply f to the value of each promise in a list of promises
  		 * and return a new list containing the results.
  		 * @param {array} promises
  		 * @param {function(x:*, index:Number):*} f mapping function
  		 * @returns {Promise}
  		 */
  		function map(promises, f) {
  			return Promise._traverse(f, promises);
  		}
  
  		/**
  		 * Filter the provided array of promises using the provided predicate.  Input may
  		 * contain promises and values
  		 * @param {Array} promises array of promises and values
  		 * @param {function(x:*, index:Number):boolean} predicate filtering predicate.
  		 *  Must return truthy (or promise for truthy) for items to retain.
  		 * @returns {Promise} promise that will fulfill with an array containing all items
  		 *  for which predicate returned truthy.
  		 */
  		function filter(promises, predicate) {
  			var a = slice.call(promises);
  			return Promise._traverse(predicate, a).then(function(keep) {
  				return filterSync(a, keep);
  			});
  		}
  
  		function filterSync(promises, keep) {
  			// Safe because we know all promises have fulfilled if we've made it this far
  			var l = keep.length;
  			var filtered = new Array(l);
  			for(var i=0, j=0; i<l; ++i) {
  				if(keep[i]) {
  					filtered[j++] = Promise._handler(promises[i]).value;
  				}
  			}
  			filtered.length = j;
  			return filtered;
  
  		}
  
  		/**
  		 * Return a promise that will always fulfill with an array containing
  		 * the outcome states of all input promises.  The returned promise
  		 * will never reject.
  		 * @param {Array} promises
  		 * @returns {Promise} promise for array of settled state descriptors
  		 */
  		function settle(promises) {
  			return all(promises.map(settleOne));
  		}
  
  		function settleOne(p) {
  			// Optimize the case where we get an already-resolved when.js promise
  			//  by extracting its state:
  			var handler;
  			if (p instanceof Promise) {
  				// This is our own Promise type and we can reach its handler internals:
  				handler = p._handler.join();
  			}
  			if((handler && handler.state() === 0) || !handler) {
  				// Either still pending, or not a Promise at all:
  				return toPromise(p).then(state.fulfilled, state.rejected);
  			}
  
  			// The promise is our own, but it is already resolved. Take a shortcut.
  			// Since we're not actually handling the resolution, we need to disable
  			// rejection reporting.
  			handler._unreport();
  			return state.inspect(handler);
  		}
  
  		/**
  		 * Traditional reduce function, similar to `Array.prototype.reduce()`, but
  		 * input may contain promises and/or values, and reduceFunc
  		 * may return either a value or a promise, *and* initialValue may
  		 * be a promise for the starting value.
  		 * @param {Array|Promise} promises array or promise for an array of anything,
  		 *      may contain a mix of promises and values.
  		 * @param {function(accumulated:*, x:*, index:Number):*} f reduce function
  		 * @returns {Promise} that will resolve to the final reduced value
  		 */
  		function reduce(promises, f /*, initialValue */) {
  			return arguments.length > 2 ? ar.call(promises, liftCombine(f), arguments[2])
  					: ar.call(promises, liftCombine(f));
  		}
  
  		/**
  		 * Traditional reduce function, similar to `Array.prototype.reduceRight()`, but
  		 * input may contain promises and/or values, and reduceFunc
  		 * may return either a value or a promise, *and* initialValue may
  		 * be a promise for the starting value.
  		 * @param {Array|Promise} promises array or promise for an array of anything,
  		 *      may contain a mix of promises and values.
  		 * @param {function(accumulated:*, x:*, index:Number):*} f reduce function
  		 * @returns {Promise} that will resolve to the final reduced value
  		 */
  		function reduceRight(promises, f /*, initialValue */) {
  			return arguments.length > 2 ? arr.call(promises, liftCombine(f), arguments[2])
  					: arr.call(promises, liftCombine(f));
  		}
  
  		function liftCombine(f) {
  			return function(z, x, i) {
  				return applyFold(f, void 0, [z,x,i]);
  			};
  		}
  	};
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
  
  },{"../apply":103,"../state":117}],105:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function() {
  
  	return function flow(Promise) {
  
  		var resolve = Promise.resolve;
  		var reject = Promise.reject;
  		var origCatch = Promise.prototype['catch'];
  
  		/**
  		 * Handle the ultimate fulfillment value or rejection reason, and assume
  		 * responsibility for all errors.  If an error propagates out of result
  		 * or handleFatalError, it will be rethrown to the host, resulting in a
  		 * loud stack track on most platforms and a crash on some.
  		 * @param {function?} onResult
  		 * @param {function?} onError
  		 * @returns {undefined}
  		 */
  		Promise.prototype.done = function(onResult, onError) {
  			this._handler.visit(this._handler.receiver, onResult, onError);
  		};
  
  		/**
  		 * Add Error-type and predicate matching to catch.  Examples:
  		 * promise.catch(TypeError, handleTypeError)
  		 *   .catch(predicate, handleMatchedErrors)
  		 *   .catch(handleRemainingErrors)
  		 * @param onRejected
  		 * @returns {*}
  		 */
  		Promise.prototype['catch'] = Promise.prototype.otherwise = function(onRejected) {
  			if (arguments.length < 2) {
  				return origCatch.call(this, onRejected);
  			}
  
  			if(typeof onRejected !== 'function') {
  				return this.ensure(rejectInvalidPredicate);
  			}
  
  			return origCatch.call(this, createCatchFilter(arguments[1], onRejected));
  		};
  
  		/**
  		 * Wraps the provided catch handler, so that it will only be called
  		 * if the predicate evaluates truthy
  		 * @param {?function} handler
  		 * @param {function} predicate
  		 * @returns {function} conditional catch handler
  		 */
  		function createCatchFilter(handler, predicate) {
  			return function(e) {
  				return evaluatePredicate(e, predicate)
  					? handler.call(this, e)
  					: reject(e);
  			};
  		}
  
  		/**
  		 * Ensures that onFulfilledOrRejected will be called regardless of whether
  		 * this promise is fulfilled or rejected.  onFulfilledOrRejected WILL NOT
  		 * receive the promises' value or reason.  Any returned value will be disregarded.
  		 * onFulfilledOrRejected may throw or return a rejected promise to signal
  		 * an additional error.
  		 * @param {function} handler handler to be called regardless of
  		 *  fulfillment or rejection
  		 * @returns {Promise}
  		 */
  		Promise.prototype['finally'] = Promise.prototype.ensure = function(handler) {
  			if(typeof handler !== 'function') {
  				return this;
  			}
  
  			return this.then(function(x) {
  				return runSideEffect(handler, this, identity, x);
  			}, function(e) {
  				return runSideEffect(handler, this, reject, e);
  			});
  		};
  
  		function runSideEffect (handler, thisArg, propagate, value) {
  			var result = handler.call(thisArg);
  			return maybeThenable(result)
  				? propagateValue(result, propagate, value)
  				: propagate(value);
  		}
  
  		function propagateValue (result, propagate, x) {
  			return resolve(result).then(function () {
  				return propagate(x);
  			});
  		}
  
  		/**
  		 * Recover from a failure by returning a defaultValue.  If defaultValue
  		 * is a promise, it's fulfillment value will be used.  If defaultValue is
  		 * a promise that rejects, the returned promise will reject with the
  		 * same reason.
  		 * @param {*} defaultValue
  		 * @returns {Promise} new promise
  		 */
  		Promise.prototype['else'] = Promise.prototype.orElse = function(defaultValue) {
  			return this.then(void 0, function() {
  				return defaultValue;
  			});
  		};
  
  		/**
  		 * Shortcut for .then(function() { return value; })
  		 * @param  {*} value
  		 * @return {Promise} a promise that:
  		 *  - is fulfilled if value is not a promise, or
  		 *  - if value is a promise, will fulfill with its value, or reject
  		 *    with its reason.
  		 */
  		Promise.prototype['yield'] = function(value) {
  			return this.then(function() {
  				return value;
  			});
  		};
  
  		/**
  		 * Runs a side effect when this promise fulfills, without changing the
  		 * fulfillment value.
  		 * @param {function} onFulfilledSideEffect
  		 * @returns {Promise}
  		 */
  		Promise.prototype.tap = function(onFulfilledSideEffect) {
  			return this.then(onFulfilledSideEffect)['yield'](this);
  		};
  
  		return Promise;
  	};
  
  	function rejectInvalidPredicate() {
  		throw new TypeError('catch predicate must be a function');
  	}
  
  	function evaluatePredicate(e, predicate) {
  		return isError(predicate) ? e instanceof predicate : predicate(e);
  	}
  
  	function isError(predicate) {
  		return predicate === Error
  			|| (predicate != null && predicate.prototype instanceof Error);
  	}
  
  	function maybeThenable(x) {
  		return (typeof x === 'object' || typeof x === 'function') && x !== null;
  	}
  
  	function identity(x) {
  		return x;
  	}
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  
  },{}],106:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  /** @author Jeff Escalante */
  
  (function(define) { 'use strict';
  define(function() {
  
  	return function fold(Promise) {
  
  		Promise.prototype.fold = function(f, z) {
  			var promise = this._beget();
  
  			this._handler.fold(function(z, x, to) {
  				Promise._handler(z).fold(function(x, z, to) {
  					to.resolve(f.call(this, z, x));
  				}, x, this, to);
  			}, z, promise._handler.receiver, promise._handler);
  
  			return promise;
  		};
  
  		return Promise;
  	};
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  
  },{}],107:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function(require) {
  
  	var inspect = require('../state').inspect;
  
  	return function inspection(Promise) {
  
  		Promise.prototype.inspect = function() {
  			return inspect(Promise._handler(this));
  		};
  
  		return Promise;
  	};
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
  
  },{"../state":117}],108:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function() {
  
  	return function generate(Promise) {
  
  		var resolve = Promise.resolve;
  
  		Promise.iterate = iterate;
  		Promise.unfold = unfold;
  
  		return Promise;
  
  		/**
  		 * @deprecated Use github.com/cujojs/most streams and most.iterate
  		 * Generate a (potentially infinite) stream of promised values:
  		 * x, f(x), f(f(x)), etc. until condition(x) returns true
  		 * @param {function} f function to generate a new x from the previous x
  		 * @param {function} condition function that, given the current x, returns
  		 *  truthy when the iterate should stop
  		 * @param {function} handler function to handle the value produced by f
  		 * @param {*|Promise} x starting value, may be a promise
  		 * @return {Promise} the result of the last call to f before
  		 *  condition returns true
  		 */
  		function iterate(f, condition, handler, x) {
  			return unfold(function(x) {
  				return [x, f(x)];
  			}, condition, handler, x);
  		}
  
  		/**
  		 * @deprecated Use github.com/cujojs/most streams and most.unfold
  		 * Generate a (potentially infinite) stream of promised values
  		 * by applying handler(generator(seed)) iteratively until
  		 * condition(seed) returns true.
  		 * @param {function} unspool function that generates a [value, newSeed]
  		 *  given a seed.
  		 * @param {function} condition function that, given the current seed, returns
  		 *  truthy when the unfold should stop
  		 * @param {function} handler function to handle the value produced by unspool
  		 * @param x {*|Promise} starting value, may be a promise
  		 * @return {Promise} the result of the last value produced by unspool before
  		 *  condition returns true
  		 */
  		function unfold(unspool, condition, handler, x) {
  			return resolve(x).then(function(seed) {
  				return resolve(condition(seed)).then(function(done) {
  					return done ? seed : resolve(unspool(seed)).spread(next);
  				});
  			});
  
  			function next(item, newSeed) {
  				return resolve(handler(item)).then(function() {
  					return unfold(unspool, condition, handler, newSeed);
  				});
  			}
  		}
  	};
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  
  },{}],109:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function() {
  
  	return function progress(Promise) {
  
  		/**
  		 * @deprecated
  		 * Register a progress handler for this promise
  		 * @param {function} onProgress
  		 * @returns {Promise}
  		 */
  		Promise.prototype.progress = function(onProgress) {
  			return this.then(void 0, void 0, onProgress);
  		};
  
  		return Promise;
  	};
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  
  },{}],110:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function(require) {
  
  	var env = require('../env');
  	var TimeoutError = require('../TimeoutError');
  
  	function setTimeout(f, ms, x, y) {
  		return env.setTimer(function() {
  			f(x, y, ms);
  		}, ms);
  	}
  
  	return function timed(Promise) {
  		/**
  		 * Return a new promise whose fulfillment value is revealed only
  		 * after ms milliseconds
  		 * @param {number} ms milliseconds
  		 * @returns {Promise}
  		 */
  		Promise.prototype.delay = function(ms) {
  			var p = this._beget();
  			this._handler.fold(handleDelay, ms, void 0, p._handler);
  			return p;
  		};
  
  		function handleDelay(ms, x, h) {
  			setTimeout(resolveDelay, ms, x, h);
  		}
  
  		function resolveDelay(x, h) {
  			h.resolve(x);
  		}
  
  		/**
  		 * Return a new promise that rejects after ms milliseconds unless
  		 * this promise fulfills earlier, in which case the returned promise
  		 * fulfills with the same value.
  		 * @param {number} ms milliseconds
  		 * @param {Error|*=} reason optional rejection reason to use, defaults
  		 *   to a TimeoutError if not provided
  		 * @returns {Promise}
  		 */
  		Promise.prototype.timeout = function(ms, reason) {
  			var p = this._beget();
  			var h = p._handler;
  
  			var t = setTimeout(onTimeout, ms, reason, p._handler);
  
  			this._handler.visit(h,
  				function onFulfill(x) {
  					env.clearTimer(t);
  					this.resolve(x); // this = h
  				},
  				function onReject(x) {
  					env.clearTimer(t);
  					this.reject(x); // this = h
  				},
  				h.notify);
  
  			return p;
  		};
  
  		function onTimeout(reason, h, ms) {
  			var e = typeof reason === 'undefined'
  				? new TimeoutError('timed out after ' + ms + 'ms')
  				: reason;
  			h.reject(e);
  		}
  
  		return Promise;
  	};
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
  
  },{"../TimeoutError":102,"../env":113}],111:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function(require) {
  
  	var setTimer = require('../env').setTimer;
  	var format = require('../format');
  
  	return function unhandledRejection(Promise) {
  
  		var logError = noop;
  		var logInfo = noop;
  		var localConsole;
  
  		if(typeof console !== 'undefined') {
  			// Alias console to prevent things like uglify's drop_console option from
  			// removing console.log/error. Unhandled rejections fall into the same
  			// category as uncaught exceptions, and build tools shouldn't silence them.
  			localConsole = console;
  			logError = typeof localConsole.error !== 'undefined'
  				? function (e) { localConsole.error(e); }
  				: function (e) { localConsole.log(e); };
  
  			logInfo = typeof localConsole.info !== 'undefined'
  				? function (e) { localConsole.info(e); }
  				: function (e) { localConsole.log(e); };
  		}
  
  		Promise.onPotentiallyUnhandledRejection = function(rejection) {
  			enqueue(report, rejection);
  		};
  
  		Promise.onPotentiallyUnhandledRejectionHandled = function(rejection) {
  			enqueue(unreport, rejection);
  		};
  
  		Promise.onFatalRejection = function(rejection) {
  			enqueue(throwit, rejection.value);
  		};
  
  		var tasks = [];
  		var reported = [];
  		var running = null;
  
  		function report(r) {
  			if(!r.handled) {
  				reported.push(r);
  				logError('Potentially unhandled rejection [' + r.id + '] ' + format.formatError(r.value));
  			}
  		}
  
  		function unreport(r) {
  			var i = reported.indexOf(r);
  			if(i >= 0) {
  				reported.splice(i, 1);
  				logInfo('Handled previous rejection [' + r.id + '] ' + format.formatObject(r.value));
  			}
  		}
  
  		function enqueue(f, x) {
  			tasks.push(f, x);
  			if(running === null) {
  				running = setTimer(flush, 0);
  			}
  		}
  
  		function flush() {
  			running = null;
  			while(tasks.length > 0) {
  				tasks.shift()(tasks.shift());
  			}
  		}
  
  		return Promise;
  	};
  
  	function throwit(e) {
  		throw e;
  	}
  
  	function noop() {}
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
  
  },{"../env":113,"../format":114}],112:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function() {
  
  	return function addWith(Promise) {
  		/**
  		 * Returns a promise whose handlers will be called with `this` set to
  		 * the supplied receiver.  Subsequent promises derived from the
  		 * returned promise will also have their handlers called with receiver
  		 * as `this`. Calling `with` with undefined or no arguments will return
  		 * a promise whose handlers will again be called in the usual Promises/A+
  		 * way (no `this`) thus safely undoing any previous `with` in the
  		 * promise chain.
  		 *
  		 * WARNING: Promises returned from `with`/`withThis` are NOT Promises/A+
  		 * compliant, specifically violating 2.2.5 (http://promisesaplus.com/#point-41)
  		 *
  		 * @param {object} receiver `this` value for all handlers attached to
  		 *  the returned promise.
  		 * @returns {Promise}
  		 */
  		Promise.prototype['with'] = Promise.prototype.withThis = function(receiver) {
  			var p = this._beget();
  			var child = p._handler;
  			child.receiver = receiver;
  			this._handler.chain(child, receiver);
  			return p;
  		};
  
  		return Promise;
  	};
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  
  
  },{}],113:[function(require,module,exports){
  (function (process){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  /*global process,document,setTimeout,clearTimeout,MutationObserver,WebKitMutationObserver*/
  (function(define) { 'use strict';
  define(function(require) {
  	/*jshint maxcomplexity:6*/
  
  	// Sniff "best" async scheduling option
  	// Prefer process.nextTick or MutationObserver, then check for
  	// setTimeout, and finally vertx, since its the only env that doesn't
  	// have setTimeout
  
  	var MutationObs;
  	var capturedSetTimeout = typeof setTimeout !== 'undefined' && setTimeout;
  
  	// Default env
  	var setTimer = function(f, ms) { return setTimeout(f, ms); };
  	var clearTimer = function(t) { return clearTimeout(t); };
  	var asap = function (f) { return capturedSetTimeout(f, 0); };
  
  	// Detect specific env
  	if (isNode()) { // Node
  		asap = function (f) { return process.nextTick(f); };
  
  	} else if (MutationObs = hasMutationObserver()) { // Modern browser
  		asap = initMutationObserver(MutationObs);
  
  	} else if (!capturedSetTimeout) { // vert.x
  		var vertxRequire = require;
  		var vertx = vertxRequire('vertx');
  		setTimer = function (f, ms) { return vertx.setTimer(ms, f); };
  		clearTimer = vertx.cancelTimer;
  		asap = vertx.runOnLoop || vertx.runOnContext;
  	}
  
  	return {
  		setTimer: setTimer,
  		clearTimer: clearTimer,
  		asap: asap
  	};
  
  	function isNode () {
  		return typeof process !== 'undefined' &&
  			Object.prototype.toString.call(process) === '[object process]';
  	}
  
  	function hasMutationObserver () {
  	    return (typeof MutationObserver !== 'undefined' && MutationObserver) ||
  			(typeof WebKitMutationObserver !== 'undefined' && WebKitMutationObserver);
  	}
  
  	function initMutationObserver(MutationObserver) {
  		var scheduled;
  		var node = document.createTextNode('');
  		var o = new MutationObserver(run);
  		o.observe(node, { characterData: true });
  
  		function run() {
  			var f = scheduled;
  			scheduled = void 0;
  			f();
  		}
  
  		var i = 0;
  		return function (f) {
  			scheduled = f;
  			node.data = (i ^= 1);
  		};
  	}
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
  
  }).call(this,require('_process'))
  },{"_process":137}],114:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function() {
  
  	return {
  		formatError: formatError,
  		formatObject: formatObject,
  		tryStringify: tryStringify
  	};
  
  	/**
  	 * Format an error into a string.  If e is an Error and has a stack property,
  	 * it's returned.  Otherwise, e is formatted using formatObject, with a
  	 * warning added about e not being a proper Error.
  	 * @param {*} e
  	 * @returns {String} formatted string, suitable for output to developers
  	 */
  	function formatError(e) {
  		var s = typeof e === 'object' && e !== null && (e.stack || e.message) ? e.stack || e.message : formatObject(e);
  		return e instanceof Error ? s : s + ' (WARNING: non-Error used)';
  	}
  
  	/**
  	 * Format an object, detecting "plain" objects and running them through
  	 * JSON.stringify if possible.
  	 * @param {Object} o
  	 * @returns {string}
  	 */
  	function formatObject(o) {
  		var s = String(o);
  		if(s === '[object Object]' && typeof JSON !== 'undefined') {
  			s = tryStringify(o, s);
  		}
  		return s;
  	}
  
  	/**
  	 * Try to return the result of JSON.stringify(x).  If that fails, return
  	 * defaultValue
  	 * @param {*} x
  	 * @param {*} defaultValue
  	 * @returns {String|*} JSON.stringify(x) or defaultValue
  	 */
  	function tryStringify(x, defaultValue) {
  		try {
  			return JSON.stringify(x);
  		} catch(e) {
  			return defaultValue;
  		}
  	}
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  
  },{}],115:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function() {
  
  	return function liftAll(liftOne, combine, dst, src) {
  		if(typeof combine === 'undefined') {
  			combine = defaultCombine;
  		}
  
  		return Object.keys(src).reduce(function(dst, key) {
  			var f = src[key];
  			return typeof f === 'function' ? combine(dst, liftOne(f), key) : dst;
  		}, typeof dst === 'undefined' ? defaultDst(src) : dst);
  	};
  
  	function defaultCombine(o, f, k) {
  		o[k] = f;
  		return o;
  	}
  
  	function defaultDst(src) {
  		return typeof src === 'function' ? src.bind() : Object.create(src);
  	}
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  
  },{}],116:[function(require,module,exports){
  (function (process){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function() {
  
  	return function makePromise(environment) {
  
  		var tasks = environment.scheduler;
  		var emitRejection = initEmitRejection();
  
  		var objectCreate = Object.create ||
  			function(proto) {
  				function Child() {}
  				Child.prototype = proto;
  				return new Child();
  			};
  
  		/**
  		 * Create a promise whose fate is determined by resolver
  		 * @constructor
  		 * @returns {Promise} promise
  		 * @name Promise
  		 */
  		function Promise(resolver, handler) {
  			this._handler = resolver === Handler ? handler : init(resolver);
  		}
  
  		/**
  		 * Run the supplied resolver
  		 * @param resolver
  		 * @returns {Pending}
  		 */
  		function init(resolver) {
  			var handler = new Pending();
  
  			try {
  				resolver(promiseResolve, promiseReject, promiseNotify);
  			} catch (e) {
  				promiseReject(e);
  			}
  
  			return handler;
  
  			/**
  			 * Transition from pre-resolution state to post-resolution state, notifying
  			 * all listeners of the ultimate fulfillment or rejection
  			 * @param {*} x resolution value
  			 */
  			function promiseResolve (x) {
  				handler.resolve(x);
  			}
  			/**
  			 * Reject this promise with reason, which will be used verbatim
  			 * @param {Error|*} reason rejection reason, strongly suggested
  			 *   to be an Error type
  			 */
  			function promiseReject (reason) {
  				handler.reject(reason);
  			}
  
  			/**
  			 * @deprecated
  			 * Issue a progress event, notifying all progress listeners
  			 * @param {*} x progress event payload to pass to all listeners
  			 */
  			function promiseNotify (x) {
  				handler.notify(x);
  			}
  		}
  
  		// Creation
  
  		Promise.resolve = resolve;
  		Promise.reject = reject;
  		Promise.never = never;
  
  		Promise._defer = defer;
  		Promise._handler = getHandler;
  
  		/**
  		 * Returns a trusted promise. If x is already a trusted promise, it is
  		 * returned, otherwise returns a new trusted Promise which follows x.
  		 * @param  {*} x
  		 * @return {Promise} promise
  		 */
  		function resolve(x) {
  			return isPromise(x) ? x
  				: new Promise(Handler, new Async(getHandler(x)));
  		}
  
  		/**
  		 * Return a reject promise with x as its reason (x is used verbatim)
  		 * @param {*} x
  		 * @returns {Promise} rejected promise
  		 */
  		function reject(x) {
  			return new Promise(Handler, new Async(new Rejected(x)));
  		}
  
  		/**
  		 * Return a promise that remains pending forever
  		 * @returns {Promise} forever-pending promise.
  		 */
  		function never() {
  			return foreverPendingPromise; // Should be frozen
  		}
  
  		/**
  		 * Creates an internal {promise, resolver} pair
  		 * @private
  		 * @returns {Promise}
  		 */
  		function defer() {
  			return new Promise(Handler, new Pending());
  		}
  
  		// Transformation and flow control
  
  		/**
  		 * Transform this promise's fulfillment value, returning a new Promise
  		 * for the transformed result.  If the promise cannot be fulfilled, onRejected
  		 * is called with the reason.  onProgress *may* be called with updates toward
  		 * this promise's fulfillment.
  		 * @param {function=} onFulfilled fulfillment handler
  		 * @param {function=} onRejected rejection handler
  		 * @param {function=} onProgress @deprecated progress handler
  		 * @return {Promise} new promise
  		 */
  		Promise.prototype.then = function(onFulfilled, onRejected, onProgress) {
  			var parent = this._handler;
  			var state = parent.join().state();
  
  			if ((typeof onFulfilled !== 'function' && state > 0) ||
  				(typeof onRejected !== 'function' && state < 0)) {
  				// Short circuit: value will not change, simply share handler
  				return new this.constructor(Handler, parent);
  			}
  
  			var p = this._beget();
  			var child = p._handler;
  
  			parent.chain(child, parent.receiver, onFulfilled, onRejected, onProgress);
  
  			return p;
  		};
  
  		/**
  		 * If this promise cannot be fulfilled due to an error, call onRejected to
  		 * handle the error. Shortcut for .then(undefined, onRejected)
  		 * @param {function?} onRejected
  		 * @return {Promise}
  		 */
  		Promise.prototype['catch'] = function(onRejected) {
  			return this.then(void 0, onRejected);
  		};
  
  		/**
  		 * Creates a new, pending promise of the same type as this promise
  		 * @private
  		 * @returns {Promise}
  		 */
  		Promise.prototype._beget = function() {
  			return begetFrom(this._handler, this.constructor);
  		};
  
  		function begetFrom(parent, Promise) {
  			var child = new Pending(parent.receiver, parent.join().context);
  			return new Promise(Handler, child);
  		}
  
  		// Array combinators
  
  		Promise.all = all;
  		Promise.race = race;
  		Promise._traverse = traverse;
  
  		/**
  		 * Return a promise that will fulfill when all promises in the
  		 * input array have fulfilled, or will reject when one of the
  		 * promises rejects.
  		 * @param {array} promises array of promises
  		 * @returns {Promise} promise for array of fulfillment values
  		 */
  		function all(promises) {
  			return traverseWith(snd, null, promises);
  		}
  
  		/**
  		 * Array<Promise<X>> -> Promise<Array<f(X)>>
  		 * @private
  		 * @param {function} f function to apply to each promise's value
  		 * @param {Array} promises array of promises
  		 * @returns {Promise} promise for transformed values
  		 */
  		function traverse(f, promises) {
  			return traverseWith(tryCatch2, f, promises);
  		}
  
  		function traverseWith(tryMap, f, promises) {
  			var handler = typeof f === 'function' ? mapAt : settleAt;
  
  			var resolver = new Pending();
  			var pending = promises.length >>> 0;
  			var results = new Array(pending);
  
  			for (var i = 0, x; i < promises.length && !resolver.resolved; ++i) {
  				x = promises[i];
  
  				if (x === void 0 && !(i in promises)) {
  					--pending;
  					continue;
  				}
  
  				traverseAt(promises, handler, i, x, resolver);
  			}
  
  			if(pending === 0) {
  				resolver.become(new Fulfilled(results));
  			}
  
  			return new Promise(Handler, resolver);
  
  			function mapAt(i, x, resolver) {
  				if(!resolver.resolved) {
  					traverseAt(promises, settleAt, i, tryMap(f, x, i), resolver);
  				}
  			}
  
  			function settleAt(i, x, resolver) {
  				results[i] = x;
  				if(--pending === 0) {
  					resolver.become(new Fulfilled(results));
  				}
  			}
  		}
  
  		function traverseAt(promises, handler, i, x, resolver) {
  			if (maybeThenable(x)) {
  				var h = getHandlerMaybeThenable(x);
  				var s = h.state();
  
  				if (s === 0) {
  					h.fold(handler, i, void 0, resolver);
  				} else if (s > 0) {
  					handler(i, h.value, resolver);
  				} else {
  					resolver.become(h);
  					visitRemaining(promises, i+1, h);
  				}
  			} else {
  				handler(i, x, resolver);
  			}
  		}
  
  		Promise._visitRemaining = visitRemaining;
  		function visitRemaining(promises, start, handler) {
  			for(var i=start; i<promises.length; ++i) {
  				markAsHandled(getHandler(promises[i]), handler);
  			}
  		}
  
  		function markAsHandled(h, handler) {
  			if(h === handler) {
  				return;
  			}
  
  			var s = h.state();
  			if(s === 0) {
  				h.visit(h, void 0, h._unreport);
  			} else if(s < 0) {
  				h._unreport();
  			}
  		}
  
  		/**
  		 * Fulfill-reject competitive race. Return a promise that will settle
  		 * to the same state as the earliest input promise to settle.
  		 *
  		 * WARNING: The ES6 Promise spec requires that race()ing an empty array
  		 * must return a promise that is pending forever.  This implementation
  		 * returns a singleton forever-pending promise, the same singleton that is
  		 * returned by Promise.never(), thus can be checked with ===
  		 *
  		 * @param {array} promises array of promises to race
  		 * @returns {Promise} if input is non-empty, a promise that will settle
  		 * to the same outcome as the earliest input promise to settle. if empty
  		 * is empty, returns a promise that will never settle.
  		 */
  		function race(promises) {
  			if(typeof promises !== 'object' || promises === null) {
  				return reject(new TypeError('non-iterable passed to race()'));
  			}
  
  			// Sigh, race([]) is untestable unless we return *something*
  			// that is recognizable without calling .then() on it.
  			return promises.length === 0 ? never()
  				 : promises.length === 1 ? resolve(promises[0])
  				 : runRace(promises);
  		}
  
  		function runRace(promises) {
  			var resolver = new Pending();
  			var i, x, h;
  			for(i=0; i<promises.length; ++i) {
  				x = promises[i];
  				if (x === void 0 && !(i in promises)) {
  					continue;
  				}
  
  				h = getHandler(x);
  				if(h.state() !== 0) {
  					resolver.become(h);
  					visitRemaining(promises, i+1, h);
  					break;
  				} else {
  					h.visit(resolver, resolver.resolve, resolver.reject);
  				}
  			}
  			return new Promise(Handler, resolver);
  		}
  
  		// Promise internals
  		// Below this, everything is @private
  
  		/**
  		 * Get an appropriate handler for x, without checking for cycles
  		 * @param {*} x
  		 * @returns {object} handler
  		 */
  		function getHandler(x) {
  			if(isPromise(x)) {
  				return x._handler.join();
  			}
  			return maybeThenable(x) ? getHandlerUntrusted(x) : new Fulfilled(x);
  		}
  
  		/**
  		 * Get a handler for thenable x.
  		 * NOTE: You must only call this if maybeThenable(x) == true
  		 * @param {object|function|Promise} x
  		 * @returns {object} handler
  		 */
  		function getHandlerMaybeThenable(x) {
  			return isPromise(x) ? x._handler.join() : getHandlerUntrusted(x);
  		}
  
  		/**
  		 * Get a handler for potentially untrusted thenable x
  		 * @param {*} x
  		 * @returns {object} handler
  		 */
  		function getHandlerUntrusted(x) {
  			try {
  				var untrustedThen = x.then;
  				return typeof untrustedThen === 'function'
  					? new Thenable(untrustedThen, x)
  					: new Fulfilled(x);
  			} catch(e) {
  				return new Rejected(e);
  			}
  		}
  
  		/**
  		 * Handler for a promise that is pending forever
  		 * @constructor
  		 */
  		function Handler() {}
  
  		Handler.prototype.when
  			= Handler.prototype.become
  			= Handler.prototype.notify // deprecated
  			= Handler.prototype.fail
  			= Handler.prototype._unreport
  			= Handler.prototype._report
  			= noop;
  
  		Handler.prototype._state = 0;
  
  		Handler.prototype.state = function() {
  			return this._state;
  		};
  
  		/**
  		 * Recursively collapse handler chain to find the handler
  		 * nearest to the fully resolved value.
  		 * @returns {object} handler nearest the fully resolved value
  		 */
  		Handler.prototype.join = function() {
  			var h = this;
  			while(h.handler !== void 0) {
  				h = h.handler;
  			}
  			return h;
  		};
  
  		Handler.prototype.chain = function(to, receiver, fulfilled, rejected, progress) {
  			this.when({
  				resolver: to,
  				receiver: receiver,
  				fulfilled: fulfilled,
  				rejected: rejected,
  				progress: progress
  			});
  		};
  
  		Handler.prototype.visit = function(receiver, fulfilled, rejected, progress) {
  			this.chain(failIfRejected, receiver, fulfilled, rejected, progress);
  		};
  
  		Handler.prototype.fold = function(f, z, c, to) {
  			this.when(new Fold(f, z, c, to));
  		};
  
  		/**
  		 * Handler that invokes fail() on any handler it becomes
  		 * @constructor
  		 */
  		function FailIfRejected() {}
  
  		inherit(Handler, FailIfRejected);
  
  		FailIfRejected.prototype.become = function(h) {
  			h.fail();
  		};
  
  		var failIfRejected = new FailIfRejected();
  
  		/**
  		 * Handler that manages a queue of consumers waiting on a pending promise
  		 * @constructor
  		 */
  		function Pending(receiver, inheritedContext) {
  			Promise.createContext(this, inheritedContext);
  
  			this.consumers = void 0;
  			this.receiver = receiver;
  			this.handler = void 0;
  			this.resolved = false;
  		}
  
  		inherit(Handler, Pending);
  
  		Pending.prototype._state = 0;
  
  		Pending.prototype.resolve = function(x) {
  			this.become(getHandler(x));
  		};
  
  		Pending.prototype.reject = function(x) {
  			if(this.resolved) {
  				return;
  			}
  
  			this.become(new Rejected(x));
  		};
  
  		Pending.prototype.join = function() {
  			if (!this.resolved) {
  				return this;
  			}
  
  			var h = this;
  
  			while (h.handler !== void 0) {
  				h = h.handler;
  				if (h === this) {
  					return this.handler = cycle();
  				}
  			}
  
  			return h;
  		};
  
  		Pending.prototype.run = function() {
  			var q = this.consumers;
  			var handler = this.handler;
  			this.handler = this.handler.join();
  			this.consumers = void 0;
  
  			for (var i = 0; i < q.length; ++i) {
  				handler.when(q[i]);
  			}
  		};
  
  		Pending.prototype.become = function(handler) {
  			if(this.resolved) {
  				return;
  			}
  
  			this.resolved = true;
  			this.handler = handler;
  			if(this.consumers !== void 0) {
  				tasks.enqueue(this);
  			}
  
  			if(this.context !== void 0) {
  				handler._report(this.context);
  			}
  		};
  
  		Pending.prototype.when = function(continuation) {
  			if(this.resolved) {
  				tasks.enqueue(new ContinuationTask(continuation, this.handler));
  			} else {
  				if(this.consumers === void 0) {
  					this.consumers = [continuation];
  				} else {
  					this.consumers.push(continuation);
  				}
  			}
  		};
  
  		/**
  		 * @deprecated
  		 */
  		Pending.prototype.notify = function(x) {
  			if(!this.resolved) {
  				tasks.enqueue(new ProgressTask(x, this));
  			}
  		};
  
  		Pending.prototype.fail = function(context) {
  			var c = typeof context === 'undefined' ? this.context : context;
  			this.resolved && this.handler.join().fail(c);
  		};
  
  		Pending.prototype._report = function(context) {
  			this.resolved && this.handler.join()._report(context);
  		};
  
  		Pending.prototype._unreport = function() {
  			this.resolved && this.handler.join()._unreport();
  		};
  
  		/**
  		 * Wrap another handler and force it into a future stack
  		 * @param {object} handler
  		 * @constructor
  		 */
  		function Async(handler) {
  			this.handler = handler;
  		}
  
  		inherit(Handler, Async);
  
  		Async.prototype.when = function(continuation) {
  			tasks.enqueue(new ContinuationTask(continuation, this));
  		};
  
  		Async.prototype._report = function(context) {
  			this.join()._report(context);
  		};
  
  		Async.prototype._unreport = function() {
  			this.join()._unreport();
  		};
  
  		/**
  		 * Handler that wraps an untrusted thenable and assimilates it in a future stack
  		 * @param {function} then
  		 * @param {{then: function}} thenable
  		 * @constructor
  		 */
  		function Thenable(then, thenable) {
  			Pending.call(this);
  			tasks.enqueue(new AssimilateTask(then, thenable, this));
  		}
  
  		inherit(Pending, Thenable);
  
  		/**
  		 * Handler for a fulfilled promise
  		 * @param {*} x fulfillment value
  		 * @constructor
  		 */
  		function Fulfilled(x) {
  			Promise.createContext(this);
  			this.value = x;
  		}
  
  		inherit(Handler, Fulfilled);
  
  		Fulfilled.prototype._state = 1;
  
  		Fulfilled.prototype.fold = function(f, z, c, to) {
  			runContinuation3(f, z, this, c, to);
  		};
  
  		Fulfilled.prototype.when = function(cont) {
  			runContinuation1(cont.fulfilled, this, cont.receiver, cont.resolver);
  		};
  
  		var errorId = 0;
  
  		/**
  		 * Handler for a rejected promise
  		 * @param {*} x rejection reason
  		 * @constructor
  		 */
  		function Rejected(x) {
  			Promise.createContext(this);
  
  			this.id = ++errorId;
  			this.value = x;
  			this.handled = false;
  			this.reported = false;
  
  			this._report();
  		}
  
  		inherit(Handler, Rejected);
  
  		Rejected.prototype._state = -1;
  
  		Rejected.prototype.fold = function(f, z, c, to) {
  			to.become(this);
  		};
  
  		Rejected.prototype.when = function(cont) {
  			if(typeof cont.rejected === 'function') {
  				this._unreport();
  			}
  			runContinuation1(cont.rejected, this, cont.receiver, cont.resolver);
  		};
  
  		Rejected.prototype._report = function(context) {
  			tasks.afterQueue(new ReportTask(this, context));
  		};
  
  		Rejected.prototype._unreport = function() {
  			if(this.handled) {
  				return;
  			}
  			this.handled = true;
  			tasks.afterQueue(new UnreportTask(this));
  		};
  
  		Rejected.prototype.fail = function(context) {
  			this.reported = true;
  			emitRejection('unhandledRejection', this);
  			Promise.onFatalRejection(this, context === void 0 ? this.context : context);
  		};
  
  		function ReportTask(rejection, context) {
  			this.rejection = rejection;
  			this.context = context;
  		}
  
  		ReportTask.prototype.run = function() {
  			if(!this.rejection.handled && !this.rejection.reported) {
  				this.rejection.reported = true;
  				emitRejection('unhandledRejection', this.rejection) ||
  					Promise.onPotentiallyUnhandledRejection(this.rejection, this.context);
  			}
  		};
  
  		function UnreportTask(rejection) {
  			this.rejection = rejection;
  		}
  
  		UnreportTask.prototype.run = function() {
  			if(this.rejection.reported) {
  				emitRejection('rejectionHandled', this.rejection) ||
  					Promise.onPotentiallyUnhandledRejectionHandled(this.rejection);
  			}
  		};
  
  		// Unhandled rejection hooks
  		// By default, everything is a noop
  
  		Promise.createContext
  			= Promise.enterContext
  			= Promise.exitContext
  			= Promise.onPotentiallyUnhandledRejection
  			= Promise.onPotentiallyUnhandledRejectionHandled
  			= Promise.onFatalRejection
  			= noop;
  
  		// Errors and singletons
  
  		var foreverPendingHandler = new Handler();
  		var foreverPendingPromise = new Promise(Handler, foreverPendingHandler);
  
  		function cycle() {
  			return new Rejected(new TypeError('Promise cycle'));
  		}
  
  		// Task runners
  
  		/**
  		 * Run a single consumer
  		 * @constructor
  		 */
  		function ContinuationTask(continuation, handler) {
  			this.continuation = continuation;
  			this.handler = handler;
  		}
  
  		ContinuationTask.prototype.run = function() {
  			this.handler.join().when(this.continuation);
  		};
  
  		/**
  		 * Run a queue of progress handlers
  		 * @constructor
  		 */
  		function ProgressTask(value, handler) {
  			this.handler = handler;
  			this.value = value;
  		}
  
  		ProgressTask.prototype.run = function() {
  			var q = this.handler.consumers;
  			if(q === void 0) {
  				return;
  			}
  
  			for (var c, i = 0; i < q.length; ++i) {
  				c = q[i];
  				runNotify(c.progress, this.value, this.handler, c.receiver, c.resolver);
  			}
  		};
  
  		/**
  		 * Assimilate a thenable, sending it's value to resolver
  		 * @param {function} then
  		 * @param {object|function} thenable
  		 * @param {object} resolver
  		 * @constructor
  		 */
  		function AssimilateTask(then, thenable, resolver) {
  			this._then = then;
  			this.thenable = thenable;
  			this.resolver = resolver;
  		}
  
  		AssimilateTask.prototype.run = function() {
  			var h = this.resolver;
  			tryAssimilate(this._then, this.thenable, _resolve, _reject, _notify);
  
  			function _resolve(x) { h.resolve(x); }
  			function _reject(x)  { h.reject(x); }
  			function _notify(x)  { h.notify(x); }
  		};
  
  		function tryAssimilate(then, thenable, resolve, reject, notify) {
  			try {
  				then.call(thenable, resolve, reject, notify);
  			} catch (e) {
  				reject(e);
  			}
  		}
  
  		/**
  		 * Fold a handler value with z
  		 * @constructor
  		 */
  		function Fold(f, z, c, to) {
  			this.f = f; this.z = z; this.c = c; this.to = to;
  			this.resolver = failIfRejected;
  			this.receiver = this;
  		}
  
  		Fold.prototype.fulfilled = function(x) {
  			this.f.call(this.c, this.z, x, this.to);
  		};
  
  		Fold.prototype.rejected = function(x) {
  			this.to.reject(x);
  		};
  
  		Fold.prototype.progress = function(x) {
  			this.to.notify(x);
  		};
  
  		// Other helpers
  
  		/**
  		 * @param {*} x
  		 * @returns {boolean} true iff x is a trusted Promise
  		 */
  		function isPromise(x) {
  			return x instanceof Promise;
  		}
  
  		/**
  		 * Test just enough to rule out primitives, in order to take faster
  		 * paths in some code
  		 * @param {*} x
  		 * @returns {boolean} false iff x is guaranteed *not* to be a thenable
  		 */
  		function maybeThenable(x) {
  			return (typeof x === 'object' || typeof x === 'function') && x !== null;
  		}
  
  		function runContinuation1(f, h, receiver, next) {
  			if(typeof f !== 'function') {
  				return next.become(h);
  			}
  
  			Promise.enterContext(h);
  			tryCatchReject(f, h.value, receiver, next);
  			Promise.exitContext();
  		}
  
  		function runContinuation3(f, x, h, receiver, next) {
  			if(typeof f !== 'function') {
  				return next.become(h);
  			}
  
  			Promise.enterContext(h);
  			tryCatchReject3(f, x, h.value, receiver, next);
  			Promise.exitContext();
  		}
  
  		/**
  		 * @deprecated
  		 */
  		function runNotify(f, x, h, receiver, next) {
  			if(typeof f !== 'function') {
  				return next.notify(x);
  			}
  
  			Promise.enterContext(h);
  			tryCatchReturn(f, x, receiver, next);
  			Promise.exitContext();
  		}
  
  		function tryCatch2(f, a, b) {
  			try {
  				return f(a, b);
  			} catch(e) {
  				return reject(e);
  			}
  		}
  
  		/**
  		 * Return f.call(thisArg, x), or if it throws return a rejected promise for
  		 * the thrown exception
  		 */
  		function tryCatchReject(f, x, thisArg, next) {
  			try {
  				next.become(getHandler(f.call(thisArg, x)));
  			} catch(e) {
  				next.become(new Rejected(e));
  			}
  		}
  
  		/**
  		 * Same as above, but includes the extra argument parameter.
  		 */
  		function tryCatchReject3(f, x, y, thisArg, next) {
  			try {
  				f.call(thisArg, x, y, next);
  			} catch(e) {
  				next.become(new Rejected(e));
  			}
  		}
  
  		/**
  		 * @deprecated
  		 * Return f.call(thisArg, x), or if it throws, *return* the exception
  		 */
  		function tryCatchReturn(f, x, thisArg, next) {
  			try {
  				next.notify(f.call(thisArg, x));
  			} catch(e) {
  				next.notify(e);
  			}
  		}
  
  		function inherit(Parent, Child) {
  			Child.prototype = objectCreate(Parent.prototype);
  			Child.prototype.constructor = Child;
  		}
  
  		function snd(x, y) {
  			return y;
  		}
  
  		function noop() {}
  
  		function hasCustomEvent() {
  			if(typeof CustomEvent === 'function') {
  				try {
  					var ev = new CustomEvent('unhandledRejection');
  					return ev instanceof CustomEvent;
  				} catch (ignoredException) {}
  			}
  			return false;
  		}
  
  		function hasInternetExplorerCustomEvent() {
  			if(typeof document !== 'undefined' && typeof document.createEvent === 'function') {
  				try {
  					// Try to create one event to make sure it's supported
  					var ev = document.createEvent('CustomEvent');
  					ev.initCustomEvent('eventType', false, true, {});
  					return true;
  				} catch (ignoredException) {}
  			}
  			return false;
  		}
  
  		function initEmitRejection() {
  			/*global process, self, CustomEvent*/
  			if(typeof process !== 'undefined' && process !== null
  				&& typeof process.emit === 'function') {
  				// Returning falsy here means to call the default
  				// onPotentiallyUnhandledRejection API.  This is safe even in
  				// browserify since process.emit always returns falsy in browserify:
  				// https://github.com/defunctzombie/node-process/blob/master/browser.js#L40-L46
  				return function(type, rejection) {
  					return type === 'unhandledRejection'
  						? process.emit(type, rejection.value, rejection)
  						: process.emit(type, rejection);
  				};
  			} else if(typeof self !== 'undefined' && hasCustomEvent()) {
  				return (function (self, CustomEvent) {
  					return function (type, rejection) {
  						var ev = new CustomEvent(type, {
  							detail: {
  								reason: rejection.value,
  								key: rejection
  							},
  							bubbles: false,
  							cancelable: true
  						});
  
  						return !self.dispatchEvent(ev);
  					};
  				}(self, CustomEvent));
  			} else if(typeof self !== 'undefined' && hasInternetExplorerCustomEvent()) {
  				return (function(self, document) {
  					return function(type, rejection) {
  						var ev = document.createEvent('CustomEvent');
  						ev.initCustomEvent(type, false, true, {
  							reason: rejection.value,
  							key: rejection
  						});
  
  						return !self.dispatchEvent(ev);
  					};
  				}(self, document));
  			}
  
  			return noop;
  		}
  
  		return Promise;
  	};
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  
  }).call(this,require('_process'))
  },{"_process":137}],117:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function() {
  
  	return {
  		pending: toPendingState,
  		fulfilled: toFulfilledState,
  		rejected: toRejectedState,
  		inspect: inspect
  	};
  
  	function toPendingState() {
  		return { state: 'pending' };
  	}
  
  	function toRejectedState(e) {
  		return { state: 'rejected', reason: e };
  	}
  
  	function toFulfilledState(x) {
  		return { state: 'fulfilled', value: x };
  	}
  
  	function inspect(handler) {
  		var state = handler.state();
  		return state === 0 ? toPendingState()
  			 : state > 0   ? toFulfilledState(handler.value)
  			               : toRejectedState(handler.value);
  	}
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  
  },{}],118:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function(require) {
  
  	var PromiseMonitor = require('./monitor/PromiseMonitor');
  	var ConsoleReporter = require('./monitor/ConsoleReporter');
  
  	var promiseMonitor = new PromiseMonitor(new ConsoleReporter());
  
  	return function(Promise) {
  		return promiseMonitor.monitor(Promise);
  	};
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
  
  },{"./monitor/ConsoleReporter":119,"./monitor/PromiseMonitor":120}],119:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function(require) {
  
  	var error = require('./error');
  	var unhandledRejectionsMsg = '[promises] Unhandled rejections: ';
  	var allHandledMsg = '[promises] All previously unhandled rejections have now been handled';
  
  	function ConsoleReporter() {
  		this._previouslyReported = false;
  	}
  
  	ConsoleReporter.prototype = initDefaultLogging();
  
  	ConsoleReporter.prototype.log = function(traces) {
  		if(traces.length === 0) {
  			if(this._previouslyReported) {
  				this._previouslyReported = false;
  				this.msg(allHandledMsg);
  			}
  			return;
  		}
  
  		this._previouslyReported = true;
  		this.groupStart(unhandledRejectionsMsg + traces.length);
  		try {
  			this._log(traces);
  		} finally {
  			this.groupEnd();
  		}
  	};
  
  	ConsoleReporter.prototype._log = function(traces) {
  		for(var i=0; i<traces.length; ++i) {
  			this.warn(error.format(traces[i]));
  		}
  	};
  
  	function initDefaultLogging() {
  		/*jshint maxcomplexity:7*/
  		var log, warn, groupStart, groupEnd;
  
  		if(typeof console === 'undefined') {
  			log = warn = consoleNotAvailable;
  		} else {
  			// Alias console to prevent things like uglify's drop_console option from
  			// removing console.log/error. Unhandled rejections fall into the same
  			// category as uncaught exceptions, and build tools shouldn't silence them.
  			var localConsole = console;
  			if(typeof localConsole.error === 'function'
  				&& typeof localConsole.dir === 'function') {
  				warn = function(s) {
  					localConsole.error(s);
  				};
  
  				log = function(s) {
  					localConsole.log(s);
  				};
  
  				if(typeof localConsole.groupCollapsed === 'function') {
  					groupStart = function(s) {
  						localConsole.groupCollapsed(s);
  					};
  					groupEnd = function() {
  						localConsole.groupEnd();
  					};
  				}
  			} else {
  				// IE8 has console.log and JSON, so we can make a
  				// reasonably useful warn() from those.
  				// Credit to webpro (https://github.com/webpro) for this idea
  				// typeof localConsole.log will return 'object' in IE8, so can't test it with === 'function'
  				// Since this is more of a corner case for IE8, I'm ok to check it with !== 'undefined' to reduce complexity
  				if (typeof localConsole.log !== 'undefined' && typeof JSON !== 'undefined') {
  					log = warn = function(x) {
  						if (typeof x !== 'string') {
  							try {
  								x = JSON.stringify(x);
  							} catch (e) {
  							}
  						}
  						localConsole.log(x);
  					};
  				} else {
  					log = warn = consoleNotAvailable;
  				}
  			}
  		}
  
  		return {
  			msg: log,
  			warn: warn,
  			groupStart: groupStart || warn,
  			groupEnd: groupEnd || consoleNotAvailable
  		};
  	}
  
  	function consoleNotAvailable() {}
  
  	return ConsoleReporter;
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
  
  },{"./error":122}],120:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function(require) {
  
  	var defaultStackJumpSeparator = 'from execution context:';
  	var defaultStackFilter = /[\s\(\/\\](node|module|timers)\.js:|when([\/\\]{1,2}(lib|monitor|es6-shim)[\/\\]{1,2}|\.js)|(new\sPromise)\b|(\b(PromiseMonitor|ConsoleReporter|Scheduler|RunHandlerTask|ProgressTask|Promise|.*Handler)\.[\w_]\w\w+\b)|\b(tryCatch\w+|getHandler\w*)\b/i;
  
  	var setTimer = require('../lib/env').setTimer;
  	var error = require('./error');
  
  	var executionContext = [];
  
  	function PromiseMonitor(reporter) {
  		this.logDelay = 0;
  		this.stackFilter = defaultStackFilter;
  		this.stackJumpSeparator = defaultStackJumpSeparator;
  		this.filterDuplicateFrames = true;
  
  		this._reporter = reporter;
  		if(typeof reporter.configurePromiseMonitor === 'function') {
  			reporter.configurePromiseMonitor(this);
  		}
  
  		this._traces = [];
  		this._traceTask = 0;
  
  		var self = this;
  		this._doLogTraces = function() {
  			self._logTraces();
  		};
  	}
  
  	PromiseMonitor.prototype.monitor = function(Promise) {
  		var self = this;
  		Promise.createContext = function(p, context) {
  			p.context = self.createContext(p, context);
  		};
  
  		Promise.enterContext = function(p) {
  			executionContext.push(p.context);
  		};
  
  		Promise.exitContext = function() {
  			executionContext.pop();
  		};
  
  		Promise.onPotentiallyUnhandledRejection = function(rejection, extraContext) {
  			return self.addTrace(rejection, extraContext);
  		};
  
  		Promise.onPotentiallyUnhandledRejectionHandled = function(rejection) {
  			return self.removeTrace(rejection);
  		};
  
  		Promise.onFatalRejection = function(rejection, extraContext) {
  			return self.fatal(rejection, extraContext);
  		};
  
  		return this;
  	};
  
  	PromiseMonitor.prototype.createContext = function(at, parentContext) {
  		var context = {
  			parent: parentContext || executionContext[executionContext.length - 1],
  			stack: void 0
  		};
  		error.captureStack(context, at.constructor);
  		return context;
  	};
  
  	PromiseMonitor.prototype.addTrace = function(handler, extraContext) {
  		var t, i;
  
  		for(i = this._traces.length-1; i >= 0; --i) {
  			t = this._traces[i];
  			if(t.handler === handler) {
  				break;
  			}
  		}
  
  		if(i >= 0) {
  			t.extraContext = extraContext;
  		} else {
  			this._traces.push({
  				handler: handler,
  				extraContext: extraContext
  			});
  		}
  
  		this.logTraces();
  	};
  
  	PromiseMonitor.prototype.removeTrace = function(/*handler*/) {
  		this.logTraces();
  	};
  
  	PromiseMonitor.prototype.fatal = function(handler, extraContext) {
  		var err = new Error();
  		err.stack = this._createLongTrace(handler.value, handler.context, extraContext).join('\n');
  		setTimer(function() {
  			throw err;
  		}, 0);
  	};
  
  	PromiseMonitor.prototype.logTraces = function() {
  		if(!this._traceTask) {
  			this._traceTask = setTimer(this._doLogTraces, this.logDelay);
  		}
  	};
  
  	PromiseMonitor.prototype._logTraces = function() {
  		this._traceTask = void 0;
  		this._traces = this._traces.filter(filterHandled);
  		this._reporter.log(this.formatTraces(this._traces));
  	};
  
  
  	PromiseMonitor.prototype.formatTraces = function(traces) {
  		return traces.map(function(t) {
  			return this._createLongTrace(t.handler.value, t.handler.context, t.extraContext);
  		}, this);
  	};
  
  	PromiseMonitor.prototype._createLongTrace = function(e, context, extraContext) {
  		var trace = error.parse(e) || [String(e) + ' (WARNING: non-Error used)'];
  		trace = filterFrames(this.stackFilter, trace, 0);
  		this._appendContext(trace, context);
  		this._appendContext(trace, extraContext);
  		return this.filterDuplicateFrames ? this._removeDuplicates(trace) : trace;
  	};
  
  	PromiseMonitor.prototype._removeDuplicates = function(trace) {
  		var seen = {};
  		var sep = this.stackJumpSeparator;
  		var count = 0;
  		return trace.reduceRight(function(deduped, line, i) {
  			if(i === 0) {
  				deduped.unshift(line);
  			} else if(line === sep) {
  				if(count > 0) {
  					deduped.unshift(line);
  					count = 0;
  				}
  			} else if(!seen[line]) {
  				seen[line] = true;
  				deduped.unshift(line);
  				++count;
  			}
  			return deduped;
  		}, []);
  	};
  
  	PromiseMonitor.prototype._appendContext = function(trace, context) {
  		trace.push.apply(trace, this._createTrace(context));
  	};
  
  	PromiseMonitor.prototype._createTrace = function(traceChain) {
  		var trace = [];
  		var stack;
  
  		while(traceChain) {
  			stack = error.parse(traceChain);
  
  			if (stack) {
  				stack = filterFrames(this.stackFilter, stack);
  				appendStack(trace, stack, this.stackJumpSeparator);
  			}
  
  			traceChain = traceChain.parent;
  		}
  
  		return trace;
  	};
  
  	function appendStack(trace, stack, separator) {
  		if (stack.length > 1) {
  			stack[0] = separator;
  			trace.push.apply(trace, stack);
  		}
  	}
  
  	function filterFrames(stackFilter, stack) {
  		return stack.filter(function(frame) {
  			return !stackFilter.test(frame);
  		});
  	}
  
  	function filterHandled(t) {
  		return !t.handler.handled;
  	}
  
  	return PromiseMonitor;
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
  
  },{"../lib/env":113,"./error":122}],121:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function(require) {
  
  	var monitor = require('../monitor');
  	var Promise = require('../when').Promise;
  
  	return monitor(Promise);
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
  
  },{"../monitor":118,"../when":123}],122:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  /** @author Brian Cavalier */
  /** @author John Hann */
  
  (function(define) { 'use strict';
  define(function() {
  
  	var parse, captureStack, format;
  
  	if(Error.captureStackTrace) {
  		// Use Error.captureStackTrace if available
  		parse = function(e) {
  			return e && e.stack && e.stack.split('\n');
  		};
  
  		format = formatAsString;
  		captureStack = Error.captureStackTrace;
  
  	} else {
  		// Otherwise, do minimal feature detection to determine
  		// how to capture and format reasonable stacks.
  		parse = function(e) {
  			var stack = e && e.stack && e.stack.split('\n');
  			if(stack && e.message) {
  				stack.unshift(e.message);
  			}
  			return stack;
  		};
  
  		(function() {
  			var e = new Error();
  			if(typeof e.stack !== 'string') {
  				format = formatAsString;
  				captureStack = captureSpiderMonkeyStack;
  			} else {
  				format = formatAsErrorWithStack;
  				captureStack = useStackDirectly;
  			}
  		}());
  	}
  
  	function captureSpiderMonkeyStack(host) {
  		try {
  			throw new Error();
  		} catch(err) {
  			host.stack = err.stack;
  		}
  	}
  
  	function useStackDirectly(host) {
  		host.stack = new Error().stack;
  	}
  
  	function formatAsString(longTrace) {
  		return join(longTrace);
  	}
  
  	function formatAsErrorWithStack(longTrace) {
  		var e = new Error();
  		e.stack = formatAsString(longTrace);
  		return e;
  	}
  
  	// About 5-10x faster than String.prototype.join o_O
  	function join(a) {
  		var sep = false;
  		var s = '';
  		for(var i=0; i< a.length; ++i) {
  			if(sep) {
  				s += '\n' + a[i];
  			} else {
  				s+= a[i];
  				sep = true;
  			}
  		}
  		return s;
  	}
  
  	return {
  		parse: parse,
  		format: format,
  		captureStack: captureStack
  	};
  
  });
  }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
  
  },{}],123:[function(require,module,exports){
  /** @license MIT License (c) copyright 2010-2014 original author or authors */
  
  /**
   * Promises/A+ and when() implementation
   * when is part of the cujoJS family of libraries (http://cujojs.com/)
   * @author Brian Cavalier
   * @author John Hann
   */
  (function(define) { 'use strict';
  define(function (require) {
  
  	var timed = require('./lib/decorators/timed');
  	var array = require('./lib/decorators/array');
  	var flow = require('./lib/decorators/flow');
  	var fold = require('./lib/decorators/fold');
  	var inspect = require('./lib/decorators/inspect');
  	var generate = require('./lib/decorators/iterate');
  	var progress = require('./lib/decorators/progress');
  	var withThis = require('./lib/decorators/with');
  	var unhandledRejection = require('./lib/decorators/unhandledRejection');
  	var TimeoutError = require('./lib/TimeoutError');
  
  	var Promise = [array, flow, fold, generate, progress,
  		inspect, withThis, timed, unhandledRejection]
  		.reduce(function(Promise, feature) {
  			return feature(Promise);
  		}, require('./lib/Promise'));
  
  	var apply = require('./lib/apply')(Promise);
  
  	// Public API
  
  	when.promise     = promise;              // Create a pending promise
  	when.resolve     = Promise.resolve;      // Create a resolved promise
  	when.reject      = Promise.reject;       // Create a rejected promise
  
  	when.lift        = lift;                 // lift a function to return promises
  	when['try']      = attempt;              // call a function and return a promise
  	when.attempt     = attempt;              // alias for when.try
  
  	when.iterate     = Promise.iterate;      // DEPRECATED (use cujojs/most streams) Generate a stream of promises
  	when.unfold      = Promise.unfold;       // DEPRECATED (use cujojs/most streams) Generate a stream of promises
  
  	when.join        = join;                 // Join 2 or more promises
  
  	when.all         = all;                  // Resolve a list of promises
  	when.settle      = settle;               // Settle a list of promises
  
  	when.any         = lift(Promise.any);    // One-winner race
  	when.some        = lift(Promise.some);   // Multi-winner race
  	when.race        = lift(Promise.race);   // First-to-settle race
  
  	when.map         = map;                  // Array.map() for promises
  	when.filter      = filter;               // Array.filter() for promises
  	when.reduce      = lift(Promise.reduce);       // Array.reduce() for promises
  	when.reduceRight = lift(Promise.reduceRight);  // Array.reduceRight() for promises
  
  	when.isPromiseLike = isPromiseLike;      // Is something promise-like, aka thenable
  
  	when.Promise     = Promise;              // Promise constructor
  	when.defer       = defer;                // Create a {promise, resolve, reject} tuple
  
  	// Error types
  
  	when.TimeoutError = TimeoutError;
  
  	/**
  	 * Get a trusted promise for x, or by transforming x with onFulfilled
  	 *
  	 * @param {*} x
  	 * @param {function?} onFulfilled callback to be called when x is
  	 *   successfully fulfilled.  If promiseOrValue is an immediate value, callback
  	 *   will be invoked immediately.
  	 * @param {function?} onRejected callback to be called when x is
  	 *   rejected.
  	 * @param {function?} onProgress callback to be called when progress updates
  	 *   are issued for x. @deprecated
  	 * @returns {Promise} a new promise that will fulfill with the return
  	 *   value of callback or errback or the completion value of promiseOrValue if
  	 *   callback and/or errback is not supplied.
  	 */
  	function when(x, onFulfilled, onRejected, onProgress) {
  		var p = Promise.resolve(x);
  		if (arguments.length < 2) {
  			return p;
  		}
  
  		return p.then(onFulfilled, onRejected, onProgress);
  	}
  
  	/**
  	 * Creates a new promise whose fate is determined by resolver.
  	 * @param {function} resolver function(resolve, reject, notify)
  	 * @returns {Promise} promise whose fate is determine by resolver
  	 */
  	function promise(resolver) {
  		return new Promise(resolver);
  	}
  
  	/**
  	 * Lift the supplied function, creating a version of f that returns
  	 * promises, and accepts promises as arguments.
  	 * @param {function} f
  	 * @returns {Function} version of f that returns promises
  	 */
  	function lift(f) {
  		return function() {
  			for(var i=0, l=arguments.length, a=new Array(l); i<l; ++i) {
  				a[i] = arguments[i];
  			}
  			return apply(f, this, a);
  		};
  	}
  
  	/**
  	 * Call f in a future turn, with the supplied args, and return a promise
  	 * for the result.
  	 * @param {function} f
  	 * @returns {Promise}
  	 */
  	function attempt(f /*, args... */) {
  		/*jshint validthis:true */
  		for(var i=0, l=arguments.length-1, a=new Array(l); i<l; ++i) {
  			a[i] = arguments[i+1];
  		}
  		return apply(f, this, a);
  	}
  
  	/**
  	 * Creates a {promise, resolver} pair, either or both of which
  	 * may be given out safely to consumers.
  	 * @return {{promise: Promise, resolve: function, reject: function, notify: function}}
  	 */
  	function defer() {
  		return new Deferred();
  	}
  
  	function Deferred() {
  		var p = Promise._defer();
  
  		function resolve(x) { p._handler.resolve(x); }
  		function reject(x) { p._handler.reject(x); }
  		function notify(x) { p._handler.notify(x); }
  
  		this.promise = p;
  		this.resolve = resolve;
  		this.reject = reject;
  		this.notify = notify;
  		this.resolver = { resolve: resolve, reject: reject, notify: notify };
  	}
  
  	/**
  	 * Determines if x is promise-like, i.e. a thenable object
  	 * NOTE: Will return true for *any thenable object*, and isn't truly
  	 * safe, since it may attempt to access the `then` property of x (i.e.
  	 *  clever/malicious getters may do weird things)
  	 * @param {*} x anything
  	 * @returns {boolean} true if x is promise-like
  	 */
  	function isPromiseLike(x) {
  		return x && typeof x.then === 'function';
  	}
  
  	/**
  	 * Return a promise that will resolve only once all the supplied arguments
  	 * have resolved. The resolution value of the returned promise will be an array
  	 * containing the resolution values of each of the arguments.
  	 * @param {...*} arguments may be a mix of promises and values
  	 * @returns {Promise}
  	 */
  	function join(/* ...promises */) {
  		return Promise.all(arguments);
  	}
  
  	/**
  	 * Return a promise that will fulfill once all input promises have
  	 * fulfilled, or reject when any one input promise rejects.
  	 * @param {array|Promise} promises array (or promise for an array) of promises
  	 * @returns {Promise}
  	 */
  	function all(promises) {
  		return when(promises, Promise.all);
  	}
  
  	/**
  	 * Return a promise that will always fulfill with an array containing
  	 * the outcome states of all input promises.  The returned promise
  	 * will only reject if `promises` itself is a rejected promise.
  	 * @param {array|Promise} promises array (or promise for an array) of promises
  	 * @returns {Promise} promise for array of settled state descriptors
  	 */
  	function settle(promises) {
  		return when(promises, Promise.settle);
  	}
  
  	/**
  	 * Promise-aware array map function, similar to `Array.prototype.map()`,
  	 * but input array may contain promises or values.
  	 * @param {Array|Promise} promises array of anything, may contain promises and values
  	 * @param {function(x:*, index:Number):*} mapFunc map function which may
  	 *  return a promise or value
  	 * @returns {Promise} promise that will fulfill with an array of mapped values
  	 *  or reject if any input promise rejects.
  	 */
  	function map(promises, mapFunc) {
  		return when(promises, function(promises) {
  			return Promise.map(promises, mapFunc);
  		});
  	}
  
  	/**
  	 * Filter the provided array of promises using the provided predicate.  Input may
  	 * contain promises and values
  	 * @param {Array|Promise} promises array of promises and values
  	 * @param {function(x:*, index:Number):boolean} predicate filtering predicate.
  	 *  Must return truthy (or promise for truthy) for items to retain.
  	 * @returns {Promise} promise that will fulfill with an array containing all items
  	 *  for which predicate returned truthy.
  	 */
  	function filter(promises, predicate) {
  		return when(promises, function(promises) {
  			return Promise.filter(promises, predicate);
  		});
  	}
  
  	return when;
  });
  })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });
  
  },{"./lib/Promise":100,"./lib/TimeoutError":102,"./lib/apply":103,"./lib/decorators/array":104,"./lib/decorators/flow":105,"./lib/decorators/fold":106,"./lib/decorators/inspect":107,"./lib/decorators/iterate":108,"./lib/decorators/progress":109,"./lib/decorators/timed":110,"./lib/decorators/unhandledRejection":111,"./lib/decorators/with":112}],124:[function(require,module,exports){
  module.exports={
    "name": "autobahn",
    "version": "0.12.0",
    "description": "An implementation of The Web Application Messaging Protocol (WAMP).",
    "main": "index.js",
    "scripts": {
      "test": "nodeunit test/test.js"
    },
    "engines": {
      "node": ">= 4.2.6"
    },
    "dependencies": {
      "crypto-js": ">= 3.1.8",
      "google-closure-compiler": "^20170218.0.0",
      "int64-buffer": ">= 0.1.9",
      "msgpack-lite": ">= 0.1.26",
      "cbor": ">= 3.0.0",
      "tweetnacl": ">= 0.14.3",
      "when": ">= 3.7.7",
      "ws": ">= 1.1.4"
    },
    "optionalDependencies": {
      "bufferutil": ">= 1.2.1",
      "utf-8-validate": ">= 1.2.1"
    },
    "devDependencies": {
      "browserify": ">= 13.1.1",
      "nodeunit": ">= 0.10.2",
      "deep-equal": ">= 1.0.1"
    },
    "browser": {
      "ws": false,
      "lib/transport/rawsocket.js": false
    },
    "repository": {
      "type": "git",
      "url": "git://github.com/crossbario/autobahn-js.git"
    },
    "keywords": [
      "WAMP",
      "WebSocket",
      "RPC",
      "PubSub"
    ],
    "author": "Crossbar.io Technologies GmbH",
    "license": "MIT"
  }
  
  },{}],125:[function(require,module,exports){
  
  },{}],126:[function(require,module,exports){
  'use strict'
  
  exports.byteLength = byteLength
  exports.toByteArray = toByteArray
  exports.fromByteArray = fromByteArray
  
  var lookup = []
  var revLookup = []
  var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
  
  var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  for (var i = 0, len = code.length; i < len; ++i) {
    lookup[i] = code[i]
    revLookup[code.charCodeAt(i)] = i
  }
  
  revLookup['-'.charCodeAt(0)] = 62
  revLookup['_'.charCodeAt(0)] = 63
  
  function placeHoldersCount (b64) {
    var len = b64.length
    if (len % 4 > 0) {
      throw new Error('Invalid string. Length must be a multiple of 4')
    }
  
    // the number of equal signs (place holders)
    // if there are two placeholders, than the two characters before it
    // represent one byte
    // if there is only one, then the three characters before it represent 2 bytes
    // this is just a cheap hack to not do indexOf twice
    return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
  }
  
  function byteLength (b64) {
    // base64 is 4/3 + up to two characters of the original data
    return b64.length * 3 / 4 - placeHoldersCount(b64)
  }
  
  function toByteArray (b64) {
    var i, j, l, tmp, placeHolders, arr
    var len = b64.length
    placeHolders = placeHoldersCount(b64)
  
    arr = new Arr(len * 3 / 4 - placeHolders)
  
    // if there are placeholders, only get up to the last complete 4 chars
    l = placeHolders > 0 ? len - 4 : len
  
    var L = 0
  
    for (i = 0, j = 0; i < l; i += 4, j += 3) {
      tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
      arr[L++] = (tmp >> 16) & 0xFF
      arr[L++] = (tmp >> 8) & 0xFF
      arr[L++] = tmp & 0xFF
    }
  
    if (placeHolders === 2) {
      tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
      arr[L++] = tmp & 0xFF
    } else if (placeHolders === 1) {
      tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
      arr[L++] = (tmp >> 8) & 0xFF
      arr[L++] = tmp & 0xFF
    }
  
    return arr
  }
  
  function tripletToBase64 (num) {
    return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
  }
  
  function encodeChunk (uint8, start, end) {
    var tmp
    var output = []
    for (var i = start; i < end; i += 3) {
      tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
      output.push(tripletToBase64(tmp))
    }
    return output.join('')
  }
  
  function fromByteArray (uint8) {
    var tmp
    var len = uint8.length
    var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
    var output = ''
    var parts = []
    var maxChunkLength = 16383 // must be multiple of 3
  
    // go through the array every three bytes, we'll deal with trailing stuff later
    for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
      parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
    }
  
    // pad the end with zeros, but make sure to not forget the extra bytes
    if (extraBytes === 1) {
      tmp = uint8[len - 1]
      output += lookup[tmp >> 2]
      output += lookup[(tmp << 4) & 0x3F]
      output += '=='
    } else if (extraBytes === 2) {
      tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
      output += lookup[tmp >> 10]
      output += lookup[(tmp >> 4) & 0x3F]
      output += lookup[(tmp << 2) & 0x3F]
      output += '='
    }
  
    parts.push(output)
  
    return parts.join('')
  }
  
  },{}],127:[function(require,module,exports){
  arguments[4][125][0].apply(exports,arguments)
  },{"dup":125}],128:[function(require,module,exports){
  (function (global){
  'use strict';
  
  var buffer = require('buffer');
  var Buffer = buffer.Buffer;
  var SlowBuffer = buffer.SlowBuffer;
  var MAX_LEN = buffer.kMaxLength || 2147483647;
  exports.alloc = function alloc(size, fill, encoding) {
    if (typeof Buffer.alloc === 'function') {
      return Buffer.alloc(size, fill, encoding);
    }
    if (typeof encoding === 'number') {
      throw new TypeError('encoding must not be number');
    }
    if (typeof size !== 'number') {
      throw new TypeError('size must be a number');
    }
    if (size > MAX_LEN) {
      throw new RangeError('size is too large');
    }
    var enc = encoding;
    var _fill = fill;
    if (_fill === undefined) {
      enc = undefined;
      _fill = 0;
    }
    var buf = new Buffer(size);
    if (typeof _fill === 'string') {
      var fillBuf = new Buffer(_fill, enc);
      var flen = fillBuf.length;
      var i = -1;
      while (++i < size) {
        buf[i] = fillBuf[i % flen];
      }
    } else {
      buf.fill(_fill);
    }
    return buf;
  }
  exports.allocUnsafe = function allocUnsafe(size) {
    if (typeof Buffer.allocUnsafe === 'function') {
      return Buffer.allocUnsafe(size);
    }
    if (typeof size !== 'number') {
      throw new TypeError('size must be a number');
    }
    if (size > MAX_LEN) {
      throw new RangeError('size is too large');
    }
    return new Buffer(size);
  }
  exports.from = function from(value, encodingOrOffset, length) {
    if (typeof Buffer.from === 'function' && (!global.Uint8Array || Uint8Array.from !== Buffer.from)) {
      return Buffer.from(value, encodingOrOffset, length);
    }
    if (typeof value === 'number') {
      throw new TypeError('"value" argument must not be a number');
    }
    if (typeof value === 'string') {
      return new Buffer(value, encodingOrOffset);
    }
    if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
      var offset = encodingOrOffset;
      if (arguments.length === 1) {
        return new Buffer(value);
      }
      if (typeof offset === 'undefined') {
        offset = 0;
      }
      var len = length;
      if (typeof len === 'undefined') {
        len = value.byteLength - offset;
      }
      if (offset >= value.byteLength) {
        throw new RangeError('\'offset\' is out of bounds');
      }
      if (len > value.byteLength - offset) {
        throw new RangeError('\'length\' is out of bounds');
      }
      return new Buffer(value.slice(offset, offset + len));
    }
    if (Buffer.isBuffer(value)) {
      var out = new Buffer(value.length);
      value.copy(out, 0, 0, value.length);
      return out;
    }
    if (value) {
      if (Array.isArray(value) || (typeof ArrayBuffer !== 'undefined' && value.buffer instanceof ArrayBuffer) || 'length' in value) {
        return new Buffer(value);
      }
      if (value.type === 'Buffer' && Array.isArray(value.data)) {
        return new Buffer(value.data);
      }
    }
  
    throw new TypeError('First argument must be a string, Buffer, ' + 'ArrayBuffer, Array, or array-like object.');
  }
  exports.allocUnsafeSlow = function allocUnsafeSlow(size) {
    if (typeof Buffer.allocUnsafeSlow === 'function') {
      return Buffer.allocUnsafeSlow(size);
    }
    if (typeof size !== 'number') {
      throw new TypeError('size must be a number');
    }
    if (size >= MAX_LEN) {
      throw new RangeError('size is too large');
    }
    return new SlowBuffer(size);
  }
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"buffer":129}],129:[function(require,module,exports){
  /*!
   * The buffer module from node.js, for the browser.
   *
   * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
   * @license  MIT
   */
  /* eslint-disable no-proto */
  
  'use strict'
  
  var base64 = require('base64-js')
  var ieee754 = require('ieee754')
  
  exports.Buffer = Buffer
  exports.SlowBuffer = SlowBuffer
  exports.INSPECT_MAX_BYTES = 50
  
  var K_MAX_LENGTH = 0x7fffffff
  exports.kMaxLength = K_MAX_LENGTH
  
  /**
   * If `Buffer.TYPED_ARRAY_SUPPORT`:
   *   === true    Use Uint8Array implementation (fastest)
   *   === false   Print warning and recommend using `buffer` v4.x which has an Object
   *               implementation (most compatible, even IE6)
   *
   * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
   * Opera 11.6+, iOS 4.2+.
   *
   * We report that the browser does not support typed arrays if the are not subclassable
   * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`
   * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support
   * for __proto__ and has a buggy typed array implementation.
   */
  Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport()
  
  if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' &&
      typeof console.error === 'function') {
    console.error(
      'This browser lacks typed array (Uint8Array) support which is required by ' +
      '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'
    )
  }
  
  function typedArraySupport () {
    // Can typed array instances can be augmented?
    try {
      var arr = new Uint8Array(1)
      arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
      return arr.foo() === 42
    } catch (e) {
      return false
    }
  }
  
  function createBuffer (length) {
    if (length > K_MAX_LENGTH) {
      throw new RangeError('Invalid typed array length')
    }
    // Return an augmented `Uint8Array` instance
    var buf = new Uint8Array(length)
    buf.__proto__ = Buffer.prototype
    return buf
  }
  
  /**
   * The Buffer constructor returns instances of `Uint8Array` that have their
   * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
   * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
   * and the `Uint8Array` methods. Square bracket notation works as expected -- it
   * returns a single octet.
   *
   * The `Uint8Array` prototype remains unmodified.
   */
  
  function Buffer (arg, encodingOrOffset, length) {
    // Common case.
    if (typeof arg === 'number') {
      if (typeof encodingOrOffset === 'string') {
        throw new Error(
          'If encoding is specified then the first argument must be a string'
        )
      }
      return allocUnsafe(arg)
    }
    return from(arg, encodingOrOffset, length)
  }
  
  // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
  if (typeof Symbol !== 'undefined' && Symbol.species &&
      Buffer[Symbol.species] === Buffer) {
    Object.defineProperty(Buffer, Symbol.species, {
      value: null,
      configurable: true,
      enumerable: false,
      writable: false
    })
  }
  
  Buffer.poolSize = 8192 // not used by this implementation
  
  function from (value, encodingOrOffset, length) {
    if (typeof value === 'number') {
      throw new TypeError('"value" argument must not be a number')
    }
  
    if (value instanceof ArrayBuffer) {
      return fromArrayBuffer(value, encodingOrOffset, length)
    }
  
    if (typeof value === 'string') {
      return fromString(value, encodingOrOffset)
    }
  
    return fromObject(value)
  }
  
  /**
   * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
   * if value is a number.
   * Buffer.from(str[, encoding])
   * Buffer.from(array)
   * Buffer.from(buffer)
   * Buffer.from(arrayBuffer[, byteOffset[, length]])
   **/
  Buffer.from = function (value, encodingOrOffset, length) {
    return from(value, encodingOrOffset, length)
  }
  
  // Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:
  // https://github.com/feross/buffer/pull/148
  Buffer.prototype.__proto__ = Uint8Array.prototype
  Buffer.__proto__ = Uint8Array
  
  function assertSize (size) {
    if (typeof size !== 'number') {
      throw new TypeError('"size" argument must be a number')
    } else if (size < 0) {
      throw new RangeError('"size" argument must not be negative')
    }
  }
  
  function alloc (size, fill, encoding) {
    assertSize(size)
    if (size <= 0) {
      return createBuffer(size)
    }
    if (fill !== undefined) {
      // Only pay attention to encoding if it's a string. This
      // prevents accidentally sending in a number that would
      // be interpretted as a start offset.
      return typeof encoding === 'string'
        ? createBuffer(size).fill(fill, encoding)
        : createBuffer(size).fill(fill)
    }
    return createBuffer(size)
  }
  
  /**
   * Creates a new filled Buffer instance.
   * alloc(size[, fill[, encoding]])
   **/
  Buffer.alloc = function (size, fill, encoding) {
    return alloc(size, fill, encoding)
  }
  
  function allocUnsafe (size) {
    assertSize(size)
    return createBuffer(size < 0 ? 0 : checked(size) | 0)
  }
  
  /**
   * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
   * */
  Buffer.allocUnsafe = function (size) {
    return allocUnsafe(size)
  }
  /**
   * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
   */
  Buffer.allocUnsafeSlow = function (size) {
    return allocUnsafe(size)
  }
  
  function fromString (string, encoding) {
    if (typeof encoding !== 'string' || encoding === '') {
      encoding = 'utf8'
    }
  
    if (!Buffer.isEncoding(encoding)) {
      throw new TypeError('"encoding" must be a valid string encoding')
    }
  
    var length = byteLength(string, encoding) | 0
    var buf = createBuffer(length)
  
    var actual = buf.write(string, encoding)
  
    if (actual !== length) {
      // Writing a hex string, for example, that contains invalid characters will
      // cause everything after the first invalid character to be ignored. (e.g.
      // 'abxxcd' will be treated as 'ab')
      buf = buf.slice(0, actual)
    }
  
    return buf
  }
  
  function fromArrayLike (array) {
    var length = array.length < 0 ? 0 : checked(array.length) | 0
    var buf = createBuffer(length)
    for (var i = 0; i < length; i += 1) {
      buf[i] = array[i] & 255
    }
    return buf
  }
  
  function fromArrayBuffer (array, byteOffset, length) {
    if (byteOffset < 0 || array.byteLength < byteOffset) {
      throw new RangeError('\'offset\' is out of bounds')
    }
  
    if (array.byteLength < byteOffset + (length || 0)) {
      throw new RangeError('\'length\' is out of bounds')
    }
  
    var buf
    if (byteOffset === undefined && length === undefined) {
      buf = new Uint8Array(array)
    } else if (length === undefined) {
      buf = new Uint8Array(array, byteOffset)
    } else {
      buf = new Uint8Array(array, byteOffset, length)
    }
  
    // Return an augmented `Uint8Array` instance
    buf.__proto__ = Buffer.prototype
    return buf
  }
  
  function fromObject (obj) {
    if (Buffer.isBuffer(obj)) {
      var len = checked(obj.length) | 0
      var buf = createBuffer(len)
  
      if (buf.length === 0) {
        return buf
      }
  
      obj.copy(buf, 0, 0, len)
      return buf
    }
  
    if (obj) {
      if (ArrayBuffer.isView(obj) || 'length' in obj) {
        if (typeof obj.length !== 'number' || isnan(obj.length)) {
          return createBuffer(0)
        }
        return fromArrayLike(obj)
      }
  
      if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
        return fromArrayLike(obj.data)
      }
    }
  
    throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
  }
  
  function checked (length) {
    // Note: cannot use `length < K_MAX_LENGTH` here because that fails when
    // length is NaN (which is otherwise coerced to zero.)
    if (length >= K_MAX_LENGTH) {
      throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
                           'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes')
    }
    return length | 0
  }
  
  function SlowBuffer (length) {
    if (+length != length) { // eslint-disable-line eqeqeq
      length = 0
    }
    return Buffer.alloc(+length)
  }
  
  Buffer.isBuffer = function isBuffer (b) {
    return b != null && b._isBuffer === true
  }
  
  Buffer.compare = function compare (a, b) {
    if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
      throw new TypeError('Arguments must be Buffers')
    }
  
    if (a === b) return 0
  
    var x = a.length
    var y = b.length
  
    for (var i = 0, len = Math.min(x, y); i < len; ++i) {
      if (a[i] !== b[i]) {
        x = a[i]
        y = b[i]
        break
      }
    }
  
    if (x < y) return -1
    if (y < x) return 1
    return 0
  }
  
  Buffer.isEncoding = function isEncoding (encoding) {
    switch (String(encoding).toLowerCase()) {
      case 'hex':
      case 'utf8':
      case 'utf-8':
      case 'ascii':
      case 'latin1':
      case 'binary':
      case 'base64':
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return true
      default:
        return false
    }
  }
  
  Buffer.concat = function concat (list, length) {
    if (!Array.isArray(list)) {
      throw new TypeError('"list" argument must be an Array of Buffers')
    }
  
    if (list.length === 0) {
      return Buffer.alloc(0)
    }
  
    var i
    if (length === undefined) {
      length = 0
      for (i = 0; i < list.length; ++i) {
        length += list[i].length
      }
    }
  
    var buffer = Buffer.allocUnsafe(length)
    var pos = 0
    for (i = 0; i < list.length; ++i) {
      var buf = list[i]
      if (!Buffer.isBuffer(buf)) {
        throw new TypeError('"list" argument must be an Array of Buffers')
      }
      buf.copy(buffer, pos)
      pos += buf.length
    }
    return buffer
  }
  
  function byteLength (string, encoding) {
    if (Buffer.isBuffer(string)) {
      return string.length
    }
    if (ArrayBuffer.isView(string) || string instanceof ArrayBuffer) {
      return string.byteLength
    }
    if (typeof string !== 'string') {
      string = '' + string
    }
  
    var len = string.length
    if (len === 0) return 0
  
    // Use a for loop to avoid recursion
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'ascii':
        case 'latin1':
        case 'binary':
          return len
        case 'utf8':
        case 'utf-8':
        case undefined:
          return utf8ToBytes(string).length
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return len * 2
        case 'hex':
          return len >>> 1
        case 'base64':
          return base64ToBytes(string).length
        default:
          if (loweredCase) return utf8ToBytes(string).length // assume utf8
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  Buffer.byteLength = byteLength
  
  function slowToString (encoding, start, end) {
    var loweredCase = false
  
    // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
    // property of a typed array.
  
    // This behaves neither like String nor Uint8Array in that we set start/end
    // to their upper/lower bounds if the value passed is out of range.
    // undefined is handled specially as per ECMA-262 6th Edition,
    // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
    if (start === undefined || start < 0) {
      start = 0
    }
    // Return early if start > this.length. Done here to prevent potential uint32
    // coercion fail below.
    if (start > this.length) {
      return ''
    }
  
    if (end === undefined || end > this.length) {
      end = this.length
    }
  
    if (end <= 0) {
      return ''
    }
  
    // Force coersion to uint32. This will also coerce falsey/NaN values to 0.
    end >>>= 0
    start >>>= 0
  
    if (end <= start) {
      return ''
    }
  
    if (!encoding) encoding = 'utf8'
  
    while (true) {
      switch (encoding) {
        case 'hex':
          return hexSlice(this, start, end)
  
        case 'utf8':
        case 'utf-8':
          return utf8Slice(this, start, end)
  
        case 'ascii':
          return asciiSlice(this, start, end)
  
        case 'latin1':
        case 'binary':
          return latin1Slice(this, start, end)
  
        case 'base64':
          return base64Slice(this, start, end)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return utf16leSlice(this, start, end)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = (encoding + '').toLowerCase()
          loweredCase = true
      }
    }
  }
  
  // This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)
  // to detect a Buffer instance. It's not possible to use `instanceof Buffer`
  // reliably in a browserify context because there could be multiple different
  // copies of the 'buffer' package in use. This method works even for Buffer
  // instances that were created from another copy of the `buffer` package.
  // See: https://github.com/feross/buffer/issues/154
  Buffer.prototype._isBuffer = true
  
  function swap (b, n, m) {
    var i = b[n]
    b[n] = b[m]
    b[m] = i
  }
  
  Buffer.prototype.swap16 = function swap16 () {
    var len = this.length
    if (len % 2 !== 0) {
      throw new RangeError('Buffer size must be a multiple of 16-bits')
    }
    for (var i = 0; i < len; i += 2) {
      swap(this, i, i + 1)
    }
    return this
  }
  
  Buffer.prototype.swap32 = function swap32 () {
    var len = this.length
    if (len % 4 !== 0) {
      throw new RangeError('Buffer size must be a multiple of 32-bits')
    }
    for (var i = 0; i < len; i += 4) {
      swap(this, i, i + 3)
      swap(this, i + 1, i + 2)
    }
    return this
  }
  
  Buffer.prototype.swap64 = function swap64 () {
    var len = this.length
    if (len % 8 !== 0) {
      throw new RangeError('Buffer size must be a multiple of 64-bits')
    }
    for (var i = 0; i < len; i += 8) {
      swap(this, i, i + 7)
      swap(this, i + 1, i + 6)
      swap(this, i + 2, i + 5)
      swap(this, i + 3, i + 4)
    }
    return this
  }
  
  Buffer.prototype.toString = function toString () {
    var length = this.length
    if (length === 0) return ''
    if (arguments.length === 0) return utf8Slice(this, 0, length)
    return slowToString.apply(this, arguments)
  }
  
  Buffer.prototype.equals = function equals (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    if (this === b) return true
    return Buffer.compare(this, b) === 0
  }
  
  Buffer.prototype.inspect = function inspect () {
    var str = ''
    var max = exports.INSPECT_MAX_BYTES
    if (this.length > 0) {
      str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
      if (this.length > max) str += ' ... '
    }
    return '<Buffer ' + str + '>'
  }
  
  Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
    if (!Buffer.isBuffer(target)) {
      throw new TypeError('Argument must be a Buffer')
    }
  
    if (start === undefined) {
      start = 0
    }
    if (end === undefined) {
      end = target ? target.length : 0
    }
    if (thisStart === undefined) {
      thisStart = 0
    }
    if (thisEnd === undefined) {
      thisEnd = this.length
    }
  
    if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
      throw new RangeError('out of range index')
    }
  
    if (thisStart >= thisEnd && start >= end) {
      return 0
    }
    if (thisStart >= thisEnd) {
      return -1
    }
    if (start >= end) {
      return 1
    }
  
    start >>>= 0
    end >>>= 0
    thisStart >>>= 0
    thisEnd >>>= 0
  
    if (this === target) return 0
  
    var x = thisEnd - thisStart
    var y = end - start
    var len = Math.min(x, y)
  
    var thisCopy = this.slice(thisStart, thisEnd)
    var targetCopy = target.slice(start, end)
  
    for (var i = 0; i < len; ++i) {
      if (thisCopy[i] !== targetCopy[i]) {
        x = thisCopy[i]
        y = targetCopy[i]
        break
      }
    }
  
    if (x < y) return -1
    if (y < x) return 1
    return 0
  }
  
  // Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
  // OR the last index of `val` in `buffer` at offset <= `byteOffset`.
  //
  // Arguments:
  // - buffer - a Buffer to search
  // - val - a string, Buffer, or number
  // - byteOffset - an index into `buffer`; will be clamped to an int32
  // - encoding - an optional encoding, relevant is val is a string
  // - dir - true for indexOf, false for lastIndexOf
  function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
    // Empty buffer means no match
    if (buffer.length === 0) return -1
  
    // Normalize byteOffset
    if (typeof byteOffset === 'string') {
      encoding = byteOffset
      byteOffset = 0
    } else if (byteOffset > 0x7fffffff) {
      byteOffset = 0x7fffffff
    } else if (byteOffset < -0x80000000) {
      byteOffset = -0x80000000
    }
    byteOffset = +byteOffset  // Coerce to Number.
    if (isNaN(byteOffset)) {
      // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
      byteOffset = dir ? 0 : (buffer.length - 1)
    }
  
    // Normalize byteOffset: negative offsets start from the end of the buffer
    if (byteOffset < 0) byteOffset = buffer.length + byteOffset
    if (byteOffset >= buffer.length) {
      if (dir) return -1
      else byteOffset = buffer.length - 1
    } else if (byteOffset < 0) {
      if (dir) byteOffset = 0
      else return -1
    }
  
    // Normalize val
    if (typeof val === 'string') {
      val = Buffer.from(val, encoding)
    }
  
    // Finally, search either indexOf (if dir is true) or lastIndexOf
    if (Buffer.isBuffer(val)) {
      // Special case: looking for empty string/buffer always fails
      if (val.length === 0) {
        return -1
      }
      return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
    } else if (typeof val === 'number') {
      val = val & 0xFF // Search for a byte value [0-255]
      if (typeof Uint8Array.prototype.indexOf === 'function') {
        if (dir) {
          return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
        } else {
          return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
        }
      }
      return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
    }
  
    throw new TypeError('val must be string, number or Buffer')
  }
  
  function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
    var indexSize = 1
    var arrLength = arr.length
    var valLength = val.length
  
    if (encoding !== undefined) {
      encoding = String(encoding).toLowerCase()
      if (encoding === 'ucs2' || encoding === 'ucs-2' ||
          encoding === 'utf16le' || encoding === 'utf-16le') {
        if (arr.length < 2 || val.length < 2) {
          return -1
        }
        indexSize = 2
        arrLength /= 2
        valLength /= 2
        byteOffset /= 2
      }
    }
  
    function read (buf, i) {
      if (indexSize === 1) {
        return buf[i]
      } else {
        return buf.readUInt16BE(i * indexSize)
      }
    }
  
    var i
    if (dir) {
      var foundIndex = -1
      for (i = byteOffset; i < arrLength; i++) {
        if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
          if (foundIndex === -1) foundIndex = i
          if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
        } else {
          if (foundIndex !== -1) i -= i - foundIndex
          foundIndex = -1
        }
      }
    } else {
      if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
      for (i = byteOffset; i >= 0; i--) {
        var found = true
        for (var j = 0; j < valLength; j++) {
          if (read(arr, i + j) !== read(val, j)) {
            found = false
            break
          }
        }
        if (found) return i
      }
    }
  
    return -1
  }
  
  Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
    return this.indexOf(val, byteOffset, encoding) !== -1
  }
  
  Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
    return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
  }
  
  Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
    return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
  }
  
  function hexWrite (buf, string, offset, length) {
    offset = Number(offset) || 0
    var remaining = buf.length - offset
    if (!length) {
      length = remaining
    } else {
      length = Number(length)
      if (length > remaining) {
        length = remaining
      }
    }
  
    // must be an even number of digits
    var strLen = string.length
    if (strLen % 2 !== 0) throw new TypeError('Invalid hex string')
  
    if (length > strLen / 2) {
      length = strLen / 2
    }
    for (var i = 0; i < length; ++i) {
      var parsed = parseInt(string.substr(i * 2, 2), 16)
      if (isNaN(parsed)) return i
      buf[offset + i] = parsed
    }
    return i
  }
  
  function utf8Write (buf, string, offset, length) {
    return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  function asciiWrite (buf, string, offset, length) {
    return blitBuffer(asciiToBytes(string), buf, offset, length)
  }
  
  function latin1Write (buf, string, offset, length) {
    return asciiWrite(buf, string, offset, length)
  }
  
  function base64Write (buf, string, offset, length) {
    return blitBuffer(base64ToBytes(string), buf, offset, length)
  }
  
  function ucs2Write (buf, string, offset, length) {
    return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  Buffer.prototype.write = function write (string, offset, length, encoding) {
    // Buffer#write(string)
    if (offset === undefined) {
      encoding = 'utf8'
      length = this.length
      offset = 0
    // Buffer#write(string, encoding)
    } else if (length === undefined && typeof offset === 'string') {
      encoding = offset
      length = this.length
      offset = 0
    // Buffer#write(string, offset[, length][, encoding])
    } else if (isFinite(offset)) {
      offset = offset >>> 0
      if (isFinite(length)) {
        length = length >>> 0
        if (encoding === undefined) encoding = 'utf8'
      } else {
        encoding = length
        length = undefined
      }
    } else {
      throw new Error(
        'Buffer.write(string, encoding, offset[, length]) is no longer supported'
      )
    }
  
    var remaining = this.length - offset
    if (length === undefined || length > remaining) length = remaining
  
    if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
      throw new RangeError('Attempt to write outside buffer bounds')
    }
  
    if (!encoding) encoding = 'utf8'
  
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'hex':
          return hexWrite(this, string, offset, length)
  
        case 'utf8':
        case 'utf-8':
          return utf8Write(this, string, offset, length)
  
        case 'ascii':
          return asciiWrite(this, string, offset, length)
  
        case 'latin1':
        case 'binary':
          return latin1Write(this, string, offset, length)
  
        case 'base64':
          // Warning: maxLength not taken into account in base64Write
          return base64Write(this, string, offset, length)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return ucs2Write(this, string, offset, length)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.toJSON = function toJSON () {
    return {
      type: 'Buffer',
      data: Array.prototype.slice.call(this._arr || this, 0)
    }
  }
  
  function base64Slice (buf, start, end) {
    if (start === 0 && end === buf.length) {
      return base64.fromByteArray(buf)
    } else {
      return base64.fromByteArray(buf.slice(start, end))
    }
  }
  
  function utf8Slice (buf, start, end) {
    end = Math.min(buf.length, end)
    var res = []
  
    var i = start
    while (i < end) {
      var firstByte = buf[i]
      var codePoint = null
      var bytesPerSequence = (firstByte > 0xEF) ? 4
        : (firstByte > 0xDF) ? 3
        : (firstByte > 0xBF) ? 2
        : 1
  
      if (i + bytesPerSequence <= end) {
        var secondByte, thirdByte, fourthByte, tempCodePoint
  
        switch (bytesPerSequence) {
          case 1:
            if (firstByte < 0x80) {
              codePoint = firstByte
            }
            break
          case 2:
            secondByte = buf[i + 1]
            if ((secondByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
              if (tempCodePoint > 0x7F) {
                codePoint = tempCodePoint
              }
            }
            break
          case 3:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
              if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
                codePoint = tempCodePoint
              }
            }
            break
          case 4:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            fourthByte = buf[i + 3]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
              if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
                codePoint = tempCodePoint
              }
            }
        }
      }
  
      if (codePoint === null) {
        // we did not generate a valid codePoint so insert a
        // replacement char (U+FFFD) and advance only 1 byte
        codePoint = 0xFFFD
        bytesPerSequence = 1
      } else if (codePoint > 0xFFFF) {
        // encode to utf16 (surrogate pair dance)
        codePoint -= 0x10000
        res.push(codePoint >>> 10 & 0x3FF | 0xD800)
        codePoint = 0xDC00 | codePoint & 0x3FF
      }
  
      res.push(codePoint)
      i += bytesPerSequence
    }
  
    return decodeCodePointsArray(res)
  }
  
  // Based on http://stackoverflow.com/a/22747272/680742, the browser with
  // the lowest limit is Chrome, with 0x10000 args.
  // We go 1 magnitude less, for safety
  var MAX_ARGUMENTS_LENGTH = 0x1000
  
  function decodeCodePointsArray (codePoints) {
    var len = codePoints.length
    if (len <= MAX_ARGUMENTS_LENGTH) {
      return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
    }
  
    // Decode in chunks to avoid "call stack size exceeded".
    var res = ''
    var i = 0
    while (i < len) {
      res += String.fromCharCode.apply(
        String,
        codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
      )
    }
    return res
  }
  
  function asciiSlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; ++i) {
      ret += String.fromCharCode(buf[i] & 0x7F)
    }
    return ret
  }
  
  function latin1Slice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; ++i) {
      ret += String.fromCharCode(buf[i])
    }
    return ret
  }
  
  function hexSlice (buf, start, end) {
    var len = buf.length
  
    if (!start || start < 0) start = 0
    if (!end || end < 0 || end > len) end = len
  
    var out = ''
    for (var i = start; i < end; ++i) {
      out += toHex(buf[i])
    }
    return out
  }
  
  function utf16leSlice (buf, start, end) {
    var bytes = buf.slice(start, end)
    var res = ''
    for (var i = 0; i < bytes.length; i += 2) {
      res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256))
    }
    return res
  }
  
  Buffer.prototype.slice = function slice (start, end) {
    var len = this.length
    start = ~~start
    end = end === undefined ? len : ~~end
  
    if (start < 0) {
      start += len
      if (start < 0) start = 0
    } else if (start > len) {
      start = len
    }
  
    if (end < 0) {
      end += len
      if (end < 0) end = 0
    } else if (end > len) {
      end = len
    }
  
    if (end < start) end = start
  
    var newBuf = this.subarray(start, end)
    // Return an augmented `Uint8Array` instance
    newBuf.__proto__ = Buffer.prototype
    return newBuf
  }
  
  /*
   * Need to make sure that buffer isn't trying to write out of bounds.
   */
  function checkOffset (offset, ext, length) {
    if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
    if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
  }
  
  Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
    offset = offset >>> 0
    byteLength = byteLength >>> 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
    offset = offset >>> 0
    byteLength = byteLength >>> 0
    if (!noAssert) {
      checkOffset(offset, byteLength, this.length)
    }
  
    var val = this[offset + --byteLength]
    var mul = 1
    while (byteLength > 0 && (mul *= 0x100)) {
      val += this[offset + --byteLength] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 1, this.length)
    return this[offset]
  }
  
  Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 2, this.length)
    return this[offset] | (this[offset + 1] << 8)
  }
  
  Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 2, this.length)
    return (this[offset] << 8) | this[offset + 1]
  }
  
  Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return ((this[offset]) |
        (this[offset + 1] << 8) |
        (this[offset + 2] << 16)) +
        (this[offset + 3] * 0x1000000)
  }
  
  Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] * 0x1000000) +
      ((this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      this[offset + 3])
  }
  
  Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
    offset = offset >>> 0
    byteLength = byteLength >>> 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
    offset = offset >>> 0
    byteLength = byteLength >>> 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var i = byteLength
    var mul = 1
    var val = this[offset + --i]
    while (i > 0 && (mul *= 0x100)) {
      val += this[offset + --i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 1, this.length)
    if (!(this[offset] & 0x80)) return (this[offset])
    return ((0xff - this[offset] + 1) * -1)
  }
  
  Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset] | (this[offset + 1] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset + 1] | (this[offset] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset]) |
      (this[offset + 1] << 8) |
      (this[offset + 2] << 16) |
      (this[offset + 3] << 24)
  }
  
  Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] << 24) |
      (this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      (this[offset + 3])
  }
  
  Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, true, 23, 4)
  }
  
  Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, false, 23, 4)
  }
  
  Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, true, 52, 8)
  }
  
  Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
    offset = offset >>> 0
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, false, 52, 8)
  }
  
  function checkInt (buf, value, offset, ext, max, min) {
    if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
    if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('Index out of range')
  }
  
  Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset >>> 0
    byteLength = byteLength >>> 0
    if (!noAssert) {
      var maxBytes = Math.pow(2, 8 * byteLength) - 1
      checkInt(this, value, offset, byteLength, maxBytes, 0)
    }
  
    var mul = 1
    var i = 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset >>> 0
    byteLength = byteLength >>> 0
    if (!noAssert) {
      var maxBytes = Math.pow(2, 8 * byteLength) - 1
      checkInt(this, value, offset, byteLength, maxBytes, 0)
    }
  
    var i = byteLength - 1
    var mul = 1
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
    this[offset] = (value & 0xff)
    return offset + 1
  }
  
  Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    this[offset] = (value & 0xff)
    this[offset + 1] = (value >>> 8)
    return offset + 2
  }
  
  Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    this[offset] = (value >>> 8)
    this[offset + 1] = (value & 0xff)
    return offset + 2
  }
  
  Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    this[offset + 3] = (value >>> 24)
    this[offset + 2] = (value >>> 16)
    this[offset + 1] = (value >>> 8)
    this[offset] = (value & 0xff)
    return offset + 4
  }
  
  Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    this[offset] = (value >>> 24)
    this[offset + 1] = (value >>> 16)
    this[offset + 2] = (value >>> 8)
    this[offset + 3] = (value & 0xff)
    return offset + 4
  }
  
  Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) {
      var limit = Math.pow(2, (8 * byteLength) - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = 0
    var mul = 1
    var sub = 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
        sub = 1
      }
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) {
      var limit = Math.pow(2, (8 * byteLength) - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = byteLength - 1
    var mul = 1
    var sub = 0
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
        sub = 1
      }
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
    if (value < 0) value = 0xff + value + 1
    this[offset] = (value & 0xff)
    return offset + 1
  }
  
  Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    this[offset] = (value & 0xff)
    this[offset + 1] = (value >>> 8)
    return offset + 2
  }
  
  Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    this[offset] = (value >>> 8)
    this[offset + 1] = (value & 0xff)
    return offset + 2
  }
  
  Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    this[offset] = (value & 0xff)
    this[offset + 1] = (value >>> 8)
    this[offset + 2] = (value >>> 16)
    this[offset + 3] = (value >>> 24)
    return offset + 4
  }
  
  Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (value < 0) value = 0xffffffff + value + 1
    this[offset] = (value >>> 24)
    this[offset + 1] = (value >>> 16)
    this[offset + 2] = (value >>> 8)
    this[offset + 3] = (value & 0xff)
    return offset + 4
  }
  
  function checkIEEE754 (buf, value, offset, ext, max, min) {
    if (offset + ext > buf.length) throw new RangeError('Index out of range')
    if (offset < 0) throw new RangeError('Index out of range')
  }
  
  function writeFloat (buf, value, offset, littleEndian, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
    }
    ieee754.write(buf, value, offset, littleEndian, 23, 4)
    return offset + 4
  }
  
  Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
    return writeFloat(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
    return writeFloat(this, value, offset, false, noAssert)
  }
  
  function writeDouble (buf, value, offset, littleEndian, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
    }
    ieee754.write(buf, value, offset, littleEndian, 52, 8)
    return offset + 8
  }
  
  Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
    return writeDouble(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
    return writeDouble(this, value, offset, false, noAssert)
  }
  
  // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
  Buffer.prototype.copy = function copy (target, targetStart, start, end) {
    if (!start) start = 0
    if (!end && end !== 0) end = this.length
    if (targetStart >= target.length) targetStart = target.length
    if (!targetStart) targetStart = 0
    if (end > 0 && end < start) end = start
  
    // Copy 0 bytes; we're done
    if (end === start) return 0
    if (target.length === 0 || this.length === 0) return 0
  
    // Fatal error conditions
    if (targetStart < 0) {
      throw new RangeError('targetStart out of bounds')
    }
    if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
    if (end < 0) throw new RangeError('sourceEnd out of bounds')
  
    // Are we oob?
    if (end > this.length) end = this.length
    if (target.length - targetStart < end - start) {
      end = target.length - targetStart + start
    }
  
    var len = end - start
    var i
  
    if (this === target && start < targetStart && targetStart < end) {
      // descending copy from end
      for (i = len - 1; i >= 0; --i) {
        target[i + targetStart] = this[i + start]
      }
    } else if (len < 1000) {
      // ascending copy from start
      for (i = 0; i < len; ++i) {
        target[i + targetStart] = this[i + start]
      }
    } else {
      Uint8Array.prototype.set.call(
        target,
        this.subarray(start, start + len),
        targetStart
      )
    }
  
    return len
  }
  
  // Usage:
  //    buffer.fill(number[, offset[, end]])
  //    buffer.fill(buffer[, offset[, end]])
  //    buffer.fill(string[, offset[, end]][, encoding])
  Buffer.prototype.fill = function fill (val, start, end, encoding) {
    // Handle string cases:
    if (typeof val === 'string') {
      if (typeof start === 'string') {
        encoding = start
        start = 0
        end = this.length
      } else if (typeof end === 'string') {
        encoding = end
        end = this.length
      }
      if (val.length === 1) {
        var code = val.charCodeAt(0)
        if (code < 256) {
          val = code
        }
      }
      if (encoding !== undefined && typeof encoding !== 'string') {
        throw new TypeError('encoding must be a string')
      }
      if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
        throw new TypeError('Unknown encoding: ' + encoding)
      }
    } else if (typeof val === 'number') {
      val = val & 255
    }
  
    // Invalid ranges are not set to a default, so can range check early.
    if (start < 0 || this.length < start || this.length < end) {
      throw new RangeError('Out of range index')
    }
  
    if (end <= start) {
      return this
    }
  
    start = start >>> 0
    end = end === undefined ? this.length : end >>> 0
  
    if (!val) val = 0
  
    var i
    if (typeof val === 'number') {
      for (i = start; i < end; ++i) {
        this[i] = val
      }
    } else {
      var bytes = Buffer.isBuffer(val)
        ? val
        : new Buffer(val, encoding)
      var len = bytes.length
      for (i = 0; i < end - start; ++i) {
        this[i + start] = bytes[i % len]
      }
    }
  
    return this
  }
  
  // HELPER FUNCTIONS
  // ================
  
  var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g
  
  function base64clean (str) {
    // Node strips out invalid characters like \n and \t from the string, base64-js does not
    str = stringtrim(str).replace(INVALID_BASE64_RE, '')
    // Node converts strings with length < 2 to ''
    if (str.length < 2) return ''
    // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
    while (str.length % 4 !== 0) {
      str = str + '='
    }
    return str
  }
  
  function stringtrim (str) {
    if (str.trim) return str.trim()
    return str.replace(/^\s+|\s+$/g, '')
  }
  
  function toHex (n) {
    if (n < 16) return '0' + n.toString(16)
    return n.toString(16)
  }
  
  function utf8ToBytes (string, units) {
    units = units || Infinity
    var codePoint
    var length = string.length
    var leadSurrogate = null
    var bytes = []
  
    for (var i = 0; i < length; ++i) {
      codePoint = string.charCodeAt(i)
  
      // is surrogate component
      if (codePoint > 0xD7FF && codePoint < 0xE000) {
        // last char was a lead
        if (!leadSurrogate) {
          // no lead yet
          if (codePoint > 0xDBFF) {
            // unexpected trail
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          } else if (i + 1 === length) {
            // unpaired lead
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          }
  
          // valid lead
          leadSurrogate = codePoint
  
          continue
        }
  
        // 2 leads in a row
        if (codePoint < 0xDC00) {
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          leadSurrogate = codePoint
          continue
        }
  
        // valid surrogate pair
        codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
      } else if (leadSurrogate) {
        // valid bmp char, but last char was a lead
        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
      }
  
      leadSurrogate = null
  
      // encode utf8
      if (codePoint < 0x80) {
        if ((units -= 1) < 0) break
        bytes.push(codePoint)
      } else if (codePoint < 0x800) {
        if ((units -= 2) < 0) break
        bytes.push(
          codePoint >> 0x6 | 0xC0,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x10000) {
        if ((units -= 3) < 0) break
        bytes.push(
          codePoint >> 0xC | 0xE0,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x110000) {
        if ((units -= 4) < 0) break
        bytes.push(
          codePoint >> 0x12 | 0xF0,
          codePoint >> 0xC & 0x3F | 0x80,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else {
        throw new Error('Invalid code point')
      }
    }
  
    return bytes
  }
  
  function asciiToBytes (str) {
    var byteArray = []
    for (var i = 0; i < str.length; ++i) {
      // Node's code seems to be doing this and not & 0x7F..
      byteArray.push(str.charCodeAt(i) & 0xFF)
    }
    return byteArray
  }
  
  function utf16leToBytes (str, units) {
    var c, hi, lo
    var byteArray = []
    for (var i = 0; i < str.length; ++i) {
      if ((units -= 2) < 0) break
  
      c = str.charCodeAt(i)
      hi = c >> 8
      lo = c % 256
      byteArray.push(lo)
      byteArray.push(hi)
    }
  
    return byteArray
  }
  
  function base64ToBytes (str) {
    return base64.toByteArray(base64clean(str))
  }
  
  function blitBuffer (src, dst, offset, length) {
    for (var i = 0; i < length; ++i) {
      if ((i + offset >= dst.length) || (i >= src.length)) break
      dst[i + offset] = src[i]
    }
    return i
  }
  
  function isnan (val) {
    return val !== val // eslint-disable-line no-self-compare
  }
  
  },{"base64-js":126,"ieee754":132}],130:[function(require,module,exports){
  (function (Buffer){
  // Copyright Joyent, Inc. and other Node 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.
  
  // NOTE: These type checking functions intentionally don't use `instanceof`
  // because it is fragile and can be easily faked with `Object.create()`.
  
  function isArray(arg) {
    if (Array.isArray) {
      return Array.isArray(arg);
    }
    return objectToString(arg) === '[object Array]';
  }
  exports.isArray = isArray;
  
  function isBoolean(arg) {
    return typeof arg === 'boolean';
  }
  exports.isBoolean = isBoolean;
  
  function isNull(arg) {
    return arg === null;
  }
  exports.isNull = isNull;
  
  function isNullOrUndefined(arg) {
    return arg == null;
  }
  exports.isNullOrUndefined = isNullOrUndefined;
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  exports.isNumber = isNumber;
  
  function isString(arg) {
    return typeof arg === 'string';
  }
  exports.isString = isString;
  
  function isSymbol(arg) {
    return typeof arg === 'symbol';
  }
  exports.isSymbol = isSymbol;
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  exports.isUndefined = isUndefined;
  
  function isRegExp(re) {
    return objectToString(re) === '[object RegExp]';
  }
  exports.isRegExp = isRegExp;
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  exports.isObject = isObject;
  
  function isDate(d) {
    return objectToString(d) === '[object Date]';
  }
  exports.isDate = isDate;
  
  function isError(e) {
    return (objectToString(e) === '[object Error]' || e instanceof Error);
  }
  exports.isError = isError;
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  exports.isFunction = isFunction;
  
  function isPrimitive(arg) {
    return arg === null ||
           typeof arg === 'boolean' ||
           typeof arg === 'number' ||
           typeof arg === 'string' ||
           typeof arg === 'symbol' ||  // ES6 symbol
           typeof arg === 'undefined';
  }
  exports.isPrimitive = isPrimitive;
  
  exports.isBuffer = Buffer.isBuffer;
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  }).call(this,{"isBuffer":require("../../is-buffer/index.js")})
  },{"../../is-buffer/index.js":134}],131:[function(require,module,exports){
  // Copyright Joyent, Inc. and other Node 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.
  
  function EventEmitter() {
    this._events = this._events || {};
    this._maxListeners = this._maxListeners || undefined;
  }
  module.exports = EventEmitter;
  
  // Backwards-compat with node 0.10.x
  EventEmitter.EventEmitter = EventEmitter;
  
  EventEmitter.prototype._events = undefined;
  EventEmitter.prototype._maxListeners = undefined;
  
  // By default EventEmitters will print a warning if more than 10 listeners are
  // added to it. This is a useful default which helps finding memory leaks.
  EventEmitter.defaultMaxListeners = 10;
  
  // Obviously not all Emitters should be limited to 10. This function allows
  // that to be increased. Set to zero for unlimited.
  EventEmitter.prototype.setMaxListeners = function(n) {
    if (!isNumber(n) || n < 0 || isNaN(n))
      throw TypeError('n must be a positive number');
    this._maxListeners = n;
    return this;
  };
  
  EventEmitter.prototype.emit = function(type) {
    var er, handler, len, args, i, listeners;
  
    if (!this._events)
      this._events = {};
  
    // If there is no 'error' event listener then throw.
    if (type === 'error') {
      if (!this._events.error ||
          (isObject(this._events.error) && !this._events.error.length)) {
        er = arguments[1];
        if (er instanceof Error) {
          throw er; // Unhandled 'error' event
        } else {
          // At least give some kind of context to the user
          var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
          err.context = er;
          throw err;
        }
      }
    }
  
    handler = this._events[type];
  
    if (isUndefined(handler))
      return false;
  
    if (isFunction(handler)) {
      switch (arguments.length) {
        // fast cases
        case 1:
          handler.call(this);
          break;
        case 2:
          handler.call(this, arguments[1]);
          break;
        case 3:
          handler.call(this, arguments[1], arguments[2]);
          break;
        // slower
        default:
          args = Array.prototype.slice.call(arguments, 1);
          handler.apply(this, args);
      }
    } else if (isObject(handler)) {
      args = Array.prototype.slice.call(arguments, 1);
      listeners = handler.slice();
      len = listeners.length;
      for (i = 0; i < len; i++)
        listeners[i].apply(this, args);
    }
  
    return true;
  };
  
  EventEmitter.prototype.addListener = function(type, listener) {
    var m;
  
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    if (!this._events)
      this._events = {};
  
    // To avoid recursion in the case that type === "newListener"! Before
    // adding it to the listeners, first emit "newListener".
    if (this._events.newListener)
      this.emit('newListener', type,
                isFunction(listener.listener) ?
                listener.listener : listener);
  
    if (!this._events[type])
      // Optimize the case of one listener. Don't need the extra array object.
      this._events[type] = listener;
    else if (isObject(this._events[type]))
      // If we've already got an array, just append.
      this._events[type].push(listener);
    else
      // Adding the second element, need to change to array.
      this._events[type] = [this._events[type], listener];
  
    // Check for listener leak
    if (isObject(this._events[type]) && !this._events[type].warned) {
      if (!isUndefined(this._maxListeners)) {
        m = this._maxListeners;
      } else {
        m = EventEmitter.defaultMaxListeners;
      }
  
      if (m && m > 0 && this._events[type].length > m) {
        this._events[type].warned = true;
        console.error('(node) warning: possible EventEmitter memory ' +
                      'leak detected. %d listeners added. ' +
                      'Use emitter.setMaxListeners() to increase limit.',
                      this._events[type].length);
        if (typeof console.trace === 'function') {
          // not supported in IE 10
          console.trace();
        }
      }
    }
  
    return this;
  };
  
  EventEmitter.prototype.on = EventEmitter.prototype.addListener;
  
  EventEmitter.prototype.once = function(type, listener) {
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    var fired = false;
  
    function g() {
      this.removeListener(type, g);
  
      if (!fired) {
        fired = true;
        listener.apply(this, arguments);
      }
    }
  
    g.listener = listener;
    this.on(type, g);
  
    return this;
  };
  
  // emits a 'removeListener' event iff the listener was removed
  EventEmitter.prototype.removeListener = function(type, listener) {
    var list, position, length, i;
  
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    if (!this._events || !this._events[type])
      return this;
  
    list = this._events[type];
    length = list.length;
    position = -1;
  
    if (list === listener ||
        (isFunction(list.listener) && list.listener === listener)) {
      delete this._events[type];
      if (this._events.removeListener)
        this.emit('removeListener', type, listener);
  
    } else if (isObject(list)) {
      for (i = length; i-- > 0;) {
        if (list[i] === listener ||
            (list[i].listener && list[i].listener === listener)) {
          position = i;
          break;
        }
      }
  
      if (position < 0)
        return this;
  
      if (list.length === 1) {
        list.length = 0;
        delete this._events[type];
      } else {
        list.splice(position, 1);
      }
  
      if (this._events.removeListener)
        this.emit('removeListener', type, listener);
    }
  
    return this;
  };
  
  EventEmitter.prototype.removeAllListeners = function(type) {
    var key, listeners;
  
    if (!this._events)
      return this;
  
    // not listening for removeListener, no need to emit
    if (!this._events.removeListener) {
      if (arguments.length === 0)
        this._events = {};
      else if (this._events[type])
        delete this._events[type];
      return this;
    }
  
    // emit removeListener for all listeners on all events
    if (arguments.length === 0) {
      for (key in this._events) {
        if (key === 'removeListener') continue;
        this.removeAllListeners(key);
      }
      this.removeAllListeners('removeListener');
      this._events = {};
      return this;
    }
  
    listeners = this._events[type];
  
    if (isFunction(listeners)) {
      this.removeListener(type, listeners);
    } else if (listeners) {
      // LIFO order
      while (listeners.length)
        this.removeListener(type, listeners[listeners.length - 1]);
    }
    delete this._events[type];
  
    return this;
  };
  
  EventEmitter.prototype.listeners = function(type) {
    var ret;
    if (!this._events || !this._events[type])
      ret = [];
    else if (isFunction(this._events[type]))
      ret = [this._events[type]];
    else
      ret = this._events[type].slice();
    return ret;
  };
  
  EventEmitter.prototype.listenerCount = function(type) {
    if (this._events) {
      var evlistener = this._events[type];
  
      if (isFunction(evlistener))
        return 1;
      else if (evlistener)
        return evlistener.length;
    }
    return 0;
  };
  
  EventEmitter.listenerCount = function(emitter, type) {
    return emitter.listenerCount(type);
  };
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  
  },{}],132:[function(require,module,exports){
  arguments[4][67][0].apply(exports,arguments)
  },{"dup":67}],133:[function(require,module,exports){
  if (typeof Object.create === 'function') {
    // implementation from standard node.js 'util' module
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      ctor.prototype = Object.create(superCtor.prototype, {
        constructor: {
          value: ctor,
          enumerable: false,
          writable: true,
          configurable: true
        }
      });
    };
  } else {
    // old school shim for old browsers
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      var TempCtor = function () {}
      TempCtor.prototype = superCtor.prototype
      ctor.prototype = new TempCtor()
      ctor.prototype.constructor = ctor
    }
  }
  
  },{}],134:[function(require,module,exports){
  /*!
   * Determine if an object is a Buffer
   *
   * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
   * @license  MIT
   */
  
  // The _isBuffer check is for Safari 5-7 support, because it's missing
  // Object.prototype.constructor. Remove this eventually
  module.exports = function (obj) {
    return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
  }
  
  function isBuffer (obj) {
    return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
  }
  
  // For Node v0.10 support. Remove this eventually.
  function isSlowBuffer (obj) {
    return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
  }
  
  },{}],135:[function(require,module,exports){
  arguments[4][69][0].apply(exports,arguments)
  },{"dup":69}],136:[function(require,module,exports){
  (function (process){
  'use strict';
  
  if (!process.version ||
      process.version.indexOf('v0.') === 0 ||
      process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) {
    module.exports = nextTick;
  } else {
    module.exports = process.nextTick;
  }
  
  function nextTick(fn, arg1, arg2, arg3) {
    if (typeof fn !== 'function') {
      throw new TypeError('"callback" argument must be a function');
    }
    var len = arguments.length;
    var args, i;
    switch (len) {
    case 0:
    case 1:
      return process.nextTick(fn);
    case 2:
      return process.nextTick(function afterTickOne() {
        fn.call(null, arg1);
      });
    case 3:
      return process.nextTick(function afterTickTwo() {
        fn.call(null, arg1, arg2);
      });
    case 4:
      return process.nextTick(function afterTickThree() {
        fn.call(null, arg1, arg2, arg3);
      });
    default:
      args = new Array(len - 1);
      i = 0;
      while (i < args.length) {
        args[i++] = arguments[i];
      }
      return process.nextTick(function afterTick() {
        fn.apply(null, args);
      });
    }
  }
  
  }).call(this,require('_process'))
  },{"_process":137}],137:[function(require,module,exports){
  // shim for using process in browser
  var process = module.exports = {};
  
  // cached from whatever global is present so that test runners that stub it
  // don't break things.  But we need to wrap it in a try catch in case it is
  // wrapped in strict mode code which doesn't define any globals.  It's inside a
  // function because try/catches deoptimize in certain engines.
  
  var cachedSetTimeout;
  var cachedClearTimeout;
  
  function defaultSetTimout() {
      throw new Error('setTimeout has not been defined');
  }
  function defaultClearTimeout () {
      throw new Error('clearTimeout has not been defined');
  }
  (function () {
      try {
          if (typeof setTimeout === 'function') {
              cachedSetTimeout = setTimeout;
          } else {
              cachedSetTimeout = defaultSetTimout;
          }
      } catch (e) {
          cachedSetTimeout = defaultSetTimout;
      }
      try {
          if (typeof clearTimeout === 'function') {
              cachedClearTimeout = clearTimeout;
          } else {
              cachedClearTimeout = defaultClearTimeout;
          }
      } catch (e) {
          cachedClearTimeout = defaultClearTimeout;
      }
  } ())
  function runTimeout(fun) {
      if (cachedSetTimeout === setTimeout) {
          //normal enviroments in sane situations
          return setTimeout(fun, 0);
      }
      // if setTimeout wasn't available but was latter defined
      if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
          cachedSetTimeout = setTimeout;
          return setTimeout(fun, 0);
      }
      try {
          // when when somebody has screwed with setTimeout but no I.E. maddness
          return cachedSetTimeout(fun, 0);
      } catch(e){
          try {
              // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
              return cachedSetTimeout.call(null, fun, 0);
          } catch(e){
              // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
              return cachedSetTimeout.call(this, fun, 0);
          }
      }
  
  
  }
  function runClearTimeout(marker) {
      if (cachedClearTimeout === clearTimeout) {
          //normal enviroments in sane situations
          return clearTimeout(marker);
      }
      // if clearTimeout wasn't available but was latter defined
      if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
          cachedClearTimeout = clearTimeout;
          return clearTimeout(marker);
      }
      try {
          // when when somebody has screwed with setTimeout but no I.E. maddness
          return cachedClearTimeout(marker);
      } catch (e){
          try {
              // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
              return cachedClearTimeout.call(null, marker);
          } catch (e){
              // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
              // Some versions of I.E. have different rules for clearTimeout vs setTimeout
              return cachedClearTimeout.call(this, marker);
          }
      }
  
  
  
  }
  var queue = [];
  var draining = false;
  var currentQueue;
  var queueIndex = -1;
  
  function cleanUpNextTick() {
      if (!draining || !currentQueue) {
          return;
      }
      draining = false;
      if (currentQueue.length) {
          queue = currentQueue.concat(queue);
      } else {
          queueIndex = -1;
      }
      if (queue.length) {
          drainQueue();
      }
  }
  
  function drainQueue() {
      if (draining) {
          return;
      }
      var timeout = runTimeout(cleanUpNextTick);
      draining = true;
  
      var len = queue.length;
      while(len) {
          currentQueue = queue;
          queue = [];
          while (++queueIndex < len) {
              if (currentQueue) {
                  currentQueue[queueIndex].run();
              }
          }
          queueIndex = -1;
          len = queue.length;
      }
      currentQueue = null;
      draining = false;
      runClearTimeout(timeout);
  }
  
  process.nextTick = function (fun) {
      var args = new Array(arguments.length - 1);
      if (arguments.length > 1) {
          for (var i = 1; i < arguments.length; i++) {
              args[i - 1] = arguments[i];
          }
      }
      queue.push(new Item(fun, args));
      if (queue.length === 1 && !draining) {
          runTimeout(drainQueue);
      }
  };
  
  // v8 likes predictible objects
  function Item(fun, array) {
      this.fun = fun;
      this.array = array;
  }
  Item.prototype.run = function () {
      this.fun.apply(null, this.array);
  };
  process.title = 'browser';
  process.browser = true;
  process.env = {};
  process.argv = [];
  process.version = ''; // empty string to avoid regexp issues
  process.versions = {};
  
  function noop() {}
  
  process.on = noop;
  process.addListener = noop;
  process.once = noop;
  process.off = noop;
  process.removeListener = noop;
  process.removeAllListeners = noop;
  process.emit = noop;
  
  process.binding = function (name) {
      throw new Error('process.binding is not supported');
  };
  
  process.cwd = function () { return '/' };
  process.chdir = function (dir) {
      throw new Error('process.chdir is not supported');
  };
  process.umask = function() { return 0; };
  
  },{}],138:[function(require,module,exports){
  (function (global){
  /*! https://mths.be/punycode v1.4.1 by @mathias */
  ;(function(root) {
  
  	/** Detect free variables */
  	var freeExports = typeof exports == 'object' && exports &&
  		!exports.nodeType && exports;
  	var freeModule = typeof module == 'object' && module &&
  		!module.nodeType && module;
  	var freeGlobal = typeof global == 'object' && global;
  	if (
  		freeGlobal.global === freeGlobal ||
  		freeGlobal.window === freeGlobal ||
  		freeGlobal.self === freeGlobal
  	) {
  		root = freeGlobal;
  	}
  
  	/**
  	 * The `punycode` object.
  	 * @name punycode
  	 * @type Object
  	 */
  	var punycode,
  
  	/** Highest positive signed 32-bit float value */
  	maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
  
  	/** Bootstring parameters */
  	base = 36,
  	tMin = 1,
  	tMax = 26,
  	skew = 38,
  	damp = 700,
  	initialBias = 72,
  	initialN = 128, // 0x80
  	delimiter = '-', // '\x2D'
  
  	/** Regular expressions */
  	regexPunycode = /^xn--/,
  	regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
  	regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
  
  	/** Error messages */
  	errors = {
  		'overflow': 'Overflow: input needs wider integers to process',
  		'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
  		'invalid-input': 'Invalid input'
  	},
  
  	/** Convenience shortcuts */
  	baseMinusTMin = base - tMin,
  	floor = Math.floor,
  	stringFromCharCode = String.fromCharCode,
  
  	/** Temporary variable */
  	key;
  
  	/*--------------------------------------------------------------------------*/
  
  	/**
  	 * A generic error utility function.
  	 * @private
  	 * @param {String} type The error type.
  	 * @returns {Error} Throws a `RangeError` with the applicable error message.
  	 */
  	function error(type) {
  		throw new RangeError(errors[type]);
  	}
  
  	/**
  	 * A generic `Array#map` utility function.
  	 * @private
  	 * @param {Array} array The array to iterate over.
  	 * @param {Function} callback The function that gets called for every array
  	 * item.
  	 * @returns {Array} A new array of values returned by the callback function.
  	 */
  	function map(array, fn) {
  		var length = array.length;
  		var result = [];
  		while (length--) {
  			result[length] = fn(array[length]);
  		}
  		return result;
  	}
  
  	/**
  	 * A simple `Array#map`-like wrapper to work with domain name strings or email
  	 * addresses.
  	 * @private
  	 * @param {String} domain The domain name or email address.
  	 * @param {Function} callback The function that gets called for every
  	 * character.
  	 * @returns {Array} A new string of characters returned by the callback
  	 * function.
  	 */
  	function mapDomain(string, fn) {
  		var parts = string.split('@');
  		var result = '';
  		if (parts.length > 1) {
  			// In email addresses, only the domain name should be punycoded. Leave
  			// the local part (i.e. everything up to `@`) intact.
  			result = parts[0] + '@';
  			string = parts[1];
  		}
  		// Avoid `split(regex)` for IE8 compatibility. See #17.
  		string = string.replace(regexSeparators, '\x2E');
  		var labels = string.split('.');
  		var encoded = map(labels, fn).join('.');
  		return result + encoded;
  	}
  
  	/**
  	 * Creates an array containing the numeric code points of each Unicode
  	 * character in the string. While JavaScript uses UCS-2 internally,
  	 * this function will convert a pair of surrogate halves (each of which
  	 * UCS-2 exposes as separate characters) into a single code point,
  	 * matching UTF-16.
  	 * @see `punycode.ucs2.encode`
  	 * @see <https://mathiasbynens.be/notes/javascript-encoding>
  	 * @memberOf punycode.ucs2
  	 * @name decode
  	 * @param {String} string The Unicode input string (UCS-2).
  	 * @returns {Array} The new array of code points.
  	 */
  	function ucs2decode(string) {
  		var output = [],
  		    counter = 0,
  		    length = string.length,
  		    value,
  		    extra;
  		while (counter < length) {
  			value = string.charCodeAt(counter++);
  			if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
  				// high surrogate, and there is a next character
  				extra = string.charCodeAt(counter++);
  				if ((extra & 0xFC00) == 0xDC00) { // low surrogate
  					output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
  				} else {
  					// unmatched surrogate; only append this code unit, in case the next
  					// code unit is the high surrogate of a surrogate pair
  					output.push(value);
  					counter--;
  				}
  			} else {
  				output.push(value);
  			}
  		}
  		return output;
  	}
  
  	/**
  	 * Creates a string based on an array of numeric code points.
  	 * @see `punycode.ucs2.decode`
  	 * @memberOf punycode.ucs2
  	 * @name encode
  	 * @param {Array} codePoints The array of numeric code points.
  	 * @returns {String} The new Unicode string (UCS-2).
  	 */
  	function ucs2encode(array) {
  		return map(array, function(value) {
  			var output = '';
  			if (value > 0xFFFF) {
  				value -= 0x10000;
  				output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
  				value = 0xDC00 | value & 0x3FF;
  			}
  			output += stringFromCharCode(value);
  			return output;
  		}).join('');
  	}
  
  	/**
  	 * Converts a basic code point into a digit/integer.
  	 * @see `digitToBasic()`
  	 * @private
  	 * @param {Number} codePoint The basic numeric code point value.
  	 * @returns {Number} The numeric value of a basic code point (for use in
  	 * representing integers) in the range `0` to `base - 1`, or `base` if
  	 * the code point does not represent a value.
  	 */
  	function basicToDigit(codePoint) {
  		if (codePoint - 48 < 10) {
  			return codePoint - 22;
  		}
  		if (codePoint - 65 < 26) {
  			return codePoint - 65;
  		}
  		if (codePoint - 97 < 26) {
  			return codePoint - 97;
  		}
  		return base;
  	}
  
  	/**
  	 * Converts a digit/integer into a basic code point.
  	 * @see `basicToDigit()`
  	 * @private
  	 * @param {Number} digit The numeric value of a basic code point.
  	 * @returns {Number} The basic code point whose value (when used for
  	 * representing integers) is `digit`, which needs to be in the range
  	 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
  	 * used; else, the lowercase form is used. The behavior is undefined
  	 * if `flag` is non-zero and `digit` has no uppercase form.
  	 */
  	function digitToBasic(digit, flag) {
  		//  0..25 map to ASCII a..z or A..Z
  		// 26..35 map to ASCII 0..9
  		return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
  	}
  
  	/**
  	 * Bias adaptation function as per section 3.4 of RFC 3492.
  	 * https://tools.ietf.org/html/rfc3492#section-3.4
  	 * @private
  	 */
  	function adapt(delta, numPoints, firstTime) {
  		var k = 0;
  		delta = firstTime ? floor(delta / damp) : delta >> 1;
  		delta += floor(delta / numPoints);
  		for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
  			delta = floor(delta / baseMinusTMin);
  		}
  		return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
  	}
  
  	/**
  	 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
  	 * symbols.
  	 * @memberOf punycode
  	 * @param {String} input The Punycode string of ASCII-only symbols.
  	 * @returns {String} The resulting string of Unicode symbols.
  	 */
  	function decode(input) {
  		// Don't use UCS-2
  		var output = [],
  		    inputLength = input.length,
  		    out,
  		    i = 0,
  		    n = initialN,
  		    bias = initialBias,
  		    basic,
  		    j,
  		    index,
  		    oldi,
  		    w,
  		    k,
  		    digit,
  		    t,
  		    /** Cached calculation results */
  		    baseMinusT;
  
  		// Handle the basic code points: let `basic` be the number of input code
  		// points before the last delimiter, or `0` if there is none, then copy
  		// the first basic code points to the output.
  
  		basic = input.lastIndexOf(delimiter);
  		if (basic < 0) {
  			basic = 0;
  		}
  
  		for (j = 0; j < basic; ++j) {
  			// if it's not a basic code point
  			if (input.charCodeAt(j) >= 0x80) {
  				error('not-basic');
  			}
  			output.push(input.charCodeAt(j));
  		}
  
  		// Main decoding loop: start just after the last delimiter if any basic code
  		// points were copied; start at the beginning otherwise.
  
  		for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
  
  			// `index` is the index of the next character to be consumed.
  			// Decode a generalized variable-length integer into `delta`,
  			// which gets added to `i`. The overflow checking is easier
  			// if we increase `i` as we go, then subtract off its starting
  			// value at the end to obtain `delta`.
  			for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
  
  				if (index >= inputLength) {
  					error('invalid-input');
  				}
  
  				digit = basicToDigit(input.charCodeAt(index++));
  
  				if (digit >= base || digit > floor((maxInt - i) / w)) {
  					error('overflow');
  				}
  
  				i += digit * w;
  				t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  
  				if (digit < t) {
  					break;
  				}
  
  				baseMinusT = base - t;
  				if (w > floor(maxInt / baseMinusT)) {
  					error('overflow');
  				}
  
  				w *= baseMinusT;
  
  			}
  
  			out = output.length + 1;
  			bias = adapt(i - oldi, out, oldi == 0);
  
  			// `i` was supposed to wrap around from `out` to `0`,
  			// incrementing `n` each time, so we'll fix that now:
  			if (floor(i / out) > maxInt - n) {
  				error('overflow');
  			}
  
  			n += floor(i / out);
  			i %= out;
  
  			// Insert `n` at position `i` of the output
  			output.splice(i++, 0, n);
  
  		}
  
  		return ucs2encode(output);
  	}
  
  	/**
  	 * Converts a string of Unicode symbols (e.g. a domain name label) to a
  	 * Punycode string of ASCII-only symbols.
  	 * @memberOf punycode
  	 * @param {String} input The string of Unicode symbols.
  	 * @returns {String} The resulting Punycode string of ASCII-only symbols.
  	 */
  	function encode(input) {
  		var n,
  		    delta,
  		    handledCPCount,
  		    basicLength,
  		    bias,
  		    j,
  		    m,
  		    q,
  		    k,
  		    t,
  		    currentValue,
  		    output = [],
  		    /** `inputLength` will hold the number of code points in `input`. */
  		    inputLength,
  		    /** Cached calculation results */
  		    handledCPCountPlusOne,
  		    baseMinusT,
  		    qMinusT;
  
  		// Convert the input in UCS-2 to Unicode
  		input = ucs2decode(input);
  
  		// Cache the length
  		inputLength = input.length;
  
  		// Initialize the state
  		n = initialN;
  		delta = 0;
  		bias = initialBias;
  
  		// Handle the basic code points
  		for (j = 0; j < inputLength; ++j) {
  			currentValue = input[j];
  			if (currentValue < 0x80) {
  				output.push(stringFromCharCode(currentValue));
  			}
  		}
  
  		handledCPCount = basicLength = output.length;
  
  		// `handledCPCount` is the number of code points that have been handled;
  		// `basicLength` is the number of basic code points.
  
  		// Finish the basic string - if it is not empty - with a delimiter
  		if (basicLength) {
  			output.push(delimiter);
  		}
  
  		// Main encoding loop:
  		while (handledCPCount < inputLength) {
  
  			// All non-basic code points < n have been handled already. Find the next
  			// larger one:
  			for (m = maxInt, j = 0; j < inputLength; ++j) {
  				currentValue = input[j];
  				if (currentValue >= n && currentValue < m) {
  					m = currentValue;
  				}
  			}
  
  			// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
  			// but guard against overflow
  			handledCPCountPlusOne = handledCPCount + 1;
  			if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
  				error('overflow');
  			}
  
  			delta += (m - n) * handledCPCountPlusOne;
  			n = m;
  
  			for (j = 0; j < inputLength; ++j) {
  				currentValue = input[j];
  
  				if (currentValue < n && ++delta > maxInt) {
  					error('overflow');
  				}
  
  				if (currentValue == n) {
  					// Represent delta as a generalized variable-length integer
  					for (q = delta, k = base; /* no condition */; k += base) {
  						t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  						if (q < t) {
  							break;
  						}
  						qMinusT = q - t;
  						baseMinusT = base - t;
  						output.push(
  							stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
  						);
  						q = floor(qMinusT / baseMinusT);
  					}
  
  					output.push(stringFromCharCode(digitToBasic(q, 0)));
  					bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
  					delta = 0;
  					++handledCPCount;
  				}
  			}
  
  			++delta;
  			++n;
  
  		}
  		return output.join('');
  	}
  
  	/**
  	 * Converts a Punycode string representing a domain name or an email address
  	 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
  	 * it doesn't matter if you call it on a string that has already been
  	 * converted to Unicode.
  	 * @memberOf punycode
  	 * @param {String} input The Punycoded domain name or email address to
  	 * convert to Unicode.
  	 * @returns {String} The Unicode representation of the given Punycode
  	 * string.
  	 */
  	function toUnicode(input) {
  		return mapDomain(input, function(string) {
  			return regexPunycode.test(string)
  				? decode(string.slice(4).toLowerCase())
  				: string;
  		});
  	}
  
  	/**
  	 * Converts a Unicode string representing a domain name or an email address to
  	 * Punycode. Only the non-ASCII parts of the domain name will be converted,
  	 * i.e. it doesn't matter if you call it with a domain that's already in
  	 * ASCII.
  	 * @memberOf punycode
  	 * @param {String} input The domain name or email address to convert, as a
  	 * Unicode string.
  	 * @returns {String} The Punycode representation of the given domain name or
  	 * email address.
  	 */
  	function toASCII(input) {
  		return mapDomain(input, function(string) {
  			return regexNonASCII.test(string)
  				? 'xn--' + encode(string)
  				: string;
  		});
  	}
  
  	/*--------------------------------------------------------------------------*/
  
  	/** Define the public API */
  	punycode = {
  		/**
  		 * A string representing the current Punycode.js version number.
  		 * @memberOf punycode
  		 * @type String
  		 */
  		'version': '1.4.1',
  		/**
  		 * An object of methods to convert from JavaScript's internal character
  		 * representation (UCS-2) to Unicode code points, and back.
  		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
  		 * @memberOf punycode
  		 * @type Object
  		 */
  		'ucs2': {
  			'decode': ucs2decode,
  			'encode': ucs2encode
  		},
  		'decode': decode,
  		'encode': encode,
  		'toASCII': toASCII,
  		'toUnicode': toUnicode
  	};
  
  	/** Expose `punycode` */
  	// Some AMD build optimizers, like r.js, check for specific condition patterns
  	// like the following:
  	if (
  		typeof define == 'function' &&
  		typeof define.amd == 'object' &&
  		define.amd
  	) {
  		define('punycode', function() {
  			return punycode;
  		});
  	} else if (freeExports && freeModule) {
  		if (module.exports == freeExports) {
  			// in Node.js, io.js, or RingoJS v0.8.0+
  			freeModule.exports = punycode;
  		} else {
  			// in Narwhal or RingoJS v0.7.0-
  			for (key in punycode) {
  				punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
  			}
  		}
  	} else {
  		// in Rhino or a web browser
  		root.punycode = punycode;
  	}
  
  }(this));
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],139:[function(require,module,exports){
  // Copyright Joyent, Inc. and other Node 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.
  
  'use strict';
  
  // If obj.hasOwnProperty has been overridden, then calling
  // obj.hasOwnProperty(prop) will break.
  // See: https://github.com/joyent/node/issues/1707
  function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }
  
  module.exports = function(qs, sep, eq, options) {
    sep = sep || '&';
    eq = eq || '=';
    var obj = {};
  
    if (typeof qs !== 'string' || qs.length === 0) {
      return obj;
    }
  
    var regexp = /\+/g;
    qs = qs.split(sep);
  
    var maxKeys = 1000;
    if (options && typeof options.maxKeys === 'number') {
      maxKeys = options.maxKeys;
    }
  
    var len = qs.length;
    // maxKeys <= 0 means that we should not limit keys count
    if (maxKeys > 0 && len > maxKeys) {
      len = maxKeys;
    }
  
    for (var i = 0; i < len; ++i) {
      var x = qs[i].replace(regexp, '%20'),
          idx = x.indexOf(eq),
          kstr, vstr, k, v;
  
      if (idx >= 0) {
        kstr = x.substr(0, idx);
        vstr = x.substr(idx + 1);
      } else {
        kstr = x;
        vstr = '';
      }
  
      k = decodeURIComponent(kstr);
      v = decodeURIComponent(vstr);
  
      if (!hasOwnProperty(obj, k)) {
        obj[k] = v;
      } else if (isArray(obj[k])) {
        obj[k].push(v);
      } else {
        obj[k] = [obj[k], v];
      }
    }
  
    return obj;
  };
  
  var isArray = Array.isArray || function (xs) {
    return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  },{}],140:[function(require,module,exports){
  // Copyright Joyent, Inc. and other Node 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.
  
  'use strict';
  
  var stringifyPrimitive = function(v) {
    switch (typeof v) {
      case 'string':
        return v;
  
      case 'boolean':
        return v ? 'true' : 'false';
  
      case 'number':
        return isFinite(v) ? v : '';
  
      default:
        return '';
    }
  };
  
  module.exports = function(obj, sep, eq, name) {
    sep = sep || '&';
    eq = eq || '=';
    if (obj === null) {
      obj = undefined;
    }
  
    if (typeof obj === 'object') {
      return map(objectKeys(obj), function(k) {
        var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
        if (isArray(obj[k])) {
          return map(obj[k], function(v) {
            return ks + encodeURIComponent(stringifyPrimitive(v));
          }).join(sep);
        } else {
          return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
        }
      }).join(sep);
  
    }
  
    if (!name) return '';
    return encodeURIComponent(stringifyPrimitive(name)) + eq +
           encodeURIComponent(stringifyPrimitive(obj));
  };
  
  var isArray = Array.isArray || function (xs) {
    return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  function map (xs, f) {
    if (xs.map) return xs.map(f);
    var res = [];
    for (var i = 0; i < xs.length; i++) {
      res.push(f(xs[i], i));
    }
    return res;
  }
  
  var objectKeys = Object.keys || function (obj) {
    var res = [];
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
    }
    return res;
  };
  
  },{}],141:[function(require,module,exports){
  'use strict';
  
  exports.decode = exports.parse = require('./decode');
  exports.encode = exports.stringify = require('./encode');
  
  },{"./decode":139,"./encode":140}],142:[function(require,module,exports){
  module.exports = require("./lib/_stream_duplex.js")
  
  },{"./lib/_stream_duplex.js":143}],143:[function(require,module,exports){
  // a duplex stream is just a stream that is both readable and writable.
  // Since JS doesn't have multiple prototypal inheritance, this class
  // prototypally inherits from Readable, and then parasitically from
  // Writable.
  
  'use strict';
  
  /*<replacement>*/
  
  var objectKeys = Object.keys || function (obj) {
    var keys = [];
    for (var key in obj) {
      keys.push(key);
    }return keys;
  };
  /*</replacement>*/
  
  module.exports = Duplex;
  
  /*<replacement>*/
  var processNextTick = require('process-nextick-args');
  /*</replacement>*/
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  var Readable = require('./_stream_readable');
  var Writable = require('./_stream_writable');
  
  util.inherits(Duplex, Readable);
  
  var keys = objectKeys(Writable.prototype);
  for (var v = 0; v < keys.length; v++) {
    var method = keys[v];
    if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
  }
  
  function Duplex(options) {
    if (!(this instanceof Duplex)) return new Duplex(options);
  
    Readable.call(this, options);
    Writable.call(this, options);
  
    if (options && options.readable === false) this.readable = false;
  
    if (options && options.writable === false) this.writable = false;
  
    this.allowHalfOpen = true;
    if (options && options.allowHalfOpen === false) this.allowHalfOpen = false;
  
    this.once('end', onend);
  }
  
  // the no-half-open enforcer
  function onend() {
    // if we allow half-open state, or if the writable side ended,
    // then we're ok.
    if (this.allowHalfOpen || this._writableState.ended) return;
  
    // no more data can be written.
    // But allow more writes to happen in this tick.
    processNextTick(onEndNT, this);
  }
  
  function onEndNT(self) {
    self.end();
  }
  
  function forEach(xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  },{"./_stream_readable":145,"./_stream_writable":147,"core-util-is":130,"inherits":133,"process-nextick-args":136}],144:[function(require,module,exports){
  // a passthrough stream.
  // basically just the most minimal sort of Transform stream.
  // Every written chunk gets output as-is.
  
  'use strict';
  
  module.exports = PassThrough;
  
  var Transform = require('./_stream_transform');
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  util.inherits(PassThrough, Transform);
  
  function PassThrough(options) {
    if (!(this instanceof PassThrough)) return new PassThrough(options);
  
    Transform.call(this, options);
  }
  
  PassThrough.prototype._transform = function (chunk, encoding, cb) {
    cb(null, chunk);
  };
  },{"./_stream_transform":146,"core-util-is":130,"inherits":133}],145:[function(require,module,exports){
  (function (process){
  'use strict';
  
  module.exports = Readable;
  
  /*<replacement>*/
  var processNextTick = require('process-nextick-args');
  /*</replacement>*/
  
  /*<replacement>*/
  var isArray = require('isarray');
  /*</replacement>*/
  
  /*<replacement>*/
  var Duplex;
  /*</replacement>*/
  
  Readable.ReadableState = ReadableState;
  
  /*<replacement>*/
  var EE = require('events').EventEmitter;
  
  var EElistenerCount = function (emitter, type) {
    return emitter.listeners(type).length;
  };
  /*</replacement>*/
  
  /*<replacement>*/
  var Stream;
  (function () {
    try {
      Stream = require('st' + 'ream');
    } catch (_) {} finally {
      if (!Stream) Stream = require('events').EventEmitter;
    }
  })();
  /*</replacement>*/
  
  var Buffer = require('buffer').Buffer;
  /*<replacement>*/
  var bufferShim = require('buffer-shims');
  /*</replacement>*/
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  /*<replacement>*/
  var debugUtil = require('util');
  var debug = void 0;
  if (debugUtil && debugUtil.debuglog) {
    debug = debugUtil.debuglog('stream');
  } else {
    debug = function () {};
  }
  /*</replacement>*/
  
  var BufferList = require('./internal/streams/BufferList');
  var StringDecoder;
  
  util.inherits(Readable, Stream);
  
  function prependListener(emitter, event, fn) {
    // Sadly this is not cacheable as some libraries bundle their own
    // event emitter implementation with them.
    if (typeof emitter.prependListener === 'function') {
      return emitter.prependListener(event, fn);
    } else {
      // This is a hack to make sure that our error handler is attached before any
      // userland ones.  NEVER DO THIS. This is here only because this code needs
      // to continue to work with older versions of Node.js that do not include
      // the prependListener() method. The goal is to eventually remove this hack.
      if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]];
    }
  }
  
  function ReadableState(options, stream) {
    Duplex = Duplex || require('./_stream_duplex');
  
    options = options || {};
  
    // object stream flag. Used to make read(n) ignore n and to
    // make all the buffer merging and length checks go away
    this.objectMode = !!options.objectMode;
  
    if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.readableObjectMode;
  
    // the point at which it stops calling _read() to fill the buffer
    // Note: 0 is a valid value, means "don't call _read preemptively ever"
    var hwm = options.highWaterMark;
    var defaultHwm = this.objectMode ? 16 : 16 * 1024;
    this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    // A linked list is used to store data chunks instead of an array because the
    // linked list can remove elements from the beginning faster than
    // array.shift()
    this.buffer = new BufferList();
    this.length = 0;
    this.pipes = null;
    this.pipesCount = 0;
    this.flowing = null;
    this.ended = false;
    this.endEmitted = false;
    this.reading = false;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, because any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // whenever we return null, then we set a flag to say
    // that we're awaiting a 'readable' event emission.
    this.needReadable = false;
    this.emittedReadable = false;
    this.readableListening = false;
    this.resumeScheduled = false;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // when piping, we only care about 'readable' events that happen
    // after read()ing all the bytes and not getting any pushback.
    this.ranOut = false;
  
    // the number of writers that are awaiting a drain event in .pipe()s
    this.awaitDrain = 0;
  
    // if true, a maybeReadMore has been scheduled
    this.readingMore = false;
  
    this.decoder = null;
    this.encoding = null;
    if (options.encoding) {
      if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
      this.decoder = new StringDecoder(options.encoding);
      this.encoding = options.encoding;
    }
  }
  
  function Readable(options) {
    Duplex = Duplex || require('./_stream_duplex');
  
    if (!(this instanceof Readable)) return new Readable(options);
  
    this._readableState = new ReadableState(options, this);
  
    // legacy
    this.readable = true;
  
    if (options && typeof options.read === 'function') this._read = options.read;
  
    Stream.call(this);
  }
  
  // Manually shove something into the read() buffer.
  // This returns true if the highWaterMark has not been hit yet,
  // similar to how Writable.write() returns true if you should
  // write() some more.
  Readable.prototype.push = function (chunk, encoding) {
    var state = this._readableState;
  
    if (!state.objectMode && typeof chunk === 'string') {
      encoding = encoding || state.defaultEncoding;
      if (encoding !== state.encoding) {
        chunk = bufferShim.from(chunk, encoding);
        encoding = '';
      }
    }
  
    return readableAddChunk(this, state, chunk, encoding, false);
  };
  
  // Unshift should *always* be something directly out of read()
  Readable.prototype.unshift = function (chunk) {
    var state = this._readableState;
    return readableAddChunk(this, state, chunk, '', true);
  };
  
  Readable.prototype.isPaused = function () {
    return this._readableState.flowing === false;
  };
  
  function readableAddChunk(stream, state, chunk, encoding, addToFront) {
    var er = chunkInvalid(state, chunk);
    if (er) {
      stream.emit('error', er);
    } else if (chunk === null) {
      state.reading = false;
      onEofChunk(stream, state);
    } else if (state.objectMode || chunk && chunk.length > 0) {
      if (state.ended && !addToFront) {
        var e = new Error('stream.push() after EOF');
        stream.emit('error', e);
      } else if (state.endEmitted && addToFront) {
        var _e = new Error('stream.unshift() after end event');
        stream.emit('error', _e);
      } else {
        var skipAdd;
        if (state.decoder && !addToFront && !encoding) {
          chunk = state.decoder.write(chunk);
          skipAdd = !state.objectMode && chunk.length === 0;
        }
  
        if (!addToFront) state.reading = false;
  
        // Don't add to the buffer if we've decoded to an empty string chunk and
        // we're not in object mode
        if (!skipAdd) {
          // if we want the data now, just emit it.
          if (state.flowing && state.length === 0 && !state.sync) {
            stream.emit('data', chunk);
            stream.read(0);
          } else {
            // update the buffer info.
            state.length += state.objectMode ? 1 : chunk.length;
            if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk);
  
            if (state.needReadable) emitReadable(stream);
          }
        }
  
        maybeReadMore(stream, state);
      }
    } else if (!addToFront) {
      state.reading = false;
    }
  
    return needMoreData(state);
  }
  
  // if it's past the high water mark, we can push in some more.
  // Also, if we have no data yet, we can stand some
  // more bytes.  This is to work around cases where hwm=0,
  // such as the repl.  Also, if the push() triggered a
  // readable event, and the user called read(largeNumber) such that
  // needReadable was set, then we ought to push more, so that another
  // 'readable' event will be triggered.
  function needMoreData(state) {
    return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0);
  }
  
  // backwards compatibility.
  Readable.prototype.setEncoding = function (enc) {
    if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
    this._readableState.decoder = new StringDecoder(enc);
    this._readableState.encoding = enc;
    return this;
  };
  
  // Don't raise the hwm > 8MB
  var MAX_HWM = 0x800000;
  function computeNewHighWaterMark(n) {
    if (n >= MAX_HWM) {
      n = MAX_HWM;
    } else {
      // Get the next highest power of 2 to prevent increasing hwm excessively in
      // tiny amounts
      n--;
      n |= n >>> 1;
      n |= n >>> 2;
      n |= n >>> 4;
      n |= n >>> 8;
      n |= n >>> 16;
      n++;
    }
    return n;
  }
  
  // This function is designed to be inlinable, so please take care when making
  // changes to the function body.
  function howMuchToRead(n, state) {
    if (n <= 0 || state.length === 0 && state.ended) return 0;
    if (state.objectMode) return 1;
    if (n !== n) {
      // Only flow one buffer at a time
      if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length;
    }
    // If we're asking for more than the current hwm, then raise the hwm.
    if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n);
    if (n <= state.length) return n;
    // Don't have enough
    if (!state.ended) {
      state.needReadable = true;
      return 0;
    }
    return state.length;
  }
  
  // you can override either this method, or the async _read(n) below.
  Readable.prototype.read = function (n) {
    debug('read', n);
    n = parseInt(n, 10);
    var state = this._readableState;
    var nOrig = n;
  
    if (n !== 0) state.emittedReadable = false;
  
    // if we're doing read(0) to trigger a readable event, but we
    // already have a bunch of data in the buffer, then just trigger
    // the 'readable' event and move on.
    if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) {
      debug('read: emitReadable', state.length, state.ended);
      if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this);
      return null;
    }
  
    n = howMuchToRead(n, state);
  
    // if we've ended, and we're now clear, then finish it up.
    if (n === 0 && state.ended) {
      if (state.length === 0) endReadable(this);
      return null;
    }
  
    // All the actual chunk generation logic needs to be
    // *below* the call to _read.  The reason is that in certain
    // synthetic stream cases, such as passthrough streams, _read
    // may be a completely synchronous operation which may change
    // the state of the read buffer, providing enough data when
    // before there was *not* enough.
    //
    // So, the steps are:
    // 1. Figure out what the state of things will be after we do
    // a read from the buffer.
    //
    // 2. If that resulting state will trigger a _read, then call _read.
    // Note that this may be asynchronous, or synchronous.  Yes, it is
    // deeply ugly to write APIs this way, but that still doesn't mean
    // that the Readable class should behave improperly, as streams are
    // designed to be sync/async agnostic.
    // Take note if the _read call is sync or async (ie, if the read call
    // has returned yet), so that we know whether or not it's safe to emit
    // 'readable' etc.
    //
    // 3. Actually pull the requested chunks out of the buffer and return.
  
    // if we need a readable event, then we need to do some reading.
    var doRead = state.needReadable;
    debug('need readable', doRead);
  
    // if we currently have less than the highWaterMark, then also read some
    if (state.length === 0 || state.length - n < state.highWaterMark) {
      doRead = true;
      debug('length less than watermark', doRead);
    }
  
    // however, if we've ended, then there's no point, and if we're already
    // reading, then it's unnecessary.
    if (state.ended || state.reading) {
      doRead = false;
      debug('reading or ended', doRead);
    } else if (doRead) {
      debug('do read');
      state.reading = true;
      state.sync = true;
      // if the length is currently zero, then we *need* a readable event.
      if (state.length === 0) state.needReadable = true;
      // call internal read method
      this._read(state.highWaterMark);
      state.sync = false;
      // If _read pushed data synchronously, then `reading` will be false,
      // and we need to re-evaluate how much data we can return to the user.
      if (!state.reading) n = howMuchToRead(nOrig, state);
    }
  
    var ret;
    if (n > 0) ret = fromList(n, state);else ret = null;
  
    if (ret === null) {
      state.needReadable = true;
      n = 0;
    } else {
      state.length -= n;
    }
  
    if (state.length === 0) {
      // If we have nothing in the buffer, then we want to know
      // as soon as we *do* get something into the buffer.
      if (!state.ended) state.needReadable = true;
  
      // If we tried to read() past the EOF, then emit end on the next tick.
      if (nOrig !== n && state.ended) endReadable(this);
    }
  
    if (ret !== null) this.emit('data', ret);
  
    return ret;
  };
  
  function chunkInvalid(state, chunk) {
    var er = null;
    if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== null && chunk !== undefined && !state.objectMode) {
      er = new TypeError('Invalid non-string/buffer chunk');
    }
    return er;
  }
  
  function onEofChunk(stream, state) {
    if (state.ended) return;
    if (state.decoder) {
      var chunk = state.decoder.end();
      if (chunk && chunk.length) {
        state.buffer.push(chunk);
        state.length += state.objectMode ? 1 : chunk.length;
      }
    }
    state.ended = true;
  
    // emit 'readable' now to make sure it gets picked up.
    emitReadable(stream);
  }
  
  // Don't emit readable right away in sync mode, because this can trigger
  // another read() call => stack overflow.  This way, it might trigger
  // a nextTick recursion warning, but that's not so bad.
  function emitReadable(stream) {
    var state = stream._readableState;
    state.needReadable = false;
    if (!state.emittedReadable) {
      debug('emitReadable', state.flowing);
      state.emittedReadable = true;
      if (state.sync) processNextTick(emitReadable_, stream);else emitReadable_(stream);
    }
  }
  
  function emitReadable_(stream) {
    debug('emit readable');
    stream.emit('readable');
    flow(stream);
  }
  
  // at this point, the user has presumably seen the 'readable' event,
  // and called read() to consume some data.  that may have triggered
  // in turn another _read(n) call, in which case reading = true if
  // it's in progress.
  // However, if we're not ended, or reading, and the length < hwm,
  // then go ahead and try to read some more preemptively.
  function maybeReadMore(stream, state) {
    if (!state.readingMore) {
      state.readingMore = true;
      processNextTick(maybeReadMore_, stream, state);
    }
  }
  
  function maybeReadMore_(stream, state) {
    var len = state.length;
    while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) {
      debug('maybeReadMore read 0');
      stream.read(0);
      if (len === state.length)
        // didn't get any data, stop spinning.
        break;else len = state.length;
    }
    state.readingMore = false;
  }
  
  // abstract method.  to be overridden in specific implementation classes.
  // call cb(er, data) where data is <= n in length.
  // for virtual (non-string, non-buffer) streams, "length" is somewhat
  // arbitrary, and perhaps not very meaningful.
  Readable.prototype._read = function (n) {
    this.emit('error', new Error('_read() is not implemented'));
  };
  
  Readable.prototype.pipe = function (dest, pipeOpts) {
    var src = this;
    var state = this._readableState;
  
    switch (state.pipesCount) {
      case 0:
        state.pipes = dest;
        break;
      case 1:
        state.pipes = [state.pipes, dest];
        break;
      default:
        state.pipes.push(dest);
        break;
    }
    state.pipesCount += 1;
    debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
  
    var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;
  
    var endFn = doEnd ? onend : cleanup;
    if (state.endEmitted) processNextTick(endFn);else src.once('end', endFn);
  
    dest.on('unpipe', onunpipe);
    function onunpipe(readable) {
      debug('onunpipe');
      if (readable === src) {
        cleanup();
      }
    }
  
    function onend() {
      debug('onend');
      dest.end();
    }
  
    // when the dest drains, it reduces the awaitDrain counter
    // on the source.  This would be more elegant with a .once()
    // handler in flow(), but adding and removing repeatedly is
    // too slow.
    var ondrain = pipeOnDrain(src);
    dest.on('drain', ondrain);
  
    var cleanedUp = false;
    function cleanup() {
      debug('cleanup');
      // cleanup event handlers once the pipe is broken
      dest.removeListener('close', onclose);
      dest.removeListener('finish', onfinish);
      dest.removeListener('drain', ondrain);
      dest.removeListener('error', onerror);
      dest.removeListener('unpipe', onunpipe);
      src.removeListener('end', onend);
      src.removeListener('end', cleanup);
      src.removeListener('data', ondata);
  
      cleanedUp = true;
  
      // if the reader is waiting for a drain event from this
      // specific writer, then it would cause it to never start
      // flowing again.
      // So, if this is awaiting a drain, then we just call it now.
      // If we don't know, then assume that we are waiting for one.
      if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain();
    }
  
    // If the user pushes more data while we're writing to dest then we'll end up
    // in ondata again. However, we only want to increase awaitDrain once because
    // dest will only emit one 'drain' event for the multiple writes.
    // => Introduce a guard on increasing awaitDrain.
    var increasedAwaitDrain = false;
    src.on('data', ondata);
    function ondata(chunk) {
      debug('ondata');
      increasedAwaitDrain = false;
      var ret = dest.write(chunk);
      if (false === ret && !increasedAwaitDrain) {
        // If the user unpiped during `dest.write()`, it is possible
        // to get stuck in a permanently paused state if that write
        // also returned false.
        // => Check whether `dest` is still a piping destination.
        if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) {
          debug('false write response, pause', src._readableState.awaitDrain);
          src._readableState.awaitDrain++;
          increasedAwaitDrain = true;
        }
        src.pause();
      }
    }
  
    // if the dest has an error, then stop piping into it.
    // however, don't suppress the throwing behavior for this.
    function onerror(er) {
      debug('onerror', er);
      unpipe();
      dest.removeListener('error', onerror);
      if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er);
    }
  
    // Make sure our error handler is attached before userland ones.
    prependListener(dest, 'error', onerror);
  
    // Both close and finish should trigger unpipe, but only once.
    function onclose() {
      dest.removeListener('finish', onfinish);
      unpipe();
    }
    dest.once('close', onclose);
    function onfinish() {
      debug('onfinish');
      dest.removeListener('close', onclose);
      unpipe();
    }
    dest.once('finish', onfinish);
  
    function unpipe() {
      debug('unpipe');
      src.unpipe(dest);
    }
  
    // tell the dest that it's being piped to
    dest.emit('pipe', src);
  
    // start the flow if it hasn't been started already.
    if (!state.flowing) {
      debug('pipe resume');
      src.resume();
    }
  
    return dest;
  };
  
  function pipeOnDrain(src) {
    return function () {
      var state = src._readableState;
      debug('pipeOnDrain', state.awaitDrain);
      if (state.awaitDrain) state.awaitDrain--;
      if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) {
        state.flowing = true;
        flow(src);
      }
    };
  }
  
  Readable.prototype.unpipe = function (dest) {
    var state = this._readableState;
  
    // if we're not piping anywhere, then do nothing.
    if (state.pipesCount === 0) return this;
  
    // just one destination.  most common case.
    if (state.pipesCount === 1) {
      // passed in one, but it's not the right one.
      if (dest && dest !== state.pipes) return this;
  
      if (!dest) dest = state.pipes;
  
      // got a match.
      state.pipes = null;
      state.pipesCount = 0;
      state.flowing = false;
      if (dest) dest.emit('unpipe', this);
      return this;
    }
  
    // slow case. multiple pipe destinations.
  
    if (!dest) {
      // remove all.
      var dests = state.pipes;
      var len = state.pipesCount;
      state.pipes = null;
      state.pipesCount = 0;
      state.flowing = false;
  
      for (var i = 0; i < len; i++) {
        dests[i].emit('unpipe', this);
      }return this;
    }
  
    // try to find the right one.
    var index = indexOf(state.pipes, dest);
    if (index === -1) return this;
  
    state.pipes.splice(index, 1);
    state.pipesCount -= 1;
    if (state.pipesCount === 1) state.pipes = state.pipes[0];
  
    dest.emit('unpipe', this);
  
    return this;
  };
  
  // set up data events if they are asked for
  // Ensure readable listeners eventually get something
  Readable.prototype.on = function (ev, fn) {
    var res = Stream.prototype.on.call(this, ev, fn);
  
    if (ev === 'data') {
      // Start flowing on next tick if stream isn't explicitly paused
      if (this._readableState.flowing !== false) this.resume();
    } else if (ev === 'readable') {
      var state = this._readableState;
      if (!state.endEmitted && !state.readableListening) {
        state.readableListening = state.needReadable = true;
        state.emittedReadable = false;
        if (!state.reading) {
          processNextTick(nReadingNextTick, this);
        } else if (state.length) {
          emitReadable(this, state);
        }
      }
    }
  
    return res;
  };
  Readable.prototype.addListener = Readable.prototype.on;
  
  function nReadingNextTick(self) {
    debug('readable nexttick read 0');
    self.read(0);
  }
  
  // pause() and resume() are remnants of the legacy readable stream API
  // If the user uses them, then switch into old mode.
  Readable.prototype.resume = function () {
    var state = this._readableState;
    if (!state.flowing) {
      debug('resume');
      state.flowing = true;
      resume(this, state);
    }
    return this;
  };
  
  function resume(stream, state) {
    if (!state.resumeScheduled) {
      state.resumeScheduled = true;
      processNextTick(resume_, stream, state);
    }
  }
  
  function resume_(stream, state) {
    if (!state.reading) {
      debug('resume read 0');
      stream.read(0);
    }
  
    state.resumeScheduled = false;
    state.awaitDrain = 0;
    stream.emit('resume');
    flow(stream);
    if (state.flowing && !state.reading) stream.read(0);
  }
  
  Readable.prototype.pause = function () {
    debug('call pause flowing=%j', this._readableState.flowing);
    if (false !== this._readableState.flowing) {
      debug('pause');
      this._readableState.flowing = false;
      this.emit('pause');
    }
    return this;
  };
  
  function flow(stream) {
    var state = stream._readableState;
    debug('flow', state.flowing);
    while (state.flowing && stream.read() !== null) {}
  }
  
  // wrap an old-style stream as the async data source.
  // This is *not* part of the readable stream interface.
  // It is an ugly unfortunate mess of history.
  Readable.prototype.wrap = function (stream) {
    var state = this._readableState;
    var paused = false;
  
    var self = this;
    stream.on('end', function () {
      debug('wrapped end');
      if (state.decoder && !state.ended) {
        var chunk = state.decoder.end();
        if (chunk && chunk.length) self.push(chunk);
      }
  
      self.push(null);
    });
  
    stream.on('data', function (chunk) {
      debug('wrapped data');
      if (state.decoder) chunk = state.decoder.write(chunk);
  
      // don't skip over falsy values in objectMode
      if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return;
  
      var ret = self.push(chunk);
      if (!ret) {
        paused = true;
        stream.pause();
      }
    });
  
    // proxy all the other methods.
    // important when wrapping filters and duplexes.
    for (var i in stream) {
      if (this[i] === undefined && typeof stream[i] === 'function') {
        this[i] = function (method) {
          return function () {
            return stream[method].apply(stream, arguments);
          };
        }(i);
      }
    }
  
    // proxy certain important events.
    var events = ['error', 'close', 'destroy', 'pause', 'resume'];
    forEach(events, function (ev) {
      stream.on(ev, self.emit.bind(self, ev));
    });
  
    // when we try to consume some more bytes, simply unpause the
    // underlying stream.
    self._read = function (n) {
      debug('wrapped _read', n);
      if (paused) {
        paused = false;
        stream.resume();
      }
    };
  
    return self;
  };
  
  // exposed for testing purposes only.
  Readable._fromList = fromList;
  
  // Pluck off n bytes from an array of buffers.
  // Length is the combined lengths of all the buffers in the list.
  // This function is designed to be inlinable, so please take care when making
  // changes to the function body.
  function fromList(n, state) {
    // nothing buffered
    if (state.length === 0) return null;
  
    var ret;
    if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) {
      // read it all, truncate the list
      if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length);
      state.buffer.clear();
    } else {
      // read part of list
      ret = fromListPartial(n, state.buffer, state.decoder);
    }
  
    return ret;
  }
  
  // Extracts only enough buffered data to satisfy the amount requested.
  // This function is designed to be inlinable, so please take care when making
  // changes to the function body.
  function fromListPartial(n, list, hasStrings) {
    var ret;
    if (n < list.head.data.length) {
      // slice is the same for buffers and strings
      ret = list.head.data.slice(0, n);
      list.head.data = list.head.data.slice(n);
    } else if (n === list.head.data.length) {
      // first chunk is a perfect match
      ret = list.shift();
    } else {
      // result spans more than one buffer
      ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list);
    }
    return ret;
  }
  
  // Copies a specified amount of characters from the list of buffered data
  // chunks.
  // This function is designed to be inlinable, so please take care when making
  // changes to the function body.
  function copyFromBufferString(n, list) {
    var p = list.head;
    var c = 1;
    var ret = p.data;
    n -= ret.length;
    while (p = p.next) {
      var str = p.data;
      var nb = n > str.length ? str.length : n;
      if (nb === str.length) ret += str;else ret += str.slice(0, n);
      n -= nb;
      if (n === 0) {
        if (nb === str.length) {
          ++c;
          if (p.next) list.head = p.next;else list.head = list.tail = null;
        } else {
          list.head = p;
          p.data = str.slice(nb);
        }
        break;
      }
      ++c;
    }
    list.length -= c;
    return ret;
  }
  
  // Copies a specified amount of bytes from the list of buffered data chunks.
  // This function is designed to be inlinable, so please take care when making
  // changes to the function body.
  function copyFromBuffer(n, list) {
    var ret = bufferShim.allocUnsafe(n);
    var p = list.head;
    var c = 1;
    p.data.copy(ret);
    n -= p.data.length;
    while (p = p.next) {
      var buf = p.data;
      var nb = n > buf.length ? buf.length : n;
      buf.copy(ret, ret.length - n, 0, nb);
      n -= nb;
      if (n === 0) {
        if (nb === buf.length) {
          ++c;
          if (p.next) list.head = p.next;else list.head = list.tail = null;
        } else {
          list.head = p;
          p.data = buf.slice(nb);
        }
        break;
      }
      ++c;
    }
    list.length -= c;
    return ret;
  }
  
  function endReadable(stream) {
    var state = stream._readableState;
  
    // If we get here before consuming all the bytes, then that is a
    // bug in node.  Should never happen.
    if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream');
  
    if (!state.endEmitted) {
      state.ended = true;
      processNextTick(endReadableNT, state, stream);
    }
  }
  
  function endReadableNT(state, stream) {
    // Check that we didn't get one last unshift.
    if (!state.endEmitted && state.length === 0) {
      state.endEmitted = true;
      stream.readable = false;
      stream.emit('end');
    }
  }
  
  function forEach(xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  
  function indexOf(xs, x) {
    for (var i = 0, l = xs.length; i < l; i++) {
      if (xs[i] === x) return i;
    }
    return -1;
  }
  }).call(this,require('_process'))
  },{"./_stream_duplex":143,"./internal/streams/BufferList":148,"_process":137,"buffer":129,"buffer-shims":128,"core-util-is":130,"events":131,"inherits":133,"isarray":135,"process-nextick-args":136,"string_decoder/":154,"util":127}],146:[function(require,module,exports){
  // a transform stream is a readable/writable stream where you do
  // something with the data.  Sometimes it's called a "filter",
  // but that's not a great name for it, since that implies a thing where
  // some bits pass through, and others are simply ignored.  (That would
  // be a valid example of a transform, of course.)
  //
  // While the output is causally related to the input, it's not a
  // necessarily symmetric or synchronous transformation.  For example,
  // a zlib stream might take multiple plain-text writes(), and then
  // emit a single compressed chunk some time in the future.
  //
  // Here's how this works:
  //
  // The Transform stream has all the aspects of the readable and writable
  // stream classes.  When you write(chunk), that calls _write(chunk,cb)
  // internally, and returns false if there's a lot of pending writes
  // buffered up.  When you call read(), that calls _read(n) until
  // there's enough pending readable data buffered up.
  //
  // In a transform stream, the written data is placed in a buffer.  When
  // _read(n) is called, it transforms the queued up data, calling the
  // buffered _write cb's as it consumes chunks.  If consuming a single
  // written chunk would result in multiple output chunks, then the first
  // outputted bit calls the readcb, and subsequent chunks just go into
  // the read buffer, and will cause it to emit 'readable' if necessary.
  //
  // This way, back-pressure is actually determined by the reading side,
  // since _read has to be called to start processing a new chunk.  However,
  // a pathological inflate type of transform can cause excessive buffering
  // here.  For example, imagine a stream where every byte of input is
  // interpreted as an integer from 0-255, and then results in that many
  // bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
  // 1kb of data being output.  In this case, you could write a very small
  // amount of input, and end up with a very large amount of output.  In
  // such a pathological inflating mechanism, there'd be no way to tell
  // the system to stop doing the transform.  A single 4MB write could
  // cause the system to run out of memory.
  //
  // However, even in such a pathological case, only a single written chunk
  // would be consumed, and then the rest would wait (un-transformed) until
  // the results of the previous transformed chunk were consumed.
  
  'use strict';
  
  module.exports = Transform;
  
  var Duplex = require('./_stream_duplex');
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  util.inherits(Transform, Duplex);
  
  function TransformState(stream) {
    this.afterTransform = function (er, data) {
      return afterTransform(stream, er, data);
    };
  
    this.needTransform = false;
    this.transforming = false;
    this.writecb = null;
    this.writechunk = null;
    this.writeencoding = null;
  }
  
  function afterTransform(stream, er, data) {
    var ts = stream._transformState;
    ts.transforming = false;
  
    var cb = ts.writecb;
  
    if (!cb) return stream.emit('error', new Error('no writecb in Transform class'));
  
    ts.writechunk = null;
    ts.writecb = null;
  
    if (data !== null && data !== undefined) stream.push(data);
  
    cb(er);
  
    var rs = stream._readableState;
    rs.reading = false;
    if (rs.needReadable || rs.length < rs.highWaterMark) {
      stream._read(rs.highWaterMark);
    }
  }
  
  function Transform(options) {
    if (!(this instanceof Transform)) return new Transform(options);
  
    Duplex.call(this, options);
  
    this._transformState = new TransformState(this);
  
    var stream = this;
  
    // start out asking for a readable event once data is transformed.
    this._readableState.needReadable = true;
  
    // we have implemented the _read method, and done the other things
    // that Readable wants before the first _read call, so unset the
    // sync guard flag.
    this._readableState.sync = false;
  
    if (options) {
      if (typeof options.transform === 'function') this._transform = options.transform;
  
      if (typeof options.flush === 'function') this._flush = options.flush;
    }
  
    // When the writable side finishes, then flush out anything remaining.
    this.once('prefinish', function () {
      if (typeof this._flush === 'function') this._flush(function (er, data) {
        done(stream, er, data);
      });else done(stream);
    });
  }
  
  Transform.prototype.push = function (chunk, encoding) {
    this._transformState.needTransform = false;
    return Duplex.prototype.push.call(this, chunk, encoding);
  };
  
  // This is the part where you do stuff!
  // override this function in implementation classes.
  // 'chunk' is an input chunk.
  //
  // Call `push(newChunk)` to pass along transformed output
  // to the readable side.  You may call 'push' zero or more times.
  //
  // Call `cb(err)` when you are done with this chunk.  If you pass
  // an error, then that'll put the hurt on the whole operation.  If you
  // never call cb(), then you'll never get another chunk.
  Transform.prototype._transform = function (chunk, encoding, cb) {
    throw new Error('_transform() is not implemented');
  };
  
  Transform.prototype._write = function (chunk, encoding, cb) {
    var ts = this._transformState;
    ts.writecb = cb;
    ts.writechunk = chunk;
    ts.writeencoding = encoding;
    if (!ts.transforming) {
      var rs = this._readableState;
      if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
    }
  };
  
  // Doesn't matter what the args are here.
  // _transform does all the work.
  // That we got here means that the readable side wants more data.
  Transform.prototype._read = function (n) {
    var ts = this._transformState;
  
    if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
      ts.transforming = true;
      this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
    } else {
      // mark that we need a transform, so that any data that comes in
      // will get processed, now that we've asked for it.
      ts.needTransform = true;
    }
  };
  
  function done(stream, er, data) {
    if (er) return stream.emit('error', er);
  
    if (data !== null && data !== undefined) stream.push(data);
  
    // if there's nothing in the write buffer, then that means
    // that nothing more will ever be provided
    var ws = stream._writableState;
    var ts = stream._transformState;
  
    if (ws.length) throw new Error('Calling transform done when ws.length != 0');
  
    if (ts.transforming) throw new Error('Calling transform done when still transforming');
  
    return stream.push(null);
  }
  },{"./_stream_duplex":143,"core-util-is":130,"inherits":133}],147:[function(require,module,exports){
  (function (process){
  // A bit simpler than readable streams.
  // Implement an async ._write(chunk, encoding, cb), and it'll handle all
  // the drain event emission and buffering.
  
  'use strict';
  
  module.exports = Writable;
  
  /*<replacement>*/
  var processNextTick = require('process-nextick-args');
  /*</replacement>*/
  
  /*<replacement>*/
  var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick;
  /*</replacement>*/
  
  /*<replacement>*/
  var Duplex;
  /*</replacement>*/
  
  Writable.WritableState = WritableState;
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  /*<replacement>*/
  var internalUtil = {
    deprecate: require('util-deprecate')
  };
  /*</replacement>*/
  
  /*<replacement>*/
  var Stream;
  (function () {
    try {
      Stream = require('st' + 'ream');
    } catch (_) {} finally {
      if (!Stream) Stream = require('events').EventEmitter;
    }
  })();
  /*</replacement>*/
  
  var Buffer = require('buffer').Buffer;
  /*<replacement>*/
  var bufferShim = require('buffer-shims');
  /*</replacement>*/
  
  util.inherits(Writable, Stream);
  
  function nop() {}
  
  function WriteReq(chunk, encoding, cb) {
    this.chunk = chunk;
    this.encoding = encoding;
    this.callback = cb;
    this.next = null;
  }
  
  function WritableState(options, stream) {
    Duplex = Duplex || require('./_stream_duplex');
  
    options = options || {};
  
    // object stream flag to indicate whether or not this stream
    // contains buffers or objects.
    this.objectMode = !!options.objectMode;
  
    if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.writableObjectMode;
  
    // the point at which write() starts returning false
    // Note: 0 is a valid value, means that we always return false if
    // the entire buffer is not flushed immediately on write()
    var hwm = options.highWaterMark;
    var defaultHwm = this.objectMode ? 16 : 16 * 1024;
    this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    // drain event flag.
    this.needDrain = false;
    // at the start of calling end()
    this.ending = false;
    // when end() has been called, and returned
    this.ended = false;
    // when 'finish' is emitted
    this.finished = false;
  
    // should we decode strings into buffers before passing to _write?
    // this is here so that some node-core streams can optimize string
    // handling at a lower level.
    var noDecode = options.decodeStrings === false;
    this.decodeStrings = !noDecode;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // not an actual buffer we keep track of, but a measurement
    // of how much we're waiting to get pushed to some underlying
    // socket or file.
    this.length = 0;
  
    // a flag to see when we're in the middle of a write.
    this.writing = false;
  
    // when true all writes will be buffered until .uncork() call
    this.corked = 0;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, because any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // a flag to know if we're processing previously buffered items, which
    // may call the _write() callback in the same tick, so that we don't
    // end up in an overlapped onwrite situation.
    this.bufferProcessing = false;
  
    // the callback that's passed to _write(chunk,cb)
    this.onwrite = function (er) {
      onwrite(stream, er);
    };
  
    // the callback that the user supplies to write(chunk,encoding,cb)
    this.writecb = null;
  
    // the amount that is being written when _write is called.
    this.writelen = 0;
  
    this.bufferedRequest = null;
    this.lastBufferedRequest = null;
  
    // number of pending user-supplied write callbacks
    // this must be 0 before 'finish' can be emitted
    this.pendingcb = 0;
  
    // emit prefinish if the only thing we're waiting for is _write cbs
    // This is relevant for synchronous Transform streams
    this.prefinished = false;
  
    // True if the error was already emitted and should not be thrown again
    this.errorEmitted = false;
  
    // count buffered requests
    this.bufferedRequestCount = 0;
  
    // allocate the first CorkedRequest, there is always
    // one allocated and free to use, and we maintain at most two
    this.corkedRequestsFree = new CorkedRequest(this);
  }
  
  WritableState.prototype.getBuffer = function getBuffer() {
    var current = this.bufferedRequest;
    var out = [];
    while (current) {
      out.push(current);
      current = current.next;
    }
    return out;
  };
  
  (function () {
    try {
      Object.defineProperty(WritableState.prototype, 'buffer', {
        get: internalUtil.deprecate(function () {
          return this.getBuffer();
        }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.')
      });
    } catch (_) {}
  })();
  
  // Test _writableState for inheritance to account for Duplex streams,
  // whose prototype chain only points to Readable.
  var realHasInstance;
  if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') {
    realHasInstance = Function.prototype[Symbol.hasInstance];
    Object.defineProperty(Writable, Symbol.hasInstance, {
      value: function (object) {
        if (realHasInstance.call(this, object)) return true;
  
        return object && object._writableState instanceof WritableState;
      }
    });
  } else {
    realHasInstance = function (object) {
      return object instanceof this;
    };
  }
  
  function Writable(options) {
    Duplex = Duplex || require('./_stream_duplex');
  
    // Writable ctor is applied to Duplexes, too.
    // `realHasInstance` is necessary because using plain `instanceof`
    // would return false, as no `_writableState` property is attached.
  
    // Trying to use the custom `instanceof` for Writable here will also break the
    // Node.js LazyTransform implementation, which has a non-trivial getter for
    // `_writableState` that would lead to infinite recursion.
    if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) {
      return new Writable(options);
    }
  
    this._writableState = new WritableState(options, this);
  
    // legacy.
    this.writable = true;
  
    if (options) {
      if (typeof options.write === 'function') this._write = options.write;
  
      if (typeof options.writev === 'function') this._writev = options.writev;
    }
  
    Stream.call(this);
  }
  
  // Otherwise people can pipe Writable streams, which is just wrong.
  Writable.prototype.pipe = function () {
    this.emit('error', new Error('Cannot pipe, not readable'));
  };
  
  function writeAfterEnd(stream, cb) {
    var er = new Error('write after end');
    // TODO: defer error events consistently everywhere, not just the cb
    stream.emit('error', er);
    processNextTick(cb, er);
  }
  
  // Checks that a user-supplied chunk is valid, especially for the particular
  // mode the stream is in. Currently this means that `null` is never accepted
  // and undefined/non-string values are only allowed in object mode.
  function validChunk(stream, state, chunk, cb) {
    var valid = true;
    var er = false;
  
    if (chunk === null) {
      er = new TypeError('May not write null values to stream');
    } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
      er = new TypeError('Invalid non-string/buffer chunk');
    }
    if (er) {
      stream.emit('error', er);
      processNextTick(cb, er);
      valid = false;
    }
    return valid;
  }
  
  Writable.prototype.write = function (chunk, encoding, cb) {
    var state = this._writableState;
    var ret = false;
    var isBuf = Buffer.isBuffer(chunk);
  
    if (typeof encoding === 'function') {
      cb = encoding;
      encoding = null;
    }
  
    if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding;
  
    if (typeof cb !== 'function') cb = nop;
  
    if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) {
      state.pendingcb++;
      ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb);
    }
  
    return ret;
  };
  
  Writable.prototype.cork = function () {
    var state = this._writableState;
  
    state.corked++;
  };
  
  Writable.prototype.uncork = function () {
    var state = this._writableState;
  
    if (state.corked) {
      state.corked--;
  
      if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
    }
  };
  
  Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
    // node::ParseEncoding() requires lower case.
    if (typeof encoding === 'string') encoding = encoding.toLowerCase();
    if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding);
    this._writableState.defaultEncoding = encoding;
    return this;
  };
  
  function decodeChunk(state, chunk, encoding) {
    if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
      chunk = bufferShim.from(chunk, encoding);
    }
    return chunk;
  }
  
  // if we're already writing something, then just put this
  // in the queue, and wait our turn.  Otherwise, call _write
  // If we return false, then we need a drain event, so set that flag.
  function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
    if (!isBuf) {
      chunk = decodeChunk(state, chunk, encoding);
      if (Buffer.isBuffer(chunk)) encoding = 'buffer';
    }
    var len = state.objectMode ? 1 : chunk.length;
  
    state.length += len;
  
    var ret = state.length < state.highWaterMark;
    // we must ensure that previous needDrain will not be reset to false.
    if (!ret) state.needDrain = true;
  
    if (state.writing || state.corked) {
      var last = state.lastBufferedRequest;
      state.lastBufferedRequest = new WriteReq(chunk, encoding, cb);
      if (last) {
        last.next = state.lastBufferedRequest;
      } else {
        state.bufferedRequest = state.lastBufferedRequest;
      }
      state.bufferedRequestCount += 1;
    } else {
      doWrite(stream, state, false, len, chunk, encoding, cb);
    }
  
    return ret;
  }
  
  function doWrite(stream, state, writev, len, chunk, encoding, cb) {
    state.writelen = len;
    state.writecb = cb;
    state.writing = true;
    state.sync = true;
    if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite);
    state.sync = false;
  }
  
  function onwriteError(stream, state, sync, er, cb) {
    --state.pendingcb;
    if (sync) processNextTick(cb, er);else cb(er);
  
    stream._writableState.errorEmitted = true;
    stream.emit('error', er);
  }
  
  function onwriteStateUpdate(state) {
    state.writing = false;
    state.writecb = null;
    state.length -= state.writelen;
    state.writelen = 0;
  }
  
  function onwrite(stream, er) {
    var state = stream._writableState;
    var sync = state.sync;
    var cb = state.writecb;
  
    onwriteStateUpdate(state);
  
    if (er) onwriteError(stream, state, sync, er, cb);else {
      // Check if we're actually ready to finish, but don't emit yet
      var finished = needFinish(state);
  
      if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
        clearBuffer(stream, state);
      }
  
      if (sync) {
        /*<replacement>*/
        asyncWrite(afterWrite, stream, state, finished, cb);
        /*</replacement>*/
      } else {
        afterWrite(stream, state, finished, cb);
      }
    }
  }
  
  function afterWrite(stream, state, finished, cb) {
    if (!finished) onwriteDrain(stream, state);
    state.pendingcb--;
    cb();
    finishMaybe(stream, state);
  }
  
  // Must force callback to be called on nextTick, so that we don't
  // emit 'drain' before the write() consumer gets the 'false' return
  // value, and has a chance to attach a 'drain' listener.
  function onwriteDrain(stream, state) {
    if (state.length === 0 && state.needDrain) {
      state.needDrain = false;
      stream.emit('drain');
    }
  }
  
  // if there's something in the buffer waiting, then process it
  function clearBuffer(stream, state) {
    state.bufferProcessing = true;
    var entry = state.bufferedRequest;
  
    if (stream._writev && entry && entry.next) {
      // Fast case, write everything using _writev()
      var l = state.bufferedRequestCount;
      var buffer = new Array(l);
      var holder = state.corkedRequestsFree;
      holder.entry = entry;
  
      var count = 0;
      while (entry) {
        buffer[count] = entry;
        entry = entry.next;
        count += 1;
      }
  
      doWrite(stream, state, true, state.length, buffer, '', holder.finish);
  
      // doWrite is almost always async, defer these to save a bit of time
      // as the hot path ends with doWrite
      state.pendingcb++;
      state.lastBufferedRequest = null;
      if (holder.next) {
        state.corkedRequestsFree = holder.next;
        holder.next = null;
      } else {
        state.corkedRequestsFree = new CorkedRequest(state);
      }
    } else {
      // Slow case, write chunks one-by-one
      while (entry) {
        var chunk = entry.chunk;
        var encoding = entry.encoding;
        var cb = entry.callback;
        var len = state.objectMode ? 1 : chunk.length;
  
        doWrite(stream, state, false, len, chunk, encoding, cb);
        entry = entry.next;
        // if we didn't call the onwrite immediately, then
        // it means that we need to wait until it does.
        // also, that means that the chunk and cb are currently
        // being processed, so move the buffer counter past them.
        if (state.writing) {
          break;
        }
      }
  
      if (entry === null) state.lastBufferedRequest = null;
    }
  
    state.bufferedRequestCount = 0;
    state.bufferedRequest = entry;
    state.bufferProcessing = false;
  }
  
  Writable.prototype._write = function (chunk, encoding, cb) {
    cb(new Error('_write() is not implemented'));
  };
  
  Writable.prototype._writev = null;
  
  Writable.prototype.end = function (chunk, encoding, cb) {
    var state = this._writableState;
  
    if (typeof chunk === 'function') {
      cb = chunk;
      chunk = null;
      encoding = null;
    } else if (typeof encoding === 'function') {
      cb = encoding;
      encoding = null;
    }
  
    if (chunk !== null && chunk !== undefined) this.write(chunk, encoding);
  
    // .end() fully uncorks
    if (state.corked) {
      state.corked = 1;
      this.uncork();
    }
  
    // ignore unnecessary end() calls.
    if (!state.ending && !state.finished) endWritable(this, state, cb);
  };
  
  function needFinish(state) {
    return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
  }
  
  function prefinish(stream, state) {
    if (!state.prefinished) {
      state.prefinished = true;
      stream.emit('prefinish');
    }
  }
  
  function finishMaybe(stream, state) {
    var need = needFinish(state);
    if (need) {
      if (state.pendingcb === 0) {
        prefinish(stream, state);
        state.finished = true;
        stream.emit('finish');
      } else {
        prefinish(stream, state);
      }
    }
    return need;
  }
  
  function endWritable(stream, state, cb) {
    state.ending = true;
    finishMaybe(stream, state);
    if (cb) {
      if (state.finished) processNextTick(cb);else stream.once('finish', cb);
    }
    state.ended = true;
    stream.writable = false;
  }
  
  // It seems a linked list but it is not
  // there will be only 2 of these for each stream
  function CorkedRequest(state) {
    var _this = this;
  
    this.next = null;
    this.entry = null;
    this.finish = function (err) {
      var entry = _this.entry;
      _this.entry = null;
      while (entry) {
        var cb = entry.callback;
        state.pendingcb--;
        cb(err);
        entry = entry.next;
      }
      if (state.corkedRequestsFree) {
        state.corkedRequestsFree.next = _this;
      } else {
        state.corkedRequestsFree = _this;
      }
    };
  }
  }).call(this,require('_process'))
  },{"./_stream_duplex":143,"_process":137,"buffer":129,"buffer-shims":128,"core-util-is":130,"events":131,"inherits":133,"process-nextick-args":136,"util-deprecate":157}],148:[function(require,module,exports){
  'use strict';
  
  var Buffer = require('buffer').Buffer;
  /*<replacement>*/
  var bufferShim = require('buffer-shims');
  /*</replacement>*/
  
  module.exports = BufferList;
  
  function BufferList() {
    this.head = null;
    this.tail = null;
    this.length = 0;
  }
  
  BufferList.prototype.push = function (v) {
    var entry = { data: v, next: null };
    if (this.length > 0) this.tail.next = entry;else this.head = entry;
    this.tail = entry;
    ++this.length;
  };
  
  BufferList.prototype.unshift = function (v) {
    var entry = { data: v, next: this.head };
    if (this.length === 0) this.tail = entry;
    this.head = entry;
    ++this.length;
  };
  
  BufferList.prototype.shift = function () {
    if (this.length === 0) return;
    var ret = this.head.data;
    if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
    --this.length;
    return ret;
  };
  
  BufferList.prototype.clear = function () {
    this.head = this.tail = null;
    this.length = 0;
  };
  
  BufferList.prototype.join = function (s) {
    if (this.length === 0) return '';
    var p = this.head;
    var ret = '' + p.data;
    while (p = p.next) {
      ret += s + p.data;
    }return ret;
  };
  
  BufferList.prototype.concat = function (n) {
    if (this.length === 0) return bufferShim.alloc(0);
    if (this.length === 1) return this.head.data;
    var ret = bufferShim.allocUnsafe(n >>> 0);
    var p = this.head;
    var i = 0;
    while (p) {
      p.data.copy(ret, i);
      i += p.data.length;
      p = p.next;
    }
    return ret;
  };
  },{"buffer":129,"buffer-shims":128}],149:[function(require,module,exports){
  module.exports = require("./lib/_stream_passthrough.js")
  
  },{"./lib/_stream_passthrough.js":144}],150:[function(require,module,exports){
  (function (process){
  var Stream = (function (){
    try {
      return require('st' + 'ream'); // hack to fix a circular dependency issue when used with browserify
    } catch(_){}
  }());
  exports = module.exports = require('./lib/_stream_readable.js');
  exports.Stream = Stream || exports;
  exports.Readable = exports;
  exports.Writable = require('./lib/_stream_writable.js');
  exports.Duplex = require('./lib/_stream_duplex.js');
  exports.Transform = require('./lib/_stream_transform.js');
  exports.PassThrough = require('./lib/_stream_passthrough.js');
  
  if (!process.browser && process.env.READABLE_STREAM === 'disable' && Stream) {
    module.exports = Stream;
  }
  
  }).call(this,require('_process'))
  },{"./lib/_stream_duplex.js":143,"./lib/_stream_passthrough.js":144,"./lib/_stream_readable.js":145,"./lib/_stream_transform.js":146,"./lib/_stream_writable.js":147,"_process":137}],151:[function(require,module,exports){
  module.exports = require("./lib/_stream_transform.js")
  
  },{"./lib/_stream_transform.js":146}],152:[function(require,module,exports){
  module.exports = require("./lib/_stream_writable.js")
  
  },{"./lib/_stream_writable.js":147}],153:[function(require,module,exports){
  // Copyright Joyent, Inc. and other Node 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.
  
  module.exports = Stream;
  
  var EE = require('events').EventEmitter;
  var inherits = require('inherits');
  
  inherits(Stream, EE);
  Stream.Readable = require('readable-stream/readable.js');
  Stream.Writable = require('readable-stream/writable.js');
  Stream.Duplex = require('readable-stream/duplex.js');
  Stream.Transform = require('readable-stream/transform.js');
  Stream.PassThrough = require('readable-stream/passthrough.js');
  
  // Backwards-compat with node 0.4.x
  Stream.Stream = Stream;
  
  
  
  // old-style streams.  Note that the pipe method (the only relevant
  // part of this class) is overridden in the Readable class.
  
  function Stream() {
    EE.call(this);
  }
  
  Stream.prototype.pipe = function(dest, options) {
    var source = this;
  
    function ondata(chunk) {
      if (dest.writable) {
        if (false === dest.write(chunk) && source.pause) {
          source.pause();
        }
      }
    }
  
    source.on('data', ondata);
  
    function ondrain() {
      if (source.readable && source.resume) {
        source.resume();
      }
    }
  
    dest.on('drain', ondrain);
  
    // If the 'end' option is not supplied, dest.end() will be called when
    // source gets the 'end' or 'close' events.  Only dest.end() once.
    if (!dest._isStdio && (!options || options.end !== false)) {
      source.on('end', onend);
      source.on('close', onclose);
    }
  
    var didOnEnd = false;
    function onend() {
      if (didOnEnd) return;
      didOnEnd = true;
  
      dest.end();
    }
  
  
    function onclose() {
      if (didOnEnd) return;
      didOnEnd = true;
  
      if (typeof dest.destroy === 'function') dest.destroy();
    }
  
    // don't leave dangling pipes when there are errors.
    function onerror(er) {
      cleanup();
      if (EE.listenerCount(this, 'error') === 0) {
        throw er; // Unhandled stream error in pipe.
      }
    }
  
    source.on('error', onerror);
    dest.on('error', onerror);
  
    // remove all the event listeners that were added.
    function cleanup() {
      source.removeListener('data', ondata);
      dest.removeListener('drain', ondrain);
  
      source.removeListener('end', onend);
      source.removeListener('close', onclose);
  
      source.removeListener('error', onerror);
      dest.removeListener('error', onerror);
  
      source.removeListener('end', cleanup);
      source.removeListener('close', cleanup);
  
      dest.removeListener('close', cleanup);
    }
  
    source.on('end', cleanup);
    source.on('close', cleanup);
  
    dest.on('close', cleanup);
  
    dest.emit('pipe', source);
  
    // Allow for unix-like usage: A.pipe(B).pipe(C)
    return dest;
  };
  
  },{"events":131,"inherits":133,"readable-stream/duplex.js":142,"readable-stream/passthrough.js":149,"readable-stream/readable.js":150,"readable-stream/transform.js":151,"readable-stream/writable.js":152}],154:[function(require,module,exports){
  // Copyright Joyent, Inc. and other Node 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.
  
  var Buffer = require('buffer').Buffer;
  
  var isBufferEncoding = Buffer.isEncoding
    || function(encoding) {
         switch (encoding && encoding.toLowerCase()) {
           case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
           default: return false;
         }
       }
  
  
  function assertEncoding(encoding) {
    if (encoding && !isBufferEncoding(encoding)) {
      throw new Error('Unknown encoding: ' + encoding);
    }
  }
  
  // StringDecoder provides an interface for efficiently splitting a series of
  // buffers into a series of JS strings without breaking apart multi-byte
  // characters. CESU-8 is handled as part of the UTF-8 encoding.
  //
  // @TODO Handling all encodings inside a single object makes it very difficult
  // to reason about this code, so it should be split up in the future.
  // @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
  // points as used by CESU-8.
  var StringDecoder = exports.StringDecoder = function(encoding) {
    this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
    assertEncoding(encoding);
    switch (this.encoding) {
      case 'utf8':
        // CESU-8 represents each of Surrogate Pair by 3-bytes
        this.surrogateSize = 3;
        break;
      case 'ucs2':
      case 'utf16le':
        // UTF-16 represents each of Surrogate Pair by 2-bytes
        this.surrogateSize = 2;
        this.detectIncompleteChar = utf16DetectIncompleteChar;
        break;
      case 'base64':
        // Base-64 stores 3 bytes in 4 chars, and pads the remainder.
        this.surrogateSize = 3;
        this.detectIncompleteChar = base64DetectIncompleteChar;
        break;
      default:
        this.write = passThroughWrite;
        return;
    }
  
    // Enough space to store all bytes of a single character. UTF-8 needs 4
    // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
    this.charBuffer = new Buffer(6);
    // Number of bytes received for the current incomplete multi-byte character.
    this.charReceived = 0;
    // Number of bytes expected for the current incomplete multi-byte character.
    this.charLength = 0;
  };
  
  
  // write decodes the given buffer and returns it as JS string that is
  // guaranteed to not contain any partial multi-byte characters. Any partial
  // character found at the end of the buffer is buffered up, and will be
  // returned when calling write again with the remaining bytes.
  //
  // Note: Converting a Buffer containing an orphan surrogate to a String
  // currently works, but converting a String to a Buffer (via `new Buffer`, or
  // Buffer#write) will replace incomplete surrogates with the unicode
  // replacement character. See https://codereview.chromium.org/121173009/ .
  StringDecoder.prototype.write = function(buffer) {
    var charStr = '';
    // if our last write ended with an incomplete multibyte character
    while (this.charLength) {
      // determine how many remaining bytes this buffer has to offer for this char
      var available = (buffer.length >= this.charLength - this.charReceived) ?
          this.charLength - this.charReceived :
          buffer.length;
  
      // add the new bytes to the char buffer
      buffer.copy(this.charBuffer, this.charReceived, 0, available);
      this.charReceived += available;
  
      if (this.charReceived < this.charLength) {
        // still not enough chars in this buffer? wait for more ...
        return '';
      }
  
      // remove bytes belonging to the current character from the buffer
      buffer = buffer.slice(available, buffer.length);
  
      // get the character that was split
      charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
  
      // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
      var charCode = charStr.charCodeAt(charStr.length - 1);
      if (charCode >= 0xD800 && charCode <= 0xDBFF) {
        this.charLength += this.surrogateSize;
        charStr = '';
        continue;
      }
      this.charReceived = this.charLength = 0;
  
      // if there are no more bytes in this buffer, just emit our char
      if (buffer.length === 0) {
        return charStr;
      }
      break;
    }
  
    // determine and set charLength / charReceived
    this.detectIncompleteChar(buffer);
  
    var end = buffer.length;
    if (this.charLength) {
      // buffer the incomplete character bytes we got
      buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
      end -= this.charReceived;
    }
  
    charStr += buffer.toString(this.encoding, 0, end);
  
    var end = charStr.length - 1;
    var charCode = charStr.charCodeAt(end);
    // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
    if (charCode >= 0xD800 && charCode <= 0xDBFF) {
      var size = this.surrogateSize;
      this.charLength += size;
      this.charReceived += size;
      this.charBuffer.copy(this.charBuffer, size, 0, size);
      buffer.copy(this.charBuffer, 0, 0, size);
      return charStr.substring(0, end);
    }
  
    // or just emit the charStr
    return charStr;
  };
  
  // detectIncompleteChar determines if there is an incomplete UTF-8 character at
  // the end of the given buffer. If so, it sets this.charLength to the byte
  // length that character, and sets this.charReceived to the number of bytes
  // that are available for this character.
  StringDecoder.prototype.detectIncompleteChar = function(buffer) {
    // determine how many bytes we have to check at the end of this buffer
    var i = (buffer.length >= 3) ? 3 : buffer.length;
  
    // Figure out if one of the last i bytes of our buffer announces an
    // incomplete char.
    for (; i > 0; i--) {
      var c = buffer[buffer.length - i];
  
      // See http://en.wikipedia.org/wiki/UTF-8#Description
  
      // 110XXXXX
      if (i == 1 && c >> 5 == 0x06) {
        this.charLength = 2;
        break;
      }
  
      // 1110XXXX
      if (i <= 2 && c >> 4 == 0x0E) {
        this.charLength = 3;
        break;
      }
  
      // 11110XXX
      if (i <= 3 && c >> 3 == 0x1E) {
        this.charLength = 4;
        break;
      }
    }
    this.charReceived = i;
  };
  
  StringDecoder.prototype.end = function(buffer) {
    var res = '';
    if (buffer && buffer.length)
      res = this.write(buffer);
  
    if (this.charReceived) {
      var cr = this.charReceived;
      var buf = this.charBuffer;
      var enc = this.encoding;
      res += buf.slice(0, cr).toString(enc);
    }
  
    return res;
  };
  
  function passThroughWrite(buffer) {
    return buffer.toString(this.encoding);
  }
  
  function utf16DetectIncompleteChar(buffer) {
    this.charReceived = buffer.length % 2;
    this.charLength = this.charReceived ? 2 : 0;
  }
  
  function base64DetectIncompleteChar(buffer) {
    this.charReceived = buffer.length % 3;
    this.charLength = this.charReceived ? 3 : 0;
  }
  
  },{"buffer":129}],155:[function(require,module,exports){
  // Copyright Joyent, Inc. and other Node 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.
  
  'use strict';
  
  var punycode = require('punycode');
  var util = require('./util');
  
  exports.parse = urlParse;
  exports.resolve = urlResolve;
  exports.resolveObject = urlResolveObject;
  exports.format = urlFormat;
  
  exports.Url = Url;
  
  function Url() {
    this.protocol = null;
    this.slashes = null;
    this.auth = null;
    this.host = null;
    this.port = null;
    this.hostname = null;
    this.hash = null;
    this.search = null;
    this.query = null;
    this.pathname = null;
    this.path = null;
    this.href = null;
  }
  
  // Reference: RFC 3986, RFC 1808, RFC 2396
  
  // define these here so at least they only have to be
  // compiled once on the first module load.
  var protocolPattern = /^([a-z0-9.+-]+:)/i,
      portPattern = /:[0-9]*$/,
  
      // Special case for a simple path URL
      simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
  
      // RFC 2396: characters reserved for delimiting URLs.
      // We actually just auto-escape these.
      delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
  
      // RFC 2396: characters not allowed for various reasons.
      unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
  
      // Allowed by RFCs, but cause of XSS attacks.  Always escape these.
      autoEscape = ['\''].concat(unwise),
      // Characters that are never ever allowed in a hostname.
      // Note that any invalid chars are also handled, but these
      // are the ones that are *expected* to be seen, so we fast-path
      // them.
      nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
      hostEndingChars = ['/', '?', '#'],
      hostnameMaxLen = 255,
      hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
      hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
      // protocols that can allow "unsafe" and "unwise" chars.
      unsafeProtocol = {
        'javascript': true,
        'javascript:': true
      },
      // protocols that never have a hostname.
      hostlessProtocol = {
        'javascript': true,
        'javascript:': true
      },
      // protocols that always contain a // bit.
      slashedProtocol = {
        'http': true,
        'https': true,
        'ftp': true,
        'gopher': true,
        'file': true,
        'http:': true,
        'https:': true,
        'ftp:': true,
        'gopher:': true,
        'file:': true
      },
      querystring = require('querystring');
  
  function urlParse(url, parseQueryString, slashesDenoteHost) {
    if (url && util.isObject(url) && url instanceof Url) return url;
  
    var u = new Url;
    u.parse(url, parseQueryString, slashesDenoteHost);
    return u;
  }
  
  Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
    if (!util.isString(url)) {
      throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
    }
  
    // Copy chrome, IE, opera backslash-handling behavior.
    // Back slashes before the query string get converted to forward slashes
    // See: https://code.google.com/p/chromium/issues/detail?id=25916
    var queryIndex = url.indexOf('?'),
        splitter =
            (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
        uSplit = url.split(splitter),
        slashRegex = /\\/g;
    uSplit[0] = uSplit[0].replace(slashRegex, '/');
    url = uSplit.join(splitter);
  
    var rest = url;
  
    // trim before proceeding.
    // This is to support parse stuff like "  http://foo.com  \n"
    rest = rest.trim();
  
    if (!slashesDenoteHost && url.split('#').length === 1) {
      // Try fast path regexp
      var simplePath = simplePathPattern.exec(rest);
      if (simplePath) {
        this.path = rest;
        this.href = rest;
        this.pathname = simplePath[1];
        if (simplePath[2]) {
          this.search = simplePath[2];
          if (parseQueryString) {
            this.query = querystring.parse(this.search.substr(1));
          } else {
            this.query = this.search.substr(1);
          }
        } else if (parseQueryString) {
          this.search = '';
          this.query = {};
        }
        return this;
      }
    }
  
    var proto = protocolPattern.exec(rest);
    if (proto) {
      proto = proto[0];
      var lowerProto = proto.toLowerCase();
      this.protocol = lowerProto;
      rest = rest.substr(proto.length);
    }
  
    // figure out if it's got a host
    // user@server is *always* interpreted as a hostname, and url
    // resolution will treat //foo/bar as host=foo,path=bar because that's
    // how the browser resolves relative URLs.
    if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
      var slashes = rest.substr(0, 2) === '//';
      if (slashes && !(proto && hostlessProtocol[proto])) {
        rest = rest.substr(2);
        this.slashes = true;
      }
    }
  
    if (!hostlessProtocol[proto] &&
        (slashes || (proto && !slashedProtocol[proto]))) {
  
      // there's a hostname.
      // the first instance of /, ?, ;, or # ends the host.
      //
      // If there is an @ in the hostname, then non-host chars *are* allowed
      // to the left of the last @ sign, unless some host-ending character
      // comes *before* the @-sign.
      // URLs are obnoxious.
      //
      // ex:
      // http://a@b@c/ => user:a@b host:c
      // http://a@b?@c => user:a host:c path:/?@c
  
      // v0.12 TODO(isaacs): This is not quite how Chrome does things.
      // Review our test case against browsers more comprehensively.
  
      // find the first instance of any hostEndingChars
      var hostEnd = -1;
      for (var i = 0; i < hostEndingChars.length; i++) {
        var hec = rest.indexOf(hostEndingChars[i]);
        if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
          hostEnd = hec;
      }
  
      // at this point, either we have an explicit point where the
      // auth portion cannot go past, or the last @ char is the decider.
      var auth, atSign;
      if (hostEnd === -1) {
        // atSign can be anywhere.
        atSign = rest.lastIndexOf('@');
      } else {
        // atSign must be in auth portion.
        // http://a@b/c@d => host:b auth:a path:/c@d
        atSign = rest.lastIndexOf('@', hostEnd);
      }
  
      // Now we have a portion which is definitely the auth.
      // Pull that off.
      if (atSign !== -1) {
        auth = rest.slice(0, atSign);
        rest = rest.slice(atSign + 1);
        this.auth = decodeURIComponent(auth);
      }
  
      // the host is the remaining to the left of the first non-host char
      hostEnd = -1;
      for (var i = 0; i < nonHostChars.length; i++) {
        var hec = rest.indexOf(nonHostChars[i]);
        if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
          hostEnd = hec;
      }
      // if we still have not hit it, then the entire thing is a host.
      if (hostEnd === -1)
        hostEnd = rest.length;
  
      this.host = rest.slice(0, hostEnd);
      rest = rest.slice(hostEnd);
  
      // pull out port.
      this.parseHost();
  
      // we've indicated that there is a hostname,
      // so even if it's empty, it has to be present.
      this.hostname = this.hostname || '';
  
      // if hostname begins with [ and ends with ]
      // assume that it's an IPv6 address.
      var ipv6Hostname = this.hostname[0] === '[' &&
          this.hostname[this.hostname.length - 1] === ']';
  
      // validate a little.
      if (!ipv6Hostname) {
        var hostparts = this.hostname.split(/\./);
        for (var i = 0, l = hostparts.length; i < l; i++) {
          var part = hostparts[i];
          if (!part) continue;
          if (!part.match(hostnamePartPattern)) {
            var newpart = '';
            for (var j = 0, k = part.length; j < k; j++) {
              if (part.charCodeAt(j) > 127) {
                // we replace non-ASCII char with a temporary placeholder
                // we need this to make sure size of hostname is not
                // broken by replacing non-ASCII by nothing
                newpart += 'x';
              } else {
                newpart += part[j];
              }
            }
            // we test again with ASCII char only
            if (!newpart.match(hostnamePartPattern)) {
              var validParts = hostparts.slice(0, i);
              var notHost = hostparts.slice(i + 1);
              var bit = part.match(hostnamePartStart);
              if (bit) {
                validParts.push(bit[1]);
                notHost.unshift(bit[2]);
              }
              if (notHost.length) {
                rest = '/' + notHost.join('.') + rest;
              }
              this.hostname = validParts.join('.');
              break;
            }
          }
        }
      }
  
      if (this.hostname.length > hostnameMaxLen) {
        this.hostname = '';
      } else {
        // hostnames are always lower case.
        this.hostname = this.hostname.toLowerCase();
      }
  
      if (!ipv6Hostname) {
        // IDNA Support: Returns a punycoded representation of "domain".
        // It only converts parts of the domain name that
        // have non-ASCII characters, i.e. it doesn't matter if
        // you call it with a domain that already is ASCII-only.
        this.hostname = punycode.toASCII(this.hostname);
      }
  
      var p = this.port ? ':' + this.port : '';
      var h = this.hostname || '';
      this.host = h + p;
      this.href += this.host;
  
      // strip [ and ] from the hostname
      // the host field still retains them, though
      if (ipv6Hostname) {
        this.hostname = this.hostname.substr(1, this.hostname.length - 2);
        if (rest[0] !== '/') {
          rest = '/' + rest;
        }
      }
    }
  
    // now rest is set to the post-host stuff.
    // chop off any delim chars.
    if (!unsafeProtocol[lowerProto]) {
  
      // First, make 100% sure that any "autoEscape" chars get
      // escaped, even if encodeURIComponent doesn't think they
      // need to be.
      for (var i = 0, l = autoEscape.length; i < l; i++) {
        var ae = autoEscape[i];
        if (rest.indexOf(ae) === -1)
          continue;
        var esc = encodeURIComponent(ae);
        if (esc === ae) {
          esc = escape(ae);
        }
        rest = rest.split(ae).join(esc);
      }
    }
  
  
    // chop off from the tail first.
    var hash = rest.indexOf('#');
    if (hash !== -1) {
      // got a fragment string.
      this.hash = rest.substr(hash);
      rest = rest.slice(0, hash);
    }
    var qm = rest.indexOf('?');
    if (qm !== -1) {
      this.search = rest.substr(qm);
      this.query = rest.substr(qm + 1);
      if (parseQueryString) {
        this.query = querystring.parse(this.query);
      }
      rest = rest.slice(0, qm);
    } else if (parseQueryString) {
      // no query string, but parseQueryString still requested
      this.search = '';
      this.query = {};
    }
    if (rest) this.pathname = rest;
    if (slashedProtocol[lowerProto] &&
        this.hostname && !this.pathname) {
      this.pathname = '/';
    }
  
    //to support http.request
    if (this.pathname || this.search) {
      var p = this.pathname || '';
      var s = this.search || '';
      this.path = p + s;
    }
  
    // finally, reconstruct the href based on what has been validated.
    this.href = this.format();
    return this;
  };
  
  // format a parsed object into a url string
  function urlFormat(obj) {
    // ensure it's an object, and not a string url.
    // If it's an obj, this is a no-op.
    // this way, you can call url_format() on strings
    // to clean up potentially wonky urls.
    if (util.isString(obj)) obj = urlParse(obj);
    if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
    return obj.format();
  }
  
  Url.prototype.format = function() {
    var auth = this.auth || '';
    if (auth) {
      auth = encodeURIComponent(auth);
      auth = auth.replace(/%3A/i, ':');
      auth += '@';
    }
  
    var protocol = this.protocol || '',
        pathname = this.pathname || '',
        hash = this.hash || '',
        host = false,
        query = '';
  
    if (this.host) {
      host = auth + this.host;
    } else if (this.hostname) {
      host = auth + (this.hostname.indexOf(':') === -1 ?
          this.hostname :
          '[' + this.hostname + ']');
      if (this.port) {
        host += ':' + this.port;
      }
    }
  
    if (this.query &&
        util.isObject(this.query) &&
        Object.keys(this.query).length) {
      query = querystring.stringify(this.query);
    }
  
    var search = this.search || (query && ('?' + query)) || '';
  
    if (protocol && protocol.substr(-1) !== ':') protocol += ':';
  
    // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
    // unless they had them to begin with.
    if (this.slashes ||
        (!protocol || slashedProtocol[protocol]) && host !== false) {
      host = '//' + (host || '');
      if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
    } else if (!host) {
      host = '';
    }
  
    if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
    if (search && search.charAt(0) !== '?') search = '?' + search;
  
    pathname = pathname.replace(/[?#]/g, function(match) {
      return encodeURIComponent(match);
    });
    search = search.replace('#', '%23');
  
    return protocol + host + pathname + search + hash;
  };
  
  function urlResolve(source, relative) {
    return urlParse(source, false, true).resolve(relative);
  }
  
  Url.prototype.resolve = function(relative) {
    return this.resolveObject(urlParse(relative, false, true)).format();
  };
  
  function urlResolveObject(source, relative) {
    if (!source) return relative;
    return urlParse(source, false, true).resolveObject(relative);
  }
  
  Url.prototype.resolveObject = function(relative) {
    if (util.isString(relative)) {
      var rel = new Url();
      rel.parse(relative, false, true);
      relative = rel;
    }
  
    var result = new Url();
    var tkeys = Object.keys(this);
    for (var tk = 0; tk < tkeys.length; tk++) {
      var tkey = tkeys[tk];
      result[tkey] = this[tkey];
    }
  
    // hash is always overridden, no matter what.
    // even href="" will remove it.
    result.hash = relative.hash;
  
    // if the relative url is empty, then there's nothing left to do here.
    if (relative.href === '') {
      result.href = result.format();
      return result;
    }
  
    // hrefs like //foo/bar always cut to the protocol.
    if (relative.slashes && !relative.protocol) {
      // take everything except the protocol from relative
      var rkeys = Object.keys(relative);
      for (var rk = 0; rk < rkeys.length; rk++) {
        var rkey = rkeys[rk];
        if (rkey !== 'protocol')
          result[rkey] = relative[rkey];
      }
  
      //urlParse appends trailing / to urls like http://www.example.com
      if (slashedProtocol[result.protocol] &&
          result.hostname && !result.pathname) {
        result.path = result.pathname = '/';
      }
  
      result.href = result.format();
      return result;
    }
  
    if (relative.protocol && relative.protocol !== result.protocol) {
      // if it's a known url protocol, then changing
      // the protocol does weird things
      // first, if it's not file:, then we MUST have a host,
      // and if there was a path
      // to begin with, then we MUST have a path.
      // if it is file:, then the host is dropped,
      // because that's known to be hostless.
      // anything else is assumed to be absolute.
      if (!slashedProtocol[relative.protocol]) {
        var keys = Object.keys(relative);
        for (var v = 0; v < keys.length; v++) {
          var k = keys[v];
          result[k] = relative[k];
        }
        result.href = result.format();
        return result;
      }
  
      result.protocol = relative.protocol;
      if (!relative.host && !hostlessProtocol[relative.protocol]) {
        var relPath = (relative.pathname || '').split('/');
        while (relPath.length && !(relative.host = relPath.shift()));
        if (!relative.host) relative.host = '';
        if (!relative.hostname) relative.hostname = '';
        if (relPath[0] !== '') relPath.unshift('');
        if (relPath.length < 2) relPath.unshift('');
        result.pathname = relPath.join('/');
      } else {
        result.pathname = relative.pathname;
      }
      result.search = relative.search;
      result.query = relative.query;
      result.host = relative.host || '';
      result.auth = relative.auth;
      result.hostname = relative.hostname || relative.host;
      result.port = relative.port;
      // to support http.request
      if (result.pathname || result.search) {
        var p = result.pathname || '';
        var s = result.search || '';
        result.path = p + s;
      }
      result.slashes = result.slashes || relative.slashes;
      result.href = result.format();
      return result;
    }
  
    var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
        isRelAbs = (
            relative.host ||
            relative.pathname && relative.pathname.charAt(0) === '/'
        ),
        mustEndAbs = (isRelAbs || isSourceAbs ||
                      (result.host && relative.pathname)),
        removeAllDots = mustEndAbs,
        srcPath = result.pathname && result.pathname.split('/') || [],
        relPath = relative.pathname && relative.pathname.split('/') || [],
        psychotic = result.protocol && !slashedProtocol[result.protocol];
  
    // if the url is a non-slashed url, then relative
    // links like ../.. should be able
    // to crawl up to the hostname, as well.  This is strange.
    // result.protocol has already been set by now.
    // Later on, put the first path part into the host field.
    if (psychotic) {
      result.hostname = '';
      result.port = null;
      if (result.host) {
        if (srcPath[0] === '') srcPath[0] = result.host;
        else srcPath.unshift(result.host);
      }
      result.host = '';
      if (relative.protocol) {
        relative.hostname = null;
        relative.port = null;
        if (relative.host) {
          if (relPath[0] === '') relPath[0] = relative.host;
          else relPath.unshift(relative.host);
        }
        relative.host = null;
      }
      mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
    }
  
    if (isRelAbs) {
      // it's absolute.
      result.host = (relative.host || relative.host === '') ?
                    relative.host : result.host;
      result.hostname = (relative.hostname || relative.hostname === '') ?
                        relative.hostname : result.hostname;
      result.search = relative.search;
      result.query = relative.query;
      srcPath = relPath;
      // fall through to the dot-handling below.
    } else if (relPath.length) {
      // it's relative
      // throw away the existing file, and take the new path instead.
      if (!srcPath) srcPath = [];
      srcPath.pop();
      srcPath = srcPath.concat(relPath);
      result.search = relative.search;
      result.query = relative.query;
    } else if (!util.isNullOrUndefined(relative.search)) {
      // just pull out the search.
      // like href='?foo'.
      // Put this after the other two cases because it simplifies the booleans
      if (psychotic) {
        result.hostname = result.host = srcPath.shift();
        //occationaly the auth can get stuck only in host
        //this especially happens in cases like
        //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
        var authInHost = result.host && result.host.indexOf('@') > 0 ?
                         result.host.split('@') : false;
        if (authInHost) {
          result.auth = authInHost.shift();
          result.host = result.hostname = authInHost.shift();
        }
      }
      result.search = relative.search;
      result.query = relative.query;
      //to support http.request
      if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
        result.path = (result.pathname ? result.pathname : '') +
                      (result.search ? result.search : '');
      }
      result.href = result.format();
      return result;
    }
  
    if (!srcPath.length) {
      // no path at all.  easy.
      // we've already handled the other stuff above.
      result.pathname = null;
      //to support http.request
      if (result.search) {
        result.path = '/' + result.search;
      } else {
        result.path = null;
      }
      result.href = result.format();
      return result;
    }
  
    // if a url ENDs in . or .., then it must get a trailing slash.
    // however, if it ends in anything else non-slashy,
    // then it must NOT get a trailing slash.
    var last = srcPath.slice(-1)[0];
    var hasTrailingSlash = (
        (result.host || relative.host || srcPath.length > 1) &&
        (last === '.' || last === '..') || last === '');
  
    // strip single dots, resolve double dots to parent dir
    // if the path tries to go above the root, `up` ends up > 0
    var up = 0;
    for (var i = srcPath.length; i >= 0; i--) {
      last = srcPath[i];
      if (last === '.') {
        srcPath.splice(i, 1);
      } else if (last === '..') {
        srcPath.splice(i, 1);
        up++;
      } else if (up) {
        srcPath.splice(i, 1);
        up--;
      }
    }
  
    // if the path is allowed to go above the root, restore leading ..s
    if (!mustEndAbs && !removeAllDots) {
      for (; up--; up) {
        srcPath.unshift('..');
      }
    }
  
    if (mustEndAbs && srcPath[0] !== '' &&
        (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
      srcPath.unshift('');
    }
  
    if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
      srcPath.push('');
    }
  
    var isAbsolute = srcPath[0] === '' ||
        (srcPath[0] && srcPath[0].charAt(0) === '/');
  
    // put the host back
    if (psychotic) {
      result.hostname = result.host = isAbsolute ? '' :
                                      srcPath.length ? srcPath.shift() : '';
      //occationaly the auth can get stuck only in host
      //this especially happens in cases like
      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
      var authInHost = result.host && result.host.indexOf('@') > 0 ?
                       result.host.split('@') : false;
      if (authInHost) {
        result.auth = authInHost.shift();
        result.host = result.hostname = authInHost.shift();
      }
    }
  
    mustEndAbs = mustEndAbs || (result.host && srcPath.length);
  
    if (mustEndAbs && !isAbsolute) {
      srcPath.unshift('');
    }
  
    if (!srcPath.length) {
      result.pathname = null;
      result.path = null;
    } else {
      result.pathname = srcPath.join('/');
    }
  
    //to support request.http
    if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
      result.path = (result.pathname ? result.pathname : '') +
                    (result.search ? result.search : '');
    }
    result.auth = relative.auth || result.auth;
    result.slashes = result.slashes || relative.slashes;
    result.href = result.format();
    return result;
  };
  
  Url.prototype.parseHost = function() {
    var host = this.host;
    var port = portPattern.exec(host);
    if (port) {
      port = port[0];
      if (port !== ':') {
        this.port = port.substr(1);
      }
      host = host.substr(0, host.length - port.length);
    }
    if (host) this.hostname = host;
  };
  
  },{"./util":156,"punycode":138,"querystring":141}],156:[function(require,module,exports){
  'use strict';
  
  module.exports = {
    isString: function(arg) {
      return typeof(arg) === 'string';
    },
    isObject: function(arg) {
      return typeof(arg) === 'object' && arg !== null;
    },
    isNull: function(arg) {
      return arg === null;
    },
    isNullOrUndefined: function(arg) {
      return arg == null;
    }
  };
  
  },{}],157:[function(require,module,exports){
  (function (global){
  
  /**
   * Module exports.
   */
  
  module.exports = deprecate;
  
  /**
   * Mark that a method should not be used.
   * Returns a modified function which warns once by default.
   *
   * If `localStorage.noDeprecation = true` is set, then it is a no-op.
   *
   * If `localStorage.throwDeprecation = true` is set, then deprecated functions
   * will throw an Error when invoked.
   *
   * If `localStorage.traceDeprecation = true` is set, then deprecated functions
   * will invoke `console.trace()` instead of `console.error()`.
   *
   * @param {Function} fn - the function to deprecate
   * @param {String} msg - the string to print to the console when `fn` is invoked
   * @returns {Function} a new "deprecated" version of `fn`
   * @api public
   */
  
  function deprecate (fn, msg) {
    if (config('noDeprecation')) {
      return fn;
    }
  
    var warned = false;
    function deprecated() {
      if (!warned) {
        if (config('throwDeprecation')) {
          throw new Error(msg);
        } else if (config('traceDeprecation')) {
          console.trace(msg);
        } else {
          console.warn(msg);
        }
        warned = true;
      }
      return fn.apply(this, arguments);
    }
  
    return deprecated;
  }
  
  /**
   * Checks `localStorage` for boolean values for the given `name`.
   *
   * @param {String} name
   * @returns {Boolean}
   * @api private
   */
  
  function config (name) {
    // accessing global.localStorage can trigger a DOMException in sandboxed iframes
    try {
      if (!global.localStorage) return false;
    } catch (_) {
      return false;
    }
    var val = global.localStorage[name];
    if (null == val) return false;
    return String(val).toLowerCase() === 'true';
  }
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],158:[function(require,module,exports){
  arguments[4][133][0].apply(exports,arguments)
  },{"dup":133}],159:[function(require,module,exports){
  module.exports = function isBuffer(arg) {
    return arg && typeof arg === 'object'
      && typeof arg.copy === 'function'
      && typeof arg.fill === 'function'
      && typeof arg.readUInt8 === 'function';
  }
  },{}],160:[function(require,module,exports){
  (function (process,global){
  // Copyright Joyent, Inc. and other Node 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.
  
  var formatRegExp = /%[sdj%]/g;
  exports.format = function(f) {
    if (!isString(f)) {
      var objects = [];
      for (var i = 0; i < arguments.length; i++) {
        objects.push(inspect(arguments[i]));
      }
      return objects.join(' ');
    }
  
    var i = 1;
    var args = arguments;
    var len = args.length;
    var str = String(f).replace(formatRegExp, function(x) {
      if (x === '%%') return '%';
      if (i >= len) return x;
      switch (x) {
        case '%s': return String(args[i++]);
        case '%d': return Number(args[i++]);
        case '%j':
          try {
            return JSON.stringify(args[i++]);
          } catch (_) {
            return '[Circular]';
          }
        default:
          return x;
      }
    });
    for (var x = args[i]; i < len; x = args[++i]) {
      if (isNull(x) || !isObject(x)) {
        str += ' ' + x;
      } else {
        str += ' ' + inspect(x);
      }
    }
    return str;
  };
  
  
  // Mark that a method should not be used.
  // Returns a modified function which warns once by default.
  // If --no-deprecation is set, then it is a no-op.
  exports.deprecate = function(fn, msg) {
    // Allow for deprecating things in the process of starting up.
    if (isUndefined(global.process)) {
      return function() {
        return exports.deprecate(fn, msg).apply(this, arguments);
      };
    }
  
    if (process.noDeprecation === true) {
      return fn;
    }
  
    var warned = false;
    function deprecated() {
      if (!warned) {
        if (process.throwDeprecation) {
          throw new Error(msg);
        } else if (process.traceDeprecation) {
          console.trace(msg);
        } else {
          console.error(msg);
        }
        warned = true;
      }
      return fn.apply(this, arguments);
    }
  
    return deprecated;
  };
  
  
  var debugs = {};
  var debugEnviron;
  exports.debuglog = function(set) {
    if (isUndefined(debugEnviron))
      debugEnviron = process.env.NODE_DEBUG || '';
    set = set.toUpperCase();
    if (!debugs[set]) {
      if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
        var pid = process.pid;
        debugs[set] = function() {
          var msg = exports.format.apply(exports, arguments);
          console.error('%s %d: %s', set, pid, msg);
        };
      } else {
        debugs[set] = function() {};
      }
    }
    return debugs[set];
  };
  
  
  /**
   * Echos the value of a value. Trys to print the value out
   * in the best way possible given the different types.
   *
   * @param {Object} obj The object to print out.
   * @param {Object} opts Optional options object that alters the output.
   */
  /* legacy: obj, showHidden, depth, colors*/
  function inspect(obj, opts) {
    // default options
    var ctx = {
      seen: [],
      stylize: stylizeNoColor
    };
    // legacy...
    if (arguments.length >= 3) ctx.depth = arguments[2];
    if (arguments.length >= 4) ctx.colors = arguments[3];
    if (isBoolean(opts)) {
      // legacy...
      ctx.showHidden = opts;
    } else if (opts) {
      // got an "options" object
      exports._extend(ctx, opts);
    }
    // set default options
    if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
    if (isUndefined(ctx.depth)) ctx.depth = 2;
    if (isUndefined(ctx.colors)) ctx.colors = false;
    if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
    if (ctx.colors) ctx.stylize = stylizeWithColor;
    return formatValue(ctx, obj, ctx.depth);
  }
  exports.inspect = inspect;
  
  
  // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
  inspect.colors = {
    'bold' : [1, 22],
    'italic' : [3, 23],
    'underline' : [4, 24],
    'inverse' : [7, 27],
    'white' : [37, 39],
    'grey' : [90, 39],
    'black' : [30, 39],
    'blue' : [34, 39],
    'cyan' : [36, 39],
    'green' : [32, 39],
    'magenta' : [35, 39],
    'red' : [31, 39],
    'yellow' : [33, 39]
  };
  
  // Don't use 'blue' not visible on cmd.exe
  inspect.styles = {
    'special': 'cyan',
    'number': 'yellow',
    'boolean': 'yellow',
    'undefined': 'grey',
    'null': 'bold',
    'string': 'green',
    'date': 'magenta',
    // "name": intentionally not styling
    'regexp': 'red'
  };
  
  
  function stylizeWithColor(str, styleType) {
    var style = inspect.styles[styleType];
  
    if (style) {
      return '\u001b[' + inspect.colors[style][0] + 'm' + str +
             '\u001b[' + inspect.colors[style][1] + 'm';
    } else {
      return str;
    }
  }
  
  
  function stylizeNoColor(str, styleType) {
    return str;
  }
  
  
  function arrayToHash(array) {
    var hash = {};
  
    array.forEach(function(val, idx) {
      hash[val] = true;
    });
  
    return hash;
  }
  
  
  function formatValue(ctx, value, recurseTimes) {
    // Provide a hook for user-specified inspect functions.
    // Check that value is an object with an inspect function on it
    if (ctx.customInspect &&
        value &&
        isFunction(value.inspect) &&
        // Filter out the util module, it's inspect function is special
        value.inspect !== exports.inspect &&
        // Also filter out any prototype objects using the circular check.
        !(value.constructor && value.constructor.prototype === value)) {
      var ret = value.inspect(recurseTimes, ctx);
      if (!isString(ret)) {
        ret = formatValue(ctx, ret, recurseTimes);
      }
      return ret;
    }
  
    // Primitive types cannot have properties
    var primitive = formatPrimitive(ctx, value);
    if (primitive) {
      return primitive;
    }
  
    // Look up the keys of the object.
    var keys = Object.keys(value);
    var visibleKeys = arrayToHash(keys);
  
    if (ctx.showHidden) {
      keys = Object.getOwnPropertyNames(value);
    }
  
    // IE doesn't make error fields non-enumerable
    // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
    if (isError(value)
        && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
      return formatError(value);
    }
  
    // Some type of object without properties can be shortcutted.
    if (keys.length === 0) {
      if (isFunction(value)) {
        var name = value.name ? ': ' + value.name : '';
        return ctx.stylize('[Function' + name + ']', 'special');
      }
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      }
      if (isDate(value)) {
        return ctx.stylize(Date.prototype.toString.call(value), 'date');
      }
      if (isError(value)) {
        return formatError(value);
      }
    }
  
    var base = '', array = false, braces = ['{', '}'];
  
    // Make Array say that they are Array
    if (isArray(value)) {
      array = true;
      braces = ['[', ']'];
    }
  
    // Make functions say that they are functions
    if (isFunction(value)) {
      var n = value.name ? ': ' + value.name : '';
      base = ' [Function' + n + ']';
    }
  
    // Make RegExps say that they are RegExps
    if (isRegExp(value)) {
      base = ' ' + RegExp.prototype.toString.call(value);
    }
  
    // Make dates with properties first say the date
    if (isDate(value)) {
      base = ' ' + Date.prototype.toUTCString.call(value);
    }
  
    // Make error with message first say the error
    if (isError(value)) {
      base = ' ' + formatError(value);
    }
  
    if (keys.length === 0 && (!array || value.length == 0)) {
      return braces[0] + base + braces[1];
    }
  
    if (recurseTimes < 0) {
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      } else {
        return ctx.stylize('[Object]', 'special');
      }
    }
  
    ctx.seen.push(value);
  
    var output;
    if (array) {
      output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
    } else {
      output = keys.map(function(key) {
        return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
      });
    }
  
    ctx.seen.pop();
  
    return reduceToSingleString(output, base, braces);
  }
  
  
  function formatPrimitive(ctx, value) {
    if (isUndefined(value))
      return ctx.stylize('undefined', 'undefined');
    if (isString(value)) {
      var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                                               .replace(/'/g, "\\'")
                                               .replace(/\\"/g, '"') + '\'';
      return ctx.stylize(simple, 'string');
    }
    if (isNumber(value))
      return ctx.stylize('' + value, 'number');
    if (isBoolean(value))
      return ctx.stylize('' + value, 'boolean');
    // For some reason typeof null is "object", so special case here.
    if (isNull(value))
      return ctx.stylize('null', 'null');
  }
  
  
  function formatError(value) {
    return '[' + Error.prototype.toString.call(value) + ']';
  }
  
  
  function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
    var output = [];
    for (var i = 0, l = value.length; i < l; ++i) {
      if (hasOwnProperty(value, String(i))) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            String(i), true));
      } else {
        output.push('');
      }
    }
    keys.forEach(function(key) {
      if (!key.match(/^\d+$/)) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            key, true));
      }
    });
    return output;
  }
  
  
  function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
    var name, str, desc;
    desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
    if (desc.get) {
      if (desc.set) {
        str = ctx.stylize('[Getter/Setter]', 'special');
      } else {
        str = ctx.stylize('[Getter]', 'special');
      }
    } else {
      if (desc.set) {
        str = ctx.stylize('[Setter]', 'special');
      }
    }
    if (!hasOwnProperty(visibleKeys, key)) {
      name = '[' + key + ']';
    }
    if (!str) {
      if (ctx.seen.indexOf(desc.value) < 0) {
        if (isNull(recurseTimes)) {
          str = formatValue(ctx, desc.value, null);
        } else {
          str = formatValue(ctx, desc.value, recurseTimes - 1);
        }
        if (str.indexOf('\n') > -1) {
          if (array) {
            str = str.split('\n').map(function(line) {
              return '  ' + line;
            }).join('\n').substr(2);
          } else {
            str = '\n' + str.split('\n').map(function(line) {
              return '   ' + line;
            }).join('\n');
          }
        }
      } else {
        str = ctx.stylize('[Circular]', 'special');
      }
    }
    if (isUndefined(name)) {
      if (array && key.match(/^\d+$/)) {
        return str;
      }
      name = JSON.stringify('' + key);
      if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
        name = name.substr(1, name.length - 2);
        name = ctx.stylize(name, 'name');
      } else {
        name = name.replace(/'/g, "\\'")
                   .replace(/\\"/g, '"')
                   .replace(/(^"|"$)/g, "'");
        name = ctx.stylize(name, 'string');
      }
    }
  
    return name + ': ' + str;
  }
  
  
  function reduceToSingleString(output, base, braces) {
    var numLinesEst = 0;
    var length = output.reduce(function(prev, cur) {
      numLinesEst++;
      if (cur.indexOf('\n') >= 0) numLinesEst++;
      return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
    }, 0);
  
    if (length > 60) {
      return braces[0] +
             (base === '' ? '' : base + '\n ') +
             ' ' +
             output.join(',\n  ') +
             ' ' +
             braces[1];
    }
  
    return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
  }
  
  
  // NOTE: These type checking functions intentionally don't use `instanceof`
  // because it is fragile and can be easily faked with `Object.create()`.
  function isArray(ar) {
    return Array.isArray(ar);
  }
  exports.isArray = isArray;
  
  function isBoolean(arg) {
    return typeof arg === 'boolean';
  }
  exports.isBoolean = isBoolean;
  
  function isNull(arg) {
    return arg === null;
  }
  exports.isNull = isNull;
  
  function isNullOrUndefined(arg) {
    return arg == null;
  }
  exports.isNullOrUndefined = isNullOrUndefined;
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  exports.isNumber = isNumber;
  
  function isString(arg) {
    return typeof arg === 'string';
  }
  exports.isString = isString;
  
  function isSymbol(arg) {
    return typeof arg === 'symbol';
  }
  exports.isSymbol = isSymbol;
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  exports.isUndefined = isUndefined;
  
  function isRegExp(re) {
    return isObject(re) && objectToString(re) === '[object RegExp]';
  }
  exports.isRegExp = isRegExp;
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  exports.isObject = isObject;
  
  function isDate(d) {
    return isObject(d) && objectToString(d) === '[object Date]';
  }
  exports.isDate = isDate;
  
  function isError(e) {
    return isObject(e) &&
        (objectToString(e) === '[object Error]' || e instanceof Error);
  }
  exports.isError = isError;
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  exports.isFunction = isFunction;
  
  function isPrimitive(arg) {
    return arg === null ||
           typeof arg === 'boolean' ||
           typeof arg === 'number' ||
           typeof arg === 'string' ||
           typeof arg === 'symbol' ||  // ES6 symbol
           typeof arg === 'undefined';
  }
  exports.isPrimitive = isPrimitive;
  
  exports.isBuffer = require('./support/isBuffer');
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  
  function pad(n) {
    return n < 10 ? '0' + n.toString(10) : n.toString(10);
  }
  
  
  var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
                'Oct', 'Nov', 'Dec'];
  
  // 26 Feb 16:19:34
  function timestamp() {
    var d = new Date();
    var time = [pad(d.getHours()),
                pad(d.getMinutes()),
                pad(d.getSeconds())].join(':');
    return [d.getDate(), months[d.getMonth()], time].join(' ');
  }
  
  
  // log is just a thin wrapper to console.log that prepends a timestamp
  exports.log = function() {
    console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
  };
  
  
  /**
   * Inherit the prototype methods from one constructor into another.
   *
   * The Function.prototype.inherits from lang.js rewritten as a standalone
   * function (not on Function.prototype). NOTE: If this file is to be loaded
   * during bootstrapping this function needs to be rewritten using some native
   * functions as prototype setup using normal JavaScript does not work as
   * expected during bootstrapping (see mirror.js in r114903).
   *
   * @param {function} ctor Constructor function which needs to inherit the
   *     prototype.
   * @param {function} superCtor Constructor function to inherit prototype from.
   */
  exports.inherits = require('inherits');
  
  exports._extend = function(origin, add) {
    // Don't do anything if add isn't an object
    if (!add || !isObject(add)) return origin;
  
    var keys = Object.keys(add);
    var i = keys.length;
    while (i--) {
      origin[keys[i]] = add[keys[i]];
    }
    return origin;
  };
  
  function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }
  
  }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"./support/isBuffer":159,"_process":137,"inherits":158}]},{},[3])(3)
  });