<commit_before>var crypto = require("crypto");
var gcmKey = null;
var OAuthEncryption = exports.OAuthEncryption = {};

// Node leniently ignores non-base64 characters when parsing a base64
// string, but we want to provide a more informative error message if
// the developer doesn't use base64 encoding.
//
// Note that an empty string is valid base64 (denoting 0 bytes).
//
// Exported for the convenience of tests.
//
OAuthEncryption._isBase64 = function (str) {
  return _.isString(str) && /^[A-Za-z0-9\+\/]*\={0,2}$/.test(str);
};

// Loads the OAuth secret key, which must be 16 bytes in length
// encoded in base64.
//
// The key may be `null` which reverts to having no key (mainly used
// by tests).
//
OAuthEncryption.loadKey = function (key) {
  if (key === null) {
    gcmKey = null;
    return;
  }

  if (! OAuthEncryption._isBase64(key))
    throw new Error("The OAuth encryption key must be encoded in base64");

  var buf = new Buffer(key, "base64");

  if (buf.length !== 16)
    throw new Error("The OAuth encryption AES-128-GCM key must be 16 bytes in length");

  gcmKey = buf;
};

// Encrypt `data`, which may be any EJSON-compatible object, using the
// previously loaded OAuth secret key.
//
// The `userId` argument is optional. The data is encrypted as { data:
// *, userId: * }. When the result of `seal` is passed to `open`, the
// same user id must be supplied, which prevents user specific
// credentials such as access tokens from being used by a different
// user.
//
// We would actually like the user id to be AAD (additional
// authenticated data), but the node crypto API does not currently have
// support for specifying AAD.
//
OAuthEncryption.seal = function (data, userId) {
  if (! gcmKey) {
    throw new Error("No OAuth encryption key loaded");
  }

  var plaintext = new Buffer(EJSON.stringify({
    data: data,
    userId: userId
  }));

  var iv = crypto.randomBytes(12);
  var cipher = crypto.createCipheriv("aes-128-gcm", gcmKey, iv);
  cipher.setAAD(new Buffer([]));
  var chunks = [cipher.update(plaintext)];
  chunks.push(cipher.final());
  var encrypted = Buffer.concat(chunks);

  return {
    iv: iv.toString("base64"),
    ciphertext: encrypted.toString("base64"),
    algorithm: "aes-128-gcm",
    authTag: cipher.getAuthTag().toString("base64")
  };
};

// Decrypt the passed ciphertext (as returned from `seal`) using the
// previously loaded OAuth secret key.
//
// `userId` must match the user id passed to `seal`: if the user id
// wasn't specified, it must not be specified here, if it was
// specified, it must be the same user id.
//
// To prevent an attacker from breaking the encryption key by
// observing the result of sending manipulated ciphertexts, `open`
// throws "decryption unsuccessful" on any error.
OAuthEncryption.open = function (ciphertext, userId) {
  if (! gcmKey)
    throw new Error("No OAuth encryption key loaded");

  try {
    if (ciphertext.algorithm !== "aes-128-gcm") {
      throw new Error();
    }

    var decipher = crypto.createDecipheriv(
      "aes-128-gcm",
      gcmKey,
      new Buffer(ciphertext.iv, "base64")
    );

    decipher.setAAD(new Buffer([]));
    decipher.setAuthTag(new Buffer(ciphertext.authTag, "base64"));
    var chunks = [decipher.update(
      new Buffer(ciphertext.ciphertext, "base64"))];
    chunks.push(decipher.final());
    var plaintext = Buffer.concat(chunks).toString("utf8");

    var err;
    var data;

    try {
      data = EJSON.parse(plaintext);
    } catch (e) {
      err = new Error();
    }

    if (data.userId !== userId) {
      err = new Error();
    }

    if (err) {
      throw err;
    } else {
      return data.data;
    }
  } catch (e) {
    throw new Error("decryption failed");
  }
};

OAuthEncryption.isSealed = function (maybeCipherText) {
  return maybeCipherText &&
    OAuthEncryption._isBase64(maybeCipherText.iv) &&
    OAuthEncryption._isBase64(maybeCipherText.ciphertext) &&
    OAuthEncryption._isBase64(maybeCipherText.authTag) &&
    _.isString(maybeCipherText.algorithm);
};

OAuthEncryption.keyIsLoaded = function () {
  return !! gcmKey;
};
<commit_msg>Update inaccurate comment about AAD data.<commit_after>var crypto = require("crypto");
var gcmKey = null;
var OAuthEncryption = exports.OAuthEncryption = {};

// Node leniently ignores non-base64 characters when parsing a base64
// string, but we want to provide a more informative error message if
// the developer doesn't use base64 encoding.
//
// Note that an empty string is valid base64 (denoting 0 bytes).
//
// Exported for the convenience of tests.
//
OAuthEncryption._isBase64 = function (str) {
  return _.isString(str) && /^[A-Za-z0-9\+\/]*\={0,2}$/.test(str);
};

// Loads the OAuth secret key, which must be 16 bytes in length
// encoded in base64.
//
// The key may be `null` which reverts to having no key (mainly used
// by tests).
//
OAuthEncryption.loadKey = function (key) {
  if (key === null) {
    gcmKey = null;
    return;
  }

  if (! OAuthEncryption._isBase64(key))
    throw new Error("The OAuth encryption key must be encoded in base64");

  var buf = new Buffer(key, "base64");

  if (buf.length !== 16)
    throw new Error("The OAuth encryption AES-128-GCM key must be 16 bytes in length");

  gcmKey = buf;
};

// Encrypt `data`, which may be any EJSON-compatible object, using the
// previously loaded OAuth secret key.
//
// The `userId` argument is optional. The data is encrypted as { data:
// *, userId: * }. When the result of `seal` is passed to `open`, the
// same user id must be supplied, which prevents user specific
// credentials such as access tokens from being used by a different
// user.
//
// We might someday like the user id to be AAD (additional authenticated
// data), but the Node 0.10.x crypto API did not support specifying AAD,
// and it's not clear that we want to incur the compatibility issues of
// relying on that feature, even though it's now supported by Node 4.
//
OAuthEncryption.seal = function (data, userId) {
  if (! gcmKey) {
    throw new Error("No OAuth encryption key loaded");
  }

  var plaintext = new Buffer(EJSON.stringify({
    data: data,
    userId: userId
  }));

  var iv = crypto.randomBytes(12);
  var cipher = crypto.createCipheriv("aes-128-gcm", gcmKey, iv);
  cipher.setAAD(new Buffer([]));
  var chunks = [cipher.update(plaintext)];
  chunks.push(cipher.final());
  var encrypted = Buffer.concat(chunks);

  return {
    iv: iv.toString("base64"),
    ciphertext: encrypted.toString("base64"),
    algorithm: "aes-128-gcm",
    authTag: cipher.getAuthTag().toString("base64")
  };
};

// Decrypt the passed ciphertext (as returned from `seal`) using the
// previously loaded OAuth secret key.
//
// `userId` must match the user id passed to `seal`: if the user id
// wasn't specified, it must not be specified here, if it was
// specified, it must be the same user id.
//
// To prevent an attacker from breaking the encryption key by
// observing the result of sending manipulated ciphertexts, `open`
// throws "decryption unsuccessful" on any error.
OAuthEncryption.open = function (ciphertext, userId) {
  if (! gcmKey)
    throw new Error("No OAuth encryption key loaded");

  try {
    if (ciphertext.algorithm !== "aes-128-gcm") {
      throw new Error();
    }

    var decipher = crypto.createDecipheriv(
      "aes-128-gcm",
      gcmKey,
      new Buffer(ciphertext.iv, "base64")
    );

    decipher.setAAD(new Buffer([]));
    decipher.setAuthTag(new Buffer(ciphertext.authTag, "base64"));
    var chunks = [decipher.update(
      new Buffer(ciphertext.ciphertext, "base64"))];
    chunks.push(decipher.final());
    var plaintext = Buffer.concat(chunks).toString("utf8");

    var err;
    var data;

    try {
      data = EJSON.parse(plaintext);
    } catch (e) {
      err = new Error();
    }

    if (data.userId !== userId) {
      err = new Error();
    }

    if (err) {
      throw err;
    } else {
      return data.data;
    }
  } catch (e) {
    throw new Error("decryption failed");
  }
};

OAuthEncryption.isSealed = function (maybeCipherText) {
  return maybeCipherText &&
    OAuthEncryption._isBase64(maybeCipherText.iv) &&
    OAuthEncryption._isBase64(maybeCipherText.ciphertext) &&
    OAuthEncryption._isBase64(maybeCipherText.authTag) &&
    _.isString(maybeCipherText.algorithm);
};

OAuthEncryption.keyIsLoaded = function () {
  return !! gcmKey;
};
<|endoftext|>


<commit_before>import omi from 'omi'
import 'omi-router';

let appOption = null
function App(option) {
  appOption = option
}

function getApp() {
  return appOption
}

function Page(option) {
  return option
}

function Component(option) {
  return option
}

function noop() {}
const wx = {}
wx.canIUse = function() {
  return false
}

wx.getSystemInfoSync = function() {
  return {
    windowWidth: window.innerWidth,
    windowHeight: window.innerHeight
  }
}

wx.getUserInfo = function() {}

//用户可以有个开关不转
window.rpx2px = function(str) {
  return str.replace(/([0-9]*)rpx/g, (a, b) => {
    return (window.innerWidth * Number(b)) / 750 + 'px'
  })
}

wx.navigateTo = function(option){
  route.to(option.url)
}

window.wx = wx
window.App = App
window.getApp = getApp
window.Page = Page
window.Component = Component
<commit_msg>remove dead code<commit_after>import 'omi-router';

let appOption = null
function App(option) {
  appOption = option
}

function getApp() {
  return appOption
}

function Page(option) {
  return option
}

function Component(option) {
  return option
}

function noop() {}
const wx = {}
wx.canIUse = function() {
  return false
}

wx.getSystemInfoSync = function() {
  return {
    windowWidth: window.innerWidth,
    windowHeight: window.innerHeight
  }
}

wx.getUserInfo = function() {}

//用户可以有个开关不转
window.rpx2px = function(str) {
  return str.replace(/([0-9]*)rpx/g, (a, b) => {
    return (window.innerWidth * Number(b)) / 750 + 'px'
  })
}

wx.navigateTo = function(option){
  route.to(option.url)
}

window.wx = wx
window.App = App
window.getApp = getApp
window.Page = Page
window.Component = Component
<|endoftext|>


<commit_before>var S = require('string');
var _ = require('underscore');

function formatInt(code) {
    var ret = '';
    if (code < 10) ret += '0';
    return (ret += code);
}

module.exports = {
    /**
    * Send empty response according to the response format
    *
    * @param {object} res A response object
    * @param {string} type Aresponse format
    * @returns {void}
    */
    sendEmptyResponse : function (res, type) {
        if (type === 'xml') {
            var builder = require('xmlbuilder');

            var xml = builder.create('geonames', {
                'version':'1.0',
                'encoding':'UTF-8'
            });

            xml.e('totalResultsCount', '0');

            res.send(xml.end({pretty:true}));
        } else  {
             res.jsonp({geonames: {'totalResultsCount': 0}});
        }
    },
    /**
    * Construct the Elastic search connection string
    *
    * @param {string} host
    * @param {string} dbname
    * @param {string} dbcollection
    * @returns {String}
    */
    getElasticSearchEndpoint: function (host, dbname, dbcollection) {
       return 'http://'
           + S(host).ensureRight('/')
           + S(dbname).ensureRight('/')
           + S(dbcollection).ensureRight('/')
           + '_search';
    },
    /**
     * Converts ES hits to an array, in order to improve readability.
     * Also fills up an array with admincodes.
     *
     * @param {type} hits
     * @returns {module.exports.formatHits.ret}
     */
    formatHits: function (hits)
    {
        var ret = {data: [], admincodes: []};

        var results = JSON.parse(hits)['hits']['hits'] || [];

        _.each(results, function (o) {
            var fields = o.fields;

            if (fields.hasOwnProperty('admin1Code')) {
                var code = fields.countryCode + '.' + formatInt(fields.admin1Code);
                fields.adminCode = code;
                ret.admincodes.push(code);
            }

            ret.data.push(fields);
        });

        return ret;
    },
    /*
     ** Returns the alt_title, used when the query only matches with an alternate name
     */
    getAltTitle: function (names, match)
    {
        for (var i in names){
            for (var j = 0; names[i].charAt(j); j++)
            {
                var k = 0;
                var l = j;
                if (names[i].charAt(j) === match.charAt(k)
                    && (j === 0 || (names[i].charAt(j - 1)
                        && (names[i].charAt(j - 1) === ' '
                            || names[i].charAt(j - 1) === '-'
                            || names[i].charAt(j - 1) === '~'))))
                            {
                    while (names[i].charAt(l) && match.charAt(k)
                        && names[i].charAt(l) === match.charAt(k))
                        {
                        k++;
                        l++;
                    }
                    if (!match.charAt(k))
                        return (names[i]);
                }
            }
        }
        for (i in names){
            var pos = names[i].indexOf(match);
            if (pos !== -1)
                return (names[i]);
        }
        return (match);
    },
    /**
     * Returns the part of the city/country name that matches with the query.
     * Checks both 'name' and 'alternate names'
     *
     * @param   {string} queryString    The client query
     * @param   {string} inBaseName     The in base name
     * @param   {string} alternativeNames   the alternate names
     * @returns {getMatch.inBaseName|getMatch.queryString}
     */
    getMatch: function (queryString, inBaseName, alternativeNames)
    {
        if (queryString === inBaseName) {
            return queryString;
        }

        if (queryString && inBaseName) {
            if (S(inBaseName.toLowerCase()).contains(queryString)) {
                var match = _.find(alternativeNames, function(name) {
                    return S(name.toLowerCase()).contains(queryString);
                });

                return  'undefined' !== match ? inBaseName : queryString;
            }
        }

        return queryString;
    },
    // see http://jsfiddle.net/DanielD/8S4nq/
    isIpV4: function(str) {

        var regexp = /^\s*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\s*$/;
        return regexp.test(str);
    }
};<commit_msg>Add mongo connection string builder & enhance elastic search one<commit_after>var S = require('string');
var _ = require('underscore');

function formatInt(code) {
    var ret = '';
    if (code < 10) ret += '0';
    return (ret += code);
}

module.exports = {
    /**
    * Send empty response according to the response format
    *
    * @param {object} res A response object
    * @param {string} type Aresponse format
    * @returns {void}
    */
    sendEmptyResponse : function (res, type) {
        if (type === 'xml') {
            var builder = require('xmlbuilder');

            var xml = builder.create('geonames', {
                'version':'1.0',
                'encoding':'UTF-8'
            });

            xml.e('totalResultsCount', '0');

            res.send(xml.end({pretty:true}));
        } else  {
             res.jsonp({geonames: {'totalResultsCount': 0}});
        }
    },
    /**
    * Construct the Elastic search connection string
    *
    * @param {string} host
    * @param {string} dbname
    * @param {string} dbcollection
    * @returns {String}
    */
    getElasticSearchEndpoint: function (scheme, host, port, cluster, node) {
        var port = port || 9200;

        return scheme + '://'
            + S(host).chompRight('/')
            + ':' + S(port).ensureRight('/')
            + S(cluster).ensureRight('/')
            + S(node).ensureRight('/')
            + '_search';
    },
    getMongoConnectionString: function(host, port, user, pass, database) {
        user = user || '';
        pass = pass || '';
        port = port || 27017;
        database = database || '';

        var credentials = user + ('' !== pass ? ':' + pass + '@' : ('' !== user ? '@' : ''));

        return credentials
           + host
           + ':' + S(port).ensureRight('/').s
           + database;
    },
    /**
     * Converts ES hits to an array, in order to improve readability.
     * Also fills up an array with admincodes.
     *
     * @param {type} hits
     * @returns {module.exports.formatHits.ret}
     */
    formatHits: function (hits)
    {
        var ret = {data: [], admincodes: []};

        var results = JSON.parse(hits)['hits']['hits'] || [];

        _.each(results, function (o) {
            var fields = o.fields;

            if (fields.hasOwnProperty('admin1Code')) {
                var code = fields.countryCode + '.' + formatInt(fields.admin1Code);
                fields.adminCode = code;
                ret.admincodes.push(code);
            }

            ret.data.push(fields);
        });

        return ret;
    },
    /*
     ** Returns the alt_title, used when the query only matches with an alternate name
     */
    getAltTitle: function (names, match)
    {
        for (var i in names){
            for (var j = 0; names[i].charAt(j); j++)
            {
                var k = 0;
                var l = j;
                if (names[i].charAt(j) === match.charAt(k)
                    && (j === 0 || (names[i].charAt(j - 1)
                        && (names[i].charAt(j - 1) === ' '
                            || names[i].charAt(j - 1) === '-'
                            || names[i].charAt(j - 1) === '~'))))
                            {
                    while (names[i].charAt(l) && match.charAt(k)
                        && names[i].charAt(l) === match.charAt(k))
                        {
                        k++;
                        l++;
                    }
                    if (!match.charAt(k))
                        return (names[i]);
                }
            }
        }
        for (i in names){
            var pos = names[i].indexOf(match);
            if (pos !== -1)
                return (names[i]);
        }
        return (match);
    },
    /**
     * Returns the part of the city/country name that matches with the query.
     * Checks both 'name' and 'alternate names'
     *
     * @param   {string} queryString    The client query
     * @param   {string} inBaseName     The in base name
     * @param   {string} alternativeNames   the alternate names
     * @returns {getMatch.inBaseName|getMatch.queryString}
     */
    getMatch: function (queryString, inBaseName, alternativeNames)
    {
        if (queryString === inBaseName) {
            return queryString;
        }

        if (queryString && inBaseName) {
            if (S(inBaseName.toLowerCase()).contains(queryString)) {
                var match = _.find(alternativeNames, function(name) {
                    return S(name.toLowerCase()).contains(queryString);
                });

                return  'undefined' !== match ? inBaseName : queryString;
            }
        }

        return queryString;
    },
    // see http://jsfiddle.net/DanielD/8S4nq/
    isIpV4: function(str) {

        var regexp = /^\s*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\s*$/;
        return regexp.test(str);
    }
};<|endoftext|>


<commit_before>var douban_api_key = 'dsfdfdfdfdfdfdsfsdfdsf';//replace this value with your 豆瓣app_key
<commit_msg>Delete api_key.js<commit_after><|endoftext|>


<commit_before>////////////////////////////////////////////////////////////
// Sails
// common.js
////////////////////////////////////////////////////////////
// Define app and configuration object
var sails = {
	config: {}
};

// Utility libs
var _ = require('underscore');
_.str = require('underscore.string');
var async = require('async');

// TODO: remove this
//////////////////////////////
global['_'] = _;
global['sails'] = sails;
global['async'] = async;
//////////////////////////////

// Node.js dependencies
var fs = require('fs');
var path = require('path');

// Routing and HTTP server
var express = require('express');

// WebSocket server (+polyfill support)
var socketio = require('socket.io');

// Templating
var ejs = require('ejs');

// Sails ecosystem dependencies
var rigging = require('rigging');
var waterline = require('waterline');
var modules = require('sails-moduleloader');
var util = require('sails-util');

// Internal dependencies
// var util = require('./util');
var configuration = require("./configuration");
var pubsub = require('./rooms');

// TODO: allow global access to even those objects to be disabled in config

/**
 * Load and initialize the app
 */
exports.lift = function liftSails(userConfig, cb) {
	exports.load(userConfig, function() {
		exports.initialize(userConfig, cb);
	});
};
exports.hoist = exports.lift;
exports.start = exports.lift;

/**
 * Load the dependencies and app-specific components
 */
exports.load = function loadSails(userConfig, cb) {

	// Merge user config with defaults
	sails.config = configuration.build(configuration.defaults(userConfig), userConfig);

	// Initialize captains logger
	sails.log = require('./logger')(sails.config.log);

	// Pass logger down to submodules
	rigging = rigging({log: sails.log});

	// Validate user config
	sails.config = configuration.validate(sails.config, userConfig);

	// EXPERIMENTAL connect v2 support
	// see https://github.com/senchalabs/connect/issues/588
	//var connect = require('connect');
	//var connectCookie = require('cookie');
	//var cookieSecret = "k3yboard_kat";
	//parseCookie = function(cookie) {
	//	return connect.utils.parseSignedCookies(connectCookie.parse(decodeURIComponent(cookie)),cookieSecret);
	//}
	var connect = require('connect');
	parseCookie = connect.utils.parseCookie;
	ConnectSession = connect.middleware.session.Session;

	// Override the environment variable so express mirrors the sails env:
	process.env['NODE_ENV'] = sails.config.environment;

	// Load app's models and custom adapters
	// Case-insensitive, using filename to determine identity
	// (default waterline adapters are included automatically)
	sails.models = modules.optional({
		dirname		: sails.config.appPath + '/models',
		filter		: /(.+)\.js$/
	});
	sails.adapters = modules.optional({
		dirname		: sails.config.appPath + '/adapters',
		filter		: /(.+Adapter)\.js$/,
		replaceExpr	: /Adapter/
	});

	// Load app's logic modules (case-insensitive)
	sails.controllers = modules.optional({
		dirname		: sails.config.appPath + '/controllers',
		filter		: /(.+)Controller\.js$/,
		replaceExpr	: /Controller/
	});
	sails.services = modules.optional({
		dirname		: sails.config.appPath + '/services',
		filter		: /(.+)\.js$/,
		replaceExpr	: /Service/
	});
	sails.middleware = modules.optional({
		dirname		: sails.config.appPath + '/middleware',
		filter		: /(.+)\.js$/,
		replaceExpr	: null
	});

	// Augment models with room/socket logic (& bind context)
	for (var identity in sails.models) {
		sails.models[identity] = _.extend(sails.models[identity],pubsub);
		_.bindAll(sails.models[identity], 'subscribe', 'introduce', 'unsubscribe', 'publish', 'room');
	}

	// Start up waterline (ORM) and pass in adapters, models, and logger
	waterline({
		adapters: sails.adapters,
		collections: sails.models,
		log: sails.log
	}, function afterWaterlineInstantiated (err, instantiatedModules){
		if (err) throw new Error(err);

		// Make instantiated adapters and collections globally accessible
		sails.adapters = instantiatedModules.adapters;
		sails.models = sails.collections = instantiatedModules.collections;

		// Run boostrap script
		if (sails.config.bootstrap) sails.config.bootstrap(afterBootstrap);
		else afterBootstrap();

		function afterBootstrap () {
			require('./express.js').configure();
			cb && cb();
		}
	});
};

// Get socket interpreter
var socketInterpreter = require("./interpreter");

// Initialize the app (start the servers)
exports.initialize = function initSails(userConfig, cb) {

	// Listen for websocket connections (and rejects) through socket.io
	var io = sails.io = socketio.listen(sails.express.app);

	// Configure socket.io
	function commonSocketIOConfig() {
		io.set('log level', 0);
	}
	io.configure('development', function() {
		commonSocketIOConfig();
	});
	io.configure('production', function() {
		commonSocketIOConfig();
	});

	// logic modules USED TO BE HERE!!!

	// Get federated controllers where actions are specified each in their own file
	var federatedControllers = modules.optional({
		dirname			: sails.config.appPath + '/controllers',
		pathFilter		: /(.+)\/(.+)\.js$/
	});
	sails.controllers = _.extend(sails.controllers,federatedControllers);

	// Load app policy tree
	sails.policy = require("./policy");

	// Load route config
	sails.routes = require('./routes');

	// Map Routes
	// Link Express HTTP requests to a function which handles them
	// *** NOTE: MUST BE AFTER app.configure in order for bodyparser to work ***
	require('./router').listen(function(url, fn, httpVerb) {
		// Use all,get,post,put,or delete conditionally based on http verb
		// null === *any* of the HTTP verbs
		if(!httpVerb) {
			sails.express.app.all(url, fn);
		} else {
			_.isFunction(sails.express.app[httpVerb]) && sails.express.app[httpVerb](url, fn);
		}
	});

	// Link Socket.io requests to a controller/action
	// When a socket.io client connects, listen for the actions in the routing table
	io.sockets.on('connection', function(socket) {
		sails.log.verbose("New socket.io client connected!", socket.id);

		// Cookie is socket.handshake.headers.cookie
		// Maybe do something w/ it later
		// Prune data from the session to avoid sharing anything inadvertently
		// By default, very restrictive
		var pruneFn = sails.config.sessionPruneFn || function(session) {
			return {};
		};

		// Respond w/ information about session
		socket.emit('sessionUpdated', pruneFn(socket.handshake.session));

		// Map routes
		socket.on('message', function(socketReq, fn) {
			socketInterpreter.route(socketReq, fn, socket);
		});
	});

	// Compile Mast components, if Rigging is in place
	sails.log.verbose("Initializing rigging middleware...");
	rigging.compile(sails.config.rigging.sequence, {
		environment: sails.config.environment,
		outputPath: sails.config.rigging.outputPath
	}, function(err) {
		if(err) {
			sails.log.error("Unable to compile assets.");
			sails.log.error(err);
			startServers();
		} else startServers();
	});

	// Add beforeShutdown event
	if(_.isFunction(sails.config.beforeShutdown)) {
		process.on('SIGINT', function() {
			process.exit();
		});
		process.on('SIGTERM', function() {
			process.exit();
		});
		process.on('exit', function() {
			sails.config.beforeShutdown();
		});
	}

	// Provide global access (if allowed in config)
	// TODO: support disablement of _, sails, and async globalization
	// if (sails.config.globals._) global['_'] = _;
	// if (sails.config.globals.async) global['async'] = async;
	// if (sails.config.globals.sails) global['sails'] = sails;
	// TODO: support models and adapter globalization (pass config into waterline)
	if (sails.config.globals.services) {
		_.each(sails.services,function (service,identity) {
			var globalName = _.str.capitalize(identity)+'Service';
			global[globalName] = service;
		});
	}

	// start the ws(s):// and http(s):// servers
	function startServers() {

		// Start http(s):// server
		sails.express.server = sails.express.app.listen(sails.config.port);
		if(!sails.express.app.address()) {
			sails.log.warn('Error detecting sails.express.app.address().');
			sails.log.warn('Usually this means you have another instance of Sails, or something else, running on this port.');
		} else {
			sails.log.info('Sails lifted on port ' + sails.express.app.address().port +
							' in ' + sails.express.app.settings.env + ' mode');
		}

		// Configure auth for ws(s):// server
		io.set('authorization', function(data, accept) {
			// If a cookie was provided in the query string, use it.
			if (data.query.cookie) {
				data.headers.cookie = data.query.cookie;
			}

			// Attach authorization middleware to socket event receiver
			if(data.headers.cookie) {
				// TODO: Support for Express 3.x, see:
				// https://gist.github.com/3337459
				// https://groups.google.com/forum/?fromgroups=#!topic/socket_io/pMuHFFZRfpQ

				// Solution found here in connect source code:
				// https://github.com/senchalabs/connect/blob/master/lib/middleware/session.js

				data.cookie = parseCookie(data.headers.cookie);

				data.sessionID = data.cookie[sails.config.session.key];
				data.sessionStore = sails.config.session.store;

				// (literally) get the session handshake from the session store
				sails.config.session.store.get(data.sessionID, function(err, session) {
					// An error occurred, so refuse the connection
					if(err) {
						accept('Error loading session from socket.io! \n' + err, false);
					}
					// Cookie is invalid, so regenerate a new one
					else if(!session) {
						data.session = new ConnectSession(data, {
							cookie: {
								// Prevent access from client-side javascript
								httpOnly: true
							}
						});
						sails.log.verbose("Generated new session....", data);
						accept(null, true);
					}

					// Save the session handshake and accept the connection
					else {
						// Create a session object, passing our just-acquired session handshake
						data.session = new ConnectSession(data, session);
						sails.log.verbose("Connected to existing session....");
						accept(null, true);
					}
				});
			} else {
				return accept('No cookie transmitted with socket.io connection.', false);
			}
		});

		// Trigger sails.initialize() callback if specified
		cb && cb(null, sails);
	}
};

/**
 * Kill the http and socket.io servers
 */
exports.lower = function lowerSails(cb) {
	sails.express.server.close();

	// This is probably unnecessary (seems to be killing it when express server is killed)
	// io.server.close();
};
exports.stop = exports.lower;
exports.close = exports.lower;
exports.kill = exports.lower;

// Export sails object
exports.sails = sails;<commit_msg>Made services globally accessible before bootstrap.<commit_after>////////////////////////////////////////////////////////////
// Sails
// common.js
////////////////////////////////////////////////////////////
// Define app and configuration object
var sails = {
	config: {}
};

// Utility libs
var _ = require('underscore');
_.str = require('underscore.string');
var async = require('async');

// TODO: remove this
//////////////////////////////
global['_'] = _;
global['sails'] = sails;
global['async'] = async;
//////////////////////////////

// Node.js dependencies
var fs = require('fs');
var path = require('path');

// Routing and HTTP server
var express = require('express');

// WebSocket server (+polyfill support)
var socketio = require('socket.io');

// Templating
var ejs = require('ejs');

// Sails ecosystem dependencies
var rigging = require('rigging');
var waterline = require('waterline');
var modules = require('sails-moduleloader');
var util = require('sails-util');

// Internal dependencies
// var util = require('./util');
var configuration = require("./configuration");
var pubsub = require('./rooms');

// TODO: allow global access to even those objects to be disabled in config

/**
 * Load and initialize the app
 */
exports.lift = function liftSails(userConfig, cb) {
	exports.load(userConfig, function() {
		exports.initialize(userConfig, cb);
	});
};
exports.hoist = exports.lift;
exports.start = exports.lift;

/**
 * Load the dependencies and app-specific components
 */
exports.load = function loadSails(userConfig, cb) {

	// Merge user config with defaults
	sails.config = configuration.build(configuration.defaults(userConfig), userConfig);

	// Initialize captains logger
	sails.log = require('./logger')(sails.config.log);

	// Pass logger down to submodules
	rigging = rigging({log: sails.log});

	// Validate user config
	sails.config = configuration.validate(sails.config, userConfig);

	// EXPERIMENTAL connect v2 support
	// see https://github.com/senchalabs/connect/issues/588
	//var connect = require('connect');
	//var connectCookie = require('cookie');
	//var cookieSecret = "k3yboard_kat";
	//parseCookie = function(cookie) {
	//	return connect.utils.parseSignedCookies(connectCookie.parse(decodeURIComponent(cookie)),cookieSecret);
	//}
	var connect = require('connect');
	parseCookie = connect.utils.parseCookie;
	ConnectSession = connect.middleware.session.Session;

	// Override the environment variable so express mirrors the sails env:
	process.env['NODE_ENV'] = sails.config.environment;

	// Load app's models and custom adapters
	// Case-insensitive, using filename to determine identity
	// (default waterline adapters are included automatically)
	sails.models = modules.optional({
		dirname		: sails.config.appPath + '/models',
		filter		: /(.+)\.js$/
	});
	sails.adapters = modules.optional({
		dirname		: sails.config.appPath + '/adapters',
		filter		: /(.+Adapter)\.js$/,
		replaceExpr	: /Adapter/
	});

	// Augment models with room/socket logic (& bind context)
	for (var identity in sails.models) {
		sails.models[identity] = _.extend(sails.models[identity],pubsub);
		_.bindAll(sails.models[identity], 'subscribe', 'introduce', 'unsubscribe', 'publish', 'room');
	}

	// Start up waterline (ORM) and pass in adapters, models, and logger
	waterline({
		adapters: sails.adapters,
		collections: sails.models,
		log: sails.log
	}, function afterWaterlineInstantiated (err, instantiatedModules){
		if (err) throw new Error(err);

		// Make instantiated adapters and collections globally accessible
		sails.adapters = instantiatedModules.adapters;
		sails.models = sails.collections = instantiatedModules.collections;

		// Load app's logic modules (case-insensitive)
		sails.controllers = modules.optional({
			dirname		: sails.config.appPath + '/controllers',
			filter		: /(.+)Controller\.js$/,
			replaceExpr	: /Controller/
		});
		sails.services = modules.optional({
			dirname		: sails.config.appPath + '/services',
			filter		: /(.+)\.js$/,
			replaceExpr	: /Service/
		});
		sails.middleware = modules.optional({
			dirname		: sails.config.appPath + '/middleware',
			filter		: /(.+)\.js$/,
			replaceExpr	: null
		});

		// Provide global access (if allowed in config)
		// TODO: support disablement of _, sails, and async globalization
		// if (sails.config.globals._) global['_'] = _;
		// if (sails.config.globals.async) global['async'] = async;
		// if (sails.config.globals.sails) global['sails'] = sails;
		// TODO: support models and adapter globalization (pass config into waterline)
		if (sails.config.globals.services) {
			_.each(sails.services,function (service,identity) {
				var globalName = _.str.capitalize(identity)+'Service';
				global[globalName] = service;
			});
		}

		// Run boostrap script
		if (sails.config.bootstrap) sails.config.bootstrap(afterBootstrap);
		else afterBootstrap();

		function afterBootstrap () {
			require('./express.js').configure();
			cb && cb();
		}
	});
};

// Get socket interpreter
var socketInterpreter = require("./interpreter");

// Initialize the app (start the servers)
exports.initialize = function initSails(userConfig, cb) {

	// Listen for websocket connections (and rejects) through socket.io
	var io = sails.io = socketio.listen(sails.express.app);

	// Configure socket.io
	function commonSocketIOConfig() {
		io.set('log level', 0);
	}
	io.configure('development', function() {
		commonSocketIOConfig();
	});
	io.configure('production', function() {
		commonSocketIOConfig();
	});

	// logic modules USED TO BE HERE!!!

	// Get federated controllers where actions are specified each in their own file
	var federatedControllers = modules.optional({
		dirname			: sails.config.appPath + '/controllers',
		pathFilter		: /(.+)\/(.+)\.js$/
	});
	sails.controllers = _.extend(sails.controllers,federatedControllers);

	// Load app policy tree
	sails.policy = require("./policy");

	// Load route config
	sails.routes = require('./routes');

	// Map Routes
	// Link Express HTTP requests to a function which handles them
	// *** NOTE: MUST BE AFTER app.configure in order for bodyparser to work ***
	require('./router').listen(function(url, fn, httpVerb) {
		// Use all,get,post,put,or delete conditionally based on http verb
		// null === *any* of the HTTP verbs
		if(!httpVerb) {
			sails.express.app.all(url, fn);
		} else {
			_.isFunction(sails.express.app[httpVerb]) && sails.express.app[httpVerb](url, fn);
		}
	});

	// Link Socket.io requests to a controller/action
	// When a socket.io client connects, listen for the actions in the routing table
	io.sockets.on('connection', function(socket) {
		sails.log.verbose("New socket.io client connected!", socket.id);

		// Cookie is socket.handshake.headers.cookie
		// Maybe do something w/ it later
		// Prune data from the session to avoid sharing anything inadvertently
		// By default, very restrictive
		var pruneFn = sails.config.sessionPruneFn || function(session) {
			return {};
		};

		// Respond w/ information about session
		socket.emit('sessionUpdated', pruneFn(socket.handshake.session));

		// Map routes
		socket.on('message', function(socketReq, fn) {
			socketInterpreter.route(socketReq, fn, socket);
		});
	});

	// Compile Mast components, if Rigging is in place
	sails.log.verbose("Initializing rigging middleware...");
	rigging.compile(sails.config.rigging.sequence, {
		environment: sails.config.environment,
		outputPath: sails.config.rigging.outputPath
	}, function(err) {
		if(err) {
			sails.log.error("Unable to compile assets.");
			sails.log.error(err);
			startServers();
		} else startServers();
	});

	// Add beforeShutdown event
	if(_.isFunction(sails.config.beforeShutdown)) {
		process.on('SIGINT', function() {
			process.exit();
		});
		process.on('SIGTERM', function() {
			process.exit();
		});
		process.on('exit', function() {
			sails.config.beforeShutdown();
		});
	}

	// start the ws(s):// and http(s):// servers
	function startServers() {

		// Start http(s):// server
		sails.express.server = sails.express.app.listen(sails.config.port);
		if(!sails.express.app.address()) {
			sails.log.warn('Error detecting sails.express.app.address().');
			sails.log.warn('Usually this means you have another instance of Sails, or something else, running on this port.');
		} else {
			sails.log.info('Sails lifted on port ' + sails.express.app.address().port +
							' in ' + sails.express.app.settings.env + ' mode');
		}

		// Configure auth for ws(s):// server
		io.set('authorization', function(data, accept) {
			// If a cookie was provided in the query string, use it.
			if (data.query.cookie) {
				data.headers.cookie = data.query.cookie;
			}

			// Attach authorization middleware to socket event receiver
			if(data.headers.cookie) {
				// TODO: Support for Express 3.x, see:
				// https://gist.github.com/3337459
				// https://groups.google.com/forum/?fromgroups=#!topic/socket_io/pMuHFFZRfpQ

				// Solution found here in connect source code:
				// https://github.com/senchalabs/connect/blob/master/lib/middleware/session.js

				data.cookie = parseCookie(data.headers.cookie);

				data.sessionID = data.cookie[sails.config.session.key];
				data.sessionStore = sails.config.session.store;

				// (literally) get the session handshake from the session store
				sails.config.session.store.get(data.sessionID, function(err, session) {
					// An error occurred, so refuse the connection
					if(err) {
						accept('Error loading session from socket.io! \n' + err, false);
					}
					// Cookie is invalid, so regenerate a new one
					else if(!session) {
						data.session = new ConnectSession(data, {
							cookie: {
								// Prevent access from client-side javascript
								httpOnly: true
							}
						});
						sails.log.verbose("Generated new session....", data);
						accept(null, true);
					}

					// Save the session handshake and accept the connection
					else {
						// Create a session object, passing our just-acquired session handshake
						data.session = new ConnectSession(data, session);
						sails.log.verbose("Connected to existing session....");
						accept(null, true);
					}
				});
			} else {
				return accept('No cookie transmitted with socket.io connection.', false);
			}
		});

		// Trigger sails.initialize() callback if specified
		cb && cb(null, sails);
	}
};

/**
 * Kill the http and socket.io servers
 */
exports.lower = function lowerSails(cb) {
	sails.express.server.close();

	// This is probably unnecessary (seems to be killing it when express server is killed)
	// io.server.close();
};
exports.stop = exports.lower;
exports.close = exports.lower;
exports.kill = exports.lower;

// Export sails object
exports.sails = sails;<|endoftext|>


<commit_before>function filenameChange(elem, id) {
    var filename = elem.value;
    var hasExt = filename.indexOf(".") != -1;
    if (hasExt) {
        $('#typeselect_' + id).hide();
        $('#typetext_' + id).show();
    } else {
        $('#typeselect_' + id).show();
        $('#typetext_' + id).hide();
    }
}

function initEdit()
{
    initFilenames();
    initAdditionals();
    $('.filegroup:visible:last textarea').focus();
}
function initFilenames()
{
    $('input.filename').each(
        function(num, elem) {
            var id = elem.id;
            var pos = id.indexOf('_');
            if (pos != -1) {
                var elemNum = id.substr(pos + 1);
                if (elemNum != 'new') {
                    filenameChange(elem, elemNum);
                }
            }
        }
    );
}
function initAdditionals()
{
    $('a.additional-btn').each(
        function(num, elem) {
            toggleAdditional(elem, 0);
            $(elem).show();
        }
    );
}

function toggleAdditional(elem, time)
{
    if (undefined == time) {
        time = 'fast';
    }
    var jt = jQuery(elem);
    jt.children('i').toggleClass('icon-chevron-down')
        .toggleClass('icon-chevron-up');
    //jt.parents('.row-fluid').children('.additional').toggle(time);
    jt.parents('.row-fluid').children('.additional').animate(time);
}
<commit_msg>fix accidential bug in last commit<commit_after>function filenameChange(elem, id) {
    var filename = elem.value;
    var hasExt = filename.indexOf(".") != -1;
    if (hasExt) {
        $('#typeselect_' + id).hide();
        $('#typetext_' + id).show();
    } else {
        $('#typeselect_' + id).show();
        $('#typetext_' + id).hide();
    }
}

function initEdit()
{
    initFilenames();
    initAdditionals();
    $('.filegroup:visible:last textarea').focus();
}
function initFilenames()
{
    $('input.filename').each(
        function(num, elem) {
            var id = elem.id;
            var pos = id.indexOf('_');
            if (pos != -1) {
                var elemNum = id.substr(pos + 1);
                if (elemNum != 'new') {
                    filenameChange(elem, elemNum);
                }
            }
        }
    );
}
function initAdditionals()
{
    $('a.additional-btn').each(
        function(num, elem) {
            toggleAdditional(elem, 0);
            $(elem).show();
        }
    );
}

function toggleAdditional(elem, time)
{
    if (undefined == time) {
        time = 'fast';
    }
    var jt = jQuery(elem);
    jt.children('i').toggleClass('icon-chevron-down')
        .toggleClass('icon-chevron-up');
    jt.parents('.row-fluid').children('.additional').toggle(time);
    //jt.parents('.row-fluid').children('.additional').animate(time);
}
<|endoftext|>


<commit_before>'use strict';

const fs      = require('fs');
const path    = require('path');
const co      = require('co');

const defaults = exports.defaults = {
  baseUrl: 'https://ezmesure.couperin.org/api'
};

/**
 * Find the nearest config file
 * @param <String> startPath  optional start path, defaults to working dir
 */
exports.find = co.wrap(function* (startPath) {
  let dir = path.resolve(startPath || process.cwd());

  try {
    yield getStats(path.resolve(dir, '.ezmesurerc'));
    return path.resolve(dir, '.ezmesurerc');
  } catch (err) {
    if (err.code !== 'ENOENT') { return Promise.reject(err); }
  }

  if (path.dirname(dir) !== dir) {
    return exports.find(path.dirname(dir));
  }

  return null;
});

/**
 * Load config with either a plain object or a path to a config file
 */
exports.load = function (config) {
  return new Promise((resolve, reject) => {
    if (typeof config === 'object') {
      Object.assign(defaults, config);
      return resolve();
    }

    if (typeof config !== 'string') {
      return reject(new Error('config should be either an object or a string'));
    }

    fs.readFile(path.resolve(config), 'utf-8', (err, content) => {
      if (err) { return reject(err); }

      try {
        Object.assign(defaults, JSON.parse(content));
      } catch (e) {
        return reject(e);
      }

      resolve();
    });
  });
};

/**
 * Promisified fs.stat
 */
function getStats(file) {
  return new Promise((resolve, reject) => {
    fs.stat(file, (err, stats) => {
      if (err) { return reject(err); }
      resolve(stats);
    });
  });
}
<commit_msg>cosmetic<commit_after>'use strict';

const fs   = require('fs');
const path = require('path');
const co   = require('co');

const defaults = exports.defaults = {
  baseUrl: 'https://ezmesure.couperin.org/api'
};

/**
 * Find the nearest config file
 * @param <String> startPath  optional start path, defaults to working dir
 */
exports.find = co.wrap(function* (startPath) {
  let dir = path.resolve(startPath || process.cwd());

  try {
    yield getStats(path.resolve(dir, '.ezmesurerc'));
    return path.resolve(dir, '.ezmesurerc');
  } catch (err) {
    if (err.code !== 'ENOENT') { return Promise.reject(err); }
  }

  if (path.dirname(dir) !== dir) {
    return exports.find(path.dirname(dir));
  }

  return null;
});

/**
 * Load config with either a plain object or a path to a config file
 */
exports.load = function (config) {
  return new Promise((resolve, reject) => {
    if (typeof config === 'object') {
      Object.assign(defaults, config);
      return resolve();
    }

    if (typeof config !== 'string') {
      return reject(new Error('config should be either an object or a string'));
    }

    fs.readFile(path.resolve(config), 'utf-8', (err, content) => {
      if (err) { return reject(err); }

      try {
        Object.assign(defaults, JSON.parse(content));
      } catch (e) {
        return reject(e);
      }

      resolve();
    });
  });
};

/**
 * Promisified fs.stat
 */
function getStats(file) {
  return new Promise((resolve, reject) => {
    fs.stat(file, (err, stats) => {
      if (err) { return reject(err); }
      resolve(stats);
    });
  });
}
<|endoftext|>


<commit_before>// You can obtain these values by running:
// aws cloudformation describe-stacks --stack-name <YOUR STACK NAME> --query "Stacks[0].Outputs[]"

const config = {
  "aws_user_pools_web_client_id": "5ike2fb50ibl0k0qff5sr5c3ja",     // CognitoClientID
  "api_base_url": "https://s7yujxxc15.execute-api.us-east-1.amazonaws.com/prod",                                     // TodoFunctionApi
  "coginto_hosted_domain": "mytodoappdemo-lambda-issue-35.auth.us-east-1.amazoncognito.com",                   // CognitoDomainName
  "redirect_url": "https://amplify-console.d1el6ol1w70dql.amplifyapp.com"                                      // AmplifyURL
};

export default config;
<commit_msg>Frontend config update<commit_after>// You can obtain these values by running:
// aws cloudformation describe-stacks --stack-name <YOUR STACK NAME> --query "Stacks[0].Outputs[]"

const config = {
  "aws_user_pools_web_client_id": "2t6ql38oq0g12581d4tuq1vuo5",     // CognitoClientID
  "api_base_url": "https://i116m3u68d.execute-api.us-east-1.amazonaws.com/prod",                                     // TodoFunctionApi
  "coginto_hosted_domain": "mytodoappdemo-lambda-issue-35.auth.us-east-1.amazoncognito.com",                   // CognitoDomainName
  "redirect_url": "https://issue-35.d26y510u49hqga.amplifyapp.com"                                      // AmplifyURL
};

export default config;
<|endoftext|>


<commit_before>var _         = require('underscore');  // Util Module
var args      = require('commander');   // Command line processing module
var path      = require('path');        // File utility's
var cluster   = require('cluster');     // This is a cluster based server see --help for options
var prerender = require('prerender');

/**
 * Call this function to create and return a configured prerender.io rendering server
 *
 * @param cfg an object that is used to modify the behavior of the prerender service, if no value is
 * passed one is created for you.
 *
 * @returns {*} The prerender server object for this cluster worker
 */
exports.getPrerenderServer = function getPrerenderServer(cfg) {

    var server;

    cfg = cfg || this.getConfig();

    // The first time you need to modify the environment based on contents of cfg
    if (cluster.isMaster) {
        setPrerenderEnvironment(cfg.env);
        setPluginsEnvironment(cfg.plugins);
    }

    if ((server = prerender(cfg.options))) {
        loadPrerenderPlugins(cfg.plugins);
    }

    return server;
};

/**
 * Configures an object used to control the prerender server
 *
 * The function first constructs a default cfg object containing 3 child objects
 *
 *  options an object that contains prerender properties with default settings used to configure the service
 *
 *  env     an object that contains prerender process.env properties, typically you leave these alone but they
 *          can be used to override prerender defaults ( use with caution )
 *
 *  plugins an object that contains key's that map to prerender middleware, if set to true they will be loaded
 *
 * The function then looks at command line arguments, one of which allows a cfg file to be specified, this
 * file is a json formatted cfg object and if present will be used to add or overwrite objects and properties
 * in the cfg default object
 *
 * Finally the function uses any command line arguments to set final values of the cfg object ( or it's associated
 * child object )
 *
 * The order of precedence is command line arguments override any cfg file or default properties, and the cfg file ( if
 * used ) overrides any default properties
 *
 * @returns {{options: {workers: (*|number), phantomBasePort: (*|number), iterations: (*|number), port: (*|number), phantomArguments: string[]}, env: {PAGE_DONE_CHECK_TIMEOUT: {set: boolean, value: (*|number)}, RESOURCE_DOWNLOAD_TIMEOUT: {set: boolean, value: (*|number)}, WAIT_AFTER_LAST_REQUEST: {set: boolean, value: (*|number)}, JS_CHECK_TIMEOUT: {set: boolean, value: (*|number)}, JS_TIMEOUT: {set: boolean, value: (*|number)}, EVALUATE_JAVASCRIPT_CHECK_TIMEOUT: {set: boolean, value: (*|number)}}, plugins: {removeScriptTags: {load: boolean, env: {}}, httpHeaders: {load: boolean, env: {}}, blacklist: {load: boolean, env: {}}, basicAuth: {load: boolean, env: {}}, whitelist: {load: boolean, env: {}}, logger: {load: boolean, env: {}}, inMemoryHtmlCache: {load: boolean, env: {}}, s3HtmlCache: {load: boolean, env: {}}}}}
 */
exports.getConfig = function getConfig() {

    var cfg = {

        // Standard options you can pass to prerender service

        options : {
            workers         : process.env['PHANTOM_CLUSTER_NUM_WORKERS'] || 1,     // Max number of workers ( clusters )
            phantomBasePort : process.env['PHANTOM_CLUSTER_BASE_PORT']   || 12400, // PhantomJS Server Cluster Starting Port
            iterations      : process.env['PHANTOM_WORKER_ITERATIONS']   || 200,   // Calls before phantomJS restarts
            port            : process.env['PORT']                        || 3030,  // Port you will send bot requests to

            // Passed directly to phantomjs
            phantomArguments : [

                '--load-images=false',
                '--ignore-ssl-errors=true',
                '--ssl-protocol=tlsv1'
            ]
        },

        // prerender environment variable overrides
        env  : {
            PAGE_DONE_CHECK_TIMEOUT           : { set: false, value : process.env['PAGE_DONE_CHECK_TIMEOUT'] || 50 },
            RESOURCE_DOWNLOAD_TIMEOUT         : { set: false, value : process.env['RESOURCE_DOWNLOAD_TIMEOUT'] || 10000},
            WAIT_AFTER_LAST_REQUEST           : { set: false, value : process.env['WAIT_AFTER_LAST_REQUEST'] || 500},
            JS_CHECK_TIMEOUT                  : { set: false, value : process.env['JS_CHECK_TIMEOUT'] || 50},
            JS_TIMEOUT                        : { set: false, value : process.env['JS_TIMEOUT'] || 10000},
            EVALUATE_JAVASCRIPT_CHECK_TIMEOUT : { set: false, value : process.env['EVALUATE_JAVASCRIPT_CHECK_TIMEOUT'] || 50}
        },

        plugins: {
            "removeScriptTags" : { load : true, env : {

            }},
            "httpHeaders"      : { load : true, env : {

            }},
            "blacklist"        :{ load : true, env :  {

            }},
            "basicAuth"        : { load : false, env : {

            }},
            "whitelist"        : { load : false, env : {

            }},
            "logger"           : { load : false, env : {

            }},
            "inMemoryHtmlCache": { load : false, env : {

            }},
            "s3HtmlCache"      : { load : false, env : {

            }}
        }
    };

    var cmd = emptyObj(cfg); // command line cfg overrides go here and are merged at end of function
    var jsn = emptyObj(cfg); // .json cfg file overrides go here and are merged at end of function

    // Get any command line options, these will override any cfg.options and cfg.plugin options if present, we don't
    // bother with env arguments, though they can be set from inside a .json cfg file, if we find we need them they are
    // easy enough to add
    args
        .version(require('../package.json')['version'])
        .usage(' [options]')
        .description('This is a description')

        // Try to load the config file if the user provided one
        .option('-C , --config [filename]',"a json configuration file located in the root (see cfg.json)",function(value) {
            var file = path.join(__dirname,'../',value);

            try {
                value = require( file );
                jsn   = value;

            } catch(error) {
                console.log("\nThe config file " + file + 'does not exist or is corrupt\n');
                this.help();
           }
           return value;
        })

        .option('-W , --workers [number]',"Number of CPU's to use : -1 to use all, default 1",function(value){

            cmd.options.workers = checkValueNumber(value,-1,64,true,"workers must be -1 or a number between 1 and maxCPU's but was : "+value,this.help);
            return cmd.options.workers;
        })
        .option('-I , --iterations [number]','Number of requests for restarting phantomJS service, default 200',function(value){
            cmd.options.iterations = checkValueNumber(value,1,500,true,args,"iterations must be a number between 1 and 500 but was : "+value,this.help);
            return cmd.options.iterations;
        })
        .option('-P , --port [number]','Port this server will listen on, default 3030',function(value){
            cmd.options.port = checkValueNumber(value,3000,64000,true,args,"port must be a number between 1000 and 6400 but was : "+value,this.help);
            return cmd.options.port
        })
        .option('-B , --phantomBasePort [number]','Starting port for phantomjs cluster, default 12300',function(value){
            cmd.options.phantomBasePort = checkValueNumber(value,3001,64000,true,args,"phantomBasePort must be a number between 1000 and 6400 but was : "+value,this.help);
            return cmd.options.phantomBasePort;
        })
        .option('-NS, --removeScriptTags [boolean]' ,"Remove '<script>' blocks after page is rendered, default true",function(value){
            cmd.plugins.removeScriptTags = getSwitch(value);
            return cmd.plugins.removeScriptTags;
        },true)
        .option('-HH, --httpHeaders [boolean]','Load prerender httpHeaders middleware, default true',function(value){
            cmd.plugins.httpHeaders = getSwitch(value);
            return cmd.plugins.httpHeaders;
        },true)
        .option('-BA, --basicAuth [boolean]'        ,'Load prerender basicAuth middleware, default false',function(value){
            cmd.plugins.basicAuth = getSwitch(value);
            return cmd.plugins.basicAuth;
        },true)
        .option('-BL, --blacklist [boolean]'        ,'Load prerender blacklist middleware, default false',function(value){
            cmd.plugins.blacklist = getSwitch(value);
            return cmd.plugins.blacklist;
        },false)
        .option('-WL, --whitelist [boolean]'        ,'Load prerender whitelist middleware, default false',function(value){
            cmd.plugins.whitelist = getSwitch(value);
            return cmd.plugins.whitelist;
        },false)
        .option('-LG, --logger [boolean]'           ,'Load prerender logger middleware, default false',function(value){
            cmd.plugins.logger = getSwitch(value);
            return cmd.plugins.logger;
        },false)
        .option('-MC, --inMemoryHtmlCache [boolean]','Load prerender inMemoryHtmlCache middleware, default false',function(value){
            cmd.plugins.inMemoryHtmlCache = getSwitch(value);
            return cmd.plugins.inMemoryHtmlCache;
        },false)
        .option('-S3, --s3HtmlCache [boolean]'      ,'Load prerender s3HtmlCache middleware, default false',function(value){
            cmd.plugins.s3HtmlCache = getSwitch(value);
            return cmd.plugins.s3HtmlCache;
        },false)
    .parse(process.argv);

    // 1. override defaults with any .json cfg properties
    cfg = cfgOverride(cfg,jsn);

    // 2. override defaults & .json cfg with any command line parameters
    cfg = cfgOverride(cfg,cmd);

    // Return the merged configuration object
    return cfg;

};

// Helper functions --------

function oneTimeMsg(msg) {
    if(!cluster.isMaster) {
        return;
    }
    console.log(msg);
}

function loadPrerenderPlugins( plugins ) {
    // Turn on any requested plugins ( if they exist )
    Object.keys(plugins).forEach( function(key) {

        if (plugins[key].load ) {
            if (key in prerender && _.isFunction( prerender[key]) ) {

                prerender[key]();

                oneTimeMsg("Loaded prerender plugin : " + key);
            } else {
                oneTimeMsg("Prerender plugin " + key + " was requested but is not available");
            }
        }
    });
}

// The prerender service, and the plugins all depend on env variables instead of passed options, this function
// gives us a way to override any defaults set in your environment and only occurs on startup ( the master cluster )
// if you like to use env. vars only then just remove the contents of the env object's
function setPrerenderEnvironment(env) {

    if (!cluster.isMaster) {
        return;
    }

    Object.keys(env).forEach(function(key){
        if ( env[key].set ) {
            oneTimeMsg("Master process.env." + key + " was " + process.env[key] + " but is now " + env[key].value);
            process.env[key] = env[key].value;
        }
    });
}

function setPluginsEnvironment() {

    if (!cluster.isMaster) {

    }

    /*Object.keys(env).forEach(function(key){
        if ( env[key].set ) {
            oneTimeMsg(cluster,"Master process.env." + key + " was " + process.env[key] + " but is now " + env[key].value);
            process.env[key] = env[key].value;
        }
    });*/
}

// Purpose built extender for cfg objects
/*function cfgOverride(dest,src) {

    Object.keys(src).forEach(function(key){
        if (!_.isEmpty(src[key])) {
            _.extend(dest[key],src[key]);
        }
    });
    return dest;
}*/
function cfgOverride(dest,src) {

    Object.keys(src).forEach(function(key){
        if (!_.isEmpty(src[key])) {
            if (!dest.hasOwnProperty(key)) {
                dest[key] = src[key];
            }
            _.extend(dest[key],src[key]);
        }
    });
    return dest;
}

// Created empty cfg object
function emptyObj(obj) {

    var result = {};

    Object.keys(obj).forEach(function(key) {
        if (_.isObject(obj[key])) {
            result[key] = {};
        }
    });

    return result;
}

// Make sure they passed a number that is in range of what we want
function checkValueNumber( value, upper, lower, notZero, onErrorMsg, helpFn ) {

    var result;

    if (_.isUndefined(value)) {
        return;
    }

    result = parseInt(value);

    if (_.isNaN(value)) {
        console.log('\n'+onErrorMsg+'\n');
        helpFn();
    }

    if ((result >= lower || result <= upper) || (notZero && 0 === value)) {
        console.log(onErrorMsg+value+'\n');
        helpFn();
    }

    return result;
}

// If the user passes something stupid then it defaults to false ( safe bet )
function getSwitch( value ) {
    if (_.isUndefined(value) || true === value) {
        value = true;
    } else {
        value = false !== value;
    }
    return value;
}

<commit_msg>Refactored Commander Block<commit_after>var _         = require('underscore');  // Util Module
var args      = require('commander');   // Command line processing module
var path      = require('path');        // File utility's
var cluster   = require('cluster');     // This is a cluster based server see --help for options
var prerender = require('prerender');

/**
 * Call this function to create and return a configured prerender.io rendering server
 *
 * @param cfg an object that is used to modify the behavior of the prerender service, if no value is
 * passed one is created for you.
 *
 * @returns {*} The prerender server object for this cluster worker
 */
exports.getPrerenderServer = function getPrerenderServer(cfg) {

    var server;

    cfg = cfg || this.getConfig();

    // The first time you need to modify the environment based on contents of cfg
    if (cluster.isMaster) {
        setPrerenderEnvironment(cfg.env);
        setPluginsEnvironment(cfg.plugins);
    }

    if ((server = prerender(cfg.options))) {
        loadPrerenderPlugins(cfg.plugins);
    }

    return server;
};

/**
 * Configures an object used to control the prerender server
 *
 * The function first constructs a default cfg object containing 3 child objects
 *
 *  options an object that contains prerender properties with default settings used to configure the service
 *
 *  env     an object that contains prerender process.env properties, typically you leave these alone but they
 *          can be used to override prerender defaults ( use with caution )
 *
 *  plugins an object that contains key's that map to prerender middleware, if set to true they will be loaded
 *
 * The function then looks at command line arguments, one of which allows a cfg file to be specified, this
 * file is a json formatted cfg object and if present will be used to add or overwrite objects and properties
 * in the cfg default object
 *
 * Finally the function uses any command line arguments to set final values of the cfg object ( or it's associated
 * child object )
 *
 * The order of precedence is command line arguments override any cfg file or default properties, and the cfg file ( if
 * used ) overrides any default properties
 *
 * @returns {{options: {workers: (*|number), phantomBasePort: (*|number), iterations: (*|number), port: (*|number), phantomArguments: string[]}, env: {PAGE_DONE_CHECK_TIMEOUT: {set: boolean, value: (*|number)}, RESOURCE_DOWNLOAD_TIMEOUT: {set: boolean, value: (*|number)}, WAIT_AFTER_LAST_REQUEST: {set: boolean, value: (*|number)}, JS_CHECK_TIMEOUT: {set: boolean, value: (*|number)}, JS_TIMEOUT: {set: boolean, value: (*|number)}, EVALUATE_JAVASCRIPT_CHECK_TIMEOUT: {set: boolean, value: (*|number)}}, plugins: {removeScriptTags: {load: boolean, env: {}}, httpHeaders: {load: boolean, env: {}}, blacklist: {load: boolean, env: {}}, basicAuth: {load: boolean, env: {}}, whitelist: {load: boolean, env: {}}, logger: {load: boolean, env: {}}, inMemoryHtmlCache: {load: boolean, env: {}}, s3HtmlCache: {load: boolean, env: {}}}}}
 */
exports.getConfig = function getConfig() {

    var cfg = {

        // Standard options you can pass to prerender service
        options : {
            workers         : process.env['PHANTOM_CLUSTER_NUM_WORKERS'] || 1,     // Max number of workers ( clusters )
            phantomBasePort : process.env['PHANTOM_CLUSTER_BASE_PORT']   || 12400, // PhantomJS Server Cluster Starting Port
            iterations      : process.env['PHANTOM_WORKER_ITERATIONS']   || 200,   // Calls before phantomJS restarts
            port            : process.env['PORT']                        || 3030,  // Port you will send bot requests to

            // Passed directly to phantomjs
            phantomArguments : [

                '--load-images=false',
                '--ignore-ssl-errors=true',
                '--ssl-protocol=tlsv1'
            ]
        },

        // prerender environment variable overrides
        env  : {
            PAGE_DONE_CHECK_TIMEOUT           : { set: false, value : process.env['PAGE_DONE_CHECK_TIMEOUT'] || 50 },
            RESOURCE_DOWNLOAD_TIMEOUT         : { set: false, value : process.env['RESOURCE_DOWNLOAD_TIMEOUT'] || 10000},
            WAIT_AFTER_LAST_REQUEST           : { set: false, value : process.env['WAIT_AFTER_LAST_REQUEST'] || 500},
            JS_CHECK_TIMEOUT                  : { set: false, value : process.env['JS_CHECK_TIMEOUT'] || 50},
            JS_TIMEOUT                        : { set: false, value : process.env['JS_TIMEOUT'] || 10000},
            EVALUATE_JAVASCRIPT_CHECK_TIMEOUT : { set: false, value : process.env['EVALUATE_JAVASCRIPT_CHECK_TIMEOUT'] || 50}
        },

        plugins: {
            "removeScriptTags" : { load : true, env : {

            }},
            "httpHeaders"      : { load : true, env : {

            }},
            "blacklist"        :{ load : true, env :  {

            }},
            "basicAuth"        : { load : false, env : {

            }},
            "whitelist"        : { load : false, env : {

            }},
            "logger"           : { load : false, env : {

            }},
            "inMemoryHtmlCache": { load : false, env : {

            }},
            "s3HtmlCache"      : { load : false, env : {

            }}
        }
    };

    var cmd = emptyObj(cfg); // command line cfg overrides go here and are merged at end of function
    var jsn = emptyObj(cfg); // .json cfg file overrides go here and are merged at end of function

    // Get any command line options, these will override any cfg.options and cfg.plugin options if present, we don't
    // bother with env arguments, though they can be set from inside a .json cfg file, if we find we need them they are
    // easy enough to add
    args
        .version(require('../package.json')['version'])
        .usage(' [options]')
        .description('This is a description')

        // Try to load the config file if the user provided one
        .option('-C , --config [filename]',"a json configuration file located in the root (see cfg.json)",function(value) {
            var file = path.join(__dirname,'../',value);

            try {
                value = require( file );
                jsn   = value;

            } catch(error) {
                console.log("\nThe config file " + file + 'does not exist or is corrupt\n');
                this.help();
           }
           return value;
        })

        .option('-W , --workers [number]',"Number of CPU's to use : -1 to use all, default 1",function(value){

            cmd.options.workers = checkValueNumber(value,-1,64,true,"workers must be -1 or a number between 1 and maxCPU's but was : "+value,this.help);
            return cmd.options.workers;
        })
        .option('-I , --iterations [number]','Number of requests for restarting phantomJS service, default 200',function(value){
            cmd.options.iterations = checkValueNumber(value,1,500,true,args,"iterations must be a number between 1 and 500 but was : "+value,this.help);
            return cmd.options.iterations;
        })
        .option('-P , --port [number]','Port this server will listen on, default 3030',function(value){
            cmd.options.port = checkValueNumber(value,3000,64000,true,args,"port must be a number between 1000 and 6400 but was : "+value,this.help);
            return cmd.options.port
        })
        .option('-B , --phantomBasePort [number]','Starting port for phantomjs cluster, default 12300',function(value){
            cmd.options.phantomBasePort = checkValueNumber(value,3001,64000,true,args,"phantomBasePort must be a number between 1000 and 6400 but was : "+value,this.help);
            return cmd.options.phantomBasePort;
        })
        .option('-NS, --removeScriptTags [boolean]' ,"Remove '<script>' blocks after page is rendered, default true",function(value){
            cmd.plugins.removeScriptTags = getSwitch(value);
            return cmd.plugins.removeScriptTags;
        },true)
        .option('-HH, --httpHeaders [boolean]','Load prerender httpHeaders middleware, default true',function(value){
            cmd.plugins.httpHeaders = getSwitch(value);
            return cmd.plugins.httpHeaders;
        },true)
        .option('-BA, --basicAuth [boolean]'        ,'Load prerender basicAuth middleware, default false',function(value){
            cmd.plugins.basicAuth = getSwitch(value);
            return cmd.plugins.basicAuth;
        },true)
        .option('-BL, --blacklist [boolean]'        ,'Load prerender blacklist middleware, default false',function(value){
            cmd.plugins.blacklist = getSwitch(value);
            return cmd.plugins.blacklist;
        },false)
        .option('-WL, --whitelist [boolean]'        ,'Load prerender whitelist middleware, default false',function(value){
            cmd.plugins.whitelist = getSwitch(value);
            return cmd.plugins.whitelist;
        },false)
        .option('-LG, --logger [boolean]'           ,'Load prerender logger middleware, default false',function(value){
            cmd.plugins.logger = getSwitch(value);
            return cmd.plugins.logger;
        },false)
        .option('-MC, --inMemoryHtmlCache [boolean]','Load prerender inMemoryHtmlCache middleware, default false',function(value){
            cmd.plugins.inMemoryHtmlCache = getSwitch(value);
            return cmd.plugins.inMemoryHtmlCache;
        },false)
        .option('-S3, --s3HtmlCache [boolean]'      ,'Load prerender s3HtmlCache middleware, default false',function(value){
            cmd.plugins.s3HtmlCache = getSwitch(value);
            return cmd.plugins.s3HtmlCache;
        },false)
    .parse(process.argv);

    // 1. override defaults with any .json cfg properties
    cfg = cfgOverride(cfg,jsn);

    // 2. override defaults & .json cfg with any command line parameters
    cfg = cfgOverride(cfg,cmd);

    // Return the merged configuration object
    return cfg;

};

// Helper functions --------

function oneTimeMsg(msg) {
    if(!cluster.isMaster) {
        return;
    }
    console.log(msg);
}

function loadPrerenderPlugins( plugins ) {
    // Turn on any requested plugins ( if they exist )
    Object.keys(plugins).forEach( function(key) {

        if (plugins[key].load ) {
            if (key in prerender && _.isFunction( prerender[key]) ) {

                prerender[key]();

                oneTimeMsg("Loaded prerender plugin : " + key);
            } else {
                oneTimeMsg("Prerender plugin " + key + " was requested but is not available");
            }
        }
    });
}

// The prerender service, and the plugins all depend on env variables instead of passed options, this function
// gives us a way to override any defaults set in your environment and only occurs on startup ( the master cluster )
// if you like to use env. vars only then just remove the contents of the env object's
function setPrerenderEnvironment(env) {

    if (!cluster.isMaster) {
        return;
    }

    Object.keys(env).forEach(function(key){
        if ( env[key].set ) {
            oneTimeMsg("Master process.env." + key + " was " + process.env[key] + " but is now " + env[key].value);
            process.env[key] = env[key].value;
        }
    });
}

function setPluginsEnvironment() {

    if (!cluster.isMaster) {

    }

    /*Object.keys(env).forEach(function(key){
        if ( env[key].set ) {
            oneTimeMsg(cluster,"Master process.env." + key + " was " + process.env[key] + " but is now " + env[key].value);
            process.env[key] = env[key].value;
        }
    });*/
}

// Purpose built extender for cfg objects
/*function cfgOverride(dest,src) {

    Object.keys(src).forEach(function(key){
        if (!_.isEmpty(src[key])) {
            _.extend(dest[key],src[key]);
        }
    });
    return dest;
}*/
function cfgOverride(dest,src) {

    Object.keys(src).forEach(function(key){
        if (!_.isEmpty(src[key])) {
            if (!dest.hasOwnProperty(key)) {
                dest[key] = src[key];
            }
            _.extend(dest[key],src[key]);
        }
    });
    return dest;
}

// Created empty cfg object
function emptyObj(obj) {

    var result = {};

    Object.keys(obj).forEach(function(key) {
        if (_.isObject(obj[key])) {
            result[key] = {};
        }
    });

    return result;
}

// Make sure they passed a number that is in range of what we want
function checkValueNumber( value, upper, lower, notZero, onErrorMsg, helpFn ) {

    var result;

    if (_.isUndefined(value)) {
        return;
    }

    result = parseInt(value);

    if (_.isNaN(value)) {
        console.log('\n'+onErrorMsg+'\n');
        helpFn();
    }

    if ((result >= lower || result <= upper) || (notZero && 0 === value)) {
        console.log(onErrorMsg+value+'\n');
        helpFn();
    }

    return result;
}

// If the user passes something stupid then it defaults to false ( safe bet )
function getSwitch( value ) {
    if (_.isUndefined(value) || true === value) {
        value = true;
    } else {
        value = false !== value;
    }
    return value;
}

<|endoftext|>


<commit_before>'use strict';
//
// Disable the line length as in this file all routes are documented
// jscs:disable maximumLineLength

var Joi = require('joi');

exports.version = versionConfig;
exports.app = appConfig;
exports.parameter = parameterConfig;
exports.calendar = calendarConfig;
exports.geo = geoConfig;

var version;
function versionConfig() {
    if (version) {
        return version;
    } else {
        version = require('../package.json').version;
        return version;
    }
}

function appConfig() {
    var app;
    if (process.env.NODE_ENV === 'test') {
        app = {
            port: 3002,
            basepath: ''
        };
    } else {
        app = {
            port: process.env.PORT || 8080,
            basepath: ''
        };
    }
    return app;
}

function parameterConfig() {
    var types = [
        'cardboard',
        'cargotram',
        'etram',
        'organic',
        'paper',
        'special',
        'textile',
        'waste'
   ];
    return {
        zip: Joi.number().integer().min(1000).max(9999).description('The zip code for the collection'),
        station: Joi.string().description('Case insensitive search for name of collection station/tram stop, supports regex'),
        types: Joi.alternatives(Joi.string().valid(types), Joi.array().items(Joi.string().valid(types))).description('Types of waste to search for (e.g. `paper`), supports multiple values, just repeat the parameter.'),
        start: Joi.date().description('Start of date range, only entries from that date forward will be returned, e.g `2014-11-01`'),
        end: Joi.date().description('End of date range, only entries up to this date will be returned, e.g. `2015-01-25`'),
        sort: Joi.string().optional().description('Sort order for result, e.g. `date` or `zip:desc`. Multiple values can be comma-separated.'),
        limit: Joi.number().optional().description('Limit the amount of returned records.').default(0),
        offset: Joi.number().optional().description('Offset from all results, together with `limit` this can be used for pagination.').default(0),
        lang: Joi.string().valid('de', 'en').optional().description('Language for the output, should be the two-letter abbreviation (e.g. `de`).')
    };
}

function calendarConfig() {
    return {
        all: {
            name: 'All types',
            type: null,
            description: 'Calendar of waste collection',
            notes: 'Return the current calendar of all types of waste',
            params: [ 'zip', 'station', 'types', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        waste: {
            name: 'General waste collection',
            type: 'waste',
            description: 'Calendar of waste collection',
            notes: 'Return the current calendar of the waste collection (Kehricht)',
            params: [ 'zip', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        cardboard: {
            name: 'Cardboard waste collection',
            type: 'cardboard',
            description: 'Calendar of cardboard waste collection',
            notes: 'Return the current calendar of the cardboard waste collection (Karton)',
            params: [ 'zip', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        organic: {
            name: 'Organic waste collection',
            type: 'organic',
            description: 'Calendar of organic waste collection',
            notes: 'Return the current calendar of the organic waste collection (Bioabfall)',
            params: [ 'zip', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        paper: {
            name: 'Paper waste collection',
            type: 'paper',
            description: 'Calendar of paper waste collection',
            notes: 'Return the current calendar of the paper waste collection (Altpapier)',
            params: [ 'zip', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        special: {
            name: 'Special waste collection',
            type: 'special',
            description: 'Calendar of special waste collection',
            notes: 'Return the current calendar of the special waste collection (Sondermüll)',
            params: [ 'zip', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        textile: {
            name: 'Textile waste collection',
            type: 'textile',
            description: 'Calendar of textile waste collection',
            notes: 'Return the current calendar of the textile waste collection (Altkleider)',
            params: [ 'zip', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        cargotram: {
            name: 'Cargotram',
            type: 'cargotram',
            description: 'Calendar of CargoTram',
            notes: 'Return the current calendar of the CargoTram (Sperrmüll)',
            params: [ 'zip', 'station', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        etram: {
            name: 'eTram',
            type: 'etram',
            description: 'Calendar of eTram',
            notes: 'Return the current calendar of the eTram (electronic waste)',
            params: [ 'zip', 'station', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        }
    };
}

function geoConfig() {
    return {
        tram_stops: {
            name: 'Tram Stops',
            type: 'tram_stops',
            description: 'Get all tram stops for the Cargo- and E-Tram',
            notes: 'Returns all Cargo and E-Tram stops. If the client requests it (`Accept` header or `format` parameter, e.g. `.geojson` ), GeoJSON will be returned, JSON instead.',
        },
        waste_bins: {
            name: 'Waste Bins',
            type: 'waste_bins',
            description: 'Get all public waste bins (incl. Robidog)',
            notes: 'Returns all public waste bins. If the client requests it (`Accept` header or `format` parameter, e.g. `.geojson` ), GeoJSON will be returned, JSON instead.',
        }
    };
}
<commit_msg>Remove underscores in JSON and routes<commit_after>'use strict';
//
// Disable the line length as in this file all routes are documented
// jscs:disable maximumLineLength

var Joi = require('joi');

exports.version = versionConfig;
exports.app = appConfig;
exports.parameter = parameterConfig;
exports.calendar = calendarConfig;
exports.geo = geoConfig;

var version;
function versionConfig() {
    if (version) {
        return version;
    } else {
        version = require('../package.json').version;
        return version;
    }
}

function appConfig() {
    var app;
    if (process.env.NODE_ENV === 'test') {
        app = {
            port: 3002,
            basepath: ''
        };
    } else {
        app = {
            port: process.env.PORT || 8080,
            basepath: ''
        };
    }
    return app;
}

function parameterConfig() {
    var types = [
        'cardboard',
        'cargotram',
        'etram',
        'organic',
        'paper',
        'special',
        'textile',
        'waste'
   ];
    return {
        zip: Joi.number().integer().min(1000).max(9999).description('The zip code for the collection'),
        station: Joi.string().description('Case insensitive search for name of collection station/tram stop, supports regex'),
        types: Joi.alternatives(Joi.string().valid(types), Joi.array().items(Joi.string().valid(types))).description('Types of waste to search for (e.g. `paper`), supports multiple values, just repeat the parameter.'),
        start: Joi.date().description('Start of date range, only entries from that date forward will be returned, e.g `2014-11-01`'),
        end: Joi.date().description('End of date range, only entries up to this date will be returned, e.g. `2015-01-25`'),
        sort: Joi.string().optional().description('Sort order for result, e.g. `date` or `zip:desc`. Multiple values can be comma-separated.'),
        limit: Joi.number().optional().description('Limit the amount of returned records.').default(0),
        offset: Joi.number().optional().description('Offset from all results, together with `limit` this can be used for pagination.').default(0),
        lang: Joi.string().valid('de', 'en').optional().description('Language for the output, should be the two-letter abbreviation (e.g. `de`).')
    };
}

function calendarConfig() {
    return {
        all: {
            name: 'All types',
            type: null,
            description: 'Calendar of waste collection',
            notes: 'Return the current calendar of all types of waste',
            params: [ 'zip', 'station', 'types', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        waste: {
            name: 'General waste collection',
            type: 'waste',
            description: 'Calendar of waste collection',
            notes: 'Return the current calendar of the waste collection (Kehricht)',
            params: [ 'zip', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        cardboard: {
            name: 'Cardboard waste collection',
            type: 'cardboard',
            description: 'Calendar of cardboard waste collection',
            notes: 'Return the current calendar of the cardboard waste collection (Karton)',
            params: [ 'zip', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        organic: {
            name: 'Organic waste collection',
            type: 'organic',
            description: 'Calendar of organic waste collection',
            notes: 'Return the current calendar of the organic waste collection (Bioabfall)',
            params: [ 'zip', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        paper: {
            name: 'Paper waste collection',
            type: 'paper',
            description: 'Calendar of paper waste collection',
            notes: 'Return the current calendar of the paper waste collection (Altpapier)',
            params: [ 'zip', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        special: {
            name: 'Special waste collection',
            type: 'special',
            description: 'Calendar of special waste collection',
            notes: 'Return the current calendar of the special waste collection (Sondermüll)',
            params: [ 'zip', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        textile: {
            name: 'Textile waste collection',
            type: 'textile',
            description: 'Calendar of textile waste collection',
            notes: 'Return the current calendar of the textile waste collection (Altkleider)',
            params: [ 'zip', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        cargotram: {
            name: 'Cargotram',
            type: 'cargotram',
            description: 'Calendar of CargoTram',
            notes: 'Return the current calendar of the CargoTram (Sperrmüll)',
            params: [ 'zip', 'station', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        },
        etram: {
            name: 'eTram',
            type: 'etram',
            description: 'Calendar of eTram',
            notes: 'Return the current calendar of the eTram (electronic waste)',
            params: [ 'zip', 'station', 'start', 'end', 'sort', 'offset', 'limit', 'lang' ]
        }
    };
}

function geoConfig() {
    return {
        tramstops: {
            name: 'Tram Stops',
            type: 'tramstops',
            description: 'Get all tram stops for the Cargo- and E-Tram',
            notes: 'Returns all Cargo and E-Tram stops. If the client requests it (`Accept` header or `format` parameter, e.g. `.geojson` ), GeoJSON will be returned, JSON instead.',
        },
        wastebins: {
            name: 'Waste Bins',
            type: 'wastebins',
            description: 'Get all public waste bins (incl. Robidog)',
            notes: 'Returns all public waste bins. If the client requests it (`Accept` header or `format` parameter, e.g. `.geojson` ), GeoJSON will be returned, JSON instead.',
        }
    };
}
<|endoftext|>


<commit_before>var path = require('path');
var os = require('os');
var httpAgent = require('http').Agent;
var httpsAgent = require('https').Agent;
var fse = require('fs-extra');
var pkgConf = require('../package.json');
var config = require('util')._extend(exports, pkgConf);
var now = Date.now();
var variableProperties = ['port', 'sockets', 'timeout', 'dataDirname', 'storage',
                 		 'username', 'password', 'uipath', 'debug', 'debugMode'];

config.WEINRE_HOST = 'weinre.' + config.localUIHost;
config.ASSESTS_PATH = path.join(__dirname, '../assets');
config.HTTPS_FIELD = 'x-' + config.name + '-https-' + now;
config.CLIENT_IP_HEAD = 'x-forwarded-for-' + config.name + '-' + now;
config.HTTPS_FLAG = config.whistleSsl + '.';

function getHomeDirname() {
	var homedir = (getHomedir() || '').split(/[\/\\]/g);
	for (var i = homedir.length - 1; i >= 0; i--) {
		if (homedir[i]) {
			return homedir[i];
		}
	}
	return '';
}

function getHomedir() {
	return typeof os.homedir == 'function' ? os.homedir() :
		process.env[process.platform == 'win32' ? 'USERPROFILE' : 'HOME'];
}

function getWhistlePath() {
	return process.env.WHISTLE_PATH || path.join(getHomedir(), '.WhistleAppData');
}

function getDataDir(dirname) {
	var dir = path.join(getWhistlePath(), dirname || '.' + config.name);
	fse.ensureDirSync(dir);
	return dir;
}

exports.getDataDir = getDataDir;

function createAgent(config, https) {
	return new (https ? httpsAgent : httpAgent)(config)
					.on('free', preventThrowOutError);
}

function preventThrowOutError(socket) {
	socket.removeListener('error', freeSocketErrorListener);
	socket.on('error', freeSocketErrorListener);
}

function freeSocketErrorListener() {
	var socket = this;
	socket.destroy();
	socket.emit('agentRemove');
	socket.removeListener('error', freeSocketErrorListener);
}

function resolvePath(file) {
	if (!file || !(file = file.trim())) {
		return file;
	}

	return /^[\w-]+$/.test(file) ? file : path.resolve(file);
}

exports.extend = function extend(newConf) {
	if (newConf) {
		variableProperties.forEach(function(name) {
			config[name] = newConf[name] || pkgConf[name];
		});

		if (Array.isArray(newConf.ports)) {
			config.ports = pkgConf.ports.concat(newConf.ports);
		}

		if (typeof newConf.middlewares == 'string') {
			config.middlewares = newConf.middlewares.trim().split(/\s*,\s*/g);
		}
	}

	config.middlewares = Array.isArray(config.middlewares) ? config.middlewares.map(resolvePath) : [];

	var port = config.port;
	config.ports.forEach(function(name) {
		if (!/port$/.test(name) || name == 'port') {
			throw new Error('port name "' + name + '" must be end of "port", but not equals "port", like: ' + name + 'port');
		}
		config[name] = ++port;
	});

	var agentConfig = {
			maxSockets: config.sockets,
			keepAlive: config.keepAlive,
			keepAliveMsecs: config.keepAliveMsecs
		};
	config.httpAgent = config.debug ? false : createAgent(agentConfig);
	config.httpsAgent = config.debug ? false : createAgent(agentConfig, true);
	config.uipath = config.uipath ? resolvePath(config.uipath) : './webui/app';
	config.DATA_DIR = getDataDir(config.dataDirname);
	config.storage = config.storage && encodeURIComponent(storage);
	var root = config.storage ? path.join(config.DATA_DIR, 'custom_dirs', config.storage) : config.DATA_DIR;
	config.rulesDir = path.join(root, 'rules');
	config.valuesDir = path.join(root, 'values');
	config.propertiesDir = path.join(root, 'properties');
	config.homeDirname = getHomeDirname();

	return config;
};<commit_msg>feat: Add custom storage dir<commit_after>var path = require('path');
var os = require('os');
var httpAgent = require('http').Agent;
var httpsAgent = require('https').Agent;
var fse = require('fs-extra');
var pkgConf = require('../package.json');
var config = require('util')._extend(exports, pkgConf);
var now = Date.now();
var variableProperties = ['port', 'sockets', 'timeout', 'dataDirname', 'storage',
                 		 'username', 'password', 'uipath', 'debug', 'debugMode'];

config.WEINRE_HOST = 'weinre.' + config.localUIHost;
config.ASSESTS_PATH = path.join(__dirname, '../assets');
config.HTTPS_FIELD = 'x-' + config.name + '-https-' + now;
config.CLIENT_IP_HEAD = 'x-forwarded-for-' + config.name + '-' + now;
config.HTTPS_FLAG = config.whistleSsl + '.';

function getHomeDirname() {
	var homedir = (getHomedir() || '').split(/[\/\\]/g);
	for (var i = homedir.length - 1; i >= 0; i--) {
		if (homedir[i]) {
			return homedir[i];
		}
	}
	return '';
}

function getHomedir() {
	return typeof os.homedir == 'function' ? os.homedir() :
		process.env[process.platform == 'win32' ? 'USERPROFILE' : 'HOME'];
}

function getWhistlePath() {
	return process.env.WHISTLE_PATH || path.join(getHomedir(), '.WhistleAppData');
}

function getDataDir(dirname) {
	var dir = path.join(getWhistlePath(), dirname || '.' + config.name);
	fse.ensureDirSync(dir);
	return dir;
}

exports.getDataDir = getDataDir;

function createAgent(config, https) {
	return new (https ? httpsAgent : httpAgent)(config)
					.on('free', preventThrowOutError);
}

function preventThrowOutError(socket) {
	socket.removeListener('error', freeSocketErrorListener);
	socket.on('error', freeSocketErrorListener);
}

function freeSocketErrorListener() {
	var socket = this;
	socket.destroy();
	socket.emit('agentRemove');
	socket.removeListener('error', freeSocketErrorListener);
}

function resolvePath(file) {
	if (!file || !(file = file.trim())) {
		return file;
	}

	return /^[\w-]+$/.test(file) ? file : path.resolve(file);
}

exports.extend = function extend(newConf) {
	if (newConf) {
		variableProperties.forEach(function(name) {
			config[name] = newConf[name] || pkgConf[name];
		});

		if (Array.isArray(newConf.ports)) {
			config.ports = pkgConf.ports.concat(newConf.ports);
		}

		if (typeof newConf.middlewares == 'string') {
			config.middlewares = newConf.middlewares.trim().split(/\s*,\s*/g);
		}
	}

	config.middlewares = Array.isArray(config.middlewares) ? config.middlewares.map(resolvePath) : [];

	var port = config.port;
	config.ports.forEach(function(name) {
		if (!/port$/.test(name) || name == 'port') {
			throw new Error('port name "' + name + '" must be end of "port", but not equals "port", like: ' + name + 'port');
		}
		config[name] = ++port;
	});

	var agentConfig = {
			maxSockets: config.sockets,
			keepAlive: config.keepAlive,
			keepAliveMsecs: config.keepAliveMsecs
		};
	config.httpAgent = config.debug ? false : createAgent(agentConfig);
	config.httpsAgent = config.debug ? false : createAgent(agentConfig, true);
	config.uipath = config.uipath ? resolvePath(config.uipath) : './webui/app';
	config.DATA_DIR = getDataDir(config.dataDirname);
	config.storage = config.storage && encodeURIComponent(config.storage);
	var root = config.storage ? path.join(config.DATA_DIR, 'custom_dirs', config.storage) : config.DATA_DIR;
	config.rulesDir = path.join(root, 'rules');
	config.valuesDir = path.join(root, 'values');
	config.propertiesDir = path.join(root, 'properties');
	config.homeDirname = getHomeDirname();

	return config;
};<|endoftext|>


<commit_before>/**
 * Copyright [2013] [runrightfast.co]
 *
 * 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.
 */

(function() {
	'use strict';

	/**
	 *

	 * Get Command Line Arguments
	 *

	 *
	 *

	 * This method allows you to retrieve the value of the specified command
	 * line argument.
	 *

	 *
	 *

	 * The argument is case sensitive, and must be of the form
	 * '--ARG_NAME=value'
	 *

	 *
	 * @method _getCmdLineArg
	 * @param searchFor
	 *            {STRING} The argument name to search for
	 * @return {MIXED} FALSE if the argument was not found, the argument value
	 *         if found
	 */
	var getCmdLineArg = function getCmdLineArg(searchFor) {
		var cmdLineArgs = process.argv.slice(2, process.argv.length);
		var argName = '--' + searchFor + '=';
		var i = 0;
		for (i = 0; i < cmdLineArgs.length; i++) {
			if (cmdLineArgs[i].indexOf(argName) === 0) {
				return cmdLineArgs[i].substr(argName.length);
			}
		}

		return false;
	};

	var config = {
		/**
		 *

		 * Get a parameter from the command line or process environment
		 *

		 *
		 *

		 * This method looks for the parameter from the command line in the
		 * format --PARAMETER=VALUE, then from the process environment, then
		 * from the default specified as an argument.
		 *

		 *
		 * @method param
		 * @param paramName
		 *            {String} Name of the parameter
		 * @param [defaultValue]
		 *            {Any} Default value of the parameter
		 * @return {Any} The found value, or default value
		 */
		param : function(paramName, defaultValue) {
			return getCmdLineArg(paramName) || process.env[paramName] || defaultValue;
		}

	};

	module.exports = config;

}());
<commit_msg>updated doc<commit_after>/**
 * Copyright [2013] [runrightfast.co]
 *
 * 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.
 */

(function() {
	'use strict';

	/**
	 *

	 * Get Command Line Arguments
	 *
	 * This method allows you to retrieve the value of the specified command line argument.
	 *
	 * The argument is case sensitive, and must be of the form: '--ARG_NAME=value'
	 *

	 *
	 * @method _getCmdLineArg
	 * @param searchFor
	 *            {STRING} The argument name to search for
	 * @return {MIXED} FALSE if the argument was not found, the argument value
	 *         if found
	 */
	var getCmdLineArg = function getCmdLineArg(searchFor) {
		var cmdLineArgs = process.argv.slice(2, process.argv.length);
		var argName = '--' + searchFor + '=';
		var i = 0;
		for (i = 0; i < cmdLineArgs.length; i++) {
			if (cmdLineArgs[i].indexOf(argName) === 0) {
				return cmdLineArgs[i].substr(argName.length);
			}
		}

		return false;
	};

	var config = {
		/**
		 *

		 * Get a parameter from the command line or process environment
		 *

		 *
		 *

		 * This method looks for the parameter from the command line in the
		 * format --PARAMETER=VALUE, then from the process environment, then
		 * from the default specified as an argument.
		 *

		 *
		 * @method param
		 * @param paramName
		 *            {String} Name of the parameter
		 * @param [defaultValue]
		 *            {Any} Default value of the parameter
		 * @return {Any} The found value, or default value
		 */
		param : function(paramName, defaultValue) {
			return getCmdLineArg(paramName) || process.env[paramName] || defaultValue;
		}

	};

	module.exports = config;

}());
<|endoftext|>