<commit_before>'use strict';

var debug = require('debug')('echo:verify'),
    path = require('path'),
    url = require('url'),
    https = (process.env.NODE_ENV === 'development') ? require('http') : require('https'),
    Promise = require('bluebird'),
    pem = require('pem'),
    crypto = require('crypto');

var MAX_REQUEST_AGE = (process.env.NODE_ENV === 'development') ? (9999999) : (150 * 1000);

var readCertInfo = Promise.promisify(pem.readCertificateInfo),
    getPublicKey = Promise.promisify(pem.getPublicKey);

function VerifyError() {
    return require('./create-error-type').call(this, arguments);
}

function verifySignature(headers, rawBody) { return new Promise(function (resolve, reject) {
    var body, sigUrl, sigParsed, nowGMT, reqTimestamp;

    try {
        body = JSON.parse(rawBody);
    } catch(e) {
        return reject(new VerifyError('Echo request body is not valid JSON'));
    }

    if (!headers.signaturecertchainurl || !headers.signature) {
        return reject(new VerifyError('Missing Echo signature headers on request'));
    }

    sigUrl = path.normalize(headers.signaturecertchainurl);
    sigUrl = sigUrl.replace(/^http(s?):\/([^\/])/, 'http$1://$2');

    debug('Cert data URL', sigUrl);

    sigParsed = url.parse(sigUrl);

    if (process.env.NODE_ENV !== 'development' &&
        (!/^https\:?$/.test(sigParsed.protocol) ||
        sigParsed.hostname.toLowerCase() !== 's3.amazonaws.com' ||
        !/^\/echo\.api\//i.test(sigParsed.path) ||
        (sigParsed.port && sigParsed.port !== 443))) {
        return reject(new VerifyError('Invalid Echo signature URL (' + headers.signaturecertchainurl + ')'));
    }

    nowGMT = convertToGMT(new Date()).getTime();
    reqTimestamp = convertToGMT(new Date(body.request && body.request.timestamp));
    reqTimestamp = (reqTimestamp && reqTimestamp.getTime()) || 0;

    if (!reqTimestamp || (nowGMT - reqTimestamp) > MAX_REQUEST_AGE) {
        return reject(new VerifyError('Stale Echo request sent (ts:' + reqTimestamp + ', diff:' + (nowGMT - reqTimestamp) + ')'));
    }

    debug('Verifying signature from URL:', sigUrl);

    https.get(sigUrl, function(res) {
        var certData = '';

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

        res.on('end', function() {
            debug('Retrieved cert data');

            verifyCertificate(certData)
                .then(function(certParts) {
                    var verifier = crypto.createVerify('SHA1');

                    verifier.update(rawBody);

                    if (process.env.NODE_ENV === 'development' ||
                        verifier.verify(certData, headers.signature, 'base64')) {

                        debug('Echo request verified using', sigUrl);
                        resolve();

                    } else {
                        reject(new VerifyError('Unable to verify request body with signature.'));
                    }

                })
                .catch(reject);

        });

    }).on('error', reject);

}); }

function convertToGMT(d) {
    if (!d || !d.getTime()) {
        return null;
    }
    return new Date(d.getTime() + (d.getTimezoneOffset() * 60 * 1000));
}

function verifyCertificate(certData) { return new Promise(function (resolve, reject) {

    var csr;

    readCertInfo(certData)
        .then(function(certParts) {
            var nowGMT = convertToGMT(new Date()).getTime();

            debug(certParts);

            if (!certParts.validity ||
                certParts.validity.start > nowGMT ||
                certParts.validity.end < nowGMT) {
                return reject(new VerifyError('Echo certificate is no longer valid'));
            }

            if (!certParts.san ||
                !/(\'|\")echo\-api\.amazon\.com(\'|\")/.test(JSON.stringify(certParts.san))) {
                return reject(new VerifyError('Echo domain not present in certificate SAN'));
            }

            if (!certParts.issuer || !certParts.issuer.organization) {
                return reject(new VerifyError('Echo request certificate has no issuing organization'));
            }

            csr = certParts;

            return getPublicKey(certData);
        })
        .then(function(data) {
            debug('Retrieved public key from certificate chain');
            csr.pubKey = data.publicKey;
            resolve(csr);
        })
        .catch(reject);

}); }

// --------------- Public methods ----------------- //

function validateRequest(headers, rawBody, cb) {

    verifySignature(headers, rawBody)
        .then(cb)
        .catch(cb);
}

module.exports = function() {

    return {
        validateRequest: validateRequest
    };

};

<commit_msg>Added application ID check to echo request verification<commit_after>'use strict';

var debug = require('debug')('echo:verify'),
    path = require('path'),
    url = require('url'),
    https = (process.env.NODE_ENV === 'development') ? require('http') : require('https'),
    Promise = require('bluebird'),
    pem = require('pem'),
    crypto = require('crypto');

var MAX_REQUEST_AGE = (process.env.NODE_ENV === 'development') ? (9999999) : (150 * 1000);

var readCertInfo = Promise.promisify(pem.readCertificateInfo),
    getPublicKey = Promise.promisify(pem.getPublicKey);

function VerifyError() {
    return require('./create-error-type').call(this, arguments);
}

function verifySignature(headers, rawBody) { return new Promise(function (resolve, reject) {
    var body, sigUrl, sigParsed, nowGMT, reqTimestamp;

    try {
        body = JSON.parse(rawBody);
    } catch(e) {
        return reject(new VerifyError('Echo request body is not valid JSON'));
    }

    if (!process.env.ECHO_APP_ID) {
        return reject(new VerifyError('Echo application ID environment variable is not set.'));
    }
    if (!body.session || !body.session.application ||
        body.session.application.applicationId !== process.env.ECHO_APP_ID) {
        return reject(new VerifyError('Echo request application ID does not match'));
    }

    if (!headers.signaturecertchainurl || !headers.signature) {
        return reject(new VerifyError('Missing Echo signature headers on request'));
    }

    sigUrl = path.normalize(headers.signaturecertchainurl);
    sigUrl = sigUrl.replace(/^http(s?):\/([^\/])/, 'http$1://$2');

    debug('Cert data URL', sigUrl);

    sigParsed = url.parse(sigUrl);

    if (process.env.NODE_ENV !== 'development' &&
        (!/^https\:?$/.test(sigParsed.protocol) ||
        sigParsed.hostname.toLowerCase() !== 's3.amazonaws.com' ||
        !/^\/echo\.api\//i.test(sigParsed.path) ||
        (sigParsed.port && sigParsed.port !== 443))) {
        return reject(new VerifyError('Invalid Echo signature URL (' + headers.signaturecertchainurl + ')'));
    }

    nowGMT = convertToGMT(new Date()).getTime();
    reqTimestamp = convertToGMT(new Date(body.request && body.request.timestamp));
    reqTimestamp = (reqTimestamp && reqTimestamp.getTime()) || 0;

    if (!reqTimestamp || (nowGMT - reqTimestamp) > MAX_REQUEST_AGE) {
        return reject(new VerifyError('Stale Echo request sent (ts:' + reqTimestamp + ', diff:' + (nowGMT - reqTimestamp) + ')'));
    }

    debug('Verifying signature from URL:', sigUrl);

    https.get(sigUrl, function(res) {
        var certData = '';

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

        res.on('end', function() {
            debug('Retrieved cert data');

            verifyCertificate(certData)
                .then(function(certParts) {
                    var verifier = crypto.createVerify('SHA1');

                    verifier.update(rawBody);

                    if (process.env.NODE_ENV === 'development' ||
                        verifier.verify(certData, headers.signature, 'base64')) {

                        debug('Echo request verified using', sigUrl);
                        resolve();

                    } else {
                        reject(new VerifyError('Unable to verify request body with signature.'));
                    }

                })
                .catch(reject);

        });

    }).on('error', reject);

}); }

function convertToGMT(d) {
    if (!d || !d.getTime()) {
        return null;
    }
    return new Date(d.getTime() + (d.getTimezoneOffset() * 60 * 1000));
}

function verifyCertificate(certData) { return new Promise(function (resolve, reject) {

    var csr;

    readCertInfo(certData)
        .then(function(certParts) {
            var nowGMT = convertToGMT(new Date()).getTime();

            debug(certParts);

            if (!certParts.validity ||
                certParts.validity.start > nowGMT ||
                certParts.validity.end < nowGMT) {
                return reject(new VerifyError('Echo certificate is no longer valid'));
            }

            if (!certParts.san ||
                !/(\'|\")echo\-api\.amazon\.com(\'|\")/.test(JSON.stringify(certParts.san))) {
                return reject(new VerifyError('Echo domain not present in certificate SAN'));
            }

            if (!certParts.issuer || !certParts.issuer.organization) {
                return reject(new VerifyError('Echo request certificate has no issuing organization'));
            }

            csr = certParts;

            return getPublicKey(certData);
        })
        .then(function(data) {
            debug('Retrieved public key from certificate chain');
            csr.pubKey = data.publicKey;
            resolve(csr);
        })
        .catch(reject);

}); }

// --------------- Public methods ----------------- //

function validateRequest(headers, rawBody, cb) {

    verifySignature(headers, rawBody)
        .then(cb)
        .catch(cb);
}

module.exports = function() {

    return {
        validateRequest: validateRequest
    };

};

<|endoftext|>


<commit_before>/*
 * Copyright 2016, Lorenzo Mangani (lorenzo.mangani@gmail.com)
 * Copyright 2015, Rao Chenlin (rao.chenlin@gmail.com)
 *
 * This file is part of Sentinl (http://github.com/sirensolutions/sentinl)
 *
 * 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.
 */

import Boom from 'boom';
import _ from 'lodash';
import { errors as esErrors } from 'elasticsearch';

module.exports = function handleESError(error) {
  if (!(error instanceof Error)) {
    throw new Error('Expected an instance of Error');
  }

  if (error instanceof esErrors.ConnectionFault ||
    error instanceof esErrors.ServiceUnavailable ||
    error instanceof esErrors.NoConnections ||
    error instanceof esErrors.RequestTimeout) {
    return Boom.serverTimeout(error);
  } else if (error instanceof esErrors.Conflict || _.contains(error.message, 'index_template_already_exists')) {
    return Boom.conflict(error);
  } else if (error instanceof esErrors[403]) {
    return Boom.forbidden(error);
  } else if (error instanceof esErrors.NotFound) {
    return Boom.notFound(error);
  } else if (error instanceof esErrors.BadRequest) {
    return Boom.badRequest(error);
  } else {
    return error;
  }
};
<commit_msg>_.contains is no more in lodash lib.<commit_after>/*
 * Copyright 2016, Lorenzo Mangani (lorenzo.mangani@gmail.com)
 * Copyright 2015, Rao Chenlin (rao.chenlin@gmail.com)
 *
 * This file is part of Sentinl (http://github.com/sirensolutions/sentinl)
 *
 * 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.
 */

import Boom from 'boom';
import _ from 'lodash';
import { errors as esErrors } from 'elasticsearch';

module.exports = function handleESError(error) {
  if (!(error instanceof Error)) {
    throw new Error('Expected an instance of Error');
  }

  if (error instanceof esErrors.ConnectionFault ||
    error instanceof esErrors.ServiceUnavailable ||
    error instanceof esErrors.NoConnections ||
    error instanceof esErrors.RequestTimeout) {
    return Boom.serverTimeout(error);
  } else if (error instanceof esErrors.Conflict || _.includes(error.message, 'index_template_already_exists')) {
    return Boom.conflict(error);
  } else if (error instanceof esErrors[403]) {
    return Boom.forbidden(error);
  } else if (error instanceof esErrors.NotFound) {
    return Boom.notFound(error);
  } else if (error instanceof esErrors.BadRequest) {
    return Boom.badRequest(error);
  } else {
    return error;
  }
};
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2013, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */
/*jshint strict:false */

var fs = require('fs'),
    path = require('path'),
    mkdirp = require('mkdirp').sync,

    log = require('./log'),
    utils = require('./utils'),

    replacer = require('./replacer'),
    Scan = require('scanfs'),

    // empty files named ".placeholder" are used to materialize
    // otherwise empty dirs from git, but we should ignore them
    ignore = [/^\.(git|svn)/, '.placeholder'],
    TEMPLATE_RE = /[.]hb$/;

function saver(base_from, base_to) {
    return function saveas(pathname) {
        var subpath = pathname.substring(base_from.length);
        return path.join(base_to, subpath);
    };
}

function mkdir(err, pathname) {
    var dest = this.saveas(pathname);
    log.debug('mkdirp %s', dest);
    mkdirp(dest);
}

function copy(err, pathname) {
    var dest = this.saveas(pathname);
    log.debug('copy %s -> %s', pathname, dest);
    fs.createReadStream(pathname)
        .pipe(fs.createWriteStream(dest));
}

function templatizer(err, pathname) {
    var dest = this.saveas(pathname).replace(TEMPLATE_RE, '');

    log.debug('render %s -> %s', pathname, dest);
    fs.createReadStream(pathname)
        .pipe(replacer(this.data))
        .pipe(fs.createWriteStream(dest));
}

function isTemplate(err, pathname, stat) {
    if (stat.isFile() && pathname.match(TEMPLATE_RE)) {
        return 'template';
    }
}

function handleBareFileDir(from, to) {
    var stat = utils.exists(from),
        is_file = stat && stat.isFile(),
        destdir = path.dirname(to);

    if (is_file && !utils.exists(destdir)) {
        // if a --destination option is specified, we may need to mkdirp it
        // this supports the single file archetype use-case
        log.debug('mkdirp --destination', destdir);
        mkdirp(destdir);
    }
}

// todo: enable config TEMPLATE_RE
// todo: modularize templatizer
function main(from, to, data, cb) {
    var scan = new Scan(ignore), errs = [];

    // special case where "from" is a file, not a directory
    // when "from" is a dir, the dir event invokes mkdirp
    // when "from" is a file, this doesn't happen
    handleBareFileDir(from, to);

    function ondone(count) {
        cb(errs.length ? errs : null, count);
    }

    function onerr(err) {
        log.error(err.toString());
        errs.push(err);
    }

    scan.typeSetter = isTemplate;
    scan.saveas = saver(from, to);
    scan.data = data;

    scan.on('dir', mkdir);
    scan.on('file', copy);
    scan.on('template', templatizer);
    scan.on('error', onerr);
    scan.on('done', ondone);
    scan.relatively(from);
    return scan;
}

module.exports = main;
<commit_msg>minor, rm todo comment<commit_after>/*
 * Copyright (c) 2011-2013, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */
/*jshint strict:false */

var fs = require('fs'),
    path = require('path'),
    mkdirp = require('mkdirp').sync,

    log = require('./log'),
    utils = require('./utils'),

    replacer = require('./replacer'),
    Scan = require('scanfs'),

    // empty files named ".placeholder" are used to materialize
    // otherwise empty dirs from git, but we should ignore them
    ignore = [/^\.(git|svn)/, '.placeholder'],
    TEMPLATE_RE = /[.]hb$/;

function saver(base_from, base_to) {
    return function saveas(pathname) {
        var subpath = pathname.substring(base_from.length);
        return path.join(base_to, subpath);
    };
}

function mkdir(err, pathname) {
    var dest = this.saveas(pathname);
    log.debug('mkdirp %s', dest);
    mkdirp(dest);
}

function copy(err, pathname) {
    var dest = this.saveas(pathname);
    log.debug('copy %s -> %s', pathname, dest);
    fs.createReadStream(pathname)
        .pipe(fs.createWriteStream(dest));
}

function templatizer(err, pathname) {
    var dest = this.saveas(pathname).replace(TEMPLATE_RE, '');

    log.debug('render %s -> %s', pathname, dest);
    fs.createReadStream(pathname)
        .pipe(replacer(this.data))
        .pipe(fs.createWriteStream(dest));
}

function isTemplate(err, pathname, stat) {
    if (stat.isFile() && pathname.match(TEMPLATE_RE)) {
        return 'template';
    }
}

function handleBareFileDir(from, to) {
    var stat = utils.exists(from),
        is_file = stat && stat.isFile(),
        destdir = path.dirname(to);

    if (is_file && !utils.exists(destdir)) {
        // if a --destination option is specified, we may need to mkdirp it
        // this supports the single file archetype use-case
        log.debug('mkdirp --destination', destdir);
        mkdirp(destdir);
    }
}

// todo: enable config TEMPLATE_RE
function main(from, to, data, cb) {
    var scan = new Scan(ignore), errs = [];

    // special case where "from" is a file, not a directory
    // when "from" is a dir, the dir event invokes mkdirp
    // when "from" is a file, this doesn't happen
    handleBareFileDir(from, to);

    function ondone(count) {
        cb(errs.length ? errs : null, count);
    }

    function onerr(err) {
        log.error(err.toString());
        errs.push(err);
    }

    scan.typeSetter = isTemplate;
    scan.saveas = saver(from, to);
    scan.data = data;

    scan.on('dir', mkdir);
    scan.on('file', copy);
    scan.on('template', templatizer);
    scan.on('error', onerr);
    scan.on('done', ondone);
    scan.relatively(from);
    return scan;
}

module.exports = main;
<|endoftext|>


<commit_before>var gutil = require('gulp-util');
var prettyTime = require('pretty-hrtime');
var glob = require('glob');
var path = require('path');
var chalk = require('chalk');
var archy = require('archy');
var Liftoff = require('liftoff');
var taskTree = require('../util/taskTree');
var log = require('../util/logger');
var slushPackage = require('../../package');
var argv = {};
var versionFlag = "";
var params = [];
var generatorAndTasks = [];
var generatorName = "";
var generator = {};

module.exports = function init(options) {
  return new Promise((resolve, reject) => {
    generatorName = options.generator;
    params = [generatorName];
    if (!generatorName) {
      if (versionFlag) {
        log.info(slushPackage.version);
      } else {
        logGenerators(getAllGenerators());
      }
      process.exit(0);
      reject();
    }

    generator = getGenerator(generatorName);

    if (!generator) {
      log.info(chalk.red('No generator by name: "' + generatorName + '" was found!'));
      log.info(chalk.red('Try installing it with `npm install -g @td/slush-' + generatorName + '` first.'));
      process.exit(1);
      reject();
    }

    argv.cwd = process.cwd();
    argv.slushfile = path.join(generator.path, 'slushfile.js');
    argv._ = generatorAndTasks;

    var cli = new Liftoff({
      processTitle: 'slush',
      moduleName: 'gulp',
      configName: 'slushfile'
      // completions: require('../lib/completion') FIXME
    });

    cli.on('require', function(name) {
      gutil.log('Requiring external module', chalk.magenta(name));
    });

    cli.on('requireFail', function(name) {
      gutil.log(chalk.red('Failed to load external module'), chalk.magenta(name));
    });

    cli.launch(handleArguments, argv);

  })
}

function handleArguments(env) {

  var argv = env.argv;
  var tasksFlag = argv.T || argv.tasks;
  var tasks = argv._;
  var toRun = tasks.length ? tasks : ['default'];
  var args = params;

  if (versionFlag) {
    log.info(slushPackage.version);
    if (env.modulePackage) {
      gutil.log(env.modulePackage.version);
    }
    if (generator.pkg.version) {
      console.log('[' + chalk.green('@td/slush-' + generator.name) + '] ' + generator.pkg.version);
    }
    process.exit(0);
  }

  if (!env.modulePath) {
    gutil.log(chalk.red('No local gulp install found in'), chalk.magenta(generator.path));
    log.info(chalk.red('This is an issue with the `@td/slush-' + generator.name + '` generator'));
    process.exit(1);
  }

  if (!env.configPath) {
    log.info(chalk.red('No slushfile found'));
    log.info(chalk.red('This is an issue with the `@td/slush-' + generator.name + '` generator'));
    process.exit(1);
  }

  require(env.configPath);
  log.info('Using slushfile', chalk.magenta(env.configPath));

  var gulpInst = require(env.modulePath);
  gulpInst.args = args;
  logEvents(generator.name, gulpInst);

  if (process.cwd() !== env.cwd) {
    process.chdir(env.cwd);
    gutil.log('Working directory changed to', chalk.magenta(env.cwd));
  }

  process.nextTick(function() {
    if (tasksFlag) {
      return logTasks(generator.name, gulpInst);
    }
    gulpInst.start.apply(gulpInst, toRun);
  });
}

function logGenerators(generators) {
  var tree = {
    label: 'Installed generators',
    nodes: generators.map(function (gen) {
      return {label: gen.name + (gen.pkg.version ? chalk.grey(' (' + gen.pkg.version + ')') : '')};
    })
  };
  archy(tree).split('\n').forEach(function(v) {
    if (v.trim().length === 0) return;
    log.info(v);
  });
}

function logTasks(name, localGulp) {
  var tree = taskTree(localGulp.tasks);
  tree.label = 'Tasks for generator ' + chalk.magenta(name);
  archy(tree).split('\n').forEach(function(v) {
    if (v.trim().length === 0) return;
    gutil.log(v);
  });
}

// format orchestrator errors
function formatError(e) {
  if (!e.err) return e.message;
  if (e.err.message) return e.err.message;
  return JSON.stringify(e.err);
}

// wire up logging events
function logEvents(name, gulpInst) {
  gulpInst.on('task_start', function(e) {
    gutil.log('Starting', "'" + chalk.cyan(name + ':' + e.task) + "'...");
  });

  gulpInst.on('task_stop', function(e) {
    var time = prettyTime(e.hrDuration);
    gutil.log('Finished', "'" + chalk.cyan(name + ':' + e.task) + "'", 'after', chalk.magenta(time));
  });

  gulpInst.on('task_err', function(e) {
    var msg = formatError(e);
    var time = prettyTime(e.hrDuration);
    gutil.log("'" + chalk.cyan(name + ':' + e.task) + "'", 'errored after', chalk.magenta(time), chalk.red(msg));
  });

  gulpInst.on('task_not_found', function(err) {
    log.info(chalk.red("Task '" + err.task + "' was not defined in `@td/slush-" + name + "` but you tried to run it."));
    process.exit(1);
  });

  gulpInst.on('stop', function () {
    log.info('Scaffolding done');
  });
}

function getGenerator (name) {
  return getAllGenerators().filter(function (gen) {
    return gen.name === name;
  })[0];
}

function getAllGenerators () {
  const modulesPaths = getModulesPaths().map( path => `${path}/@td`);
  return findGenerators(modulesPaths);
}

function getModulesPaths () {
  if (process.env.NODE_ENV === 'test') {
    return [path.join(__dirname, '..', 'test')];
  }
  var sep = (process.platform === 'win32') ? ';' : ':';
  var paths = [];

  if (process.env.NODE_PATH) {
    paths = paths.concat(process.env.NODE_PATH.split(sep));
  } else {
    if (process.platform === 'win32') {
      paths.push(path.join(process.env.APPDATA, 'npm', 'node_modules/@td'));
    } else {
      paths.push('/usr/lib/node_modules');
      paths.push('/usr/local/lib/node_modules');
    }
  }

  paths.push(path.join(__dirname, '..', '..'));
  paths.push.apply(paths, require.main.paths);
  return paths.filter(function(path, index, all){
    return all.lastIndexOf(path) === index;
  });
}

function findGenerators (searchpaths) {
  return searchpaths.reduce(function (arr, searchpath) {
    return arr.concat(glob.sync('{@*/,}slush-*', {cwd: searchpath, stat: true}).map(function (match) {
      var generator = {path: path.join(searchpath, match), name: match.replace(/(?:@[\w]+[\/|\\]+)?slush-/, ""), pkg: {}};
      try {
        generator.pkg = require(path.join(searchpath, match, 'package.json'));
      } catch (e) {
      }
      return generator;
    }));
  }, []);
}
<commit_msg>去掉@td<commit_after>var gutil = require('gulp-util');
var prettyTime = require('pretty-hrtime');
var glob = require('glob');
var path = require('path');
var chalk = require('chalk');
var archy = require('archy');
var Liftoff = require('liftoff');
var taskTree = require('../util/taskTree');
var log = require('../util/logger');
var slushPackage = require('../../package');
var argv = {};
var versionFlag = "";
var params = [];
var generatorAndTasks = [];
var generatorName = "";
var generator = {};

module.exports = function init(options) {
  return new Promise((resolve, reject) => {
    generatorName = options.generator;
    params = [generatorName];
    if (!generatorName) {
      if (versionFlag) {
        log.info(slushPackage.version);
      } else {
        logGenerators(getAllGenerators());
      }
      process.exit(0);
      reject();
    }

    generator = getGenerator(generatorName);

    if (!generator) {
      log.info(chalk.red('No generator by name: "' + generatorName + '" was found!'));
      log.info(chalk.red('Try installing it with `npm install -g slush-' + generatorName + '` first.'));
      process.exit(1);
      reject();
    }

    argv.cwd = process.cwd();
    argv.slushfile = path.join(generator.path, 'slushfile.js');
    argv._ = generatorAndTasks;

    var cli = new Liftoff({
      processTitle: 'slush',
      moduleName: 'gulp',
      configName: 'slushfile'
      // completions: require('../lib/completion') FIXME
    });

    cli.on('require', function(name) {
      gutil.log('Requiring external module', chalk.magenta(name));
    });

    cli.on('requireFail', function(name) {
      gutil.log(chalk.red('Failed to load external module'), chalk.magenta(name));
    });

    cli.launch(handleArguments, argv);

  })
}

function handleArguments(env) {

  var argv = env.argv;
  var tasksFlag = argv.T || argv.tasks;
  var tasks = argv._;
  var toRun = tasks.length ? tasks : ['default'];
  var args = params;

  if (versionFlag) {
    log.info(slushPackage.version);
    if (env.modulePackage) {
      gutil.log(env.modulePackage.version);
    }
    if (generator.pkg.version) {
      console.log('[' + chalk.green('slush-' + generator.name) + '] ' + generator.pkg.version);
    }
    process.exit(0);
  }

  if (!env.modulePath) {
    gutil.log(chalk.red('No local gulp install found in'), chalk.magenta(generator.path));
    log.info(chalk.red('This is an issue with the `slush-' + generator.name + '` generator'));
    process.exit(1);
  }

  if (!env.configPath) {
    log.info(chalk.red('No slushfile found'));
    log.info(chalk.red('This is an issue with the `slush-' + generator.name + '` generator'));
    process.exit(1);
  }

  require(env.configPath);
  log.info('Using slushfile', chalk.magenta(env.configPath));

  var gulpInst = require(env.modulePath);
  gulpInst.args = args;
  logEvents(generator.name, gulpInst);

  if (process.cwd() !== env.cwd) {
    process.chdir(env.cwd);
    gutil.log('Working directory changed to', chalk.magenta(env.cwd));
  }

  process.nextTick(function() {
    if (tasksFlag) {
      return logTasks(generator.name, gulpInst);
    }
    gulpInst.start.apply(gulpInst, toRun);
  });
}

function logGenerators(generators) {
  var tree = {
    label: 'Installed generators',
    nodes: generators.map(function (gen) {
      return {label: gen.name + (gen.pkg.version ? chalk.grey(' (' + gen.pkg.version + ')') : '')};
    })
  };
  archy(tree).split('\n').forEach(function(v) {
    if (v.trim().length === 0) return;
    log.info(v);
  });
}

function logTasks(name, localGulp) {
  var tree = taskTree(localGulp.tasks);
  tree.label = 'Tasks for generator ' + chalk.magenta(name);
  archy(tree).split('\n').forEach(function(v) {
    if (v.trim().length === 0) return;
    gutil.log(v);
  });
}

// format orchestrator errors
function formatError(e) {
  if (!e.err) return e.message;
  if (e.err.message) return e.err.message;
  return JSON.stringify(e.err);
}

// wire up logging events
function logEvents(name, gulpInst) {
  gulpInst.on('task_start', function(e) {
    gutil.log('Starting', "'" + chalk.cyan(name + ':' + e.task) + "'...");
  });

  gulpInst.on('task_stop', function(e) {
    var time = prettyTime(e.hrDuration);
    gutil.log('Finished', "'" + chalk.cyan(name + ':' + e.task) + "'", 'after', chalk.magenta(time));
  });

  gulpInst.on('task_err', function(e) {
    var msg = formatError(e);
    var time = prettyTime(e.hrDuration);
    gutil.log("'" + chalk.cyan(name + ':' + e.task) + "'", 'errored after', chalk.magenta(time), chalk.red(msg));
  });

  gulpInst.on('task_not_found', function(err) {
    log.info(chalk.red("Task '" + err.task + "' was not defined in `slush-" + name + "` but you tried to run it."));
    process.exit(1);
  });

  gulpInst.on('stop', function () {
    log.info('Scaffolding done');
  });
}

function getGenerator (name) {
  return getAllGenerators().filter(function (gen) {
    return gen.name === name;
  })[0];
}

function getAllGenerators () {
  return findGenerators(getModulesPaths());
}

function getModulesPaths () {
  if (process.env.NODE_ENV === 'test') {
    return [path.join(__dirname, '..', 'test')];
  }
  var sep = (process.platform === 'win32') ? ';' : ':';
  var paths = [];

  if (process.env.NODE_PATH) {
    paths = paths.concat(process.env.NODE_PATH.split(sep));
  } else {
    if (process.platform === 'win32') {
      paths.push(path.join(process.env.APPDATA, 'npm', 'node_modules'));
    } else {
      paths.push('/usr/lib/node_modules');
      paths.push('/usr/local/lib/node_modules');
    }
  }

  paths.push(path.join(__dirname, '..', '..'));
  paths.push.apply(paths, require.main.paths);
  return paths.filter(function(path, index, all){
    return all.lastIndexOf(path) === index;
  });
}

function findGenerators (searchpaths) {
  return searchpaths.reduce(function (arr, searchpath) {
    return arr.concat(glob.sync('{@*/,}slush-*', {cwd: searchpath, stat: true}).map(function (match) {
      var generator = {path: path.join(searchpath, match), name: match.replace(/(?:@[\w]+[\/|\\]+)?slush-/, ""), pkg: {}};
      try {
        generator.pkg = require(path.join(searchpath, match, 'package.json'));
      } catch (e) {
      }
      return generator;
    }));
  }, []);
}
<|endoftext|>


<commit_before>var Client = require('ssh2').Client
  , fs = require('fs')
  , tessel = require('tessel')
  , envfile = require('envfile')
  , config = envfile.parseFileSync(__dirname + '/../config.env')

function sftpDeploy(opts) {

  tessel.logs.info('Connecting to remote Tessel...');
  // Create a new SSH client connection object
  var conn = new Client()

  // Open up an SSH Connection
  conn.on('ready', function() {
    // Log that it was successful
    tessel.logs.info('Connected.');

    // Start an SFTP Transfer
    conn.sftp(function transferStarted (err, sftp) {
      // Throw any unfortunate errors
      if (err) throw err;
      tessel.logs.info('Bundling up code...');
      // Command V2 to extract a tarball it receives on stdin to the remote deploy dir
      conn.exec('rm -rf /root/remote-script/*; tar -x -C /root/remote-script', function(err, rstdin) {
        // Gather details about the file structure of the script being sent
        var ret = tessel.analyzeScript(process.cwd() + "/" + opts.entryPoint, {verbose: opts.verbose});
        // Tar up the code to improve transfer rates
        tessel.tarCode(ret.pushdir, {node: true}, function(err, bundle) {
          tessel.logs.info('Bundled.')
          // Throw any unfortunate errors
          if (err) throw err;

          tessel.logs.info('Deploying code of size', ret.size, 'bytes ...');
          // Write the zipped code to stdin on v2
          rstdin.end(bundle);

          // Wait for the transfer to finish...
          rstdin.once('finish', function() {
            tessel.logs.info('Deployed.');
            tessel.logs.info('Running script...');
            // Once it has been written, run the script with Node
            conn.exec('node remote-script/' + opts.entryPoint, function(err, stream) {
              if (err) throw err;
              stream.on('close', function(code, signal) {
                console.log('CLOSING')
                sftp.end();
                conn.end();
              }).on('data', function(data) {
                console.log(data.toString());
              }).stderr.on('data', function(data) {
                if (opts.verbose) console.log("Err: ", data.toString());
              });
            });
          });
        });
      });
    });
  }).connect({
    host: config.host,
    port: 22,
    username: config.username,
    privateKey: require('fs').readFileSync(config.keyPath),
    passphrase: config.keyPassphrase
  });
}

module.exports.sftpDeploy = sftpDeploy;<commit_msg>Remove unused sftp process<commit_after>var Client = require('ssh2').Client
  , fs = require('fs')
  , tessel = require('tessel')
  , envfile = require('envfile')
  , config = envfile.parseFileSync(__dirname + '/../config.env')

function sftpDeploy(opts) {

  tessel.logs.info('Connecting to remote Tessel...');
  // Create a new SSH client connection object
  var conn = new Client()

  // Open up an SSH Connection
  conn.on('ready', function() {
    // Log that it was successful
    tessel.logs.info('Connected.');

    tessel.logs.info('Bundling up code...');
    // Command V2 to extract a tarball it receives on stdin to the remote deploy dir
    conn.exec('rm -rf /root/remote-script/*; tar -x -C /root/remote-script', function(err, rstdin) {
      // Gather details about the file structure of the script being sent
      var ret = tessel.analyzeScript(process.cwd() + "/" + opts.entryPoint, {verbose: opts.verbose});
      // Tar up the code to improve transfer rates
      tessel.tarCode(ret.pushdir, {node: true}, function(err, bundle) {
        tessel.logs.info('Bundled.')
        // Throw any unfortunate errors
        if (err) throw err;

        tessel.logs.info('Deploying code of size', ret.size, 'bytes ...');
        // Write the zipped code to stdin on v2
        rstdin.end(bundle);

        // Wait for the transfer to finish...
        rstdin.once('finish', function() {
          tessel.logs.info('Deployed.');
          tessel.logs.info('Running script...');
          // Once it has been written, run the script with Node
          conn.exec('node remote-script/' + opts.entryPoint, function(err, stream) {
            if (err) throw err;
            stream.on('close', function(code, signal) {
              conn.end();
            }).on('data', function(data) {
              console.log(data.toString());
            }).stderr.on('data', function(data) {
              if (opts.verbose) console.log("Err: ", data.toString());
            });
          });
        });
      });
    });
  }).connect({
    host: config.host,
    port: 22,
    username: config.username,
    privateKey: require('fs').readFileSync(config.keyPath),
    passphrase: config.keyPassphrase
  });
}

module.exports.sftpDeploy = sftpDeploy;<|endoftext|>


<commit_before>/**
 * Copyright 2015 Mozilla
 *
 * 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.
 */

'use strict';

// Import this first so we can use it to wrap other modules we import.
var promisify = require("promisify-node");

var childProcess = require('child_process');
var ghPages = require('gh-pages');
var gitconfiglocal = require('gitconfiglocal');
var gutil = require('gulp-util');

var fs = require('fs');
var path = require('path');

module.exports = promisify(function(config, callback) {
  config = config || {};
  var ghPagesConfig = {};
  var rootDir = config.rootDir ? config.rootDir : '.';
  var cloneDir = config.cloneDir ? config.cloneDir : null;
  var commitMessage = config.message ? config.message : childProcess.execSync('git log --format=%B -n 1').toString().trim();

  gutil.log('Deploying "' + commitMessage + '"');

  if (cloneDir) {
    ghPagesConfig.clone = cloneDir;
  }

  ghPagesConfig.commitMessage = commitMessage;

  if (fs.existsSync(path.join(rootDir, 'node_modules'))) {
    gutil.log(gutil.colors.red('With the current value of the \'rootDir\' option, the entire node_modules directory is going to be deployed. Please make sure this is what you really want.'));
  }

  if ('GH_TOKEN' in process.env) {
    // We can't log here because it would leak the GitHub token on Travis.
    // We can't use the gh-pages silent option because it makes error messages
    // less informative (https://github.com/mozilla/oghliner/pull/58#issuecomment-147550610).
    // ghPagesConfig.logger = gutil.log;

    // We're using a token to authenticate with GitHub, so we have to embed
    // the token into the repo URL (if it isn't already there).
    gitconfiglocal('./', function(error, config) {
      if (error) {
        callback(error);
        return;
      }

      if ('remote' in config && 'origin' in config.remote && 'url' in config.remote.origin) {
        var url = config.remote.origin.url;
        var match;
        if (match = url.match(/^git@github.com:([^/]+)\/([^.]+)\.git$/) ||
                    url.match(/^https:\/\/github.com\/([^/]+)\/([^.]+)\.git$/)) {
          url = 'https://' + process.env.GH_TOKEN + '@github.com/' + match[1] + '/' + match[2] + '.git';
        }

        ghPages.publish(rootDir, ghPagesConfig, callback);
      } else {
        callback('repo has no origin url');
      }
    });
  } else {
    // We aren't using a token to authenticate with GitHub, so we don't have to
    // alter the repo URL.  And we can log, since we won't leak a GitHub token.
    ghPagesConfig.logger = gutil.log;
    ghPages.publish(rootDir, ghPagesConfig, callback);
  }
});
<commit_msg>Replace usage of existsSync with accessSync in lib/deploy.js<commit_after>/**
 * Copyright 2015 Mozilla
 *
 * 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.
 */

'use strict';

// Import this first so we can use it to wrap other modules we import.
var promisify = require("promisify-node");

var childProcess = require('child_process');
var ghPages = require('gh-pages');
var gitconfiglocal = require('gitconfiglocal');
var gutil = require('gulp-util');

var fs = require('fs');
var path = require('path');

module.exports = promisify(function(config, callback) {
  config = config || {};
  var ghPagesConfig = {};
  var rootDir = config.rootDir ? config.rootDir : '.';
  var cloneDir = config.cloneDir ? config.cloneDir : null;
  var commitMessage = config.message ? config.message : childProcess.execSync('git log --format=%B -n 1').toString().trim();

  gutil.log('Deploying "' + commitMessage + '"');

  if (cloneDir) {
    ghPagesConfig.clone = cloneDir;
  }

  ghPagesConfig.commitMessage = commitMessage;

  try {
    fs.accessSync(path.join(rootDir, 'node_modules'));
    gutil.log(gutil.colors.red('With the current value of the \'rootDir\' option, the entire node_modules directory is going to be deployed. Please make sure this is what you really want.'));
  } catch (ex) {}

  if ('GH_TOKEN' in process.env) {
    // We can't log here because it would leak the GitHub token on Travis.
    // We can't use the gh-pages silent option because it makes error messages
    // less informative (https://github.com/mozilla/oghliner/pull/58#issuecomment-147550610).
    // ghPagesConfig.logger = gutil.log;

    // We're using a token to authenticate with GitHub, so we have to embed
    // the token into the repo URL (if it isn't already there).
    gitconfiglocal('./', function(error, config) {
      if (error) {
        callback(error);
        return;
      }

      if ('remote' in config && 'origin' in config.remote && 'url' in config.remote.origin) {
        var url = config.remote.origin.url;
        var match;
        if (match = url.match(/^git@github.com:([^/]+)\/([^.]+)\.git$/) ||
                    url.match(/^https:\/\/github.com\/([^/]+)\/([^.]+)\.git$/)) {
          url = 'https://' + process.env.GH_TOKEN + '@github.com/' + match[1] + '/' + match[2] + '.git';
        }

        ghPages.publish(rootDir, ghPagesConfig, callback);
      } else {
        callback('repo has no origin url');
      }
    });
  } else {
    // We aren't using a token to authenticate with GitHub, so we don't have to
    // alter the repo URL.  And we can log, since we won't leak a GitHub token.
    ghPagesConfig.logger = gutil.log;
    ghPages.publish(rootDir, ghPagesConfig, callback);
  }
});
<|endoftext|>


<commit_before>/* Based on Categorizr (https://github.com/bjankord/Categorizr) by Brett Jankord (http://www.brettjankord.com) */

'use strict';

var useragent = require('useragent');

var defaultOptions = {
    emptyUserAgentDeviceType: 'desktop',
    unknownUserAgentDeviceType: 'phone',
    botUserAgentDeviceType: 'bot',
    carUserAgentDeviceType: 'car',
    parseUserAgent: false
};

function merge(obj1, obj2) {
    var obj3 = {};
    if (obj1) { for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; } }
    if (obj2) { for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; } }
    return obj3;
}

function DeviceParser(user_agent, options) {
    var self = this;

    self.options = merge(defaultOptions, options);

    self.make_sure_parser_was_executed = function () {
        if (self.options.parseUserAgent === true && !self.useragent)
            self.useragent = useragent.lookup(user_agent);
    };

    self.get_model = function () {
        self.make_sure_parser_was_executed();
        if (self.useragent)
            return self.useragent.device.family;
        return '';
    };

    self.get_type = function () {
        var ua = user_agent;

        if (!ua || ua === '') {
            // No user agent.
            return self.options.emptyUserAgentDeviceType;
        }
        // overwrite Flipboard user agent otherwise it's detected as a desktop
        if (ua.match(/FlipboardProxy/i))
            ua = 'FlipboardProxy/1.1;  http://flipboard.com/browserproxy';
        if (ua.match(/Applebot/i))
            ua = 'Applebot/0.1;  http://www.apple.com/go/applebot';
        if (ua.match(/GoogleTV|SmartTV|Internet TV|NetCast|NETTV|AppleTV|boxee|Kylo|Roku|DLNADOC|hbbtv|CrKey|CE\-HTML/i)) {
            // if user agent is a smart TV - http://goo.gl/FocDk
            return 'tv';
        } else if (ua.match(/Xbox|PLAYSTATION (3|4)|Wii/i)) {
            // if user agent is a TV Based Gaming Console
            return 'tv';
        } else if (ua.match(/QtCarBrowser/i)) {
            // if the user agent is a car
            return self.options.carUserAgentDeviceType;;
        } else if (ua.match(/iP(a|ro)d/i) || (ua.match(/tablet/i) && !ua.match(/RX-34/i)) || ua.match(/FOLIO/i)) {
            // if user agent is a Tablet
            return 'tablet';
        } else if (ua.match(/Linux/i) && ua.match(/Android/i) && !ua.match(/Fennec|mobi|HTC Magic|HTCX06HT|Nexus One|SC-02B|fone 945/i)) {
            // if user agent is an Android Tablet
            return 'tablet';
        } else if (ua.match(/Kindle/i) || (ua.match(/Mac OS/i) && ua.match(/Silk/i)) || (ua.match(/AppleWebKit/i) && ua.match(/Silk/i) && !ua.match(/Playstation Vita/i))) {
            // if user agent is a Kindle or Kindle Fire
            return 'tablet';
        } else if (ua.match(/GT-P10|SC-01C|SHW-M180S|SGH-T849|SCH-I800|SHW-M180L|SPH-P100|SGH-I987|zt180|HTC( Flyer|_Flyer)|Sprint ATP51|ViewPad7|pandigital(sprnova|nova)|Ideos S7|Dell Streak 7|Advent Vega|A101IT|A70BHT|MID7015|Next2|nook/i) || (ua.match(/MB511/i) && ua.match(/RUTEM/i))) {
            // if user agent is a pre Android 3.0 Tablet
            return 'tablet';
        } else if (ua.match(/BOLT|Fennec|Iris|Maemo|Minimo|Mobi|mowser|NetFront|Novarra|Prism|RX-34|Skyfire|Tear|XV6875|XV6975|Google Wireless Transcoder/i)) {
            // if user agent is unique phone User Agent
            return 'phone';
        } else if (ua.match(/Opera/i) && ua.match(/Windows NT 5/i) && ua.match(/HTC|Xda|Mini|Vario|SAMSUNG\-GT\-i8000|SAMSUNG\-SGH\-i9/i)) {
            // if user agent is an odd Opera User Agent - http://goo.gl/nK90K
            return 'phone';
        } else if ((ua.match(/Windows (NT|XP|ME|9)/) && !ua.match(/Phone/i)) && !ua.match(/Bot|Spider|ia_archiver|NewsGator/i) || ua.match(/Win( ?9|NT)/i)) {
            // if user agent is Windows Desktop
            return 'desktop';
        } else if (ua.match(/Macintosh|PowerPC/i) && !ua.match(/Silk/i)) {
            // if agent is Mac Desktop
            return 'desktop';
        } else if (ua.match(/Linux/i) && ua.match(/X11/i) && !ua.match(/Charlotte/i)) {
            // if user agent is a Linux Desktop
            return 'desktop';
        } else if (ua.match(/CrOS/)) {
            // if user agent is a Chrome Book
            return 'desktop';
        } else if (ua.match(/Solaris|SunOS|BSD/i)) {
            // if user agent is a Solaris, SunOS, BSD Desktop
            return 'desktop';
        } else if (ua.match(/Mozilla\/5\.0 \(\)|jack|Applebot|FlipboardProxy|Go 1.1 package|HTMLParser|simplereach|python-requests|ShowyouBot|MetaURI|nineconnections|(^Java\/[0-9._]*)|Commons-HttpClient|InAGist|HTTP-Java-Client|curl|Bot|B-O-T|Crawler|Spider|Spyder|Yahoo|ia_archiver|Covario-IDS|findlinks|DataparkSearch|larbin|Mediapartners-Google|NG-Search|Snappy|Teoma|Jeeves|Charlotte|NewsGator|TinEye|Cerberian|SearchSight|Zao|Scrubby|Qseero|PycURL|Pompos|oegp|SBIder|yoogliFetchAgent|yacy|webcollage|VYU2|voyager|updated|truwoGPS|StackRambler|Sqworm|silk|semanticdiscovery|ScoutJet|Nymesis|NetResearchServer|MVAClient|mogimogi|Mnogosearch|Arachmo|Accoona|holmes|htdig|ichiro|webis|LinkWalker|lwp-trivial|facebookexternalhit|monit\/|ELB-HealthChecker\//i) && !ua.match(/phone|Playstation/i)) {
            // if user agent is a BOT/Crawler/Spider
            return self.options.botUserAgentDeviceType;
        } else {
            // Otherwise assume it is a phone Device
            return self.options.unknownUserAgentDeviceType;
        }
    };
}

function parse(useragent, options) {
    var parser = new DeviceParser(useragent, options);
    var type = parser.get_type();
    var model = parser.get_model();

    var device = {
        parser: parser, // to expose the device parser object to the running app
        type: type,
        model: model,
        is: function (t) {
            return type === t;
        }
    };

    return device;
}

exports = module.exports = parse;
exports.useragent_is = parse; // for backwards compatibility
exports.version = require('../package').version;
exports.Parser = DeviceParser;<commit_msg>added extra smart-tv check<commit_after>/* Based on Categorizr (https://github.com/bjankord/Categorizr) by Brett Jankord (http://www.brettjankord.com) */

'use strict';

var useragent = require('useragent');

var defaultOptions = {
    emptyUserAgentDeviceType: 'desktop',
    unknownUserAgentDeviceType: 'phone',
    botUserAgentDeviceType: 'bot',
    carUserAgentDeviceType: 'car',
    parseUserAgent: false
};

function merge(obj1, obj2) {
    var obj3 = {};
    if (obj1) { for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; } }
    if (obj2) { for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; } }
    return obj3;
}

function DeviceParser(user_agent, options) {
    var self = this;

    self.options = merge(defaultOptions, options);

    self.make_sure_parser_was_executed = function () {
        if (self.options.parseUserAgent === true && !self.useragent)
            self.useragent = useragent.lookup(user_agent);
    };

    self.get_model = function () {
        self.make_sure_parser_was_executed();
        if (self.useragent)
            return self.useragent.device.family;
        return '';
    };

    self.get_type = function () {
        var ua = user_agent;

        if (!ua || ua === '') {
            // No user agent.
            return self.options.emptyUserAgentDeviceType;
        }
        // overwrite Flipboard user agent otherwise it's detected as a desktop
        if (ua.match(/FlipboardProxy/i))
            ua = 'FlipboardProxy/1.1;  http://flipboard.com/browserproxy';
        if (ua.match(/Applebot/i))
            ua = 'Applebot/0.1;  http://www.apple.com/go/applebot';
        if (ua.match(/GoogleTV|SmartTV|SMART-TV|Internet TV|NetCast|NETTV|AppleTV|boxee|Kylo|Roku|DLNADOC|hbbtv|CrKey|CE\-HTML/i)) {
            // if user agent is a smart TV - http://goo.gl/FocDk
            return 'tv';
        } else if (ua.match(/Xbox|PLAYSTATION (3|4)|Wii/i)) {
            // if user agent is a TV Based Gaming Console
            return 'tv';
        } else if (ua.match(/QtCarBrowser/i)) {
            // if the user agent is a car
            return self.options.carUserAgentDeviceType;;
        } else if (ua.match(/iP(a|ro)d/i) || (ua.match(/tablet/i) && !ua.match(/RX-34/i)) || ua.match(/FOLIO/i)) {
            // if user agent is a Tablet
            return 'tablet';
        } else if (ua.match(/Linux/i) && ua.match(/Android/i) && !ua.match(/Fennec|mobi|HTC Magic|HTCX06HT|Nexus One|SC-02B|fone 945/i)) {
            // if user agent is an Android Tablet
            return 'tablet';
        } else if (ua.match(/Kindle/i) || (ua.match(/Mac OS/i) && ua.match(/Silk/i)) || (ua.match(/AppleWebKit/i) && ua.match(/Silk/i) && !ua.match(/Playstation Vita/i))) {
            // if user agent is a Kindle or Kindle Fire
            return 'tablet';
        } else if (ua.match(/GT-P10|SC-01C|SHW-M180S|SGH-T849|SCH-I800|SHW-M180L|SPH-P100|SGH-I987|zt180|HTC( Flyer|_Flyer)|Sprint ATP51|ViewPad7|pandigital(sprnova|nova)|Ideos S7|Dell Streak 7|Advent Vega|A101IT|A70BHT|MID7015|Next2|nook/i) || (ua.match(/MB511/i) && ua.match(/RUTEM/i))) {
            // if user agent is a pre Android 3.0 Tablet
            return 'tablet';
        } else if (ua.match(/BOLT|Fennec|Iris|Maemo|Minimo|Mobi|mowser|NetFront|Novarra|Prism|RX-34|Skyfire|Tear|XV6875|XV6975|Google Wireless Transcoder/i)) {
            // if user agent is unique phone User Agent
            return 'phone';
        } else if (ua.match(/Opera/i) && ua.match(/Windows NT 5/i) && ua.match(/HTC|Xda|Mini|Vario|SAMSUNG\-GT\-i8000|SAMSUNG\-SGH\-i9/i)) {
            // if user agent is an odd Opera User Agent - http://goo.gl/nK90K
            return 'phone';
        } else if ((ua.match(/Windows (NT|XP|ME|9)/) && !ua.match(/Phone/i)) && !ua.match(/Bot|Spider|ia_archiver|NewsGator/i) || ua.match(/Win( ?9|NT)/i)) {
            // if user agent is Windows Desktop
            return 'desktop';
        } else if (ua.match(/Macintosh|PowerPC/i) && !ua.match(/Silk/i)) {
            // if agent is Mac Desktop
            return 'desktop';
        } else if (ua.match(/Linux/i) && ua.match(/X11/i) && !ua.match(/Charlotte/i)) {
            // if user agent is a Linux Desktop
            return 'desktop';
        } else if (ua.match(/CrOS/)) {
            // if user agent is a Chrome Book
            return 'desktop';
        } else if (ua.match(/Solaris|SunOS|BSD/i)) {
            // if user agent is a Solaris, SunOS, BSD Desktop
            return 'desktop';
        } else if (ua.match(/Mozilla\/5\.0 \(\)|jack|Applebot|FlipboardProxy|Go 1.1 package|HTMLParser|simplereach|python-requests|ShowyouBot|MetaURI|nineconnections|(^Java\/[0-9._]*)|Commons-HttpClient|InAGist|HTTP-Java-Client|curl|Bot|B-O-T|Crawler|Spider|Spyder|Yahoo|ia_archiver|Covario-IDS|findlinks|DataparkSearch|larbin|Mediapartners-Google|NG-Search|Snappy|Teoma|Jeeves|Charlotte|NewsGator|TinEye|Cerberian|SearchSight|Zao|Scrubby|Qseero|PycURL|Pompos|oegp|SBIder|yoogliFetchAgent|yacy|webcollage|VYU2|voyager|updated|truwoGPS|StackRambler|Sqworm|silk|semanticdiscovery|ScoutJet|Nymesis|NetResearchServer|MVAClient|mogimogi|Mnogosearch|Arachmo|Accoona|holmes|htdig|ichiro|webis|LinkWalker|lwp-trivial|facebookexternalhit|monit\/|ELB-HealthChecker\//i) && !ua.match(/phone|Playstation/i)) {
            // if user agent is a BOT/Crawler/Spider
            return self.options.botUserAgentDeviceType;
        } else {
            // Otherwise assume it is a phone Device
            return self.options.unknownUserAgentDeviceType;
        }
    };
}

function parse(useragent, options) {
    var parser = new DeviceParser(useragent, options);
    var type = parser.get_type();
    var model = parser.get_model();

    var device = {
        parser: parser, // to expose the device parser object to the running app
        type: type,
        model: model,
        is: function (t) {
            return type === t;
        }
    };

    return device;
}

exports = module.exports = parse;
exports.useragent_is = parse; // for backwards compatibility
exports.version = require('../package').version;
exports.Parser = DeviceParser;
<|endoftext|>


<commit_before>#!/usr/bin/env node

var crawler = require('../lib'),
    program = require('commander'),
    hostName = 'localhost',
    portNumber = 27017,
    dbName = 'apksDB',
    collectionName = 'apks',
    pluginName = ''

var setHost = function(host) {
    hostName = host
}
var setPort = function(port) {
    portNumber = port
}
var setDB = function(db) {
    dbName = db
}
var setCollection = function(collection) {
    collectionName = collection
}
var setPlugin = function(plugin) {
    pluginName = plugin
}

program
    .version("0.0.1")
    .usage("<options> <command>")
    .description("Downloads apks");
program
    .option('-H, --host_name <arg>', "The host name that the mongod is connected to." +
        " Default host is " + hostName, setHost)
    .option('-b, --db_name <arg>', "The name of MongoDB database to store the apks" +
        " . Default name is " + dbName, setDB)
    .option('-p, --plugin <path>', "The path to the plugin for a specific service" +
        " to download APKs from", setPlugin)
    .option('-p, --port_number <arg>', "The port number that the mongod instance is" +
        " listening. Default number is " + portNumber, setPort)
    .option('-c, --collection <arg>', "The name of MongoDB database collection to" +
        " store the apks. Default name is " + collectionName,
        setCollection)

program
    .command("keyword <keyword> <output_dir>")
    .description("Download apps by the given keyword.")
    .action(function(keyword, output_dir) {
        var dbArray = [hostName, portNumber, dbName, collectionName]
        crawler.readKeyword(keyword, output_dir, pluginName, dbArray);
    });

program
    .command("file <keyword-file> <output_dir>")
    .description("Download apps by the given keyword CSV file.")
    .action(function(keyword, output_dir) {
        var dbArray = [hostName, portNumber, dbName, collectionName]
        crawler.readKeywordFile(keyword, output_dir, pluginName, dbArray);
    });

program.parse(process.argv);

if (!program.args.length){
	program.help();
}
<commit_msg>Changes port number flag. Fixes #2<commit_after>#!/usr/bin/env node

var crawler = require('../lib'),
    program = require('commander'),
    hostName = 'localhost',
    portNumber = 27017,
    dbName = 'apksDB',
    collectionName = 'apks',
    pluginName = ''

var setHost = function(host) {
    hostName = host
}
var setPort = function(port) {
    portNumber = port
}
var setDB = function(db) {
    dbName = db
}
var setCollection = function(collection) {
    collectionName = collection
}
var setPlugin = function(plugin) {
    pluginName = plugin
}

program
    .version("0.0.1")
    .usage("<options> <command>")
    .description("Downloads apks");
program
    .option('-H, --host_name <arg>', "The host name that the mongod is connected to." +
        " Default host is " + hostName, setHost)
    .option('-b, --db_name <arg>', "The name of MongoDB database to store the apks" +
        " . Default name is " + dbName, setDB)
    .option('-p, --plugin <path>', "The path to the plugin for a specific service" +
        " to download APKs from", setPlugin)
    .option('-n, --port_number <arg>', "The port number that the mongod instance is" +
        " listening. Default number is " + portNumber, setPort)
    .option('-c, --collection <arg>', "The name of MongoDB database collection to" +
        " store the apks. Default name is " + collectionName,
        setCollection)

program
    .command("keyword <keyword> <output_dir>")
    .description("Download apps by the given keyword.")
    .action(function(keyword, output_dir) {
        var dbArray = [hostName, portNumber, dbName, collectionName]
        crawler.readKeyword(keyword, output_dir, pluginName, dbArray);
    });

program
    .command("file <keyword-file> <output_dir>")
    .description("Download apps by the given keyword CSV file.")
    .action(function(keyword, output_dir) {
        var dbArray = [hostName, portNumber, dbName, collectionName]
        crawler.readKeywordFile(keyword, output_dir, pluginName, dbArray);
    });

program.parse(process.argv);

if (!program.args.length){
	program.help();
}
<|endoftext|>


<commit_before>// db.Base extensions. Currently purely about base methods needed for JSON snapshots

'use strict';

var memoize  = require('memoizee/plain')
  , ensureDb = require('dbjs/valid-dbjs');

module.exports = memoize(function (db) {
	ensureDb(db).Base.prototype.__descriptorPrototype__.setProperties({
		// Field (label: value) JSON serializer
		fieldToJSON: function (ignore) {
			return {
				label: this.dynamicLabelKey ? this.object.get(this.dynamicLabelKey) : this.label,
				value: this.type.valueToJSON(this.object.get(this.key))
			};
		}
	});

	db.Base.prototype.defineProperties({
		// Whether value should be considered as empty
		isEmpty: { type: db.Function },
		toJSON: { type: db.Function }
	});

	return db.Base.defineProperties({
		// Whether provided value should be considered empty
		isValueEmpty: { type: db.Function, value: function (value) {
			if (value == null) return true;
			if (typeof value.isEmpty !== 'function') return false;
			return value.isEmpty();
		} },
		// Returns JSON representation of provided value (in many cases it's same as value)
		valueToJSON: { type: db.Function, value: function (value) {
			if (value == null) return value;
			if (typeof value.toJSON === 'function') return value.toJSON(this);
			if (this.database.isObjectType(this)) value = value.toString(this);
			return (new this(value)).toString(this);
		} }
	});
}, { normalizer: require('memoizee/normalizers/get-1')() });
<commit_msg>Fix toJSON resolution<commit_after>// db.Base extensions. Currently purely about base methods needed for JSON snapshots

'use strict';

var memoize  = require('memoizee/plain')
  , ensureDb = require('dbjs/valid-dbjs');

module.exports = memoize(function (db) {
	ensureDb(db).Base.prototype.__descriptorPrototype__.setProperties({
		// Field (label: value) JSON serializer
		fieldToJSON: function (ignore) {
			return {
				label: this.dynamicLabelKey ? this.object.get(this.dynamicLabelKey) : this.label,
				value: this.type.valueToJSON(this.object.get(this.key), this)
			};
		}
	});

	db.Base.prototype.defineProperties({
		// Whether value should be considered as empty
		isEmpty: { type: db.Function },
		toJSON: { type: db.Function }
	});

	return db.Base.defineProperties({
		// Whether provided value should be considered empty
		isValueEmpty: { type: db.Function, value: function (value) {
			if (value == null) return true;
			if (typeof value.isEmpty !== 'function') return false;
			return value.isEmpty();
		} },
		// Returns JSON representation of provided value (in many cases it's same as value)
		valueToJSON: { type: db.Function, value: function (value, descriptor) {
			if (value == null) return value;
			if (this.database.isObjectType(this)) {
				if (typeof value.toJSON === 'function') return value.toJSON(this);
				return value.toString(descriptor);
			}
			return (new this(value)).toString(descriptor);
		} }
	});
}, { normalizer: require('memoizee/normalizers/get-1')() });
<|endoftext|>


<commit_before>var chalk = require('chalk');
var inquirer = require('inquirer');
var fs = require('fs-extra');
var path = require('path');
var titleize = require('titleize');
var extend = require('extend');

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

var _projectName;
var _promptAnswers;

var PROMPT_OPTIONS = [{
    type: "input",
    name: "projectAuthor",
    message: "Who is the author of the project?",
    validate: function(value) {
        var isValid = (value !== "");

        if(isValid) {
            return true;
        } else {
            return "Author cannot be empty"
        }

    },
    filter: function(value) {
        return titleize(value);
    }
}, {
    type: "input",
    name: "projectDescription",
    message: "What is the project description?",
    default: function () { return ""; }
},{
    type: "confirm",
    name: "isOkToCopyFiles",
    message: "Copying over files to current directory. Press enter to confirm",
    default: true
}]

module.exports = function(appDir) {

    return {
        init: init
    };

    function init(name) {
        _projectName = name;
        console.log('Creating a new project: %s', chalk.underline(_projectName));
        inquirer.prompt(PROMPT_OPTIONS, inquirerCallback);
    }

    function getTemplateData() {
        return {
            projectName: _projectName,
            projectNameFileName: _projectName.toLowerCase().replace(/ /g,"-"),
            // projectAuthor: _promptAnswers.projectAuthor,
            // projectDescription: _promptAnswers.projectDescription
        }
    }

    function inquirerCallback(answers) {
        _promptAnswers = answers;

        if(_promptAnswers.isOkToCopyFiles) {
            console.log('copying over files...');

            fs.copy(appDir, process.cwd(), {
                filter: function(path) {
                    return path.indexOf("node_modules") === -1;
                }
            }, function (err) {
                if (err) return console.error(err)

                templateCopiedFiles();
            })

        } else {
            console.log('User cancelled - no files copied')
        }
    }

    function templateCopiedFiles() {
        var templateData = extend({}, _promptAnswers, getTemplateData())

        fileTemplater.setTemplateData(templateData);
        fileTemplater.setFileList(['_config/creds.json', 'package.json']);

        fileTemplater.run(function() {
            console.log('hits templater callback');
        });
    }
}<commit_msg>chore: Remove comments<commit_after>var chalk = require('chalk');
var inquirer = require('inquirer');
var fs = require('fs-extra');
var path = require('path');
var titleize = require('titleize');
var extend = require('extend');

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

var _projectName;
var _promptAnswers;

var PROMPT_OPTIONS = [{
    type: "input",
    name: "projectAuthor",
    message: "Who is the author of the project?",
    validate: function(value) {
        var isValid = (value !== "");

        if(isValid) {
            return true;
        } else {
            return "Author cannot be empty"
        }

    },
    filter: function(value) {
        return titleize(value);
    }
}, {
    type: "input",
    name: "projectDescription",
    message: "What is the project description?",
    default: function () { return ""; }
},{
    type: "confirm",
    name: "isOkToCopyFiles",
    message: "Copying over files to current directory. Press enter to confirm",
    default: true
}]

module.exports = function(appDir) {

    return {
        init: init
    };

    function init(name) {
        _projectName = name;
        console.log('Creating a new project: %s', chalk.underline(_projectName));
        inquirer.prompt(PROMPT_OPTIONS, inquirerCallback);
    }

    function getTemplateData() {
        return {
            projectName: _projectName,
            projectNameFileName: _projectName.toLowerCase().replace(/ /g,"-"),
        }
    }

    function inquirerCallback(answers) {
        _promptAnswers = answers;

        if(_promptAnswers.isOkToCopyFiles) {
            console.log('copying over files...');

            fs.copy(appDir, process.cwd(), {
                filter: function(path) {
                    return path.indexOf("node_modules") === -1;
                }
            }, function (err) {
                if (err) return console.error(err)

                templateCopiedFiles();
            })

        } else {
            console.log('User cancelled - no files copied')
        }
    }

    function templateCopiedFiles() {
        var templateData = extend({}, _promptAnswers, getTemplateData())

        fileTemplater.setTemplateData(templateData);
        fileTemplater.setFileList(['_config/creds.json', 'package.json']);

        fileTemplater.run(function() {
            console.log('hits templater callback');
        });
    }
}<|endoftext|>


<commit_before>'use strict';

var ensureString = require('es5-ext/object/validate-stringifiable-value')
  , getDebug     = require('debug-ext')
  , now          = require('microtime-x');

module.exports = function (ns) {
	var debug = getDebug('health:' + ensureString(ns));

	debug.color = 5;

	debug("%sMB", (process.memoryUsage().rss / 1048576).toFixed(3));

	setInterval(function () {
		debug("%s %s %sMB", (new Date()).toISOString(), now(),
			(process.memoryUsage().rss / 1048576).toFixed(3) + "\n");
	}, 1000 * 60);
};
<commit_msg>Fix debug log<commit_after>'use strict';

var ensureString = require('es5-ext/object/validate-stringifiable-value')
  , getDebug     = require('debug-ext')
  , now          = require('microtime-x');

module.exports = function (ns) {
	var debug = getDebug('health:' + ensureString(ns));

	debug.color = 5;

	debug("%sMB\n", (process.memoryUsage().rss / 1048576).toFixed(3));

	setInterval(function () {
		debug("%s %s %sMB\n", (new Date()).toISOString(), now(),
			(process.memoryUsage().rss / 1048576).toFixed(3));
	}, 1000 * 60);
};
<|endoftext|>


<commit_before>/*
 * dotlit
 *
 * Literate programming source code processor
 *
 * https://github.com/zoopdoop/dotlit
 *
 * Copyright (c) 2013 Doug Martin, Zoopdoop, LLC.
 *
 * Licensed under the MIT license.
 * https://github.com/zoopdoop/dotlit/blob/master/LICENSE
 */

'use strict';

var fs = require('fs'),
    path = require('path'),
    trim, log, LitFile, EmbeddedFile, _FileOperation;

exports.version = "0.2.0";

// utilities
trim = function (s) {
  return s.replace(/^\s+|\s+$/, '');
};

log = {
  info: console.info.bind(console, '[INFO]'),
  warn: console.warn.bind(console, '[WARN]'),
  error: function() {
    console.log.bind(console, '[ERROR]').apply(console, arguments);
  },
  isVerbose: false,
  verbose: function() {
    if (log.isVerbose) {
      console.log.bind(console, '[INFO]').apply(console, arguments);
    }
  }
};

exports.LitFile = LitFile = function (filename, text) {
  var parseResult;

  this._filename = filename;
  this._extractFilename = this._getExtractFilename(filename);
  this._text = text;

  parseResult = this._parse();
  this._files = parseResult.files;
  this._fileMap = parseResult.fileMap;
};
LitFile.prototype = {

  _getExtractFilename: function (filename) {
    var parts = filename.split(/\.lit(\.|$)/);
    return path.basename(parts[0]);
  },

  _parse: function () {
    var lines = this._text.split('\n'),
        files = [],
        fileMap = {},
        codeLine =/^(\t| {4})/,   // line starts with tab or four spaces
        fileLine = /^\s*\$\s*([^(]*)\s*(\((.*)\))?\s*$/,   // $ filename (operation)
        currentFile = null,
        extractFilename = this._extractFilename,
        getFile;

    getFile = function (filename) {
      if (!fileMap.hasOwnProperty(filename)) {
        fileMap[filename] = new EmbeddedFile(filename);
        files.push(fileMap[filename]);
      }
      return fileMap[filename];
    };

    lines.forEach(function (line) {
      var normalizedLine = line.replace('\t', '    ').substr(4),
          matches,
          filename, operation;

      // empty line?
      if (trim(line).length === 0) {
        // if we have an active file add the line, otherwise ignore
        if (currentFile !== null) {
          currentFile._addLine(normalizedLine);
        }
      }
      // code line?
      else if (codeLine.test(line)) {
        matches = normalizedLine.match(fileLine);

        // file line?
        if (matches !== null) {
          filename = trim(matches[1]);
          operation = matches[3] !== undefined ? trim(matches[3]) : '';

          // anonymous block?
          if (filename.length === 0) {
            filename = extractFilename;
            // empty operations on anonymous blocks means append
            operation = operation.length === 0 ? '+' : operation;
          }

          currentFile = getFile(filename);
          currentFile._addOperation(operation);
        }
        else {
          // first line of anonymous block?
          if (currentFile === null) {
            currentFile = getFile(extractFilename);
            // anonymous blocks always append
            currentFile._addOperation('+');
          }

          currentFile._addLine(normalizedLine);
        }
      }
      // markdown line, so end the current file
      else {
        currentFile = null;
      }
    });

    return {
      files: files,
      fileMap: fileMap
    };
  },

  extract: function (filename) {
    return this._fileMap.hasOwnProperty(filename) ? this._fileMap[filename] : null;
  },

  get html() {
    var marked = require('marked');
    return marked(this._text);
  },

  get filename() {
    return this._filename;
  },

  get extractFilename() {
    return this._extractFilename;
  },

  get text() {
    return this._text;
  },

  get files() {
    return this._files;
  },

  get fileMap() {
    return this._fileMap;
  }
};

exports._FileOperation = _FileOperation = function (operation) {
  this.operation = trim(operation);
  this.lines = [];
};
_FileOperation.prototype = {
  _lineOperation: /^(\d+)/,
  _replaceLine: /^(\d+)$/,
  _insertAtLine: /^(\d+)\s*\+$/,
  _deleteLines: /^(\d+)\s*\-\s*(\d+)$/,
  _replaceLines: /^(\d+)\s*\:\s*(\d+)$/,

  addLine: function (line) {
    this.lines.push(line);
  },

  execute: function (lines) {
    var matches, lineNumber, before, after;

    // remove the trailing empty lines
    while (this.lines.length > 0) {
      if (trim(this.lines[this.lines.length - 1]).length === 0) {
        this.lines.pop();
        continue;
      }
      break;
    }

    // nothing means reset the file
    if (this.operation === '') {
      return this.lines;
    }

    // (+) - append lines
    if (this.operation === '+') {
      return lines.concat(this.lines);
    }

    // line operation?
    matches = this.operation.match(this._lineOperation);
    if (matches !== null) {
      lineNumber = Math.max(1, parseInt(matches[1], 10));

      // pad the lines to the line number
      while (lines.length + 1 < lineNumber) {
        lines.push('');
      }

      // (1) - replace line
      matches = this.operation.match(this._replaceLine);
      if (matches !== null) {
        lines[lineNumber - 1] = this.lines[0];
        return lines;
      }

      // (2+) - insert lines at line number
      matches = this.operation.match(this._insertAtLine);
      if (matches !== null) {
        if (lineNumber === 1) {
          // just prepend the new lines
          lines = this.lines.concat(lines);
        }
        else {
          // insert the lines
          before = lines.slice(0, lineNumber);
          after = lines.slice(lineNumber);
          lines = before.concat(this.lines).concat(after);
        }
        return lines;
      }

      // (1-2) - delete lines at line number
      matches = this.operation.match(this._deleteLines);
      if (matches !== null) {
        lines.splice(lineNumber - 1, parseInt(matches[2], 10));
        return lines;
      }

      // (1:2) - replace N lines at line number
      matches = this.operation.match(this._replaceLines);
      if (matches !== null) {
        lines.splice.apply(lines, [lineNumber - 1, parseInt(matches[2], 10)].concat(this.lines.slice()));
        return lines;
      }
    }

    return lines;
  }
};

exports.EmbeddedFile = EmbeddedFile = function (filename) {
  this._filename = filename;
  this._operations = [];
};
EmbeddedFile.prototype = {

  _addOperation: function (operation) {
    this._operations.push(new _FileOperation(operation));
  },

  _addLine: function (line) {
    var numOperations = this._operations.length;
    if (numOperations > 0) {
      this._operations[numOperations - 1 ].addLine(line);
    }
  },

  get contents() {
    var lines = [];

    this._operations.forEach(function (operation) {
      lines = operation.execute(lines);
    });

    return [lines.join('\n'), '\n'].join('');
  },

  get filename() {
    return this._filename;
  }
};

exports._getCommandLineOptions = function(args) {
  var flags = {
        help: ['-h', '-?', '--help'],
        list: ['-l', '--list'],
        extractAll: ['-a', '--extract-all'],
        verbose: ['-v', '--verbose'],
        force: ['-f', '--force']
      },
      options = {
        help: false,
        list: false,
        extractAll: false,
        verbose: false,
        force: false,
        file: null,
        render: null,
        extractFiles: [],
        printFiles: [],
        error: false
      },
      checkFlag, hasFlag, option, arg, argFilename;

  checkFlag = function (option, arg) {
    if (flags[option].indexOf(arg) !== -1) {
      options[option] = true;
      return true;
    }
    return false;
  };

  // Look at each of the args. I could have used the optimist module here but I wanted to make it testable
  while ((args.length > 0) && (options.error === false)) {
    arg = args.shift();

    // filename?
    if (arg[0] !== '-') {
      // get the dotlit filename
      if (options.file !== null) {
        options.error = 'Only one dotlit file is allowed.  Use --help for usage guidelines.';
      }
      options.file = arg;
    }
    // option with value?
    else if (['-e', '--extract', '-p', '--print', '-r', '--render'].indexOf(arg) !== -1) {
      // get the file
      argFilename = args.shift();
      if ((argFilename === undefined) || (argFilename.length === 0) || (argFilename[0] === '-')) {
        options.error = ['Missing filename for ', arg, '.  Use --help for usage guidelines.'].join('');
      }
      if ((arg === '-e') || (arg === '--extract')) {
        options.extractFiles.push(argFilename);
      }
      else if ((arg === '-p') || (arg === '--print')) {
        options.printFiles.push(argFilename);
      }
      else {
        options.render = argFilename;
      }
    }
    else {
      // look for the flags
      hasFlag = false;
      for (option in flags) {
        if (flags.hasOwnProperty(option)) {
          hasFlag = hasFlag || checkFlag(option, arg);
        }
      }

      if (!hasFlag) {
        options.error = ['Unknown option ', arg].join('');
      }
    }
  }

  // override any previous error with the main one
  if (options.file === null) {
    options.error = 'Missing dotlit filename.  Use --help for usage guidelines.';
  }

  // default to list if no other option given
  options.list = options.list || ((options.render === null) && !options.extractAll && (options.extractFiles.length === 0) && (options.printFiles.length === 0));

  return options;
};

exports._processCommandLine = function() {
  var options = exports._getCommandLineOptions(process.argv.splice(2)),
      litFile;

  if (options.help) {
    console.log([
        ['dolit version ', exports.version].join(''),
        '',
        ['Usage: ', path.basename(process.argv[1]), ' <file> [options]'].join(''),
        '',
        'Options:',
        '  -l, --list            Lists the embedded files (default if no option is given)',
        '  -e, --extract <file>  Extracts the specified embedded file',
        '  -p, --print <file>    Prints the specified embedded file',
        '  -a, --extract-all     Extracts all the embedded files',
        '  -r, --render          Renders the dotfile file as html',
        '  -v, --verbose         Shows messages while processing',
        '  -f, --force           Skips confirmation when extracting files outside the current directory',
        '  -h, -?, --help        Shows this information'
        ].join('\n'));
    return 0;
  }

  if (options.error !== false) {
    log.error(options.error);
    return 3;
  }

  // set the verbosity level
  log.isVerbose = options.verbose;

  // open the file
  try {
    litFile = exports.loadSync(options.file);
  }
  catch (err) {
    log.verbose('Error opening', options.file, err);
    if (err.errno === 34) {
      log.error('Unable to open', options.file);
      return 3;
    }
    throw err;
  }

  // if extracting all just grab all the files
  if (options.extractAll) {
    options.extractFiles = litFile.files;
  }

  // list?
  if (options.list) {
    litFile.files.forEach(function (file) {
      console.log(file.filename);
    });
  }

  // print?
  if (options.printFiles.length > 0) {
    options.printFiles.forEach(function (filename) {
      var embeddedFile = litFile.extract(filename);
      if (embeddedFile === null) {
        log.error('Unable to find', filename, 'in dotlit file');
      }
      else {
        console.log(embeddedFile.contents);
      }
    });
  }

  // check (and prompt) if the file exists outside the tree or if the file is newer
  // this has to be done with a callback as stdio only uses events
  if (options.render || (options.extractFiles.length > 0)) {
    exports._checkBeforeWriting(options, function (checkedRender, checkedExtractFiles) {
      // render html?
      if (checkedRender !== null) {
        if (exports._writeFileSync(checkedRender, litFile.html)) {
          log.verbose('Rendered to', checkedRender);
        }
      }

      // extract files?
      checkedExtractFiles.forEach(function (filename) {
        var embeddedFile = litFile.extract(filename);

        if (embeddedFile !== null) {
          if (exports._writeFileSync(filename, embeddedFile.contents)) {
            log.verbose('Extracted', filename);
          }
        }
        else {
          log.error('Unable to find', filename, 'in dotlit file');
        }
      });
    });
  }

  return 0;
};

exports._checkBeforeWriting = function(options, done) {
  var checkedRender = null,
      checkedExtractFiles = [],
      checkExtractedFiles;

  if (options.force) {
    done(options.render, options.extractFiles);
    return;
  }

  checkExtractedFiles = function (index) {
    index = index || 0;
    if (index < options.extractFiles.length) {
      exports._checkBeforeWritingPrompt('Extract', options.extractFiles[index], function () {
        checkedExtractFiles.push(options.extractFiles[index]);
      }, function () {
        checkExtractedFiles(index + 1);
      });
    }
    else {
      done(checkedRender, checkedExtractFiles);
    }
  };

  if (options.render !== null) {
    exports._checkBeforeWritingPrompt('Render', options.render, function () {
      checkedRender = options.render;
    }, checkExtractedFiles);
  }
  else {
    checkExtractedFiles();
  }
};

exports._checkBeforeWritingPrompt = function (action, filename, ifYes, done) {
  var prompt = require('cli-prompt'),
      cwd = process.cwd(),
      resolvedPath = path.resolve(cwd, filename),
      promptText;

  promptText = cwd !== resolvedPath.substr(0, cwd.length) ? ([action, ' ', filename, '? (outside of tree) [y/N] '].join('')) : null;
  if (promptText !== null) {
    prompt(promptText, function (val, end) {
      if ((val === 'y') || (val === 'yes')) {
        ifYes();
      }
      end();
      done();
    });
  }
  else {
    ifYes();
    done();
  }
};

exports._writeFileSync = function (filename, text) {
  try {
    fs.writeFileSync(filename, text);
  }
  catch (err) {
    log.error('Unable to write', filename, err);
    return false;
  }
  return true;
};

exports.load = function (filename, done) {
  fs.readFile(filename, 'utf8', function (err, data) {
    return err ? done(err) : done(null, exports.create(filename, data));
  });
};

exports.loadSync = function (filename) {
  var data = fs.readFileSync(filename, 'utf8');
  return data === null ? null : exports.create(filename, data);
};

exports.create = function (filename, data) {
  return new LitFile(filename, data);
};

<commit_msg>Added print-all command line option and removed short command line options<commit_after>/*
 * dotlit
 *
 * Literate programming source code processor
 *
 * https://github.com/zoopdoop/dotlit
 *
 * Copyright (c) 2013 Doug Martin, Zoopdoop, LLC.
 *
 * Licensed under the MIT license.
 * https://github.com/zoopdoop/dotlit/blob/master/LICENSE
 */

'use strict';

var fs = require('fs'),
    path = require('path'),
    trim, log, LitFile, EmbeddedFile, _FileOperation;

exports.version = "0.2.0";

// utilities
trim = function (s) {
  return s.replace(/^\s+|\s+$/, '');
};

log = {
  info: console.info.bind(console, '[INFO]'),
  warn: console.warn.bind(console, '[WARN]'),
  error: function() {
    console.log.bind(console, '[ERROR]').apply(console, arguments);
  },
  isVerbose: false,
  verbose: function() {
    if (log.isVerbose) {
      console.log.bind(console, '[INFO]').apply(console, arguments);
    }
  }
};

exports.LitFile = LitFile = function (filename, text) {
  var parseResult;

  this._filename = filename;
  this._extractFilename = this._getExtractFilename(filename);
  this._text = text;

  parseResult = this._parse();
  this._files = parseResult.files;
  this._fileMap = parseResult.fileMap;
};
LitFile.prototype = {

  _getExtractFilename: function (filename) {
    var parts = filename.split(/\.lit(\.|$)/);
    return path.basename(parts[0]);
  },

  _parse: function () {
    var lines = this._text.split('\n'),
        files = [],
        fileMap = {},
        codeLine =/^(\t| {4})/,   // line starts with tab or four spaces
        fileLine = /^\s*\$\s*([^(]*)\s*(\((.*)\))?\s*$/,   // $ filename (operation)
        currentFile = null,
        extractFilename = this._extractFilename,
        getFile;

    getFile = function (filename) {
      if (!fileMap.hasOwnProperty(filename)) {
        fileMap[filename] = new EmbeddedFile(filename);
        files.push(fileMap[filename]);
      }
      return fileMap[filename];
    };

    lines.forEach(function (line) {
      var normalizedLine = line.replace('\t', '    ').substr(4),
          matches,
          filename, operation;

      // empty line?
      if (trim(line).length === 0) {
        // if we have an active file add the line, otherwise ignore
        if (currentFile !== null) {
          currentFile._addLine(normalizedLine);
        }
      }
      // code line?
      else if (codeLine.test(line)) {
        matches = normalizedLine.match(fileLine);

        // file line?
        if (matches !== null) {
          filename = trim(matches[1]);
          operation = matches[3] !== undefined ? trim(matches[3]) : '';

          // anonymous block?
          if (filename.length === 0) {
            filename = extractFilename;
            // empty operations on anonymous blocks means append
            operation = operation.length === 0 ? '+' : operation;
          }

          currentFile = getFile(filename);
          currentFile._addOperation(operation);
        }
        else {
          // first line of anonymous block?
          if (currentFile === null) {
            currentFile = getFile(extractFilename);
            // anonymous blocks always append
            currentFile._addOperation('+');
          }

          currentFile._addLine(normalizedLine);
        }
      }
      // markdown line, so end the current file
      else {
        currentFile = null;
      }
    });

    return {
      files: files,
      fileMap: fileMap
    };
  },

  extract: function (filename) {
    return this._fileMap.hasOwnProperty(filename) ? this._fileMap[filename] : null;
  },

  get html() {
    var marked = require('marked');
    return marked(this._text);
  },

  get filename() {
    return this._filename;
  },

  get extractFilename() {
    return this._extractFilename;
  },

  get text() {
    return this._text;
  },

  get files() {
    return this._files;
  },

  get filenames() {
    return this._files.map(function (file) {
      return file.filename;
    });
  },

  get fileMap() {
    return this._fileMap;
  }
};

exports._FileOperation = _FileOperation = function (operation) {
  this.operation = trim(operation);
  this.lines = [];
};
_FileOperation.prototype = {
  _lineOperation: /^(\d+)/,
  _replaceLine: /^(\d+)$/,
  _insertAtLine: /^(\d+)\s*\+$/,
  _deleteLines: /^(\d+)\s*\-\s*(\d+)$/,
  _replaceLines: /^(\d+)\s*\:\s*(\d+)$/,

  addLine: function (line) {
    this.lines.push(line);
  },

  execute: function (lines) {
    var matches, lineNumber, before, after;

    // remove the trailing empty lines
    while (this.lines.length > 0) {
      if (trim(this.lines[this.lines.length - 1]).length === 0) {
        this.lines.pop();
        continue;
      }
      break;
    }

    // nothing means reset the file
    if (this.operation === '') {
      return this.lines;
    }

    // (+) - append lines
    if (this.operation === '+') {
      return lines.concat(this.lines);
    }

    // line operation?
    matches = this.operation.match(this._lineOperation);
    if (matches !== null) {
      lineNumber = Math.max(1, parseInt(matches[1], 10));

      // pad the lines to the line number
      while (lines.length + 1 < lineNumber) {
        lines.push('');
      }

      // (1) - replace line
      matches = this.operation.match(this._replaceLine);
      if (matches !== null) {
        lines[lineNumber - 1] = this.lines[0];
        return lines;
      }

      // (2+) - insert lines at line number
      matches = this.operation.match(this._insertAtLine);
      if (matches !== null) {
        if (lineNumber === 1) {
          // just prepend the new lines
          lines = this.lines.concat(lines);
        }
        else {
          // insert the lines
          before = lines.slice(0, lineNumber);
          after = lines.slice(lineNumber);
          lines = before.concat(this.lines).concat(after);
        }
        return lines;
      }

      // (1-2) - delete lines at line number
      matches = this.operation.match(this._deleteLines);
      if (matches !== null) {
        lines.splice(lineNumber - 1, parseInt(matches[2], 10));
        return lines;
      }

      // (1:2) - replace N lines at line number
      matches = this.operation.match(this._replaceLines);
      if (matches !== null) {
        lines.splice.apply(lines, [lineNumber - 1, parseInt(matches[2], 10)].concat(this.lines.slice()));
        return lines;
      }
    }

    return lines;
  }
};

exports.EmbeddedFile = EmbeddedFile = function (filename) {
  this._filename = filename;
  this._operations = [];
};
EmbeddedFile.prototype = {

  _addOperation: function (operation) {
    this._operations.push(new _FileOperation(operation));
  },

  _addLine: function (line) {
    var numOperations = this._operations.length;
    if (numOperations > 0) {
      this._operations[numOperations - 1 ].addLine(line);
    }
  },

  get contents() {
    var lines = [];

    this._operations.forEach(function (operation) {
      lines = operation.execute(lines);
    });

    return [lines.join('\n'), '\n'].join('');
  },

  get filename() {
    return this._filename;
  }
};

exports._getCommandLineOptions = function(args) {
  var flags = {
        '--help': 'help',
        '--list': 'list',
        '--extract-all': 'extractAll',
        '--print-all': 'printAll',
        '--verbose': 'verbose',
        '--force': 'force'
      },
      options = {
        help: false,
        list: false,
        extractAll: false,
        printAll: false,
        verbose: false,
        force: false,
        file: null,
        render: null,
        extractFiles: [],
        printFiles: [],
        error: false
      },
      checkFlag, hasFlag, option, arg, argFilename;

  checkFlag = function (option, arg) {
    if (flags[option].indexOf(arg) !== -1) {
      options[option] = true;
      return true;
    }
    return false;
  };

  // Look at each of the args. I could have used the optimist module here but I wanted to make it testable
  while ((args.length > 0) && (options.error === false)) {
    arg = args.shift();

    // filename?
    if (arg[0] !== '-') {
      // get the dotlit filename
      if (options.file !== null) {
        options.error = 'Only one dotlit file is allowed';
      }
      options.file = arg;
    }
    // option with value?
    else if (['--extract', '--print', '--render'].indexOf(arg) !== -1) {
      // get the file
      argFilename = args.shift();
      if ((argFilename === undefined) || (argFilename.length === 0) || (argFilename[0] === '-')) {
        options.error = ['Missing filename for ', arg].join('');
      }
      if (arg === '--extract') {
        options.extractFiles.push(argFilename);
      }
      else if (arg === '--print') {
        options.printFiles.push(argFilename);
      }
      else {
        options.render = argFilename;
      }
    }
    else {
      hasFlag = flags.hasOwnProperty(arg);
      if (hasFlag) {
        options[flags[arg]] = true;
      }
      else {
        options.error = ['Unknown option ', arg].join('');
      }
    }
  }

  // override any previous error with the main one
  if (options.file === null) {
    options.error = 'Missing dotlit filename';
  }

  // default to list if no other option given
  options.list = options.list || ((options.render === null) && !options.extractAll && (options.extractFiles.length === 0) && !options.printAll && (options.printFiles.length === 0));

  return options;
};

exports._processCommandLine = function() {
  var options = exports._getCommandLineOptions(process.argv.splice(2)),
      litFile, printAllLine;

  if (options.help) {
    console.log([
        ['dolit version ', exports.version].join(''),
        '',
        ['Usage: ', path.basename(process.argv[1]), ' <file> [options]'].join(''),
        '',
        'Options:',
        '  --list            Lists the embedded files (default if no option is given)',
        '  --extract <file>  Extracts the specified embedded file',
        '  --extract-all     Extracts all the embedded files',
        '  --print <file>    Prints the specified embedded file to stdout',
        '  --print-all       Prints all the embedded files to stdout',
        '  --render <file>   Renders the dotlit file as html',
        '  --force           Skips confirmation when extracting files outside the current directory',
        '  --verbose         Shows messages while processing',
        '  --help            Shows this information'
        ].join('\n'));
    return 0;
  }

  if (options.error !== false) {
    log.error([options.error, '.  Use --help for usage guidelines.'].join(''));
    return 3;
  }

  // set the verbosity level
  log.isVerbose = options.verbose;

  // open the file
  try {
    litFile = exports.loadSync(options.file);
  }
  catch (err) {
    log.verbose('Error opening', options.file, err);
    if (err.errno === 34) {
      log.error('Unable to open', options.file);
      return 3;
    }
    throw err;
  }

  // if extracting or printing all just grab all the files
  if (options.extractAll) {
    options.extractFiles = litFile.filenames;
  }
  if (options.printAll) {
    options.printFiles = litFile.filenames;
  }

  // list?
  if (options.list) {
    litFile.filenames.forEach(function (filename) {
      console.log(filename);
    });
  }

  // print?
  if (options.printFiles.length > 0) {
    printAllLine = (new Array(80)).join('-');
    options.printFiles.forEach(function (filename) {
      var embeddedFile = litFile.extract(filename);
      if (embeddedFile === null) {
        log.error('Unable to find', filename, 'in dotlit file');
      }
      else {
        if (options.printFiles.length > 1) {
          console.log(filename);
          console.log(printAllLine);
        }
        console.log(embeddedFile.contents);
      }
    });
  }

  // check (and prompt) if the file exists outside the tree or if the file is newer
  // this has to be done with a callback as stdio only uses events
  if (options.render || (options.extractFiles.length > 0)) {
    exports._checkBeforeWriting(options, function (checkedRender, checkedExtractFiles) {
      // render html?
      if (checkedRender !== null) {
        if (exports._writeFileSync(checkedRender, litFile.html)) {
          log.verbose('Rendered to', checkedRender);
        }
      }

      // extract files?
      checkedExtractFiles.forEach(function (filename) {
        var embeddedFile = litFile.extract(filename);

        if (embeddedFile !== null) {
          if (exports._writeFileSync(filename, embeddedFile.contents)) {
            log.verbose('Extracted', filename);
          }
        }
        else {
          log.error('Unable to find', filename, 'in dotlit file');
        }
      });
    });
  }

  return 0;
};

exports._checkBeforeWriting = function(options, done) {
  var checkedRender = null,
      checkedExtractFiles = [],
      checkExtractedFiles;

  if (options.force) {
    done(options.render, options.extractFiles);
    return;
  }

  checkExtractedFiles = function (index) {
    index = index || 0;
    if (index < options.extractFiles.length) {
      exports._checkBeforeWritingPrompt('Extract', options.extractFiles[index], function () {
        checkedExtractFiles.push(options.extractFiles[index]);
      }, function () {
        checkExtractedFiles(index + 1);
      });
    }
    else {
      done(checkedRender, checkedExtractFiles);
    }
  };

  if (options.render !== null) {
    exports._checkBeforeWritingPrompt('Render', options.render, function () {
      checkedRender = options.render;
    }, checkExtractedFiles);
  }
  else {
    checkExtractedFiles();
  }
};

exports._checkBeforeWritingPrompt = function (action, filename, ifYes, done) {
  var prompt = require('cli-prompt'),
      cwd = process.cwd(),
      resolvedPath = path.resolve(cwd, filename),
      promptText;

  promptText = cwd !== resolvedPath.substr(0, cwd.length) ? ([action, ' ', filename, '? (outside of tree) [y/N] '].join('')) : null;
  if (promptText !== null) {
    prompt(promptText, function (val, end) {
      if ((val === 'y') || (val === 'yes')) {
        ifYes();
      }
      end();
      done();
    });
  }
  else {
    ifYes();
    done();
  }
};

exports._writeFileSync = function (filename, text) {
  try {
    fs.writeFileSync(filename, text);
  }
  catch (err) {
    log.error('Unable to write', filename, err);
    return false;
  }
  return true;
};

exports.load = function (filename, done) {
  fs.readFile(filename, 'utf8', function (err, data) {
    return err ? done(err) : done(null, exports.create(filename, data));
  });
};

exports.loadSync = function (filename) {
  var data = fs.readFileSync(filename, 'utf8');
  return data === null ? null : exports.create(filename, data);
};

exports.create = function (filename, data) {
  return new LitFile(filename, data);
};

<|endoftext|>


<commit_before>var mongoose = require('mongoose'),
  Schema = mongoose.Schema;

var user = new Schema({
  _id: String,
  name: String,
  email: String,
  office: String,
  phone: String,
  mobile: String,
  roles: [String],
  lastVisitedOn: Date,
  forms: [String],
  travelers: [String],
  subscribe: {
    type: Boolean,
    default: false
  }
});

var User = mongoose.model('User', user);
module.exports = {
  User: User
};<commit_msg>update user model to use objectid<commit_after>var mongoose = require('mongoose'),
  Schema = mongoose.Schema,
  ObjectId = Schema.Types.ObjectId;

var user = new Schema({
  _id: String,
  name: String,
  email: String,
  office: String,
  phone: String,
  mobile: String,
  roles: [String],
  lastVisitedOn: Date,
  forms: [ObjectId],
  travelers: [ObjectId],
  subscribe: {
    type: Boolean,
    default: false
  }
});

var User = mongoose.model('User', user);
module.exports = {
  User: User
};<|endoftext|>