<commit_before>/**
 * https://developer.mozilla.org/en-US/docs/Web/API/PerformancePaintTiming
 */
function calculatePaintingTimes(result) {
  if ('performance' in window) {
    let performance = window.performance;
    let performanceEntries = performance.getEntriesByType('paint');
    performanceEntries.forEach((performanceEntry, i, entries) => {
      result[performanceEntry.name] = Math.round(performanceEntry.startTime);
    });
  }
}

/**
 * https://developers.google.com/web/fundamentals/performance/critical-rendering-path/measure-crp
 */
function measureCRP(result) {
  if ('performance' in window) {
    let t = window.performance.timing;
    result['dom-interactive-time'] = t.domInteractive - t.navigationStart;
    result['dom-content-loaded'] = t.domContentLoadedEventEnd - t.navigationStart;
    result['page-loaded'] = t.loadEventEnd - t.navigationStart;
    result['request-start'] = t.requestStart - t.navigationStart;
    result['response-start'] = t.responseStart - t.navigationStart;
    result['response-end'] = t.responseEnd - t.navigationStart;
    return result;
  }
}

function readConnectionType(result) {
  var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
  if (connection) {
    result['connection'] = connection.effectiveType;
    result['downlink'] = connection.downlink;
  }
}

import ttiPolyfill from './tti-polyfill.js';

function sendResults(result) {
  var xhr = new XMLHttpRequest();
  xhr.open('POST', '/logs/', true);
  xhr.setRequestHeader('Content-type', 'application/json');
  let data = {
    attributes: {
      context: result,
      url: window.location.href
    }
  };
  xhr.send(JSON.stringify(data));
}

function calculateMetrics() {
  let result = {};
  ttiPolyfill.getFirstConsistentlyInteractive().then((tti) => {
    result['time-to-interactive'] = Math.round(tti);
    return result;
  }).then(result => {
    measureCRP(result);
    calculatePaintingTimes(result);
    readConnectionType(result);
    sendResults(result);
  });
}

window.addEventListener('load', function () {
  function updateOnlineStatus(event) {
    if (navigator.onLine) {
      $('#offlineAlert').hide('slow');
    } else {
      $('#offlineAlert').show('slow');
    }
  }
  window.addEventListener('online', updateOnlineStatus);
  window.addEventListener('offline', updateOnlineStatus);
  updateOnlineStatus();
});

calculateMetrics();
<commit_msg>Tobias/sw precache logging: show offline alert for testgroup only (#846)<commit_after>/**
 * https://developer.mozilla.org/en-US/docs/Web/API/PerformancePaintTiming
 */
function calculatePaintingTimes(result) {
  if ('performance' in window) {
    let performance = window.performance;
    let performanceEntries = performance.getEntriesByType('paint');
    performanceEntries.forEach((performanceEntry, i, entries) => {
      result[performanceEntry.name] = Math.round(performanceEntry.startTime);
    });
  }
}

/**
 * https://developers.google.com/web/fundamentals/performance/critical-rendering-path/measure-crp
 */
function measureCRP(result) {
  if ('performance' in window) {
    let t = window.performance.timing;
    result['dom-interactive-time'] = t.domInteractive - t.navigationStart;
    result['dom-content-loaded'] = t.domContentLoadedEventEnd - t.navigationStart;
    result['page-loaded'] = t.loadEventEnd - t.navigationStart;
    result['request-start'] = t.requestStart - t.navigationStart;
    result['response-start'] = t.responseStart - t.navigationStart;
    result['response-end'] = t.responseEnd - t.navigationStart;
    return result;
  }
}

function readConnectionType(result) {
  var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
  if (connection) {
    result['connection'] = connection.effectiveType;
    result['downlink'] = connection.downlink;
  }
}

import ttiPolyfill from './tti-polyfill.js';

function sendResults(result) {
  var xhr = new XMLHttpRequest();
  xhr.open('POST', '/logs/', true);
  xhr.setRequestHeader('Content-type', 'application/json');
  let data = {
    attributes: {
      context: result,
      url: window.location.href
    }
  };
  xhr.send(JSON.stringify(data));
}

function calculateMetrics() {
  let result = {};
  ttiPolyfill.getFirstConsistentlyInteractive().then((tti) => {
    result['time-to-interactive'] = Math.round(tti);
    return result;
  }).then(result => {
    measureCRP(result);
    calculatePaintingTimes(result);
    readConnectionType(result);
    sendResults(result);
  });
}

window.addEventListener('load', function () {
  function updateOnlineStatus(event) {
    if (navigator.onLine) {
      $('#offlineAlert').hide();
    } else {
      $('#offlineAlert').show();
    }
  }
  let testUserGroup = parseInt(document.getElementById('testUserGroup').value);
  if (testUserGroup == 1) {
    window.addEventListener('online', updateOnlineStatus);
    window.addEventListener('offline', updateOnlineStatus);
    updateOnlineStatus();
  }
});

calculateMetrics();
<|endoftext|>


<commit_before>require('./shims/classList.js');

import loadModules from '@pod-point/module-loader';
import combineDomModules from '@pod-point/dom-module-loader';
import * as dom from '@pod-point/dom-ops';
import {addClass} from '@pod-point/dom-ops';

import base from './modules/base';
import modal from './modules/modal';
import ajaxForm from './modules/ajax-form';
import formFields from './modules/form-fields';
import collapse from './modules/collapse';
import dropdown from './modules/dropdown';
import toggle from './modules/toggle';
import toggleAccordionPanel from './modules/toggle-accordion-panel';
import toggleElement from './modules/toggle-element';
import gallerySimple from './modules/gallery-simple';
import accordion from './modules/accordion';
import headerNav from './modules/header-nav';
import carousel from './modules/carousel';
import addressLookup from './modules/address-lookup';
import changeContent from './modules/change-content';
import checkoutYourPodPoint from './modules/checkout-your-pod-point';
import claimOlev from './modules/claim-olev';
import claimDealerDiscount from './modules/claim-dealer-discount';
import basket from './modules/basket';
import flipCounter from './modules/flip-counter';
import evMap from './modules/ev-map';

import { initAutocomplete, geolocate, fillInAddress } from './modules/address-lookup';

window.initAutocomplete = initAutocomplete;
window.geolocate = geolocate;
window.fillInAddress = fillInAddress;

dom.whenReady(() => {
    loadModules({
        base,
        formFields,
        domModules: combineDomModules({
            modal,
            ajaxForm,
            collapse,
            dropdown,
            toggle,
            toggleAccordionPanel,
            toggleElement,
            gallerySimple,
            headerNav,
            accordion,
            carousel,
            addressLookup,
            changeContent,
            checkoutYourPodPoint,
            claimOlev,
            claimDealerDiscount,
            basket,
            flipCounter,
            evMap,
        })
    });
});

function debounce(callback, wait, context = this) {
    let timeout = null
    let callbackArgs = null
    const later = () => callback.apply(context, callbackArgs)

    return function() {
        callbackArgs = arguments
        clearTimeout(timeout)
        timeout = setTimeout(later, wait)
    }
}
const handleResize = debounce((e) => {
    loadModules();
}, 100)

// window.addEventListener('resize', handleResize)

<commit_msg>eslint script.js<commit_after>import loadModules from '@pod-point/module-loader';
import combineDomModules from '@pod-point/dom-module-loader';
import * as dom from '@pod-point/dom-ops';

import base from './modules/base';
import modal from './modules/modal';
import ajaxForm from './modules/ajax-form';
import formFields from './modules/form-fields';
import collapse from './modules/collapse';
import dropdown from './modules/dropdown';
import toggle from './modules/toggle';
import toggleAccordionPanel from './modules/toggle-accordion-panel';
import toggleElement from './modules/toggle-element';
import gallerySimple from './modules/gallery-simple';
import accordion from './modules/accordion';
import headerNav from './modules/header-nav';
import carousel from './modules/carousel';
import changeContent from './modules/change-content';
import checkoutYourPodPoint from './modules/checkout-your-pod-point';
import claimOlev from './modules/claim-olev';
import claimDealerDiscount from './modules/claim-dealer-discount';
import basket from './modules/basket';
import flipCounter from './modules/flip-counter';
import evMap from './modules/ev-map';
import * as addressLookup from './modules/address-lookup';

require('./shims/classList.js');

window.initAutocomplete = addressLookup.initAutocomplete;
window.geolocate = addressLookup.geolocate;
window.fillInAddress = addressLookup.fillInAddress;

dom.whenReady(() => {
    loadModules({
        base,
        formFields,
        domModules: combineDomModules({
            modal,
            ajaxForm,
            collapse,
            dropdown,
            toggle,
            toggleAccordionPanel,
            toggleElement,
            gallerySimple,
            headerNav,
            accordion,
            carousel,
            addressLookup,
            changeContent,
            checkoutYourPodPoint,
            claimOlev,
            claimDealerDiscount,
            basket,
            flipCounter,
            evMap,
        }),
    });
});

// function debounce(callback, wait, context = this) {
//     let timeout = null;
//     let callbackArgs = null;
//     const later = () => callback.apply(context, callbackArgs);

//     return () => {
//         callbackArgs = arguments;
//         clearTimeout(timeout);
//         timeout = setTimeout(later, wait);
//     };
// }
// const handleResize = debounce((e) => {
//     loadModules();
// }, 100);

// window.addEventListener('resize', handleResize)

<|endoftext|>


<commit_before>/**
 * Object polyfill / shims
 *
 * (c) copyright 2011-2012 Brian Cavalier and John Hann
 *
 * This module is part of the cujo.js family of libraries (http://cujojs.com/).
 *
 * Licensed under the MIT License at:
 * 		http://www.opensource.org/licenses/mit-license.php
 */
/**
 * The goal of these shims is to emulate a JavaScript 1.8.5+ environments as
 * much as possible.  While it's not feasible to fully shim Object,
 * we can try to maximize code compatibility with older js engines.
 *
 * Note: these shims cannot fix `for (var p in obj) {}`. Instead, use this:
 *     Object.keys(obj).forEach(function (p) {}); // shimmed Array
 *
 * Also, these shims can't prevent writing to object properties.
 *
 * If you want your code to fail loudly if a shim can't mimic ES5 closely
 * then set the AMD loader config option `failIfShimmed`.  Possible values
 * for `failIfShimmed` include:
 *
 * true: fail on every shimmed Object function
 * false: fail never
 * function: fail for shims whose name returns true from function (name) {}
 *
 * By default, no shims fail.
 *
 * The following functions are safely shimmed:
 * create (unless the second parameter is specified since that calls defineProperties)
 * keys
 * getOwnPropertyNames
 * getPrototypeOf
 * isExtensible
 *
 * In order to play nicely with several third-party libs (including Promises/A
 * implementations), the following functions don't fail by default even though
 * they can't be correctly shimmed:
 * freeze
 * seal
 * isFrozen
 * isSealed
 *
 * Note: this shim doesn't do anything special with IE8's minimally useful
 * Object.defineProperty(domNode).
 *
 * The poly/strict module will set failIfShimmed to fail for some shims.
 * See the documentation for more information.
 *
 * IE missing enum properties fixes copied from kangax:
 * https://github.com/kangax/protolicious/blob/master/experimental/object.for_in.js
 *
 */
define(['./lib/_base'], function (base) {
"use strict";

	var refObj,
		refProto,
		getPrototypeOf,
		keys,
		featureMap,
		shims,
		undef;

	refObj = Object;
	refProto = refObj.prototype;

	getPrototypeOf = typeof {}.__proto__ == 'object'
		? function (object) { return object.__proto__; }
		: function (object) { return object.constructor ? object.constructor.prototype : refProto; };

	keys = !hasNonEnumerableProps
		? _keys
		: (function (masked) {
			return function (object) {
				var result = _keys(object), i = 0, m;
				while (m = masked[i++]) {
					if (hasProp(object, m)) result.push(m);
				}
			}
		}([ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toString', 'toLocaleString', 'valueOf' ]));

	featureMap = {
		'object-create': 'create',
		'object-freeze': 'freeze',
		'object-isfrozen': 'isFrozen',
		'object-seal': 'seal',
		'object-issealed': 'isSealed',
		'object-getprototypeof': 'getPrototypeOf',
		'object-keys': 'keys',
		'object-getownpropertynames': 'getOwnPropertyNames',
		'object-defineproperty': 'defineProperty',
		'object-defineproperties': 'defineProperties',
		'object-isextensible': 'isExtensible',
		'object-preventextensions': 'preventExtensions',
		'object-getownpropertydescriptor': 'getOwnPropertyDescriptor'
	};

	shims = {};

	function hasNonEnumerableProps () {
		for (var p in { toString: 1 }) return false;
		return true;
	}

	function createFlameThrower (feature) {
		return function () {
			throw new Error('poly/object: ' + feature + ' is not safely supported.');
		}
	}

	function has (feature) {
		var prop = featureMap[feature];
		return prop in refObj;
	}

	function PolyBase () {}

	// for better compression
	function hasProp (object, name) {
		return object.hasOwnProperty(name);
	}

	function _keys (object) {
		var result = [];
		for (var p in object) {
			if (hasProp(object, p)) {
				result.push(p);
			}
		}
		return result;
	}

	if (!has('object-create')) {
		Object.create = shims.create = function create (proto, props) {
			var obj;
			if (proto) {
				PolyBase.prototype = proto;
				obj = new PolyBase(props);
				PolyBase.prototype = null;
			}
			else {
				obj = {};
			}
			if (arguments.length > 1) {
				// defineProperties could throw depending on `shouldThrow`
				Object.defineProperties(obj, props);
			}
			return obj;
		};
	}

	if (!has('object-freeze')) {
		Object.freeze = shims.freeze = function freeze (object) {
			return object;
		};
	}

	if (!has('object-isfrozen')) {
		Object.isFrozen = shims.isFrozen = function isFrozen (object) {
			return false;
		};
	}

	if (!has('object-seal')) {
		Object.seal = shims.seal = function seal (object) {
			return object;
		};
	}

	if (!has('object-issealed')) {
		Object.isSealed = shims.isSealed = function isSealed (object) {
			return false;
		};
	}

	if (!has('object-getprototypeof')) {
		Object.getPrototypeOf = shims.getPrototypeOf = getPrototypeOf;
	}

	if (!has('object-keys')) {
		Object.keys = keys;
	}

	if (!has('object-getownpropertynames')) {
		Object.getOwnPropertyNames = shims.getOwnPropertyNames = function getOwnPropertyNames (object) {
			return keys(object);
		};
	}

	if (!has('object-defineproperty') || !has('object-defineproperties')) {
		Object.defineProperty = shims.defineProperty = function defineProperty (object, name, descriptor) {
			object[name] = descriptor && descriptor.value;
			return object;
		};
	}

	if (!has('object-defineproperties') || !has('object-create')) {
		Object.defineProperties = shims.defineProperties = function defineProperties (object, descriptors) {
			var names, name;
			names = keys(descriptors);
			while ((name = names.pop())) {
				Object.defineProperty(object, name, descriptors[name]);
			}
			return object;
		};
	}

	if (!has('object-isextensible')) {
		Object.isExtensible = shims.isExtensible = function isExtensible (object) {
			var prop = '_poly_';
			// create unique property name
			while (prop in object) prop += '_';
			// try to set it
			try {
				object[prop] = 1;
				return hasProp(object, prop);
			}
			finally {
				delete object[prop];
			}
		};
	}

	if (!has('object-preventextensions')) {
		Object.preventExtensions = shims.preventExtensions = function preventExtensions (object) {
			return object;
		};
	}

	if (!has('object-getownpropertydescriptor')) {
		Object.getOwnPropertyDescriptor = shims.getOwnPropertyDescriptor = function getOwnPropertyDescriptor (object, name) {
			return hasProp(object, name)
				? {
					value: object[name],
					enumerable: true,
					configurable: true,
					writable: true
				}
				: undef;
		};
	}

	function failIfShimmed (failTest) {
		var shouldThrow;

		if (typeof failTest == 'function') {
			shouldThrow = failTest;
		}
		else {
			// assume truthy/falsey
			shouldThrow = function () { return failTest; };
		}

		// create throwers for some features
		for (var feature in shims) {
			Object[feature] = shouldThrow(feature)
				? createFlameThrower(feature)
				: shims[feature];
		}
	}

	// this is effectively a no-op, so why execute it?
	//failIfShimmed(false);

	return {
		failIfShimmed: failIfShimmed
	};

});
<commit_msg>fix Object.keys() and make Object.create() follow es5 spec<commit_after>/**
 * Object polyfill / shims
 *
 * (c) copyright 2011-2012 Brian Cavalier and John Hann
 *
 * This module is part of the cujo.js family of libraries (http://cujojs.com/).
 *
 * Licensed under the MIT License at:
 * 		http://www.opensource.org/licenses/mit-license.php
 */
/**
 * The goal of these shims is to emulate a JavaScript 1.8.5+ environments as
 * much as possible.  While it's not feasible to fully shim Object,
 * we can try to maximize code compatibility with older js engines.
 *
 * Note: these shims cannot fix `for (var p in obj) {}`. Instead, use this:
 *     Object.keys(obj).forEach(function (p) {}); // shimmed Array
 *
 * Also, these shims can't prevent writing to object properties.
 *
 * If you want your code to fail loudly if a shim can't mimic ES5 closely
 * then set the AMD loader config option `failIfShimmed`.  Possible values
 * for `failIfShimmed` include:
 *
 * true: fail on every shimmed Object function
 * false: fail never
 * function: fail for shims whose name returns true from function (name) {}
 *
 * By default, no shims fail.
 *
 * The following functions are safely shimmed:
 * create (unless the second parameter is specified since that calls defineProperties)
 * keys
 * getOwnPropertyNames
 * getPrototypeOf
 * isExtensible
 *
 * In order to play nicely with several third-party libs (including Promises/A
 * implementations), the following functions don't fail by default even though
 * they can't be correctly shimmed:
 * freeze
 * seal
 * isFrozen
 * isSealed
 *
 * Note: this shim doesn't do anything special with IE8's minimally useful
 * Object.defineProperty(domNode).
 *
 * The poly/strict module will set failIfShimmed to fail for some shims.
 * See the documentation for more information.
 *
 * IE missing enum properties fixes copied from kangax:
 * https://github.com/kangax/protolicious/blob/master/experimental/object.for_in.js
 *
 */
define(['./lib/_base'], function (base) {
"use strict";

	var refObj,
		refProto,
		getPrototypeOf,
		keys,
		featureMap,
		shims,
		undef;

	refObj = Object;
	refProto = refObj.prototype;

	getPrototypeOf = typeof {}.__proto__ == 'object'
		? function (object) { return object.__proto__; }
		: function (object) { return object.constructor ? object.constructor.prototype : refProto; };

	keys = !hasNonEnumerableProps
		? _keys
		: (function (masked) {
			return function (object) {
				var result = _keys(object), i = 0, m;
				while (m = masked[i++]) {
					if (hasProp(object, m)) result.push(m);
				}
				return result;
			}
		}([ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toString', 'toLocaleString', 'valueOf' ]));

	featureMap = {
		'object-create': 'create',
		'object-freeze': 'freeze',
		'object-isfrozen': 'isFrozen',
		'object-seal': 'seal',
		'object-issealed': 'isSealed',
		'object-getprototypeof': 'getPrototypeOf',
		'object-keys': 'keys',
		'object-getownpropertynames': 'getOwnPropertyNames',
		'object-defineproperty': 'defineProperty',
		'object-defineproperties': 'defineProperties',
		'object-isextensible': 'isExtensible',
		'object-preventextensions': 'preventExtensions',
		'object-getownpropertydescriptor': 'getOwnPropertyDescriptor'
	};

	shims = {};

	function hasNonEnumerableProps () {
		for (var p in { toString: 1 }) return false;
		return true;
	}

	function createFlameThrower (feature) {
		return function () {
			throw new Error('poly/object: ' + feature + ' is not safely supported.');
		}
	}

	function has (feature) {
		var prop = featureMap[feature];
		return prop in refObj;
	}

	function PolyBase () {}

	// for better compression
	function hasProp (object, name) {
		return object.hasOwnProperty(name);
	}

	function _keys (object) {
		var result = [];
		for (var p in object) {
			if (hasProp(object, p)) {
				result.push(p);
			}
		}
		return result;
	}

	if (!has('object-create')) {
		Object.create = shims.create = function create (proto, props) {
			var obj;

			if (typeof proto != 'object') throw new TypeError('prototype is not of type Object or Null.');

			PolyBase.prototype = proto;
			obj = new PolyBase(props);
			PolyBase.prototype = null;

			if (arguments.length > 1) {
				// defineProperties could throw depending on `shouldThrow`
				Object.defineProperties(obj, props);
			}

			return obj;
		};
	}

	if (!has('object-freeze')) {
		Object.freeze = shims.freeze = function freeze (object) {
			return object;
		};
	}

	if (!has('object-isfrozen')) {
		Object.isFrozen = shims.isFrozen = function isFrozen (object) {
			return false;
		};
	}

	if (!has('object-seal')) {
		Object.seal = shims.seal = function seal (object) {
			return object;
		};
	}

	if (!has('object-issealed')) {
		Object.isSealed = shims.isSealed = function isSealed (object) {
			return false;
		};
	}

	if (!has('object-getprototypeof')) {
		Object.getPrototypeOf = shims.getPrototypeOf = getPrototypeOf;
	}

	if (!has('object-keys')) {
		Object.keys = keys;
	}

	if (!has('object-getownpropertynames')) {
		Object.getOwnPropertyNames = shims.getOwnPropertyNames = function getOwnPropertyNames (object) {
			return keys(object);
		};
	}

	if (!has('object-defineproperty') || !has('object-defineproperties')) {
		Object.defineProperty = shims.defineProperty = function defineProperty (object, name, descriptor) {
			object[name] = descriptor && descriptor.value;
			return object;
		};
	}

	if (!has('object-defineproperties') || !has('object-create')) {
		Object.defineProperties = shims.defineProperties = function defineProperties (object, descriptors) {
			var names, name;
			names = keys(descriptors);
			while ((name = names.pop())) {
				Object.defineProperty(object, name, descriptors[name]);
			}
			return object;
		};
	}

	if (!has('object-isextensible')) {
		Object.isExtensible = shims.isExtensible = function isExtensible (object) {
			var prop = '_poly_';
			// create unique property name
			while (prop in object) prop += '_';
			// try to set it
			try {
				object[prop] = 1;
				return hasProp(object, prop);
			}
			finally {
				delete object[prop];
			}
		};
	}

	if (!has('object-preventextensions')) {
		Object.preventExtensions = shims.preventExtensions = function preventExtensions (object) {
			return object;
		};
	}

	if (!has('object-getownpropertydescriptor')) {
		Object.getOwnPropertyDescriptor = shims.getOwnPropertyDescriptor = function getOwnPropertyDescriptor (object, name) {
			return hasProp(object, name)
				? {
					value: object[name],
					enumerable: true,
					configurable: true,
					writable: true
				}
				: undef;
		};
	}

	function failIfShimmed (failTest) {
		var shouldThrow;

		if (typeof failTest == 'function') {
			shouldThrow = failTest;
		}
		else {
			// assume truthy/falsey
			shouldThrow = function () { return failTest; };
		}

		// create throwers for some features
		for (var feature in shims) {
			Object[feature] = shouldThrow(feature)
				? createFlameThrower(feature)
				: shims[feature];
		}
	}

	// this is effectively a no-op, so why execute it?
	//failIfShimmed(false);

	return {
		failIfShimmed: failIfShimmed
	};

});
<|endoftext|>


<commit_before>var validateHTTP = require("./validateHTTP.js");
var restify = require('restify'),
    request = require('request'),
    rand = require('csprng'),
    sha1 = require('sha1'),
    uuid = require('node-uuid'),
    neo4j = require('node-neo4j');
module.exports.addOffer = function(req, res, next) {
    if((validateHTTP.validateHTTP(req, res, next, "business")) === true) {
        console.log('NEW OFFER!');
        console.log('PUT: ' + req.params.offer)
        db = new neo4j('http://localhost:7474');
        var rand = uuid.v1()
        var businessName = req.params.businessname
        var offertitle = req.params.offer + ' - ' + businessName
        var nodeid = 0;
        var url = 'http://localhost:5984/offers/' + offertitle;
        var description = req.params.description
        var REQ = req
        request.get(url, function(err, response, body) {
            if(err) {
                return next(new restify.InternalServerError('Error has occured'));
            }
            // if the document isnt found it will create it from sratch
            console.log('code' + response.statusCode)
            if(response.statusCode === 200) {
                return next(new restify.ConflictError('Offer already created'));
            } else if(response.statusCode === 404) {
                db.insertNode({
                    name: offertitle
                }, ['Offer', businessName], function(err, node) {
                    if(err) throw err;
                    // Output node properties.
                    console.log('New neo4j node created with name = ' + node.name);
                    // Output node id.
                    console.log(node._id);
                    nodeid = node._id
                    var d = new Date(),
                        date = d.toUTCString();
                    console.log(date);
                    console.log('Just above doc node id  ' + nodeid);
                    var doc = {
                        date_created: date,
                        last_modified: date,
                        uuid: rand,
                        offer_title: REQ.params.offer,
                        offer_description: description,
                        businessname: businessName,
                        redeems: [],
                        nodeid: nodeid
                    };
                    console.log('underneath node.id  ' + doc.nodeid);
                    var docStr = JSON.stringify(doc);
                    var params = {
                        uri: url,
                        body: JSON.stringify(doc)
                    };
                    request.put(params, function(err, response, body) {
                        if(err) {
                            return next(new restify.InternalServerError('Cant create document'));
                        }
                        // document has been inserted into database
                        body = JSON.parse(body);
                        res.send({
                            offer: req.params
                        });
                        res.end();
                    });
                });
            };
        });
        // if the document is found, that means the user is already created.
    };
};
module.exports.getAllOffers = function(req, res, next) {
    if((validateHTTP.validateHTTP(req, res, next, "users")) === true) {
        console.log('Get All OFFERS!');
        //Gets all offers from couchDB as JSON
        var url = 'http://localhost:5984/offers/_design/offers/_view/all';
        request.get(url, function(err, response, body) {
            if(err) {
                return next(new restify.InternalServerError('Error has occured'));
            }
            if(response.statusCode === 200) {
                res.send(JSON.parse(response.body));
            }
            else if(response.statusCode === 404) {
                return next(new restify.InternalServerError('No Offers Found'));
            };
        });
    };
};
module.exports.getBusinessOffers = function(req, res, next) {
    if((validateHTTP.validateHTTP(req, res, next, "users")) === true) {
        var business = req.params.businessname;
        console.log('Get All OFFERS from' + business);
        //Gets all offers from couchDB as JSON
        var url = 'http://localhost:5984/offers/_design/offers/_view/business?startkey="' + business + '"&endkey="' + business + '"';
        request.get(url, function(err, response, body) {
            if(err) {
                return next(new restify.InternalServerError('Error has occured'));
            }
            if(response.statusCode === 200) {
                res.send(JSON.parse(response.body));
            }
            else if(response.statusCode === 404) {
                return next(new restify.InternalServerError('No Offers Found'));
            };
        });
    };
};<commit_msg>Changed response when requesting offers<commit_after>var validateHTTP = require("./validateHTTP.js");
var restify = require('restify'),
    request = require('request'),
    rand = require('csprng'),
    sha1 = require('sha1'),
    uuid = require('node-uuid'),
    neo4j = require('node-neo4j');
module.exports.addOffer = function(req, res, next) {
    if((validateHTTP.validateHTTP(req, res, next, "business")) === true) {
        console.log('NEW OFFER!');
        console.log('PUT: ' + req.params.offer)
        db = new neo4j('http://localhost:7474');
        var rand = uuid.v1()
        var businessName = req.params.businessname
        var offertitle = req.params.offer + ' - ' + businessName
        var nodeid = 0;
        var url = 'http://localhost:5984/offers/' + offertitle;
        var description = req.params.description
        var REQ = req
        request.get(url, function(err, response, body) {
            if(err) {
                return next(new restify.InternalServerError('Error has occured'));
            }
            // if the document isnt found it will create it from sratch
            console.log('code' + response.statusCode)
            if(response.statusCode === 200) {
                return next(new restify.ConflictError('Offer already created'));
            } else if(response.statusCode === 404) {
                db.insertNode({
                    name: offertitle
                }, ['Offer', businessName], function(err, node) {
                    if(err) throw err;
                    // Output node properties.
                    console.log('New neo4j node created with name = ' + node.name);
                    // Output node id.
                    console.log(node._id);
                    nodeid = node._id
                    var d = new Date(),
                        date = d.toUTCString();
                    console.log(date);
                    console.log('Just above doc node id  ' + nodeid);
                    var doc = {
                        date_created: date,
                        last_modified: date,
                        uuid: rand,
                        offer_title: REQ.params.offer,
                        offer_description: description,
                        businessname: businessName,
                        redeems: [],
                        nodeid: nodeid
                    };
                    console.log('underneath node.id  ' + doc.nodeid);
                    var docStr = JSON.stringify(doc);
                    var params = {
                        uri: url,
                        body: JSON.stringify(doc)
                    };
                    request.put(params, function(err, response, body) {
                        if(err) {
                            return next(new restify.InternalServerError('Cant create document'));
                        }
                        // document has been inserted into database
                        body = JSON.parse(body);
                        res.send({
                            offer: req.params
                        });
                        res.end();
                    });
                });
            };
        });
        // if the document is found, that means the user is already created.
    };
};
module.exports.getAllOffers = function(req, res, next) {
    if((validateHTTP.validateHTTP(req, res, next, "users")) === true) {
        console.log('Get All OFFERS!');
        //Gets all offers from couchDB as JSON
        var url = 'http://localhost:5984/offers/_design/offers/_view/all';
        request.get(url, function(err, response, body) {
            if(err) {
                return next(new restify.InternalServerError('Error has occured'));
            }
            if(response.statusCode === 200) {
                var resp = JSON.parse(body)
                var offers = {
                    total_Offers: resp.rows.length,
                    offers: resp.rows
                }
                res.send(JSON.stringify(offers));
            } else if(response.statusCode === 404) {
                return next(new restify.InternalServerError('No Offers Found'));
            };
        });
    };
};
module.exports.getBusinessOffers = function(req, res, next) {
    if((validateHTTP.validateHTTP(req, res, next, "users")) === true) {
        var business = req.params.businessname;
        console.log('Get All OFFERS from' + business);
        //Gets all offers from couchDB as JSON
        var url = 'http://localhost:5984/offers/_design/offers/_view/business?startkey="' + business + '"&endkey="' + business + '"';
        request.get(url, function(err, response, body) {
            if(err) {
                return next(new restify.InternalServerError('Error has occured'));
            }
            if(response.statusCode === 200) {
                var resp = JSON.parse(body)
                var offers = {
                    total_Offers: resp.rows.length,
                    offers: resp.rows
                }
                res.send(JSON.stringify(offers));
            } else if(response.statusCode === 404) {
                return next(new restify.InternalServerError('No Offers Found'));
            };
        });
    };
};<|endoftext|>


<commit_before>const TimerState = new Enum({
  Stopped: 0,
  Running: 1,
  Paused: 2
});

class Timer extends EventEmitter
{
  constructor(durationSec, tickSec) {
    super();

    this._state = TimerState.Stopped;

    this.durationSec = durationSec;
    this.tickSec = tickSec;

    this.tickInterval = null;
    this.expireTimeout = null;

    this.periodStartTime = null;
    this.remainingSec = null;
  }

  observe(observer) {
    if (observer.start) {
      this.on('start', (...args) => observer.start(...args));
    }
    if (observer.stop) {
      this.on('stop', (...args) => observer.stop(...args));
    }
    if (observer.pause) {
      this.on('pause', (...args) => observer.pause(...args));
    }
    if (observer.resume) {
      this.on('resume', (...args) => observer.resume(...args));
    }
    if (observer.tick) {
      this.on('tick', (...args) => observer.tick(...args));
    }
    if (observer.expire) {
      this.on('expire', (...args) => observer.expire(...args));
    }
    if (observer.change) {
      this.on('change', (...args) => observer.change(...args));
    }
  }

  get state() {
    return this._state;
  }

  get isStopped() {
    return this.state === TimerState.Stopped;
  }

  get isRunning() {
    return this.state === TimerState.Running;
  }

  get isPaused() {
    return this.state === TimerState.Paused;
  }

  start() {
    if (!this.isStopped) {
      return;
    }

    this.setExpireTimeout(this.durationSec);
    this.setTickInterval(this.tickSec);

    this.remainingSec = this.durationSec;

    this._state = TimerState.Running;
    this.periodStartTime = Date.now();
    this.emit('start', 0, this.remainingSec);
    this.emit('change');
  }

  stop() {
    if (this.isStopped) {
      return;
    }

    clearInterval(this.tickInterval);
    clearTimeout(this.expireTimeout);

    this.tickInterval = null;
    this.expireTimeout = null;
    this.periodStartTime = null;
    this.remainingSec = null;

    this._state = TimerState.Stopped;
    this.emit('stop');
    this.emit('change');
  }

  pause() {
    if (!this.isRunning) {
      return;
    }

    clearInterval(this.tickInterval);
    clearTimeout(this.expireTimeout);

    let periodSec = (Date.now() - this.periodStartTime) / 1000;
    this.remainingSec -= periodSec;

    this._state = TimerState.Paused;
    this.periodStartTime = null;

    let elapsed = this.durationSec - this.remainingSec;
    this.emit('pause', elapsed, this.remainingSec);
    this.emit('change');
  }

  resume() {
    if (!this.isPaused) {
      return;
    }

    this.setExpireTimeout(this.remainingSec);
    this.setTickInterval(this.tickSec);

    this._state = TimerState.Running;
    this.periodStartTime = Date.now();

    let elapsed = this.durationSec - this.remainingSec;
    this.emit('resume', elapsed, this.remainingSec);
    this.emit('change');
  }

  reset() {
    this.stop();
    this.start();
  }

  setExpireTimeout(seconds) {
    this.expireTimeout = setTimeout(() => {
      clearInterval(this.tickInterval);
      clearTimeout(this.expireTimeout);

      this.tickInterval = null;
      this.expireTimeout = null;
      this.periodStartTime = null;
      this.remainingSec = null;

      this._state = TimerState.Stopped;

      this.emit('expire', this.durationSec, 0);
      this.emit('change', [{}]);
    }, seconds * 1000);
  }

  setTickInterval(seconds) {
    this.tickInterval = setInterval(() => {
      let periodSec = (Date.now() - this.periodStartTime) / 1000;
      let remainingSec = this.remainingSec - periodSec;

      let elapsed = this.durationSec - remainingSec;
      this.emit('tick', elapsed, remainingSec);
    }, seconds * 1000);
  }
}

const Phase = new Enum({
  Focus: 0,
  ShortBreak: 1,
  LongBreak: 2
});

class PomodoroTimer
{
  constructor(timerFactory, longBreakInterval) {
    this.timerFactory = timerFactory;
    this.longBreakInterval = longBreakInterval;
    this.breakCount = 0;

    this.timer = null;
    this._phase = Phase.Focus;
  }

  get phase() {
    return this._phase;
  }

  get state() {
    return this.timer ? this.timer.state : null;
  }

  get isRunning() {
    return this.timer ? this.timer.isRunning : false;
  }

  get isStopped() {
    return this.timer ? this.timer.isStopped : false;
  }

  get isPaused() {
    return this.timer ? this.timer.isPaused : false;
  }

  start(phase = null) {
    if (this.timer) {
      this.timer.stop();
    }

    if (phase) {
      this._phase = phase;
      if (phase === Phase.LongBreak) {
        this.breakCount = 0;
      }
    }

    var nextBreakCount;
    var nextPhase;

    if (this._phase !== Phase.Focus) {
      nextBreakCount = this.breakCount;
      nextPhase = Phase.Focus;
    } else {
      nextBreakCount = (this.breakCount + 1) % this.longBreakInterval;
      nextPhase = (nextBreakCount == 0) ? Phase.LongBreak : Phase.ShortBreak;
    }

    this.timer = this.timerFactory(this._phase, nextPhase);
    this.timer.on('expire', () => {
      this.breakCount = nextBreakCount;
      this._phase = nextPhase;
    });

    this.timer.start();
  }

  pause() {
    this.timer ? this.timer.pause() : null;
  }

  stop() {
    this.timer ? this.timer.stop() : null;
  }

  resume() {
    this.timer ? this.timer.resume() : null;
  }

  reset() {
    this.timer ? this.timer.reset() : null;
  }
}
<commit_msg>Clear event listeners when cycling timers.<commit_after>const TimerState = new Enum({
  Stopped: 0,
  Running: 1,
  Paused: 2
});

class Timer extends EventEmitter
{
  constructor(durationSec, tickSec) {
    super();

    this._state = TimerState.Stopped;

    this.durationSec = durationSec;
    this.tickSec = tickSec;

    this.tickInterval = null;
    this.expireTimeout = null;

    this.periodStartTime = null;
    this.remainingSec = null;
  }

  observe(observer) {
    if (observer.start) {
      this.on('start', (...args) => observer.start(...args));
    }
    if (observer.stop) {
      this.on('stop', (...args) => observer.stop(...args));
    }
    if (observer.pause) {
      this.on('pause', (...args) => observer.pause(...args));
    }
    if (observer.resume) {
      this.on('resume', (...args) => observer.resume(...args));
    }
    if (observer.tick) {
      this.on('tick', (...args) => observer.tick(...args));
    }
    if (observer.expire) {
      this.on('expire', (...args) => observer.expire(...args));
    }
    if (observer.change) {
      this.on('change', (...args) => observer.change(...args));
    }
  }

  get state() {
    return this._state;
  }

  get isStopped() {
    return this.state === TimerState.Stopped;
  }

  get isRunning() {
    return this.state === TimerState.Running;
  }

  get isPaused() {
    return this.state === TimerState.Paused;
  }

  start() {
    if (!this.isStopped) {
      return;
    }

    this.setExpireTimeout(this.durationSec);
    this.setTickInterval(this.tickSec);

    this.remainingSec = this.durationSec;

    this._state = TimerState.Running;
    this.periodStartTime = Date.now();
    this.emit('start', 0, this.remainingSec);
    this.emit('change');
  }

  stop() {
    if (this.isStopped) {
      return;
    }

    clearInterval(this.tickInterval);
    clearTimeout(this.expireTimeout);

    this.tickInterval = null;
    this.expireTimeout = null;
    this.periodStartTime = null;
    this.remainingSec = null;

    this._state = TimerState.Stopped;
    this.emit('stop');
    this.emit('change');
  }

  pause() {
    if (!this.isRunning) {
      return;
    }

    clearInterval(this.tickInterval);
    clearTimeout(this.expireTimeout);

    let periodSec = (Date.now() - this.periodStartTime) / 1000;
    this.remainingSec -= periodSec;

    this._state = TimerState.Paused;
    this.periodStartTime = null;

    let elapsed = this.durationSec - this.remainingSec;
    this.emit('pause', elapsed, this.remainingSec);
    this.emit('change');
  }

  resume() {
    if (!this.isPaused) {
      return;
    }

    this.setExpireTimeout(this.remainingSec);
    this.setTickInterval(this.tickSec);

    this._state = TimerState.Running;
    this.periodStartTime = Date.now();

    let elapsed = this.durationSec - this.remainingSec;
    this.emit('resume', elapsed, this.remainingSec);
    this.emit('change');
  }

  reset() {
    this.stop();
    this.start();
  }

  setExpireTimeout(seconds) {
    this.expireTimeout = setTimeout(() => {
      clearInterval(this.tickInterval);
      clearTimeout(this.expireTimeout);

      this.tickInterval = null;
      this.expireTimeout = null;
      this.periodStartTime = null;
      this.remainingSec = null;

      this._state = TimerState.Stopped;

      this.emit('expire', this.durationSec, 0);
      this.emit('change');
    }, seconds * 1000);
  }

  setTickInterval(seconds) {
    this.tickInterval = setInterval(() => {
      let periodSec = (Date.now() - this.periodStartTime) / 1000;
      let remainingSec = this.remainingSec - periodSec;

      let elapsed = this.durationSec - remainingSec;
      this.emit('tick', elapsed, remainingSec);
    }, seconds * 1000);
  }
}

const Phase = new Enum({
  Focus: 0,
  ShortBreak: 1,
  LongBreak: 2
});

class PomodoroTimer
{
  constructor(timerFactory, longBreakInterval) {
    this.timerFactory = timerFactory;
    this.longBreakInterval = longBreakInterval;
    this.breakCount = 0;

    this.timer = null;
    this._phase = Phase.Focus;
  }

  get phase() {
    return this._phase;
  }

  get state() {
    return this.timer ? this.timer.state : null;
  }

  get isRunning() {
    return this.timer ? this.timer.isRunning : false;
  }

  get isStopped() {
    return this.timer ? this.timer.isStopped : false;
  }

  get isPaused() {
    return this.timer ? this.timer.isPaused : false;
  }

  start(phase = null) {
    if (this.timer) {
      this.timer.stop();
      this.timer.removeAllListeners();
    }

    if (phase) {
      this._phase = phase;
      if (phase === Phase.LongBreak) {
        this.breakCount = 0;
      }
    }

    var nextBreakCount;
    var nextPhase;

    if (this._phase !== Phase.Focus) {
      nextBreakCount = this.breakCount;
      nextPhase = Phase.Focus;
    } else if (this.longBreakInterval === 0) {
      nextBreakCount = this.breakCount;
      nextPhase = Phase.ShortBreak;
    } else {
      nextBreakCount = (this.breakCount + 1) % this.longBreakInterval;
      nextPhase = (nextBreakCount === 0) ? Phase.LongBreak : Phase.ShortBreak;
    }

    this.timer = this.timerFactory(this._phase, nextPhase);
    this.timer.on('expire', () => {
      this.breakCount = nextBreakCount;
      this._phase = nextPhase;
    });

    this.timer.start();
  }

  pause() {
    this.timer ? this.timer.pause() : null;
  }

  stop() {
    this.timer ? this.timer.stop() : null;
  }

  resume() {
    this.timer ? this.timer.resume() : null;
  }

  reset() {
    this.timer ? this.timer.reset() : null;
  }
}
<|endoftext|>


<commit_before>goog.provide('lime.scheduleManager');

goog.require('goog.array');
goog.require('goog.userAgent');
goog.require('lime');

/**
 * Unified timer provider class
 * Don't create instances of this class. Used the shared instance.
 * @this {lime.scheduleManager}
 * @constructor
 */
lime.scheduleManager = new (function() {

    /**
     * Array of registered functions
     * @type {Array.<lime.scheduleManager.Task>}
     * @private
     */
    this.taskStack_ = [];

    /**
     * ScheduleManager is active
     * @type {boolean}
     * @private
     */
    this.active_ = false;
    this.started_ = false;

    /**
     * Internal setInterval id
     * @type {number}
     * @private
     */
    this.intervalID_ = 0;

    /**
     * Internal requestAnimationFrame id
     * @type {number}
     * @private
     */
    this.requestID_ = 0;

    /**
     * Maximum update rate in ms.
     * @type {number}
     * @private
     */
    this.displayRate_ = 1000 / 30;

    /**
     * Timer last fire timestamp
     * @type {number}
     * @private
     */
    this.lastRunTime_ = 0;

})();

lime.scheduleManager.Callback = function (f, ctx, delta) {
    this.f = f;
    this.ctx = ctx;
    this.paused = false;
    this.delta = delta;
}

/**
 * Scheduled task
 * @param {number} maxdelta Timer wait value after iteration.
 * @param {number=} opt_limit Number of calls.
 * @constructor
 */
lime.scheduleManager.Task = function(maxdelta, opt_limit) {
    this.maxdelta = maxdelta;
    this.limit = goog.isDef(opt_limit) ? opt_limit : -1;
    this.functionStack_ = [];
};

/**
 * Handle iteration
 * @param {number} dt Delta time since last iteration.
 * @private
 */
lime.scheduleManager.Task.prototype.step_ = function(dt) {
    if (!this.functionStack_.length) return;

    var f;
    var i = this.functionStack_.length;
    while (--i >= 0) {
        f = this.functionStack_[i];
        if (f && !f.paused && goog.isFunction(f.f)) {
            if (f.delta > dt) {
                f.delta -= dt;
            }
            else {
                var delta = this.maxdelta + dt - f.delta;
                f.delta = this.maxdelta - (dt - f.delta);
                if (f.delta < 0) f.delta = 0;
                (f.f).call(f.ctx, delta);

                if (this.limit !== -1) {
                    this.limit--;
                    if (this.limit == 0) {
                        lime.scheduleManager.unschedule(f.f, f.ctx);
                    }
                }
            }
        }
    }

};

lime.scheduleManager.taskStack_.push(new lime.scheduleManager.Task(0));

(function() {
    var vendors = ['webkit', 'moz'];
    for(var x = 0; x < vendors.length && !goog.global.requestAnimationFrame; ++x) {
        goog.global.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        goog.global.cancelAnimationFrame =
          goog.global[vendors[x]+'CancelAnimationFrame'] || goog.global[vendors[x]+'CancelRequestAnimationFrame'];
    }
}());

/**
 * Whether to use requestAnimationFrame instead of timer events
 * Exposed here so it could be disabled if needed.
 * @type {boolean}
 */
lime.scheduleManager.USE_ANIMATION_FRAME = !!goog.global.requestAnimationFrame;

/**
 * Returns maximum fire rate in ms. If you need FPS then use 1000/x
 * @this {lime.scheduleManager}
 * @return {number} Display rate.
 */
lime.scheduleManager.getDisplayRate = function() {
    //todo: bad name
    return this.displayRate_;
};

/**
 * Sets maximum fire rate for the scheduler in ms.
 * If you have FPS then send 1000/x
 * Note that if animation frame methods are used browser chooses
 * max display rate and this value has no effect.
 * @this {lime.scheduleManager}
 * @param {number} value New display rate.
 */
lime.scheduleManager.setDisplayRate = function(value) {
     this.displayRate_ = value;
     if (this.active_) {
         lime.scheduleManager.disable_();
         lime.scheduleManager.activate_();
     }
};

/**
 * Schedule a function. Passed function will be called on every frame
 * with delta time from last run time
 * @this {lime.scheduleManager}
 * @param {function(number)} f Function to be called.
 * @param {Object} context The context used when calling function.
 * @param {lime.scheduleManager.Task=} opt_task Task object.
 */
lime.scheduleManager.schedule = function(f, context, opt_task) {
    var task = goog.isDef(opt_task) ? opt_task : this.taskStack_[0];
    goog.array.insert(task.functionStack_, new this.Callback(f, context, task.maxdelta));
    goog.array.insert(this.taskStack_, task);
    if (!this.active_) {
        lime.scheduleManager.activate_();
    }
};

/**
 * Unschedule a function. For functions that have be previously scheduled
 * @this {lime.scheduleManager}
 * @param {function(number)} f Function to be unscheduled.
 * @param {Object} context Context used when scheduling.
 */
lime.scheduleManager.unschedule = function(f, context) {
    var j = this.taskStack_.length;
    while (--j >= 0) {
        var task = this.taskStack_[j],
            functionStack_ = task.functionStack_,
            fi, i = functionStack_.length;
        while (--i >= 0) {
            fi = functionStack_[i];
            if (fi.f == f && fi.ctx == context) {
                goog.array.remove(functionStack_, fi);
            }
        }
        if (functionStack_.length == 0 && j != 0) {
           goog.array.remove(this.taskStack_, task);
        }
    }
    // if no more functions: stop timers
    if (this.taskStack_.length == 1 &&
            this.taskStack_[0].functionStack_.length == 0) {
        lime.scheduleManager.disable_();
    }
};

/**
 * Start the internal timer functions
 * @this {lime.scheduleManager}
 * @private
 */
lime.scheduleManager.activate_ = function() {
    if (this.active_) return;

    // There are serious freezes on startup so its better to wait for first event loop.
    if (this.started_) this.activate__();
    else setTimeout(goog.bind(this.activate__, this), 0);

    this.started_ = true;

    this.active_ = true;
};

lime.scheduleManager.activate__ = function() {
    this.lastRunTime_ = this.now();

    if(lime.scheduleManager.USE_ANIMATION_FRAME && goog.global.requestAnimationFrame) {
        // old mozilla
        if(goog.global['mozRequestAnimationFrame'] && goog.userAgent.VERSION < 11) {
            goog.global['mozRequestAnimationFrame']();
            this.beforePaintHandlerBinded_ = goog.bind(lime.scheduleManager.beforePaintHandler_,this);
            goog.global.addEventListener('MozBeforePaint',this.beforePaintHandlerBinded_, false);
        }
        else {
            this.animationFrameHandlerBinded_ = goog.bind(lime.scheduleManager.animationFrameHandler_,this);
            this.requestID_ = goog.global.requestAnimationFrame(this.animationFrameHandlerBinded_);
        }
    }
    else {
        this.intervalID_ = setInterval(goog.bind(lime.scheduleManager.stepTimer_, this),
            lime.scheduleManager.getDisplayRate());
    }
};

(function() {

var performance = goog.global['performance']
var now = performance && (performance['now'] || performance['webkitNow'])

lime.scheduleManager.now = function() {
    return now ? now.call(performance) : goog.now();
};

})();

/**
 * Stop interval timer functions
 * @this {lime.scheduleManager}
 * @private
 */
lime.scheduleManager.disable_ = function() {
    if (!this.active_) return;

    if(lime.scheduleManager.USE_ANIMATION_FRAME && goog.global.requestAnimationFrame) {
        // old mozilla
        if(goog.global['mozRequestAnimationFrame'] && goog.userAgent.VERSION < 11) {
            goog.global.removeEventListener('MozBeforePaint',this.beforePaintHandlerBinded_, false);
        }
        else {
            goog.global.cancelAnimationFrame(this.requestId_);
        }
    }
    else {
        clearInterval(this.intervalID_);
    }
    this.active_ = false;
};

/**
 * Webkit implemtation of requestAnimationFrame handler.
 * @this {lime.scheduleManager}
 * @private
 */
lime.scheduleManager.animationFrameHandler_ = function(){
    time = this.now()
    var delta = time - this.lastRunTime_;
    if (delta < 0) { // i0S6 reports relative to the device restart time. So first is negative.
        delta = 1;
    }
    lime.scheduleManager.dispatch_(delta);
    this.lastRunTime_ = time;
    this.requestId_ = goog.global.requestAnimationFrame(this.animationFrameHandlerBinded_);
}

/**
 * Mozilla < 11 implementation of requestAnimationFrame handler.
 * @this {lime.scheduleManager}
 * @private
 */
lime.scheduleManager.beforePaintHandler_ = function(event){
    var delta = event.timeStamp - this.lastRunTime_;
    lime.scheduleManager.dispatch_(delta);
    this.lastRunTime_ = event.timeStamp;
    goog.global['mozRequestAnimationFrame']();
}

/**
 * Timer events step function that delegates to other objects waiting
 * @this {lime.scheduleManager}
 * @private
 */
lime.scheduleManager.stepTimer_ = function() {
    var t;
    var curTime = this.now();
    var delta = curTime - this.lastRunTime_;
    if (delta < 0) delta = 1;
    lime.scheduleManager.dispatch_(delta);
    this.lastRunTime_ = curTime;
};

/**
 * Call all scheduled tasks
 * @this {lime.scheduleManager}
 * @param {number} delta Milliseconds since last run.
 * @private
 */
lime.scheduleManager.dispatch_ = function(delta){

    var stack = this.taskStack_.slice()
    var i = stack.length;
    while (--i >= 0) stack[i].step_(delta);
    //hack to deal with FF4 CSS transformation issue https://bugzilla.mozilla.org/show_bug.cgi?id=637597
    if(lime.transformSet_ == 1 && (/Firefox\/18./).test(goog.userAgent.getUserAgentString()) &&
       !lime.FF4_USE_HW_ACCELERATION){
        if(lime.scheduleManager.odd_){
            document.body.style['MozTransform'] = '';
            lime.scheduleManager.odd_=0;
        }
        else {
            document.body.style['MozTransform'] = 'scale(1,1)';
            lime.scheduleManager.odd_=1;
        }
        lime.transformSet_=0;
    }
};

/**
 * Change director's activity. Used for pausing updates when director is paused
 * @this {lime.scheduleManager}
 * @param {lime.Director} director Director.
 * @param {boolean} value Active or inactive?
 */
lime.scheduleManager.changeDirectorActivity = function(director, value) {
    var t, context, f, d, i,
    j = this.taskStack_.length;
    while (--j >= 0) {

        t = this.taskStack_[j];
        i = t.functionStack_.length;
        while (--i >= 0) {
            f = t.functionStack_[i];
            context = f.ctx;
            if (goog.isFunction(context.getDirector)) {
                d = context.getDirector();
                if (d == director) {
                    f.paused = !!value
                }
            }
        }
    }
};

/**
 * Set up function to be called once after a delay
 * @param {function(number)} f Function to be called.
 * @param {Object} context Context used when calling object.
 * @param {number} delay Delay before calling.
 */
lime.scheduleManager.callAfter = function(f, context, delay) {
    lime.scheduleManager.scheduleWithDelay(f, context, delay, 1);
};

/**
 * Set up function to be called repeatedly after a delay
 * @param {function(number)} f Function to be called.
 * @param {Object} context Context used when calling object.
 * @param {number} delay Delay before calling.
 * @param {number=} opt_limit Number of times to call.
 * @this {lime.scheduleManager}
 */
lime.scheduleManager.scheduleWithDelay = function(f, context,
        delay, opt_limit) {
    var task = new lime.scheduleManager.Task(delay, opt_limit);
    lime.scheduleManager.schedule(f, context, task);
};
<commit_msg>Fix unscheduling functions that are used multiple times<commit_after>goog.provide('lime.scheduleManager');

goog.require('goog.array');
goog.require('goog.userAgent');
goog.require('lime');

/**
 * Unified timer provider class
 * Don't create instances of this class. Used the shared instance.
 * @this {lime.scheduleManager}
 * @constructor
 */
lime.scheduleManager = new (function() {

    /**
     * Array of registered functions
     * @type {Array.<lime.scheduleManager.Task>}
     * @private
     */
    this.taskStack_ = [];

    /**
     * ScheduleManager is active
     * @type {boolean}
     * @private
     */
    this.active_ = false;
    this.started_ = false;

    /**
     * Internal setInterval id
     * @type {number}
     * @private
     */
    this.intervalID_ = 0;

    /**
     * Internal requestAnimationFrame id
     * @type {number}
     * @private
     */
    this.requestID_ = 0;

    /**
     * Maximum update rate in ms.
     * @type {number}
     * @private
     */
    this.displayRate_ = 1000 / 30;

    /**
     * Timer last fire timestamp
     * @type {number}
     * @private
     */
    this.lastRunTime_ = 0;

})();

lime.scheduleManager.Callback = function (f, ctx, delta) {
    this.f = f;
    this.ctx = ctx;
    this.paused = false;
    this.delta = delta;
}

/**
 * Scheduled task
 * @param {number} maxdelta Timer wait value after iteration.
 * @param {number=} opt_limit Number of calls.
 * @constructor
 */
lime.scheduleManager.Task = function(maxdelta, opt_limit) {
    this.maxdelta = maxdelta;
    this.limit = goog.isDef(opt_limit) ? opt_limit : -1;
    this.functionStack_ = [];
};

/**
 * Handle iteration
 * @param {number} dt Delta time since last iteration.
 * @private
 */
lime.scheduleManager.Task.prototype.step_ = function(dt) {
    if (!this.functionStack_.length) return;

    var f;
    var i = this.functionStack_.length;
    while (--i >= 0) {
        f = this.functionStack_[i];
        if (f && !f.paused && goog.isFunction(f.f)) {
            if (f.delta > dt) {
                f.delta -= dt;
            }
            else {
                var delta = this.maxdelta + dt - f.delta;
                f.delta = this.maxdelta - (dt - f.delta);
                if (f.delta < 0) f.delta = 0;
                (f.f).call(f.ctx, delta);

                if (this.limit !== -1) {
                    this.limit--;
                    if (this.limit == 0) {
                        lime.scheduleManager.unschedule(f.id);
                    }
                }
            }
        }
    }

};

lime.scheduleManager.taskStack_.push(new lime.scheduleManager.Task(0));

(function() {
    var vendors = ['webkit', 'moz'];
    for(var x = 0; x < vendors.length && !goog.global.requestAnimationFrame; ++x) {
        goog.global.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        goog.global.cancelAnimationFrame =
          goog.global[vendors[x]+'CancelAnimationFrame'] || goog.global[vendors[x]+'CancelRequestAnimationFrame'];
    }
}());

/**
 * Whether to use requestAnimationFrame instead of timer events
 * Exposed here so it could be disabled if needed.
 * @type {boolean}
 */
lime.scheduleManager.USE_ANIMATION_FRAME = !!goog.global.requestAnimationFrame;

/**
 * Returns maximum fire rate in ms. If you need FPS then use 1000/x
 * @this {lime.scheduleManager}
 * @return {number} Display rate.
 */
lime.scheduleManager.getDisplayRate = function() {
    //todo: bad name
    return this.displayRate_;
};

/**
 * Sets maximum fire rate for the scheduler in ms.
 * If you have FPS then send 1000/x
 * Note that if animation frame methods are used browser chooses
 * max display rate and this value has no effect.
 * @this {lime.scheduleManager}
 * @param {number} value New display rate.
 */
lime.scheduleManager.setDisplayRate = function(value) {
     this.displayRate_ = value;
     if (this.active_) {
         lime.scheduleManager.disable_();
         lime.scheduleManager.activate_();
     }
};
/**
 * Generate unique id for scheduled function
 */
lime.scheduleManager.nextFunctionId__=(function() {
	var curId = 0;
	//next id
	return function(){return curId++};
})()
/**
 * Schedule a function. Passed function will be called on every frame
 * with delta time from last run time
 * @this {lime.scheduleManager}
 * @param {function(number)} f Function to be called.
 * @param {Object} context The context used when calling function.
 * @param {lime.scheduleManager.Task=} opt_task Task object.
 */

lime.scheduleManager.schedule = function(f, context, opt_task) {
    var task = goog.isDef(opt_task) ? opt_task : this.taskStack_[0];
	var cb = new this.Callback(f, context, task.maxdelta);
	cb.id = this.nextFunctionId__();
    goog.array.insert(task.functionStack_, cb);
    goog.array.insert(this.taskStack_, task);
    if (!this.active_) {
        lime.scheduleManager.activate_();
    }
};

/**
 * Unschedule a function. For functions that have be previously scheduled
 * @this {lime.scheduleManager}
 * @param {Number} functionId Id generated when scheduling.
 */
lime.scheduleManager.unschedule = function(functionId) {
    var j = this.taskStack_.length;
	//Just for  compatible with the old API lime.scheduleManager.unschedule(function,context)
	var isEqualFun = goog.isFunction(functionId)?(function(context) {
		console&&console.warn&&console.warn("lime.scheduleManager.unschedule(function,context)"+ " is deprecated,You can use  unschedule(functionId) to replace it,"
		+"details see https://github.com/digitalfruit/limejs/issues/43")
		return function(f) {return f.f == functionId && f.ctx == context}
	})(arguments[1]):function(f) {
		return f.id == functionId;
	}
    while (--j >= 0) {
        var task = this.taskStack_[j],
            functionStack_ = task.functionStack_,
            fi, i = functionStack_.length;
        while (--i >= 0) {
            fi = functionStack_[i];
            if (isEqualFun(fi)) {
                goog.array.remove(functionStack_, fi);
            }
        }
        if (functionStack_.length == 0 && j != 0) {
           goog.array.remove(this.taskStack_, task);
        }
    }
    // if no more functions: stop timers
    if (this.taskStack_.length == 1 &&
            this.taskStack_[0].functionStack_.length == 0) {
        lime.scheduleManager.disable_();
    }
};

/**
 * Start the internal timer functions
 * @this {lime.scheduleManager}
 * @private
 */
lime.scheduleManager.activate_ = function() {
    if (this.active_) return;

    // There are serious freezes on startup so its better to wait for first event loop.
    if (this.started_) this.activate__();
    else setTimeout(goog.bind(this.activate__, this), 0);

    this.started_ = true;

    this.active_ = true;
};

lime.scheduleManager.activate__ = function() {
    this.lastRunTime_ = this.now();

    if(lime.scheduleManager.USE_ANIMATION_FRAME && goog.global.requestAnimationFrame) {
        // old mozilla
        if(goog.global['mozRequestAnimationFrame'] && goog.userAgent.VERSION < 11) {
            goog.global['mozRequestAnimationFrame']();
            this.beforePaintHandlerBinded_ = goog.bind(lime.scheduleManager.beforePaintHandler_,this);
            goog.global.addEventListener('MozBeforePaint',this.beforePaintHandlerBinded_, false);
        }
        else {
            this.animationFrameHandlerBinded_ = goog.bind(lime.scheduleManager.animationFrameHandler_,this);
            this.requestID_ = goog.global.requestAnimationFrame(this.animationFrameHandlerBinded_);
        }
    }
    else {
        this.intervalID_ = setInterval(goog.bind(lime.scheduleManager.stepTimer_, this),
            lime.scheduleManager.getDisplayRate());
    }
};

(function() {

var performance = goog.global['performance']
var now = performance && (performance['now'] || performance['webkitNow'])

lime.scheduleManager.now = function() {
    return now ? now.call(performance) : goog.now();
};

})();

/**
 * Stop interval timer functions
 * @this {lime.scheduleManager}
 * @private
 */
lime.scheduleManager.disable_ = function() {
    if (!this.active_) return;

    if(lime.scheduleManager.USE_ANIMATION_FRAME && goog.global.requestAnimationFrame) {
        // old mozilla
        if(goog.global['mozRequestAnimationFrame'] && goog.userAgent.VERSION < 11) {
            goog.global.removeEventListener('MozBeforePaint',this.beforePaintHandlerBinded_, false);
        }
        else {
            goog.global.cancelAnimationFrame(this.requestId_);
        }
    }
    else {
        clearInterval(this.intervalID_);
    }
    this.active_ = false;
};

/**
 * Webkit implemtation of requestAnimationFrame handler.
 * @this {lime.scheduleManager}
 * @private
 */
lime.scheduleManager.animationFrameHandler_ = function(){
    time = this.now()
    var delta = time - this.lastRunTime_;
    if (delta < 0) { // i0S6 reports relative to the device restart time. So first is negative.
        delta = 1;
    }
    lime.scheduleManager.dispatch_(delta);
    this.lastRunTime_ = time;
    this.requestId_ = goog.global.requestAnimationFrame(this.animationFrameHandlerBinded_);
}

/**
 * Mozilla < 11 implementation of requestAnimationFrame handler.
 * @this {lime.scheduleManager}
 * @private
 */
lime.scheduleManager.beforePaintHandler_ = function(event){
    var delta = event.timeStamp - this.lastRunTime_;
    lime.scheduleManager.dispatch_(delta);
    this.lastRunTime_ = event.timeStamp;
    goog.global['mozRequestAnimationFrame']();
}

/**
 * Timer events step function that delegates to other objects waiting
 * @this {lime.scheduleManager}
 * @private
 */
lime.scheduleManager.stepTimer_ = function() {
    var t;
    var curTime = this.now();
    var delta = curTime - this.lastRunTime_;
    if (delta < 0) delta = 1;
    lime.scheduleManager.dispatch_(delta);
    this.lastRunTime_ = curTime;
};

/**
 * Call all scheduled tasks
 * @this {lime.scheduleManager}
 * @param {number} delta Milliseconds since last run.
 * @private
 */
lime.scheduleManager.dispatch_ = function(delta){

    var stack = this.taskStack_.slice()
    var i = stack.length;
    while (--i >= 0) stack[i].step_(delta);
    //hack to deal with FF4 CSS transformation issue https://bugzilla.mozilla.org/show_bug.cgi?id=637597
    if(lime.transformSet_ == 1 && (/Firefox\/18./).test(goog.userAgent.getUserAgentString()) &&
       !lime.FF4_USE_HW_ACCELERATION){
        if(lime.scheduleManager.odd_){
            document.body.style['MozTransform'] = '';
            lime.scheduleManager.odd_=0;
        }
        else {
            document.body.style['MozTransform'] = 'scale(1,1)';
            lime.scheduleManager.odd_=1;
        }
        lime.transformSet_=0;
    }
};

/**
 * Change director's activity. Used for pausing updates when director is paused
 * @this {lime.scheduleManager}
 * @param {lime.Director} director Director.
 * @param {boolean} value Active or inactive?
 */
lime.scheduleManager.changeDirectorActivity = function(director, value) {
    var t, context, f, d, i,
    j = this.taskStack_.length;
    while (--j >= 0) {

        t = this.taskStack_[j];
        i = t.functionStack_.length;
        while (--i >= 0) {
            f = t.functionStack_[i];
            context = f.ctx;
            if (goog.isFunction(context.getDirector)) {
                d = context.getDirector();
                if (d == director) {
                    f.paused = !!value
                }
            }
        }
    }
};

/**
 * Set up function to be called once after a delay
 * @param {function(number)} f Function to be called.
 * @param {Object} context Context used when calling object.
 * @param {number} delay Delay before calling.
 */
lime.scheduleManager.callAfter = function(f, context, delay) {
    lime.scheduleManager.scheduleWithDelay(f, context, delay, 1);
};

/**
 * Set up function to be called repeatedly after a delay
 * @param {function(number)} f Function to be called.
 * @param {Object} context Context used when calling object.
 * @param {number} delay Delay before calling.
 * @param {number=} opt_limit Number of times to call.
 * @this {lime.scheduleManager}
 */
lime.scheduleManager.scheduleWithDelay = function(f, context,
        delay, opt_limit) {
    var task = new lime.scheduleManager.Task(delay, opt_limit);
    lime.scheduleManager.schedule(f, context, task);
};
<|endoftext|>


<commit_before>var B = require('bluebird');
var superagent = require('superagent');
var childProcess = require('child_process');
var fs = require('fs');
var path = require('path');

// Override the default behavior of superagent, which encodes to UTF-8.
var _parse = function(res, done) {
    res.text = '';
    res.setEncoding('binary');
    res.on('data', function(chunk) { res.text += chunk; });
    res.on('end', done);
};

function _verifyJsonFormat(aasa) {
    var applinks = aasa.applinks;
    if (!applinks) {
        return false;
    }

    var details = applinks.details;
    if (!details) {
        return false;
    }

    // Domains are an array: [ { appID: '01234567890.com.foo.FooApp', paths: [ '*' ] } ]
    if (details instanceof Array) {
        for (var i = 0; i < details.length; i++) {
            var domain = details[i];
            if (!(typeof domain.appID === 'string' && domain.paths instanceof Array)) {
                return false;
            }
        }
    }
    // Domains are an object: { '01234567890.com.foo.FooApp': { paths: [ '*' ] } }
    else {
        for (var domain in details) {
            if (!(details[domain].paths instanceof Array)) {
                return false;
            }
        }
    }

    return true;
}

function _verifyBundleIdentifierIsPresent(aasa, bundleIdentifier, teamIdentifier) {
    var regexString = bundleIdentifier.replace(/\./g, '\\.') + '$';
    if (teamIdentifier) {
        regexString = teamIdentifier + '\\.' + regexString;
    }

    var identifierRegex = new RegExp(regexString);

    var details = aasa.applinks.details;

    // Domains are an array: [ { appID: '01234567890.com.foo.FooApp', paths: [ '*' ] } ]
    if (details instanceof Array) {
        for (var i = 0; i < details.length; i++) {
            var domain = details[i];
            if (identifierRegex.test(domain.appID) && domain.paths instanceof Array) {
                return true;
            }
        }
    }
    // Domains are an object: { '01234567890.com.foo.FooApp': { paths: [ '*' ] } }
    else {
        for (var domain in details) {
            if (identifierRegex.test(domain) && details[domain].paths instanceof Array) {
                return true;
            }
        }
    }

    return false;
}

function _evaluateAASA(content, bundleIdentifier, teamIdentifier, encrypted) {
    return new B(function(resolve, reject) {
        try {
            var domainAASAValue = JSON.parse(content);

            // Make sure format is good.
            var jsonValidationResult = _verifyJsonFormat(domainAASAValue);

            // Only check bundle identifier if json is good and a bundle identifier to test against is present
            var bundleIdentifierResult;
            if (jsonValidationResult && bundleIdentifier) {
                bundleIdentifierResult =_verifyBundleIdentifierIsPresent(domainAASAValue, bundleIdentifier, teamIdentifier);
            }

            resolve({ encrypted: encrypted, aasa: domainAASAValue, jsonValid: jsonValidationResult, bundleIdentifierFound: bundleIdentifierResult });
        }
        catch (e) {
            reject(e);
        }
    });
}

function _writeAASAContentsToDiskAndValidate(writePath, content, bundleIdentifier, teamIdentifier) {
    return new B(function(resolve, reject) {
        // Write the file to disk. Probably don't actually *need* to do this,
        // but I haven't figured out how to provide it to the process' stdin.
        fs.writeFile(writePath, content, { encoding: 'binary' }, function(err) {
            // TODO handle this as a 500 on our end
            if (err) {
                console.log('Failed to write aasa file to disk: ', err);
                reject({ opensslVerifyFailed: true });
                return;
            }

            // Now the fun part -- actually read the contents of the aasa file and verify they are properly formatted.
            childProcess.exec('openssl smime -verify -inform DER -noverify -in ' + writePath, function(err, stdOut, stderr) {
                if (err) {
                    console.log('Failed to parse aasa file: ', stderr);
                    reject({ opensslVerifyFailed: true });
                }
                else {
                    return _evaluateAASA(stdOut, bundleIdentifier, teamIdentifier, true)
                        .then(resolve)
                        .catch(function() {
                            reject({ opensslVerifyFailed: false, invalidJson: true });
                        });
                }

                // Cleanup. Don't wait for this.
                fs.unlink(writePath);
            });
        });
    });
}

function _checkDomain(domain, bundleIdentifier, teamIdentifier, allowUnencrypted) {
    // Clean up domains, removing scheme and path
    var cleanedDomain = domain.replace(/https?:\/\//, '');
    cleanedDomain = cleanedDomain.replace(/\/.*/, '');

    var fileUrl = 'https://' + cleanedDomain + '/apple-app-site-association';
    var writePath = path.join('tmp-app-files', cleanedDomain);

    return new B(function(resolve, reject) {
        var errorObj = { };

        superagent
            .get(fileUrl)
            .redirects(0)
            .buffer()
            .parse(_parse)
            .end(function(err, res) {
                if (err && !res) {
                    // Unable to resolve DNS name
                    if (err.code == 'ENOTFOUND') {
                        errorObj.badDns = true;
                    }
                    // Doesn't support HTTPS
                    else if (err.code == 'ECONNREFUSED' || /Hostname\/IP doesn't match certificate's altnames/.test(err.message)) {
                        errorObj.badDns = false;
                        errorObj.httpsFailure = true;
                    }
                    else {
                        console.log(err);
                    }

                    reject(errorObj);
                }
                else {
                    errorObj.badDns = false;
                    errorObj.httpsFailure = false;

                    var isEncryptedMimeType = res.headers['content-type'] === 'application/pkcs7-mime';
                    var isJsonMimeType = res.headers['content-type'] === 'application/json' || res.headers['content-type'] === 'text/json';
                    var isJsonTypeOK = allowUnencrypted && isJsonMimeType; // Only ok if both the "allow" flag is true, and... it's a valid type.

                    // Bad server response
                    if (res.status >= 400) {
                        errorObj.serverError = true;

                        reject(errorObj);
                    }
                    // No redirects allowed
                    else if (res.status >= 300) {
                        errorObj.serverError = false;
                        errorObj.redirects = true

                        reject(errorObj);
                    }
                    // Must have content-type of application/pkcs7-mime, or if unencrypted, must be text/json or application/json
                    else if (!isEncryptedMimeType && !isJsonTypeOK) {
                        errorObj.serverError = false;
                        errorObj.redirects = false;
                        errorObj.badContentType = true;

                        reject(errorObj);
                    }
                    else {
                        errorObj.serverError = false;
                        errorObj.redirects = false;
                        errorObj.badContentType = false;

                        if (allowUnencrypted) {
                            // Try to decode the JSON right away (this assumes the file is not encrypted)
                            _evaluateAASA(res.text, bundleIdentifier, teamIdentifier, false)
                                .then(resolve) // Not encrypted, send it back
                                .catch(function() { // Nope, encrypted. Go through the rest of the process
                                    return _writeAASAContentsToDiskAndValidate(writePath, res.text, bundleIdentifier, teamIdentifier)
                                })
                                .then(resolve)
                                .catch(function(err) {
                                    errorObj.opensslVerifyFailed = err.opensslVerifyFailed;
                                    errorObj.invalidJson = err.invalidJson;
                                    reject(errorObj);
                                });
                        }
                        else {
                            _writeAASAContentsToDiskAndValidate(writePath, res.text, bundleIdentifier, teamIdentifier)
                                .then(resolve)
                                .catch(function(err) {
                                    errorObj.opensslVerifyFailed = err.opensslVerifyFailed;
                                    errorObj.invalidJson = err.invalidJson;
                                    reject(errorObj);
                                });
                        }
                    }
                }
            });
    });
}

module.exports = _checkDomain;
<commit_msg>Well this is awkward. Apparently the max standard out buffer for Node is 200kb. Some files, in particular my primary test site (bnc.lt), are much larger than that. Bumping to 1mb now. Wont't fix everything, but it should be sufficient for most.<commit_after>var B = require('bluebird');
var superagent = require('superagent');
var childProcess = require('child_process');
var fs = require('fs');
var path = require('path');

// Override the default behavior of superagent, which encodes to UTF-8.
var _parse = function(res, done) {
    res.text = '';
    res.setEncoding('binary');
    res.on('data', function(chunk) { res.text += chunk; });
    res.on('end', done);
};

function _verifyJsonFormat(aasa) {
    var applinks = aasa.applinks;
    if (!applinks) {
        return false;
    }

    var details = applinks.details;
    if (!details) {
        return false;
    }

    // Domains are an array: [ { appID: '01234567890.com.foo.FooApp', paths: [ '*' ] } ]
    if (details instanceof Array) {
        for (var i = 0; i < details.length; i++) {
            var domain = details[i];
            if (!(typeof domain.appID === 'string' && domain.paths instanceof Array)) {
                return false;
            }
        }
    }
    // Domains are an object: { '01234567890.com.foo.FooApp': { paths: [ '*' ] } }
    else {
        for (var domain in details) {
            if (!(details[domain].paths instanceof Array)) {
                return false;
            }
        }
    }

    return true;
}

function _verifyBundleIdentifierIsPresent(aasa, bundleIdentifier, teamIdentifier) {
    var regexString = bundleIdentifier.replace(/\./g, '\\.') + '$';
    if (teamIdentifier) {
        regexString = teamIdentifier + '\\.' + regexString;
    }

    var identifierRegex = new RegExp(regexString);

    var details = aasa.applinks.details;

    // Domains are an array: [ { appID: '01234567890.com.foo.FooApp', paths: [ '*' ] } ]
    if (details instanceof Array) {
        for (var i = 0; i < details.length; i++) {
            var domain = details[i];
            if (identifierRegex.test(domain.appID) && domain.paths instanceof Array) {
                return true;
            }
        }
    }
    // Domains are an object: { '01234567890.com.foo.FooApp': { paths: [ '*' ] } }
    else {
        for (var domain in details) {
            if (identifierRegex.test(domain) && details[domain].paths instanceof Array) {
                return true;
            }
        }
    }

    return false;
}

function _evaluateAASA(content, bundleIdentifier, teamIdentifier, encrypted) {
    return new B(function(resolve, reject) {
        try {
            var domainAASAValue = JSON.parse(content);

            // Make sure format is good.
            var jsonValidationResult = _verifyJsonFormat(domainAASAValue);

            // Only check bundle identifier if json is good and a bundle identifier to test against is present
            var bundleIdentifierResult;
            if (jsonValidationResult && bundleIdentifier) {
                bundleIdentifierResult =_verifyBundleIdentifierIsPresent(domainAASAValue, bundleIdentifier, teamIdentifier);
            }

            resolve({ encrypted: encrypted, aasa: domainAASAValue, jsonValid: jsonValidationResult, bundleIdentifierFound: bundleIdentifierResult });
        }
        catch (e) {
            reject(e);
        }
    });
}

function _writeAASAContentsToDiskAndValidate(writePath, content, bundleIdentifier, teamIdentifier) {
    return new B(function(resolve, reject) {
        // Write the file to disk. Probably don't actually *need* to do this,
        // but I haven't figured out how to provide it to the process' stdin.
        fs.writeFile(writePath, content, { encoding: 'binary' }, function(err) {
            // TODO handle this as a 500 on our end
            if (err) {
                console.log('Failed to write aasa file to disk: ', err);
                reject({ opensslVerifyFailed: true });
                return;
            }

            // Now the fun part -- actually read the contents of the aasa file and verify they are properly formatted.
            // Note, some people are hosting *TONS* of these items, which results in large stdOut buffer. To make this
            // work for most cases, I've upped the buffer from 200kb default to 1mb. This still won't handle all cases,
            // but I think it'll cover a reasonable amount.
            childProcess.exec('openssl smime -verify -inform DER -noverify -in ' + writePath, { maxBuffer: 1024 * 1024 }, function(err, stdOut, stderr) {
                if (err) {
                    console.log(err);
                    console.log('Failed to parse aasa file: ', stderr);
                    reject({ opensslVerifyFailed: true });
                }
                else {
                    return _evaluateAASA(stdOut, bundleIdentifier, teamIdentifier, true)
                        .then(resolve)
                        .catch(function() {
                            reject({ opensslVerifyFailed: false, invalidJson: true });
                        });
                }

                // Cleanup. Don't wait for this.
                fs.unlink(writePath);
            });
        });
    });
}

function _checkDomain(domain, bundleIdentifier, teamIdentifier, allowUnencrypted) {
    // Clean up domains, removing scheme and path
    var cleanedDomain = domain.replace(/https?:\/\//, '');
    cleanedDomain = cleanedDomain.replace(/\/.*/, '');

    var fileUrl = 'https://' + cleanedDomain + '/apple-app-site-association';
    var writePath = path.join('tmp-app-files', cleanedDomain);

    return new B(function(resolve, reject) {
        var errorObj = { };

        superagent
            .get(fileUrl)
            .redirects(0)
            .buffer()
            .parse(_parse)
            .end(function(err, res) {
                if (err && !res) {
                    // Unable to resolve DNS name
                    if (err.code == 'ENOTFOUND') {
                        errorObj.badDns = true;
                    }
                    // Doesn't support HTTPS
                    else if (err.code == 'ECONNREFUSED' || /Hostname\/IP doesn't match certificate's altnames/.test(err.message)) {
                        errorObj.badDns = false;
                        errorObj.httpsFailure = true;
                    }
                    else {
                        console.log(err);
                    }

                    reject(errorObj);
                }
                else {
                    errorObj.badDns = false;
                    errorObj.httpsFailure = false;

                    var isEncryptedMimeType = res.headers['content-type'] === 'application/pkcs7-mime';
                    var isJsonMimeType = res.headers['content-type'] === 'application/json' || res.headers['content-type'] === 'text/json';
                    var isJsonTypeOK = allowUnencrypted && isJsonMimeType; // Only ok if both the "allow" flag is true, and... it's a valid type.

                    // Bad server response
                    if (res.status >= 400) {
                        errorObj.serverError = true;

                        reject(errorObj);
                    }
                    // No redirects allowed
                    else if (res.status >= 300) {
                        errorObj.serverError = false;
                        errorObj.redirects = true

                        reject(errorObj);
                    }
                    // Must have content-type of application/pkcs7-mime, or if unencrypted, must be text/json or application/json
                    else if (!isEncryptedMimeType && !isJsonTypeOK) {
                        errorObj.serverError = false;
                        errorObj.redirects = false;
                        errorObj.badContentType = true;

                        reject(errorObj);
                    }
                    else {
                        errorObj.serverError = false;
                        errorObj.redirects = false;
                        errorObj.badContentType = false;

                        if (allowUnencrypted) {
                            // Try to decode the JSON right away (this assumes the file is not encrypted)
                            _evaluateAASA(res.text, bundleIdentifier, teamIdentifier, false)
                                .then(resolve) // Not encrypted, send it back
                                .catch(function() { // Nope, encrypted. Go through the rest of the process
                                    return _writeAASAContentsToDiskAndValidate(writePath, res.text, bundleIdentifier, teamIdentifier)
                                })
                                .then(resolve)
                                .catch(function(err) {
                                    errorObj.opensslVerifyFailed = err.opensslVerifyFailed;
                                    errorObj.invalidJson = err.invalidJson;
                                    reject(errorObj);
                                });
                        }
                        else {
                            _writeAASAContentsToDiskAndValidate(writePath, res.text, bundleIdentifier, teamIdentifier)
                                .then(resolve)
                                .catch(function(err) {
                                    errorObj.opensslVerifyFailed = err.opensslVerifyFailed;
                                    errorObj.invalidJson = err.invalidJson;
                                    reject(errorObj);
                                });
                        }
                    }
                }
            });
    });
}

module.exports = _checkDomain;
<|endoftext|>


<commit_before>'use strict';

var d3 = require('d3');
var RtmClient = require('@slack/client').RtmClient;
var CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;

var config = require('./config');

var bot = {
};

var instant = [];
var procs = [];

var start_data = {};
var channelname_data_map = {};
var username_data_map = {};

var token = config.get('token');

//var rtm = new RtmClient(token, {logLevel: 'debug'});
var rtm = new RtmClient(token);
rtm.start();

var dispatcher = d3.dispatch('tick');

d3.rebind(bot, dispatcher, 'on');

var heart_beat = null;

var _constant = function(_) {
  return function(){return _;};
};

var _ask = function(f) {
  var args = (arguments.length === 1?
              [arguments[0]]:
              Array.apply(null, arguments));
  if (typeof f === 'function') {
    instant.push(function(){return f.apply(this, args.slice(1));});
  }
};

bot.say = function(message, channel, cb) {
  var _cb = cb || function(){};
  _ask(
    function(){
      if (channelname_data_map[channel] === void 0)
      {

        return _cb(new Error('unknown channel: ' + channel), null);
      }
      rtm.sendMessage(message,
                      channelname_data_map[channel].id,
                      _cb);
    }
  );
};

var _kill = function()
{
  if (heart_beat == null) {
    return;
  }
  if (arguments.length === 0 || arguments[0] > 0) {
    if (instant.length) {
      setTimeout(_kill, 3000, (arguments[0]-1)||5);
      return;
    }
  }
  dispatcher.on('tick', null);
  rtm.disconnect();
  clearInterval(heart_beat);
  heart_beat = null;
};

bot.kill = _kill;

rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, function (rtmStartData) {
  start_data = rtmStartData;
  start_data.channels.forEach(function(d)
  {
    channelname_data_map[d.name] = d;
  });
  start_data.users.forEach(function(d) {
    username_data_map[d.name] = d;
  });
});

rtm.on(CLIENT_EVENTS.RTM.RTM_CONNECTION_OPENED, function () {
  heart_beat = setInterval(function()
  {
    if (instant.length) {
      setTimeout(instant.shift(1)(), 200);
    }
    dispatcher.tick();
  }, 2000);
});

process.on('exit', function() {
  console.log('killing');
  _kill();
});

module.exports = bot;
<commit_msg>removed console.log<commit_after>'use strict';

var d3 = require('d3');
var RtmClient = require('@slack/client').RtmClient;
var CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;

var config = require('./config');

var bot = {
};

var instant = [];
var procs = [];

var start_data = {};
var channelname_data_map = {};
var username_data_map = {};

var token = config.get('token');

//var rtm = new RtmClient(token, {logLevel: 'debug'});
var rtm = new RtmClient(token);
rtm.start();

var dispatcher = d3.dispatch('tick');

d3.rebind(bot, dispatcher, 'on');

var heart_beat = null;

var _constant = function(_) {
  return function(){return _;};
};

var _ask = function(f) {
  var args = (arguments.length === 1?
              [arguments[0]]:
              Array.apply(null, arguments));
  if (typeof f === 'function') {
    instant.push(function(){return f.apply(this, args.slice(1));});
  }
};

bot.say = function(message, channel, cb) {
  var _cb = cb || function(){};
  _ask(
    function(){
      if (channelname_data_map[channel] === void 0)
      {

        return _cb(new Error('unknown channel: ' + channel), null);
      }
      rtm.sendMessage(message,
                      channelname_data_map[channel].id,
                      _cb);
    }
  );
};

var _kill = function()
{
  if (heart_beat == null) {
    return;
  }
  if (arguments.length === 0 || arguments[0] > 0) {
    if (instant.length) {
      setTimeout(_kill, 3000, (arguments[0]-1)||5);
      return;
    }
  }
  dispatcher.on('tick', null);
  rtm.disconnect();
  clearInterval(heart_beat);
  heart_beat = null;
};

bot.kill = _kill;

rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, function (rtmStartData) {
  start_data = rtmStartData;
  start_data.channels.forEach(function(d)
  {
    channelname_data_map[d.name] = d;
  });
  start_data.users.forEach(function(d) {
    username_data_map[d.name] = d;
  });
});

rtm.on(CLIENT_EVENTS.RTM.RTM_CONNECTION_OPENED, function () {
  heart_beat = setInterval(function()
  {
    if (instant.length) {
      setTimeout(instant.shift(1)(), 200);
    }
    dispatcher.tick();
  }, 2000);
});

process.on('exit', function() {
  _kill();
});

module.exports = bot;
<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.
if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFil<commit_msg>Update character<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.
if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile<|endoftext|>