<commit_before>self.importScripts( '../../../build/three.js' );

self.onmessage = function ( message ) {

	var data = message.data;
	init( data.drawingSurface, data.width, data.height, data.pixelRatio );

};

var camera, scene, renderer, mesh, clock;

function createBoxMesh( size, material ) {
	var material = new THREE.MeshBasicMaterial(material);
	var geometry = new THREE.BoxBufferGeometry(size, size, size);
	return new THREE.Mesh(geometry, material);
}

function init( offscreen, width, height, pixelRatio ) {

	camera = new THREE.PerspectiveCamera( 70, width / height, 1, 1000 );
	camera.position.z = 400;

	scene = new THREE.Scene();

	clock = new THREE.Clock();

	// we don't use ImageLoader since it has a DOM dependency (HTML5 image element)

	var loader = new THREE.ImageBitmapLoader();

	loader.load( '../../textures/crate.gif', function ( imageBitmap ) {

		var texture = new THREE.CanvasTexture( imageBitmap );
		mesh = createBoxMesh(200, { map: texture });
		scene.add( mesh );

		animate();

	}, null, function(e) {
		// On error use color instead of texture.
		mesh = createBoxMesh(200, { color: 0x00ff00 });
		scene.add( mesh );

		animate();

	} );

	renderer = new THREE.WebGLRenderer({ antialias: true, canvas: offscreen });
	renderer.setPixelRatio(pixelRatio);
	renderer.setSize(width, height, false);
}

function animate() {

	var delta = clock.getDelta();

	mesh.rotation.x += delta * 0.2;
	mesh.rotation.y += delta * 0.5;

	renderer.render( scene, camera );
	if (self.requestAnimationFrame) {
		self.requestAnimationFrame(animate);
	} else if (renderer.context.commit) {
		renderer.context.commit().then(animate);
	}

}
<commit_msg>Update formatting to match code style<commit_after>self.importScripts( '../../../build/three.js' );

self.onmessage = function ( message ) {

	var data = message.data;
	init( data.drawingSurface, data.width, data.height, data.pixelRatio );

};

var camera, scene, renderer, mesh, clock;

function createBoxMesh( size, material ) {

	var material = new THREE.MeshBasicMaterial( material );
	var geometry = new THREE.BoxBufferGeometry( size, size, size );
	return new THREE.Mesh( geometry, material );

}

function init( offscreen, width, height, pixelRatio ) {

	camera = new THREE.PerspectiveCamera( 70, width / height, 1, 1000 );
	camera.position.z = 400;

	scene = new THREE.Scene();

	clock = new THREE.Clock();

	// we don't use ImageLoader since it has a DOM dependency (HTML5 image element)

	var loader = new THREE.ImageBitmapLoader();

	loader.load( '../../textures/crate.gif', function ( imageBitmap ) {

		var texture = new THREE.CanvasTexture( imageBitmap );
		mesh = createBoxMesh( 200, { map: texture } );
		scene.add( mesh );

		animate();

	}, null, function () {

		// On error use color instead of texture.

		mesh = createBoxMesh( 200, { color: 0x00ff00 } );
		scene.add( mesh );

		animate();

	} );

	renderer = new THREE.WebGLRenderer( { antialias: true, canvas: offscreen } );
	renderer.setPixelRatio( pixelRatio );
	renderer.setSize( width, height, false );

}

function animate() {

	var delta = clock.getDelta();

	mesh.rotation.x += delta * 0.2;
	mesh.rotation.y += delta * 0.5;

	renderer.render( scene, camera );

	if ( self.requestAnimationFrame ) {
		self.requestAnimationFrame( animate );
	} else if ( renderer.context.commit ) {
		renderer.context.commit().then( animate );
	}

}
<|endoftext|>


<commit_before>
Helpers = {}

Helpers.interval = 1000*60*60;
Helpers.getVariations = getVariations;
Helpers.getEmptyVariations = getEmptyVariations;
Helpers.getInterval = getInterval;
Helpers.getDay = getDay;
Helpers.validateTweet = validateTweet;
Helpers.getTweetLength = getTweetLength;

function getVariations (_variations, _settings) {
  var settings = _settings || Defaults.Settings();
  var variations = _variations || [];
  var currentTime = new Date().getTime();
  var interval = getInterval(settings);
  for(var i=settings.repeatCount; i-->0;) {
    if (!variations[i])
      variations[i] = Defaults.Variations();
    variations[i].time = currentTime + interval * i;
  };
  return variations.slice(0, settings.repeatCount)
}

function getEmptyVariations (_variations, _settings) {
  var settings = _settings || Defaults.Settings();
  var variations = _variations || [];
  var currentTime = new Date().getTime();
  var interval = getInterval(settings);
  for(var i=settings.repeatCount; i-->0;) {
    if (!variations[i])
      variations[i] = Defaults.Variations();
    variations[i].time = currentTime + interval * i;
    variations[i].text = null;
  };
  return variations.slice(0, settings.repeatCount)
}

function getInterval (settings) {
  var option = settings.intervalUnitOptions[0];
  for(var i=settings.intervalUnitOptions.length; i-->0;){
    if (settings.intervalUnitOptions[i].title === settings.intervalUnit) {
      return settings.intervalUnitOptions[i].millis*settings.intervalValue;
    };
  };
  return settings.intervalUnitOptions[0].millis*settings.intervalValue;
}

function getDay (ts) {
  var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
  var date = new Date(ts);
  var day = date.getDay();
  var time = date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
  return days[day] + ' ' + time;
}

function validateTweet (tweet) {
  console.log('validating', tweet);
  if (tweet.defaultText === '')
    return 'Please enter tweet text';
  if (getTweetLength(tweet.defaultText) > 140)
    return 'Tweet is longer than 140 characters';
  for(var i=tweet.variations.length; i-->0;) {
    if (getTweetLength(tweet.variations[i]) > 140)
      return 'Tweet variation number ' + i + ' is longer than 140 characters';
  }
}

function getTweetLength (text) {
  var shortUrl = '12345678901234567890123';
  var clean = text.replace(/(https?:\/\/[^/]+)\/?([^/]*)([^ ]*)/gi, shortUrl);
  return clean.length;
}<commit_msg>Update regEx to detect URL<commit_after>
Helpers = {}

Helpers.interval = 1000*60*60;
Helpers.getVariations = getVariations;
Helpers.getEmptyVariations = getEmptyVariations;
Helpers.getInterval = getInterval;
Helpers.getDay = getDay;
Helpers.validateTweet = validateTweet;
Helpers.getTweetLength = getTweetLength;

function getVariations (_variations, _settings) {
  var settings = _settings || Defaults.Settings();
  var variations = _variations || [];
  var currentTime = new Date().getTime();
  var interval = getInterval(settings);
  for(var i=settings.repeatCount; i-->0;) {
    if (!variations[i])
      variations[i] = Defaults.Variations();
    variations[i].time = currentTime + interval * i;
  };
  return variations.slice(0, settings.repeatCount)
}

function getEmptyVariations (_variations, _settings) {
  var settings = _settings || Defaults.Settings();
  var variations = _variations || [];
  var currentTime = new Date().getTime();
  var interval = getInterval(settings);
  for(var i=settings.repeatCount; i-->0;) {
    if (!variations[i])
      variations[i] = Defaults.Variations();
    variations[i].time = currentTime + interval * i;
    variations[i].text = null;
  };
  return variations.slice(0, settings.repeatCount)
}

function getInterval (settings) {
  var option = settings.intervalUnitOptions[0];
  for(var i=settings.intervalUnitOptions.length; i-->0;){
    if (settings.intervalUnitOptions[i].title === settings.intervalUnit) {
      return settings.intervalUnitOptions[i].millis*settings.intervalValue;
    };
  };
  return settings.intervalUnitOptions[0].millis*settings.intervalValue;
}

function getDay (ts) {
  var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
  var date = new Date(ts);
  var day = date.getDay();
  var time = date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
  return days[day] + ' ' + time;
}

function validateTweet (tweet) {
  console.log('validating', tweet);
  if (tweet.defaultText === '')
    return 'Please enter tweet text';
  if (getTweetLength(tweet.defaultText) > 140)
    return 'Tweet is longer than 140 characters';
  for(var i=tweet.variations.length; i-->0;) {
    if (getTweetLength(tweet.variations[i]) > 140)
      return 'Tweet variation number ' + i + ' is longer than 140 characters';
  }
}

function getTweetLength (text) {
  var shortUrl = '_______________________';
  var regEx = /https?[^ ]+/gi;
  var clean = text.replace(regEx, shortUrl);
  return clean.length;
}<|endoftext|>


<commit_before>'use strict';

var bpack = require('browser-pack');
var fs = require('fs');
var path = require('path');
var xtend = require('xtend');

var preludePath = path.join(__dirname, 'prelude.js');
var prelude = fs.readFileSync(preludePath, 'utf8');

// This plugin replaces the prelude and adds a transform
var plugin = exports.plugin = function (bfy, opts) {
  var replacePrelude = function() {
    var packOpts = {
      raw: true, // Added in regular Browserifiy as well
      preludePath: preludePath,
      prelude: prelude
    };

    var packer = bpack(xtend(bfy._options, packOpts));
    // Replace the 'pack' step with the new browser-pack instance
    bfy.pipeline.splice('pack', 1, packer);
  }
  bfy.transform(require('./transform'));
  bfy.on('reset', replacePrelude);
  replacePrelude();
};

// Maintain support for the old interface
exports.browserify = function (files) {
  console.error('You are setting up proxyquireify via the old API which will be deprecated in future versions.');
  console.error('It is recommended to use it as a browserify-plugin instead - see the example in the README.');
  return require('browserify')(files).plugin(plugin);
};
<commit_msg>adapting code style<commit_after>'use strict';

var bpack = require('browser-pack');
var fs = require('fs');
var path = require('path');
var xtend = require('xtend');

var preludePath = path.join(__dirname, 'prelude.js');
var prelude = fs.readFileSync(preludePath, 'utf8');

// This plugin replaces the prelude and adds a transform
var plugin = exports.plugin = function (bfy, opts) {
  function replacePrelude() {
    var packOpts = {
      raw         : true, // Added in regular Browserifiy as well
      preludePath : preludePath,
      prelude     : prelude
    };

    var packer = bpack(xtend(bfy._options, packOpts));
    // Replace the 'pack' step with the new browser-pack instance
    bfy.pipeline.splice('pack', 1, packer);
  }

  bfy.transform(require('./transform'));
  bfy.on('reset', replacePrelude);

  replacePrelude();
};

// Maintain support for the old interface
exports.browserify = function (files) {
  console.error('You are setting up proxyquireify via the old API which will be deprecated in future versions.');
  console.error('It is recommended to use it as a browserify-plugin instead - see the example in the README.');
  return require('browserify')(files).plugin(plugin);
};
<|endoftext|>


<commit_before>/*
Script: Builder.js
	Automatically includes MooTools files right from the project folder.

License:
	MIT-style license.

Note:
	If you use this script in your own page, you must be out of your mind.
*/

var Builder = {

	root: '../',

	cssImport: '',

	paths: {
		source: 'Source',
		docs: 'Source'
	},

	included: {
		source: {},
		docs: {}
	},

	scripts: {
		source: {
			'Core' : [
				'Mif'
			],
			'Tree' : [
				'Mif.Tree.mootools-patch',
				'Mif.Tree',
				'Mif.Tree.Node',
				'Mif.Tree.Hover',
				'Mif.Tree.Selection',
				'Mif.Tree.Load',
				'Mif.Tree.Draw',
				'Mif.Tree.KeyNav',
				'Mif.Tree.Sort',
				'Mif.Tree.Transform',
				'Mif.Tree.Drag',
				'Mif.Tree.Drag.Element',
				'Mif.Tree.Checkbox',
				'Mif.Tree.Rename',
				'Mif.Tree.CookieStorage'
			],
			'Menu' : [
				'Mif.Menu.Utils',
				'Mif.Menu',
				'Mif.Menu.List',
				'Mif.Menu.Item',
				'Mif.Menu.Container',
				'Mif.Menu.CanvasContainer',
				'Mif.Menu.KeyNav'
			]
		},

		docs: {
			'Core' : [
				'Mif'
			],
			'Tree' : [
				'Mif.Tree',
				'Mif.Tree.Node',
				'Mif.Tree.Hover',
				'Mif.Tree.Selection',
				'Mif.Tree.Load',
				'Mif.Tree.Draw',
				'Mif.Tree.KeyNav',
				'Mif.Tree.Sort',
				'Mif.Tree.Transform',
				'Mif.Tree.Drag',
				'Mif.Tree.Checkbox',
				'Mif.Tree.Rename',
				'Mif.Tree.CookieStorage'
			]
		}
	},

	initialize: function(root){
		if (root) this.root = root;
		this.includeType('source');
		return this;
	},

	getFolder: function(type, file){
		var scripts = this.scripts[type];
		for (var folder in scripts){
			for (var i = 0; i < scripts[folder].length; i++){
				var script = scripts[folder][i];
				if (script == file) return folder;
			}
		}
		return false;
	},

	getRequest: function(){
		var pairs = window.location.search.substring(1).split('&');
		var obj = {};
		for (var i = 0, l = pairs.length; i < l; i++){
			var pair = pairs[i].split('=');
			obj[pair[0]] = pair[1];
		}
		return obj;
	},

	includeFile: function(type, folder, file){
		folder = folder || this.getFolder(type, file);
		if (!folder) return false;
		this.included[type][folder] = this.included[type][folder] || [];
		var files = this.included[type][folder];
		for (var i = 0; i < files.length; i++){
			if (files[i] == file) return false;
		}
		this.included[type][folder].push(file);
		this.cssImport+='\t@import "' + this.root + this.paths[type] + '/assets/' + folder + '/' + file + '.css";\n';
		return document.writeln('\t<script type="text/javascript" src="' + this.root + this.paths[type] + '/' + folder + '/' + file + '.js"></script>');
	},

	includeFolder: function(type, folder){
		var scripts = this.scripts[type][folder];
		for (var i = 0, l = scripts.length; i < l; i++) this.includeFile(type, folder, scripts[i]);
	},

	includeType: function(type){
		for (var folder in this.scripts[type]) this.includeFolder(type, folder);
		this.includeCSS();
	},

	includeCSS: function(){
		return document.writeln('<style type="text/css" media="all">\n'+this.cssImport+'</style>');
	},

	includeRequest: function(type){
		var req = this.getRequest();
		if (!req.files && !req.folders) return false;
		var files = (req.files) ? req.files.split('+') : [];
		var folders = (req.folders) ? req.folders.split('+') : [];
		for (var j = 0; j < files.length; j++) this.includeFile(type, null, files[j]);
		for (var i = 0; i < folders.length; i++) this.includeFolder(type, folders[i]);
		return true;
	}

};<commit_msg>fix builder scripts array<commit_after>/*
Script: Builder.js
	Automatically includes MooTools files right from the project folder.

License:
	MIT-style license.

Note:
	If you use this script in your own page, you must be out of your mind.
*/

var Builder = {

	root: '../',

	cssImport: '',

	paths: {
		source: 'Source',
		docs: 'Source'
	},

	included: {
		source: {},
		docs: {}
	},

	scripts: {
		source: {
			'Core' : [
				'Mif'
			],
			'Tree' : [
				'Mif.Tree.mootools-patch',
				'Mif.Tree',
				'Mif.Tree.Node',
				'Mif.Tree.Hover',
				'Mif.Tree.Selection',
				'Mif.Tree.Load',
				'Mif.Tree.Draw',
				'Mif.Tree.KeyNav',
				'Mif.Tree.Sort',
				'Mif.Tree.Transform',
				'Mif.Tree.Drag',
				'Mif.Tree.Drag.Element',
				'Mif.Tree.Checkbox',
				'Mif.Tree.Rename',
				'Mif.Tree.CookieStorage'
			],
			'Menu' : [
				'Mif.Menu.Utils',
				'Mif.Menu',
				'Mif.Menu.List',
				'Mif.Menu.Item',
				'Mif.Menu.KeyNav'
			]
		},

		docs: {
			'Core' : [
				'Mif'
			],
			'Tree' : [
				'Mif.Tree',
				'Mif.Tree.Node',
				'Mif.Tree.Hover',
				'Mif.Tree.Selection',
				'Mif.Tree.Load',
				'Mif.Tree.Draw',
				'Mif.Tree.KeyNav',
				'Mif.Tree.Sort',
				'Mif.Tree.Transform',
				'Mif.Tree.Drag',
				'Mif.Tree.Checkbox',
				'Mif.Tree.Rename',
				'Mif.Tree.CookieStorage'
			]
		}
	},

	initialize: function(root){
		if (root) this.root = root;
		this.includeType('source');
		return this;
	},

	getFolder: function(type, file){
		var scripts = this.scripts[type];
		for (var folder in scripts){
			for (var i = 0; i < scripts[folder].length; i++){
				var script = scripts[folder][i];
				if (script == file) return folder;
			}
		}
		return false;
	},

	getRequest: function(){
		var pairs = window.location.search.substring(1).split('&');
		var obj = {};
		for (var i = 0, l = pairs.length; i < l; i++){
			var pair = pairs[i].split('=');
			obj[pair[0]] = pair[1];
		}
		return obj;
	},

	includeFile: function(type, folder, file){
		folder = folder || this.getFolder(type, file);
		if (!folder) return false;
		this.included[type][folder] = this.included[type][folder] || [];
		var files = this.included[type][folder];
		for (var i = 0; i < files.length; i++){
			if (files[i] == file) return false;
		}
		this.included[type][folder].push(file);
		this.cssImport+='\t@import "' + this.root + this.paths[type] + '/assets/' + folder + '/' + file + '.css";\n';
		return document.writeln('\t<script type="text/javascript" src="' + this.root + this.paths[type] + '/' + folder + '/' + file + '.js"></script>');
	},

	includeFolder: function(type, folder){
		var scripts = this.scripts[type][folder];
		for (var i = 0, l = scripts.length; i < l; i++) this.includeFile(type, folder, scripts[i]);
	},

	includeType: function(type){
		for (var folder in this.scripts[type]) this.includeFolder(type, folder);
		this.includeCSS();
	},

	includeCSS: function(){
		return document.writeln('<style type="text/css" media="all">\n'+this.cssImport+'</style>');
	},

	includeRequest: function(type){
		var req = this.getRequest();
		if (!req.files && !req.folders) return false;
		var files = (req.files) ? req.files.split('+') : [];
		var folders = (req.folders) ? req.folders.split('+') : [];
		for (var j = 0; j < files.length; j++) this.includeFile(type, null, files[j]);
		for (var i = 0; i < folders.length; i++) this.includeFolder(type, folders[i]);
		return true;
	}

};<|endoftext|>


<commit_before>var http = require('http'),
    https = require('https'),
    crypto = require('crypto'),
    querystring = require('querystring'),
    url = require('url'),
    storeDefaults = {
      adapter: 'memory'
    },
    requestDefaults = {
      request: {

      },
      caching: {
        ttl: 60 * 60,
        prefix: 'requestCaching'
      }
    };

function mergeOptions(obj1, obj2) {
  for (var prop in obj2) {
    try {
      if (typeof obj2[prop] === 'object') {
        obj1[prop] = mergeOptions(obj1[prop], obj2[prop]);
      } else if (typeof obj1[prop] === 'undefined') {
        obj1[prop] = obj2[prop];
      }
    } catch (err) {
      obj1[prop] = obj2[prop];
    }
  }

  return obj1;
}

function initRequestOptions(options) {
  if (!options)
    throw new Error('Missing [options] argument');
  if (typeof options !== 'object')
    throw new Error('[options] must be an object');

  mergeOptions(options, requestDefaults);

  if (!(typeof options.caching.ttl === 'number' && options.caching.ttl >= 0))
    throw new Error('[options.caching.ttl] must be a number >= 0');

  if (typeof options.caching.prefix !== 'string')
    throw new Error('[options.caching.prefix] must be a string');

  if (options.caching.key && typeof options.caching.key !== 'string')
    throw new Error('[options.caching.key] must be a string');

  if (typeof options.uri === 'string') {
    var parts = url.parse(options.uri);
    options.request.host = parts.hostname ||  '';
    options.request.port = parts.port;
    options.request.protocol = parts.protocol ||  'http:';
    options.request.path = parts.path ||  '';
  }

  if (options.params && typeof options.params === 'object') {
    if (options.request.method === 'GET' && typeof options.request.path === 'string') {
      var parts = url.parse(options.request.path, true);
      mergeOptions(options.params, parts.query);
      options.paramsStringified = querystring.stringify(options.params);
      options.request.path = parts.pathname + '?' + options.paramsStringified;
    }
    else if (options.request.method === 'POST') {
      options.paramsStringified = querystring.stringify(options.params);
      if (options.paramsStringified.length > 0) {
        if (!options.request.header)
          options.request.header = {};

        mergeOptions(options.request.header, {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': options.paramsStringified.length
        });
      }
    }
  }

  if (!options.caching.key) {
    options.caching.key = crypto.createHash('md5').update(JSON.stringify(options.request)).digest('hex');
  }

  return options;
}

var RequestCaching = function(options) {
  if (!options)
    options = {};
  if (typeof options !== 'object')
    throw new Error('[options] must be an object');
  if (!options.store)
    options.store = 'memory';
  if (typeof options.store !== 'string')
    throw new Error('[options.store] must be a string');

  if (!options.store) {
    options.store = storeDefaults;
  }
  else {
    if (typeof options.store === 'string')
      options.store = {adapter: options.store};
    else if (typeof options.store === 'object')
      options.store = mergeOptions(options.store, storeDefaults);
    else
      throw new Error('[options.store] must be string or an object');
  }

  try {
    var Store = require('./store/' + options.store.adapter);
    this._store = new Store(options.store.options);
  } catch (err) {
    throw new Error('Cannot find an implementation for [options.store] "' + options.store + '"');
  }
};

RequestCaching.prototype.request = function(options, callback) {
  if (callback && typeof callback !== 'function')
    throw new Error('[callback] must be a function');

  var options = initRequestOptions(options),
      self = this,
      key = (options.caching.prefix ? options.caching.prefix + ':' : '') + options.caching.key;

  self._store.get(key, function(err, data) {
    if (!err &&  data) {
      callback.apply(self, [null, data.res, data.body, {key: key, hit: true}]);
    }
    else {
      var client = options.request.protocol === 'https:' ? https : http;
      var req = client.request(options.request, function(res) {
        if (!callback) return;

        var body = '';

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

        res.on('end', function() {
          self._store.set(key, {res: res, body: body}, options.caching.ttl, function(err, data) {
            if (err) {
              callback.apply(self, [err, data.res, data.body, {key: key, hit: false}]);
            }
            else {
              callback.apply(self, [null, data.res, data.body, {key: key, hit: false}]);
            }
          });
        });
      });

      req.on('error', function(err) {
        if (!callback) return;
        callback.apply(this, [err, null, null]);
      });

      if (typeof options.paramsStringified === 'string' &&
          options.paramsStringified.length > 0 &&
          options.request.method === 'POST') {
        req.write(options.paramsStringified);
      }

      req.end();
    }
  });
};

RequestCaching.prototype.get = function(uri, queryString, ttl, callback) {
  return this.request({
    uri: uri,
    params: queryString,
    request: {
      method: 'GET'
    },
    caching: {
      ttl: ttl
    }
  }, callback);
};

RequestCaching.prototype.post = function(uri, postData, ttl, callback) {
  return this.request({
    uri: uri,
    params: postData,
    request: {
      method: 'POST'
    },
    caching: {
      ttl: ttl
    }
  }, callback);
};

module.exports = RequestCaching;
<commit_msg>Removed unused checks on store options validity<commit_after>var http = require('http'),
    https = require('https'),
    crypto = require('crypto'),
    querystring = require('querystring'),
    url = require('url'),
    storeDefaults = {
      adapter: 'memory'
    },
    requestDefaults = {
      request: {

      },
      caching: {
        ttl: 60 * 60,
        prefix: 'requestCaching'
      }
    };

function mergeOptions(obj1, obj2) {
  for (var prop in obj2) {
    try {
      if (typeof obj2[prop] === 'object') {
        obj1[prop] = mergeOptions(obj1[prop], obj2[prop]);
      } else if (typeof obj1[prop] === 'undefined') {
        obj1[prop] = obj2[prop];
      }
    } catch (err) {
      obj1[prop] = obj2[prop];
    }
  }

  return obj1;
}

function initRequestOptions(options) {
  if (!options)
    throw new Error('Missing [options] argument');
  if (typeof options !== 'object')
    throw new Error('[options] must be an object');

  mergeOptions(options, requestDefaults);

  if (!(typeof options.caching.ttl === 'number' && options.caching.ttl >= 0))
    throw new Error('[options.caching.ttl] must be a number >= 0');

  if (typeof options.caching.prefix !== 'string')
    throw new Error('[options.caching.prefix] must be a string');

  if (options.caching.key && typeof options.caching.key !== 'string')
    throw new Error('[options.caching.key] must be a string');

  if (typeof options.uri === 'string') {
    var parts = url.parse(options.uri);
    options.request.host = parts.hostname ||  '';
    options.request.port = parts.port;
    options.request.protocol = parts.protocol ||  'http:';
    options.request.path = parts.path ||  '';
  }

  if (options.params && typeof options.params === 'object') {
    if (options.request.method === 'GET' && typeof options.request.path === 'string') {
      var parts = url.parse(options.request.path, true);
      mergeOptions(options.params, parts.query);
      options.paramsStringified = querystring.stringify(options.params);
      options.request.path = parts.pathname + '?' + options.paramsStringified;
    }
    else if (options.request.method === 'POST') {
      options.paramsStringified = querystring.stringify(options.params);
      if (options.paramsStringified.length > 0) {
        if (!options.request.header)
          options.request.header = {};

        mergeOptions(options.request.header, {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': options.paramsStringified.length
        });
      }
    }
  }

  if (!options.caching.key) {
    options.caching.key = crypto.createHash('md5').update(JSON.stringify(options.request)).digest('hex');
  }

  return options;
}

var RequestCaching = function(options) {
  if (!options)
    options = {};
  if (typeof options !== 'object')
    throw new Error('[options] must be an object');

  if (!options.store) {
    options.store = storeDefaults;
  }
  else {
    if (typeof options.store === 'string')
      options.store = {adapter: options.store};
    else if (typeof options.store === 'object')
      options.store = mergeOptions(options.store, storeDefaults);
    else
      throw new Error('[options.store] must be string or an object');
  }

  try {
    var Store = require('./store/' + options.store.adapter);
    this._store = new Store(options.store.options);
  } catch (err) {
    throw new Error('Cannot find an implementation for [options.store] "' + options.store + '"');
  }
};

RequestCaching.prototype.request = function(options, callback) {
  if (callback && typeof callback !== 'function')
    throw new Error('[callback] must be a function');

  var options = initRequestOptions(options),
      self = this,
      key = (options.caching.prefix ? options.caching.prefix + ':' : '') + options.caching.key;

  self._store.get(key, function(err, data) {
    if (!err &&  data) {
      callback.apply(self, [null, data.res, data.body, {key: key, hit: true}]);
    }
    else {
      var client = options.request.protocol === 'https:' ? https : http;
      var req = client.request(options.request, function(res) {
        if (!callback) return;

        var body = '';

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

        res.on('end', function() {
          self._store.set(key, {res: res, body: body}, options.caching.ttl, function(err, data) {
            if (err) {
              callback.apply(self, [err, data.res, data.body, {key: key, hit: false}]);
            }
            else {
              callback.apply(self, [null, data.res, data.body, {key: key, hit: false}]);
            }
          });
        });
      });

      req.on('error', function(err) {
        if (!callback) return;
        callback.apply(this, [err, null, null]);
      });

      if (typeof options.paramsStringified === 'string' &&
          options.paramsStringified.length > 0 &&
          options.request.method === 'POST') {
        req.write(options.paramsStringified);
      }

      req.end();
    }
  });
};

RequestCaching.prototype.get = function(uri, queryString, ttl, callback) {
  return this.request({
    uri: uri,
    params: queryString,
    request: {
      method: 'GET'
    },
    caching: {
      ttl: ttl
    }
  }, callback);
};

RequestCaching.prototype.post = function(uri, postData, ttl, callback) {
  return this.request({
    uri: uri,
    params: postData,
    request: {
      method: 'POST'
    },
    caching: {
      ttl: ttl
    }
  }, callback);
};

module.exports = RequestCaching;
<|endoftext|>


<commit_before>function airline_init_pre() {
  prop.airline = {};
  prop.airline.airlines = {};
}

/**
 * An aircrcraft operating agency
 */
zlsa.atc.Airline = Fiber.extend(function() {
  return {
    /**
     * Create new airline
     */
    init: function (icao, options) {
      /** ICAO airline designation */
      this.icao = "YYY";

      /** Agency name */
      this.name = "Default airline";

      /** Radio callsign */
      this.callsign = 'Default';

      /** Parameters for flight number generation */
      this.flightNumberGeneration = {
        /** How many characters in the flight number */
        length: 3,
        /** Whether to use alphabetical characters */
        alpha: false,
      };

      /** Named weighted sets of aircraft */
      this.fleets = {
        default: [],
      };

      this.parse(icao, options);
    },

    /**
     * Initialize object from data
     */
    parse: function (icao, data) {
      if (data.icao)
        this.icao = data.icao;
      else
        this.icao = icao;

      this.name = data.name;
      this.callsign = data.callsign.name;
      this.flightNumberGeneration.length = data.callsign.length;
      this.flightNumberGeneration.alpha = (data.callsign.alpha === true);
      if (data.fleets)
        this.fleets = data.fleets;
      else
        this.fleets.default = data.aircraft;

      for (var f in this.fleets) {
        for (var j=0;j<this.fleets[f].length;j++) {
          this.fleets[f][j][0] = this.fleets[f][j][0].toLowerCase();
        }
      }
    },

    /**
     * Return a random ICAO aircraft designator from the given fleet
     *
     * If no fleet is specified the default fleet is used
     */
    chooseAircraft: function (fleet) {
      if (!fleet)
        fleet = 'default';

      try {
        return choose_weight(this.fleets[fleet.toLowerCase()]);
      }
      catch (e) {
        console.log("Unable to find fleet " + fleet
                    + " for airline " + this.icao);
        throw e;
      }
    },

    /**
     * Create a flight number/identifier
     */
    generateFlightNumber: function () {
      var flightNumberLength = this.flightNumberGeneration.length;
      var flightNumber = "";

      var list = "0123456789";

      // Start with a number other than zero
      flightNumber += choose(list.substr(1));

      if (this.flightNumberGeneration.alpha) {
        for (var i=0; i<flightNumberLength - 3; i++)
          flightNumber += choose(list);
        list = "abcdefghijklmnopqrstuvwxyz";
        for (var i=0; i<2; i++)
          flightNumber += choose(list);
      } else {
        for (var i=1; i<flightNumberLength;i++)
          flightNumber += choose(list);
      }
      return flightNumber;
    },

    /**
     * Checks all fleets for valid aircraft identifiers and log errors
     */
    validateFleets: function () {
      for (var f in this.fleets) {
        for (var j=0;j<this.fleets[f].length;j++) {
          if (!(this.fleets[f][j][0] in prop.aircraft.models)) {
            console.warn("Airline " + this.icao.toUpperCase()
                         + " uses nonexistent aircraft " + this.fleets[f][j][0]
                         + ", expect errors");
          }

          if (typeof this.fleets[f][j][1] != "number") {
            console.warn("Airline " + this.icao.toUpperCase()
                         + " uses non numeric weight for aircraft " +
                         this.fleets[f][j][0] + ", expect errors");
          }
        }
      }
    },
  };
});

function airline_init() {
  airline_load("AAL");
  airline_load("ACA");
  airline_load("AEA");
  airline_load("AFL");
  airline_load("AFR");
  airline_load("AIC");
  airline_load("AIRTAXI");
  airline_load("AMX");
  airline_load("ARG");
  airline_load("ASA");
  airline_load("ASQ");
  airline_load("AUA");
  airline_load("AVA");
  airline_load("AWE");
  airline_load("AWI");
  airline_load("AWQ");
  airline_load("AXB");
  airline_load("AZA");
  airline_load("AZU");
  airline_load("BAW");
  airline_load("BCY");
  airline_load("BEE");
  airline_load("BEL");
  airline_load("BER");
  airline_load("BTK");
  airline_load("BWA");
  airline_load("CCA");
  airline_load("CES");
  airline_load("CESSNA");
  airline_load("CFG");
  airline_load("CFS");
  airline_load("CPA");
  airline_load("CPZ");
  airline_load("CSN");
  airline_load("CTV");
  airline_load("CWC");
  airline_load("DAL");
  airline_load("DLH");
  airline_load("EIN");
  airline_load("EMBRAER");
  airline_load("ENY");
  airline_load("ETD");
  airline_load("EXS");
  airline_load("EVA");
  airline_load("EZY");
  airline_load("FAB");
  airline_load("FASTGA");
  airline_load("FDB");
  airline_load("FDX");
  airline_load("FFT");
  airline_load("FLG");
  airline_load("FWI");
  airline_load("GIA");
  airline_load("GJS");
  airline_load("GLO");
  airline_load("GOW");
  airline_load("GWI");
  airline_load("HAL");
  airline_load("HDA");
  airline_load("IAD");
  airline_load("IBE");
  airline_load("IGO");
  airline_load("INC");
  airline_load("JAI");
  airline_load("JAL");
  airline_load("JBU");
  airline_load("JIA");
  airline_load("KAL");
  airline_load("KAP");
  airline_load("KLC");
  airline_load("KLM");
  airline_load("LAN");
  airline_load("LIGHTGA");
  airline_load("LLR");
  airline_load("LNI");
  airline_load("MON");
  airline_load("MOV");
  airline_load("NAX");
  airline_load("NKS");
  airline_load("ONE");
  airline_load("PAA");
  airline_load("PDT");
  airline_load("QFA");
  airline_load("QXE");
  airline_load("RFF");
  airline_load("RLU");
  airline_load("RPA");
  airline_load("RYR");
  airline_load("SAS");
  airline_load("SBI");
  airline_load("SCX");
  airline_load("SEJ");
  airline_load("SJY");
  airline_load("SKW");
  airline_load("SLK");
  airline_load("SVR");
  airline_load("SWA");
  airline_load("SWR");
  airline_load("SXD");
  airline_load("TAM");
  airline_load("TCF");
  airline_load("TCX");
  airline_load("TGw");
  airline_load("THY");
  airline_load("TOM");
  airline_load("TSO");
  airline_load("TUI");
  airline_load("TWA");
  airline_load("TYA");
  airline_load("UAE");
  airline_load("UAL");
  airline_load("UPS");
  airline_load("USAF");
  airline_load("VIR");
  airline_load("VRD");
  airline_load("VTI");
  airline_load("WIA");
  airline_load("XAX");
}

function airline_load(icao) {
  icao = icao.toLowerCase();
  new Content({
    type: "json",
    url: "assets/airlines/"+icao+".json",
    payload: icao.toLowerCase(),
    callback: function(status, data, payload) {
      if(status == "ok") {
        prop.airline.airlines[payload] = new zlsa.atc.Airline(payload, data);
      }
    }
  });
}

function airline_get(icao) {
  icao = icao.toLowerCase();
  return prop.airline.airlines[icao];
}

function airline_ready() {
  for(var i in prop.airline.airlines) {
    prop.airline.airlines[i].validateFleets();
  }
}
<commit_msg>Load Singapore Airlines<commit_after>function airline_init_pre() {
  prop.airline = {};
  prop.airline.airlines = {};
}

/**
 * An aircrcraft operating agency
 */
zlsa.atc.Airline = Fiber.extend(function() {
  return {
    /**
     * Create new airline
     */
    init: function (icao, options) {
      /** ICAO airline designation */
      this.icao = "YYY";

      /** Agency name */
      this.name = "Default airline";

      /** Radio callsign */
      this.callsign = 'Default';

      /** Parameters for flight number generation */
      this.flightNumberGeneration = {
        /** How many characters in the flight number */
        length: 3,
        /** Whether to use alphabetical characters */
        alpha: false,
      };

      /** Named weighted sets of aircraft */
      this.fleets = {
        default: [],
      };

      this.parse(icao, options);
    },

    /**
     * Initialize object from data
     */
    parse: function (icao, data) {
      if (data.icao)
        this.icao = data.icao;
      else
        this.icao = icao;

      this.name = data.name;
      this.callsign = data.callsign.name;
      this.flightNumberGeneration.length = data.callsign.length;
      this.flightNumberGeneration.alpha = (data.callsign.alpha === true);
      if (data.fleets)
        this.fleets = data.fleets;
      else
        this.fleets.default = data.aircraft;

      for (var f in this.fleets) {
        for (var j=0;j<this.fleets[f].length;j++) {
          this.fleets[f][j][0] = this.fleets[f][j][0].toLowerCase();
        }
      }
    },

    /**
     * Return a random ICAO aircraft designator from the given fleet
     *
     * If no fleet is specified the default fleet is used
     */
    chooseAircraft: function (fleet) {
      if (!fleet)
        fleet = 'default';

      try {
        return choose_weight(this.fleets[fleet.toLowerCase()]);
      }
      catch (e) {
        console.log("Unable to find fleet " + fleet
                    + " for airline " + this.icao);
        throw e;
      }
    },

    /**
     * Create a flight number/identifier
     */
    generateFlightNumber: function () {
      var flightNumberLength = this.flightNumberGeneration.length;
      var flightNumber = "";

      var list = "0123456789";

      // Start with a number other than zero
      flightNumber += choose(list.substr(1));

      if (this.flightNumberGeneration.alpha) {
        for (var i=0; i<flightNumberLength - 3; i++)
          flightNumber += choose(list);
        list = "abcdefghijklmnopqrstuvwxyz";
        for (var i=0; i<2; i++)
          flightNumber += choose(list);
      } else {
        for (var i=1; i<flightNumberLength;i++)
          flightNumber += choose(list);
      }
      return flightNumber;
    },

    /**
     * Checks all fleets for valid aircraft identifiers and log errors
     */
    validateFleets: function () {
      for (var f in this.fleets) {
        for (var j=0;j<this.fleets[f].length;j++) {
          if (!(this.fleets[f][j][0] in prop.aircraft.models)) {
            console.warn("Airline " + this.icao.toUpperCase()
                         + " uses nonexistent aircraft " + this.fleets[f][j][0]
                         + ", expect errors");
          }

          if (typeof this.fleets[f][j][1] != "number") {
            console.warn("Airline " + this.icao.toUpperCase()
                         + " uses non numeric weight for aircraft " +
                         this.fleets[f][j][0] + ", expect errors");
          }
        }
      }
    },
  };
});

function airline_init() {
  airline_load("AAL");
  airline_load("ACA");
  airline_load("AEA");
  airline_load("AFL");
  airline_load("AFR");
  airline_load("AIC");
  airline_load("AIRTAXI");
  airline_load("AMX");
  airline_load("ARG");
  airline_load("ASA");
  airline_load("ASQ");
  airline_load("AUA");
  airline_load("AVA");
  airline_load("AWE");
  airline_load("AWI");
  airline_load("AWQ");
  airline_load("AXB");
  airline_load("AZA");
  airline_load("AZU");
  airline_load("BAW");
  airline_load("BCY");
  airline_load("BEE");
  airline_load("BEL");
  airline_load("BER");
  airline_load("BTK");
  airline_load("BWA");
  airline_load("CCA");
  airline_load("CES");
  airline_load("CESSNA");
  airline_load("CFG");
  airline_load("CFS");
  airline_load("CPA");
  airline_load("CPZ");
  airline_load("CSN");
  airline_load("CTV");
  airline_load("CWC");
  airline_load("DAL");
  airline_load("DLH");
  airline_load("EIN");
  airline_load("EMBRAER");
  airline_load("ENY");
  airline_load("ETD");
  airline_load("EXS");
  airline_load("EVA");
  airline_load("EZY");
  airline_load("FAB");
  airline_load("FASTGA");
  airline_load("FDB");
  airline_load("FDX");
  airline_load("FFT");
  airline_load("FLG");
  airline_load("FWI");
  airline_load("GIA");
  airline_load("GJS");
  airline_load("GLO");
  airline_load("GOW");
  airline_load("GWI");
  airline_load("HAL");
  airline_load("HDA");
  airline_load("IAD");
  airline_load("IBE");
  airline_load("IGO");
  airline_load("INC");
  airline_load("JAI");
  airline_load("JAL");
  airline_load("JBU");
  airline_load("JIA");
  airline_load("KAL");
  airline_load("KAP");
  airline_load("KLC");
  airline_load("KLM");
  airline_load("LAN");
  airline_load("LIGHTGA");
  airline_load("LLR");
  airline_load("LNI");
  airline_load("MON");
  airline_load("MOV");
  airline_load("NAX");
  airline_load("NKS");
  airline_load("ONE");
  airline_load("PAA");
  airline_load("PDT");
  airline_load("QFA");
  airline_load("QXE");
  airline_load("RFF");
  airline_load("RLU");
  airline_load("RPA");
  airline_load("RYR");
  airline_load("SAS");
  airline_load("SBI");
  airline_load("SCX");
  airline_load("SEJ");
  airline_load("SIA");
  airline_load("SJY");
  airline_load("SKW");
  airline_load("SLK");
  airline_load("SVR");
  airline_load("SWA");
  airline_load("SWR");
  airline_load("SXD");
  airline_load("TAM");
  airline_load("TCF");
  airline_load("TCX");
  airline_load("TGw");
  airline_load("THY");
  airline_load("TOM");
  airline_load("TSO");
  airline_load("TUI");
  airline_load("TWA");
  airline_load("TYA");
  airline_load("UAE");
  airline_load("UAL");
  airline_load("UPS");
  airline_load("USAF");
  airline_load("VIR");
  airline_load("VRD");
  airline_load("VTI");
  airline_load("WIA");
  airline_load("XAX");
}

function airline_load(icao) {
  icao = icao.toLowerCase();
  new Content({
    type: "json",
    url: "assets/airlines/"+icao+".json",
    payload: icao.toLowerCase(),
    callback: function(status, data, payload) {
      if(status == "ok") {
        prop.airline.airlines[payload] = new zlsa.atc.Airline(payload, data);
      }
    }
  });
}

function airline_get(icao) {
  icao = icao.toLowerCase();
  return prop.airline.airlines[icao];
}

function airline_ready() {
  for(var i in prop.airline.airlines) {
    prop.airline.airlines[i].validateFleets();
  }
}
<|endoftext|>


<commit_before>/**
 * Copyright reelyActive 2015
 * We believe in an open Internet of Things
 */

var STATUS_OK = "ok";
var STATUS_NOTFOUND = "notFound";
var STATUS_BADREQUEST = "badRequest";
var CODE_OK = 200;
var CODE_NOTFOUND = 404;
var CODE_BADREQUEST = 400;
var LONELY_DEVICE = {};

/**
 * Prepares the JSON for an API query response which is successful
 * @param {Object} devices List of devices
 * @param {Object} params The parameters of the query
 */
function prepareResponse(devices, params) {
  var response = {};
  prepareMeta(response, STATUS_OK);
  prepareLinks(response, params);
  prepareDevices(response, devices, params);
  return response;
};

/**
 * Prepares the JSON for an API query response which is successful,
 * but where no devices are present.
 * @param {Object} params The parameters of the query
 */
function prepareLonelyResponse(params) {
  return prepareResponse(LONELY_DEVICE, params);
};

/**
 * Prepares the JSON for an API query response which is unsuccessful
 * @param {String} status String representing the status message
 */
function prepareFailureResponse(status) {
  var response = {};
  prepareMeta(response, status);
  return response;
};

/**
 * Prepares and adds the _meta to the given API query response
 * @param {Object} response JSON representation of the response
 * @param {String} status String representing the status message
 */
function prepareMeta(response, status) {
  switch(status) {
    case STATUS_OK:
      response._meta = { "message": STATUS_OK,
                         "statusCode": CODE_OK };
      break;
    case STATUS_NOTFOUND:
      response._meta = { "message": STATUS_NOTFOUND,
                         "statusCode": CODE_NOTFOUND };
      break;
    default:
      response._meta = { "message": STATUS_BADREQUEST,
                         "statusCode": CODE_BADREQUEST };
  }
};

/**
 * Prepares and adds the _links to the given API query response
 * @param {Object} response JSON representation of the response
 * @param {Object} params The query parameters
 */
function prepareLinks(response, params) {
  var selfLink = { "href": params.rootUrl + params.queryPath };
  response._links = {};
  response._links["self"] = selfLink;
}

/**
 * Prepares and adds the devices to the given API query response
 * @param {Object} response JSON representation of the response
 * @param {Object} devices The list of devices
 * @param {Object} params The query parameters
 */
function prepareDevices(response, devices, params) {
  for(device in devices) {
    devices[device].href = params.rootUrl + "/id/" + device;
  }
  response.devices = devices;
}

module.exports.prepareResponse = prepareResponse;
module.exports.prepareLonelyResponse = prepareLonelyResponse;
module.exports.prepareFailureResponse = prepareFailureResponse;
<commit_msg>API functionality removed<commit_after><|endoftext|>


<commit_before>/*global document*/
'use strict';

var fs = require('fs');
var hyperglue = require('hyperglue');
var locationTracker = require('./location-tracker');
var animate = require('./animate');
var color = require('./color');
var message = require('./message');

var html = fs.readFileSync(__dirname + '/screen-navigate.html', 'utf8');

var POSITION_ERRORS = {
  '1': 'Permission Denied',
  '2': 'Position Unavailable',
  '3': 'Position Timeout'
};

exports.create = function (parent, shape, opts, next) {
  var screen = hyperglue(html, {});
  if (opts.compass === false) {
    screen.querySelector('.compass').style.display = 'none';
  }
  parent.appendChild(screen);

  var sx = shape.center.latitude;
  var sy = shape.center.longitude;
  var mx, my, deg;
  var lastPos;
  var visible = false;
  var animating = false;
  var arrow = screen.querySelector('.arrow');

  function updateArrow() {
    // http://www.movable-type.co.uk/scripts/latlong.html
    mx = lastPos.latitude;
    my = lastPos.longitude;
    var wy = sy - my;
    var x = Math.cos(mx) * Math.sin(sx)
      - Math.sin(mx) * Math.cos(sx) * Math.cos(wy);
    var y = Math.sin(wy) * Math.cos(sx);
    var d = Math.atan2(x, y) * 180 / Math.PI;
    var transform = 'rotate(' + Math.round(d - deg + 180) + 'deg)';
    arrow.style.transform = transform;
    arrow.style.webkitTransform = transform;
    if (!visible) {
      visible = true;
      animating = true;
      arrow.style.visibility = 'visible';
      animate(arrow, 'zoomIn', function () {
        animating = false;
        updateArrow();
      });
    }
  }

  var tracker = locationTracker.create();
  var makeColor = opts.colorSteps ? color(opts.colorSteps) : null;
  var accuracyElement = screen.querySelector('.accuracy');
  var distanceElement = screen.querySelector('.distance');

  tracker.on('error', function (err) {
    visible = false;
    arrow.style.visibility = 'hidden';
    document.documentElement.style.backgroundColor = 'inherit';
    animating = true;
    var text = POSITION_ERRORS[err.code] || 'Position Error';
    message.create(screen, text);
  });

  function updateAccuracy() {
    var acc = lastPos.accuracy;
    var pre = acc < 20 ? '' : 'Accuracy: ';
    accuracyElement.innerHTML = pre + Math.round(acc || 10000) + ' m';
  }

  tracker.on('position', function (pos) {
    lastPos = pos;
    if (animating) {
      return;
    }
    var distance = shape.distance(pos);
    if (opts.distance !== false) {
      distanceElement.innerHTML = distance + ' m';
      updateAccuracy();
    }
    if (deg !== undefined) {
      updateArrow();
    }
    var goodAccuracy = pos.accuracy && pos.accuracy < 20;
    if (goodAccuracy) {
      if (accuracyElement.classList.contains('bad')) {
        accuracyElement.classList.remove('bad');
        if (opts.distance === false) {
          accuracyElement.innerHTML = '';
        }
      }
    } else {
      accuracyElement.classList.add('bad');
      if (opts.distance === false) {
        updateAccuracy();
      }
    }
    if (makeColor) {
      document.documentElement.style.backgroundColor = goodAccuracy
        ? makeColor(distance)
        : 'inherit';
    }
    if (shape.within(pos)) {
      tracker.destroy();
      animate(screen, 'flash', { iterationCount: 3 }, function () {
        document.documentElement.style.backgroundColor = 'inherit';
        next();
      });
    }
  });

  if (opts.compass !== false) {
    tracker.on('heading', function (heading) {
      if (!heading) {
        return;
      }
      deg = heading;
      if (lastPos && !animating) {
        updateArrow();
      }
    });
  }
};
<commit_msg>Improve tracking permission error messages<commit_after>/*global document*/
'use strict';

var fs = require('fs');
var hyperglue = require('hyperglue');
var locationTracker = require('./location-tracker');
var animate = require('./animate');
var color = require('./color');
var message = require('./message');

var html = fs.readFileSync(__dirname + '/screen-navigate.html', 'utf8');

var POSITION_ERRORS = {
  1: 'Position tracking not allowed',
  2: 'Position tracking unavailable',
  3: 'Position tracking timeout',
  DEFAULT: 'Position tracking error'
};

exports.create = function (parent, shape, opts, next) {
  var screen = hyperglue(html, {});
  if (opts.compass === false) {
    screen.querySelector('.compass').style.display = 'none';
  }
  parent.appendChild(screen);

  var sx = shape.center.latitude;
  var sy = shape.center.longitude;
  var mx, my, deg;
  var lastPos;
  var visible = false;
  var animating = false;
  var arrow = screen.querySelector('.arrow');

  function updateArrow() {
    // http://www.movable-type.co.uk/scripts/latlong.html
    mx = lastPos.latitude;
    my = lastPos.longitude;
    var wy = sy - my;
    var x = Math.cos(mx) * Math.sin(sx)
      - Math.sin(mx) * Math.cos(sx) * Math.cos(wy);
    var y = Math.sin(wy) * Math.cos(sx);
    var d = Math.atan2(x, y) * 180 / Math.PI;
    var transform = 'rotate(' + Math.round(d - deg + 180) + 'deg)';
    arrow.style.transform = transform;
    arrow.style.webkitTransform = transform;
    if (!visible) {
      visible = true;
      animating = true;
      arrow.style.visibility = 'visible';
      animate(arrow, 'zoomIn', function () {
        animating = false;
        updateArrow();
      });
    }
  }

  var tracker = locationTracker.create();
  var makeColor = opts.colorSteps ? color(opts.colorSteps) : null;
  var accuracyElement = screen.querySelector('.accuracy');
  var distanceElement = screen.querySelector('.distance');

  tracker.on('error', function (err) {
    visible = false;
    arrow.style.visibility = 'hidden';
    document.documentElement.style.backgroundColor = 'inherit';
    animating = true;
    var text = POSITION_ERRORS[err.code] || POSITION_ERRORS.DEFAULT;
    message.create(screen, text);
  });

  function updateAccuracy() {
    var acc = lastPos.accuracy;
    var pre = acc < 20 ? '' : 'Accuracy: ';
    accuracyElement.innerHTML = pre + Math.round(acc || 10000) + ' m';
  }

  tracker.on('position', function (pos) {
    lastPos = pos;
    if (animating) {
      return;
    }
    var distance = shape.distance(pos);
    if (opts.distance !== false) {
      distanceElement.innerHTML = distance + ' m';
      updateAccuracy();
    }
    if (deg !== undefined) {
      updateArrow();
    }
    var goodAccuracy = pos.accuracy && pos.accuracy < 20;
    if (goodAccuracy) {
      if (accuracyElement.classList.contains('bad')) {
        accuracyElement.classList.remove('bad');
        if (opts.distance === false) {
          accuracyElement.innerHTML = '';
        }
      }
    } else {
      accuracyElement.classList.add('bad');
      if (opts.distance === false) {
        updateAccuracy();
      }
    }
    if (makeColor) {
      document.documentElement.style.backgroundColor = goodAccuracy
        ? makeColor(distance)
        : 'inherit';
    }
    if (shape.within(pos)) {
      tracker.destroy();
      animate(screen, 'flash', { iterationCount: 3 }, function () {
        document.documentElement.style.backgroundColor = 'inherit';
        next();
      });
    }
  });

  if (opts.compass !== false) {
    tracker.on('heading', function (heading) {
      if (!heading) {
        return;
      }
      deg = heading;
      if (lastPos && !animating) {
        updateArrow();
      }
    });
  }
};
<|endoftext|>


<commit_before>var Factory = function (dialogs, options) {
  this.dialogs = dialogs;

  this.options = options || {};
  this.config = options.config || {};
  this.templates = options.templates || {};
};

Factory.prototype.createDialog = function (dialog, options) {
  var opts = options || {};
  opts.dialog = dialog;

  var Dialog = this.dialogs.get(dialog.type);

  // add any classname if defined
  if (dialog.className) {
    opts.className = Dialog.prototype.className + ' ' + dialog.className;
  }

  // instanciate dialog
  var view = new Dialog(opts);
  // we need to set the template before rendering the view
  // if no template has been attached to the view search for the main template registry
  if (!view.template) {
    view.template = this.templates[dialog.template];
  }

  return view;
};

Factory.prototype.create = function (slug, options) {
  if (!slug && !this.config.dialogs[slug]) {
    return;
  }

  var dialog = this.config.dialogs[slug];
  return this.createDialog(dialog, options);
};

Factory.prototype.render = function (region, slug, options) {
  if (!region) {
    return;
  }

  var dialog = this.create(slug, options);

  if (!dialog) {
    return false;
  }

  region.show(dialog);

  return dialog;
};
<commit_msg>feat(dialogs): default to default templates<commit_after>var Factory = function (dialogs, options) {
  this.dialogs = dialogs;

  this.options = options || {};
  this.config = options.config || {};
  this.templates = options.templates || {};
};

Factory.prototype.createDialog = function (dialog, options) {
  var opts = options || {};
  opts.dialog = dialog;

  var Dialog = this.dialogs.get(dialog.type);

  // add any classname if defined
  if (dialog.className) {
    opts.className = Dialog.prototype.className + ' ' + dialog.className;
  }

  // instanciate dialog
  var view = new Dialog(opts);
  // we need to set the template before rendering the view
  // if no template has been attached to the view search for the main template registry
  if (!view.template) {
    view.template = this.templates[dialog.template || dialog.type];
  }

  return view;
};

Factory.prototype.create = function (slug, options) {
  if (!slug && !this.config.dialogs[slug]) {
    return;
  }

  var dialog = this.config.dialogs[slug];
  return this.createDialog(dialog, options);
};

Factory.prototype.render = function (region, slug, options) {
  if (!region) {
    return;
  }

  var dialog = this.create(slug, options);

  if (!dialog) {
    return false;
  }

  region.show(dialog);

  return dialog;
};
<|endoftext|>


<commit_before>
module.exports = secureendpoints;
secureendpoints.usage =
               "\nfhc secureendpoints [get] <app-id> [--live]"
              +"\nfhc secureendpoints set-default <app-id> <default> [--live]"
              +"\nfhc secureendpoints set-override <app-id> <endpoint> <security> [--live]"
              +"\nfhc secureendpoints remove-override <app-id> <endpoint> [--live]"
              +"\nfhc secureendpoints auditlog <app-id> [--live]"
              +"\nwhere 'default' can be either 'https' or 'appapikey'"
              +"\nUse 'fhc appendpoints' to list an Apps endpoints.";

var log = require("./utils/log");
var fhc = require("./fhc");
var fhreq = require("./utils/request");
var common = require("./common");
var util = require('util');
var async = require('async');
var path = require('path');
var ini = require('./utils/ini');
var Table = require('cli-table');

// Main secureendpoints entry point
function secureendpoints (args, cb) {
  var target = ini.get('live') ? 'live' : 'dev';
  // horrible hack for using as a script, check if the last arg is trying to override target
  if (args[args.length -1] === 'live' || args[args.length -1] === 'dev') {
    target = args[args.length -1];
    args.pop();
  }

  if (args.length == 1){
    return getSecureEndpoints(args[0], target, cb);
  }

  var action = args[0];
  if (action == 'get') {
    return getSecureEndpoints(args[1], target, cb);
  }else if (action === 'set-default'){
    if (args.length !== 3) return cb("Invalid arguments for 'set-default':" + secureendpoints.usage);
    return setDefault(args[1], args[2], target, cb);
  }else if (action === 'set-override'){
    if (args.length !== 4) return cb("Invalid arguments for 'set-override':" + secureendpoints.usage);
    return setOverride(args[1], args[2], args[3], target, cb);
  }else if (action === 'remove-override'){
    if (args.length !== 3) return cb("Invalid arguments for 'remove-override':" + secureendpoints.usage);
    return removeOverride(args[1], args[2], target, cb);
  }else if (action === 'auditlog'){
    return auditLog(args[1], args[2], target, cb);
  }else{
    return cb("Unknown command '" + action + "'. Usage: " + secureendpoints.usage);
  }
};

// get secureendpoints
function getSecureEndpoints(appId, env, cb) {
  var payload = {appId: appId, environment: env};
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/app/endpointsecurity/get", payload, "Error getting secureendpoints: ", function(err, secureendpoints){
    if(err) return cb(err);
    return cb(undefined, secureendpoints);
  });
};

// set default secureendpoints
function setDefault(appId, def, env, cb) {
  if (def !== 'https' && def !== 'appapikey') return cb("'default' must be 'https' or 'appapikey': " + secureendpoints.usage);
  var payload = {appId: appId, environment: env};
  payload['default'] = def;
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/app/endpointsecurity/setDefault", payload, "Error setting default secureendpoint: ", function(err, resp){
    if(err) return cb(err);
    return cb(undefined, resp);
  });
};

// set override
function setOverride(appId, endpoint, security, env, cb) {
  if (security !== 'https' && security !== 'appapikey') return cb("'security' must be 'https' or 'appapikey': " + secureendpoints.usage);
  var payload = {appId: appId, environment: env};
  payload.overrides = {};
  payload.overrides[endpoint] = {
    security: security
  };
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/app/endpointsecurity/setOverride", payload, "Error overriding secureendpoint: ", function(err, resp){
    if(err) return cb(err);
    return cb(undefined, resp);
  });
};

// remove override
function removeOverride(appId, endpoint, env, cb) {
  var payload = {appId: appId, environment: env, endpoint: endpoint};
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/app/endpointsecurity/removeOverride", payload, "Error removing override: ", function(err, resp){
    if(err) return cb(err);
    return cb(undefined, resp);
  });
};

// get audit log for this apps secure endpoints
function auditLog(appId, filter, env, cb) {
  var payload = {appId: appId, environment: env};
  if (filter) {
    if (typeof filter === "string") {
      try{
        filter = JSON.parse(filter);
      } catch (x) {
        return cb("Error parsing json: " + filter + " - " + util.inspect(filter));
      }
    }
    payload.filter = filter;
  }

  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/app/endpointsecurity/auditLog", payload, "Error getting auditlog: ", function(err, log){
    if(err) return cb(err);
    return cb(undefined, log);
  });
};

// bash completion
secureendpoints.completion = function (opts, cb) {
  var argv = opts.conf.argv.remain;
  if (argv[1] !== "secureendpoints") argv.unshift("secureendpoints");
  if (argv.length === 2) {
    var cmds = ["get", "set-default", "set-override", "remove-override", "auditlog"];
    if (opts.partialWord !== "l") cmds.push("list");
    return cb(undefined, cmds);
  }

  common.getAppIds(cb);
};
<commit_msg>Ticket 2877 [IR190] Create some tables for secureendpoints data in fhc: table now for auditlog<commit_after>
module.exports = secureendpoints;
secureendpoints.usage =
               "\nfhc secureendpoints [get] <app-id> [--live]"
              +"\nfhc secureendpoints set-default <app-id> <default> [--live]"
              +"\nfhc secureendpoints set-override <app-id> <endpoint> <security> [--live]"
              +"\nfhc secureendpoints remove-override <app-id> <endpoint> [--live]"
              +"\nfhc secureendpoints auditlog <app-id> [--live]"
              +"\nwhere 'default' can be either 'https' or 'appapikey'"
              +"\nUse 'fhc appendpoints' to list an Apps endpoints.";

var log = require("./utils/log");
var fhc = require("./fhc");
var fhreq = require("./utils/request");
var common = require("./common");
var util = require('util');
var async = require('async');
var path = require('path');
var ini = require('./utils/ini');
var Table = require('cli-table');

// Main secureendpoints entry point
function secureendpoints (args, cb) {
  var target = ini.get('live') ? 'live' : 'dev';
  // horrible hack for using as a script, check if the last arg is trying to override target
  if (args[args.length -1] === 'live' || args[args.length -1] === 'dev') {
    target = args[args.length -1];
    args.pop();
  }

  if (args.length == 1){
    return getSecureEndpoints(args[0], target, cb);
  }

  var action = args[0];
  if (action == 'get') {
    return getSecureEndpoints(args[1], target, cb);
  }else if (action === 'set-default'){
    if (args.length !== 3) return cb("Invalid arguments for 'set-default':" + secureendpoints.usage);
    return setDefault(args[1], args[2], target, cb);
  }else if (action === 'set-override'){
    if (args.length !== 4) return cb("Invalid arguments for 'set-override':" + secureendpoints.usage);
    return setOverride(args[1], args[2], args[3], target, cb);
  }else if (action === 'remove-override'){
    if (args.length !== 3) return cb("Invalid arguments for 'remove-override':" + secureendpoints.usage);
    return removeOverride(args[1], args[2], target, cb);
  }else if (action === 'auditlog'){
    return auditLog(args[1], args[2], target, cb);
  }else{
    return cb("Unknown command '" + action + "'. Usage: " + secureendpoints.usage);
  }
};

// get secureendpoints
function getSecureEndpoints(appId, env, cb) {
  var payload = {appId: appId, environment: env};
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/app/endpointsecurity/get", payload, "Error getting secureendpoints: ", function(err, secureendpoints){
    if(err) return cb(err);
    return cb(undefined, secureendpoints);
  });
};

// set default secureendpoints
function setDefault(appId, def, env, cb) {
  if (def !== 'https' && def !== 'appapikey') return cb("'default' must be 'https' or 'appapikey': " + secureendpoints.usage);
  var payload = {appId: appId, environment: env};
  payload['default'] = def;
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/app/endpointsecurity/setDefault", payload, "Error setting default secureendpoint: ", function(err, resp){
    if(err) return cb(err);
    return cb(undefined, resp);
  });
};

// set override
function setOverride(appId, endpoint, security, env, cb) {
  if (security !== 'https' && security !== 'appapikey') return cb("'security' must be 'https' or 'appapikey': " + secureendpoints.usage);
  var payload = {appId: appId, environment: env};
  payload.overrides = {};
  payload.overrides[endpoint] = {
    security: security
  };
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/app/endpointsecurity/setOverride", payload, "Error overriding secureendpoint: ", function(err, resp){
    if(err) return cb(err);
    return cb(undefined, resp);
  });
};

// remove override
function removeOverride(appId, endpoint, env, cb) {
  var payload = {appId: appId, environment: env, endpoint: endpoint};
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/app/endpointsecurity/removeOverride", payload, "Error removing override: ", function(err, resp){
    if(err) return cb(err);
    return cb(undefined, resp);
  });
};

// get audit log for this apps secure endpoints
function auditLog(appId, filter, env, cb) {
  var payload = {appId: appId, environment: env};
  if (filter) {
    if (typeof filter === "string") {
      try{
        filter = JSON.parse(filter);
      } catch (x) {
        return cb("Error parsing json: " + filter + " - " + util.inspect(filter));
      }
    }
    payload.filter = filter;
  }

  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/app/endpointsecurity/auditLog", payload, "Error getting auditlog: ", function(err, log){
    if(err) return cb(err);

    if(ini.get('table') === true) {
      secureendpoints.table = createTableForAuditLog(log.list);
    }
    return cb(undefined, log);
  });
};

function createTableForAuditLog(entries) {
    // calculate widths
  var maxEvent=5, maxEndpoint=8, maxSecurity=8, maxUpdatedBy=9, maxUpdatedWhen=11;

  for (var i=0; i<entries.length; i++) {
    var entry = entries[i];
    if(common.strlen(entry.event) > maxEvent) maxEvent = common.strlen(entry.event);
    if(common.strlen(entry.endpoint) > maxEndpoint) maxEndpoint = common.strlen(entry.endpoint);
    if(common.strlen(entry.security) > maxSecurity) maxSecurity = common.strlen(entry.security);
    if(common.strlen(entry.updatedBy) > maxUpdatedBy) maxUpdatedBy = common.strlen(entry.updatedBy);
    if(common.strlen(entry.updatedWhen) > maxUpdatedWhen) maxUpdatedWhen = common.strlen(entry.updatedWhen);
  }

  // create our table
  var table = new Table({
    head: ['Event', 'Endpoint', 'Security', 'Updated By', 'Updated When'],
    colWidths: [maxEvent +2 , maxEndpoint + 2, maxSecurity + 2, maxUpdatedBy + 2, maxUpdatedWhen + 2],
    style: common.style()
  });

  // populate our table
  for (var i=0; i<entries.length; i++) {
    var entry = entries[i];
    table.push([entry.event, entry.endpoint, entry.security, entry.updatedBy, entry.updatedWhen]);
  }
  return table;
};

// bash completion
secureendpoints.completion = function (opts, cb) {
  var argv = opts.conf.argv.remain;
  if (argv[1] !== "secureendpoints") argv.unshift("secureendpoints");
  if (argv.length === 2) {
    var cmds = ["get", "set-default", "set-override", "remove-override", "auditlog"];
    if (opts.partialWord !== "l") cmds.push("list");
    return cb(undefined, cmds);
  }

  common.getAppIds(cb);
};
<|endoftext|>


<commit_before>var ws = require('ws');
var WSServer = ws.Server;
var SCSocket = require('./scsocket');
var AuthEngine = require('./auth').AuthEngine;
var EventEmitter = require('events').EventEmitter;
var base64id = require('base64id');
var async = require('async');
var url = require('url');
var domain = require('domain');

var SCServer = function (options) {
  var self = this;

  var opts = {
    ackTimeout: 10000,
    allowClientPublish: true,
    path: '/socketcluster/'
  };

  var i;
  for (i in options) {
    opts[i] = options[i];
  }

  this.MIDDLEWARE_HANDSHAKE = 'handshake';
  this.MIDDLEWARE_EMIT = 'emit';
  this.MIDDLEWARE_SUBSCRIBE = 'subscribe';
  this.MIDDLEWARE_PUBLISH_IN = 'publishin';
  this.MIDDLEWARE_PUBLISH_OUT = 'publishout';

  // Deprecated
  this.MIDDLEWARE_PUBLISH = this.MIDDLEWARE_PUBLISH_IN;

  this.EVENT_PUBLISH = 'publish';

  this.ERROR_NO_PUBLISH = 'Error: Client publish feature is disabled';

  this._middleware = {};
  this._middleware[this.MIDDLEWARE_HANDSHAKE] = [];
  this._middleware[this.MIDDLEWARE_EMIT] = [];
  this._middleware[this.MIDDLEWARE_SUBSCRIBE] = [];
  this._middleware[this.MIDDLEWARE_PUBLISH_IN] = [];
  this._middleware[this.MIDDLEWARE_PUBLISH_OUT] = [];

  this.origins = opts.origins;
  this._allowAllOrigins = this.origins.indexOf('*:*') != -1;

  this.ackTimeout = opts.ackTimeout;
  this.pingInterval = opts.pingInterval;
  this.pingTimeout = opts.pingTimeout;
  this.allowClientPublish = opts.allowClientPublish;
  this.perMessageDeflate = opts.perMessageDeflate;
  this.httpServer = opts.httpServer;

  this.deliveryTimeout = opts.deliveryTimeout;

  this._ioClusterClient = opts.ioClusterClient;
  this.appName = opts.appName || '';
  this._path = opts.path;

  if (opts.authCookieName == null) {
    this._authCookieName = 'n/' + this.appName + '/auth';
  } else {
    this._authCookieName = opts.authCookieName;
  }

  this.auth = new AuthEngine({
    cookieName: this._authCookieName,
    defaultExpiryInMinutes: opts.defaultAuthTokenExpiryInMinutes,
    key: opts.authKey
  });

  this.clients = {};
  this.clientsCount = 0;

  this.global = this._ioClusterClient.global();

  this.wsServer = new WSServer({
    server: this.httpServer,
    clientTracking: false,
    perMessageDeflate: this.perMessageDeflate,
    handleProtocols: opts.handleProtocols,
    verifyClient: this.verifyHandshake.bind(this)
  });

  this.wsServer.on('error', this._handleServerError.bind(this));
  this.wsServer.on('connection', this._handleSocketConnection.bind(this));
};

SCServer.prototype = Object.create(EventEmitter.prototype);

SCServer.errorStatuses = {
  0: 'Failed handshake'
};

SCServer.prototype.sendErrorMessage = function (res, code) {
  res.writeHead(400, {'Content-Type': 'application/json'});
  res.end(JSON.stringify({
    code: code,
    message: SCServer.errorStatuses[code]
  }));
};

SCServer.prototype._handleServerError = function (error) {
  this.emit('error', error);
};

SCServer.prototype._handleSocketError = function (error) {
  // We don't want to crash the entire worker on socket error
  // so we emit it as a notice instead.
  var errorPrefix = 'Socket Error: ';
  if (error.message) {
    error.message = errorPrefix + error.message;
  } else if (typeof error == 'string') {
    error = errorPrefix + error;
  }
  this.emit('notice', error);
};

SCServer.prototype.setAuthTokenVerifyOptionsFactory = function (factoryFn) {
  this.auth.setTokenVerifyOptionsFactory(factoryFn);
};

SCServer.prototype.getAuthTokenVerifyOptionsFactory = function () {
  return this.auth.getTokenVerifyOptionsFactory();
};

SCServer.prototype._handleSocketConnection = function (wsSocket) {
  var self = this;

  this.auth.parseToken(wsSocket.upgradeReq, function (err, authToken) {
    var id = self.generateId();

    // In case of an expired, malformed or invalid token, emit an event
    // and keep going without a token.
    if (err) {
      self.emit('badAuthToken', err);
    }

    var authData = {
      token: authToken
    };

    if (err) {
      authData.error = {
        name: err.name,
        message: err.message
      };
    }

    var socketDomain = domain.createDomain();
    var scSocket = new SCSocket(id, self, wsSocket, authData);

    self.clients[id] = scSocket;
    self.clientsCount++;

    socketDomain.on('error', function (err) {
      self._handleSocketError(err);
      scSocket.disconnect();
    });
    socketDomain.add(scSocket);

    self._ioClusterClient.bind(scSocket, function (err, sock, isNotice) {
      if (err) {
        var errorMessage = 'Failed to bind socket to io cluster - ' + err;
        scSocket.emit('fail', errorMessage);
        scSocket.disconnect();
        if (isNotice) {
          self.emit('notice', errorMessage);
        } else {
          self.emit('error', new Error(errorMessage));
        }
      } else {
        scSocket.global = self.global;
        self.emit('connection', scSocket);
      }
    });

    scSocket.once('_disconnect', function () {
      delete self.clients[id];
      self.clientsCount--;
      self._ioClusterClient.unbind(scSocket, function (err) {
        if (err) {
          self.emit('error', new Error('Failed to unbind socket from io cluster - ' + err));
        } else {
          self.emit('disconnection', scSocket);
        }
      });
    });
  });
};

SCServer.prototype.close = function () {
  this.wsServer.close();
};

SCServer.prototype.getPath = function () {
  return this._path;
};

SCServer.prototype.generateId = function () {
  return base64id.generateId();
};

SCServer.prototype.on = function (event, listener) {
  if (event == 'ready') {
    this._ioClusterClient.once(event, listener);
  } else {
    EventEmitter.prototype.on.apply(this, arguments);
  }
};

SCServer.prototype.removeListener = function (event, listener) {
  if (event == 'ready') {
    this._ioClusterClient.removeListener(event, listener);
  } else {
    EventEmitter.prototype.removeListener.apply(this, arguments);
  }
};

SCServer.prototype.addMiddleware = function (type, middleware) {
  this._middleware[type].push(middleware);
};

SCServer.prototype.verifyHandshake = function (info, cb) {
  var self = this;

  var req = info.req;
  var origin = info.origin;
  if (origin == 'null' || origin == null) {
    origin = '*';
  }
  var ok = false;

  if (this._allowAllOrigins) {
    ok = true;
  } else {
    try {
      var parts = url.parse(origin);
      parts.port = parts.port || 80;
      ok = ~this.origins.indexOf(parts.hostname + ':' + parts.port) ||
        ~this.origins.indexOf(parts.hostname + ':*') ||
        ~this.origins.indexOf('*:' + parts.port);
    } catch (e) {}
  }

  if (ok) {
    var handshakeMiddleware = this._middleware[this.MIDDLEWARE_HANDSHAKE];
    if (handshakeMiddleware.length) {
      async.applyEachSeries(handshakeMiddleware, req, function (err) {
        if (err) {
          self.emit('notice', err);
          cb(false, 401, err);
        } else {
          cb(true);
        }
      });
    } else {
      cb(true);
    }
  } else {
    var err = 'Failed to authorize socket handshake - Invalid origin: ' + origin;
    this.emit('notice', err);
    cb(false, 403, err);
  }
};

SCServer.prototype.verifyInboundEvent = function (socket, event, data, cb) {
  var self = this;

  if (event == this.MIDDLEWARE_SUBSCRIBE) {
    async.applyEachSeries(this._middleware[this.MIDDLEWARE_SUBSCRIBE], socket, data,
      function (err) {
        if (err) {
          self.emit('notice', err);
        }
        cb(err);
      }
    );
  } else if (event == this.EVENT_PUBLISH) {
    if (this.allowClientPublish) {
      async.applyEachSeries(this._middleware[this.MIDDLEWARE_PUBLISH_IN], socket, data.channel, data.data,
        function (err) {
          if (err) {
            self.emit('notice', err);
            cb(err);
          } else {
            self.global.publishRaw(data.channel, data.data, data.mid, function (err) {
              cb(err);
            });
          }
        }
      );
    } else {
      cb(this.ERROR_NO_PUBLISH);
    }
  } else {
    async.applyEachSeries(this._middleware[this.MIDDLEWARE_EMIT], socket, event, data,
      function (err) {
        if (err) {
          self.emit('notice', err);
        }
        cb(err);
      }
    );
  }
};

SCServer.prototype.verifyOutboundEvent = function (socket, event, data, cb) {
  var self = this;

  if (event == this.EVENT_PUBLISH) {
    async.applyEachSeries(this._middleware[this.MIDDLEWARE_PUBLISH_OUT], socket, data.channel, data.data,
      function (err) {
        if (err) {
          if (err !== true) {
            self.emit('notice', err);
          }
          self._ioClusterClient.clearPubAck(socket.id, data.mid);
          cb(err);
        } else {
          cb();
        }
      }
    );
  } else {
    cb();
  }
};

module.exports = SCServer;
<commit_msg>Use camel casing for middleware name<commit_after>var ws = require('ws');
var WSServer = ws.Server;
var SCSocket = require('./scsocket');
var AuthEngine = require('./auth').AuthEngine;
var EventEmitter = require('events').EventEmitter;
var base64id = require('base64id');
var async = require('async');
var url = require('url');
var domain = require('domain');

var SCServer = function (options) {
  var self = this;

  var opts = {
    ackTimeout: 10000,
    allowClientPublish: true,
    path: '/socketcluster/'
  };

  var i;
  for (i in options) {
    opts[i] = options[i];
  }

  this.MIDDLEWARE_HANDSHAKE = 'handshake';
  this.MIDDLEWARE_EMIT = 'emit';
  this.MIDDLEWARE_SUBSCRIBE = 'subscribe';
  this.MIDDLEWARE_PUBLISH_IN = 'publishIn';
  this.MIDDLEWARE_PUBLISH_OUT = 'publishOut';

  // Deprecated
  this.MIDDLEWARE_PUBLISH = this.MIDDLEWARE_PUBLISH_IN;

  this.EVENT_PUBLISH = 'publish';

  this.ERROR_NO_PUBLISH = 'Error: Client publish feature is disabled';

  this._middleware = {};
  this._middleware[this.MIDDLEWARE_HANDSHAKE] = [];
  this._middleware[this.MIDDLEWARE_EMIT] = [];
  this._middleware[this.MIDDLEWARE_SUBSCRIBE] = [];
  this._middleware[this.MIDDLEWARE_PUBLISH_IN] = [];
  this._middleware[this.MIDDLEWARE_PUBLISH_OUT] = [];

  this.origins = opts.origins;
  this._allowAllOrigins = this.origins.indexOf('*:*') != -1;

  this.ackTimeout = opts.ackTimeout;
  this.pingInterval = opts.pingInterval;
  this.pingTimeout = opts.pingTimeout;
  this.allowClientPublish = opts.allowClientPublish;
  this.perMessageDeflate = opts.perMessageDeflate;
  this.httpServer = opts.httpServer;

  this.deliveryTimeout = opts.deliveryTimeout;

  this._ioClusterClient = opts.ioClusterClient;
  this.appName = opts.appName || '';
  this._path = opts.path;

  if (opts.authCookieName == null) {
    this._authCookieName = 'n/' + this.appName + '/auth';
  } else {
    this._authCookieName = opts.authCookieName;
  }

  this.auth = new AuthEngine({
    cookieName: this._authCookieName,
    defaultExpiryInMinutes: opts.defaultAuthTokenExpiryInMinutes,
    key: opts.authKey
  });

  this.clients = {};
  this.clientsCount = 0;

  this.global = this._ioClusterClient.global();

  this.wsServer = new WSServer({
    server: this.httpServer,
    clientTracking: false,
    perMessageDeflate: this.perMessageDeflate,
    handleProtocols: opts.handleProtocols,
    verifyClient: this.verifyHandshake.bind(this)
  });

  this.wsServer.on('error', this._handleServerError.bind(this));
  this.wsServer.on('connection', this._handleSocketConnection.bind(this));
};

SCServer.prototype = Object.create(EventEmitter.prototype);

SCServer.errorStatuses = {
  0: 'Failed handshake'
};

SCServer.prototype.sendErrorMessage = function (res, code) {
  res.writeHead(400, {'Content-Type': 'application/json'});
  res.end(JSON.stringify({
    code: code,
    message: SCServer.errorStatuses[code]
  }));
};

SCServer.prototype._handleServerError = function (error) {
  this.emit('error', error);
};

SCServer.prototype._handleSocketError = function (error) {
  // We don't want to crash the entire worker on socket error
  // so we emit it as a notice instead.
  var errorPrefix = 'Socket Error: ';
  if (error.message) {
    error.message = errorPrefix + error.message;
  } else if (typeof error == 'string') {
    error = errorPrefix + error;
  }
  this.emit('notice', error);
};

SCServer.prototype.setAuthTokenVerifyOptionsFactory = function (factoryFn) {
  this.auth.setTokenVerifyOptionsFactory(factoryFn);
};

SCServer.prototype.getAuthTokenVerifyOptionsFactory = function () {
  return this.auth.getTokenVerifyOptionsFactory();
};

SCServer.prototype._handleSocketConnection = function (wsSocket) {
  var self = this;

  this.auth.parseToken(wsSocket.upgradeReq, function (err, authToken) {
    var id = self.generateId();

    // In case of an expired, malformed or invalid token, emit an event
    // and keep going without a token.
    if (err) {
      self.emit('badAuthToken', err);
    }

    var authData = {
      token: authToken
    };

    if (err) {
      authData.error = {
        name: err.name,
        message: err.message
      };
    }

    var socketDomain = domain.createDomain();
    var scSocket = new SCSocket(id, self, wsSocket, authData);

    self.clients[id] = scSocket;
    self.clientsCount++;

    socketDomain.on('error', function (err) {
      self._handleSocketError(err);
      scSocket.disconnect();
    });
    socketDomain.add(scSocket);

    self._ioClusterClient.bind(scSocket, function (err, sock, isNotice) {
      if (err) {
        var errorMessage = 'Failed to bind socket to io cluster - ' + err;
        scSocket.emit('fail', errorMessage);
        scSocket.disconnect();
        if (isNotice) {
          self.emit('notice', errorMessage);
        } else {
          self.emit('error', new Error(errorMessage));
        }
      } else {
        scSocket.global = self.global;
        self.emit('connection', scSocket);
      }
    });

    scSocket.once('_disconnect', function () {
      delete self.clients[id];
      self.clientsCount--;
      self._ioClusterClient.unbind(scSocket, function (err) {
        if (err) {
          self.emit('error', new Error('Failed to unbind socket from io cluster - ' + err));
        } else {
          self.emit('disconnection', scSocket);
        }
      });
    });
  });
};

SCServer.prototype.close = function () {
  this.wsServer.close();
};

SCServer.prototype.getPath = function () {
  return this._path;
};

SCServer.prototype.generateId = function () {
  return base64id.generateId();
};

SCServer.prototype.on = function (event, listener) {
  if (event == 'ready') {
    this._ioClusterClient.once(event, listener);
  } else {
    EventEmitter.prototype.on.apply(this, arguments);
  }
};

SCServer.prototype.removeListener = function (event, listener) {
  if (event == 'ready') {
    this._ioClusterClient.removeListener(event, listener);
  } else {
    EventEmitter.prototype.removeListener.apply(this, arguments);
  }
};

SCServer.prototype.addMiddleware = function (type, middleware) {
  this._middleware[type].push(middleware);
};

SCServer.prototype.verifyHandshake = function (info, cb) {
  var self = this;

  var req = info.req;
  var origin = info.origin;
  if (origin == 'null' || origin == null) {
    origin = '*';
  }
  var ok = false;

  if (this._allowAllOrigins) {
    ok = true;
  } else {
    try {
      var parts = url.parse(origin);
      parts.port = parts.port || 80;
      ok = ~this.origins.indexOf(parts.hostname + ':' + parts.port) ||
        ~this.origins.indexOf(parts.hostname + ':*') ||
        ~this.origins.indexOf('*:' + parts.port);
    } catch (e) {}
  }

  if (ok) {
    var handshakeMiddleware = this._middleware[this.MIDDLEWARE_HANDSHAKE];
    if (handshakeMiddleware.length) {
      async.applyEachSeries(handshakeMiddleware, req, function (err) {
        if (err) {
          self.emit('notice', err);
          cb(false, 401, err);
        } else {
          cb(true);
        }
      });
    } else {
      cb(true);
    }
  } else {
    var err = 'Failed to authorize socket handshake - Invalid origin: ' + origin;
    this.emit('notice', err);
    cb(false, 403, err);
  }
};

SCServer.prototype.verifyInboundEvent = function (socket, event, data, cb) {
  var self = this;

  if (event == this.MIDDLEWARE_SUBSCRIBE) {
    async.applyEachSeries(this._middleware[this.MIDDLEWARE_SUBSCRIBE], socket, data,
      function (err) {
        if (err) {
          self.emit('notice', err);
        }
        cb(err);
      }
    );
  } else if (event == this.EVENT_PUBLISH) {
    if (this.allowClientPublish) {
      async.applyEachSeries(this._middleware[this.MIDDLEWARE_PUBLISH_IN], socket, data.channel, data.data,
        function (err) {
          if (err) {
            self.emit('notice', err);
            cb(err);
          } else {
            self.global.publishRaw(data.channel, data.data, data.mid, function (err) {
              cb(err);
            });
          }
        }
      );
    } else {
      cb(this.ERROR_NO_PUBLISH);
    }
  } else {
    async.applyEachSeries(this._middleware[this.MIDDLEWARE_EMIT], socket, event, data,
      function (err) {
        if (err) {
          self.emit('notice', err);
        }
        cb(err);
      }
    );
  }
};

SCServer.prototype.verifyOutboundEvent = function (socket, event, data, cb) {
  var self = this;

  if (event == this.EVENT_PUBLISH) {
    async.applyEachSeries(this._middleware[this.MIDDLEWARE_PUBLISH_OUT], socket, data.channel, data.data,
      function (err) {
        if (err) {
          if (err !== true) {
            self.emit('notice', err);
          }
          self._ioClusterClient.clearPubAck(socket.id, data.mid);
          cb(err);
        } else {
          cb();
        }
      }
    );
  } else {
    cb();
  }
};

module.exports = SCServer;
<|endoftext|>


<commit_before>/**
*
*	STREAM: sum
*
*
*
*	DESCRIPTION:
*		-
*
*
*	API:
*		-
*
*
*	NOTES:
*		[1]
*
*
*	TODO:
*		[1]
*
*
*	HISTORY:
*		- 2014/05/23: Created. [AReines].
*
*
*	DEPENDENCIES:
*		[1]
*
*
*	LICENSE:
*		MIT
*
*	Copyright (c) 2014. Athan Reines.
*
*
*	AUTHOR:
*		Athan Reines. athan@nodeprime.com. 2014.
*
*/

(function() {
	'use strict';

	// MODULES //

	var // Stream reduce:
		reducer = require( './../../reduce' );

	// FUNCTIONS //

	/**
	* FUNCTION: reduce( sum, data )
	*	Defines the data reduction.
	*
	* @param {number} sum - current value
	* @param {number} data - numeric stream data
	* @returns {number} reduced data
	*/
	function reduce( sum, x ) {
		sum += x;
		return sum;
	} // end FUNCTION reduce()

	// STREAM //

	/**
	* FUNCTION: Stream()
	*	Stream constructor.
	*
	* @returns {object} Stream instance
	*/
	function Stream() {
		// Default accumulator value:
		this._value = 0;

		return this;
	} // end FUNCTION stream()

	/**
	* METHOD: value( value )
	*	Setter and getter for initial value from which to begin accumulation. If a value is provided, sets the initial accumulator value. If no value is provided, returns the initial accumulator value.
	*
	* @param {number} value - initial value
	* @returns {object|number} instance object or initial value
	*/
	Stream.prototype.value = function( value ) {
		if ( !arguments.length ) {
			return this._value;
		}
		this._value = value;
		return this;
	}; // end METHOD value()

	/**
	* METHOD: stream()
	*	Returns a JSON data reduction stream for calculating the statistic.
	*/
	Stream.prototype.stream = function() {
		// Get the reduction stream:
		return reducer( reduce, this._value );
	}; // end METHOD stream()

	// EXPORTS //

	module.exports = function createStream() {
		return new Stream();
	};

})();<commit_msg>[UPDATE] additional input type checking.<commit_after>/**
*
*	STREAM: sum
*
*
*
*	DESCRIPTION:
*		-
*
*
*	API:
*		-
*
*
*	NOTES:
*		[1]
*
*
*	TODO:
*		[1]
*
*
*	HISTORY:
*		- 2014/05/23: Created. [AReines].
*
*
*	DEPENDENCIES:
*		[1]
*
*
*	LICENSE:
*		MIT
*
*	Copyright (c) 2014. Athan Reines.
*
*
*	AUTHOR:
*		Athan Reines. athan@nodeprime.com. 2014.
*
*/

(function() {
	'use strict';

	// MODULES //

	var // Stream reduce:
		reducer = require( './../../reduce' );

	// FUNCTIONS //

	/**
	* FUNCTION: reduce( sum, data )
	*	Defines the data reduction.
	*
	* @param {number} sum - current value
	* @param {number} data - numeric stream data
	* @returns {number} reduced data
	*/
	function reduce( sum, x ) {
		sum += x;
		return sum;
	} // end FUNCTION reduce()

	// STREAM //

	/**
	* FUNCTION: Stream()
	*	Stream constructor.
	*
	* @returns {object} Stream instance
	*/
	function Stream() {
		// Default accumulator value:
		this._value = 0;

		return this;
	} // end FUNCTION stream()

	/**
	* METHOD: value( value )
	*	Setter and getter for initial value from which to begin accumulation. If a value is provided, sets the initial accumulator value. If no value is provided, returns the initial accumulator value.
	*
	* @param {number} value - initial value
	* @returns {object|number} instance object or initial value
	*/
	Stream.prototype.value = function( value ) {
		if ( !arguments.length ) {
			return this._value;
		}
		if ( typeof value !== 'number' || value !== value ) {
			throw new Error( 'value()::invalid input argument. Initial value must be numeric.' );
		}
		this._value = value;
		return this;
	}; // end METHOD value()

	/**
	* METHOD: stream()
	*	Returns a JSON data reduction stream for calculating the statistic.
	*/
	Stream.prototype.stream = function() {
		// Get the reduction stream:
		return reducer( reduce, this._value );
	}; // end METHOD stream()

	// EXPORTS //

	module.exports = function createStream() {
		return new Stream();
	};

})();<|endoftext|>


<commit_before>/**
 * Convert a object to string.
 *
 * @static
 * @param {*} object
 * @returns string or empty if null or undefined
 **/
module.exports = function toString(object) {
    if (object === null || object === undefined) {
        return '';
    }
    return object.toString();
};
<commit_msg>Update toString.js<commit_after>/**
 * Convert a object to string.
 *
 * @static
 * @param {*} object
 * @returns string or empty if null or undefined
 **/
module.exports = function toString(object) {
    if (object === null || object === undefined || isNaN(obhect)) {
        return '';
    }
    return object.toString();
};
<|endoftext|>