<commit_before>exports.ActionMgr = function (db, mongodb, async, converter, prefix, mapping) {
	//CLIENT------------------------------------------------------------------------
	var Util = require('./util');
	var util = new Util(db, mongodb, async, converter, prefix);

	var url = require('url');

	/* Ghi nhận một action mới
	 Tham số: {
	 _mtid : number
	 _typeid: number // type of action, eg: "purchase", "pageview"
	 osid: number // os information, eg: "window", "linux",
	 browserid : number // eg, "chrome", "firefox", "opera",
	 locationid : number // location code, eg: Hanoi, Vietnam
	 referer: string
	 deviceid : number
	 _ctime: date // created time
	 ip: string // public ip address
	 screenres: string // screen resolution of the device
	 totalsec: number // total number of sec to finish the action
	 url: string
	 browserversion : number
	 osversion : number
	 _data: data
	 }
	 */
	this.save = function (req, res, callback) {
		var data = req.body;
		var query = url.parse(data.url, true).query;

		// extract campaign
		var utm_source = query.utm_source;
		var utm_campaign = query.utm_campaign;

		var appid = req.params.appid;

		var mtid = data._mtid;
		var temp = data.user;
		delete data.user;
		var collection = prefix + appid;
		var collectionmapping = prefix + mapping;

		data._mtid = new mongodb.ObjectID(data._mtid);
		data._segments = [];
		// Add created time
		data._ctime = Math.round(new Date() / 1000);

		// retrive real mtid because user can still use old mtid
		db.collection(collectionmapping).find({key: data._mtid}, {key: 1, value: 1}).limit(1).toArray(function (err, r) {
			if (err) throw err;
			if (r.length != 0) data._mtid = r[0].value;

			converter.toObject(data, function (results) {
				db.collection(collection).insertOne(results, function (err, r) {
					if (err) throw err;
					res.status(200).end();
					if (callback) callback();
				});
			});

			//get user infomation
			db.collection(collection).find({_id: data._mtid}).limit(1).toArray(function (err, ret) {
				var user = ret[0];
				var typeid = data._typeid;
				converter.toIds('_revenue', '_firstcampaign', '_lastcampaign', '_campaign', function (ids) {
					// increase revenue
					if (typeid == 'purchase') {
						if (user[ids._revenue] == undefined) user[ids._revenue] = 0;
						user[ids._revenue] += data.data.amount;
					}

					if (typeid == 'pageview') {
						// record campaign
						if (utm_campaign) {
							if (user[ids._firstcampaign] == undefined) {
								user[ids._firstcampaign] = utm_campaign;
							}

							user[ids._lastcampaign] = utm_campaign;
							if (user[ids.campaign] == undefined) user[ids.campaign] = [];
							if (user[ids.campaign].indexOf(utm_campaign) == -1)
								user[ids.campaign] = user[ids.campaign].concat(utm_campaign).sort();
						}
					}

					util.updateUserInf(appid, _mtid, temp);

				});
			});
		});
	};

	// purpose: add new data to arrays in user
	// param:
	// + collection: collection to query user information
	// + mtid: mongodb.ObjectID mtid of user
	// + data: data to be append to user
	function updateArrayBasedUserInfo(collection, mtid, data) {
		converter.toObject(data, function (datax) {
			// get the user record
			db.collection(collection).find({_id: mtid}).limit(1).toArray(function (err, r) {
				if (err) throw err;
				if (r.length == 0) throw "user not found mtid=" + mtid;
				var user = r[0];

				// append new element to the array or create one
				var arr = [];
				for (var p in datax) if (datax.hasOwnProperty(p)) {
					if (user[p] != undefined) {
						arr = user[p];
					}
					if (arr instanceof Array == false)
						arr = [arr];

					arr = arr.concat(datax[p]).sort();
				}
				db.collection(collection).updateOne({_id: mtid}, {"$set": user}, function (err, r) {
					if (err) throw err;
				});
			});
		});
	}

	// purposer: phương thức này dùng để báo cho hệ thống biết một anonymous
	// user thực ra là một user đã tồn tại. Xem thêm ở http://pasteboard.co/1WAK4HYz.png
	// url: {appid}
	// param:
	// + mtid: string, //mtid của anonymous user
	// + user: {[userid], name, email, age, birth, gender, ...}
	// condition:
	// + case 1 : userid exist, iden-mtid is equal mtid
	//         client want to update info of an existing user
	//         just update the info based on mtid.
	// + case 2: user.userid exist, iden-mtid (mtid found by user.userid) is not equals to mtid
	//         mtid is now an ano-mtid (mtid for an anonymous visitor)
	//         add a mapping beetwen ano-mtid and ide-mtid, after this
	//         all action done by ano-mtid is converted to ide-mtid
	//         update info, delete ano-mtid user record if existed
	// + case 3: user.userid doesn't exist
	//         client want identify ano-mtid into registed user
	//         in this case, create new user with ide-mtid equal ano-mtid.
	//         just simply add userid field to old ano-mtid record, and
	//         udpate new info
	// + case 4: user.userid does not present
	//         client want to update info of an user
	//         do exactly as case 1.
	// output: return mtid of identified visitor
	this.identify = function (req, res, callback) {
		var data = req.body;
		var collection = prefix + req.params.appid;
		var collectionmapping = prefix + mapping;
		var user = data.user;
		var userid = user.userid;

		// protect system properties, allow working only on user-based props
		// user-based prop is not started with an underscore '_' character
		var userex = {};
		for (var p in user) if (user.hasOwnProperty(p))
			if (p.startsWith('_') == false)
				userex[p] = user[p];
		user = userex;

		var themtid = new mongodb.ObjectID(data.mtid);
		converter.toIDs(['_isUser', 'userid', '_mtid'], function (ids) {
			converter.toObject(user, function (userx) {
				// check for case 4
				if (userid == undefined) return updateUserInfo(themtid, userx, callback);

				var query = {};
				query[ids._isUser] = true;
				query[ids.userid] = userid;
				db.collection(collection).findOneAndUpdate(query, {$set: userx}, {projection: {_id: 1}}, function (err, r) {
					if (err) throw err;

					// case 3 : user doesn't exist
					if (r.value == null) return updateUserInfo(themtid, userx, callback);

					// user exist
					var ide_mtid = r.value._id;
					// check for case 1
					if (themtid == ide_mtid) return updateUserInfo(themtid, userx, callback);

					// case 2
					// add to mapping collection
					db.collection(collectionmapping).insertOne({
						anomtid: themtid,
						idemtid: ide_mtid,
						ctime: new Date()
					}, function (err) {
						if (err) throw err;
					});

					//convert all ano-mtid to ide-mtid
					var query = {};
					var update = {};
					query[ids._mtid] = themtid;
					update[ids._mtid] = ide_mtid;
					db.collection(collection).updateMany(query, {$set: update}, function (err) {
						if (err) throw err;
					});

					// delete ano-mtid record IF EXISTED
					db.collection(collection).deleteOne({_id: themtid}, function () {
					});

					return updateUserInfo(ide_mtid, userx, callback)
				});
			});
		});

		// purpose: update info which mtid is mtid
		function updateUserInfo(mtid, userx, callback) {
			res.send(mtid);
			db.collection(collection).updateOne({_id: mtid}, {$set: userx}, function (err, result) {
				if (err) throw err;
				callback(mtid);
			});
		}

	};

	// purpose: set up new record for anonymous user
	// Url /{appid}/?deltatime=20
	// param:
	// + appid: id of the app
	// + deltatime: number of second had elapsed before the request sent
	// output: new mtid
	this.setup = function (req, res, callback) {
		var deltatime = req.body._deltatime || 0;
		var collection = prefix + req.params.appid;
		var user = {
			_isUser: true,
			_segments: [],
			_stime: Math.round(new Date() / 1000) - deltatime
		};
		converter.toObject(user, function (user) {
			db.collection(collection).insertOne(user, function (err, results) {
				if (err) throw err;
				var mtid = results.insertedId;
				res.send(mtid);
				if (callback) callback(mtid);
			});
		});
	};
};<commit_msg>refine record method<commit_after>exports.ActionMgr = function (db, mongodb, async, converter, prefix, mapping) {
	//CLIENT------------------------------------------------------------------------
	var Util = require('./util');
	var util = new Util(db, mongodb, async, converter, prefix);

	var url = require('url');

	// purpose: record an action
	// url: {appid}/r
	// param:
	// + _deltat: number of delayed second before request sent
	// + _mtid : number
	// + _typeid: string // type of action, eg: "purchase", "pageview"
	// + _osid: number // os information, eg: "window", "linux",
	// + _browserid : number // eg, "chrome", "firefox", "opera",
	// + _locationid : number // location code, eg: Hanoi, Vietnam
	// + _referer: string
	// + _deviceid : number
	// + _ip: string // public ip address
	// + _screenres: string // screen resolution of the device
	// + _totalsec: number // total number of sec to finish the action
	// + _url: string
	// + _browserversion : number
	// + _osversion : number
	// + data1
	// + data2
	// + data3
	// }
	////
	this.save = function (req, res, callback) {
		var data = req.body;
		var query = url.parse(data.url, true).query;

		// extract campaign
		var utm_source = query.utm_source;
		var utm_campaign = query.utm_campaign;

		var appid = req.params.appid;

		var mtid = new mongodb.ObjectID(data._mtid);
		var temp = data.user;
		delete data.user;
		var collection = prefix + appid;
		var collectionmapping = prefix + mapping;

		data._segments = [];

		// correct timming
		data._ctime = Math.round(new Date() / 1000) + (data._deltat ? data._deltat : 0);
		delete data._deltat;

		// retrive real mtid because user can still use old mtid
		db.collection(collectionmapping).find({anomtid: mtid}).limit(1).toArray(function (err, r) {
			if (err) throw err;
			if (r.length != 0) mtid = r[0].idemtid;

			converter.toObject(data, function (results) {
				db.collection(collection).insertOne(results, function (err, r) {
					if (err) throw err;
					console.log(r.insertedId);
					res.status(200).end();
					if (callback) callback();
				});
			});

			//get user infomation
			db.collection(collection).find({_id: data._mtid}).limit(1).toArray(function (err, ret) {
				var user = ret[0];
				var typeid = data._typeid;
				converter.toIds('_revenue', '_firstcampaign', '_lastcampaign', '_campaign', function (ids) {
					// increase revenue
					if (typeid == 'purchase') {
						if (user[ids._revenue] == undefined) user[ids._revenue] = 0;
						user[ids._revenue] += data.data.amount;
					}

					if (typeid == 'pageview') {
						// record campaign
						if (utm_campaign) {
							if (user[ids._firstcampaign] == undefined) {
								user[ids._firstcampaign] = utm_campaign;
							}

							user[ids._lastcampaign] = utm_campaign;
							if (user[ids.campaign] == undefined) user[ids.campaign] = [];
							if (user[ids.campaign].indexOf(utm_campaign) == -1)
								user[ids.campaign] = user[ids.campaign].concat(utm_campaign).sort();
						}
					}

					updateArrayBasedUserInfo(collection, _mtid, temp);
				});
			});
		});
	};

	// purpose: add new data to arrays in user
	// param:
	// + collection: collection to query user information
	// + mtid: mongodb.ObjectID mtid of user
	// + data: data to be append to user
	function updateArrayBasedUserInfo(collection, mtid, data) {
		converter.toObject(data, function (datax) {
			// get the user record
			db.collection(collection).find({_id: mtid}).limit(1).toArray(function (err, r) {
				if (err) throw err;
				if (r.length == 0) throw "user not found mtid=" + mtid;
				var user = r[0];

				// append new element to the array or create one
				var arr = [];
				for (var p in datax) if (datax.hasOwnProperty(p)) {
					if (user[p] != undefined) {
						arr = user[p];
					}
					if (arr instanceof Array == false)
						arr = [arr];

					arr = arr.concat(datax[p]).sort();
				}
				db.collection(collection).updateOne({_id: mtid}, {"$set": user}, function (err, r) {
					if (err) throw err;
				});
			});
		});
	}

	// purposer: phương thức này dùng để báo cho hệ thống biết một anonymous
	// user thực ra là một user đã tồn tại. Xem thêm ở http://pasteboard.co/1WAK4HYz.png
	// url: {appid}
	// param:
	// + mtid: string, //mtid của anonymous user
	// + user: {[userid], name, email, age, birth, gender, ...}
	// condition:
	// + case 1 : userid exist, iden-mtid is equal mtid
	//         client want to update info of an existing user
	//         just update the info based on mtid.
	// + case 2: user.userid exist, iden-mtid (mtid found by user.userid) is not equals to mtid
	//         mtid is now an ano-mtid (mtid for an anonymous visitor)
	//         add a mapping beetwen ano-mtid and ide-mtid, after this
	//         all action done by ano-mtid is converted to ide-mtid
	//         update info, delete ano-mtid user record if existed
	// + case 3: user.userid doesn't exist
	//         client want identify ano-mtid into registed user
	//         in this case, create new user with ide-mtid equal ano-mtid.
	//         just simply add userid field to old ano-mtid record, and
	//         udpate new info
	// + case 4: user.userid does not present
	//         client want to update info of an user
	//         do exactly as case 1.
	// output: return mtid of identified visitor
	this.identify = function (req, res, callback) {
		var data = req.body;
		var collection = prefix + req.params.appid;
		var collectionmapping = prefix + mapping;
		var user = data.user;
		var userid = user.userid;

		// protect system properties, allow working only on user-based props
		// user-based prop is not started with an underscore '_' character
		var userex = {};
		for (var p in user) if (user.hasOwnProperty(p))
			if (p.startsWith('_') == false)
				userex[p] = user[p];
		user = userex;

		var themtid = new mongodb.ObjectID(data.mtid);
		converter.toIDs(['_isUser', 'userid', '_mtid'], function (ids) {
			converter.toObject(user, function (userx) {
				// check for case 4
				if (userid == undefined) return updateUserInfo(themtid, userx, callback);

				var query = {};
				query[ids._isUser] = true;
				query[ids.userid] = userid;
				db.collection(collection).findOneAndUpdate(query, {$set: userx}, {projection: {_id: 1}}, function (err, r) {
					if (err) throw err;

					// case 3 : user doesn't exist
					if (r.value == null) return updateUserInfo(themtid, userx, callback);

					// user exist
					var ide_mtid = r.value._id;
					// check for case 1
					if (themtid == ide_mtid) return updateUserInfo(themtid, userx, callback);

					// case 2
					// add to mapping collection
					db.collection(collectionmapping).insertOne({
						anomtid: themtid,
						idemtid: ide_mtid,
						ctime: new Date()
					}, function (err) {
						if (err) throw err;
					});

					//convert all ano-mtid to ide-mtid
					var query = {};
					var update = {};
					query[ids._mtid] = themtid;
					update[ids._mtid] = ide_mtid;
					db.collection(collection).updateMany(query, {$set: update}, function (err) {
						if (err) throw err;
					});

					// delete ano-mtid record IF EXISTED
					db.collection(collection).deleteOne({_id: themtid}, function () {
					});

					return updateUserInfo(ide_mtid, userx, callback)
				});
			});
		});

		// purpose: update info which mtid is mtid
		function updateUserInfo(mtid, userx, callback) {
			res.send(mtid);
			db.collection(collection).updateOne({_id: mtid}, {$set: userx}, function (err, result) {
				if (err) throw err;
				callback(mtid);
			});
		}

	};

	// purpose: set up new record for anonymous user
	// Url /{appid}/?deltatime=20
	// param:
	// + appid: id of the app
	// + deltatime: number of second had elapsed before the request sent
	// output: new mtid
	this.setup = function (req, res, callback) {
		var deltatime = req.body._deltatime || 0;
		var collection = prefix + req.params.appid;
		var user = {
			_isUser: true,
			_segments: [],
			_stime: Math.round(new Date() / 1000) - deltatime
		};
		converter.toObject(user, function (user) {
			db.collection(collection).insertOne(user, function (err, results) {
				if (err) throw err;
				var mtid = results.insertedId;
				res.send(mtid);
				if (callback) callback(mtid);
			});
		});
	};
};<|endoftext|>


<commit_before>'use strict';
const requireDir = require('./helpers/require-dir');
const path = require('path');
const request = require('sonos-discovery/lib/helpers/request');
const logger = require('sonos-discovery/lib/helpers/logger');

function HttpAPI(discovery, settings) {

  const port = settings.port;
  const webroot = settings.webroot;
  const actions = {};

  this.getWebRoot = function () {
    return webroot;
  };

  this.getPort = function () {
    return port;
  };

  this.discovery = discovery;

  discovery.on('transport-state', function (player) {
    invokeWebhook('transport-state', player);
  });

  discovery.on('topology-change', function (topology) {
    invokeWebhook('topology-change', topology);
  });

  discovery.on('volume-change', function (volumeChange) {
    invokeWebhook('volume-change', volumeChange);
  });

  discovery.on('mute-change', function (muteChange) {
    invokeWebhook('mute-change', muteChange);
  });

  // this handles registering of all actions
  this.registerAction = function (action, handler) {
    actions[action] = handler;
  };

  //load modularized actions
  requireDir(path.join(__dirname, './actions'), (registerAction) => {
    registerAction(this);
  });

  this.requestHandler = function (req, res) {
    if (req.url === '/favicon.ico') {
      res.end();
      return;
    }

    if (discovery.zones.length === 0) {
      const msg = 'No system has yet been discovered. Please see https://github.com/jishi/node-sonos-http-api/issues/77 if it doesn\'t resolve itself in a few seconds.';
      logger.error(msg);
      sendResponse(500, { status: 'error', error: msg });
      return;
    }

    const params = req.url.substring(1).split('/');

    let player = discovery.getPlayer(decodeURIComponent(params[0]));

    const opt = {};

    if (player) {
      opt.action = (params[1] || '').toLowerCase();
      opt.values = params.splice(2);
    } else {
      player = discovery.getAnyPlayer();
      opt.action = (params[0] || '').toLowerCase();
      opt.values = params.splice(1);
    }

    function sendResponse(code, body) {
      var jsonResponse = JSON.stringify(body);
      res.statusCode = code;
      res.setHeader('Content-Length', Buffer.byteLength(jsonResponse));
      res.setHeader('Content-Type', 'application/json;charset=utf-8');
      res.write(new Buffer(jsonResponse));
      res.end();
    }

    opt.player = player;
    handleAction(opt)
    .then((response) => {
      if (!response || response.constructor.name === 'IncomingMessage') {
        response = { status: 'success' };
      } else if (Array.isArray(response) && response.length > 0 && response[0].constructor.name === 'IncomingMessage') {
        response = { status: 'success' };
      }

      sendResponse(200, response);
    }).catch((error) => {
      logger.error(error);
      sendResponse(500, { status: 'error', error: error.message, stack: error.stack });
    });
  };

  function handleAction(options) {
    var player = options.player;

    if (!actions[options.action]) {
      return Promise.reject({ error: 'action \'' + options.action + '\' not found' });
    }

    return actions[options.action](player, options.values);

  }

  function invokeWebhook(type, data) {
    if (!settings.webhook) return;

    const jsonBody = JSON.stringify({
      type: type,
      data: data
    });

    const body = new Buffer(jsonBody, 'utf8');

    request({
      method: 'POST',
      uri: settings.webhook,
      headers: {
        'Content-Type': 'application/json',
        'Content-Length': body.length
      },
      body
    })
    .catch(function (err) {
      logger.error('Could not reach webhook endpoint', settings.webhook, 'for some reason. Verify that the receiving end is up and running.');
      logger.error(err);
    })
  }

}

module.exports = HttpAPI;
<commit_msg>Changed function invokeWebhook to allow for additional settings (#487)<commit_after>'use strict';
const requireDir = require('./helpers/require-dir');
const path = require('path');
const request = require('sonos-discovery/lib/helpers/request');
const logger = require('sonos-discovery/lib/helpers/logger');

function HttpAPI(discovery, settings) {

  const port = settings.port;
  const webroot = settings.webroot;
  const actions = {};

  this.getWebRoot = function () {
    return webroot;
  };

  this.getPort = function () {
    return port;
  };

  this.discovery = discovery;

  discovery.on('transport-state', function (player) {
    invokeWebhook('transport-state', player);
  });

  discovery.on('topology-change', function (topology) {
    invokeWebhook('topology-change', topology);
  });

  discovery.on('volume-change', function (volumeChange) {
    invokeWebhook('volume-change', volumeChange);
  });

  discovery.on('mute-change', function (muteChange) {
    invokeWebhook('mute-change', muteChange);
  });

  // this handles registering of all actions
  this.registerAction = function (action, handler) {
    actions[action] = handler;
  };

  //load modularized actions
  requireDir(path.join(__dirname, './actions'), (registerAction) => {
    registerAction(this);
  });

  this.requestHandler = function (req, res) {
    if (req.url === '/favicon.ico') {
      res.end();
      return;
    }

    if (discovery.zones.length === 0) {
      const msg = 'No system has yet been discovered. Please see https://github.com/jishi/node-sonos-http-api/issues/77 if it doesn\'t resolve itself in a few seconds.';
      logger.error(msg);
      sendResponse(500, { status: 'error', error: msg });
      return;
    }

    const params = req.url.substring(1).split('/');

    let player = discovery.getPlayer(decodeURIComponent(params[0]));

    const opt = {};

    if (player) {
      opt.action = (params[1] || '').toLowerCase();
      opt.values = params.splice(2);
    } else {
      player = discovery.getAnyPlayer();
      opt.action = (params[0] || '').toLowerCase();
      opt.values = params.splice(1);
    }

    function sendResponse(code, body) {
      var jsonResponse = JSON.stringify(body);
      res.statusCode = code;
      res.setHeader('Content-Length', Buffer.byteLength(jsonResponse));
      res.setHeader('Content-Type', 'application/json;charset=utf-8');
      res.write(new Buffer(jsonResponse));
      res.end();
    }

    opt.player = player;
    handleAction(opt)
    .then((response) => {
      if (!response || response.constructor.name === 'IncomingMessage') {
        response = { status: 'success' };
      } else if (Array.isArray(response) && response.length > 0 && response[0].constructor.name === 'IncomingMessage') {
        response = { status: 'success' };
      }

      sendResponse(200, response);
    }).catch((error) => {
      logger.error(error);
      sendResponse(500, { status: 'error', error: error.message, stack: error.stack });
    });
  };

  function handleAction(options) {
    var player = options.player;

    if (!actions[options.action]) {
      return Promise.reject({ error: 'action \'' + options.action + '\' not found' });
    }

    return actions[options.action](player, options.values);

  }

  function invokeWebhook(type, data) {
    var typeName = "type";
    var dataName = "data";
    if (!settings.webhook) return;

    if (settings.webhookType) { typeName = settings.webhookType; }
    if (settings.webhookData) { dataName = settings.webhookData; }

    const jsonBody = JSON.stringify({
      [typeName]: type,
      [dataName]: data
    });

    const body = new Buffer(jsonBody, 'utf8');

    var headers = {
        'Content-Type': 'application/json',
        'Content-Length': body.length
      }
    if (settings.webhookHeaderName && settings.webhookHeaderContents) {
      headers[settings.webhookHeaderName] = settings.webhookHeaderContents;
    }

    request({
      method: 'POST',
      uri: settings.webhook,
      headers: headers,
      body
    })
    .catch(function (err) {
      logger.error('Could not reach webhook endpoint', settings.webhook, 'for some reason. Verify that the receiving end is up and running.');
      logger.error(err);
    })
  }

}

module.exports = HttpAPI;
<|endoftext|>


<commit_before>function lock() {
	chrome.extension.getBackgroundPage().data = null;

	$("#div-unlocked").hide();
	$("#div-login-error").hide();
	$("#div-login-details").hide();
	$("#div-locked").show();

	$("#input-password").focus();
}

function unlock(pwd) {
	<% if @config[:chrome][:embed] %>
	var text = decrypt(pwd, cfg.pbkdf2.salt, cfg.ciphertext, cfg.pbkdf2.iterations, cfg.aes.iv);
	return jQuery.parseJSON(text);
	<% else %>
	// TODO
	return null;
	<% end %>
}

function sendToBackground(r) {
	chrome.tabs.getSelected(null, function(tab) {
		chrome.tabs.sendMessage(tab.id, r, function(msg) {
			console.log("sent msg");
		});
	});
}

function onUnlock(tab, data) {
	var matched = new Array();
	var unmatched = new Array();

	var address = sitename(tab.url);

	for (var i = 0; i < data.length; i++) {
		var el = data[i];
		if (el.type == "magic") {
			if (el.value != "270389")
				throw("<%= @text[:incorrect_password] %>");

			continue;
		}

		if (el.type != 'login')
			continue;

		if (el.form.action == undefined)
			continue;

		var action = sitename(el.form.action);

		if (address == action) {
			matched.push(el);
		} else {
			if (el.visible == true)
				unmatched.push(el);
		}
	}

	function createLink(id, name) {
//		return '

' + name + '

[Show details]

';
		return '
' + name + '
<button class="btn btn-mini btn-primary" type="button"><%= @text[:button_details] %></button>

';
	}

	$("#table-matched tbody").html('');
	$("#table-unmatched tbody").html('');
	$("#table-matched").show();
	$("#table-unmatched").show();

	for (var i = 0; i < matched.length; i++) {
		var name = matched[i].name + ' (' + matched[i].form.vars.user + ')';
		$('#table-matched tbody').append(createLink('matched_' + i, name));
	}
	if (matched.length == 0)
		$('#table-matched').hide();

	for (var i = 0; i < unmatched.length; i++) {
		var name = unmatched[i].name + ' (' + unmatched[i].form.vars.user + ')';
		$('#table-unmatched tbody').append(createLink('unmatched_' + i, name));
	}
	if (unmatched.length == 0)
		$('#table-unmatched').hide();

	function addListenerForMatched(id, form) {
		var e = document.getElementById(id);
		e.addEventListener("click", function() { sendToBackground(form); window.close(); });
	}

	function addListenerForUnmatched(id, form) {
	}

	for (var i = 0; i < matched.length; i++)
		addListenerForMatched("matched_" + i, matched[i]);

	for (var i = 0; i < unmatched.length; i++)
		addListenerForUnmatched("unmatched_" + i, unmatched[i]);

}

function showData(data) {
	$("#div-login-error").hide();
	$("#div-login-details").hide();

	try {
		chrome.tabs.getSelected(null, function (t){
			onUnlock(t, data);

			$("#div-locked").hide();
			$("#div-login-error").hide();
			$("#div-unlocked").show();

			$("#input-filter").focus();
		});
	} catch(e) {
		$("#div-login-error").show();
		alert(e);
		return;
	}
}

$(document).ready(function() {
	$("#button-lock").click(lock);

	if (chrome.extension.getBackgroundPage().data != null) {
		chrome.extension.getBackgroundPage().lockTimeoutUpdate();
		showData(chrome.extension.getBackgroundPage().data);
	} else {
		lock();

		$("#form-unlock").submit(function(event) {
			event.preventDefault();
			var data = unlock($("#input-password").val());
			$("#input-password").val("");

			chrome.extension.getBackgroundPage().lockTimeoutStart();
			chrome.extension.getBackgroundPage().data = data;

			showData(data);
		});
	}

	$("body").mousemove(function() { chrome.extension.getBackgroundPage().lockTimeoutUpdate(); });
});
<commit_msg>chrome: add details button<commit_after>function lock() {
	chrome.extension.getBackgroundPage().data = null;

	$("#div-unlocked").hide();
	$("#div-login-error").hide();
	$("#div-login-details").hide();
	$("#div-locked").show();

	$("#input-password").focus();
}

function unlock(pwd) {
	<% if @config[:chrome][:embed] %>
	var text = decrypt(pwd, cfg.pbkdf2.salt, cfg.ciphertext, cfg.pbkdf2.iterations, cfg.aes.iv);
	return jQuery.parseJSON(text);
	<% else %>
	// TODO
	return null;
	<% end %>
}

function sendToBackground(r) {
	chrome.tabs.getSelected(null, function(tab) {
		chrome.tabs.sendMessage(tab.id, r, function(msg) {
			console.log("sent msg");
		});
	});
}

function onUnlock(tab, data) {
	var matched = new Array();
	var unmatched = new Array();

	var address = sitename(tab.url);

	for (var i = 0; i < data.length; i++) {
		var el = data[i];
		if (el.type == "magic") {
			if (el.value != "270389")
				throw("<%= @text[:incorrect_password] %>");

			continue;
		}

		if (el.type != 'login')
			continue;

		if (el.form.action == undefined)
			continue;

		var action = sitename(el.form.action);

		if (address == action) {
			matched.push(el);
		} else {
			if (el.visible == true)
				unmatched.push(el);
		}
	}

	function createLink(id, name) {
		return '
' + name + '
<button id="' + id + '_button" class="btn btn-mini btn-primary" type="button" data-toggle="button"><%= @text[:button_details] %></button>

';
	}
	function createDetails(id, user, pass) {
		var t = '

<%= @text[:username] %>:

' + user + '

<%= @text[:password] %>:

' + pass + '

';

		return '
' + t + '
';
	}

	$("#table-matched tbody").html('');
	$("#table-unmatched tbody").html('');
	$("#table-matched").show();
	$("#table-unmatched").show();

	for (var i = 0; i < matched.length; i++) {
		var name = matched[i].name + ' (' + matched[i].form.vars.user + ')';
		$('#table-matched tbody').append(createLink('matched_' + i, name));
		$('#table-matched tbody').append(createDetails('matched_' + i, matched[i].form.vars.user, matched[i].form.vars.pass));
	}
	if (matched.length == 0)
		$('#table-matched').hide();

	for (var i = 0; i < unmatched.length; i++) {
		var name = unmatched[i].name + ' (' + unmatched[i].form.vars.user + ')';
		$('#table-unmatched tbody').append(createLink('unmatched_' + i, name));
		$('#table-unmatched tbody').append(createDetails('unmatched_' + i, unmatched[i].form.vars.user, unmatched[i].form.vars.pass));
	}
	if (unmatched.length == 0)
		$('#table-unmatched').hide();

	function addListenerForMatched(id, form) {
		var e = document.getElementById(id);
		e.addEventListener("click", function() { sendToBackground(form); window.close(); });

		e = document.getElementById(id + '_button');
		e.addEventListener("click", function() { $('#' + id + '_details').toggle(); });
	}

	function addListenerForUnmatched(id, form) {
		var e = document.getElementById(id + '_button');
		e.addEventListener("click", function() { $('#' + id + '_details').toggle(); });

	}

	for (var i = 0; i < matched.length; i++)
		addListenerForMatched("matched_" + i, matched[i]);

	for (var i = 0; i < unmatched.length; i++) {
		addListenerForUnmatched("unmatched_" + i, unmatched[i]);
	}

}

function showData(data) {
	$("#div-login-error").hide();
	$("#div-login-details").hide();

	try {
		chrome.tabs.getSelected(null, function (t){
			onUnlock(t, data);

			$("#div-locked").hide();
			$("#div-login-error").hide();
			$("#div-unlocked").show();

			$("#input-filter").focus();
		});
	} catch(e) {
		$("#div-login-error").show();
		alert(e);
		return;
	}
}

$(document).ready(function() {
	$("#button-lock").click(lock);

	if (chrome.extension.getBackgroundPage().data != null) {
		chrome.extension.getBackgroundPage().lockTimeoutUpdate();
		showData(chrome.extension.getBackgroundPage().data);
	} else {
		lock();

		$("#form-unlock").submit(function(event) {
			event.preventDefault();
			var data = unlock($("#input-password").val());
			$("#input-password").val("");

			chrome.extension.getBackgroundPage().lockTimeoutStart();
			chrome.extension.getBackgroundPage().data = data;

			showData(data);
		});
	}

	$("body").mousemove(function() { chrome.extension.getBackgroundPage().lockTimeoutUpdate(); });
});
<|endoftext|>


<commit_before><commit_msg>quick update to user js to only call update when new values present<commit_after><|endoftext|>


<commit_before>
/**
 * Copyright (c) 2013 Continuuity, Inc.
 */

var express = require('express'),
	http = require('http'),
	https = require('https'),
	io = require('socket.io'),
	Int64 = require('node-int64').Int64;
	fs = require('fs'),
	xml2js = require('xml2js'),
	log4js = require('log4js'),
	utils = require('connect').utils,
	cookie = require('cookie'),
	crypto = require('crypto');

var Api = require('../common/api'),
	Env = require('./env');

/**
 * Setting the environment to Cloud.
 */
process.env.NODE_ENV = 'production';

var LOG_LEVEL = 'INFO';
var config = {};
var sockets = {};

/**
* Configure logger.
*/
log4js.configure({
	appenders: [
		{ type : 'console' }
	]
});
var logger = process.logger = log4js.getLogger('Cloud UI');
logger.setLevel(LOG_LEVEL);

/**
 * Read configuration and start the server.
 */
var configPath = __dirname + '/continuuity-local.xml';
if (fs.existsSync(process.env.CONTINUUITY_HOME + '/conf/continuuity-site.xml')) {
	configPath = process.env.CONTINUUITY_HOME + '/conf/continuuity-site.xml';
}

/**
 * Get user.
 */
function getUser (name, done) {

	var options = {
		hostname: config['accounts-host'],
		port: config['accounts-port'],
		path: '/api/vpc/getUser/' + name,
		method: 'GET'
	};
	https.request(options, function(result) {
		result.setEncoding('utf8');
		var data = '';
		result.on('data', function(chunk) {
			data += chunk;
		});
		result.on('end', function () {
			done(data);
		});
	}).on('error', function(e) {
		console.error(e);
	}).end();
}

/**
 * Read the configuration file.
 */

fs.readFile(configPath, function (error, result) {

	var parser = new xml2js.Parser();
	parser.parseString(result, function (err, result) {

		result = result.property;

		for (var item in result) {
			item = result[item];
			config[item.name] = item.value;
		}

		logger.info('Continuuity HOME', process.env.CONTINUUITY_HOME);
		logger.info(config);

		/**
		 * Configure Express Web server.
		 */
		var app = express();
		app.use(express.bodyParser());

		/**
		 * Express cookie sessions.
		 */
		app.use(express.cookieParser());
		app.use(express.cookieSession({
			key: 'continuuity-sso',
			secret: config['cookie-secret'],
			cookie: {
				path: '/',
				domain: '.continuuity.net',
				maxAge: 24 * 60 * 60 * 1000
			}
		}));

		/**
		 * Session check.
		 */
		function checkSSO (req, res, next) {

			logger.trace(req.session);

			if (req.session.account_id) {

				next();

				/*

				if (req.session.account_id !== config['user']) {
					res.write('Denied (' + config['user'] + ':' + req.session.account_id + ')');
					res.end();
				} else {
					next();
				}

				*/

			} else {

				var ret = config['cluster-name'];
				var host = config['accounts-host'];
				if (config['accounts-port'] !== '443') {
					host += ':' + config['accounts-port'];
				}

				res.redirect('https://' + host +
					'/sso?return=' + encodeURIComponent(ret));

			}

		}
		// Root in production.
		app.get('/', checkSSO);

		// Root in development.
		app.get('/cloud/', checkSSO);

		// Redirected from central with a fresh nonce.
		// Todo: encrypt an SSO token with the user info.
		app.get('/sso/:nonce', function (req, res) {

			var nonce = req.params.nonce;

			logger.trace('< /sso/' + nonce);

			var options = {
				hostname: config['accounts-host'],
				port: config['accounts-port'],
				path: '/getSSOUser/' + nonce,
				method: 'GET'
			};

			https.request(options, function(result) {

				result.setEncoding('utf8');
				var data = '';

				result.on('data', function(chunk) {
					data += chunk;
				});

				result.on('end', function () {

					logger.trace('> /getSSOUser', data);

					if (res.statusCode !== 200) {

						res.write('Error: ' + data);
						res.end();

					} else {

						var account = JSON.parse(data);
						// Create a unique ID for this session.
						var current_date = (new Date()).valueOf().toString();
						var random = Math.random().toString();
						req.session.session_id = crypto.createHash('sha1')
							.update(current_date + random).digest('hex');

						/*
						if (account.account_id !== config['user']) {
							res.write('Denied (' + config['user'] + ':' + account.account_id + ')');
							res.end();
						} else {
						*/
							req.session.account_id = account.account_id;
							req.session.name = account.first_name + ' ' + account.last_name;
							req.session.api_key = account.api_key;
							res.redirect('/');
						/*
						}
						*/

					}

				});
			}).on('error', function(e) {
				console.error(e);
			}).end();

		});
		app.get('/logout', function (req, res) {

			req.session = null;
			res.redirect('https://accounts.continuuity.com/logout');

		});

		/**
		 * Express static directory.
		 */
		if (fs.existsSync(__dirname + '/../client/')) {
			app.use(express.static(__dirname + '/../client/'));
		} else {
			app.use(express.static(__dirname + '/../../client/'));
		}

		/**
		 * SocketIO handlers
		 */
		function socketResponse (socket, request, error, response) {
			socket.emit('exec', error, {
				method: request.method,
				params: typeof response === "string" ? JSON.parse(response) : response,
				id: request.id
			});
		}
		function setSocketHandlers () {

			/**
			 * SocketIO cookie sessions
			 */
			io.set('authorization', function (data, accept) {

				if (data.headers.cookie) {

					var cookies = cookie.parse(data.headers.cookie);
					var signedCookies = utils.parseSignedCookies(cookies, config['cookie-secret']);
					var obj = utils.parseJSONCookies(signedCookies);

					data.account_id = obj['continuuity-sso'].account_id;
					data.name = obj['continuuity-sso'].name;

					if (data.account_id) {

						/**
						 * Used to make Sockets available to HTTP requests.
						 */
						data.session_id = obj['continuuity-sso'].account_id;

						return accept(null, true);

					} else {
						return accept('No session detected.', false);
					}

				} else {

					return accept('No cookie transmitted.', false);

				}
			});

			/**
			 * SocketIO per-socket handlers
			 */
			io.sockets.on('connection', function (socket) {

				/**
				 * For reference by request.session.account_id elsewhere.
				 */
				socket.join(socket.handshake.session_id);

				/**
				 * Emits environment information to the client.
				 */
				socket.emit('env', {
					"location": "remote",
					"version": Env.version,
					"ip": Env.ip,
					"account": {
						"account_id": socket.handshake.account_id,
						"name": socket.handshake.name
					}
				});

				/**
				 * Metadata request. Requires an accountID.
				 */
				socket.on('metadata', function (request) {

					Api.metadata(socket.handshake.account_id,
						request.method, request.params, function (error, response) {
						socketResponse(socket, request, error, response);
					});

				});

				/**
				 * FAR request. Requires an  accountID.
				 */
				socket.on('far', function (request) {

					Api.far(socket.handshake.account_id,
						request.method, request.params, function (error, response) {
						socketResponse(socket, request, error, response);
					});
				});

				/**
				 * Flow Monitor request. Requires an accountID.
				 */
				socket.on('monitor', function (request) {

					Api.monitor(socket.handshake.account_id,
						request.method, request.params, function (error, response) {
						socketResponse(socket, request, error, response);
					});
				});

				/**
				 * Flow Manager request. Requires an accountID.
				 */
				socket.on('manager', function (request) {

					Api.manager(socket.handshake.account_id,
						request.method, request.params, function (error, response) {

						if (response && response.length) {
							var int64values = {
								"lastStarted": 1,
								"lastStopped": 1,
								"startTime": 1,
								"endTime": 1
							};

							// Hax. Int64 is not being jsonized nicely.
							for (var i = 0; i < response.length; i ++) {
								for (var j in response[i]) {
									if (j in int64values) {
										response[i][j] = parseInt(response[i][j].toString(), 10);
									}
								}
							}
						}

						socketResponse(socket, request, error, response);

					});
				});

				/**
				 * Gateway request. Requires an API Key.
				 */
				socket.on('gateway', function (request) {
					Api.gateway(request.session.api_key, request.method,
						request.params, function (error, response) {
						socketResponse(socket, request, error, response);
					});
				}, true);
			});

		}

		/**
		 * HTTP handlers.
		 */
		app.post('/upload/:file', function (req, res) {

			var session_id = req.session.session_id;
			Api.upload(req.session.account_id, req, res, req.params.file, io.sockets.in(session_id));

		});
		app.on('error', function () {
			logger.warn('Port ' + config['node-port'] + ' is in use.');
			process.exit(1);
		});

		getUser(config['cluster-name'], function (user) {
			config['user'] = user;
			Env.getVersion(function (version) {
				Env.getAddress(function (error, address) {

					logger.trace('Version', version);
					logger.trace('IP Address', address);
					logger.trace('User', user);

					logger.trace('Configuring with', config);
					Api.configure(config);

					/**
					 * Create an HTTP server that redirects to HTTPS.
					 */
					http.createServer(function (request, response) {

						var host = request.headers.host.split(':')[0];

						var path = 'https://' + host + ':' +
							config['cloud-ui-ssl-port'] + request.url;

						response.writeHead(302, {'Location': path});
						response.end();

					}).listen(config['cloud-ui-port']);
					logger.trace('HTTP listening on port', config['cloud-ui-port']);

					/**
					 * HTTPS credentials
					 */
					var certs = {
						ca: fs.readFileSync(__dirname + '/certs/STAR_continuuity_net.ca-bundle'),
						key: fs.readFileSync(__dirname + '/certs/continuuity-com-key.key'),
						cert: fs.readFileSync(__dirname + '/certs/STAR_continuuity_net.crt')
					};

					/**
					 * Create the HTTPS server
					 */
					var server = https.createServer(certs, app).listen(config['cloud-ui-ssl-port']);
					logger.trace('HTTPS listening on port', config['cloud-ui-ssl-port']);

					logger.info('Listening on port ');

					/**
					 * Configure Socket IO
					 */
					io = io.listen(server, certs);
					io.configure('production', function(){
						io.set('transports', ['websocket', 'xhr-polling']);
						io.enable('browser client minification');
						io.enable('browser client gzip');
						io.set('log level', 1);
						io.set('resource', '/socket.io');
					});

					/**
					 * Set the handlers after io has been configured.
					 */
					setSocketHandlers();

				});
			});
		});
	});
});<commit_msg>Changing cluster-name to gateway.cluster.name to be compatible with continuuity-site.xml<commit_after>
/**
 * Copyright (c) 2013 Continuuity, Inc.
 */

var express = require('express'),
	http = require('http'),
	https = require('https'),
	io = require('socket.io'),
	Int64 = require('node-int64').Int64;
	fs = require('fs'),
	xml2js = require('xml2js'),
	log4js = require('log4js'),
	utils = require('connect').utils,
	cookie = require('cookie'),
	crypto = require('crypto');

var Api = require('../common/api'),
	Env = require('./env');

/**
 * Setting the environment to Cloud.
 */
process.env.NODE_ENV = 'production';

var LOG_LEVEL = 'INFO';
var config = {};
var sockets = {};

/**
* Configure logger.
*/
log4js.configure({
	appenders: [
		{ type : 'console' }
	]
});
var logger = process.logger = log4js.getLogger('Cloud UI');
logger.setLevel(LOG_LEVEL);

/**
 * Read configuration and start the server.
 */
var configPath = __dirname + '/continuuity-local.xml';
if (fs.existsSync(process.env.CONTINUUITY_HOME + '/conf/continuuity-site.xml')) {
	configPath = process.env.CONTINUUITY_HOME + '/conf/continuuity-site.xml';
}

/**
 * Get user.
 */
function getUser (name, done) {

	var options = {
		hostname: config['accounts-host'],
		port: config['accounts-port'],
		path: '/api/vpc/getUser/' + name,
		method: 'GET'
	};
	https.request(options, function(result) {
		result.setEncoding('utf8');
		var data = '';
		result.on('data', function(chunk) {
			data += chunk;
		});
		result.on('end', function () {
			done(data);
		});
	}).on('error', function(e) {
		console.error(e);
	}).end();
}

/**
 * Read the configuration file.
 */

fs.readFile(configPath, function (error, result) {

	var parser = new xml2js.Parser();
	parser.parseString(result, function (err, result) {

		result = result.property;

		for (var item in result) {
			item = result[item];
			config[item.name] = item.value;
		}

		logger.info('Continuuity HOME', process.env.CONTINUUITY_HOME);
		logger.info(config);

		/**
		 * Configure Express Web server.
		 */
		var app = express();
		app.use(express.bodyParser());

		/**
		 * Express cookie sessions.
		 */
		app.use(express.cookieParser());
		app.use(express.cookieSession({
			key: 'continuuity-sso',
			secret: config['cookie-secret'],
			cookie: {
				path: '/',
				domain: '.continuuity.net',
				maxAge: 24 * 60 * 60 * 1000
			}
		}));

		/**
		 * Session check.
		 */
		function checkSSO (req, res, next) {

			logger.trace(req.session);

			if (req.session.account_id) {

				next();

				/*

				if (req.session.account_id !== config['user']) {
					res.write('Denied (' + config['user'] + ':' + req.session.account_id + ')');
					res.end();
				} else {
					next();
				}

				*/

			} else {

				var ret = config['gateway.cluster.name'];
				var host = config['accounts-host'];
				if (config['accounts-port'] !== '443') {
					host += ':' + config['accounts-port'];
				}

				res.redirect('https://' + host +
					'/sso?return=' + encodeURIComponent(ret));

			}

		}
		// Root in production.
		app.get('/', checkSSO);

		// Root in development.
		app.get('/cloud/', checkSSO);

		// Redirected from central with a fresh nonce.
		// Todo: encrypt an SSO token with the user info.
		app.get('/sso/:nonce', function (req, res) {

			var nonce = req.params.nonce;

			logger.trace('< /sso/' + nonce);

			var options = {
				hostname: config['accounts-host'],
				port: config['accounts-port'],
				path: '/getSSOUser/' + nonce,
				method: 'GET'
			};

			https.request(options, function(result) {

				result.setEncoding('utf8');
				var data = '';

				result.on('data', function(chunk) {
					data += chunk;
				});

				result.on('end', function () {

					logger.trace('> /getSSOUser', data);

					if (res.statusCode !== 200) {

						res.write('Error: ' + data);
						res.end();

					} else {

						var account = JSON.parse(data);
						// Create a unique ID for this session.
						var current_date = (new Date()).valueOf().toString();
						var random = Math.random().toString();
						req.session.session_id = crypto.createHash('sha1')
							.update(current_date + random).digest('hex');

						/*
						if (account.account_id !== config['user']) {
							res.write('Denied (' + config['user'] + ':' + account.account_id + ')');
							res.end();
						} else {
						*/
							req.session.account_id = account.account_id;
							req.session.name = account.first_name + ' ' + account.last_name;
							req.session.api_key = account.api_key;
							res.redirect('/');
						/*
						}
						*/

					}

				});
			}).on('error', function(e) {
				console.error(e);
			}).end();

		});
		app.get('/logout', function (req, res) {

			req.session = null;
			res.redirect('https://accounts.continuuity.com/logout');

		});

		/**
		 * Express static directory.
		 */
		if (fs.existsSync(__dirname + '/../client/')) {
			app.use(express.static(__dirname + '/../client/'));
		} else {
			app.use(express.static(__dirname + '/../../client/'));
		}

		/**
		 * SocketIO handlers
		 */
		function socketResponse (socket, request, error, response) {
			socket.emit('exec', error, {
				method: request.method,
				params: typeof response === "string" ? JSON.parse(response) : response,
				id: request.id
			});
		}
		function setSocketHandlers () {

			/**
			 * SocketIO cookie sessions
			 */
			io.set('authorization', function (data, accept) {

				if (data.headers.cookie) {

					var cookies = cookie.parse(data.headers.cookie);
					var signedCookies = utils.parseSignedCookies(cookies, config['cookie-secret']);
					var obj = utils.parseJSONCookies(signedCookies);

					data.account_id = obj['continuuity-sso'].account_id;
					data.name = obj['continuuity-sso'].name;

					if (data.account_id) {

						/**
						 * Used to make Sockets available to HTTP requests.
						 */
						data.session_id = obj['continuuity-sso'].account_id;

						return accept(null, true);

					} else {
						return accept('No session detected.', false);
					}

				} else {

					return accept('No cookie transmitted.', false);

				}
			});

			/**
			 * SocketIO per-socket handlers
			 */
			io.sockets.on('connection', function (socket) {

				/**
				 * For reference by request.session.account_id elsewhere.
				 */
				socket.join(socket.handshake.session_id);

				/**
				 * Emits environment information to the client.
				 */
				socket.emit('env', {
					"location": "remote",
					"version": Env.version,
					"ip": Env.ip,
					"account": {
						"account_id": socket.handshake.account_id,
						"name": socket.handshake.name
					}
				});

				/**
				 * Metadata request. Requires an accountID.
				 */
				socket.on('metadata', function (request) {

					Api.metadata(socket.handshake.account_id,
						request.method, request.params, function (error, response) {
						socketResponse(socket, request, error, response);
					});

				});

				/**
				 * FAR request. Requires an  accountID.
				 */
				socket.on('far', function (request) {

					Api.far(socket.handshake.account_id,
						request.method, request.params, function (error, response) {
						socketResponse(socket, request, error, response);
					});
				});

				/**
				 * Flow Monitor request. Requires an accountID.
				 */
				socket.on('monitor', function (request) {

					Api.monitor(socket.handshake.account_id,
						request.method, request.params, function (error, response) {
						socketResponse(socket, request, error, response);
					});
				});

				/**
				 * Flow Manager request. Requires an accountID.
				 */
				socket.on('manager', function (request) {

					Api.manager(socket.handshake.account_id,
						request.method, request.params, function (error, response) {

						if (response && response.length) {
							var int64values = {
								"lastStarted": 1,
								"lastStopped": 1,
								"startTime": 1,
								"endTime": 1
							};

							// Hax. Int64 is not being jsonized nicely.
							for (var i = 0; i < response.length; i ++) {
								for (var j in response[i]) {
									if (j in int64values) {
										response[i][j] = parseInt(response[i][j].toString(), 10);
									}
								}
							}
						}

						socketResponse(socket, request, error, response);

					});
				});

				/**
				 * Gateway request. Requires an API Key.
				 */
				socket.on('gateway', function (request) {
					Api.gateway(request.session.api_key, request.method,
						request.params, function (error, response) {
						socketResponse(socket, request, error, response);
					});
				}, true);
			});

		}

		/**
		 * HTTP handlers.
		 */
		app.post('/upload/:file', function (req, res) {

			var session_id = req.session.session_id;
			Api.upload(req.session.account_id, req, res, req.params.file, io.sockets.in(session_id));

		});
		app.on('error', function () {
			logger.warn('Port ' + config['node-port'] + ' is in use.');
			process.exit(1);
		});

		getUser(config['gateway.cluster.name'], function (user) {
			config['user'] = user;
			Env.getVersion(function (version) {
				Env.getAddress(function (error, address) {

					logger.trace('Version', version);
					logger.trace('IP Address', address);
					logger.trace('User', user);

					logger.trace('Configuring with', config);
					Api.configure(config);

					/**
					 * Create an HTTP server that redirects to HTTPS.
					 */
					http.createServer(function (request, response) {

						var host = request.headers.host.split(':')[0];

						var path = 'https://' + host + ':' +
							config['cloud-ui-ssl-port'] + request.url;

						response.writeHead(302, {'Location': path});
						response.end();

					}).listen(config['cloud-ui-port']);
					logger.trace('HTTP listening on port', config['cloud-ui-port']);

					/**
					 * HTTPS credentials
					 */
					var certs = {
						ca: fs.readFileSync(__dirname + '/certs/STAR_continuuity_net.ca-bundle'),
						key: fs.readFileSync(__dirname + '/certs/continuuity-com-key.key'),
						cert: fs.readFileSync(__dirname + '/certs/STAR_continuuity_net.crt')
					};

					/**
					 * Create the HTTPS server
					 */
					var server = https.createServer(certs, app).listen(config['cloud-ui-ssl-port']);
					logger.trace('HTTPS listening on port', config['cloud-ui-ssl-port']);

					logger.info('Listening on port ');

					/**
					 * Configure Socket IO
					 */
					io = io.listen(server, certs);
					io.configure('production', function(){
						io.set('transports', ['websocket', 'xhr-polling']);
						io.enable('browser client minification');
						io.enable('browser client gzip');
						io.set('log level', 1);
						io.set('resource', '/socket.io');
					});

					/**
					 * Set the handlers after io has been configured.
					 */
					setSocketHandlers();

				});
			});
		});
	});
});<|endoftext|>


<commit_before>"use strict";
/**
 * @module opcua.transport
 */
require("requirish")._(module);

// system requires
var EventEmitter = require("events").EventEmitter;
var assert = require("assert");
var _ = require("underscore");
var util = require("util");

// opcua requires
var opcua = require("lib/opcua.js");

var writeTCPMessageHeader = opcua.writeTCPMessageHeader;
var readRawMessageHeader  = opcua.readRawMessageHeader;
var PacketAssembler = opcua.packet_assembler.PacketAssembler;
var hexDump = opcua.utils.hexDump;

var debugLog = opcua.utils.make_debugLog(__filename);
var doDebug = opcua.utils.checkDebugFlag(__filename);

var fakeSocket = {invalid: true};

exports.setFakeTransport = function (socket_like_mock) {
    fakeSocket = socket_like_mock;
};

exports.getFakeTransport = function () {
    return fakeSocket;
};

/**
 * TCP_transport
 *
 * @class TCP_transport
 * @constructor
 * @extends EventEmitter
 */
function TCP_transport() {

    /**
     * timeout
     * @property [timeout=2000]
     * @type {number}
     */
    this.timeout = 3000; // 3 seconds timeout

    this._socket = null;

    /**
     * @property headerSize the size of the header in bytes
     * @type {number}
     * @default  8
     */
    this.headerSize = 8;

    /**
     * @property protocolVersion indicates the version number of the OPCUA protocol used
     * @type {number}
     * @default  0
     */
    this.protocolVersion = 0;

    this.__disconnecting__ = false;

    this.bytesWritten = 0;
    this.bytesRead = 0;

    this._the_callback = null;
}

util.inherits(TCP_transport, EventEmitter);

/**
 * ```createChunk``` is used to construct a pre-allocated chunk to store up to ```length``` bytes of data.
 * The created chunk includes a prepended header for ```chunk_type``` of size ```self.headerSize```.
 *
 * @method createChunk
 * @param msg_type
 * @param chunk_type {String} chunk type. should be 'F' 'C' or 'A'
 * @param length
 * @return {Buffer} a buffer object with the required length representing the chunk.
 *
 * Note:
 *  - only one chunk can be created at a time.
 *  - a created chunk should be committed using the ```write``` method before an other one is created.
 */
TCP_transport.prototype.createChunk = function (msg_type, chunk_type, length) {

    assert(msg_type === "MSG");
    assert(this._pending_buffer === undefined, "createChunk has already been called ( use write first)");

    var total_length = length + this.headerSize;
    var buffer = new Buffer(total_length);
    writeTCPMessageHeader("MSG", chunk_type, total_length, buffer);

    this._pending_buffer = buffer;

    return buffer;
};

TCP_transport.prototype._write_chunk = function (message_chunk) {

    if (this._socket) {
        this.bytesWritten += message_chunk.length;
        this._socket.write(message_chunk);
    }
};

/**
 * write the message_chunk on the socket.
 * @method write
 * @param message_chunk {Buffer}
 *
 * Notes:
 *  - the message chunk must have been created by ```createChunk```.
 *  - once a message chunk has been written, it is possible to call ```createChunk``` again.
 *
 */
TCP_transport.prototype.write = function (message_chunk) {

    assert((this._pending_buffer === undefined) || this._pending_buffer === message_chunk, " write should be used with buffer created by createChunk");

    var header = readRawMessageHeader(message_chunk);
    assert(header.length === message_chunk.length);
    assert(['F', 'C', 'A'].indexOf(header.messageHeader.isFinal) !== -1);

    this._write_chunk(message_chunk);

    this._pending_buffer = undefined;
};

function _fulfill_pending_promises(err, data) {

    var self = this;

    _cleanup_timers.call(self);

    var the_callback = self._the_callback;
    self._the_callback = null;

    if (the_callback) {
        the_callback(err, data);
        return true;
    }
    return false;

}

function _on_message_received(message_chunk) {

    var self = this;
    var has_callback = _fulfill_pending_promises.call(self, null, message_chunk);

    if (!has_callback) {
        /**
         * notify the observers that a message chunk has been received
         * @event message
         * @param message_chunk {Buffer} the message chunk
         */
        self.emit("message", message_chunk);

    }

}

function _cleanup_timers() {

    var self = this;
    if (self._timerId) {
        clearTimeout(self._timerId);
        this._timerId = null;
    }
}

function _start_timeout_timer() {

    var self = this;
    assert(!self._timerId, "timer already started");
    self._timerId = setTimeout(function () {

        _fulfill_pending_promises.call(self,new Error("Timeout in waiting for data on socket"));

    }, self.timeout);

}

function _on_socket_ended_message(err) {

    var self = this;
    if (self.__disconnecting__) {
        return;
    }
    self._on_socket_ended = null;
    self._on_data_received = null;

    debugLog('Transport Connection ended'.red);
    assert(!self.__disconnecting__);
    err = err || new Error("_socket has been disconnected by third party");
    /**
     * notify the observers that the transport layer has been disconnected.
     * @event close
     * @param err the Error object or null
     */
    self.emit("close", err);
    self.__disconnecting__ = true;

    debugLog(" bytesRead    = ", self.bytesRead);
    debugLog(" bytesWritten = ", self.bytesWritten);
    _fulfill_pending_promises.call(self, new Error("Connection aborted - ended by server : " + (err ? err.message : "")));
}

/**
 * @method _install_socket
 * @param socket {Socket}
 * @protected
 */
TCP_transport.prototype._install_socket = function (socket) {

    var self = this;

    assert(socket);

    self._socket = socket;

    // install packet assembler ...
    self.packetAssembler = new PacketAssembler({
        readMessageFunc: readRawMessageHeader,
        minimumSizeInBytes: self.headerSize
    });

    self.packetAssembler.on("message", function (message_chunk) {
        _on_message_received.call(self, message_chunk);
    });

    self._socket.on("data", function (data) {

        self.bytesRead += data.length;
        if (data.length > 0) {
            self.packetAssembler.feed(data);
        }

    }).on('close', function (had_error) {

        //xx console.log("xxxx SOCKET close : had error".red, had_error.toString().cyan);

    }).on('end', function (err) {

        _on_socket_ended_message.call(self);

    }).on('error', function (err) {
        // node The 'close' event will be called directly following this event.
        debugLog("SOCKET Error : " + err);
    });

};

/**
 * @method _install_one_time_message_receiver
 *
 * install a one time message receiver callback
 *
 * Rules:
 * * TCP_transport will not emit the ```message``` event, while the "one time message receiver" is in operation.
 * * the TCP_transport will wait for the next complete message chunk and call the provided callback func
 *   ```callback(null,messageChunk);```
 * * if a messageChunk is not received within ```TCP_transport.timeout``` or if the underlying socket reports an error,
 *    the callback function will be called with an Error.
 *
 * @param callback {Function} the callback function
 * @param callback.err {null|Error}
 * @param callback.messageChunk {Buffer|null}
 * @protected
 */
TCP_transport.prototype._install_one_time_message_receiver = function (callback) {

    var self = this;
    assert(!self._the_callback  , "callback already set");
    assert(_.isFunction(callback));
    self._the_callback = callback;
    _start_timeout_timer.call(self);

};

/**
 * disconnect the TCP layer and close the underlying socket.
 * The ```"close"``` event will be emitted to the observers with err=null.
 *
 * @method disconnect
 * @async
 * @param callback
 */
TCP_transport.prototype.disconnect = function (callback) {

    assert(_.isFunction(callback), "expecting a callback function, but got " + callback);

    var self = this;
    if (self.__disconnecting__) {
        callback();
        return;
    }

    assert(!self.__disconnecting__, "TCP Transport has already been disconnected");
    self.__disconnecting__ = true;

    assert(!self._the_callback,"disconnect shall not be called while the 'one time message receiver' is in operation");
    _cleanup_timers.call(self);

    if (self._socket) {
        self._socket.destroy();
        self._socket.end();
        self._socket = null;
    }

    setImmediate(function () {
        self.emit("close", null);
        callback();
    });

};

exports.TCP_transport = TCP_transport;
<commit_msg>:ambulance: fix large message chunking corruption<commit_after>"use strict";
/**
 * @module opcua.transport
 */
require("requirish")._(module);

// system requires
var EventEmitter = require("events").EventEmitter;
var assert = require("assert");
var _ = require("underscore");
var util = require("util");

// opcua requires
var opcua = require("lib/opcua.js");

var writeTCPMessageHeader = opcua.writeTCPMessageHeader;
var readRawMessageHeader  = opcua.readRawMessageHeader;
var PacketAssembler = opcua.packet_assembler.PacketAssembler;

var debugLog = opcua.utils.make_debugLog(__filename);
var doDebug = opcua.utils.checkDebugFlag(__filename);

var fakeSocket = {invalid: true};

exports.setFakeTransport = function (socket_like_mock) {
    fakeSocket = socket_like_mock;
};

exports.getFakeTransport = function () {
    return fakeSocket;
};

/**
 * TCP_transport
 *
 * @class TCP_transport
 * @constructor
 * @extends EventEmitter
 */
function TCP_transport() {

    /**
     * timeout
     * @property [timeout=3000]
     * @type {number}
     */
    this.timeout = 3000; // 3 seconds timeout

    this._socket = null;

    /**
     * @property headerSize the size of the header in bytes
     * @type {number}
     * @default  8
     */
    this.headerSize = 8;

    /**
     * @property protocolVersion indicates the version number of the OPCUA protocol used
     * @type {number}
     * @default  0
     */
    this.protocolVersion = 0;

    this.__disconnecting__ = false;

    this.bytesWritten = 0;
    this.bytesRead = 0;

    this._the_callback = null;

    /**
     * @property chunkSize
     * @type {number}
     */
    this.chunkSize = 0;
}

util.inherits(TCP_transport, EventEmitter);

/**
 * ```createChunk``` is used to construct a pre-allocated chunk to store up to ```length``` bytes of data.
 * The created chunk includes a prepended header for ```chunk_type``` of size ```self.headerSize```.
 *
 * @method createChunk
 * @param msg_type
 * @param chunk_type {String} chunk type. should be 'F' 'C' or 'A'
 * @param length
 * @return {Buffer} a buffer object with the required length representing the chunk.
 *
 * Note:
 *  - only one chunk can be created at a time.
 *  - a created chunk should be committed using the ```write``` method before an other one is created.
 */
TCP_transport.prototype.createChunk = function (msg_type, chunk_type, length) {

    assert(msg_type === "MSG");
    assert(this._pending_buffer === undefined, "createChunk has already been called ( use write first)");

    var total_length = length + this.headerSize;
    var buffer = new Buffer(total_length);
    writeTCPMessageHeader("MSG", chunk_type, total_length, buffer);

    this._pending_buffer = buffer;

    return buffer;
};

TCP_transport.prototype._write_chunk = function (message_chunk) {

    if (this._socket) {
        this.bytesWritten += message_chunk.length;
        var b = new Buffer(message_chunk);
        this._socket.write(b);
    }
};

/**
 * write the message_chunk on the socket.
 * @method write
 * @param message_chunk {Buffer}
 *
 * Notes:
 *  - the message chunk must have been created by ```createChunk```.
 *  - once a message chunk has been written, it is possible to call ```createChunk``` again.
 *
 */
TCP_transport.prototype.write = function (message_chunk) {

    assert((this._pending_buffer === undefined) || this._pending_buffer === message_chunk, " write should be used with buffer created by createChunk");

    var header = readRawMessageHeader(message_chunk);
    assert(header.length === message_chunk.length);
    assert(['F', 'C', 'A'].indexOf(header.messageHeader.isFinal) !== -1);

    this._write_chunk(message_chunk);

    this._pending_buffer = undefined;
};

function _fulfill_pending_promises(err, data) {

    var self = this;

    _cleanup_timers.call(self);

    var the_callback = self._the_callback;
    self._the_callback = null;

    if (the_callback) {
        the_callback(err, data);
        return true;
    }
    return false;

}

function _on_message_received(message_chunk) {

    var self = this;
    var has_callback = _fulfill_pending_promises.call(self, null, message_chunk);

    if (!has_callback) {
        /**
         * notify the observers that a message chunk has been received
         * @event message
         * @param message_chunk {Buffer} the message chunk
         */
        self.emit("message", message_chunk);

    }

}

function _cleanup_timers() {

    var self = this;
    if (self._timerId) {
        clearTimeout(self._timerId);
        this._timerId = null;
    }
}

function _start_timeout_timer() {

    var self = this;
    assert(!self._timerId, "timer already started");
    self._timerId = setTimeout(function () {

        _fulfill_pending_promises.call(self,new Error("Timeout in waiting for data on socket"));

    }, self.timeout);

}

function _on_socket_ended_message(err) {

    var self = this;
    if (self.__disconnecting__) {
        return;
    }
    self._on_socket_ended = null;
    self._on_data_received = null;

    debugLog('Transport Connection ended'.red);
    assert(!self.__disconnecting__);
    err = err || new Error("_socket has been disconnected by third party");
    /**
     * notify the observers that the transport layer has been disconnected.
     * @event close
     * @param err the Error object or null
     */
    self.emit("close", err);
    self.__disconnecting__ = true;

    debugLog(" bytesRead    = ", self.bytesRead);
    debugLog(" bytesWritten = ", self.bytesWritten);
    _fulfill_pending_promises.call(self, new Error("Connection aborted - ended by server : " + (err ? err.message : "")));
}

/**
 * @method _install_socket
 * @param socket {Socket}
 * @protected
 */
TCP_transport.prototype._install_socket = function (socket) {

    var self = this;

    assert(socket);

    self._socket = socket;

    // install packet assembler ...
    self.packetAssembler = new PacketAssembler({
        readMessageFunc: readRawMessageHeader,
        minimumSizeInBytes: self.headerSize
    });

    self.packetAssembler.on("message", function (message_chunk) {
        _on_message_received.call(self, message_chunk);
    });

    self._socket.on("data", function (data) {

        self.bytesRead += data.length;
        if (data.length > 0) {
            self.packetAssembler.feed(data);
        }

    }).on('close', function (had_error) {

        //xx console.log("xxxx SOCKET close : had error".red, had_error.toString().cyan);

    }).on('end', function (err) {

        _on_socket_ended_message.call(self);

    }).on('error', function (err) {
        // node The 'close' event will be called directly following this event.
        debugLog("SOCKET Error : " + err);
    });

};

/**
 * @method _install_one_time_message_receiver
 *
 * install a one time message receiver callback
 *
 * Rules:
 * * TCP_transport will not emit the ```message``` event, while the "one time message receiver" is in operation.
 * * the TCP_transport will wait for the next complete message chunk and call the provided callback func
 *   ```callback(null,messageChunk);```
 * * if a messageChunk is not received within ```TCP_transport.timeout``` or if the underlying socket reports an error,
 *    the callback function will be called with an Error.
 *
 * @param callback {Function} the callback function
 * @param callback.err {null|Error}
 * @param callback.messageChunk {Buffer|null}
 * @protected
 */
TCP_transport.prototype._install_one_time_message_receiver = function (callback) {

    var self = this;
    assert(!self._the_callback  , "callback already set");
    assert(_.isFunction(callback));
    self._the_callback = callback;
    _start_timeout_timer.call(self);

};

/**
 * disconnect the TCP layer and close the underlying socket.
 * The ```"close"``` event will be emitted to the observers with err=null.
 *
 * @method disconnect
 * @async
 * @param callback
 */
TCP_transport.prototype.disconnect = function (callback) {

    assert(_.isFunction(callback), "expecting a callback function, but got " + callback);

    var self = this;
    if (self.__disconnecting__) {
        callback();
        return;
    }

    assert(!self.__disconnecting__, "TCP Transport has already been disconnected");
    self.__disconnecting__ = true;

    assert(!self._the_callback,"disconnect shall not be called while the 'one time message receiver' is in operation");
    _cleanup_timers.call(self);

    if (self._socket) {
        self._socket.destroy();
        self._socket.end();
        self._socket = null;
    }

    setImmediate(function () {
        self.emit("close", null);
        callback();
    });

};

exports.TCP_transport = TCP_transport;
<|endoftext|>


<commit_before>var Wave = {};
Wave.Game = function(game) {};

Wave.Game.prototype = {
  init: function(){
    this.count = 0;
    this.waveTotalLength = 1600;
    this.numWaves = 10;
    this.waves = null;
    this.boat = null;
    this.sky = null;

    this.firstWave = null;
    this.lastWave = null;

    this.WAVE_LENGTH = 160;

    this.debug = false;
    this.debugKey = null;
    this.showBodies = false;
    this.bodyKey = null;
  },

  preload: function(){
    this.game.load.spritesheet('wave', 'wave.png', this.WAVE_LENGTH, this.WAVE_LENGTH);
    this.game.load.image('boat', 'boat.png');
    this.game.load.image('sky', 'sky.png');
  },

  create: function(){
    var x, y, wave;
    this.game.world.setBounds(0, 0, 3200, 600);
    this.game.physics.startSystem(Phaser.Physics.ARCADE);
    this.game.time.advancedTiming = true;

    this.debugKey = this.game.input.keyboard.addKey(Phaser.Keyboard.D);
    this.debugKey.onUp.add(function(){
      this.debug = !this.debug;
      this.game.debug.reset();
    }, this);
    this.bodyKey = this.game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
    this.bodyKey.onUp.add(function(){
      this.showBodies = !this.showBodies;
      this.game.debug.reset();
    }, this);

    this.sky = this.game.add.image(0,0,'sky');
    this.sky.fixedToCamera = true;
    this.sky.scale.setTo(1.2,1.2);

    this.waves = this.game.add.group();
    this.waves.x = -this.WAVE_LENGTH*2;
    this.waves.y = this.game.world.height - 50;
    this.waves.enableBody = true;
    this.waves.physicsBodyType = Phaser.Physics.ARCADE;

    for (var i = 0; i < this.numWaves; i++)
    {
      x = i*this.WAVE_LENGTH;
      y = 0;
      wave = this.game.add.sprite(x, y, 'wave', this.game.rnd.between(0,1));
      wave.anchor.set(0.5,0.5);
      this.waves.add(wave);
      wave.body.setCircle(this.game.rnd.between(80,140));
      wave.body.offset.set(0, 50);
      wave.body.immovable = true;
    }
    this.setFirstLastWave();

    this.boat = this.game.add.sprite(0, 0, 'boat');
    this.game.physics.arcade.enable(this.boat);
    this.boat.body.gravity.y = 250;
    this.boat.body.setCircle(32);
    this.game.camera.follow(this.boat);
  },

  update: function(){
    this.game.physics.arcade.collide(this.boat, this.waves);
    this.boat.body.velocity.x = 90; // Constantly move boat to the right
    if(this.debug) {
      this.game.debug.text("Camera "+this.game.camera.x, 0, 10);
    }

    this.animateWaves();
    this.fps();
  },

  fps: function(){
    if(this.debug) {
      this.game.debug.text(this.game.time.fps+"fps", 750, 20);
    }
  },

  setFirstLastWave: function() {
    this.firstWave = this.waves.children[0];
    this.lastWave  = this.waves.children[this.numWaves-1];
  },

  shuffleLeftMostWave: function(){
    // Look at left-most this.waves.children only!
    // check if the current wave's right edge (in world coords) is less than the camera's left edge
    if((this.firstWave.world.x + this.firstWave.offsetX) < this.game.camera.x) {
      if(this.debug) {
        this.game.debug.text("First Wave: (" + this.firstWave.x + ","+ this.firstWave.y+")", 10, 100);
      }
      newX = this.lastWave.x + this.WAVE_LENGTH;
      this.firstWave.x = newX;
      // Push firstWave to end of list
      this.waves.remove(this.firstWave, false);
      this.waves.add(this.firstWave);
      this.setFirstLastWave();
    }
  },

  animateWaves: function(){
    this.count += 0.1;

    this.shuffleLeftMostWave();

    this.waves.forEach(function(currentWave){
      var i = this.waves.getChildIndex(currentWave);
      var amp = 5;
      var x = i * 0.9 + this.count;
      var y = Math.sin(x) * amp;
      var newX;
      currentWave.y = y;

      if(this.debug) {
        this.game.debug.text("Wave["+i+"]: (" + currentWave.x + ","+ currentWave.y+")", 10, 11*i+20)
      }
    }, this);
  },

  render: function(){
    if(this.showBodies) {
      this.game.debug.body(this.boat);
      this.waves.forEach(function(wave){
        this.game.debug.body(wave);
      }, this);
    }
  }
};<commit_msg>Always show fps<commit_after>var Wave = {};
Wave.Game = function(game) {};

Wave.Game.prototype = {
  init: function(){
    this.count = 0;
    this.waveTotalLength = 1600;
    this.numWaves = 10;
    this.waves = null;
    this.boat = null;
    this.sky = null;

    this.firstWave = null;
    this.lastWave = null;

    this.WAVE_LENGTH = 160;

    this.debug = false;
    this.debugKey = null;
    this.showBodies = false;
    this.bodyKey = null;
  },

  preload: function(){
    this.game.load.spritesheet('wave', 'wave.png', this.WAVE_LENGTH, this.WAVE_LENGTH);
    this.game.load.image('boat', 'boat.png');
    this.game.load.image('sky', 'sky.png');
  },

  create: function(){
    var x, y, wave;
    this.game.world.setBounds(0, 0, 3200, 600);
    this.game.physics.startSystem(Phaser.Physics.ARCADE);
    this.game.time.advancedTiming = true;

    this.debugKey = this.game.input.keyboard.addKey(Phaser.Keyboard.D);
    this.debugKey.onUp.add(function(){
      this.debug = !this.debug;
      this.game.debug.reset();
    }, this);
    this.bodyKey = this.game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
    this.bodyKey.onUp.add(function(){
      this.showBodies = !this.showBodies;
      this.game.debug.reset();
    }, this);

    this.sky = this.game.add.image(0,0,'sky');
    this.sky.fixedToCamera = true;
    this.sky.scale.setTo(1.2,1.2);

    this.waves = this.game.add.group();
    this.waves.x = -this.WAVE_LENGTH*2;
    this.waves.y = this.game.world.height - 50;
    this.waves.enableBody = true;
    this.waves.physicsBodyType = Phaser.Physics.ARCADE;

    for (var i = 0; i < this.numWaves; i++)
    {
      x = i*this.WAVE_LENGTH;
      y = 0;
      wave = this.game.add.sprite(x, y, 'wave', this.game.rnd.between(0,1));
      wave.anchor.set(0.5,0.5);
      this.waves.add(wave);
      wave.body.setCircle(this.game.rnd.between(80,140));
      wave.body.offset.set(0, 50);
      wave.body.immovable = true;
    }
    this.setFirstLastWave();

    this.boat = this.game.add.sprite(0, 0, 'boat');
    this.game.physics.arcade.enable(this.boat);
    this.boat.body.gravity.y = 250;
    this.boat.body.setCircle(32);
    this.game.camera.follow(this.boat);
  },

  update: function(){
    this.game.physics.arcade.collide(this.boat, this.waves);
    this.boat.body.velocity.x = 90; // Constantly move boat to the right
    if(this.debug) {
      this.game.debug.text("Camera "+this.game.camera.x, 0, 10);
    }

    this.animateWaves();
    this.fps();
  },

  fps: function(){
    this.game.debug.text(this.game.time.fps+"fps", 750, 20);
  },

  setFirstLastWave: function() {
    this.firstWave = this.waves.children[0];
    this.lastWave  = this.waves.children[this.numWaves-1];
  },

  shuffleLeftMostWave: function(){
    // Look at left-most this.waves.children only!
    // check if the current wave's right edge (in world coords) is less than the camera's left edge
    if((this.firstWave.world.x + this.firstWave.offsetX) < this.game.camera.x) {
      if(this.debug) {
        this.game.debug.text("First Wave: (" + this.firstWave.x + ","+ this.firstWave.y+")", 10, 100);
      }
      newX = this.lastWave.x + this.WAVE_LENGTH;
      this.firstWave.x = newX;
      // Push firstWave to end of list
      this.waves.remove(this.firstWave, false);
      this.waves.add(this.firstWave);
      this.setFirstLastWave();
    }
  },

  animateWaves: function(){
    this.count += 0.1;

    this.shuffleLeftMostWave();

    this.waves.forEach(function(currentWave){
      var i = this.waves.getChildIndex(currentWave);
      var amp = 5;
      var x = i * 0.9 + this.count;
      var y = Math.sin(x) * amp;
      var newX;
      currentWave.y = y;

      if(this.debug) {
        this.game.debug.text("Wave["+i+"]: (" + currentWave.x + ","+ currentWave.y+")", 10, 11*i+20)
      }
    }, this);
  },

  render: function(){
    if(this.showBodies) {
      this.game.debug.body(this.boat);
      this.waves.forEach(function(wave){
        this.game.debug.body(wave);
      }, this);
    }
  }
};<|endoftext|>


<commit_before>(function() {
    'use strict';

    angular.module('chaise.errors', ['chaise.alerts', 'chaise.authen', 'chaise.modal', 'chaise.utils'])

    .constant('errorNames', {
        unauthorized: "Unauthorized",
        forbidden: "Forbidden",
        notFound: "Not Found"
    })

    .factory('Errors', [function() {
        function MalformedUriError(message) {
            this.message = message;
        }

        MalformedUriError.prototype = Object.create(Error.prototype);
        MalformedUriError.prototype.constructor = MalformedUriError;

        function InvalidInputError(message) {
            this.message = message;
        }

        InvalidInputError.prototype = Object.create(Error.prototype);
        InvalidInputError.prototype.constructor = MalformedUriError;

        return {
            InvalidInputError: InvalidInputError,
            MalformedUriError: MalformedUriError
        };
    }])

    // Factory for each error type
    .factory('ErrorService', ['AlertsService', 'errorNames', 'Session', 'messageMap', '$log', '$rootScope', '$uibModal', '$window', function ErrorService(AlertsService, errorNames, Session, messageMap, $log, $rootScope, $uibModal, $window) {

        function errorPopup(message, errorCode, pageName, redirectLink, subMessage, stackTrace) {
            var providedLink = true;
            // if it's not defined, redirect to the dataBrowser config setting (if set) or the landing page
            if (!redirectLink) {
                providedLink = false;
                var redirectLink = (chaiseConfig.dataBrowser ? chaiseConfig.dataBrowser : $window.location.origin);
            }

            var isFirefox = typeof InstallTrigger !== 'undefined';
            var isChrome = !!window.chrome && !!window.chrome.webstore;
            // If browser is chrome then
            if (subMessage && stackTrace) {
                if (isChrome) {
                    subMessage = stackTrace;
                } else {
                    subMessage = subMessage + "\n   " + stackTrace.split("\n").join("\n   ");
                }
            }
            var params = {
                message: message,
                errorCode: errorCode,
                pageName: pageName,
                subMessage: subMessage
            };

            var modalInstance = $uibModal.open({
                templateUrl: '../common/templates/errorDialog.modal.html',
                controller: 'ErrorDialogController',
                controllerAs: 'ctrl',
                backdrop: 'static',
                keyboard: false,
                resolve: {
                    params: params
                }
            });

            modalInstance.result.then(function () {
                if (errorCode == errorNames.unauthorized && !providedLink) {
                    Session.login($window.location.href);
                } else {
                    $window.location.replace(redirectLink);
                }
            });
        }

        function noRecordError(filters) {
            var noDataMessage = messageMap.noDataMessage;
            for (var k = 0; k < filters.length; k++) {
                noDataMessage += filters[k].column + filters[k].operator + filters[k].value;
                if (k != filters.length-1) {
                    noDataMessage += " or ";
                }
            }
            var error = new Error(noDataMessage);
            error.code = errorNames.notFound;

            return error;
        }

        function MalformedUriError(message) {
            this.message = message;
        }

        MalformedUriError.prototype = Object.create(Error.prototype);
        MalformedUriError.prototype.constructor = MalformedUriError;

        function InvalidInputError(message) {
            this.message = message;
        }

        InvalidInputError.prototype = Object.create(Error.prototype);
        InvalidInputError.prototype.constructor = MalformedUriError;

        // TODO: implement hierarchies of exceptions in ermrestJS and use that hierarchy to conditionally check for certain exceptions
        function catchAll(exception) {
            $log.info(exception);
            if (exception instanceof ERMrest.UnauthorizedError || exception.code == errorNames.unauthorized) {
                Session.login($window.location.href);
            } else if (exception instanceof ERMrest.PreconditionFailedError) {
                AlertsService.addAlert(messageMap.generalPreconditionFailed, 'warning');
            } else {
                AlertsService.addAlert(exception.message, 'error');
            }
        }

        var exceptionFlag = false;

        // TODO: implement hierarchies of exceptions in ermrestJS and use that hierarchy to conditionally check for certain exceptions
        function handleException(exception) {
            $log.info(exception);

            if (exceptionFlag) return;

            if (exception instanceof ERMrest.UnauthorizedError || exception.code == errorNames.unauthorized) {
                Session.login($window.location.href);
            } else if (exception instanceof ERMrest.PreconditionFailedError) {
                // A more useful general message for 412 Precondition Failed
                AlertsService.addAlert({type: 'warning', message: messageMap.generalPreconditionFailed});
            } else {
                errorPopup("An unexpected error has occurred. Please report this problem to your system administrators.", "Terminal Error", "Home Page", $window.location.origin,  exception.message , exception.stack);
            }

            exceptionFlag = true;
        }

        return {
            errorPopup: errorPopup,
            catchAll: catchAll,
            noRecordError: noRecordError,
            handleException: handleException
        };
    }])

    .config(function($provide) {
        $provide.decorator("$exceptionHandler", ['$log', '$injector' , function($log, $injector) {
            return function(exception, cause) {
                var ErrorService = $injector.get("ErrorService");
                ErrorService.handleException(exception);
            };
        }]);
    });

})();

window.onerror = function() {

    if (window.location.pathname.indexOf('chaise/search') != -1) {
        console.log(arguments[4]);
        return;
    }

    var error = arguments[4];
    error.stack = [
        arguments[1],
        arguments[2],
        arguments[3]
    ].join(':');

    var redirectLink = (chaiseConfig.dataBrowser ? chaiseConfig.dataBrowser : window.location.origin);

    if (!document || !document.body) return;

    document.body.innerHTML = '
'
        + '
'
            + '
'
                + '
'
                    + '
Error: Terminal Error
'
                + '
'
                + '
'
                    + 'An unexpected error has occurred. Please report this problem to your system administrators.'
                    + '

'
                    + 'Click OK to return to the Home Page.'
                    + '
'
                    + '
'
                        + '
' + error.message + '
' + error.stack + '
'
                    + ''
                + '
'
                + '
'
                    + '<button class="btn btn-danger" type="button" onclick="window.location.replace(\'' + redirectLink + '\');">OK</button>'
                + '
'
            + '
'
        + '
'
    + '
'
    + '

';

};
<commit_msg>Added check for whether ERMrest is defined for handleException for search app<commit_after>(function() {
    'use strict';

    angular.module('chaise.errors', ['chaise.alerts', 'chaise.authen', 'chaise.modal', 'chaise.utils'])

    .constant('errorNames', {
        unauthorized: "Unauthorized",
        forbidden: "Forbidden",
        notFound: "Not Found"
    })

    .factory('Errors', [function() {
        function MalformedUriError(message) {
            this.message = message;
        }

        MalformedUriError.prototype = Object.create(Error.prototype);
        MalformedUriError.prototype.constructor = MalformedUriError;

        function InvalidInputError(message) {
            this.message = message;
        }

        InvalidInputError.prototype = Object.create(Error.prototype);
        InvalidInputError.prototype.constructor = MalformedUriError;

        return {
            InvalidInputError: InvalidInputError,
            MalformedUriError: MalformedUriError
        };
    }])

    // Factory for each error type
    .factory('ErrorService', ['AlertsService', 'errorNames', 'Session', 'messageMap', '$log', '$rootScope', '$uibModal', '$window', function ErrorService(AlertsService, errorNames, Session, messageMap, $log, $rootScope, $uibModal, $window) {

        function errorPopup(message, errorCode, pageName, redirectLink, subMessage, stackTrace) {
            var providedLink = true;
            // if it's not defined, redirect to the dataBrowser config setting (if set) or the landing page
            if (!redirectLink) {
                providedLink = false;
                var redirectLink = (chaiseConfig.dataBrowser ? chaiseConfig.dataBrowser : $window.location.origin);
            }

            var isFirefox = typeof InstallTrigger !== 'undefined';
            var isChrome = !!window.chrome && !!window.chrome.webstore;
            // If browser is chrome then
            if (subMessage && stackTrace) {
                if (isChrome) {
                    subMessage = stackTrace;
                } else {
                    subMessage = subMessage + "\n   " + stackTrace.split("\n").join("\n   ");
                }
            }
            var params = {
                message: message,
                errorCode: errorCode,
                pageName: pageName,
                subMessage: subMessage
            };

            var modalInstance = $uibModal.open({
                templateUrl: '../common/templates/errorDialog.modal.html',
                controller: 'ErrorDialogController',
                controllerAs: 'ctrl',
                backdrop: 'static',
                keyboard: false,
                resolve: {
                    params: params
                }
            });

            modalInstance.result.then(function () {
                if (errorCode == errorNames.unauthorized && !providedLink) {
                    Session.login($window.location.href);
                } else {
                    $window.location.replace(redirectLink);
                }
            });
        }

        function noRecordError(filters) {
            var noDataMessage = messageMap.noDataMessage;
            for (var k = 0; k < filters.length; k++) {
                noDataMessage += filters[k].column + filters[k].operator + filters[k].value;
                if (k != filters.length-1) {
                    noDataMessage += " or ";
                }
            }
            var error = new Error(noDataMessage);
            error.code = errorNames.notFound;

            return error;
        }

        function MalformedUriError(message) {
            this.message = message;
        }

        MalformedUriError.prototype = Object.create(Error.prototype);
        MalformedUriError.prototype.constructor = MalformedUriError;

        function InvalidInputError(message) {
            this.message = message;
        }

        InvalidInputError.prototype = Object.create(Error.prototype);
        InvalidInputError.prototype.constructor = MalformedUriError;

        // TODO: implement hierarchies of exceptions in ermrestJS and use that hierarchy to conditionally check for certain exceptions
        function catchAll(exception) {
            $log.info(exception);
            if (exception instanceof ERMrest.UnauthorizedError || exception.code == errorNames.unauthorized) {
                Session.login($window.location.href);
            } else if (exception instanceof ERMrest.PreconditionFailedError) {
                AlertsService.addAlert(messageMap.generalPreconditionFailed, 'warning');
            } else {
                AlertsService.addAlert(exception.message, 'error');
            }
        }

        var exceptionFlag = false;

        // TODO: implement hierarchies of exceptions in ermrestJS and use that hierarchy to conditionally check for certain exceptions
        function handleException(exception) {
            $log.info(exception);

            if (exceptionFlag) return;

            if (ERMrest && exception instanceof ERMrest.UnauthorizedError || exception.code == errorNames.unauthorized) {
                Session.login($window.location.href);
            } else if (ERMrest && exception instanceof ERMrest.PreconditionFailedError) {
                // A more useful general message for 412 Precondition Failed
                AlertsService.addAlert({type: 'warning', message: messageMap.generalPreconditionFailed});
            } else {
                errorPopup("An unexpected error has occurred. Please report this problem to your system administrators.", "Terminal Error", "Home Page", $window.location.origin,  exception.message , exception.stack);
            }

            exceptionFlag = true;
        }

        return {
            errorPopup: errorPopup,
            catchAll: catchAll,
            noRecordError: noRecordError,
            handleException: handleException
        };
    }])

    .config(function($provide) {
        $provide.decorator("$exceptionHandler", ['$log', '$injector' , function($log, $injector) {
            return function(exception, cause) {
                var ErrorService = $injector.get("ErrorService");
                ErrorService.handleException(exception);
            };
        }]);
    });

})();

window.onerror = function() {

    if (window.location.pathname.indexOf('chaise/search') != -1) {
        console.log(arguments[4]);
        return;
    }

    var error = arguments[4];
    error.stack = [
        arguments[1],
        arguments[2],
        arguments[3]
    ].join(':');

    var redirectLink = (chaiseConfig.dataBrowser ? chaiseConfig.dataBrowser : window.location.origin);

    if (!document || !document.body) return;

    document.body.innerHTML = '
'
        + '
'
            + '
'
                + '
'
                    + '
Error: Terminal Error
'
                + '
'
                + '
'
                    + 'An unexpected error has occurred. Please report this problem to your system administrators.'
                    + '

'
                    + 'Click OK to return to the Home Page.'
                    + '
'
                    + '
'
                        + '
' + error.message + '
' + error.stack + '
'
                    + ''
                + '
'
                + '
'
                    + '<button class="btn btn-danger" type="button" onclick="window.location.replace(\'' + redirectLink + '\');">OK</button>'
                + '
'
            + '
'
        + '
'
    + '
'
    + '

';

};
<|endoftext|>