<commit_before>var EventEmitter = require('events').EventEmitter
var inherits     = require('util').inherits
var ranges       = require('string-range')
var fixRange     = require('level-fix-range')
var xtend        = require('xtend')

inherits(SubDB, EventEmitter)

function SubDB (db, prefix, options) {
  if('string' === typeof options) {
    console.error('db.sublevel(name, seperator<string>) is depreciated')
    console.error('use db.sublevel(name, {sep: separator})) if you must')
    options = {sep: options}
  }
  if(!(this instanceof SubDB)) return new SubDB(db, prefix, options)
  if(!db)     throw new Error('must provide db')
  if(!prefix) throw new Error('must provide prefix')

  options = options || {}
  options.sep = options.sep || '\xff'

  this._parent = db
  this._options = options
  this._prefix = prefix
  this._root = root(this)
  db.sublevels[prefix] = this
  this.sublevels = {}
  this.methods = {}
  var self = this
  this.hooks = {
    pre: function () {
      return self.pre.apply(self, arguments)
    },
    post: function () {
      return self.post.apply(self, arguments)
    }
  }
}

var SDB = SubDB.prototype

SDB._key = function (key) {
  var sep = this._options.sep
  return sep
    + this._prefix
    + sep
    + key
}

SDB._getOptsAndCb = function (opts, cb) {
  if (typeof opts == 'function') {
    cb = opts
    opts = {}
  }
  return { opts: xtend(opts, this._options), cb: cb }
}

SDB.sublevel = function (prefix, options) {
  if(this.sublevels[prefix])
    return this.sublevels[prefix]
  return new SubDB(this, prefix, options || this._options)
}

SDB.put = function (key, value, opts, cb) {
  var res = this._getOptsAndCb(opts, cb)
  this._root.put(this.prefix(key), value, res.opts, res.cb)
}

SDB.get = function (key, opts, cb) {
  var res = this._getOptsAndCb(opts, cb)
  this._root.get(this.prefix(key), res.opts, res.cb)
}

SDB.del = function (key, opts, cb) {
  this._root.del(this.prefix(key), opts, cb)
}

SDB.batch = function (changes, opts, cb) {
  var self = this
  changes.forEach(function (ch) {
    //OH YEAH, WE NEED TO VALIDATE THAT UPDATING THIS KEY/PREFIX IS ALLOWED
    if('string' === typeof ch.prefix) {
      ch.key = ch.prefix + ch.key
    } else
    ch.key = (ch.prefix || self).prefix(ch.key)
    if(ch.prefix) ch.prefix = null
  })
  this._root.batch(changes, opts, cb)
}

SDB.prefix = function (key) {
  var sep = this._options.sep
  return this._parent.prefix() + sep + this._prefix + sep + (key || '')
}

SDB.keyStream =
SDB.createKeyStream = function (opts) {
  opts = opts || {}
  opts.keys = true
  opts.values = false
  return this.createReadStream(opts)
}

SDB.valueStream =
SDB.createValueStream = function (opts) {
  opts = opts || {}
  opts.keys = false
  opts.values = true
  opts.keys = false
  return this.createReadStream(opts)
}

function selectivelyMerge(_opts, opts) {
  [ 'valueEncoding'
  , 'encoding'
  , 'keyEncoding'
  , 'reverse'
  , 'values'
  , 'keys'
  , 'limit'
  , 'fillCache'
  ]
  .forEach(function (k) {
    if (opts.hasOwnProperty(k)) _opts[k] = opts[k]
  })
}

SDB.readStream =
SDB.createReadStream = function (opts) {
  opts = opts || {}
  var r = root(this)
  var p = this.prefix()

  var _opts = ranges.prefix(opts, p)
  selectivelyMerge(_opts, xtend(opts, this._options))

  var s = r.createReadStream(_opts)

  if(_opts.values === false) {
    var emit = s.emit
    s.emit = function (event, val) {
      if(event === 'data') {
        console.log(event, val, _opts)
        emit.call(this, 'data', val.substring(p.length))
      } else
        emit.call(this, event, val)
    }
    return s
  } else if(_opts.keys === false)
    return s
  else
    return s.on('data', function (d) {
      //mutate the prefix!
      //this doesn't work for createKeyStream admittedly.
      d.key = d.key.substring(p.length)
    })
}

SDB.writeStream =
SDB.createWriteStream = function () {
  var r = root(this)
  var p = this.prefix()
  var ws = r.createWriteStream.apply(r, arguments)
  var write = ws.write
  ws.write = function (data) {
    data.key = p + data.key
    return write.call(ws, data)
  }
  return ws
}

SDB.approximateSize = function () {
  var r = root(db)
  return r.approximateSize.apply(r, arguments)
}

function root(db) {
  if(!db._parent) return db
  return root(db._parent)
}

SDB.pre = function (range, hook) {
  if(!hook) hook = range, range = null
  range = ranges.prefix(range, this.prefix(), this._options.sep)
  var r = root(this._parent)
  var p = this.prefix()
  return r.hooks.pre(fixRange(range), function (ch, add) {
    hook({
      key: ch.key.substring(p.length),
      value: ch.value,
      type: ch.type
    }, function (ch, _p) {
      //maybe remove the second add arg now
      //that op can have prefix?
      add(ch, ch.prefix ? _p : (_p || p))
    })
  })
}

SDB.post = function (range, hook) {
  if(!hook) hook = range, range = null
  var r = root(this._parent)
  var p = this.prefix()
  range = ranges.prefix(range, p, this._options.sep)
  return r.hooks.post(fixRange(range), function (data) {
    hook({key: data.key.substring(p.length), value: data.value, type: data.type})
  })
}

var exports = module.exports = SubDB

<commit_msg>remove logging<commit_after>var EventEmitter = require('events').EventEmitter
var inherits     = require('util').inherits
var ranges       = require('string-range')
var fixRange     = require('level-fix-range')
var xtend        = require('xtend')

inherits(SubDB, EventEmitter)

function SubDB (db, prefix, options) {
  if('string' === typeof options) {
    console.error('db.sublevel(name, seperator<string>) is depreciated')
    console.error('use db.sublevel(name, {sep: separator})) if you must')
    options = {sep: options}
  }
  if(!(this instanceof SubDB)) return new SubDB(db, prefix, options)
  if(!db)     throw new Error('must provide db')
  if(!prefix) throw new Error('must provide prefix')

  options = options || {}
  options.sep = options.sep || '\xff'

  this._parent = db
  this._options = options
  this._prefix = prefix
  this._root = root(this)
  db.sublevels[prefix] = this
  this.sublevels = {}
  this.methods = {}
  var self = this
  this.hooks = {
    pre: function () {
      return self.pre.apply(self, arguments)
    },
    post: function () {
      return self.post.apply(self, arguments)
    }
  }
}

var SDB = SubDB.prototype

SDB._key = function (key) {
  var sep = this._options.sep
  return sep
    + this._prefix
    + sep
    + key
}

SDB._getOptsAndCb = function (opts, cb) {
  if (typeof opts == 'function') {
    cb = opts
    opts = {}
  }
  return { opts: xtend(opts, this._options), cb: cb }
}

SDB.sublevel = function (prefix, options) {
  if(this.sublevels[prefix])
    return this.sublevels[prefix]
  return new SubDB(this, prefix, options || this._options)
}

SDB.put = function (key, value, opts, cb) {
  var res = this._getOptsAndCb(opts, cb)
  this._root.put(this.prefix(key), value, res.opts, res.cb)
}

SDB.get = function (key, opts, cb) {
  var res = this._getOptsAndCb(opts, cb)
  this._root.get(this.prefix(key), res.opts, res.cb)
}

SDB.del = function (key, opts, cb) {
  this._root.del(this.prefix(key), opts, cb)
}

SDB.batch = function (changes, opts, cb) {
  var self = this
  changes.forEach(function (ch) {
    //OH YEAH, WE NEED TO VALIDATE THAT UPDATING THIS KEY/PREFIX IS ALLOWED
    if('string' === typeof ch.prefix) {
      ch.key = ch.prefix + ch.key
    } else
    ch.key = (ch.prefix || self).prefix(ch.key)
    if(ch.prefix) ch.prefix = null
  })
  this._root.batch(changes, opts, cb)
}

SDB.prefix = function (key) {
  var sep = this._options.sep
  return this._parent.prefix() + sep + this._prefix + sep + (key || '')
}

SDB.keyStream =
SDB.createKeyStream = function (opts) {
  opts = opts || {}
  opts.keys = true
  opts.values = false
  return this.createReadStream(opts)
}

SDB.valueStream =
SDB.createValueStream = function (opts) {
  opts = opts || {}
  opts.keys = false
  opts.values = true
  opts.keys = false
  return this.createReadStream(opts)
}

function selectivelyMerge(_opts, opts) {
  [ 'valueEncoding'
  , 'encoding'
  , 'keyEncoding'
  , 'reverse'
  , 'values'
  , 'keys'
  , 'limit'
  , 'fillCache'
  ]
  .forEach(function (k) {
    if (opts.hasOwnProperty(k)) _opts[k] = opts[k]
  })
}

SDB.readStream =
SDB.createReadStream = function (opts) {
  opts = opts || {}
  var r = root(this)
  var p = this.prefix()

  var _opts = ranges.prefix(opts, p)
  selectivelyMerge(_opts, xtend(opts, this._options))

  var s = r.createReadStream(_opts)

  if(_opts.values === false) {
    var emit = s.emit
    s.emit = function (event, val) {
      if(event === 'data') {
        emit.call(this, 'data', val.substring(p.length))
      } else
        emit.call(this, event, val)
    }
    return s
  } else if(_opts.keys === false)
    return s
  else
    return s.on('data', function (d) {
      //mutate the prefix!
      //this doesn't work for createKeyStream admittedly.
      d.key = d.key.substring(p.length)
    })
}

SDB.writeStream =
SDB.createWriteStream = function () {
  var r = root(this)
  var p = this.prefix()
  var ws = r.createWriteStream.apply(r, arguments)
  var write = ws.write
  ws.write = function (data) {
    data.key = p + data.key
    return write.call(ws, data)
  }
  return ws
}

SDB.approximateSize = function () {
  var r = root(db)
  return r.approximateSize.apply(r, arguments)
}

function root(db) {
  if(!db._parent) return db
  return root(db._parent)
}

SDB.pre = function (range, hook) {
  if(!hook) hook = range, range = null
  range = ranges.prefix(range, this.prefix(), this._options.sep)
  var r = root(this._parent)
  var p = this.prefix()
  return r.hooks.pre(fixRange(range), function (ch, add) {
    hook({
      key: ch.key.substring(p.length),
      value: ch.value,
      type: ch.type
    }, function (ch, _p) {
      //maybe remove the second add arg now
      //that op can have prefix?
      add(ch, ch.prefix ? _p : (_p || p))
    })
  })
}

SDB.post = function (range, hook) {
  if(!hook) hook = range, range = null
  var r = root(this._parent)
  var p = this.prefix()
  range = ranges.prefix(range, p, this._options.sep)
  return r.hooks.post(fixRange(range), function (data) {
    hook({key: data.key.substring(p.length), value: data.value, type: data.type})
  })
}

var exports = module.exports = SubDB

<|endoftext|>


<commit_before>'use strict';

const Router = require('./index');
const middleware = require('storj-service-middleware');
const rawbody = middleware.rawbody;
const log = require('../../logger');
const errors = require('storj-service-error-types');
const merge = require('merge');
const inherits = require('util').inherits;
const authenticate = middleware.authenticate;
const crypto = require('crypto');

/**
 * Handles endpoints for all user related operations
 * @constructor
 * @extends {Router}
 */
function UsersRouter(options) {
  if (!(this instanceof UsersRouter)) {
    return new UsersRouter(options);
  }

  Router.apply(this, arguments);

  this._verify = authenticate(this.storage);
}

inherits(UsersRouter, Router);

/**
 * Sends a user activation email
 * @private
 */
UsersRouter.prototype._dispactchActivationEmail = function(user, redir) {
  let self = this;
  let profile = self.config.server.public || self.config.server;
  let host = profile.host;
  let port = [443, 80].indexOf(profile.port) === -1 ?
             ':' + profile.port :
             '';
  let proto = self.config.server.ssl &&
              self.config.server.ssl.cert &&
              self.config.server.ssl.key ?
              'https:' :
              'http:';

  self.mailer.dispatch(user.email, 'confirm', {
    token: user.activator,
    redirect: redir,
    url: proto + '//' + host + port
  }, function(err) {
    if (err) {
      log.error('failed to send activation email, reason: %s', err.message);
    }
  });
};

/**
 * Registers a new user
 * @param {http.IncomingMessage} req
 * @param {http.ServerResponse} res
 * @param {Function} next
 */
UsersRouter.prototype.createUser = function(req, res, next) {
  const self = this;
  const User = this.storage.models.User;
  const PublicKey = this.storage.models.PublicKey;

  log.info('registering user account for %s', req.body.email);

  User.create(req.body.email, req.body.password, function(err, user) {
    if (err) {
      return next(err);
    }

    if (!req.body.pubkey) {
      self._dispatchActivationEmail(user, req.body.redirect);
      return res.status(201).send(user.toObject());
    }

    PublicKey.create(user, req.body.pubkey, function(err, pubkey) {
      if (err) {
        user.remove();
        return next(new errors.BadRequestError(err.message));
      }

      self._dispatchActivationEmail(user, req.body.redirect);
      res.status(201).send(merge(user.toObject(), {
        pubkey: pubkey.key
      }));
    });
  });
};

/**
 * Confirms a user account
 * @param {http.IncomingMessage} req
 * @param {http.ServerResponse} res
 * @param {Function} next
 */
UsersRouter.prototype.confirmActivateUser = function(req, res, next) {
  const User = this.storage.models.User;

  log.info('activating user with token %s', req.params.token);

  User.findOne({
    activator: req.params.token
  }, function(err, user) {
    if (err) {
      return next(new errors.InternalError(err.message));
    }

    if (!user) {
      return next(new errors.BadRequestError('Invalid activation token'));
    }

    user.activate(function(err) {
      if (err) {
        return next(new errors.InternalError(err.message));
      }

      if (req.query.redirect) {
        res.redirect(req.query.redirect);
      } else {
        res.send(user.toObject());
      }
    });
  });
};

/**
 * Reactivates a user account
 * @param {http.IncomingMessage} req
 * @param {http.ServerResponse} res
 * @param {Function} next
 */
UsersRouter.prototype.reactivateUser = function(req, res, next) {
  const self = this;
  const User = this.storage.models.User;

  log.info('sending account reactivation email to %s', req.body.email);

  User.findOne({
    _id: req.body.email
  }, function(err, user) {
    if (err) {
      return next(new errors.InternalError(err.message));
    }

    if (!user) {
      return next(new errors.NotFoundError('User not found'));
    }

    if (user.activated) {
      return next(new errors.BadRequestError('User is already activated'));
    }

    self._dispactchActivationEmail(user, req.body.redirect);
    res.status(201).send(user.toObject());
  });
};

/**
 * Deactivates a user account
 * @param {http.IncomingMessage} req
 * @param {http.ServerResponse} res
 * @param {Function} next
 */
UsersRouter.prototype.destroyUser = function(req, res, next) {
  const self = this;
  const User = this.storage.models.User;

  log.info('creating user deactivation token');

  User.findOne({ _id: req.params.id }, function(err, user) {
    if (err) {
      return next(new errors.InternalError(err.message));
    }

    if (!user) {
      return next(new errors.NotFoundError());
    }

    if (req.user._id !== user._id) {
      return next(new errors.NotAuthorizedError());
    }

    user.deactivator = crypto.randomBytes(256).toString('hex');

    let profile = self.config.server.public || self.config.server;
    let host = profile.host;
    let port = [443, 80].indexOf(profile.port) === -1 ?
               ':' + profile.port :
               '';
    let proto = self.config.server.ssl &&
                self.config.server.ssl.cert &&
                self.config.server.ssl.key ?
                'https:' :
                'http:';

    self.mailer.dispatch(user.email, 'delete', {
      token: user.deactivator,
      redirect: req.body.redirect,
      url: proto + '//' + host + port
    }, function(err) {
      if (err) {
        log.error('failed to send deactivation email, reason: %s', err.message);
      }

      user.save(function(err) {
        if (err) {
          return next(new errors.InternalError(err.message));
        }

        res.status(200).send(user.toObject());
      });
    });
  });
};

/**
 * Confirms the deletion of a user account
 * @param {http.IncomingMessage} req
 * @param {http.ServerResponse} res
 * @param {Function} next
 */
UsersRouter.prototype.confirmDestroyUser = function(req, res, next) {
  const User = this.storage.models.User;

  log.info('deactivating user account with token %s', req.params.token);

  User.findOne({ deactivator: req.params.token }, function(err, user) {
    if (err) {
      return next(new errors.InternalError(err.message));
    }

    if (!user) {
      return next(new errors.NotFoundError());
    }

    user.deactivate(function(err) {
      if (err) {
        return next(new errors.InternalError(err.message));
      }

      if (req.query.redirect) {
        res.redirect(req.query.redirect);
      } else {
        res.status(200).send(user.toObject());
      }
    });
  });
};

/**
 * Creates a password reset token
 * @param {http.IncomingMessage} req
 * @param {http.ServerResponse} res
 * @param {Function} next
 */
UsersRouter.prototype.createPasswordResetToken = function(req, res, next) {
  const self = this;
  const User = this.storage.models.User;

  if (Buffer(req.body.password, 'hex').length * 8 !== 256) {
    return next(new Error('Password must be hex encoded SHA-256 hash'));
  }

  User.findOne({ _id: req.params.id }, function(err, user) {
    if (err) {
      return next(new errors.InternalError(err.message));
    }

    if (!user) {
      return next(new errors.NotFoundError());
    }

    log.info('creating password reset token for %s', user._id);

    user.resetter = crypto.randomBytes(256).toString('hex');
    user.pendingHashPass = crypto.createHash('sha256').update(req.body.password).digest('hex');

    user.save(function(err) {
      if (err) {
        return next(new errors.InternalError(err.message));
      }

      let profile = self.config.server.public || self.config.server;
      let host = profile.host;
      let port = [443, 80].indexOf(profile.port) === -1 ?
                 ':' + profile.port :
                 '';
      let proto = self.config.server.ssl &&
                  self.config.server.ssl.cert &&
                  self.config.server.ssl.key ?
                  'https:' :
                  'http:';

      self.mailer.dispatch(user.email, 'reset', {
        token: user.resetter,
        redirect: req.body.redirect,
        url: proto + '//' + host + port
      }, function(err) {
        if (err) {
          log.error('failed to send reset email, reason: %s', err.message);
        }

        res.status(200).send(user.toObject());
      });
    });
  });
};

/**
 * Confirms and applies the password reset
 * @param {http.IncomingMessage} req
 * @param {http.ServerResponse} res
 * @param {Function} next
 */
UsersRouter.prototype.confirmPasswordReset = function(req, res, next) {
  const User = this.storage.models.User;

  /*
   * Mitigate timing attack
   *  attempt to make non-lookup-responses take similar
   *  amounts of time as lookup-responses
   */
  User.count({}, function(err, count) {
    const rand = Math.floor(Math.random() * count);
    const nextPlusTime = (value) => {
      User.findOne(function() { // do nothing with this record
        next(value);
      }).skip(rand);
    };

    // Ensure resseter is valid; mitigate things like `PATCH /resets/null`, etc.
    //-- TODO: test - ensure passwords for users without resetters can't be reset
    if (Buffer(req.params.token, 'hex').length !== 256) {
      return nextPlusTime(new Error('Resetter must be hex encoded 256 byte string'));
    }

    User.findOne({resetter: req.params.token}, function(err, user) {
      if (err) {
        return next(new errors.InternalError(err.message));
      }

      if (!user) {
        return next(new errors.NotFoundError());
      }

      user.hashpass = user.pendingHashPass;
      user.pendingHashPass = null;
      user.resetter = null;

      user.save(function(err) {
        if (err) {
          return next(new errors.InternalError(err.message));
        }

        if (req.query.redirect) {
          res.redirect(req.query.redirect);
        } else {
          res.send(user.toObject());
        }
      });
    });
  });
};

/**
 * Export definitions
 * @private
 */
UsersRouter.prototype._definitions = function() {
  return [
    ['POST', '/users', rawbody, this.createUser],
    ['POST', '/activations', rawbody, this.reactivateUser],
    ['GET', '/activations/:token', this.confirmActivateUser],
    ['DELETE', '/users/:id', this._verify, this.destroyUser],
    ['GET', '/deactivations/:token', this.confirmDestroyUser],
    ['PATCH', '/users/:id', rawbody, this.createPasswordResetToken],
    ['GET', '/resets/:token', this.confirmPasswordReset]
  ];
};

module.exports = UsersRouter;
<commit_msg>Delete unused users route<commit_after><|endoftext|>


<commit_before>
(function() {
	var undefined;

	function execute() {

		//////////////////////////////////////////////////////////////////////////////////////
		// validation events
		var ensureInited = function($el) {
			if (!window.ExoWeb) {
				return;
			}

			if ($el.attr("__validating") === undefined) {
				// register for model validation events
				var bindings = $el.liveBindings();

				for (var i = 0; i < bindings.length; i++) {
					var binding = bindings[i];
					var srcObj = Sys_Binding_getFinalSourceObject(binding);
					var propName = Sys_Binding_getFinalPath(binding);

					var meta = srcObj.meta || srcObj;

					if (meta && meta.addPropertyValidating) {
						// wire up validating/validated events
						meta.addPropertyValidating(propName, function(sender, issues) {
							$el.trigger('validating');
						});
					}

					if (meta && meta.addPropertyValidated) {
						meta.addPropertyValidated(propName, function(sender, issues) {
							$el.trigger("validated", [issues]);
						});
					}
				}

				// don't double register for events
				$el.attr("__validating", true);
			}
		};

		jQuery.fn.validated = function(f) {
			this.each(function() {
				$(this).bind('validated', f);
				ensureInited($(this));
			});

			return this;
		};

		jQuery.fn.validating = function(f) {
			this.each(function() {
				$(this).bind("validating", f);
				ensureInited($(this));
			});

			return this;
		};

		//////////////////////////////////////////////////////////////////////////////////////
		// selectors for rules
		jQuery.expr[":"].rule = function(obj, index, meta, stack) {
			if (!(window.ExoWeb && ExoWeb.Model)) {
				return false;
			}

			var ruleName = meta[3];
			var ruleType = ExoWeb.Model.Rule[ruleName];

			if (!ruleType) {
				ExoWeb.trace.throwAndLog(["ui", "jquery"], "Unknown rule in selector: " + ruleName);
			}

			return $(obj).rules(ruleType).length > 0;
		};

		jQuery.expr[":"].bound = function(obj, index, meta, stack) {
			if (!(window.ExoWeb && ExoWeb.Model)) {
				return false;
			}
			return $(obj).liveBindings().length > 0;
		};

		//////////////////////////////////////////////////////////////////////////////////////
		// helpers for working with ms ajax controls

		jQuery.expr[":"].dataview = function(obj, index, meta, stack) {
			return window.Sys !== undefined && Sys.UI !== undefined && obj.control !== undefined && obj.control instanceof Sys.UI.DataView;
		};

		jQuery.expr[":"].content = function(obj, index, meta, stack) {
			return window.ExoWeb !== undefined && ExoWeb.UI !== undefined && obj.control !== undefined && obj.control instanceof ExoWeb.UI.Content;
		};

		jQuery.expr[":"].control = function(obj, index, meta, stack) {
			var typeName = meta[3];
			var jstype = new Function("{return " + typeName + ";}");

			return obj.control instanceof jstype;
		};

		jQuery.fn.control = function(propName, propValue) {
			if (arguments.length === 0) {
				return this.get(0).control;
			}
			else if (arguments.length == 1) {
				return this.get(0).control["get_" + propName]();
			}
			else {
				this.each(function(index, element) {
					this.control["set_" + propName](propValue);
				});
			}
		};

		jQuery.fn.commands = function(commands) {
			var control = this.control();
			control.add_command(function(sender, args) {
				var handler = commands[args.get_commandName()];
				if (handler) {
					handler(sender, args);
				}
			});
		};

		//////////////////////////////////////////////////////////////////////////////////////
		// helpers for MS AJAX and model integration
		var everRegs = [];

		function processElements(els, action) {
			for (var e = 0; e < els.length; ++e) {
				var el = els[e];

				for (var i = 0; i < everRegs.length; ++i) {
					var reg = everRegs[i];

					var handler = reg[action];

					if (!handler) {
						continue;
					}

					// test root
					if ($(el).is(reg.selector)) {
						handler.apply(el);
					}

					// test children
					$(reg.selector, el).each(handler);
				}
			}
		}

		var interceptingTemplates = false;
		var interceptingWebForms = false;
		var partialPageLoadOccurred = false;

		function ensureIntercepting() {
			if (!interceptingTemplates && window.Sys && Sys.UI && Sys.UI.Template) {
				var instantiateInBase = Sys.UI.Template.prototype.instantiateIn;
				Sys.UI.Template.prototype.instantiateIn = function(containerElement, data, dataItem, dataIndex, nodeToInsertTemplateBefore, parentContext) {
					var context = instantiateInBase.apply(this, arguments);

					processElements(context.nodes, "added");
					return context;
				};

				// intercept Sys.UI.DataView._clearContainers called conditionally during dispose() and refresh().
				// dispose is too late because the nodes will have been cleared out.
				var clearContainersBase = Sys.UI.DataView.prototype._clearContainers;
				Sys.UI.DataView.prototype._clearContainers = function() {
					var contexts = this.get_contexts();

					for (var i = 0; i < contexts.length; i++)
						processElements(contexts[i].nodes, "deleted");

					clearContainersBase.apply(this, arguments);
				}

				interceptingTemplates = true;
			}

			if (!interceptingWebForms && window.Sys && Sys.WebForms) {
				Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(function(sender, evt) {
					partialPageLoadOccurred = true;
					processElements(evt.get_panelsUpdating(), "deleted");
				});

				Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function(sender, evt) {
					// Only process elements for update panels that were added if we have actually done a partial update.
					// This is needed so that the "ever" handler is not called twice when a panel is added to the page on first page load.
					if (partialPageLoadOccurred) {
						processElements(evt.get_panelsCreated(), "added");
					}

					processElements(evt.get_panelsUpdated(), "added");
				});
				interceptingWebForms = true;
			}
		}

		// matches elements as they are dynamically added to the DOM
		jQuery.fn.ever = function(added, deleted) {

			// If the function is called in any way other than as a method on the
			// jQuery object, then intercept and return early.
			if (!(this instanceof jQuery)) {
				ensureIntercepting();
				return;
			}

			// apply now
			this.each(added);

			// and then watch for dom changes
			everRegs.push({
				selector: this.selector,
				context: this.context,
				added: added,
				deleted: deleted
			});

			ensureIntercepting();

			// really shouldn't chain calls b/c only elements
			// currently in the DOM would be affected.
			return null;
		};

		// Gets all Sys.Bindings for an element
		jQuery.fn.liveBindings = function() {
			var bindings = [];
			this.each(function() {
				if (this.__msajaxbindings)
					Array.addRange(bindings, this.__msajaxbindings);
			});

			return bindings;
		};

		// Gets all model rules associated with the property an element is bound to
		jQuery.fn.rules = function(ruleType) {
			if (!(window.ExoWeb && ExoWeb.Model)) {
				return [];
			}

			var rules = [];
			var bindings = $(this).liveBindings();

			for (var i = 0; i < bindings.length; i++) {
				var binding = bindings[i];
				var srcObj = Sys_Binding_getFinalSourceObject(binding);

				var prop;

				if (srcObj instanceof ExoWeb.View.Adapter) {
					prop = srcObj.get_propertyChain().lastProperty();
				}
				else if (srcObj instanceof ExoWeb.View.OptionAdapter) {
					prop = srcObj.get_parent().get_propertyChain().lastProperty();
				}
				else if (srcObj instanceof ExoWeb.Model.Entity) {
					var propName = Sys_Binding_getFinalPath(binding);
					prop = srcObj.meta.property(propName);
				}
				else {
					continue;
				}

				var rule = prop.rule(ruleType);
				if (rule) {
					rules.push(rule);
				}
			}

			return rules;
		};

		jQuery.fn.issues = function(options) {
			var issues = [];

			options = options || { refresh: false };

			var bindings = $(this).liveBindings();

			for (var i = 0; i < bindings.length; i++) {
				var binding = bindings[i];
				var srcObj = Sys_Binding_getFinalSourceObject(binding);

				var target;
				var prop;

				if (srcObj instanceof ExoWeb.View.Adapter) {
					var chain = srcObj.get_propertyChain();
					prop = chain.lastProperty();
					target = chain.lastTarget(srcObj.get_target());
				}
				else if (srcObj instanceof ExoWeb.View.OptionAdapter) {
					var chain = srcObj.get_parent().get_propertyChain();
					prop = chain.lastProperty();
					target = chain.lastTarget(srcObj.get_parent().get_target());
				}
				else if (srcObj instanceof ExoWeb.Model.Entity) {
					var propName = Sys_Binding_getFinalPath(binding);
					prop = srcObj.meta.property(propName);
					target = srcObj;
				}
				else {
					continue;
				}

				if (options.refresh)
					target.meta.executeRules(prop);

				Array.addRange(issues, target.meta.conditions(prop));
			}
			return issues;
		};

		// Get's the last object in the source path.  Ex: Customer.Address.Street returns the Address object.
		function Sys_Binding_getFinalSourceObject(binding) {
			var src = binding.get_source();

			for (var i = 0; i < binding._pathArray.length - 1; ++i) {
				src = src[binding._pathArray[i]] || src["get_" + binding._pathArray[i]]();
			}

			return src;
		}

		function Sys_Binding_getFinalPath(binding) {
			return binding._pathArray[binding._pathArray.length - 1];
		}
	}

	if (window.Sys && Sys.loader) {
		Sys.loader.registerScript("ExoWebJquery", null, execute);
	}
	else {
		execute();
	}
})();
<commit_msg>Additionally check for constructors, specifically dataview may be null<commit_after>
(function() {
	var undefined;

	function execute() {

		//////////////////////////////////////////////////////////////////////////////////////
		// validation events
		var ensureInited = function($el) {
			if (!window.ExoWeb) {
				return;
			}

			if ($el.attr("__validating") === undefined) {
				// register for model validation events
				var bindings = $el.liveBindings();

				for (var i = 0; i < bindings.length; i++) {
					var binding = bindings[i];
					var srcObj = Sys_Binding_getFinalSourceObject(binding);
					var propName = Sys_Binding_getFinalPath(binding);

					var meta = srcObj.meta || srcObj;

					if (meta && meta.addPropertyValidating) {
						// wire up validating/validated events
						meta.addPropertyValidating(propName, function(sender, issues) {
							$el.trigger('validating');
						});
					}

					if (meta && meta.addPropertyValidated) {
						meta.addPropertyValidated(propName, function(sender, issues) {
							$el.trigger("validated", [issues]);
						});
					}
				}

				// don't double register for events
				$el.attr("__validating", true);
			}
		};

		jQuery.fn.validated = function(f) {
			this.each(function() {
				$(this).bind('validated', f);
				ensureInited($(this));
			});

			return this;
		};

		jQuery.fn.validating = function(f) {
			this.each(function() {
				$(this).bind("validating", f);
				ensureInited($(this));
			});

			return this;
		};

		//////////////////////////////////////////////////////////////////////////////////////
		// selectors for rules
		jQuery.expr[":"].rule = function(obj, index, meta, stack) {
			if (!(window.ExoWeb && ExoWeb.Model)) {
				return false;
			}

			var ruleName = meta[3];
			var ruleType = ExoWeb.Model.Rule[ruleName];

			if (!ruleType) {
				ExoWeb.trace.throwAndLog(["ui", "jquery"], "Unknown rule in selector: " + ruleName);
			}

			return $(obj).rules(ruleType).length > 0;
		};

		jQuery.expr[":"].bound = function(obj, index, meta, stack) {
			if (!(window.ExoWeb && ExoWeb.Model)) {
				return false;
			}
			return $(obj).liveBindings().length > 0;
		};

		//////////////////////////////////////////////////////////////////////////////////////
		// helpers for working with ms ajax controls

		jQuery.expr[":"].dataview = function(obj, index, meta, stack) {
			return window.Sys !== undefined && Sys.UI !== undefined && obj.control !== undefined &&
				Sys.UI.DataView !== undefined && obj.control instanceof Sys.UI.DataView;
		};

		jQuery.expr[":"].content = function(obj, index, meta, stack) {
			return window.ExoWeb !== undefined && ExoWeb.UI !== undefined && obj.control !== undefined &&
				ExoWeb.UI.Content !== undefined && obj.control instanceof ExoWeb.UI.Content;
		};

		jQuery.expr[":"].control = function(obj, index, meta, stack) {
			var typeName = meta[3];
			var jstype = new Function("{return " + typeName + ";}");

			return obj.control instanceof jstype;
		};

		jQuery.fn.control = function(propName, propValue) {
			if (arguments.length === 0) {
				return this.get(0).control;
			}
			else if (arguments.length == 1) {
				return this.get(0).control["get_" + propName]();
			}
			else {
				this.each(function(index, element) {
					this.control["set_" + propName](propValue);
				});
			}
		};

		jQuery.fn.commands = function(commands) {
			var control = this.control();
			control.add_command(function(sender, args) {
				var handler = commands[args.get_commandName()];
				if (handler) {
					handler(sender, args);
				}
			});
		};

		//////////////////////////////////////////////////////////////////////////////////////
		// helpers for MS AJAX and model integration
		var everRegs = [];

		function processElements(els, action) {
			for (var e = 0; e < els.length; ++e) {
				var el = els[e];

				for (var i = 0; i < everRegs.length; ++i) {
					var reg = everRegs[i];

					var handler = reg[action];

					if (!handler) {
						continue;
					}

					// test root
					if ($(el).is(reg.selector)) {
						handler.apply(el);
					}

					// test children
					$(reg.selector, el).each(handler);
				}
			}
		}

		var interceptingTemplates = false;
		var interceptingWebForms = false;
		var partialPageLoadOccurred = false;

		function ensureIntercepting() {
			if (!interceptingTemplates && window.Sys && Sys.UI && Sys.UI.Template) {
				var instantiateInBase = Sys.UI.Template.prototype.instantiateIn;
				Sys.UI.Template.prototype.instantiateIn = function(containerElement, data, dataItem, dataIndex, nodeToInsertTemplateBefore, parentContext) {
					var context = instantiateInBase.apply(this, arguments);

					processElements(context.nodes, "added");
					return context;
				};

				// intercept Sys.UI.DataView._clearContainers called conditionally during dispose() and refresh().
				// dispose is too late because the nodes will have been cleared out.
				var clearContainersBase = Sys.UI.DataView.prototype._clearContainers;
				Sys.UI.DataView.prototype._clearContainers = function() {
					var contexts = this.get_contexts();

					for (var i = 0; i < contexts.length; i++)
						processElements(contexts[i].nodes, "deleted");

					clearContainersBase.apply(this, arguments);
				}

				interceptingTemplates = true;
			}

			if (!interceptingWebForms && window.Sys && Sys.WebForms) {
				Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(function(sender, evt) {
					partialPageLoadOccurred = true;
					processElements(evt.get_panelsUpdating(), "deleted");
				});

				Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function(sender, evt) {
					// Only process elements for update panels that were added if we have actually done a partial update.
					// This is needed so that the "ever" handler is not called twice when a panel is added to the page on first page load.
					if (partialPageLoadOccurred) {
						processElements(evt.get_panelsCreated(), "added");
					}

					processElements(evt.get_panelsUpdated(), "added");
				});
				interceptingWebForms = true;
			}
		}

		// matches elements as they are dynamically added to the DOM
		jQuery.fn.ever = function(added, deleted) {

			// If the function is called in any way other than as a method on the
			// jQuery object, then intercept and return early.
			if (!(this instanceof jQuery)) {
				ensureIntercepting();
				return;
			}

			// apply now
			this.each(added);

			// and then watch for dom changes
			everRegs.push({
				selector: this.selector,
				context: this.context,
				added: added,
				deleted: deleted
			});

			ensureIntercepting();

			// really shouldn't chain calls b/c only elements
			// currently in the DOM would be affected.
			return null;
		};

		// Gets all Sys.Bindings for an element
		jQuery.fn.liveBindings = function() {
			var bindings = [];
			this.each(function() {
				if (this.__msajaxbindings)
					Array.addRange(bindings, this.__msajaxbindings);
			});

			return bindings;
		};

		// Gets all model rules associated with the property an element is bound to
		jQuery.fn.rules = function(ruleType) {
			if (!(window.ExoWeb && ExoWeb.Model)) {
				return [];
			}

			var rules = [];
			var bindings = $(this).liveBindings();

			for (var i = 0; i < bindings.length; i++) {
				var binding = bindings[i];
				var srcObj = Sys_Binding_getFinalSourceObject(binding);

				var prop;

				if (srcObj instanceof ExoWeb.View.Adapter) {
					prop = srcObj.get_propertyChain().lastProperty();
				}
				else if (srcObj instanceof ExoWeb.View.OptionAdapter) {
					prop = srcObj.get_parent().get_propertyChain().lastProperty();
				}
				else if (srcObj instanceof ExoWeb.Model.Entity) {
					var propName = Sys_Binding_getFinalPath(binding);
					prop = srcObj.meta.property(propName);
				}
				else {
					continue;
				}

				var rule = prop.rule(ruleType);
				if (rule) {
					rules.push(rule);
				}
			}

			return rules;
		};

		jQuery.fn.issues = function(options) {
			var issues = [];

			options = options || { refresh: false };

			var bindings = $(this).liveBindings();

			for (var i = 0; i < bindings.length; i++) {
				var binding = bindings[i];
				var srcObj = Sys_Binding_getFinalSourceObject(binding);

				var target;
				var prop;

				if (srcObj instanceof ExoWeb.View.Adapter) {
					var chain = srcObj.get_propertyChain();
					prop = chain.lastProperty();
					target = chain.lastTarget(srcObj.get_target());
				}
				else if (srcObj instanceof ExoWeb.View.OptionAdapter) {
					var chain = srcObj.get_parent().get_propertyChain();
					prop = chain.lastProperty();
					target = chain.lastTarget(srcObj.get_parent().get_target());
				}
				else if (srcObj instanceof ExoWeb.Model.Entity) {
					var propName = Sys_Binding_getFinalPath(binding);
					prop = srcObj.meta.property(propName);
					target = srcObj;
				}
				else {
					continue;
				}

				if (options.refresh)
					target.meta.executeRules(prop);

				Array.addRange(issues, target.meta.conditions(prop));
			}
			return issues;
		};

		// Get's the last object in the source path.  Ex: Customer.Address.Street returns the Address object.
		function Sys_Binding_getFinalSourceObject(binding) {
			var src = binding.get_source();

			for (var i = 0; i < binding._pathArray.length - 1; ++i) {
				src = src[binding._pathArray[i]] || src["get_" + binding._pathArray[i]]();
			}

			return src;
		}

		function Sys_Binding_getFinalPath(binding) {
			return binding._pathArray[binding._pathArray.length - 1];
		}
	}

	if (window.Sys && Sys.loader) {
		Sys.loader.registerScript("ExoWebJquery", null, execute);
	}
	else {
		execute();
	}
})();
<|endoftext|>


<commit_before>import Ember from 'ember';
import RouteMixin from 'ember-cli-pagination/remote/route-mixin';
import { CanMixin } from 'ember-can';

export default Ember.Route.extend(CanMixin, RouteMixin, {

  model(params) {
    return Ember.RSVP.hash({
      client: this.store.findRecord('client', params.client_id),
      prefix: this.store.createRecord('client-prefix', { client: params.client_id })
    });
  }
});
<commit_msg>fix prefix route<commit_after>import Ember from 'ember';
import RouteMixin from 'ember-cli-pagination/remote/route-mixin';
import { CanMixin } from 'ember-can';

export default Ember.Route.extend(CanMixin, RouteMixin, {

  model(params) {
    return Ember.RSVP.hash({
      client: this.store.findRecord('client', this.modelFor('clients/show').get('id')),
      prefix: this.store.createRecord('client-prefix', { client: this.modelFor('clients/show').get('id') })
    });
  }
});
<|endoftext|>


<commit_before>'use strict'
var async = require('async')
var ethers = require('ethers')
var ethJSUtil = require('ethereumjs-util')
var EventManager = require('../eventManager')
var codeUtil = require('../util')

var executionContext = require('./execution-context')
var txFormat = require('./txFormat')
var txHelper = require('./txHelper')

/**
  * poll web3 each 2s if web3
  * listen on transaction executed event if VM
  * attention: blocks returned by the event `newBlock` have slightly different json properties whether web3 or the VM is used
  * trigger 'newBlock'
  *
  */
class TxListener {
  constructor (opt) {
    this.event = new EventManager()
    this._api = opt.api
    this._resolvedTransactions = {}
    this._resolvedContracts = {}
    this._isListening = false
    this._listenOnNetwork = false
    this._loopId = null
    this.init()
    executionContext.event.register('contextChanged', (context) => {
      if (this._isListening) {
        this.stopListening()
        this.startListening()
      }
    })

    opt.event.udapp.register('callExecuted', (error, from, to, data, lookupOnly, txResult) => {
      if (error) return
      // we go for that case if
      // in VM mode
      // in web3 mode && listen remix txs only
      if (!this._isListening) return // we don't listen
      if (this._loopId && executionContext.getProvider() !== 'vm') return // we seems to already listen on a "web3" network

      var call = {
        from: from,
        to: to,
        input: data,
        hash: txResult.transactionHash ? txResult.transactionHash : 'call' + (from || '') + to + data,
        isCall: true,
        returnValue: executionContext.isVM() ? txResult.result.vm.return : ethJSUtil.toBuffer(txResult.result),
        envMode: executionContext.getProvider()
      }

      addExecutionCosts(txResult, call)
      this._resolveTx(call, call, (error, resolvedData) => {
        if (!error) {
          this.event.trigger('newCall', [call])
        }
      })
    })

    opt.event.udapp.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => {
      if (error) return
      if (lookupOnly) return
      // we go for that case if
      // in VM mode
      // in web3 mode && listen remix txs only
      if (!this._isListening) return // we don't listen
      if (this._loopId && executionContext.getProvider() !== 'vm') return // we seems to already listen on a "web3" network
      executionContext.web3().eth.getTransaction(txResult.transactionHash, (error, tx) => {
        if (error) return console.log(error)

        addExecutionCosts(txResult, tx)
        tx.envMode = executionContext.getProvider()
        tx.status = txResult.result.status // 0x0 or 0x1
        this._resolve([tx], () => {
        })
      })
    })

    function addExecutionCosts (txResult, tx) {
      if (txResult && txResult.result) {
        if (txResult.result.vm) {
          tx.returnValue = txResult.result.vm.return
          if (txResult.result.vm.gasUsed) tx.executionCost = txResult.result.vm.gasUsed.toString(10)
        }
        if (txResult.result.gasUsed) tx.transactionCost = txResult.result.gasUsed.toString(10)
      }
    }
  }

  /**
    * define if txlistener should listen on the network or if only tx created from remix are managed
    *
    * @param {Bool} type - true if listen on the network
    */
  setListenOnNetwork (listenOnNetwork) {
    this._listenOnNetwork = listenOnNetwork
    if (this._loopId) {
      clearInterval(this._loopId)
    }
    if (this._listenOnNetwork) {
      this._startListenOnNetwork()
    }
  }

  /**
    * reset recorded transactions
    */
  init () {
    this.blocks = []
    this.lastBlock = null
  }

  /**
    * start listening for incoming transactions
    *
    * @param {String} type - type/name of the provider to add
    * @param {Object} obj  - provider
    */
  startListening () {
    this.init()
    this._isListening = true
    if (this._listenOnNetwork && executionContext.getProvider() !== 'vm') {
      this._startListenOnNetwork()
    }
  }

   /**
    * stop listening for incoming transactions. do not reset the recorded pool.
    *
    * @param {String} type - type/name of the provider to add
    * @param {Object} obj  - provider
    */
  stopListening () {
    if (this._loopId) {
      clearInterval(this._loopId)
    }
    this._loopId = null
    this._isListening = false
  }

  _startListenOnNetwork () {
    this._loopId = setInterval(() => {
      var currentLoopId = this._loopId
      executionContext.web3().eth.getBlockNumber((error, blockNumber) => {
        if (this._loopId === null) return
        if (error) return console.log(error)
        if (currentLoopId === this._loopId && (!this.lastBlock || blockNumber > this.lastBlock)) {
          if (!this.lastBlock) this.lastBlock = blockNumber - 1
          var current = this.lastBlock + 1
          this.lastBlock = blockNumber
          while (blockNumber >= current) {
            try {
              this._manageBlock(current)
            } catch (e) {
              console.log(e)
            }
            current++
          }
        }
      })
    }, 2000)
  }

  _manageBlock (blockNumber) {
    executionContext.web3().eth.getBlock(blockNumber, true, (error, result) => {
      if (!error) {
        this._newBlock(Object.assign({type: 'web3'}, result))
      }
    })
  }

  /**
    * try to resolve the contract name from the given @arg address
    *
    * @param {String} address - contract address to resolve
    * @return {String} - contract name
    */
  resolvedContract (address) {
    return this._resolvedContracts[address]
  }

  /**
    * try to resolve the transaction from the given @arg txHash
    *
    * @param {String} txHash - contract address to resolve
    * @return {String} - contract name
    */
  resolvedTransaction (txHash) {
    return this._resolvedTransactions[txHash]
  }

  _newBlock (block) {
    this.blocks.push(block)
    this._resolve(block.transactions, () => {
      this.event.trigger('newBlock', [block])
    })
  }

  _resolve (transactions, callback) {
    async.each(transactions, (tx, cb) => {
      this._api.resolveReceipt(tx, (error, receipt) => {
        if (error) return cb(error)
        this._resolveTx(tx, receipt, (error, resolvedData) => {
          if (error) cb(error)
          if (resolvedData) {
            this.event.trigger('txResolved', [tx, receipt, resolvedData])
          }
          this.event.trigger('newTransaction', [tx, receipt])
          cb()
        })
      })
    }, () => {
      callback()
    })
  }

  _resolveTx (tx, receipt, cb) {
    var contracts = this._api.contracts()
    if (!contracts) return cb()
    var contractName
    var fun
    if (!tx.to || tx.to === '0x0') { // testrpc returns 0x0 in that case
      // contract creation / resolve using the creation bytes code
      // if web3: we have to call getTransactionReceipt to get the created address
      // if VM: created address already included
      var code = tx.input
      contractName = this._tryResolveContract(code, contracts, true)
      if (contractName) {
        var address = receipt.contractAddress
        this._resolvedContracts[address] = contractName
        fun = this._resolveFunction(contractName, contracts, tx, true)
        if (this._resolvedTransactions[tx.hash]) {
          this._resolvedTransactions[tx.hash].contractAddress = address
        }
        return cb(null, {to: null, contractName: contractName, function: fun, creationAddress: address})
      }
      return cb()
    } else {
      // first check known contract, resolve against the `runtimeBytecode` if not known
      contractName = this._resolvedContracts[tx.to]
      if (!contractName) {
        executionContext.web3().eth.getCode(tx.to, (error, code) => {
          if (error) return cb(error)
          if (code) {
            var contractName = this._tryResolveContract(code, contracts, false)
            if (contractName) {
              this._resolvedContracts[tx.to] = contractName
              var fun = this._resolveFunction(contractName, contracts, tx, false)
              return cb(null, {to: tx.to, contractName: contractName, function: fun})
            }
          }
          return cb()
        })
        return
      }
      if (contractName) {
        fun = this._resolveFunction(contractName, contracts, tx, false)
        return cb(null, {to: tx.to, contractName: contractName, function: fun})
      }
      return cb()
    }
  }

  _resolveFunction (contractName, compiledContracts, tx, isCtor) {
    var contract = txHelper.getContract(contractName, compiledContracts)
    if (!contract) {
      console.log('txListener: cannot resolve ' + contractName)
      return
    }
    var abi = contract.object.abi
    var inputData = tx.input.replace('0x', '')
    if (!isCtor) {
      var methodIdentifiers = contract.object.evm.methodIdentifiers
      for (var fn in methodIdentifiers) {
        if (methodIdentifiers[fn] === inputData.substring(0, 8)) {
          var fnabi = getFunction(abi, fn)
          this._resolvedTransactions[tx.hash] = {
            contractName: contractName,
            to: tx.to,
            fn: fn,
            params: this._decodeInputParams(inputData.substring(8), fnabi)
          }
          if (tx.returnValue) {
            this._resolvedTransactions[tx.hash].decodedReturnValue = txFormat.decodeResponse(tx.returnValue, fnabi)
          }
          return this._resolvedTransactions[tx.hash]
        }
      }
      // fallback function
      this._resolvedTransactions[tx.hash] = {
        contractName: contractName,
        to: tx.to,
        fn: '(fallback)',
        params: null
      }
    } else {
      var bytecode = contract.object.evm.bytecode.object
      var params = null
      if (bytecode && bytecode.length) {
        params = this._decodeInputParams(inputData.substring(bytecode.length), getConstructorInterface(abi))
      }
      this._resolvedTransactions[tx.hash] = {
        contractName: contractName,
        to: null,
        fn: '(constructor)',
        params: params
      }
    }
    return this._resolvedTransactions[tx.hash]
  }

  _tryResolveContract (codeToResolve, compiledContracts, isCreation) {
    var found = null
    txHelper.visitContracts(compiledContracts, (contract) => {
      var bytes = isCreation ? contract.object.evm.bytecode.object : contract.object.evm.deployedBytecode.object
      if (codeUtil.compareByteCode(codeToResolve, '0x' + bytes)) {
        found = contract.name
        return true
      }
    })
    return found
  }

  _decodeInputParams (data, abi) {
    data = ethJSUtil.toBuffer('0x' + data)
    if (!data.length) data = new Uint8Array(32 * abi.inputs.length) // ensuring the data is at least filled by 0 cause `AbiCoder` throws if there's not engouh data

    var inputTypes = []
    for (var i = 0; i < abi.inputs.length; i++) {
      var type = abi.inputs[i].type
      inputTypes.push(type === 'tuple' ? txHelper.makeFullTupleTypeDefinition(abi.inputs[i]) : type)
    }
    var abiCoder = new ethers.utils.AbiCoder()
    var decoded = abiCoder.decode(inputTypes, data)
    var ret = {}
    for (var k in abi.inputs) {
      ret[abi.inputs[k].type + ' ' + abi.inputs[k].name] = decoded[k]
    }
    return ret
  }
}

// those function will be duplicate after the merged of the compile and run tabs split
function getConstructorInterface (abi) {
  var funABI = { 'name': '', 'inputs': [], 'type': 'constructor', 'outputs': [] }
  for (var i = 0; i < abi.length; i++) {
    if (abi[i].type === 'constructor') {
      funABI.inputs = abi[i].inputs || []
      break
    }
  }

  return funABI
}

function getFunction (abi, fnName) {
  fnName = fnName.split('(')[0]
  for (var i = 0; i < abi.length; i++) {
    if (abi[i].name === fnName) {
      return abi[i]
    }
  }
  return null
}

module.exports = TxListener
<commit_msg>fix resolveFunction: take in account types<commit_after>'use strict'
var async = require('async')
var ethers = require('ethers')
var ethJSUtil = require('ethereumjs-util')
var EventManager = require('../eventManager')
var codeUtil = require('../util')

var executionContext = require('./execution-context')
var txFormat = require('./txFormat')
var txHelper = require('./txHelper')

/**
  * poll web3 each 2s if web3
  * listen on transaction executed event if VM
  * attention: blocks returned by the event `newBlock` have slightly different json properties whether web3 or the VM is used
  * trigger 'newBlock'
  *
  */
class TxListener {
  constructor (opt) {
    this.event = new EventManager()
    this._api = opt.api
    this._resolvedTransactions = {}
    this._resolvedContracts = {}
    this._isListening = false
    this._listenOnNetwork = false
    this._loopId = null
    this.init()
    executionContext.event.register('contextChanged', (context) => {
      if (this._isListening) {
        this.stopListening()
        this.startListening()
      }
    })

    opt.event.udapp.register('callExecuted', (error, from, to, data, lookupOnly, txResult) => {
      if (error) return
      // we go for that case if
      // in VM mode
      // in web3 mode && listen remix txs only
      if (!this._isListening) return // we don't listen
      if (this._loopId && executionContext.getProvider() !== 'vm') return // we seems to already listen on a "web3" network

      var call = {
        from: from,
        to: to,
        input: data,
        hash: txResult.transactionHash ? txResult.transactionHash : 'call' + (from || '') + to + data,
        isCall: true,
        returnValue: executionContext.isVM() ? txResult.result.vm.return : ethJSUtil.toBuffer(txResult.result),
        envMode: executionContext.getProvider()
      }

      addExecutionCosts(txResult, call)
      this._resolveTx(call, call, (error, resolvedData) => {
        if (!error) {
          this.event.trigger('newCall', [call])
        }
      })
    })

    opt.event.udapp.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => {
      if (error) return
      if (lookupOnly) return
      // we go for that case if
      // in VM mode
      // in web3 mode && listen remix txs only
      if (!this._isListening) return // we don't listen
      if (this._loopId && executionContext.getProvider() !== 'vm') return // we seems to already listen on a "web3" network
      executionContext.web3().eth.getTransaction(txResult.transactionHash, (error, tx) => {
        if (error) return console.log(error)

        addExecutionCosts(txResult, tx)
        tx.envMode = executionContext.getProvider()
        tx.status = txResult.result.status // 0x0 or 0x1
        this._resolve([tx], () => {
        })
      })
    })

    function addExecutionCosts (txResult, tx) {
      if (txResult && txResult.result) {
        if (txResult.result.vm) {
          tx.returnValue = txResult.result.vm.return
          if (txResult.result.vm.gasUsed) tx.executionCost = txResult.result.vm.gasUsed.toString(10)
        }
        if (txResult.result.gasUsed) tx.transactionCost = txResult.result.gasUsed.toString(10)
      }
    }
  }

  /**
    * define if txlistener should listen on the network or if only tx created from remix are managed
    *
    * @param {Bool} type - true if listen on the network
    */
  setListenOnNetwork (listenOnNetwork) {
    this._listenOnNetwork = listenOnNetwork
    if (this._loopId) {
      clearInterval(this._loopId)
    }
    if (this._listenOnNetwork) {
      this._startListenOnNetwork()
    }
  }

  /**
    * reset recorded transactions
    */
  init () {
    this.blocks = []
    this.lastBlock = null
  }

  /**
    * start listening for incoming transactions
    *
    * @param {String} type - type/name of the provider to add
    * @param {Object} obj  - provider
    */
  startListening () {
    this.init()
    this._isListening = true
    if (this._listenOnNetwork && executionContext.getProvider() !== 'vm') {
      this._startListenOnNetwork()
    }
  }

   /**
    * stop listening for incoming transactions. do not reset the recorded pool.
    *
    * @param {String} type - type/name of the provider to add
    * @param {Object} obj  - provider
    */
  stopListening () {
    if (this._loopId) {
      clearInterval(this._loopId)
    }
    this._loopId = null
    this._isListening = false
  }

  _startListenOnNetwork () {
    this._loopId = setInterval(() => {
      var currentLoopId = this._loopId
      executionContext.web3().eth.getBlockNumber((error, blockNumber) => {
        if (this._loopId === null) return
        if (error) return console.log(error)
        if (currentLoopId === this._loopId && (!this.lastBlock || blockNumber > this.lastBlock)) {
          if (!this.lastBlock) this.lastBlock = blockNumber - 1
          var current = this.lastBlock + 1
          this.lastBlock = blockNumber
          while (blockNumber >= current) {
            try {
              this._manageBlock(current)
            } catch (e) {
              console.log(e)
            }
            current++
          }
        }
      })
    }, 2000)
  }

  _manageBlock (blockNumber) {
    executionContext.web3().eth.getBlock(blockNumber, true, (error, result) => {
      if (!error) {
        this._newBlock(Object.assign({type: 'web3'}, result))
      }
    })
  }

  /**
    * try to resolve the contract name from the given @arg address
    *
    * @param {String} address - contract address to resolve
    * @return {String} - contract name
    */
  resolvedContract (address) {
    return this._resolvedContracts[address]
  }

  /**
    * try to resolve the transaction from the given @arg txHash
    *
    * @param {String} txHash - contract address to resolve
    * @return {String} - contract name
    */
  resolvedTransaction (txHash) {
    return this._resolvedTransactions[txHash]
  }

  _newBlock (block) {
    this.blocks.push(block)
    this._resolve(block.transactions, () => {
      this.event.trigger('newBlock', [block])
    })
  }

  _resolve (transactions, callback) {
    async.each(transactions, (tx, cb) => {
      this._api.resolveReceipt(tx, (error, receipt) => {
        if (error) return cb(error)
        this._resolveTx(tx, receipt, (error, resolvedData) => {
          if (error) cb(error)
          if (resolvedData) {
            this.event.trigger('txResolved', [tx, receipt, resolvedData])
          }
          this.event.trigger('newTransaction', [tx, receipt])
          cb()
        })
      })
    }, () => {
      callback()
    })
  }

  _resolveTx (tx, receipt, cb) {
    var contracts = this._api.contracts()
    if (!contracts) return cb()
    var contractName
    var fun
    if (!tx.to || tx.to === '0x0') { // testrpc returns 0x0 in that case
      // contract creation / resolve using the creation bytes code
      // if web3: we have to call getTransactionReceipt to get the created address
      // if VM: created address already included
      var code = tx.input
      contractName = this._tryResolveContract(code, contracts, true)
      if (contractName) {
        var address = receipt.contractAddress
        this._resolvedContracts[address] = contractName
        fun = this._resolveFunction(contractName, contracts, tx, true)
        if (this._resolvedTransactions[tx.hash]) {
          this._resolvedTransactions[tx.hash].contractAddress = address
        }
        return cb(null, {to: null, contractName: contractName, function: fun, creationAddress: address})
      }
      return cb()
    } else {
      // first check known contract, resolve against the `runtimeBytecode` if not known
      contractName = this._resolvedContracts[tx.to]
      if (!contractName) {
        executionContext.web3().eth.getCode(tx.to, (error, code) => {
          if (error) return cb(error)
          if (code) {
            var contractName = this._tryResolveContract(code, contracts, false)
            if (contractName) {
              this._resolvedContracts[tx.to] = contractName
              var fun = this._resolveFunction(contractName, contracts, tx, false)
              return cb(null, {to: tx.to, contractName: contractName, function: fun})
            }
          }
          return cb()
        })
        return
      }
      if (contractName) {
        fun = this._resolveFunction(contractName, contracts, tx, false)
        return cb(null, {to: tx.to, contractName: contractName, function: fun})
      }
      return cb()
    }
  }

  _resolveFunction (contractName, compiledContracts, tx, isCtor) {
    var contract = txHelper.getContract(contractName, compiledContracts)
    if (!contract) {
      console.log('txListener: cannot resolve ' + contractName)
      return
    }
    var abi = contract.object.abi
    var inputData = tx.input.replace('0x', '')
    if (!isCtor) {
      var methodIdentifiers = contract.object.evm.methodIdentifiers
      for (var fn in methodIdentifiers) {
        if (methodIdentifiers[fn] === inputData.substring(0, 8)) {
          var fnabi = getFunction(abi, fn)
          this._resolvedTransactions[tx.hash] = {
            contractName: contractName,
            to: tx.to,
            fn: fn,
            params: this._decodeInputParams(inputData.substring(8), fnabi)
          }
          if (tx.returnValue) {
            this._resolvedTransactions[tx.hash].decodedReturnValue = txFormat.decodeResponse(tx.returnValue, fnabi)
          }
          return this._resolvedTransactions[tx.hash]
        }
      }
      // fallback function
      this._resolvedTransactions[tx.hash] = {
        contractName: contractName,
        to: tx.to,
        fn: '(fallback)',
        params: null
      }
    } else {
      var bytecode = contract.object.evm.bytecode.object
      var params = null
      if (bytecode && bytecode.length) {
        params = this._decodeInputParams(inputData.substring(bytecode.length), getConstructorInterface(abi))
      }
      this._resolvedTransactions[tx.hash] = {
        contractName: contractName,
        to: null,
        fn: '(constructor)',
        params: params
      }
    }
    return this._resolvedTransactions[tx.hash]
  }

  _tryResolveContract (codeToResolve, compiledContracts, isCreation) {
    var found = null
    txHelper.visitContracts(compiledContracts, (contract) => {
      var bytes = isCreation ? contract.object.evm.bytecode.object : contract.object.evm.deployedBytecode.object
      if (codeUtil.compareByteCode(codeToResolve, '0x' + bytes)) {
        found = contract.name
        return true
      }
    })
    return found
  }

  _decodeInputParams (data, abi) {
    data = ethJSUtil.toBuffer('0x' + data)
    if (!data.length) data = new Uint8Array(32 * abi.inputs.length) // ensuring the data is at least filled by 0 cause `AbiCoder` throws if there's not engouh data

    var inputTypes = []
    for (var i = 0; i < abi.inputs.length; i++) {
      var type = abi.inputs[i].type
      inputTypes.push(type === 'tuple' ? txHelper.makeFullTupleTypeDefinition(abi.inputs[i]) : type)
    }
    var abiCoder = new ethers.utils.AbiCoder()
    var decoded = abiCoder.decode(inputTypes, data)
    var ret = {}
    for (var k in abi.inputs) {
      ret[abi.inputs[k].type + ' ' + abi.inputs[k].name] = decoded[k]
    }
    return ret
  }
}

// those function will be duplicate after the merged of the compile and run tabs split
function getConstructorInterface (abi) {
  var funABI = { 'name': '', 'inputs': [], 'type': 'constructor', 'outputs': [] }
  for (var i = 0; i < abi.length; i++) {
    if (abi[i].type === 'constructor') {
      funABI.inputs = abi[i].inputs || []
      break
    }
  }

  return funABI
}

function getFunction (abi, fnName) {
  for (var i = 0; i < abi.length; i++) {
    var fn = abi[i]
    if (fnName === fn.name + '(' + fn.inputs.map((value) => { return value.type }).join(',') + ')') {
      return fn
    }
  }
  return null
}

module.exports = TxListener
<|endoftext|>


<commit_before>// Decryption module. Loaded in window.onload()
// Compatible with Google Chrome
// Compatible with Mozilla Firefox, Opera thanks to idb.filesystem.js by Eric Bidelman
var Decryption = (function() {
	// Private
	var chunkSize = 1024 * 1024; // Size of one chunk in B
	var cek = sessionStorage.getItem("cek");
	if (cek == null) { //check if the cek is there
		sessionStorage.clear();
		window.location.href = root+"Logout"; //doesn't exist ? Then logout the user
	}
	var target = 'User';

	var smallQuota = 1024*1024;
	var largeQuota = 1024*1024*1024*100;

	var errorHandler = function(e) {
		console.log("Error");
		console.log(e);
		if(e.constructor.name == "FileError" || e == "SecurityError: It was determined that certain files are unsafe for access within a Web application, or that too many calls are being made on file resources.") {
			alert('The file downloading feature is not available in your browser.');
		}
	};

	var time, time_chunk;

	// API
	window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;

	// Constructor
	function Decryption(fname, f_id, i) {
		this.folder_id = f_id;
		this.filename = fname;
		this.nb_chk = 0;
		this.enc;
		this.i = i; // Id of file, used only for displaying progress, different from database !
		this.halt = false;
		this.getNbChunks();
	}

	// Public
	Decryption.prototype.fromBitArrayCodec = function(arr) {
		/** Convert from a bitArray to an array of bytes. */
		var out = [], bl = sjcl.bitArray.bitLength(arr), i, tmp;
		for (i=0; i<bl/8; i++) {
			if ((i&3) === 0)
				tmp = arr[i/4];
			out.push(tmp >>> 24);
			tmp <<= 8;
		}
		return out;
	};

	Decryption.prototype.abort = function() {
		this.halt = true;
		var node;
		if(node = document.querySelector("#div_download"+(this.i))) {
			while(node.firstChild) // remove all children
				node.removeChild(node.firstChild);
		}
	};

	Decryption.prototype.getNbChunks = function() {
		var me = this;

		if(this.halt)
			return false;

		time = new Time();
		time.start();
		if(this.filename.length > 0) {
			var xhr = new XMLHttpRequest();
			xhr.open("POST", target+'/getNbChunks', true);
			xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

			xhr.onreadystatechange = function() {
				if(xhr.status == 200 && xhr.readyState == 4) {
					if(xhr.responseText > 0) {
						me.nb_chk = xhr.responseText;
						console.log("File splitted in "+me.nb_chk+" chunks");
						me.decryptChk(0);
					}
				}
			}
			xhr.send("filename="+this.filename+"&folder_id="+this.folder_id);
		}
	};

	Decryption.prototype.decryptChk = function(line) {
		var me = this;

		if(this.halt)
			return false;

		var chk;
		if(line === undefined)
			line = 0;

		console.log("Decrypting chunk "+(line+1));
		var pct = line/this.nb_chk*100;
		if(pct > 100)
			pct = 100;
		document.querySelector("#span_download"+(this.i)).innerHTML = this.filename+' : '+pct.toFixed(2)+'%';

		time_chunk = new Time();
		var xhr = new XMLHttpRequest();
		xhr.open("POST", target+'/getChunk', true);
		xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

		xhr.onreadystatechange = function() {
			if(xhr.status == 200 && xhr.readyState == 4) {
				if(xhr.responseText != '') {
					time_chunk.stop();
					console.log("Got chunk "+(line+1)+" contents in "+time_chunk.elapsed()+" ms");

					chk = decodeURIComponent(xhr.responseText);

					var split = chk.split(":");
					if (split.length !== 4) {
						throw new sjcl.exception.corrupt("Error :: Incomplete chunk!");
					}
					var c = sjcl.codec.base64.toBits(split[0]);
					var s = sjcl.codec.base64.toBits(split[1]);
					var a = sjcl.codec.base64.toBits(split[2]);
					var i = sjcl.codec.base64.toBits(split[3]);

					if(me.enc === undefined) {
						console.log("Key derivation process...");
						var key = sjcl.misc.pbkdf2(cek, s, 2000, 256);
						me.enc = new sjcl.cipher.aes(key);
					}

					chk = sjcl.mode.gcm.decrypt(me.enc, c, i, a, 128);

					chk = me.fromBitArrayCodec(chk);
					chk = new Uint8Array(chk);

					// FileSystem API
					// We request large quota (100 GB) to avoid storage errors
					if(window.requestFileSystem === undefined) {
						console.log("Your web browser is currently not supported by Mui app");
					}
					else {
						window.requestFileSystem(
							window.PERSISTENT,
							largeQuota,
							function(fs) {
								fs.root.getFile(me.filename, {create: true}, function(fileEntry) {
									fileEntry.createWriter(function(fileWriter) {
										fileWriter.onwriteend = function(e) {
											// Chunk written
											console.log('Chunk '+(line+1)+'/'+me.nb_chk+' : Write completed.');

											if((line+1) >= me.nb_chk) {
												// All chunks are written
												console.log("Done !");
												time.stop();//
												console.log("decryption + download : "+time.elapsed()+" ms");//
												var node = document.querySelector("#div_download"+(me.i));
												while(node.firstChild) // remove all children
													node.removeChild(node.firstChild);

												// Try to download the file (move from filesystem to download folder)
												if(typeof fileEntry.file === 'function') {
													fileEntry.file(function(file) {
															if(window.navigator.msSaveBlob) {
																// Microsoft
																var blobObject = new Blob([file]);
   																window.navigator.msSaveBlob(blobObject, me.filename);
															}
															else {
																file = new File([file], me.filename);
																console.log("Creating temp url");
																me.dl(window.URL.createObjectURL(file));
															}
														},
														function() {
															me.dl(fileEntry.toURL(), true);
														}
													);
												}
												else
													me.dl(fileEntry.toURL(), true);
											}
											else {
												// Write next chunk
												me.decryptChk(line+1);
											}
										};

										// Write at the end of the file
										fileWriter.seek(fileWriter.length);
										var blob = new Blob([chk]);
										fileWriter.write(blob);

									}, errorHandler);
								}, function() {
									// If we can't write to filesystem, request a quota
									me.requestQuota(me.decryptChk, me.filename, largeQuota);
								});
							},
							errorHandler
						);
					}
				}
			}
		}
		xhr.send("filename="+this.filename+"&line="+line+"&folder_id="+this.folder_id);
	};

	Decryption.prototype.requestQuota = function(fc, arg, quota) {
		// Usually for Google Chrome
		console.log("Mui cannot download contents for now. Requesting quota...");
		if(navigator.webkitPersistentStorage === undefined) {
			console.log("Your web browser is currently not supported by Mui app");
		}
		else {
			if(quota === undefined)
				quota = smallQuota;

			navigator.webkitPersistentStorage.requestQuota(
				quota,
				function(grantedBytes) {
					console.log("Allowed quota");
					fc(arg);
				},
				function() {
					console.log("Denied quota");
				}
			);
		}
	};

	Decryption.prototype.dl = function(url, feUrl) {
		var me = this;
		console.log("File name : "+this.filename+", url : "+url);

		document.querySelector("#dl_decrypted").href = url;
		document.querySelector("#dl_decrypted").download = this.filename;
		document.querySelector("#dl_decrypted").click();

		// Once downloaded, remove the file in sandbox
		setTimeout(function() {
			me.rm(me.filename);
			if(feUrl === undefined) {
				console.log("Removing temp url");
				window.URL.revokeObjectURL(url);
			}
		}, 2000);
	};

	Decryption.prototype.rm = function(filename) {
		var me = this;

		window.requestFileSystem(
			window.PERSISTENT,
			smallQuota,
			function(fs) {
				fs.root.getFile(filename, {create: false}, function(fileEntry) {
					fileEntry.remove(function() {
						console.log('File removed.');
					}, errorHandler);
				}, function() {
					// If we can't delete to filesystem, request a quota
					me.requestQuota(me.rm, filename, smallQuota);
				});
			},
			errorHandler
		);
	};

	return Decryption;
});
<commit_msg>Fixed download bug when the browser requests quota<commit_after>// Decryption module. Loaded in window.onload()
// Compatible with Google Chrome
// Compatible with Mozilla Firefox, Opera thanks to idb.filesystem.js by Eric Bidelman
var Decryption = (function() {
	// Private
	var chunkSize = 1024 * 1024; // Size of one chunk in B
	var cek = sessionStorage.getItem("cek");
	if (cek == null) { //check if the cek is there
		sessionStorage.clear();
		window.location.href = root+"Logout"; //doesn't exist ? Then logout the user
	}
	var target = 'User';

	var smallQuota = 1024*1024;
	var largeQuota = 1024*1024*1024*100;

	var errorHandler = function(e) {
		console.log("Error");
		console.log(e);
		if(e.constructor.name == "FileError" || e == "SecurityError: It was determined that certain files are unsafe for access within a Web application, or that too many calls are being made on file resources.") {
			alert('The file downloading feature is not available in your browser.');
		}
	};

	var time, time_chunk;

	// API
	window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;

	// Constructor
	function Decryption(fname, f_id, i) {
		this.folder_id = f_id;
		this.filename = fname;
		this.nb_chk = 0;
		this.enc;
		this.i = i; // Id of file, used only for displaying progress, different from database !
		this.halt = false;
		this.getNbChunks();
	}

	// Public
	Decryption.prototype.fromBitArrayCodec = function(arr) {
		/** Convert from a bitArray to an array of bytes. */
		var out = [], bl = sjcl.bitArray.bitLength(arr), i, tmp;
		for (i=0; i<bl/8; i++) {
			if ((i&3) === 0)
				tmp = arr[i/4];
			out.push(tmp >>> 24);
			tmp <<= 8;
		}
		return out;
	};

	Decryption.prototype.abort = function() {
		this.halt = true;
		var node;
		if(node = document.querySelector("#div_download"+(this.i))) {
			while(node.firstChild) // remove all children
				node.removeChild(node.firstChild);
		}
	};

	Decryption.prototype.getNbChunks = function() {
		var me = this;

		if(this.halt)
			return false;

		time = new Time();
		time.start();
		if(this.filename.length > 0) {
			var xhr = new XMLHttpRequest();
			xhr.open("POST", target+'/getNbChunks', true);
			xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

			xhr.onreadystatechange = function() {
				if(xhr.status == 200 && xhr.readyState == 4) {
					if(xhr.responseText > 0) {
						me.nb_chk = xhr.responseText;
						console.log("File splitted in "+me.nb_chk+" chunks");
						me.decryptChk(0);
					}
				}
			}
			xhr.send("filename="+this.filename+"&folder_id="+this.folder_id);
		}
	};

	Decryption.prototype.decryptChk = function(line) {
		var me = this;
		console.log(me);

		if(this.halt)
			return false;

		var chk;
		if(line === undefined)
			line = 0;

		console.log("Decrypting chunk "+(line+1));
		var pct = line/this.nb_chk*100;
		if(pct > 100)
			pct = 100;
		if(document.querySelector("#span_download"+(this.i)))
			document.querySelector("#span_download"+(this.i)).innerHTML = this.filename+' : '+pct.toFixed(2)+'%';

		time_chunk = new Time();
		var xhr = new XMLHttpRequest();
		xhr.open("POST", target+'/getChunk', true);
		xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

		xhr.onreadystatechange = function() {
			if(xhr.status == 200 && xhr.readyState == 4) {
				if(xhr.responseText != '') {
					time_chunk.stop();
					console.log("Got chunk "+(line+1)+" contents in "+time_chunk.elapsed()+" ms");

					chk = decodeURIComponent(xhr.responseText);

					var split = chk.split(":");
					if (split.length !== 4) {
						throw new sjcl.exception.corrupt("Error :: Incomplete chunk!");
					}
					var c = sjcl.codec.base64.toBits(split[0]);
					var s = sjcl.codec.base64.toBits(split[1]);
					var a = sjcl.codec.base64.toBits(split[2]);
					var i = sjcl.codec.base64.toBits(split[3]);

					if(me.enc === undefined) {
						console.log("Key derivation process...");
						var key = sjcl.misc.pbkdf2(cek, s, 2000, 256);
						me.enc = new sjcl.cipher.aes(key);
					}

					chk = sjcl.mode.gcm.decrypt(me.enc, c, i, a, 128);

					chk = me.fromBitArrayCodec(chk);
					chk = new Uint8Array(chk);

					// FileSystem API
					// We request large quota (100 GB) to avoid storage errors
					if(window.requestFileSystem === undefined) {
						console.log("Your web browser is currently not supported by Mui app");
					}
					else {
						window.requestFileSystem(
							window.PERSISTENT,
							largeQuota,
							function(fs) {
								fs.root.getFile(me.filename, {create: true}, function(fileEntry) {
									fileEntry.createWriter(function(fileWriter) {
										fileWriter.onwriteend = function(e) {
											// Chunk written
											console.log('Chunk '+(line+1)+'/'+me.nb_chk+' : Write completed.');

											if((line+1) >= me.nb_chk) {
												// All chunks are written
												console.log("Done !");
												time.stop();//
												console.log("decryption + download : "+time.elapsed()+" ms");//
												var node = document.querySelector("#div_download"+(me.i));
												while(node.firstChild) // remove all children
													node.removeChild(node.firstChild);

												// Try to download the file (move from filesystem to download folder)
												if(typeof fileEntry.file === 'function') {
													fileEntry.file(function(file) {
															if(window.navigator.msSaveBlob) {
																// Microsoft
																var blobObject = new Blob([file]);
   																window.navigator.msSaveBlob(blobObject, me.filename);
															}
															else {
																file = new File([file], me.filename);
																console.log("Creating temp url");
																me.dl(window.URL.createObjectURL(file));
															}
														},
														function() {
															me.dl(fileEntry.toURL(), true);
														}
													);
												}
												else
													me.dl(fileEntry.toURL(), true);
											}
											else {
												// Write next chunk
												me.decryptChk(line+1);
											}
										};

										// Write at the end of the file
										fileWriter.seek(fileWriter.length);
										var blob = new Blob([chk]);
										fileWriter.write(blob);

									}, errorHandler);
								}, function() {
									// If we can't write to filesystem, request a quota
									me.requestQuota(me.decryptChk, 0, largeQuota);
								});
							},
							errorHandler
						);
					}
				}
			}
		}
		xhr.send("filename="+this.filename+"&line="+line+"&folder_id="+this.folder_id);
	};

	Decryption.prototype.requestQuota = function(fc, arg, quota) {
		// Usually for Google Chrome
		var me = this;
		console.log("Mui cannot download contents for now. Requesting quota...");
		if(navigator.webkitPersistentStorage === undefined) {
			console.log("Your web browser is currently not supported by Mui app");
		}
		else {
			if(quota === undefined)
				quota = smallQuota;

			navigator.webkitPersistentStorage.requestQuota(
				quota,
				function(grantedBytes) {
					if(grantedBytes > 0) {
						console.log("Allowed quota");
						fc.bind(me, arg)();
					}
					else {
						console.log("Denied quota");
					}
				},
				function() {
					console.log("Error while requesting quota");
				}
			);
		}
	};

	Decryption.prototype.dl = function(url, feUrl) {
		var me = this;
		console.log("File name : "+this.filename+", url : "+url);

		document.querySelector("#dl_decrypted").href = url;
		document.querySelector("#dl_decrypted").download = this.filename;
		document.querySelector("#dl_decrypted").click();

		// Once downloaded, remove the file in sandbox
		setTimeout(function() {
			me.rm(me.filename);
			if(feUrl === undefined) {
				console.log("Removing temp url");
				window.URL.revokeObjectURL(url);
			}
		}, 2000);
	};

	Decryption.prototype.rm = function(filename) {
		var me = this;

		window.requestFileSystem(
			window.PERSISTENT,
			smallQuota,
			function(fs) {
				fs.root.getFile(filename, {create: false}, function(fileEntry) {
					fileEntry.remove(function() {
						console.log('File removed.');
					}, errorHandler);
				}, function() {
					// If we can't delete to filesystem, request a quota
					me.requestQuota(me.rm, filename, smallQuota);
				});
			},
			errorHandler
		);
	};

	return Decryption;
});
<|endoftext|>


<commit_before>import { module } from 'qunit';
import startApp from '../helpers/start-app';
import destroyApp from '../helpers/destroy-app';

export default function(name, options = {}) {
  module(name, {
    beforeEach() {
      this.application = startApp();

      if (options.beforeEach) {
        options.beforeEach.apply(this, arguments);
      }
    },

    afterEach() {
      if (options.afterEach) {
        options.afterEach.apply(this, arguments);
      }

      destroyApp(this.application);
    }
  });
}
<commit_msg>fix failing test<commit_after>import { module } from 'qunit';
import startApp from '../helpers/start-app';
import destroyApp from '../helpers/destroy-app';

export default function(name, options = {}) {
  module(name, {
    beforeEach() {
      this.application = startApp();

      if (options.beforeEach) {
        options.beforeEach(...arguments);
      }
    },

    afterEach() {
      if (options.afterEach) {
        options.afterEach(...arguments);
      }

      destroyApp(this.application);
    }
  });
}
<|endoftext|>


<commit_before>var EventEmitter = require('events').EventEmitter
var inherits     = require('util').inherits
var ranges       = require('string-range')
var fixRange     = require('level-fix-range')
var xtend        = require('xtend')

inherits(SubDB, EventEmitter)

function SubDB (db, prefix, options) {
  if(!(this instanceof SubDB)) return new SubDB(db, prefix, options)
  if(!db)     throw new Error('must provide db')
  if(!prefix) throw new Error('must provide prefix')

  options = options || {}
  options.sep = options.sep || '\xff'

  this._parent = db
  this._options = options
  this._prefix = prefix
  this._root = root(this)
  db.sublevels[prefix] = this
  this.sublevels = {}
  this.methods = {}
  var self = this
  this.hooks = {
    pre: function () {
      return self.pre.apply(self, arguments)
    },
    post: function () {
      return self.post.apply(self, arguments)
    }
  }
}

var SDB = SubDB.prototype

SDB._key = function (key) {
  var sep = this._options.sep
  return sep
    + this._prefix
    + sep
    + key
}

SDB._getOptsAndCb = function (opts, cb) {
  if (typeof opts == 'function') {
    cb = opts
    opts = {}
  }
  return { opts: xtend(opts, this._options), cb: cb }
}

SDB.sublevel = function (prefix, options) {
  if(this.sublevels[prefix])
    return this.sublevels[prefix]
  return new SubDB(this, prefix, options || this._options)
}

SDB.put = function (key, value, opts, cb) {
  var res = this._getOptsAndCb(opts, cb)
  this._root.put(this.prefix(key), value, res.opts, res.cb)
//  this._parent.put(this._key(key), value, opts, cb)
}

SDB.get = function (key, opts, cb) {
  var res = this._getOptsAndCb(opts, cb)
  this._root.get(this.prefix(key), res.opts, res.cb)
//  this._parent.get(this._key(key), opts, cb)
}

SDB.del = function (key, opts, cb) {
  this._root.del(this.prefix(key), opts, cb)
//  this._parent.del(this._key(key), opts, cb)
}

SDB.batch = function (changes, opts, cb) {
  var self = this
  changes.forEach(function (ch) {
    //OH YEAH, WE NEED TO VALIDATE THAT UPDATING THIS KEY/PREFIX IS ALLOWED
    if('string' === typeof ch.prefix) {
      ch.key = ch.prefix + ch.key
    } else
    ch.key = (ch.prefix || self).prefix(ch.key)
    if(ch.prefix) ch.prefix = null
  })
  this._root.batch(changes, opts, cb)
}

SDB.prefix = function (key) {
  var sep = this._options.sep
  return this._parent.prefix() + sep + this._prefix + sep + (key || '')
}

SDB.keyStream =
SDB.createKeyStream = function (opts) {
  opts = opts || {}
  opts.keys = true
  opts.values = false
  return this.createReadStream(opts)
}

SDB.valueStream =
SDB.createValueStream = function (opts) {
  opts = opts || {}
  opts.values = true
  opts.keys = false
  return this.createReadStream(opts)
}

function selectivelyMerge(_opts, opts) {
  [ 'valueEncoding'
  , 'reverse'
  , 'values'
  , 'keys'
  ]
  .forEach(function (k) {
    if (opts.hasOwnProperty(k)) _opts[k] = opts[k]
  })
}

SDB.readStream =
SDB.createReadStream = function (opts) {
  opts = opts || {}

  var r = root(this)
  var p = this.prefix()
  //opts.start = p + (opts.start || '')
  //opts.end = p + (opts.end || this._options.sep)

  var _opts = ranges.prefix(opts, p)
  selectivelyMerge(_opts, xtend(opts, this._options))

  return r.createReadStream(_opts)
    .on('data', function (d) {
      //mutate the prefix!
      //this doesn't work for createKeyStream admittedly.
      if(d.key)
        d.key = d.key.substring(p.length)

    })
}

SDB.writeStream =
SDB.createWriteStream = function () {
  var r = root(this)
  var p = this.prefix()
  var ws = r.createWriteStream.apply(r, arguments)
  var write = ws.write
  ws.write = function (data) {
    data.key = p + data.key
    return write.call(ws, data)
  }
  return ws
}

SDB.approximateSize = function () {
  var r = root(db)
  return r.approximateSize.apply(r, arguments)
}

function root(db) {
  if(!db._parent) return db
  return root(db._parent)
}

SDB.pre = function (range, hook) {
  if(!hook) hook = range, range = null
  range = ranges.prefix(range, this.prefix(), this._options.sep)
  var r = root(this._parent)
  var p = this.prefix()
  return r.hooks.pre(fixRange(range), function (ch, add) {
    hook({
      key: ch.key.substring(p.length),
      value: ch.value,
      type: ch.type
    }, function (ch, _p) {
      //maybe remove the second add arg now
      //that op can have prefix?
      add(ch, ch.prefix ? _p : (_p || p))
    })
  })
}

SDB.post = function (range, hook) {
  if(!hook) hook = range, range = null
  var r = root(this._parent)
  var p = this.prefix()
  range = ranges.prefix(range, p, this._options.sep)
  return r.hooks.post(fixRange(range), function (data) {
    hook({key: data.key.substring(p.length), value: data.value, type: data.type})
  })
}

var exports = module.exports = SubDB

<commit_msg>propagating additional options values to levelup<commit_after>var EventEmitter = require('events').EventEmitter
var inherits     = require('util').inherits
var ranges       = require('string-range')
var fixRange     = require('level-fix-range')
var xtend        = require('xtend')

inherits(SubDB, EventEmitter)

function SubDB (db, prefix, options) {
  if(!(this instanceof SubDB)) return new SubDB(db, prefix, options)
  if(!db)     throw new Error('must provide db')
  if(!prefix) throw new Error('must provide prefix')

  options = options || {}
  options.sep = options.sep || '\xff'

  this._parent = db
  this._options = options
  this._prefix = prefix
  this._root = root(this)
  db.sublevels[prefix] = this
  this.sublevels = {}
  this.methods = {}
  var self = this
  this.hooks = {
    pre: function () {
      return self.pre.apply(self, arguments)
    },
    post: function () {
      return self.post.apply(self, arguments)
    }
  }
}

var SDB = SubDB.prototype

SDB._key = function (key) {
  var sep = this._options.sep
  return sep
    + this._prefix
    + sep
    + key
}

SDB._getOptsAndCb = function (opts, cb) {
  if (typeof opts == 'function') {
    cb = opts
    opts = {}
  }
  return { opts: xtend(opts, this._options), cb: cb }
}

SDB.sublevel = function (prefix, options) {
  if(this.sublevels[prefix])
    return this.sublevels[prefix]
  return new SubDB(this, prefix, options || this._options)
}

SDB.put = function (key, value, opts, cb) {
  var res = this._getOptsAndCb(opts, cb)
  this._root.put(this.prefix(key), value, res.opts, res.cb)
//  this._parent.put(this._key(key), value, opts, cb)
}

SDB.get = function (key, opts, cb) {
  var res = this._getOptsAndCb(opts, cb)
  this._root.get(this.prefix(key), res.opts, res.cb)
//  this._parent.get(this._key(key), opts, cb)
}

SDB.del = function (key, opts, cb) {
  this._root.del(this.prefix(key), opts, cb)
//  this._parent.del(this._key(key), opts, cb)
}

SDB.batch = function (changes, opts, cb) {
  var self = this
  changes.forEach(function (ch) {
    //OH YEAH, WE NEED TO VALIDATE THAT UPDATING THIS KEY/PREFIX IS ALLOWED
    if('string' === typeof ch.prefix) {
      ch.key = ch.prefix + ch.key
    } else
    ch.key = (ch.prefix || self).prefix(ch.key)
    if(ch.prefix) ch.prefix = null
  })
  this._root.batch(changes, opts, cb)
}

SDB.prefix = function (key) {
  var sep = this._options.sep
  return this._parent.prefix() + sep + this._prefix + sep + (key || '')
}

SDB.keyStream =
SDB.createKeyStream = function (opts) {
  opts = opts || {}
  opts.keys = true
  opts.values = false
  return this.createReadStream(opts)
}

SDB.valueStream =
SDB.createValueStream = function (opts) {
  opts = opts || {}
  opts.values = true
  opts.keys = false
  return this.createReadStream(opts)
}

function selectivelyMerge(_opts, opts) {
  [ 'valueEncoding'
  , 'encoding'
  , 'keyEncoding'
  , 'reverse'
  , 'values'
  , 'keys'
  , 'limit'
  , 'fillCache'
  ]
  .forEach(function (k) {
    if (opts.hasOwnProperty(k)) _opts[k] = opts[k]
  })
}

SDB.readStream =
SDB.createReadStream = function (opts) {
  opts = opts || {}

  var r = root(this)
  var p = this.prefix()
  //opts.start = p + (opts.start || '')
  //opts.end = p + (opts.end || this._options.sep)

  var _opts = ranges.prefix(opts, p)
  selectivelyMerge(_opts, xtend(opts, this._options))

  return r.createReadStream(_opts)
    .on('data', function (d) {
      //mutate the prefix!
      //this doesn't work for createKeyStream admittedly.
      if(d.key)
        d.key = d.key.substring(p.length)

    })
}

SDB.writeStream =
SDB.createWriteStream = function () {
  var r = root(this)
  var p = this.prefix()
  var ws = r.createWriteStream.apply(r, arguments)
  var write = ws.write
  ws.write = function (data) {
    data.key = p + data.key
    return write.call(ws, data)
  }
  return ws
}

SDB.approximateSize = function () {
  var r = root(db)
  return r.approximateSize.apply(r, arguments)
}

function root(db) {
  if(!db._parent) return db
  return root(db._parent)
}

SDB.pre = function (range, hook) {
  if(!hook) hook = range, range = null
  range = ranges.prefix(range, this.prefix(), this._options.sep)
  var r = root(this._parent)
  var p = this.prefix()
  return r.hooks.pre(fixRange(range), function (ch, add) {
    hook({
      key: ch.key.substring(p.length),
      value: ch.value,
      type: ch.type
    }, function (ch, _p) {
      //maybe remove the second add arg now
      //that op can have prefix?
      add(ch, ch.prefix ? _p : (_p || p))
    })
  })
}

SDB.post = function (range, hook) {
  if(!hook) hook = range, range = null
  var r = root(this._parent)
  var p = this.prefix()
  range = ranges.prefix(range, p, this._options.sep)
  return r.hooks.post(fixRange(range), function (data) {
    hook({key: data.key.substring(p.length), value: data.value, type: data.type})
  })
}

var exports = module.exports = SubDB

<|endoftext|>