<commit_before>'use strict';

var _ = require('lodash');
var path = require('path');
var fs = require('fs');
var crypto = require('crypto');
var moment = require('moment');

var iconv = require('iconv-lite');
var request = require('request');

var Promise = require('bluebird');
var NodeRSA = require('node-rsa');

var ALIPAY_GATEWAY = 'https://openapi.alipay.com/gateway.do';

function createPromiseCallback() {
    var cb;
    var promise = new Promise(function (resolve, reject) {
        cb = function (err, data) {
            if (err) return reject(err);
            return resolve(data);
        };
    });
    cb.promise = promise;
    return cb;
};

// 除去数组中的空值和签名参数
var paramsFilter = function (params) {
    var result = {};
    if (!params) {
        return result;
    }
    for (var k in params) {
        if (!params[k] || params[k] === '' || k === 'sign') {
            continue;
        }
        result[k] = params[k];
    }
    return result;
};

// 将所有参数按照“参数=参数值”的模式用“&”字符拼接成字符串
var toQueryString = function (params) {
    var result = '';
    var sortKeys = Object.keys(params).sort();
    for (var i in sortKeys) {
        result += sortKeys[i] + '=' + params[sortKeys[i]] + '&';
    }
    if (result.length > 0) {
        return result.slice(0, -1);
    } else {
        return result;
    }
};

var Alipay = function (options) {
    this._options = options;
    return this;
};

Alipay.prototype._encryptedParams = function (params) {
    var qs = toQueryString(paramsFilter(params));
    var key = new NodeRSA(fs.readFileSync(this._options.alipay_public_key), {
        encryptionScheme: 'pkcs1'
    });
    var encrypted = key.encrypt(qs, 'base64');
    return encrypted;
};

Alipay.prototype._decryptedParams = function (toDecrypt) {
    var key = new NodeRSA(fs.readFileSync(this._options.private_key), {
        encryptionScheme: 'pkcs1'
    });
    var decrypted = key.decrypt(toDecrypt, 'utf8');
    return decrypted;
};

Alipay.prototype._generateSign = function (params) {
    var qs = toQueryString(paramsFilter(params));
    var signed = crypto.createSign('RSA-SHA1').update(new Buffer(qs, 'utf8')).sign(fs.readFileSync(this._options.private_key), 'base64');
    return signed;
};

Alipay.prototype._verifySign = function (params, signature) {
    var qs = toQueryString(paramsFilter(params));
    var verified = crypto.createVerify('RSA-SHA1').update(new Buffer(qs, 'utf8')).verify(fs.readFileSync(this._options.alipay_public_key), signature, 'base64');
    return verified;
};

Alipay.prototype.getAccessToken = function (code, cb) {
    cb = cb || createPromiseCallback();

    var self = this;

    var params = {
        app_id: self._options.app_id,
        method: 'alipay.system.oauth.token',
        format: 'JSON',
        charset: 'gbk',
        sign_type: 'RSA',
        timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
        version: '1.0',
        grant_type: 'authorization_code',
        code: code
    };
    params.sign = self._generateSign(params);

    request({
        url: ALIPAY_GATEWAY,
        method: 'POST',
        form: params
    }, function (err, response, body) {
        if (err) {
            cb(err)
        } else {
            var data = JSON.parse(iconv.decode(body, 'GBK'));
            if (data.error_response) {
                cb(new Error(data.error_response.msg));
            } else if (!data.alipay_system_oauth_token_response) {
                cb(new Error('Invalid Arguments'));
            } else {
                cb(null, data.alipay_system_oauth_token_response);
            }
        }
    });

    return cb.promise;
};

Alipay.prototype.getUser = function (token, cb) {
    cb = cb || createPromiseCallback();

    var self = this;

    var params = {
        app_id: self._options.app_id,
        method: 'alipay.user.info.share',
        format: 'JSON',
        charset: 'gbk',
        sign_type: 'RSA',
        timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
        version: '1.0',
        auth_token: token
    };
    params.sign = self._generateSign(params);

    request({
        url: ALIPAY_GATEWAY,
        method: 'POST',
        form: params,
        encoding: null
    }, function (err, response, body) {
        if (err) {
            cb(err)
        } else {
            var data = JSON.parse(iconv.decode(body, 'GBK'));
            if (data.error_response) {
                cb(new Error(data.error_response.msg));
            } else if (!data.alipay_user_info_share_response) {
                cb(new Error('Invalid Arguments'));
            } else {
                cb(null, data.alipay_user_info_share_response);
            }
        }
    });

    return cb.promise;
};

module.exports = Alipay;
<commit_msg>Resolve the issue of encoding of get access token response.<commit_after>'use strict';

var _ = require('lodash');
var path = require('path');
var fs = require('fs');
var crypto = require('crypto');
var moment = require('moment');

var iconv = require('iconv-lite');
var request = require('request');

var Promise = require('bluebird');
var NodeRSA = require('node-rsa');

var ALIPAY_GATEWAY = 'https://openapi.alipay.com/gateway.do';

function createPromiseCallback() {
    var cb;
    var promise = new Promise(function (resolve, reject) {
        cb = function (err, data) {
            if (err) return reject(err);
            return resolve(data);
        };
    });
    cb.promise = promise;
    return cb;
};

// 除去数组中的空值和签名参数
var paramsFilter = function (params) {
    var result = {};
    if (!params) {
        return result;
    }
    for (var k in params) {
        if (!params[k] || params[k] === '' || k === 'sign') {
            continue;
        }
        result[k] = params[k];
    }
    return result;
};

// 将所有参数按照“参数=参数值”的模式用“&”字符拼接成字符串
var toQueryString = function (params) {
    var result = '';
    var sortKeys = Object.keys(params).sort();
    for (var i in sortKeys) {
        result += sortKeys[i] + '=' + params[sortKeys[i]] + '&';
    }
    if (result.length > 0) {
        return result.slice(0, -1);
    } else {
        return result;
    }
};

var Alipay = function (options) {
    this._options = options;
    return this;
};

Alipay.prototype._encryptedParams = function (params) {
    var qs = toQueryString(paramsFilter(params));
    var key = new NodeRSA(fs.readFileSync(this._options.alipay_public_key), {
        encryptionScheme: 'pkcs1'
    });
    var encrypted = key.encrypt(qs, 'base64');
    return encrypted;
};

Alipay.prototype._decryptedParams = function (toDecrypt) {
    var key = new NodeRSA(fs.readFileSync(this._options.private_key), {
        encryptionScheme: 'pkcs1'
    });
    var decrypted = key.decrypt(toDecrypt, 'utf8');
    return decrypted;
};

Alipay.prototype._generateSign = function (params) {
    var qs = toQueryString(paramsFilter(params));
    var signed = crypto.createSign('RSA-SHA1').update(new Buffer(qs, 'utf8')).sign(fs.readFileSync(this._options.private_key), 'base64');
    return signed;
};

Alipay.prototype._verifySign = function (params, signature) {
    var qs = toQueryString(paramsFilter(params));
    var verified = crypto.createVerify('RSA-SHA1').update(new Buffer(qs, 'utf8')).verify(fs.readFileSync(this._options.alipay_public_key), signature, 'base64');
    return verified;
};

Alipay.prototype.getAccessToken = function (code, cb) {
    cb = cb || createPromiseCallback();

    var self = this;

    var params = {
        app_id: self._options.app_id,
        method: 'alipay.system.oauth.token',
        format: 'JSON',
        charset: 'gbk',
        sign_type: 'RSA',
        timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
        version: '1.0',
        grant_type: 'authorization_code',
        code: code
    };
    params.sign = self._generateSign(params);

    request({
        url: ALIPAY_GATEWAY,
        method: 'POST',
        form: params,
        encoding: null
    }, function (err, response, body) {
        if (err) {
            cb(err)
        } else {
            var data = JSON.parse(iconv.decode(body, 'GBK'));
            if (data.error_response) {
                cb(new Error(data.error_response.msg));
            } else if (!data.alipay_system_oauth_token_response) {
                cb(new Error('Invalid Arguments'));
            } else {
                cb(null, data.alipay_system_oauth_token_response);
            }
        }
    });

    return cb.promise;
};

Alipay.prototype.getUser = function (token, cb) {
    cb = cb || createPromiseCallback();

    var self = this;

    var params = {
        app_id: self._options.app_id,
        method: 'alipay.user.info.share',
        format: 'JSON',
        charset: 'gbk',
        sign_type: 'RSA',
        timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
        version: '1.0',
        auth_token: token
    };
    params.sign = self._generateSign(params);

    request({
        url: ALIPAY_GATEWAY,
        method: 'POST',
        form: params,
        encoding: null
    }, function (err, response, body) {
        if (err) {
            cb(err)
        } else {
            var data = JSON.parse(iconv.decode(body, 'GBK'));
            if (data.error_response) {
                cb(new Error(data.error_response.msg));
            } else if (!data.alipay_user_info_share_response) {
                cb(new Error('Invalid Arguments'));
            } else {
                cb(null, data.alipay_user_info_share_response);
            }
        }
    });

    return cb.promise;
};

module.exports = Alipay;
<|endoftext|>


<commit_before>import _ from 'lodash';
import log from './logger';
import { BaseDriver } from 'appium-base-driver';
import { FakeDriver } from 'appium-fake-driver';
import { AndroidDriver } from 'appium-android-driver';
import { IosDriver } from 'appium-ios-driver';
import { SelendroidDriver } from 'appium-selendroid-driver';
import { routeConfiguringFunction, errors,
         isSessionCommand } from 'mobile-json-wire-protocol';
import B from 'bluebird';

class AppiumDriver extends BaseDriver {
  constructor (args) {
    super();
    this.args = args;

    this.sessions = {};
  }

  sessionExists (sessionId) {
    return _.contains(_.keys(this.sessions), sessionId) &&
           this.sessions[sessionId].sessionId !== null;
  }

  driverForSession (sessionId) {
    return this.sessions[sessionId];
  }

  getDriverForCaps (caps) {
    // TODO if this logic ever becomes complex, should probably factor out
    // into its own file
    if (!caps.platformName || !_.isString(caps.platformName)) {
      throw new Error("You must include a platformName capability");
    }

    // we don't necessarily have an `automationName` capability,
    // but if we do and it is 'Selendroid', act on it
    if ((caps.automationName || '').toLowerCase() === 'selendroid') {
      return SelendroidDriver;
    }

    if (caps.platformName.toLowerCase() === "fake") {
      return FakeDriver;
    }

    if (caps.platformName.toLowerCase() === 'android') {
      return AndroidDriver;
    }

    if (caps.platformName.toLowerCase() === 'ios') {
      return IosDriver;
    }

    let msg;
    if (caps.automationName) {
      msg = `Could not find a driver for automationName '${caps.automationName}' and platformName ` +
            `'${caps.platformName}'.`;
    } else {
      msg = `Could not find a driver for platformName '${caps.platformName}'.`;
    }
    throw new Error(`${msg} Please check your desired capabilities.`);
  }

  async getStatus () {
  }

  async getSessions () {
    let sessions = [];
    for (let [id, driver] of _.pairs(this.sessions)) {
      sessions.push({id: id, capabilities: driver.caps});
    }
    return sessions;
  }

  async createSession (caps, reqCaps) {
    caps = _.defaults(_.clone(caps), this.args.defaultCapabilities);
    let InnerDriver = this.getDriverForCaps(caps);
    let curSessions;
    log.info(`Creating new ${InnerDriver.name} session`);
    try {
      curSessions = this.curSessionDataForDriver(InnerDriver);
    } catch (e) {
      throw new errors.SessionNotCreatedError(e.message);
    }
    let d = new InnerDriver(this.args);
    let [innerSessionId, dCaps] = await d.createSession(caps, reqCaps, curSessions);
    this.sessions[innerSessionId] = d;

    // Remove the session on unexpected shutdown, so that we are in a position
    // to open another session later on.
    // TODO: this should be removed and replaced by a onShutdown callback.
    d.onUnexpectedShutdown
      .then(() => { throw new Error('Unexpected shutdown'); })
      .catch(B.CancellationError, () => {})
      .catch((err) => {
        log.warn('Closing session, cause was', err.message);
        delete this.sessions[innerSessionId];
      }).done();

    log.info(`New ${InnerDriver.name} session created successfully, session ` +
             `${innerSessionId} added to master session list`);
    return [innerSessionId, dCaps];
  }

   curSessionDataForDriver (InnerDriver) {
    let data = _.values(this.sessions)
                .filter(s => s.constructor.name === InnerDriver.name)
                .map(s => s.driverData);
    for (let d of data) {
      if (!d) {
        throw new Error(`Problem getting session data for driver type ` +
                        `${InnerDriver.name}; does it implement 'get ` +
                        `driverData'?`);
      }
    }
    return data;
   }

  async deleteSession (sessionId) {
    try {
      if (this.sessions[sessionId]) {
        await this.sessions[sessionId].deleteSession();
      }
    } catch (e) {
      log.error(`Had trouble ending session ${sessionId}: ${e.message}`);
      throw e;
    } finally {
      // regardless of whether the deleteSession completes successfully or not
      // make the session unavailable, because who knows what state it might
      // be in otherwise
      log.info(`Removing session ${sessionId} from our master session list`);
      delete this.sessions[sessionId];
    }
  }

  async executeCommand (cmd, ...args) {
    if (isAppiumDriverCommand(cmd)) {
      return super.executeCommand(cmd, ...args);
    }

    // since we don't call super.executeCommand, we need
    // to clear the appium driver timeout manually
    this.clearNewCommandTimeout();
    let sessionId = args[args.length - 1];
    return this.sessions[sessionId].executeCommand(cmd, ...args);
  }

  proxyActive (sessionId) {
    return this.sessions[sessionId].proxyActive(sessionId);
  }

  getProxyAvoidList (sessionId) {
    return this.sessions[sessionId].getProxyAvoidList();
  }

  canProxy (sessionId) {
    return this.sessions[sessionId].canProxy(sessionId);
  }
}

// help decide which commands should be proxied to sub-drivers and which
// should be handled by this, our umbrella driver
function isAppiumDriverCommand (cmd) {
  return !isSessionCommand(cmd) || cmd === "deleteSession";
}

function getAppiumRouter (args) {
  let appium = new AppiumDriver(args);
  return routeConfiguringFunction(appium);
}

export { AppiumDriver, getAppiumRouter };
<commit_msg>Fix proxy handling<commit_after>import _ from 'lodash';
import log from './logger';
import { BaseDriver } from 'appium-base-driver';
import { FakeDriver } from 'appium-fake-driver';
import { AndroidDriver } from 'appium-android-driver';
import { IosDriver } from 'appium-ios-driver';
import { SelendroidDriver } from 'appium-selendroid-driver';
import { routeConfiguringFunction, errors,
         isSessionCommand } from 'mobile-json-wire-protocol';
import B from 'bluebird';

class AppiumDriver extends BaseDriver {
  constructor (args) {
    super();
    this.args = args;

    this.sessions = {};
  }

  sessionExists (sessionId) {
    return _.contains(_.keys(this.sessions), sessionId) &&
           this.sessions[sessionId].sessionId !== null;
  }

  driverForSession (sessionId) {
    return this.sessions[sessionId];
  }

  getDriverForCaps (caps) {
    // TODO if this logic ever becomes complex, should probably factor out
    // into its own file
    if (!caps.platformName || !_.isString(caps.platformName)) {
      throw new Error("You must include a platformName capability");
    }

    // we don't necessarily have an `automationName` capability,
    // but if we do and it is 'Selendroid', act on it
    if ((caps.automationName || '').toLowerCase() === 'selendroid') {
      return SelendroidDriver;
    }

    if (caps.platformName.toLowerCase() === "fake") {
      return FakeDriver;
    }

    if (caps.platformName.toLowerCase() === 'android') {
      return AndroidDriver;
    }

    if (caps.platformName.toLowerCase() === 'ios') {
      return IosDriver;
    }

    let msg;
    if (caps.automationName) {
      msg = `Could not find a driver for automationName '${caps.automationName}' and platformName ` +
            `'${caps.platformName}'.`;
    } else {
      msg = `Could not find a driver for platformName '${caps.platformName}'.`;
    }
    throw new Error(`${msg} Please check your desired capabilities.`);
  }

  async getStatus () {
  }

  async getSessions () {
    let sessions = [];
    for (let [id, driver] of _.pairs(this.sessions)) {
      sessions.push({id: id, capabilities: driver.caps});
    }
    return sessions;
  }

  async createSession (caps, reqCaps) {
    caps = _.defaults(_.clone(caps), this.args.defaultCapabilities);
    let InnerDriver = this.getDriverForCaps(caps);
    let curSessions;
    log.info(`Creating new ${InnerDriver.name} session`);
    try {
      curSessions = this.curSessionDataForDriver(InnerDriver);
    } catch (e) {
      throw new errors.SessionNotCreatedError(e.message);
    }
    let d = new InnerDriver(this.args);
    let [innerSessionId, dCaps] = await d.createSession(caps, reqCaps, curSessions);
    this.sessions[innerSessionId] = d;

    // Remove the session on unexpected shutdown, so that we are in a position
    // to open another session later on.
    // TODO: this should be removed and replaced by a onShutdown callback.
    d.onUnexpectedShutdown
      .then(() => { throw new Error('Unexpected shutdown'); })
      .catch(B.CancellationError, () => {})
      .catch((err) => {
        log.warn('Closing session, cause was', err.message);
        delete this.sessions[innerSessionId];
      }).done();

    log.info(`New ${InnerDriver.name} session created successfully, session ` +
             `${innerSessionId} added to master session list`);
    return [innerSessionId, dCaps];
  }

   curSessionDataForDriver (InnerDriver) {
    let data = _.values(this.sessions)
                .filter(s => s.constructor.name === InnerDriver.name)
                .map(s => s.driverData);
    for (let d of data) {
      if (!d) {
        throw new Error(`Problem getting session data for driver type ` +
                        `${InnerDriver.name}; does it implement 'get ` +
                        `driverData'?`);
      }
    }
    return data;
   }

  async deleteSession (sessionId) {
    try {
      if (this.sessions[sessionId]) {
        await this.sessions[sessionId].deleteSession();
      }
    } catch (e) {
      log.error(`Had trouble ending session ${sessionId}: ${e.message}`);
      throw e;
    } finally {
      // regardless of whether the deleteSession completes successfully or not
      // make the session unavailable, because who knows what state it might
      // be in otherwise
      log.info(`Removing session ${sessionId} from our master session list`);
      delete this.sessions[sessionId];
    }
  }

  async executeCommand (cmd, ...args) {
    if (isAppiumDriverCommand(cmd)) {
      return super.executeCommand(cmd, ...args);
    }

    // since we don't call super.executeCommand, we need
    // to clear the appium driver timeout manually
    this.clearNewCommandTimeout();
    let sessionId = args[args.length - 1];
    return this.sessions[sessionId].executeCommand(cmd, ...args);
  }

  proxyActive (sessionId) {
    return this.sessions[sessionId] &&
           _.isFunction(this.sessions[sessionId].proxyActive) &&
           this.sessions[sessionId].proxyActive(sessionId);
  }

  getProxyAvoidList (sessionId) {
    if (!this.sessions[sessionId]) {
      return [];
    }
    return this.sessions[sessionId].getProxyAvoidList();
  }

  canProxy (sessionId) {
    return this.sessions[sessionId] && this.sessions[sessionId].canProxy(sessionId);
  }
}

// help decide which commands should be proxied to sub-drivers and which
// should be handled by this, our umbrella driver
function isAppiumDriverCommand (cmd) {
  return !isSessionCommand(cmd) || cmd === "deleteSession";
}

function getAppiumRouter (args) {
  let appium = new AppiumDriver(args);
  return routeConfiguringFunction(appium);
}

export { AppiumDriver, getAppiumRouter };
<|endoftext|>


<commit_before>// assert.coffee -- extended asserts
//
// Copyright 2016 fuzzy.ai <evan@fuzzy.ai>
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/* jshint esversion: 6 */

import assert from 'assert';

import _ from 'lodash';

let me = module.exports;

// Copy everything from assert module to this module

_.assign(me, assert);

// Extend this module with some extra utilities

me.epsilon = function(eps, actual, expected, message) {
  me.isNumber(eps);
  me.isNumber(actual);
  me.isNumber(expected);
  return me.lesser(Math.abs(actual - expected), eps);
};

me.match = function(actual, expected, message) {
  assert(_.isRegExp(expected), `${expected} must be a regular expression`);
  return assert(expected.test(actual),
    message || `${actual} does not match ${expected}`);
};

me.matches = me.match;

me.isTrue = (actual, message) => assert(actual === true, message || "Argument must be true");

me.isFalse = (actual, message) => assert(actual === false, message || "Argument must be false");

me.isZero = (actual, message) => assert.equal(actual, 0, message || "Argument must be zero");

me.isNotZero = (actual, message) => assert.notEqual(actual, 0, message || "Argument must not be zero");

me.greater = (actual, expected, message) =>
  assert(actual > expected,
    message || `${actual} is not greater than ${expected}`)
;

me.lesser = (actual, expected, message) =>
  assert(actual < expected,
    message || `${actual} is not less than ${expected}`)
;

me.inDelta = (actual, expected, delta, message) =>
  assert(Math.abs(actual - expected) <= delta,
    message || `${actual} is not greater than ${expected}`)
;

me.include = (actual, expected, message) =>
  assert(_.hasIn(actual, expected),
    message || `${actual} does not contain ${expected}`)
;

me.includes = me.include;

me.notInclude = (actual, expected, message) =>
  assert(!_.hasIn(actual, expected),
    message || `${actual} contains ${expected}`)
;

me.notIncludes = me.notInclude;

// FIXME: figure out include/deepInclude

me.deepInclude = me.include;

me.deepIncludes = me.deepInclude;

me.isEmpty = (actual, message) => assert(_.isEmpty(actual), message || `${actual} is not empty`);

me.isNotEmpty = (actual, message) => assert(!_.isEmpty(actual),  message || `${actual} is empty`);

me.lengthOf = function(actual, expected, message) {
  assert(actual !== null);
  me.include(actual, "length");
  return assert.equal(actual.length, expected,
    `Length is ${actual.length} not ${expected}`);
};

me.isArray = (actual, message) => assert(_.isArray(actual), message || "Argument is not an array");

me.isObject = (actual, message) => assert(_.isObject(actual), message || "Argument must be an object");

me.isNumber = (actual, message) => assert(_.isNumber(actual), message || "Argument must be a number");

me.isBoolean = (actual, message) => assert(_.isBoolean(actual), message || "Argument must be a boolean");

me.isNaN = (actual, message) => assert(_.isNaN(actual), message || "Argument must be NaN");

me.isNull = (actual, message) => assert(_.isNull(actual), message || "Argument must be null");

me.isNotNull = (actual, message) => assert(!_.isNull(actual), message || "Argument must not be null");

me.isUndefined = (actual, message) => assert(_.isUndefined(actual), message || "Argument must be undefined");

me.isDefined = (actual, message) => assert(!_.isUndefined(actual), message || "Argument must be defined");

me.isString = (actual, message) => assert(_.isString(actual), message || "Argument must be a string");

me.isFunction = (actual, message) => assert(_.isFunction(actual), message || "Argument must be a function");

me.typeOf = (actual, expected, message) =>
  assert(typeof(actual) === expected,
   message || `Argument is not of type ${expected}`)
;

me.instanceOf = (actual, expected, message) =>
  assert(actual instanceof expected,
    message || `Argument is not an instance of ${expected}`)
;
<commit_msg>Line wrapping in assert.js<commit_after>// assert.coffee -- extended asserts
//
// Copyright 2016 fuzzy.ai <evan@fuzzy.ai>
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/* jshint esversion: 6 */

import assert from 'assert';

import _ from 'lodash';

let me = module.exports;

// Copy everything from assert module to this module

_.assign(me, assert);

// Extend this module with some extra utilities

me.epsilon = function(eps, actual, expected, message) {
  me.isNumber(eps);
  me.isNumber(actual);
  me.isNumber(expected);
  return me.lesser(Math.abs(actual - expected), eps);
};

me.match = function(actual, expected, message) {
  assert(_.isRegExp(expected), `${expected} must be a regular expression`);
  return assert(expected.test(actual),
    message || `${actual} does not match ${expected}`);
};

me.matches = me.match;

me.isTrue = (actual, message) =>
  assert(actual === true, message || "Argument must be true");

me.isFalse = (actual, message) =>
  assert(actual === false, message || "Argument must be false");

me.isZero = (actual, message) =>
  assert.equal(actual, 0, message || "Argument must be zero");

me.isNotZero = (actual, message) =>
  assert.notEqual(actual, 0, message || "Argument must not be zero");

me.greater = (actual, expected, message) =>
  assert(actual > expected,
    message || `${actual} is not greater than ${expected}`)
;

me.lesser = (actual, expected, message) =>
  assert(actual < expected,
    message || `${actual} is not less than ${expected}`)
;

me.inDelta = (actual, expected, delta, message) =>
  assert(Math.abs(actual - expected) <= delta,
    message || `${actual} is not greater than ${expected}`)
;

me.include = (actual, expected, message) =>
  assert(_.hasIn(actual, expected),
    message || `${actual} does not contain ${expected}`)
;

me.includes = me.include;

me.notInclude = (actual, expected, message) =>
  assert(!_.hasIn(actual, expected),
    message || `${actual} contains ${expected}`)
;

me.notIncludes = me.notInclude;

// FIXME: figure out include/deepInclude

me.deepInclude = me.include;

me.deepIncludes = me.deepInclude;

me.isEmpty = (actual, message) =>
  assert(_.isEmpty(actual), message || `${actual} is not empty`);

me.isNotEmpty = (actual, message) =>
  assert(!_.isEmpty(actual),  message || `${actual} is empty`);

me.lengthOf = function(actual, expected, message) {
  assert(actual !== null);
  me.include(actual, "length");
  return assert.equal(actual.length, expected,
    `Length is ${actual.length} not ${expected}`);
};

me.isArray = (actual, message) =>
  assert(_.isArray(actual), message || "Argument is not an array");

me.isObject = (actual, message) =>
  assert(_.isObject(actual), message || "Argument must be an object");

me.isNumber = (actual, message) =>
  assert(_.isNumber(actual), message || "Argument must be a number");

me.isBoolean = (actual, message) =>
  assert(_.isBoolean(actual), message || "Argument must be a boolean");

me.isNaN = (actual, message) =>
  assert(_.isNaN(actual), message || "Argument must be NaN");

me.isNull = (actual, message) =>
  assert(_.isNull(actual), message || "Argument must be null");

me.isNotNull = (actual, message) =>
  assert(!_.isNull(actual), message || "Argument must not be null");

me.isUndefined = (actual, message) =>
  assert(_.isUndefined(actual), message || "Argument must be undefined");

me.isDefined = (actual, message) =>
  assert(!_.isUndefined(actual), message || "Argument must be defined");

me.isString = (actual, message) =>
  assert(_.isString(actual), message || "Argument must be a string");

me.isFunction = (actual, message) =>
  assert(_.isFunction(actual), message || "Argument must be a function");

me.typeOf = (actual, expected, message) =>
  assert(typeof(actual) === expected,
   message || `Argument is not of type ${expected}`)
;

me.instanceOf = (actual, expected, message) =>
  assert(actual instanceof expected,
    message || `Argument is not an instance of ${expected}`)
;
<|endoftext|>


<commit_before>/*jshint white: false, node: true, vars: true, indent: 4 */
(function (module, __dirname) {
    "use strict";
    var path = require('path'),
        templates = path.join(__dirname, "../", "templates");

    module.exports = {

        "scripts": ["socket.io/socket.io.js"],
        "trailingScripts":
            ["js/libs/underscore/underscore-1.4.4.js",
            "js/libs/jquery/jquery-1.9.1.js",
            "js/libs/backbone/backbone-1.0.0.js",
            "js/app-utils.js",
            "js/app-starter.js",
            "js/app-store.js",
            "js/app-middle.js",
            "js/app-backbone.js",
            "js/app-container.js",
            "js/app-async.js"],
        "metas": [
            {
                "name": "HandheldFriendly",
                "content": "True"
            },
            {
                "name": "viewport",
                "content": "width=device-width,initial-scale=1.0,maximum-scale=1.0"
            },
            {
                "name": "apple-mobile-web-app-capable",
                "content": "yes"
            },
            {
                "name": "apple-mobile-web-app-status-bar-style",
                "content": "black"
            }
        ],
        "htmlFiles":
            [
                path.join(templates, "container.html")
            ],
        "links": [
            {
                "rel": "apple-touch-startup-image",
                "href": "startup.png"
            }
        ],
        "useRequireJS": false

    };
})(module, __dirname);
<commit_msg>drm WIP<commit_after>/*jshint white: false, node: true, vars: true, indent: 4 */
(function (module, __dirname) {
    "use strict";
    var path = require('path'),
        templates = path.join(__dirname, "../", "templates");

    module.exports = {

        "scripts": ["socket.io/socket.io.js"],
        "trailingScripts":
            ["js/libs/underscore/underscore-1.4.4.js",
            "js/libs/jquery/jquery-1.9.1.js",
            "js/libs/backbone/backbone-1.0.0.js",
            "js/app-utils.js",
            "js/app-starter.js",
            "js/app-store.js",
            "js/app-middle.js",
            "js/app-backbone.js",
            "js/app-container.js"],
        "metas": [
            {
                "name": "HandheldFriendly",
                "content": "True"
            },
            {
                "name": "viewport",
                "content": "width=device-width,initial-scale=1.0,maximum-scale=1.0"
            },
            {
                "name": "apple-mobile-web-app-capable",
                "content": "yes"
            },
            {
                "name": "apple-mobile-web-app-status-bar-style",
                "content": "black"
            }
        ],
        "htmlFiles":
            [
                path.join(templates, "container.html")
            ],
        "links": [
            {
                "rel": "apple-touch-startup-image",
                "href": "startup.png"
            }
        ],
        "useRequireJS": false

    };
})(module, __dirname);
<|endoftext|>


<commit_before>'use strict';
var express = require('express');
var path = require('path');
var fs = require('fs');
var clc = require('cli-color');
var log4js = require('log4js');
var redis = require('redis');
var lxHelpers = require('lx-helpers');
var RedisSessionStore = require('connect-redis')(express);

module.exports = function (rootPath) {
    var notice = clc.cyan;
    var middleware = {};
    var config = require('./config')(rootPath, notice);
    var logging = require('./logging')(config);
    var syslog = logging.syslog;
    var mail = require('./mail')(config);
    var rights = require('./rights')(config, logging);
    var settings = require('./settings')(config, logging, rights);
    var app = express();
    var baboonErrors = require('./errors');

    ///////////////////////////////////////////
    // baboon
    ///////////////////////////////////////////

    var baboon = {
        middleware: middleware,
        config: config,
        rights: rights,
        logging: logging,
        mail: mail,
        settings: settings,
        server: {
            app: app
        }
    };

    // register Errors in baboon
    lxHelpers.forEach(baboonErrors, function (value, key) {
        baboon[key] = value;
    });

    var api = require(config.path.api)(baboon);

    ///////////////////////////////////////////
    // redis server
    ///////////////////////////////////////////
    var redisClient = redis.createClient(config.redis.server1.port, config.redis.server1.host);
    var sessionStore = new RedisSessionStore({
        client: redisClient,
        ttl: config.sessionMaxLife
    });
    var RedisSocketStore = require('socket.io/lib/stores/redis');
    var pub = redis.createClient(config.redis.server1.port, config.redis.server1.host);
    var sub = redis.createClient(config.redis.server1.port, config.redis.server1.host);

    redisClient.on('error', function (err) {
        var msg = 'error event - ' + redisClient.host + ':' + redisClient.port + ' - ' + err;

        syslog.error(msg);
        throw new Error(msg);
    });

    ///////////////////////////////////////////
    // config server
    ///////////////////////////////////////////

    // set log level for syslog logger
    syslog.setLevel(config.logging.syslog);

    // set log level for syslog logger
    logging.audit.setLevel(config.logging.audit);

    var server;

    // setup server to https or http from config protocol
    if (config.protocol === 'https') {
        var https = require('https'),
            serverOptions = {
                key: fs.readFileSync(path.join(rootPath, 'server', 'ssl', 'ssl.key')),
                cert: fs.readFileSync(path.join(rootPath, 'server', 'ssl', 'ssl.crt'))
            };

        server = https.createServer(serverOptions, app);
    } else if (config.protocol === 'http') {
        var http = require('http');

        server = http.createServer(app);
    } else {
        var msg = 'error server config - missing or wrong protocol' + config.protocol;

        syslog.error(msg);
        throw new Error(msg);
    }

    var io = require('socket.io').listen(server);
    baboon.server.sio = io;

    ///////////////////////////////////////////
    // Middleware
    ///////////////////////////////////////////

    middleware.errorHandler = require('./middleware/errorHandler')(syslog);
    middleware.session = require('./middleware/session')(baboon);
    middleware.nav = require('./middleware/nav')(baboon);
    middleware.auth = require('./middleware/auth')(baboon);

    ///////////////////////////////////////////
    // start server
    ///////////////////////////////////////////

    baboon.server.start = function () {
        var startOn = 'application server has been started on: ' + config.protocol + '://' + config.host + ':' + config.port,
            startMode = 'application server has been started in ' + config.node_env + ' mode';

        server.listen(app.get('port'), function () {
            syslog.info(startOn);

            if (config.node_env !== 'production') {
                syslog.warn(startMode);
            } else {
                syslog.info(startMode);
                console.log(
                    notice('   info  - ') + startOn + '\n' +
                        notice('   info  - ') + startMode + '\n' +
                        notice('   info  - ') + 'write all entries to logfile...');
            }
        });
    };

    ///////////////////////////////////////////
    // View Engine EJS
    ///////////////////////////////////////////

    // view engine for application
    app.engine('.html', require('ejs').__express);

    ///////////////////////////////////////////
    // Init all app controllers
    ///////////////////////////////////////////

    var controllers = api.initAppControllers();

    ///////////////////////////////////////////
    // Express
    ///////////////////////////////////////////

    // express default config
    var expressConfig = function () {
        app.set('port', config.port);
        app.set('views', config.path.dist + '/app');
        app.set('view engine', 'html');

        // set log level for syslog logger
        logging.express.setLevel(config.logging.express);

        // logging
        if (config.node_env === 'production') {
            app.use(log4js.connectLogger(logging.express, {level: 'auto'}));
        } else {
            app.use(log4js.connectLogger(logging.express, {level: 'auto', format: ':status :method :url'}));
        }

        app.use(express.favicon(config.path.public + '/favicon.ico'));
        app.use(express.compress());
        app.use(express.static(config.path.public));
        app.use(express.json());
        app.use(express.urlencoded());
        app.use(express.methodOverride());
        app.use(express.cookieParser());

        // Session has session cookie with expires:false.
        // Session is only destroyed when the user closes the browser.
        // Redis ttl is maximal lifetime of session, after this time session is destroyed
        // Middleware checks the inactive period of the session by user.
        // When this period is over, the session destroyed.
        app.use(express.session({
            key: config.sessionKey,
            store: sessionStore,
            secret: config.sessionSecret,
            cookie: {expires: false}
        }));

        // routing
        app.use(app.router);

        // restricted api
        app.use('/api/v1', middleware.auth.restrictedApi);

        // Catch all other rest api requests and forward to controller
        app.use('/api/v1', function (req, res) {
            // remove trailing slash
            var route = req.url.substring(1);
            var parsedRoute = api.parseRoute(route);

            // check if user has access to route
            if (rights.userHasAccessTo(req.session.user, route)) {
                var data = req.body;

                // create request object for controller
                var request = {
                    /**
                     * Returns the current session.
                     *
                     * @param {!function(error, result)} callback The callback.
                     */
                    getSession: function (callback) {
                        callback(null, req.session);
                    },
                    /**
                     * Sets the session.
                     *
                     * @param {!Object} session The session object.
                     * @param {function(error, result)=} callback The callback.
                     */
                    setSession: function (session, callback) {
                        if (!lxHelpers.isObject(session)) {
                            var error = lxHelpers.getTypeError('session', session, {});
                            syslog.error(error);

                            if (callback) {
                                callback(error);
                            }

                            return;
                        }

                        if (callback) {
                            callback(null, true);
                        }
                    }
                };

                if (controllers[parsedRoute.controllerFullPath]) {
                    controllers[parsedRoute.controllerFullPath][parsedRoute.action](data, request, function (error, result) {
                        res.send({error: api.parseError(error, data), data: result});
                    });
                } else {
                    res.json(403, 'Wrong url');
                }
            } else {
                res.json(403, 'Access denied.');
            }
        });

        // restricted route
        app.use(middleware.auth.restrictedRoute);

        // catch all unresolved routes
        app.use(function (req, res) {
            middleware.session.checkSession(req, res, function () {
                middleware.nav.setNavData(req);
                res.render('index');
            });
        });
    };

    // express production config
    var expressProductionConfig = function () {
        // error handling middleware
        app.use(middleware.errorHandler.productionHandler);
    };

    // express development config
    var expressDevelopmentConfig = function () {
        // error handling middleware
        app.use(middleware.errorHandler.developmentHandler);
    };

    // express configure
    app.configure(expressConfig);
    app.configure('development', expressDevelopmentConfig);
    app.configure('production', expressProductionConfig);

    ///////////////////////////////////////////
    // default routes
    ///////////////////////////////////////////

    if (config.useRightsSystem === true) {

        // login middleware rest api
        app.post('/api/v1/auth/login', middleware.auth.login);

        // login extra login page app
        if (config.useRightsSystem && config.extraLoginPage) {
            app.get('/login', function (req, res) {
                middleware.session.checkSession(req, res, function () {
                    res.render('auth/index');
                });
            });
        }

        // logout middleware route
        app.get('/auth/logout', middleware.auth.logout);
    }

    // rest public api outside rights system.
    app.post('/api/v1/session/setActivity', middleware.session.setActivity);
    app.post('/api/v1/session/getLastActivity', middleware.session.getLastActivity);
    app.post('/api/v1/session/getData', middleware.session.getData);
    app.post('/api/v1/session/setData', middleware.session.setData);
    app.post('/api/v1/session/deleteData', middleware.session.deleteData);
    app.post('/api/v1/auth/getAuthData', middleware.auth.getAuthData);
//    app.post('/api/v1/auth/activateUser', middleware.auth.activateUser);
    app.post('/api/v1/nav/getNavData', middleware.nav.getNavData);

    app.get('/*/*.md', function (req, res) {

        var mdPath = path.join(rootPath, 'client', 'app', req.url);
        fs.readFile(mdPath, 'utf8', function (err, data) {
            if (err) {
                res.json(200, { markdown: err});
            }
            res.json(200, { markdown: data});
        });
    });

    ///////////////////////////////////////////
    // Socket.IO
    ///////////////////////////////////////////

    // set log level for socket logger
    logging.socket.setLevel(config.logging.socket);

    // default config
    io.configure(function () {
        // set socket.io redis store
        io.set('store', new RedisSocketStore({
            redisPub: pub,
            redisSub: sub,
            redisClient: redisClient
        }));

        // Transport
        io.set('transports',
            [
                'websocket'
                //'htmlfile',
                //'xhr-polling',
                //'jsonp-polling'
            ]
        );

        io.set('authorization', function (data, callback) {
            // check if cookie exists
            if (!data.headers.cookie) {
                callback(null, false);
            } else {
                // parse cookie in sessionId
                var signedCookies = require('express/node_modules/cookie').parse(data.headers.cookie),
                    sessionId = require('express/node_modules/connect/lib/utils')
                        .parseSignedCookies(signedCookies, config.sessionSecret)[config.sessionKey];

                // get session from redis session store
                sessionStore.get(sessionId, function (err, session) {
                    if (err || !session) {
                        callback(null, false);
                    } else {

                        var isAuth = true;

                        // restricted socket connection when extraLoginPage is enabled
                        if (config.useRightsSystem && config.extraLoginPage) {
                            isAuth = session.user && session.user.id !== -1;
                        }

                        if (isAuth) {
                            data.session = session;
                            data.session.sessionID = sessionId;
                            callback(null, true);
                        }
                        else {
                            callback(null, false);
                        }
                    }
                });
            }
        });
    });

    // production config
    io.configure('production', function () {
        io.enable('browser client minification');  // send minified client
        io.enable('browser client etag');          // apply etag caching logic based on version number
        io.enable('browser client gzip');          // gzip the file
        io.set('logger', logging.socket);
    });

    // development config
    io.configure('development', function () {
        io.set('logger', logging.socket);
    });

    // socket connection event
    io.sockets.on('connection', function (socket) {
        var session = socket.handshake.session,
            sessionId = session.sessionID;

        // save socketId in session
        session.socketID = socket.id;

        syslog.info('socket: client connected');
        syslog.info('socket: {socketId: %s, username: %s, sessionID: %s }', socket.id, ((session.user || {}).name || 'no user'), session.sessionID);

        socket.on('disconnect', function () {
            syslog.info('socket: %s disconnected', socket.id);
        });

        // register socket events based on user acl
        rights.getAclObj((session.user || {}).acl, function (error, result) {
            if (error) {
                syslog.error('rights: Error loading acl for user %s (%s)', (session.user || {}).name, (session.user || {})._id);
                return;
            }

            // create request object for controller
            var request = {
                /**
                 * Returns the current session.
                 *
                 * @param {!function(error, result)} callback The callback.
                 */
                getSession: function (callback) {
                    // get session from redis session store
                    sessionStore.get(session.sessionID, callback);
                },
                /**
                 * Sets the session.
                 *
                 * @param {!Object} session The session object.
                 * @param {function(error, result)=} callback The callback.
                 */
                setSession: function (session, callback) {
                    if (!lxHelpers.isObject(session)) {
                        var error = lxHelpers.getTypeError('session', session, {});
                        syslog.error(error);

                        if (callback) {
                            callback(error);
                        }

                        return;
                    }

                    sessionStore.set(sessionId, session, callback);
                },
                /**
                 * Returns the current socket object.
                 *
                 * @returns {*}
                 */
                getSocket: function () {
                    return socket;
                }
            };

            api.registerSocketEvents(socket, result, controllers, request);
        });
    });

    return baboon;
};<commit_msg>fix: disable gzip minification of socket.io in production, otherwhise the server will crash in windows<commit_after>'use strict';
var express = require('express');
var path = require('path');
var fs = require('fs');
var clc = require('cli-color');
var log4js = require('log4js');
var redis = require('redis');
var lxHelpers = require('lx-helpers');
var RedisSessionStore = require('connect-redis')(express);

module.exports = function (rootPath) {
    var notice = clc.cyan;
    var middleware = {};
    var config = require('./config')(rootPath, notice);
    var logging = require('./logging')(config);
    var syslog = logging.syslog;
    var mail = require('./mail')(config);
    var rights = require('./rights')(config, logging);
    var settings = require('./settings')(config, logging, rights);
    var app = express();
    var baboonErrors = require('./errors');

    ///////////////////////////////////////////
    // baboon
    ///////////////////////////////////////////

    var baboon = {
        middleware: middleware,
        config: config,
        rights: rights,
        logging: logging,
        mail: mail,
        settings: settings,
        server: {
            app: app
        }
    };

    // register Errors in baboon
    lxHelpers.forEach(baboonErrors, function (value, key) {
        baboon[key] = value;
    });

    var api = require(config.path.api)(baboon);

    ///////////////////////////////////////////
    // redis server
    ///////////////////////////////////////////
    var redisClient = redis.createClient(config.redis.server1.port, config.redis.server1.host);
    var sessionStore = new RedisSessionStore({
        client: redisClient,
        ttl: config.sessionMaxLife
    });
    var RedisSocketStore = require('socket.io/lib/stores/redis');
    var pub = redis.createClient(config.redis.server1.port, config.redis.server1.host);
    var sub = redis.createClient(config.redis.server1.port, config.redis.server1.host);

    redisClient.on('error', function (err) {
        var msg = 'error event - ' + redisClient.host + ':' + redisClient.port + ' - ' + err;

        syslog.error(msg);
        throw new Error(msg);
    });

    ///////////////////////////////////////////
    // config server
    ///////////////////////////////////////////

    // set log level for syslog logger
    syslog.setLevel(config.logging.syslog);

    // set log level for syslog logger
    logging.audit.setLevel(config.logging.audit);

    var server;

    // setup server to https or http from config protocol
    if (config.protocol === 'https') {
        var https = require('https'),
            serverOptions = {
                key: fs.readFileSync(path.join(rootPath, 'server', 'ssl', 'ssl.key')),
                cert: fs.readFileSync(path.join(rootPath, 'server', 'ssl', 'ssl.crt'))
            };

        server = https.createServer(serverOptions, app);
    } else if (config.protocol === 'http') {
        var http = require('http');

        server = http.createServer(app);
    } else {
        var msg = 'error server config - missing or wrong protocol' + config.protocol;

        syslog.error(msg);
        throw new Error(msg);
    }

    var io = require('socket.io').listen(server);
    baboon.server.sio = io;

    ///////////////////////////////////////////
    // Middleware
    ///////////////////////////////////////////

    middleware.errorHandler = require('./middleware/errorHandler')(syslog);
    middleware.session = require('./middleware/session')(baboon);
    middleware.nav = require('./middleware/nav')(baboon);
    middleware.auth = require('./middleware/auth')(baboon);

    ///////////////////////////////////////////
    // start server
    ///////////////////////////////////////////

    baboon.server.start = function () {
        var startOn = 'application server has been started on: ' + config.protocol + '://' + config.host + ':' + config.port,
            startMode = 'application server has been started in ' + config.node_env + ' mode';

        server.listen(app.get('port'), function () {
            syslog.info(startOn);

            if (config.node_env !== 'production') {
                syslog.warn(startMode);
            } else {
                syslog.info(startMode);
                console.log(
                    notice('   info  - ') + startOn + '\n' +
                        notice('   info  - ') + startMode + '\n' +
                        notice('   info  - ') + 'write all entries to logfile...');
            }
        });
    };

    ///////////////////////////////////////////
    // View Engine EJS
    ///////////////////////////////////////////

    // view engine for application
    app.engine('.html', require('ejs').__express);

    ///////////////////////////////////////////
    // Init all app controllers
    ///////////////////////////////////////////

    var controllers = api.initAppControllers();

    ///////////////////////////////////////////
    // Express
    ///////////////////////////////////////////

    // express default config
    var expressConfig = function () {
        app.set('port', config.port);
        app.set('views', config.path.dist + '/app');
        app.set('view engine', 'html');

        // set log level for syslog logger
        logging.express.setLevel(config.logging.express);

        // logging
        if (config.node_env === 'production') {
            app.use(log4js.connectLogger(logging.express, {level: 'auto'}));
        } else {
            app.use(log4js.connectLogger(logging.express, {level: 'auto', format: ':status :method :url'}));
        }

        app.use(express.favicon(config.path.public + '/favicon.ico'));
        app.use(express.compress());
        app.use(express.static(config.path.public));
        app.use(express.json());
        app.use(express.urlencoded());
        app.use(express.methodOverride());
        app.use(express.cookieParser());

        // Session has session cookie with expires:false.
        // Session is only destroyed when the user closes the browser.
        // Redis ttl is maximal lifetime of session, after this time session is destroyed
        // Middleware checks the inactive period of the session by user.
        // When this period is over, the session destroyed.
        app.use(express.session({
            key: config.sessionKey,
            store: sessionStore,
            secret: config.sessionSecret,
            cookie: {expires: false}
        }));

        // routing
        app.use(app.router);

        // restricted api
        app.use('/api/v1', middleware.auth.restrictedApi);

        // Catch all other rest api requests and forward to controller
        app.use('/api/v1', function (req, res) {
            // remove trailing slash
            var route = req.url.substring(1);
            var parsedRoute = api.parseRoute(route);

            // check if user has access to route
            if (rights.userHasAccessTo(req.session.user, route)) {
                var data = req.body;

                // create request object for controller
                var request = {
                    /**
                     * Returns the current session.
                     *
                     * @param {!function(error, result)} callback The callback.
                     */
                    getSession: function (callback) {
                        callback(null, req.session);
                    },
                    /**
                     * Sets the session.
                     *
                     * @param {!Object} session The session object.
                     * @param {function(error, result)=} callback The callback.
                     */
                    setSession: function (session, callback) {
                        if (!lxHelpers.isObject(session)) {
                            var error = lxHelpers.getTypeError('session', session, {});
                            syslog.error(error);

                            if (callback) {
                                callback(error);
                            }

                            return;
                        }

                        if (callback) {
                            callback(null, true);
                        }
                    }
                };

                if (controllers[parsedRoute.controllerFullPath]) {
                    controllers[parsedRoute.controllerFullPath][parsedRoute.action](data, request, function (error, result) {
                        res.send({error: api.parseError(error, data), data: result});
                    });
                } else {
                    res.json(403, 'Wrong url');
                }
            } else {
                res.json(403, 'Access denied.');
            }
        });

        // restricted route
        app.use(middleware.auth.restrictedRoute);

        // catch all unresolved routes
        app.use(function (req, res) {
            middleware.session.checkSession(req, res, function () {
                middleware.nav.setNavData(req);
                res.render('index');
            });
        });
    };

    // express production config
    var expressProductionConfig = function () {
        // error handling middleware
        app.use(middleware.errorHandler.productionHandler);
    };

    // express development config
    var expressDevelopmentConfig = function () {
        // error handling middleware
        app.use(middleware.errorHandler.developmentHandler);
    };

    // express configure
    app.configure(expressConfig);
    app.configure('development', expressDevelopmentConfig);
    app.configure('production', expressProductionConfig);

    ///////////////////////////////////////////
    // default routes
    ///////////////////////////////////////////

    if (config.useRightsSystem === true) {

        // login middleware rest api
        app.post('/api/v1/auth/login', middleware.auth.login);

        // login extra login page app
        if (config.useRightsSystem && config.extraLoginPage) {
            app.get('/login', function (req, res) {
                middleware.session.checkSession(req, res, function () {
                    res.render('auth/index');
                });
            });
        }

        // logout middleware route
        app.get('/auth/logout', middleware.auth.logout);
    }

    // rest public api outside rights system.
    app.post('/api/v1/session/setActivity', middleware.session.setActivity);
    app.post('/api/v1/session/getLastActivity', middleware.session.getLastActivity);
    app.post('/api/v1/session/getData', middleware.session.getData);
    app.post('/api/v1/session/setData', middleware.session.setData);
    app.post('/api/v1/session/deleteData', middleware.session.deleteData);
    app.post('/api/v1/auth/getAuthData', middleware.auth.getAuthData);
//    app.post('/api/v1/auth/activateUser', middleware.auth.activateUser);
    app.post('/api/v1/nav/getNavData', middleware.nav.getNavData);

    app.get('/*/*.md', function (req, res) {

        var mdPath = path.join(rootPath, 'client', 'app', req.url);
        fs.readFile(mdPath, 'utf8', function (err, data) {
            if (err) {
                res.json(200, { markdown: err});
            }
            res.json(200, { markdown: data});
        });
    });

    ///////////////////////////////////////////
    // Socket.IO
    ///////////////////////////////////////////

    // set log level for socket logger
    logging.socket.setLevel(config.logging.socket);

    // default config
    io.configure(function () {
        // set socket.io redis store
        io.set('store', new RedisSocketStore({
            redisPub: pub,
            redisSub: sub,
            redisClient: redisClient
        }));

        // Transport
        io.set('transports',
            [
                'websocket'
                //'htmlfile',
                //'xhr-polling',
                //'jsonp-polling'
            ]
        );

        io.set('authorization', function (data, callback) {
            // check if cookie exists
            if (!data.headers.cookie) {
                callback(null, false);
            } else {
                // parse cookie in sessionId
                var signedCookies = require('express/node_modules/cookie').parse(data.headers.cookie),
                    sessionId = require('express/node_modules/connect/lib/utils')
                        .parseSignedCookies(signedCookies, config.sessionSecret)[config.sessionKey];

                // get session from redis session store
                sessionStore.get(sessionId, function (err, session) {
                    if (err || !session) {
                        callback(null, false);
                    } else {

                        var isAuth = true;

                        // restricted socket connection when extraLoginPage is enabled
                        if (config.useRightsSystem && config.extraLoginPage) {
                            isAuth = session.user && session.user.id !== -1;
                        }

                        if (isAuth) {
                            data.session = session;
                            data.session.sessionID = sessionId;
                            callback(null, true);
                        }
                        else {
                            callback(null, false);
                        }
                    }
                });
            }
        });
    });

    // production config
    io.configure('production', function () {
        io.enable('browser client minification');  // send minified client
        io.enable('browser client etag');          // apply etag caching logic based on version number
//        io.enable('browser client gzip');          // gzip the file
        io.set('logger', logging.socket);
    });

    // development config
    io.configure('development', function () {
        io.set('logger', logging.socket);
    });

    // socket connection event
    io.sockets.on('connection', function (socket) {
        var session = socket.handshake.session,
            sessionId = session.sessionID;

        // save socketId in session
        session.socketID = socket.id;

        syslog.info('socket: client connected');
        syslog.info('socket: {socketId: %s, username: %s, sessionID: %s }', socket.id, ((session.user || {}).name || 'no user'), session.sessionID);

        socket.on('disconnect', function () {
            syslog.info('socket: %s disconnected', socket.id);
        });

        // register socket events based on user acl
        rights.getAclObj((session.user || {}).acl, function (error, result) {
            if (error) {
                syslog.error('rights: Error loading acl for user %s (%s)', (session.user || {}).name, (session.user || {})._id);
                return;
            }

            // create request object for controller
            var request = {
                /**
                 * Returns the current session.
                 *
                 * @param {!function(error, result)} callback The callback.
                 */
                getSession: function (callback) {
                    // get session from redis session store
                    sessionStore.get(session.sessionID, callback);
                },
                /**
                 * Sets the session.
                 *
                 * @param {!Object} session The session object.
                 * @param {function(error, result)=} callback The callback.
                 */
                setSession: function (session, callback) {
                    if (!lxHelpers.isObject(session)) {
                        var error = lxHelpers.getTypeError('session', session, {});
                        syslog.error(error);

                        if (callback) {
                            callback(error);
                        }

                        return;
                    }

                    sessionStore.set(sessionId, session, callback);
                },
                /**
                 * Returns the current socket object.
                 *
                 * @returns {*}
                 */
                getSocket: function () {
                    return socket;
                }
            };

            api.registerSocketEvents(socket, result, controllers, request);
        });
    });

    return baboon;
};<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var util = require('util');
var path = require('path');
var fs = require('fs');
var _ = require('lodash');

/**
 * before()
 *
 * Runs before this generator begins processing targets.
 *
 * @param  {Dictionary} scope
 * @param  {Function} done
 */

module.exports = function before (scope, done) {

  var args0 = scope.args[0];

  // Use a reasonable default app name
  var defaultAppName = args0;

  // Ensure that default app name is not "." or "" and does not contain slashes.
  if (defaultAppName === '.' || defaultAppName === './' || !defaultAppName) {
    defaultAppName = path.basename(process.cwd());
  }
  defaultAppName = defaultAppName.replace(/\//, '-');

  var author = process.env.USER || 'anonymous node/sails user';

  var owner = author;

  _.defaults(scope, {
    appName: defaultAppName,
    author: author,
    owner: owner,
    year: (new Date()).getFullYear(),
    github: {
      username: author,
      owner: owner
    },
    website: util.format('https://github.com/%s', owner)
  });

  // Allow for alternate --no-front-end cli option
  if (scope['front-end'] === false) {
    scope['frontend'] = false;
  }

  if (scope['frontend'] === false) {
    scope.modules['frontend'] = false;
    scope.modules['gruntfile'] = false;
    scope.modules['views'] = false;
  }

  // TODO: deprecate this environment variable (just use scope instead)
  if (process.env.SAILS_NEW_LINK && scope.link !== false) {
    scope.link = true;
  }

  // Make changes to the rootPath where the sails project will be created
  scope.rootPath = path.resolve(process.cwd(), args0 || '');

  // Ensure we aren't going to inadvertently delete any files.
  try {
    var files = fs.readdirSync(scope.rootPath);
    if (files.length > 0) {
      return done(new Error('Couldn\'t create a new Sails app in "'+scope.rootPath+'" (directory already exists and is not empty)'));
    }
  }
  catch (e) { }

  return done();
};
<commit_msg>Ensure 'scope.modules' exists without freaking out if it doesn't.<commit_after>/**
 * Module dependencies
 */

var util = require('util');
var path = require('path');
var fs = require('fs');
var _ = require('lodash');

/**
 * before()
 *
 * Runs before this generator begins processing targets.
 *
 * @param  {Dictionary} scope
 * @param  {Function} done
 */

module.exports = function before (scope, done) {

  var args0 = scope.args[0];

  // Use a reasonable default app name
  var defaultAppName = args0;

  // Ensure that default app name is not "." or "" and does not contain slashes.
  if (defaultAppName === '.' || defaultAppName === './' || !defaultAppName) {
    defaultAppName = path.basename(process.cwd());
  }
  defaultAppName = defaultAppName.replace(/\//, '-');

  var author = process.env.USER || 'anonymous node/sails user';

  var owner = author;

  _.defaults(scope, {
    appName: defaultAppName,
    author: author,
    owner: owner,
    year: (new Date()).getFullYear(),
    github: {
      username: author,
      owner: owner
    },
    modules: {},
    website: util.format('https://github.com/%s', owner)
  });

  // Allow for alternate --no-front-end cli option
  if (scope['front-end'] === false) {
    scope['frontend'] = false;
  }

  if (scope['frontend'] === false) {
    scope.modules['frontend'] = false;
    scope.modules['gruntfile'] = false;
    scope.modules['views'] = false;
  }

  // TODO: deprecate this environment variable (just use scope instead)
  if (process.env.SAILS_NEW_LINK && scope.link !== false) {
    scope.link = true;
  }

  // Make changes to the rootPath where the sails project will be created
  scope.rootPath = path.resolve(process.cwd(), args0 || '');

  // Ensure we aren't going to inadvertently delete any files.
  try {
    var files = fs.readdirSync(scope.rootPath);
    if (files.length > 0) {
      return done(new Error('Couldn\'t create a new Sails app in "'+scope.rootPath+'" (directory already exists and is not empty)'));
    }
  }
  catch (e) { }

  return done();
};
<|endoftext|>


<commit_before>/**
 * BezierEasing - use bezier curve for transition easing function
 * by Gaëtan Renaudeau 2014 – MIT License
 *
 * Credits: is based on Firefox's nsSMILKeySpline.cpp
 * Usage:
 * var spline = BezierEasing(0.25, 0.1, 0.25, 1.0)
 * spline(x) => returns the easing value | x must be in [0, 1] range
 *
 */
(function (definition) {
  if (typeof exports === "object") {
    module.exports = definition();
  } else if (typeof define === 'function' && define.amd) {
    define([], definition);
  } else {
    window.BezierEasing = definition();
  }
}(function () {
  var global = this;

  // These values are established by empiricism with tests (tradeoff: performance VS precision)
  var NEWTON_ITERATIONS = 4;
  var NEWTON_MIN_SLOPE = 0.001;
  var SUBDIVISION_PRECISION = 0.0000001;
  var SUBDIVISION_MAX_ITERATIONS = 10;

  var kSplineTableSize = 11;
  var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);

  var float32ArraySupported = 'Float32Array' in global;

  function BezierEasing (mX1, mY1, mX2, mY2) {
    // Validate arguments
    if (arguments.length !== 4) {
      throw new Error("BezierEasing requires 4 arguments.");
    }
    for (var i=0; i<4; ++i) {
      if (typeof arguments[i] !== "number" || isNaN(arguments[i]) || !isFinite(arguments[i])) {
        throw new Error("BezierEasing arguments should be integers.");
      }
    }
    if (mX1 < 0 || mX1 > 1 || mX2 < 0 || mX2 > 1) {
      throw new Error("BezierEasing x values must be in [0, 1] range.");
    }

    var mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);

    function A (aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
    function B (aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
    function C (aA1)      { return 3.0 * aA1; }

    // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
    function calcBezier (aT, aA1, aA2) {
      return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT;
    }

    // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
    function getSlope (aT, aA1, aA2) {
      return 3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
    }

    function newtonRaphsonIterate (aX, aGuessT) {
      for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
        var currentSlope = getSlope(aGuessT, mX1, mX2);
        if (currentSlope === 0.0) return aGuessT;
        var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
        aGuessT -= currentX / currentSlope;
      }
      return aGuessT;
    }

    function calcSampleValues () {
      for (var i = 0; i < kSplineTableSize; ++i) {
        mSampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
      }
    }

    function binarySubdivide (aX, aA, aB) {
      var currentX, currentT, i = 0;
      do {
        currentT = aA + (aB - aA) / 2.0;
        currentX = calcBezier(currentT, mX1, mX2) - aX;
        if (currentX > 0.0) {
          aB = currentT;
        } else {
          aA = currentT;
        }
      } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
      return currentT;
    }

    function getTForX (aX) {
      var intervalStart = 0.0;
      var currentSample = 1;
      var lastSample = kSplineTableSize - 1;

      for (; currentSample != lastSample && mSampleValues[currentSample] <= aX; ++currentSample) {
        intervalStart += kSampleStepSize;
      }
      --currentSample;

      // Interpolate to provide an initial guess for t
      var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample+1] - mSampleValues[currentSample]);
      var guessForT = intervalStart + dist * kSampleStepSize;

      var initialSlope = getSlope(guessForT, mX1, mX2);
      if (initialSlope >= NEWTON_MIN_SLOPE) {
        return newtonRaphsonIterate(aX, guessForT);
      } else if (initialSlope === 0.0) {
        return guessForT;
      } else {
        return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize);
      }
    }

    var _precomputed = false;
    function precompute() {
      _precomputed = true;
      if (mX1 != mY1 || mX2 != mY2)
        calcSampleValues();
    }

    var f = function (aX) {
      if (!_precomputed) precompute();
      if (mX1 === mY1 && mX2 === mY2) return aX; // linear
      // Because JavaScript number are imprecise, we should guarantee the extremes are right.
      if (aX === 0) return 0;
      if (aX === 1) return 1;
      return calcBezier(getTForX(aX), mY1, mY2);
    };

    f.getControlPoints = function() { return [{ x: mX1, y: mY1 }, { x: mX2, y: mY2 }]; };

    var args = [mX1, mY1, mX2, mY2];
    var str = "BezierEasing("+args+")";
    f.toString = function () { return str; };

    var css = "cubic-bezier("+args+")";
    f.toCSS = function () { return css; };

    return f;
  }

  // CSS mapping
  BezierEasing.css = {
    "ease":        BezierEasing(0.25, 0.1, 0.25, 1.0),
    "linear":      BezierEasing(0.00, 0.0, 1.00, 1.0),
    "ease-in":     BezierEasing(0.42, 0.0, 1.00, 1.0),
    "ease-out":    BezierEasing(0.00, 0.0, 0.58, 1.0),
    "ease-in-out": BezierEasing(0.42, 0.0, 0.58, 1.0)
  };

  return BezierEasing;

}));
<commit_msg>Remove old bezier file.<commit_after><|endoftext|>


<commit_before>var fs = require('fs'),
    url = require('url'),
    formatDate = require('./format-date');

var str = fs.readFileSync('./refs/biblio.json', 'utf8');
var json = JSON.parse(str);

var ietf = JSON.parse(fs.readFileSync('./refs/ietf.json', 'utf8'));
var w3c = JSON.parse(fs.readFileSync('./refs/w3c.json', 'utf8'));
var legacy = JSON.parse(fs.readFileSync('./refs/legacy.json', 'utf8'));
var PROPS =  [
    "id",
    "authors",
    "etAl",
    "href",
    "edDraft",
    "title",
    "date",
    "status",
    "publisher",
    "aliasOf",
    "versions",
    "versionOf",
    "deliveredBy"
];

var WG_SHORTNAME_SPECIAL_CASES = {
    'graphics_svg': 'svg',
    'graphics_webcgm': 'webcgm',
    'markup': 'html-old',
    'markup_coord': 'hypertextcg',
    'markup_forms': 'forms',
    'mobile_ccpp': 'ccpp',
    'p3p_specification': 'p3p',
    'style_css': 'css',
    'style_xsl': 'xsl',
    'xp': 'xml_protocol'
};

function _getWGShortNameFromURL(url) {
    var shortname = url.toLowerCase()
             // Die, date space die!
             .replace(/\/([0-9]+\/)+/g, '/')
             .replace(/-?wg/,'')
             .replace(/group/,'')
             .replace(/members/,'')
             .replace(/\.html/,'')
             .replace(/community/,'cg')
             .replace(/international/,'i18n')
             // base url
             .replace("http://www.w3.org/", "")
             .replace(/\/+/g, '/')
             // Trailing slash
             .replace(/\/$/, '')
             // convert / into _
             .replace(/\//g, "_") ;
    if (WG_SHORTNAME_SPECIAL_CASES[shortname]) {
	return WG_SHORTNAME_SPECIAL_CASES[shortname];
    }
    return shortname;
}

function _copyProps(src, dest) {
    for (var k in src) {
        dest[k] = src[k];
    }
}

function _cloneJSON(obj) {
    return JSON.parse(JSON.stringify(obj));
}

function Bibref() {
    this.raw = {};
    for (var i = 0; i < arguments.length; i++) {
        this.addRefs(arguments[i]);
    }
}

Bibref.prototype.addRefs = addRefs;
function addRefs(refs) {
    if (this.all) {
        throw new Error("Can no longer add references as Bibref.prototype.doneAddingRefs was called.");
    }
    _merge(this.raw, refs);
}

Bibref.prototype.doneAddingRefs = doneAddingRefs;
function doneAddingRefs() {
    this.all = cleanupRefs(addIds(createUppercaseRefs(expandRefs(this.raw))));
    this.reverseLookupTable = prepareReverseLookup(this.all);
}

function _merge(target, source) {
    for (var k in source) {
        if (k in target) {
            throw new Error("Dupliate entry " + k);
        } else {
            target[k] = source[k];
        }
    }
}

function normalizeUrl(u) {
    // We treat different protocols as identical, so omit them from the
    // output. Same for whatever's after the hash.
    // Likewise, we consider trailing slashes optional and remove them
    // when present (it's easier to remove a trailing slash than to add
    // one where missing).
    u = url.parse(u);
    u = (u.hostname || "").replace(/^www\./, "") + (u.pathname || "").replace(/\/$/, "") + (u.search || "");
    // Case insensitive match.
    return u.toLowerCase();
}

function prepareReverseLookup(refs) {
    var output = {};
    Object.keys(refs).forEach(function(k) {
        var ref = refs[k];
        var href = ref.href;
        if (href) {
            href = normalizeUrl(href);
            output[href] = refs[ref.versionOf || k];
        }
        var edDraft = ref.edDraft;
        if (edDraft && !(edDraft in output)) {
            edDraft = normalizeUrl(edDraft);
            output[edDraft] = refs[ref.versionOf || k];
        }
    });
    return output;
}

// Iterates through the reference looking for previous
// versions of the spec which it makes available as:
// KEY-SUBKEY (e.g. DAHUT-19970315).
// Properties which are missing from the previous entry
// fall back to props of the main entry.
// Correctly forwards aliases. For example:
// CSS2 is aliased to CSS21 therefore
// CSS2-20110607 will automatically be aliased to
// CSS21-20110607
function expandRefs(refs) {
    refs = _cloneJSON(refs);
    Object.keys(refs).forEach(function(key) {
        var ref = refs[key];
        if (ref.aliasOf) {
            var obj = ref,
                lastKey = key;
            while (obj && refs[obj.aliasOf]) {
                lastKey = obj.aliasOf;
                obj = refs[lastKey];
            }
        }
        if (obj && key !== lastKey) {
            obj.aliases = obj.aliases || [];
            obj.aliases.push(key);
        }
    });

    Object.keys(refs).forEach(function(key) {
        var ref = refs[key];
        var versions = ref.versions
        if (versions) {
            Object.keys(versions).forEach(function(subKey) {
                var ver = versions[subKey];
                if (ver.aliasOf) {
                    refs[key + '-' + subKey] = ver;
                } else {
                    var obj = {
                        versionOf: key
                    };
                    // Props fallback to main entry.
                    _copyProps(ref, obj);
                    _copyProps(ver, obj);
                    refs[key + '-' + subKey] = obj;
                }
            });
            if (ref.aliases) {
                ref.aliases.forEach(function(aliasKey) {
                    Object.keys(versions).forEach(function(subKey) {
                        // Watch out not to overwrite existing aliases.
                        if (!refs[aliasKey + '-' + subKey]) {
                            refs[aliasKey + '-' + subKey] = { aliasOf: key + '-' + subKey };
                        }
                    });
                });
            }
        }
    });
    return refs;
}

// Creates uppercased aliases to allow case-insensitive retrieval
function createUppercaseRefs(refs) {
    Object.keys(refs).forEach(function(key) {
        var upper = key.toUpperCase();
        if (!refs[upper]) {
            refs[upper] = { aliasOf: key };
        }
    });

    return refs;
}

function cleanupRefs(refs) {
    Object.keys(refs).forEach(function(k) {
        var ref = refs[k];
        if (typeof ref === 'object') {
            if (ref.rawDate) ref.date = formatDate(ref.rawDate);
            for (var prop in ref) {
                if (PROPS.indexOf(prop) === -1) {
                    delete ref[prop];
                }
                if (prop == "deliveredBy") {
                    ref.deliveredBy = ref.deliveredBy.map(function(url) {
                        return { url: url, shortname: _getWGShortNameFromURL(url) };
                    });
                }
                if (prop == "versions") {
                    ref.versions = Object.keys(ref[prop]).map(function(subKey) {
                        return k + "-" + subKey;
                    });
                    ref.versions.sort();
                    ref.versions.reverse();
                }
            }
        }
    });
    return refs;
}

function addIds(refs) {
    Object.keys(refs).forEach(function(k) {
        var ref = refs[k];
        if (typeof ref === 'object') {
            ref.id = k;
        }
    });
    return refs;
}

var EIGHT_DIGITS = /^\d{8}$/;

function findLatest(ref) {
    var keys, latest = null;
    if (ref.versions) {
        keys = Object.keys(ref.versions).filter(function(k) { return EIGHT_DIGITS.test(k); }).sort();
        latest = ref.versions[keys[keys.length - 1]];
    }
    return latest;
}

Bibref.prototype.get = get;
function get(ref, output) {
    output = output || {};
    var obj, versionOf;

    // if ref doesn't exist but the uppercased key does, add an alias on the fly
    if ((!this.all[ref]) && this.all[ref.toUpperCase()]) {
        output[ref] = { aliasOf: ref.toUpperCase() };
        ref = ref.toUpperCase();
    }

    do {
        obj = this.all[ref];
        if (obj && !output[ref]) output[ref] = obj;
    } while (obj && (ref = obj.aliasOf))
    if (obj && (versionOf = obj.versionOf)) {
        output[versionOf] = this.all[versionOf];
    }
    return output;
}

Bibref.prototype.getRefs = getRefs;
function getRefs(refs) {
    var output = {};
    refs.forEach(function(ref) { this.get(ref, output); }, this);
    return output;
}

Bibref.prototype.reverseLookup = reverseLookup;
function reverseLookup(urls) {
    var output = {};
    urls.forEach(function(url) {
        var ref = this.reverseLookupTable[normalizeUrl(url)];
        if (ref) output[url] = ref;
    }, this);
    return output;
}

module.exports = new Bibref(json, ietf, w3c, legacy);
module.exports.doneAddingRefs();
module.exports.create = function() {
    var b = new Bibref();
    for (var i = 0; i < arguments.length; i++) {
        b.addRefs(arguments[i]);
    }
    b.doneAddingRefs();
    return b;
};
module.exports.expandRefs = expandRefs;
module.exports.cleanupRefs = cleanupRefs;
module.exports.findLatest = findLatest;
<commit_msg>Auto-load all files in refs dir.<commit_after>var fs = require('fs'),
    path = require('path'),
    url = require('url'),
    formatDate = require('./format-date');

var PROPS =  [
    "id",
    "authors",
    "etAl",
    "href",
    "edDraft",
    "title",
    "date",
    "status",
    "publisher",
    "aliasOf",
    "versions",
    "versionOf",
    "deliveredBy"
];

var WG_SHORTNAME_SPECIAL_CASES = {
    'graphics_svg': 'svg',
    'graphics_webcgm': 'webcgm',
    'markup': 'html-old',
    'markup_coord': 'hypertextcg',
    'markup_forms': 'forms',
    'mobile_ccpp': 'ccpp',
    'p3p_specification': 'p3p',
    'style_css': 'css',
    'style_xsl': 'xsl',
    'xp': 'xml_protocol'
};

function _getWGShortNameFromURL(url) {
    var shortname = url.toLowerCase()
             // Die, date space die!
             .replace(/\/([0-9]+\/)+/g, '/')
             .replace(/-?wg/,'')
             .replace(/group/,'')
             .replace(/members/,'')
             .replace(/\.html/,'')
             .replace(/community/,'cg')
             .replace(/international/,'i18n')
             // base url
             .replace("http://www.w3.org/", "")
             .replace(/\/+/g, '/')
             // Trailing slash
             .replace(/\/$/, '')
             // convert / into _
             .replace(/\//g, "_") ;
    if (WG_SHORTNAME_SPECIAL_CASES[shortname]) {
	return WG_SHORTNAME_SPECIAL_CASES[shortname];
    }
    return shortname;
}

function _copyProps(src, dest) {
    for (var k in src) {
        dest[k] = src[k];
    }
}

function _cloneJSON(obj) {
    return JSON.parse(JSON.stringify(obj));
}

function Bibref() {
    this.raw = {};
}

Bibref.prototype.addRefs = addRefs;
function addRefs(refs) {
    if (this.all) {
        throw new Error("Can no longer add references as Bibref.prototype.doneAddingRefs was called.");
    }
    _merge(this.raw, refs);
}

Bibref.prototype.doneAddingRefs = doneAddingRefs;
function doneAddingRefs() {
    this.all = cleanupRefs(addIds(createUppercaseRefs(expandRefs(this.raw))));
    this.reverseLookupTable = prepareReverseLookup(this.all);
}

function _merge(target, source) {
    for (var k in source) {
        if (k in target) {
            throw new Error("Dupliate entry " + k);
        } else {
            target[k] = source[k];
        }
    }
}

function normalizeUrl(u) {
    // We treat different protocols as identical, so omit them from the
    // output. Same for whatever's after the hash.
    // Likewise, we consider trailing slashes optional and remove them
    // when present (it's easier to remove a trailing slash than to add
    // one where missing).
    u = url.parse(u);
    u = (u.hostname || "").replace(/^www\./, "") + (u.pathname || "").replace(/\/$/, "") + (u.search || "");
    // Case insensitive match.
    return u.toLowerCase();
}

function prepareReverseLookup(refs) {
    var output = {};
    Object.keys(refs).forEach(function(k) {
        var ref = refs[k];
        var href = ref.href;
        if (href) {
            href = normalizeUrl(href);
            output[href] = refs[ref.versionOf || k];
        }
        var edDraft = ref.edDraft;
        if (edDraft && !(edDraft in output)) {
            edDraft = normalizeUrl(edDraft);
            output[edDraft] = refs[ref.versionOf || k];
        }
    });
    return output;
}

// Iterates through the reference looking for previous
// versions of the spec which it makes available as:
// KEY-SUBKEY (e.g. DAHUT-19970315).
// Properties which are missing from the previous entry
// fall back to props of the main entry.
// Correctly forwards aliases. For example:
// CSS2 is aliased to CSS21 therefore
// CSS2-20110607 will automatically be aliased to
// CSS21-20110607
function expandRefs(refs) {
    refs = _cloneJSON(refs);
    Object.keys(refs).forEach(function(key) {
        var ref = refs[key];
        if (ref.aliasOf) {
            var obj = ref,
                lastKey = key;
            while (obj && refs[obj.aliasOf]) {
                lastKey = obj.aliasOf;
                obj = refs[lastKey];
            }
        }
        if (obj && key !== lastKey) {
            obj.aliases = obj.aliases || [];
            obj.aliases.push(key);
        }
    });

    Object.keys(refs).forEach(function(key) {
        var ref = refs[key];
        var versions = ref.versions
        if (versions) {
            Object.keys(versions).forEach(function(subKey) {
                var ver = versions[subKey];
                if (ver.aliasOf) {
                    refs[key + '-' + subKey] = ver;
                } else {
                    var obj = {
                        versionOf: key
                    };
                    // Props fallback to main entry.
                    _copyProps(ref, obj);
                    _copyProps(ver, obj);
                    refs[key + '-' + subKey] = obj;
                }
            });
            if (ref.aliases) {
                ref.aliases.forEach(function(aliasKey) {
                    Object.keys(versions).forEach(function(subKey) {
                        // Watch out not to overwrite existing aliases.
                        if (!refs[aliasKey + '-' + subKey]) {
                            refs[aliasKey + '-' + subKey] = { aliasOf: key + '-' + subKey };
                        }
                    });
                });
            }
        }
    });
    return refs;
}

// Creates uppercased aliases to allow case-insensitive retrieval
function createUppercaseRefs(refs) {
    Object.keys(refs).forEach(function(key) {
        var upper = key.toUpperCase();
        if (!refs[upper]) {
            refs[upper] = { aliasOf: key };
        }
    });

    return refs;
}

function cleanupRefs(refs) {
    Object.keys(refs).forEach(function(k) {
        var ref = refs[k];
        if (typeof ref === 'object') {
            if (ref.rawDate) ref.date = formatDate(ref.rawDate);
            for (var prop in ref) {
                if (PROPS.indexOf(prop) === -1) {
                    delete ref[prop];
                }
                if (prop == "deliveredBy") {
                    ref.deliveredBy = ref.deliveredBy.map(function(url) {
                        return { url: url, shortname: _getWGShortNameFromURL(url) };
                    });
                }
                if (prop == "versions") {
                    ref.versions = Object.keys(ref[prop]).map(function(subKey) {
                        return k + "-" + subKey;
                    });
                    ref.versions.sort();
                    ref.versions.reverse();
                }
            }
        }
    });
    return refs;
}

function addIds(refs) {
    Object.keys(refs).forEach(function(k) {
        var ref = refs[k];
        if (typeof ref === 'object') {
            ref.id = k;
        }
    });
    return refs;
}

var EIGHT_DIGITS = /^\d{8}$/;

function findLatest(ref) {
    var keys, latest = null;
    if (ref.versions) {
        keys = Object.keys(ref.versions).filter(function(k) { return EIGHT_DIGITS.test(k); }).sort();
        latest = ref.versions[keys[keys.length - 1]];
    }
    return latest;
}

Bibref.prototype.get = get;
function get(ref, output) {
    output = output || {};
    var obj, versionOf;

    // if ref doesn't exist but the uppercased key does, add an alias on the fly
    if ((!this.all[ref]) && this.all[ref.toUpperCase()]) {
        output[ref] = { aliasOf: ref.toUpperCase() };
        ref = ref.toUpperCase();
    }

    do {
        obj = this.all[ref];
        if (obj && !output[ref]) output[ref] = obj;
    } while (obj && (ref = obj.aliasOf))
    if (obj && (versionOf = obj.versionOf)) {
        output[versionOf] = this.all[versionOf];
    }
    return output;
}

Bibref.prototype.getRefs = getRefs;
function getRefs(refs) {
    var output = {};
    refs.forEach(function(ref) { this.get(ref, output); }, this);
    return output;
}

Bibref.prototype.reverseLookup = reverseLookup;
function reverseLookup(urls) {
    var output = {};
    urls.forEach(function(url) {
        var ref = this.reverseLookupTable[normalizeUrl(url)];
        if (ref) output[url] = ref;
    }, this);
    return output;
}

var REFS_DIR = './refs';

var b = new Bibref();
fs.readdirSync(REFS_DIR).forEach(function(file) {
    var content = fs.readFileSync(path.join(REFS_DIR, file), 'utf8');
    var json = JSON.parse(content);
    b.addRefs(json);
});
b.doneAddingRefs();

module.exports = b;
module.exports.create = function() {
    var b = new Bibref();
    for (var i = 0; i < arguments.length; i++) {
        b.addRefs(arguments[i]);
    }
    b.doneAddingRefs();
    return b;
};
module.exports.expandRefs = expandRefs;
module.exports.cleanupRefs = cleanupRefs;
module.exports.findLatest = findLatest;
<|endoftext|>


<commit_before>'use strict';

/* eslint-disable no-console */

let leds;

try {
  const Blinkt = require('node-blinkt');

  leds = new Blinkt();
  console.log('Platform supported by Blinkt!');
} catch (e) {
  // Mock to run unit-tests on platforms not supported by Blinkt!
  leds = {
    clearAll () {},
    sendUpdate () {},
    setAllPixels () {},
    setPixel () {},
    setup () {}
  };
  console.error('Platform not supported by Blinkt!');
}

const shutdown = function () {
  console.log('Turning off lights.');

  leds.setAllPixels(0, 0, 0, 0);

  // Workaround: https://github.com/Irrelon/node-blinkt/issues/1
  leds.sendUpdate();
  leds.sendUpdate();

  /* eslint-disable no-process-exit */
  process.nextTick(() => {
    console.log('Terminating process.');
    process.exit(0);
  });
  /* eslint-enable no-process-exit */
};

const init = function () {
  leds.setup();
  leds.clearAll();

  process.on('SIGINT', shutdown);
  process.on('SIGTERM', shutdown);

  console.log('Initialized.');
};

const blinkt = function (colors) {
  colors = colors || [];

  console.log('COLORS', colors);
  console.log('SLICED COLORS', colors.slice(-8));

  colors.slice(-8).forEach((color, i) => {
    console.log('I', i);
    leds.setPixel(7 - i, color[0], color[1], color[2], 0.3);
  });

  for (let i = 0; i < 8 - colors.length; i++) {
    leds.setPixel(i, 0, 0, 0, 0);
  }

  // Workaround: https://github.com/Irrelon/node-blinkt/issues/1
  leds.sendUpdate();
  leds.sendUpdate();
};

init();

module.exports = blinkt;
<commit_msg>Remove last debug messages.<commit_after>'use strict';

/* eslint-disable no-console */

let leds;

try {
  const Blinkt = require('node-blinkt');

  leds = new Blinkt();
  console.log('Platform supported by Blinkt!');
} catch (e) {
  // Mock to run unit-tests on platforms not supported by Blinkt!
  leds = {
    clearAll () {},
    sendUpdate () {},
    setAllPixels () {},
    setPixel () {},
    setup () {}
  };
  console.error('Platform not supported by Blinkt!');
}

const shutdown = function () {
  console.log('Turning off lights.');

  leds.setAllPixels(0, 0, 0, 0);

  // Workaround: https://github.com/Irrelon/node-blinkt/issues/1
  leds.sendUpdate();
  leds.sendUpdate();

  /* eslint-disable no-process-exit */
  process.nextTick(() => {
    console.log('Terminating process.');
    process.exit(0);
  });
  /* eslint-enable no-process-exit */
};

const init = function () {
  leds.setup();
  leds.clearAll();

  process.on('SIGINT', shutdown);
  process.on('SIGTERM', shutdown);

  console.log('Initialized.');
};

const blinkt = function (colors) {
  colors = colors || [];

  colors.slice(-8).forEach((color, i) => {
    leds.setPixel(7 - i, color[0], color[1], color[2], 0.3);
  });

  for (let i = 0; i < 8 - colors.length; i++) {
    leds.setPixel(i, 0, 0, 0, 0);
  }

  // Workaround: https://github.com/Irrelon/node-blinkt/issues/1
  leds.sendUpdate();
  leds.sendUpdate();
};

init();

module.exports = blinkt;
<|endoftext|>