<commit_before>var notFs = {};

var notFsTree;

notFs.getTree = function(){
    return notFsTree;
};

notFs.setTree = function(tree){
    notFsTree = tree;
};

var forceStack = {};

notFs.setForce = function(method, returnOrCallback){

    if(undefined === forceStack[method]){
        forceStack[method] =  [];
    }
    forceStack[method].push(returnOrCallback);

};

notFs.clearForce = function(method){

    forceStack[method] = [];

};

notFs.hasForce = function(method){

    if(undefined === forceStack[method]){
        return false;
    }

    return ( 0 < forceStack[method].length);

};

notFs.doForce = function(method){

    if(undefined === forceStack[method]){
        return undefined;
    }

    method = forceStack[method].shift();

    return method(notFs);

};

notFs.access = function(path, mode, callback){
    console.log('access', arguments);
};

notFs.accessSync = function(path, mode){
    console.log('accessSync', arguments);
};

notFs.appendFile = function(file, data, options, callback){

    notFs.appendFileSync(file, data, options);

    process.nextTick(function () {
        callback(null);
    });

};

notFs.appendFileSync = function(file, data, options){

    if(false === notFsTree.exists(file)){
         notFsTree.addFile(file);
    }

    var content = notFsTree.getByFqn(file).getContent();

    notFsTree.getByFqn(file).setContent(content + data);

};

notFs.chmod = function(path, mode, callback){
    console.log('chmod', arguments);
};

notFs.chmodSync = function(path, mode){
    console.log('chmodSync', arguments);
};

notFs.chown = function(path, uid, gid, callback){
    console.log('chown', arguments);
};

notFs.chownSync = function(path, uid, gid){
    console.log('chownSync', arguments);
};

notFs.close = function(fd, callback){
    console.log('close', arguments);
};

notFs.closeSync = function(fd){
    console.log('closeSync', arguments);
};

notFs.createReadStream = function(path, options){
    console.log('createReadStream', arguments);
};

notFs.createWriteStream = function(path, options){
    console.log('createWriteStream', arguments);
};

notFs.exists = function(path, callback){
    var exists = notFsTree.exists(path);

    process.nextTick(function () {
        callback(exists);
    });

};

notFs.existsSync = function(path){
    return notFsTree.exists(path);
};

notFs.fchmod = function(fd, mode, callback){
    console.log('fchmod', arguments);
};

notFs.fchmodSync = function(fd, mode){
    console.log('fchmodSync', arguments);
};

notFs.fchown = function(fd, uid, gid, callback){
    console.log('fchown', arguments);
};

notFs.fchownSync = function(fd, uid, gid){
    console.log('fchownSync', arguments);
};

notFs.fdatasync = function(fd, callback){
    console.log('fdatasync', arguments);
};

notFs.fdatasyncSync = function(fd){
    console.log('fdatasyncSync', arguments);
};

notFs.fstat = function(fd, callback){
    console.log('fstat', arguments);
};

notFs.fstatSync = function(fd){
    console.log('fstatSync', arguments);
};

notFs.fsync = function(fd, callback){
    console.log('fsync', arguments);
};

notFs.fsyncSync = function(fd){
    console.log('fsyncSync', arguments);
};

notFs.ftruncate = function(fd, len, callback){
    console.log('ftruncate', arguments);
};

notFs.ftruncateSync = function(fd, len){
    console.log('ftruncateSync', arguments);
};

notFs.futimes = function(fd, atime, mtime, callback){
    console.log('futimes', arguments);
};

notFs.futimesSync = function(fd, atime, mtime){
    console.log('futimesSync', arguments);
};

notFs.lchmod = function(path, mode, callback){
    console.log('lchmod', arguments);
};

notFs.lchmodSync = function(path, mode){
    console.log('lchmodSync', arguments);
};

notFs.lchown = function(path, uid, gid, callback){
    console.log('lchown', arguments);
};

notFs.lchownSync = function(path, uid, gid){
    console.log('lchownSync', arguments);
};

notFs.link = function(srcpath, dstpath, callback){
    console.log('link', arguments);
};

notFs.linkSync = function(srcpath, dstpath){
    console.log('linkSync', arguments);
};

notFs.lstat = function(path, callback){
    console.log('lstat', arguments);
};

notFs.lstatSync = function(path){
    console.log('lstatSync', arguments);
};

notFs.mkdir = function(path, mode, callback){

    if(undefined === callback){
        callback = mode;
        mode = '0755';
    }

    notFs.mkdirSync(path, mode);

    process.nextTick(function () {
        callback(null);
    });

};

notFs.mkdirSync = function(path, mode){

    var alreadyExists = notFsTree.exists(path);

    if(true === alreadyExists){
        throw new Error('EEXIST, file already exists \'' + path +'\'');
    }

    notFsTree.addDir(path);
};

notFs.open = function(path, flags, mode, callback){
    console.log('open', arguments);
};

notFs.openSync = function(path, flags, mode){
    console.log('openSync', arguments);
};

notFs.read = function(fd, buffer, offset, length, position, callback){
    console.log('read', arguments);
};

notFs.readdir = function(path, callback){

    var error = null;
    var files = null;

    try{
        var files = notFs.readdirSync(path);
    }
    catch(e){
        error = e;
    }

    process.nextTick(function () {
        callback(error, files);
    });

};

notFs.readdirSync = function(path){
    if(false === notFsTree.exists(path)){
        throw new Error('ENOENT: no such file or directory, scandir \''+ path + '\'');
    }

    var chilren = notFsTree.getByFqn(path).getChildren();

    var childrenNames = [];
    chilren.forEach(function(child){
        childrenNames.push(child.getName());
    });

    return childrenNames;
};

notFs.readFile = function(file, options, callback){
    var error = null;

    try{
        var content = notFs.readFileSync(file);
    }
    catch(e){
        error = e.message;
    }

    process.nextTick(function () {
        callback(error, content);
    });
};

notFs.readFileSync = function(file, options){

    if(false === notFsTree.exists(file)){
         throw new Error('Error: ENOENT, no such file or directory \'' + file+ '\'');
    }
    return notFsTree.getByFqn(file).getContent();
};

notFs.readlink = function(path, callback){
    console.log('readlink', arguments);
};

notFs.readlinkSync = function(path){
    console.log('readlinkSync', arguments);
};

notFs.realpath = function(path, cache, callback){
    console.log('realpath', arguments);
};

notFs.readSync = function(fd, buffer, offset, length, position){
    console.log('readSync', arguments);
};

notFs.realpathSync = function(path, cache){
    console.log('realpathSync', arguments);
};

notFs.rename = function(oldPath, newPath, callback){
    notFs.renameSync(oldPath, newPath);

    process.nextTick(function () {
        callback(null);
    });
};

//@TODO implement a real rename by seperating items from tree
notFs.renameSync = function(oldPath, newPath){

    if(false === notFsTree.exists(oldPath)){
         throw new Error(oldPath + ' does not exists.');
    }

    var node = notFsTree.getByFqn(oldPath);

    notFsTree.remove(oldPath);

    if(true === node.isDir()){
       notFsTree.addDir(newPath);
    }
    else if(true === node.isFile()){
       notFs.writeFileSync(newPath, node.getContent, {encoding:'UTF-8'});
    }

};

notFs.rmdir = function(path, callback){
    console.log('rmdir', arguments);
};

notFs.rmdirSync = function(path){
    notFsTree.remove(path);
};

notFs.stat = function(path, callback){
    console.log('stat', arguments);
};

notFs.statSync = function(path){
    var node = notFsTree.getByFqn(path);
    return node.getStats();
};

notFs.symlink = function(target, path, type, callback){
    console.log('symlink', arguments);
};

notFs.symlinkSync = function(target, path, type){
    console.log('symlinkSync', arguments);
};

notFs.truncate = function(path, len, callback){
    console.log('truncate', arguments);
};

notFs.truncateSync = function(path, len){
    console.log('truncateSync', arguments);
};

notFs.unlink = function(path, callback){

    notFsTree.remove(path);

    callbackParam = null;

    if(true === notFs.hasForce('unlink')){
        callbackParam = notFs.doForce('unlink');
    }

    process.nextTick(function () {
        callback(callbackParam);
    });
};

notFs.unlinkSync = function(path){
    notFsTree.remove(path);
    return null;
};

notFs.unwatchFile = function(filename, listener){
    console.log('unwatchFile', arguments);
};

notFs.utimes = function(path, atime, mtime, callback){
    console.log('utimes', arguments);
};

notFs.utimesSync = function(path, atime, mtime){
    console.log('utimesSync', arguments);
};

notFs.watch = function(filename, options, listener){
    console.log('watch', arguments);
};

notFs.watchFile = function(filename, options, listener){
    console.log('watchFile', arguments);
};

/**
 * @TODO param options is optional
 * @TODO add errors to callback
 */
notFs.writeFile = function(file, data, options, callback){

    notFs.writeFileSync(file, data, options);

    process.nextTick(function () {
        callback(null);
    });

};

/**
 * @TODO param options is optional
 */
notFs.writeFileSync = function(file, data, options){
    if(false === notFsTree.exists(file)){
         notFsTree.addFile(file);
    }
    notFsTree.getByFqn(file).setContent(data);

};

module.exports = notFs;

<commit_msg>make mockable methods appendFile, mkdir, readdir, rename and writeFile<commit_after>var notFs = {};

var notFsTree;

notFs.getTree = function(){
    return notFsTree;
};

notFs.setTree = function(tree){
    notFsTree = tree;
};

var forceStack = {};

notFs.setForce = function(method, returnOrCallback){

    if(undefined === forceStack[method]){
        forceStack[method] =  [];
    }
    forceStack[method].push(returnOrCallback);

};

notFs.clearForce = function(method){

    forceStack[method] = [];

};

notFs.hasForce = function(method){

    if(undefined === forceStack[method]){
        return false;
    }

    return ( 0 < forceStack[method].length);

};

notFs.doForce = function(method){

    if(undefined === forceStack[method]){
        return undefined;
    }

    method = forceStack[method].shift();

    return method(notFs);

};

notFs.access = function(path, mode, callback){
    console.log('access', arguments);
};

notFs.accessSync = function(path, mode){
    console.log('accessSync', arguments);
};

notFs.appendFile = function(file, data, options, callback){

    notFs.appendFileSync(file, data, options);

    callbackParam = null;

    if(true === notFs.hasForce('appendFile')){
        callbackParam = notFs.doForce('appendFile');
    }

    process.nextTick(function () {
        callback(callbackParam);
    });

};

notFs.appendFileSync = function(file, data, options){

    if(false === notFsTree.exists(file)){
         notFsTree.addFile(file);
    }

    var content = notFsTree.getByFqn(file).getContent();

    notFsTree.getByFqn(file).setContent(content + data);

};

notFs.chmod = function(path, mode, callback){
    console.log('chmod', arguments);
};

notFs.chmodSync = function(path, mode){
    console.log('chmodSync', arguments);
};

notFs.chown = function(path, uid, gid, callback){
    console.log('chown', arguments);
};

notFs.chownSync = function(path, uid, gid){
    console.log('chownSync', arguments);
};

notFs.close = function(fd, callback){
    console.log('close', arguments);
};

notFs.closeSync = function(fd){
    console.log('closeSync', arguments);
};

notFs.createReadStream = function(path, options){
    console.log('createReadStream', arguments);
};

notFs.createWriteStream = function(path, options){
    console.log('createWriteStream', arguments);
};

notFs.exists = function(path, callback){
    var exists = notFsTree.exists(path);

    process.nextTick(function () {
        callback(exists);
    });

};

notFs.existsSync = function(path){
    return notFsTree.exists(path);
};

notFs.fchmod = function(fd, mode, callback){
    console.log('fchmod', arguments);
};

notFs.fchmodSync = function(fd, mode){
    console.log('fchmodSync', arguments);
};

notFs.fchown = function(fd, uid, gid, callback){
    console.log('fchown', arguments);
};

notFs.fchownSync = function(fd, uid, gid){
    console.log('fchownSync', arguments);
};

notFs.fdatasync = function(fd, callback){
    console.log('fdatasync', arguments);
};

notFs.fdatasyncSync = function(fd){
    console.log('fdatasyncSync', arguments);
};

notFs.fstat = function(fd, callback){
    console.log('fstat', arguments);
};

notFs.fstatSync = function(fd){
    console.log('fstatSync', arguments);
};

notFs.fsync = function(fd, callback){
    console.log('fsync', arguments);
};

notFs.fsyncSync = function(fd){
    console.log('fsyncSync', arguments);
};

notFs.ftruncate = function(fd, len, callback){
    console.log('ftruncate', arguments);
};

notFs.ftruncateSync = function(fd, len){
    console.log('ftruncateSync', arguments);
};

notFs.futimes = function(fd, atime, mtime, callback){
    console.log('futimes', arguments);
};

notFs.futimesSync = function(fd, atime, mtime){
    console.log('futimesSync', arguments);
};

notFs.lchmod = function(path, mode, callback){
    console.log('lchmod', arguments);
};

notFs.lchmodSync = function(path, mode){
    console.log('lchmodSync', arguments);
};

notFs.lchown = function(path, uid, gid, callback){
    console.log('lchown', arguments);
};

notFs.lchownSync = function(path, uid, gid){
    console.log('lchownSync', arguments);
};

notFs.link = function(srcpath, dstpath, callback){
    console.log('link', arguments);
};

notFs.linkSync = function(srcpath, dstpath){
    console.log('linkSync', arguments);
};

notFs.lstat = function(path, callback){
    console.log('lstat', arguments);
};

notFs.lstatSync = function(path){
    console.log('lstatSync', arguments);
};

notFs.mkdir = function(path, mode, callback){

    if(undefined === callback){
        callback = mode;
        mode = '0755';
    }

    callbackParam = null;

    if(true === notFs.hasForce('mkdir')){
        callbackParam = notFs.doForce('mkdir');
    }

    notFs.mkdirSync(path, mode);

    process.nextTick(function () {
        callback(callbackParam);
    });

};

notFs.mkdirSync = function(path, mode){

    var alreadyExists = notFsTree.exists(path);

    if(true === alreadyExists){
        throw new Error('EEXIST, file already exists \'' + path +'\'');
    }

    notFsTree.addDir(path);
};

notFs.open = function(path, flags, mode, callback){
    console.log('open', arguments);
};

notFs.openSync = function(path, flags, mode){
    console.log('openSync', arguments);
};

notFs.read = function(fd, buffer, offset, length, position, callback){
    console.log('read', arguments);
};

notFs.readdir = function(path, callback){

    var error = null;
    var files = null;

    try{
        var files = notFs.readdirSync(path);
    }
    catch(e){
        error = e;
    }

    process.nextTick(function () {
        callback(error, files);
    });

};

notFs.readdirSync = function(path){
    if(false === notFsTree.exists(path)){
        throw new Error('ENOENT: no such file or directory, scandir \''+ path + '\'');
    }

    var chilren = notFsTree.getByFqn(path).getChildren();

    var childrenNames = [];
    chilren.forEach(function(child){
        childrenNames.push(child.getName());
    });

    return childrenNames;
};

notFs.readFile = function(file, options, callback){
    var error = null;

    try{
        var content = notFs.readFileSync(file);
    }
    catch(e){
        error = e.message;
    }

    process.nextTick(function () {
        callback(error, content);
    });
};

notFs.readFileSync = function(file, options){

    if(false === notFsTree.exists(file)){
         throw new Error('Error: ENOENT, no such file or directory \'' + file+ '\'');
    }
    return notFsTree.getByFqn(file).getContent();
};

notFs.readlink = function(path, callback){
    console.log('readlink', arguments);
};

notFs.readlinkSync = function(path){
    console.log('readlinkSync', arguments);
};

notFs.realpath = function(path, cache, callback){
    console.log('realpath', arguments);
};

notFs.readSync = function(fd, buffer, offset, length, position){
    console.log('readSync', arguments);
};

notFs.realpathSync = function(path, cache){
    console.log('realpathSync', arguments);
};

notFs.rename = function(oldPath, newPath, callback){
    notFs.renameSync(oldPath, newPath);

    callbackParam = null;

    if(true === notFs.hasForce('rename')){
        callbackParam = notFs.doForce('rename');
    }

    process.nextTick(function () {
        callback(callbackParam);
    });
};

//@TODO implement a real rename by seperating items from tree
notFs.renameSync = function(oldPath, newPath){

    if(false === notFsTree.exists(oldPath)){
         throw new Error(oldPath + ' does not exists.');
    }

    var node = notFsTree.getByFqn(oldPath);

    notFsTree.remove(oldPath);

    if(true === node.isDir()){
       notFsTree.addDir(newPath);
    }
    else if(true === node.isFile()){
       notFs.writeFileSync(newPath, node.getContent, {encoding:'UTF-8'});
    }

};

notFs.rmdir = function(path, callback){
    console.log('rmdir', arguments);
};

notFs.rmdirSync = function(path){
    notFsTree.remove(path);
};

notFs.stat = function(path, callback){
    console.log('stat', arguments);
};

notFs.statSync = function(path){
    var node = notFsTree.getByFqn(path);
    return node.getStats();
};

notFs.symlink = function(target, path, type, callback){
    console.log('symlink', arguments);
};

notFs.symlinkSync = function(target, path, type){
    console.log('symlinkSync', arguments);
};

notFs.truncate = function(path, len, callback){
    console.log('truncate', arguments);
};

notFs.truncateSync = function(path, len){
    console.log('truncateSync', arguments);
};

notFs.unlink = function(path, callback){

    notFsTree.remove(path);

    callbackParam = null;

    if(true === notFs.hasForce('unlink')){
        callbackParam = notFs.doForce('unlink');
    }

    process.nextTick(function () {
        callback(callbackParam);
    });
};

notFs.unlinkSync = function(path){
    notFsTree.remove(path);
    return null;
};

notFs.unwatchFile = function(filename, listener){
    console.log('unwatchFile', arguments);
};

notFs.utimes = function(path, atime, mtime, callback){
    console.log('utimes', arguments);
};

notFs.utimesSync = function(path, atime, mtime){
    console.log('utimesSync', arguments);
};

notFs.watch = function(filename, options, listener){
    console.log('watch', arguments);
};

notFs.watchFile = function(filename, options, listener){
    console.log('watchFile', arguments);
};

/**
 * @TODO param options is optional
 * @TODO add errors to callback
 */
notFs.writeFile = function(file, data, options, callback){

    notFs.writeFileSync(file, data, options);

    callbackParam = null;

    if(true === notFs.hasForce('writeFile')){
        callbackParam = notFs.doForce('writeFile');
    }

    process.nextTick(function () {
        callback(callbackParam);
    });

};

/**
 * @TODO param options is optional
 */
notFs.writeFileSync = function(file, data, options){
    if(false === notFsTree.exists(file)){
         notFsTree.addFile(file);
    }
    notFsTree.getByFqn(file).setContent(data);

};

module.exports = notFs;

<|endoftext|>


<commit_before>var http = require('http');
var https = require('https');
var net = require('net');
var connect = require('connect');
var fs = require('fs');
var path = require('path');
var log = require('./log');
var utils = require('./utils');

var DEFAULT_PORT = 8989;
var INTERNAL_HTTPS_PORT = 0;
var app;
var httpServer;
var httpsServer;
var privateKeyFile = path.join(__dirname, '..', 'keys', 'privatekey.pem');
var certificateFile = path.join(__dirname, '..', 'keys', 'certificate.pem');

/**
 * Start up nproxy server on the specified port
 * and combine the processors defined as connect middlewares into it.
 *
 * @param {String} port the port proxy server will listen on
 * @param {Object} options options for the middlewares
 */
function nproxy(port, options){
  var nm;

  if(typeof options.timeout === 'number'){
    utils.reqTimeout = options.timeout;
    utils.resTimeout = options.timeout;
  }

  if(typeof options.debug === 'boolean'){
    log.isDebug = options.debug;
  }

  nm = require('./middlewares'); //nproxy middles

  port = typeof port === 'number' ? port : DEFAULT_PORT;

  app = connect();
  if(typeof options.responderListFilePath !== 'undefined'){
    app.use(nm.respond(options.responderListFilePath));
  }
  app.use(nm.forward());

  httpServer = http.createServer(function(req, res){
    req.type = 'http';
    app(req, res);
  }).listen(port);
  httpsServer = https.createServer({
    key: fs.readFileSync(privateKeyFile),
    cert: fs.readFileSync(certificateFile)
  }, function(req, res){
    req.type = 'https';
    app(req, res);
  });
  httpsServer.on('listening', function(){
    INTERNAL_HTTPS_PORT = httpsServer.address().port;
  });
  httpsServer = httpsServer.listen(INTERNAL_HTTPS_PORT);

  proxyHttps();

  log.info('NProxy started on ' + port + '!');

  if (options.networks) {
    log.info('Network interfaces:');
    var interfaces = require('os').networkInterfaces();
    for (var key in interfaces) {
      log.info(key);
      interfaces[key].forEach(function (item) {
        log.info('  ' + item.address + '\t' + item.family);
      });
    }
  }

  return {
    httpServer: httpServer,
    httpsServer: httpsServer
  };
}

/**
 * Listen the CONNECTION method and forward the https request to internal https server
 */
function proxyHttps(){
  httpServer.on('connect', function(req, socket, upgradeHead){
    var netClient = net.createConnection(INTERNAL_HTTPS_PORT);

    netClient.on('connect', function(){
      log.info('connect to https server successfully!');
      socket.write( "HTTP/1.1 200 Connection established\r\nProxy-agent: Netscape-Proxy/1.1\r\n\r\n");
    });

    socket.on('data', function(chunk){
      netClient.write(chunk);
    });
    socket.on('end', function(){
      netClient.end();
    });
    socket.on('close', function(){
      netClient.end();
    });
    socket.on('error', function(err){
      log.error('socket error ' + err.message);
      netClient.end();
    });

    netClient.on('data', function(chunk){
      socket.write(chunk);
    });
    netClient.on('end', function(){
      socket.end();
    });
    netClient.on('close', function(){
      socket.end();
    });
    netClient.on('error', function(err){
      log.error('netClient error ' + err.message);
      socket.end();
    });

  });
};

process.on('uncaughtException', function(err){
  log.error('uncaughtException: ' + err.message);
});

module.exports = nproxy;
<commit_msg>add `DEFAULT_TIMEOUT`<commit_after>var http = require('http');
var https = require('https');
var net = require('net');
var connect = require('connect');
var fs = require('fs');
var path = require('path');
var log = require('./log');
var utils = require('./utils');

var DEFAULT_PORT = 8989;
var INTERNAL_HTTPS_PORT = 0;
var DEFAULT_TIMEOUT = 60;
var app;
var httpServer;
var httpsServer;
var privateKeyFile = path.join(__dirname, '..', 'keys', 'privatekey.pem');
var certificateFile = path.join(__dirname, '..', 'keys', 'certificate.pem');

/**
 * Start up nproxy server on the specified port
 * and combine the processors defined as connect middlewares into it.
 *
 * @param {String} port the port proxy server will listen on
 * @param {Object} options options for the middlewares
 */
function nproxy(port, options){
  var nm;

  if(typeof options.timeout === 'number'){
    utils.reqTimeout = options.timeout || DEFAULT_TIMEOUT;
    utils.resTimeout = options.timeout || DEFAULT_TIMEOUT;
  }

  if(typeof options.debug === 'boolean'){
    log.isDebug = options.debug;
  }

  nm = require('./middlewares'); //nproxy middles

  port = typeof port === 'number' ? port : DEFAULT_PORT;

  app = connect();
  if(typeof options.responderListFilePath !== 'undefined'){
    app.use(nm.respond(options.responderListFilePath));
  }
  app.use(nm.forward());

  httpServer = http.createServer(function(req, res){
    req.type = 'http';
    app(req, res);
  }).listen(port);
  httpsServer = https.createServer({
    key: fs.readFileSync(privateKeyFile),
    cert: fs.readFileSync(certificateFile)
  }, function(req, res){
    req.type = 'https';
    app(req, res);
  });
  httpsServer.on('listening', function(){
    INTERNAL_HTTPS_PORT = httpsServer.address().port;
  });
  httpsServer = httpsServer.listen(INTERNAL_HTTPS_PORT);

  proxyHttps();

  log.info('NProxy started on ' + port + '!');

  if (options.networks) {
    log.info('Network interfaces:');
    var interfaces = require('os').networkInterfaces();
    for (var key in interfaces) {
      log.info(key);
      interfaces[key].forEach(function (item) {
        log.info('  ' + item.address + '\t' + item.family);
      });
    }
  }

  return {
    httpServer: httpServer,
    httpsServer: httpsServer
  };
}

/**
 * Listen the CONNECTION method and forward the https request to internal https server
 */
function proxyHttps(){
  httpServer.on('connect', function(req, socket, upgradeHead){
    var netClient = net.createConnection(INTERNAL_HTTPS_PORT);

    netClient.on('connect', function(){
      log.info('connect to https server successfully!');
      socket.write( "HTTP/1.1 200 Connection established\r\nProxy-agent: Netscape-Proxy/1.1\r\n\r\n");
    });

    socket.on('data', function(chunk){
      netClient.write(chunk);
    });
    socket.on('end', function(){
      netClient.end();
    });
    socket.on('close', function(){
      netClient.end();
    });
    socket.on('error', function(err){
      log.error('socket error ' + err.message);
      netClient.end();
    });

    netClient.on('data', function(chunk){
      socket.write(chunk);
    });
    netClient.on('end', function(){
      socket.end();
    });
    netClient.on('close', function(){
      socket.end();
    });
    netClient.on('error', function(err){
      log.error('netClient error ' + err.message);
      socket.end();
    });

  });
};

process.on('uncaughtException', function(err){
  log.error('uncaughtException: ' + err.message);
});

module.exports = nproxy;
<|endoftext|>


<commit_before>var util = require('util')
var OAuth2Strategy = require('passport-oauth2')
var InternalOAuthError = require('passport-oauth2').InternalOAuthError;

function Strategy(options, verify) {
  options = options || {};
  options.authorizationURL = options.authorizationURL || 'https://www.linkedin.com/oauth/v2/authorization';
  options.tokenURL = options.tokenURL || 'https://www.linkedin.com/oauth/v2/accessToken';
  options.scope = options.scope || ['r_liteprofile'];
  options.profileFields = options.profileFields || null;

  //By default we want data in JSON
  options.customHeaders = options.customHeaders || {"x-li-format":"json"};

  OAuth2Strategy.call(this, options, verify);

  this.options = options;
  this.name = 'linkedin';
  this.profileUrl = options.scope.indexOf('r_basicprofile') !== -1 ?
    basicProfileUrl : liteProfileUrl;
  this.emailUrl = 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))';
}

util.inherits(Strategy, OAuth2Strategy);

Strategy.prototype.userProfile = function(accessToken, done) {
  //LinkedIn uses a custom name for the access_token parameter
  this._oauth2.setAccessTokenName("oauth2_access_token");

  this._oauth2.get(this.profileUrl, accessToken, function (err, body, res) {
    if (err) {
      return done(new InternalOAuthError('failed to fetch user profile', err));
    }

    var profile;

    try {
      profile = parseProfile(body);
    } catch(e) {
      return done(new InternalOAuthError('failed to parse profile response', e));
    }

    if (!this.options.scope.includes('r_emailaddress')) {
      return done(null, profile);
    }

    this._oauth2.get(this.emailUrl, accessToken, function (err, body, res) {
      if (err) {
        return done(new InternalOAuthError('failed to fetch user email', err));
      }

      try {
        var email = parseEmail(body);
        Object.assign(profile, email);
      } catch(e) {
        return done(new InternalOAuthError('failed to parse email response', e));
      }

      return done(null, profile);
    }.bind(this));

  }.bind(this));
}

Strategy.prototype.authorizationParams = function(options) {
  var params = {};

  // LinkedIn requires state parameter. It will return an error if not set.
  if (options.state) {
    params['state'] = options.state;
  }

  return params;
}

function parseProfile(body) {
  var json = JSON.parse(body);

  var profile = { provider: 'linkedin' };

  profile.id = json.id;

  var firstName = json.firstName.localized[Object.keys(json.firstName.localized)[0]];
  var lastName = json.lastName.localized[Object.keys(json.lastName.localized)[0]];

  profile.name = {
    givenName: firstName,
    familyName: lastName
  };

  profile.displayName = firstName + ' ' + lastName;

  if (
    json.profilePicture &&
    json.profilePicture['displayImage~'] &&
    json.profilePicture['displayImage~'].elements &&
    json.profilePicture['displayImage~'].elements.length > 0
  ) {
    profile.photos = json.profilePicture['displayImage~'].elements.reduce(function (memo, el) {
      if (el && el.identifiers && el.identifiers.length > 0) {
        memo.push({ value: el.identifiers[0].identifier }); // Keep the first pic for now
      }
      return memo;
    }, []);
  }

  profile._raw = body;
  profile._json = json;

  return profile;
}

function parseEmail(body) {
  var profile = {};

  var json = JSON.parse(body);

  if (
    json.elements &&
    json.elements.length > 0
  ) {
    profile.emails = json.elements.reduce(function (memo, el) {
      if (el['handle~'] && el['handle~'].emailAddress) {
        memo.push({
          value: el['handle~'].emailAddress
        });
      }
      return memo;
    }, []);
  }

  profile._emailRaw = body;
  profile._emailJson = json;

  return profile;
}

var liteProfileUrl = 'https://api.linkedin.com/v2/me?projection=(' +
  'id,' +
  'firstName,' +
  'lastName,' +
  'maidenName,' +
  'profilePicture(displayImage~:playableStreams)' +
  ')';

var basicProfileUrl = 'https://api.linkedin.com/v2/me?projection=(' +
  'id,' +
  'firstName,' +
  'lastName,' +
  'maidenName,' +
  'profilePicture(displayImage~:playableStreams),' +
  'phoneticFirstName,' +
  'phoneticLastName,' +
  'headline,' +
  'location,' +
  'industryId,' +
  'summary,' +
  'positions,' +
  'vanityName,' +
  'lastModified' +
  ')';

module.exports = Strategy;
<commit_msg>Fix profile fields. Implement comments from review.<commit_after>var util = require('util')
var OAuth2Strategy = require('passport-oauth2')
var InternalOAuthError = require('passport-oauth2').InternalOAuthError;

// No need for a projection for the lite profile, all fields are returned
// by default.
var liteProfileUrl = 'https://api.linkedin.com/v2/me';

// Most of these fields are only available for members of partner programs.
var basicProfileUrl = 'https://api.linkedin.com/v2/me?projection=(' +
  'id,' +
  'firstName,' +
  'lastName,' +
  'maidenName,' +
  'profilePicture(displayImage~:playableStreams),' +
  'phoneticFirstName,' +
  'phoneticLastName,' +
  'headline,' +
  'location,' +
  'industryId,' +
  'summary,' +
  'positions,' +
  'vanityName,' +
  'lastModified' +
  ')';

function Strategy(options, verify) {
  options = options || {};
  options.authorizationURL = options.authorizationURL || 'https://www.linkedin.com/oauth/v2/authorization';
  options.tokenURL = options.tokenURL || 'https://www.linkedin.com/oauth/v2/accessToken';
  options.scope = options.scope || ['r_liteprofile'];
  options.profileFields = options.profileFields || null;

  //By default we want data in JSON
  options.customHeaders = options.customHeaders || {"x-li-format":"json"};

  OAuth2Strategy.call(this, options, verify);

  this.options = options;
  this.name = 'linkedin';
  this.profileUrl = options.scope.indexOf('r_basicprofile') !== -1 ?
    basicProfileUrl : liteProfileUrl;
  this.emailUrl = 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))';
}

util.inherits(Strategy, OAuth2Strategy);

Strategy.prototype.userProfile = function(accessToken, done) {
  //LinkedIn uses a custom name for the access_token parameter
  this._oauth2.setAccessTokenName("oauth2_access_token");

  this._oauth2.get(this.profileUrl, accessToken, function (err, body, res) {
    if (err) {
      return done(new InternalOAuthError('failed to fetch user profile', err));
    }

    var profile;

    try {
      profile = parseProfile(body);
    } catch(e) {
      return done(new InternalOAuthError('failed to parse profile response', e));
    }

    if (!this.options.scope.includes('r_emailaddress')) {
      return done(null, profile);
    }

    this._oauth2.get(this.emailUrl, accessToken, function (err, body, res) {
      if (err) {
        return done(new InternalOAuthError('failed to fetch user email', err));
      }

      try {
        addEmails(profile, body);
      } catch(e) {
        return done(new InternalOAuthError('failed to parse email response', e));
      }

      return done(null, profile);
    }.bind(this));

  }.bind(this));
}

Strategy.prototype.authorizationParams = function(options) {
  var params = {};

  // LinkedIn requires state parameter. It will return an error if not set.
  if (options.state) {
    params['state'] = options.state;
  }

  return params;
}

function getName(nameObj) {
  var locale = nameObj.preferredLocale.language + '_' + nameObj.preferredLocale.country;
  return nameObj.localized[locale];
}

function getProfilePictures(profilePictureObj) {
  // This is the format we used to return in the past.
  var result = [];

  if(!profilePictureObj) {
    // Picture is optional.
    return result;
  }

  try {
    profilePictureObj['displayImage~'].elements.forEach(function(pic) {
      // We keep only public profile pictures.
      if(pic.authorizationMethod !== 'PUBLIC') {
        return;
      }

      // This should not happen, but...
      if(pic.identifiers.length === 0) {
        return;
      }

      var url = pic.identifiers[0].identifier;

      result.push({ value: url });
    });
  } catch(e) {
    // Profile picture object changed format?
    return result;
  }

  return result;
}

function parseProfile(body) {
  var json = JSON.parse(body);

  var profile = { provider: 'linkedin' };

  profile.id = json.id;

  profile.name = {
    givenName: getName(json.firstName),
    familyName: getName(json.lastName)
  };

  profile.displayName = profile.name.givenName + ' ' + profile.name.familyName;

  profile.photos = getProfilePictures(json.profilePicture);

  profile._raw = body;
  profile._json = json;

  return profile;
}

function addEmails(profile, body) {
  var json = JSON.parse(body);

  if(json.elements && json.elements.length > 0) {
    profile.emails = json.elements.reduce(function (acc, el) {
      if (el['handle~'] && el['handle~'].emailAddress) {
        acc.push({
          value: el['handle~'].emailAddress
        });
      }
      return acc;
    }, []);
  }

  profile._emailRaw = body;
  profile._emailJson = json;
}

module.exports = Strategy;
<|endoftext|>


<commit_before>var querystring= require('querystring'),
    crypto= require('crypto'),
    request= require('request'),
    URL= require('url');

exports.OAuth2= function(clientId, clientSecret, baseSite, authorizePath, accessTokenPath, customHeaders, proxy, strictSSL) {
  this._clientId= clientId;
  this._clientSecret= clientSecret;
  this._baseSite= baseSite;
  this._authorizeUrl= authorizePath || "/oauth/authorize";
  this._accessTokenUrl= accessTokenPath || "/oauth/access_token";
  this._accessTokenName= "access_token";
  this._authMethod= "Bearer";
  this._customHeaders = customHeaders || {};
  this._useAuthorizationHeaderForGET= false;
  this._proxy = proxy;
  this._strictSSL = strictSSL;
}

// This 'hack' method is required for sites that don't use
// 'access_token' as the name of the access token (for requests).
// ( http://tools.ietf.org/html/draft-ietf-oauth-v2-16#section-7 )
// it isn't clear what the correct value should be atm, so allowing
// for specific (temporary?) override for now.
exports.OAuth2.prototype.setAccessTokenName= function ( name ) {
  this._accessTokenName= name;
}

// Sets the authorization method for Authorization header.
// e.g. Authorization: Bearer <token>  # "Bearer" is the authorization method.
exports.OAuth2.prototype.setAuthMethod = function ( authMethod ) {
  this._authMethod = authMethod;
};

// If you use the OAuth2 exposed 'get' method (and don't construct your own _request call )
// this will specify whether to use an 'Authorize' header instead of passing the access_token as a query parameter
exports.OAuth2.prototype.useAuthorizationHeaderforGET = function(useIt) {
  this._useAuthorizationHeaderForGET= useIt;
}

exports.OAuth2.prototype._getAccessTokenUrl= function() {
  return this._baseSite + this._accessTokenUrl; /* + "?" + querystring.stringify(params); */
}

// Build the authorization header. In particular, build the part after the colon.
// e.g. Authorization: Bearer <token>  # Build "Bearer <token>"
exports.OAuth2.prototype.buildAuthHeader= function(token) {
  return this._authMethod + ' ' + token;
};

exports.OAuth2.prototype._chooseHttpLibrary= function( parsedUrl ) {
  var http_library= https;
  // As this is OAUth2, we *assume* https unless told explicitly otherwise.
  if( parsedUrl.protocol != "https:" ) {
    http_library= http;
  }
  return http_library;
};

exports.OAuth2.prototype._request= function(method, url, headers, post_body, access_token, callback) {

  var parsedUrl= URL.parse( url, true );

  var realHeaders= {};
  for( var key in this._customHeaders ) {
    realHeaders[key]= this._customHeaders[key];
  }
  if( headers ) {
    for(var key in headers) {
      realHeaders[key] = headers[key];
    }
  }

  if (!realHeaders['User-Agent']) {
    realHeaders['User-Agent'] = 'Node-oauth';
  }

  realHeaders['Content-Length']= post_body ? Buffer.byteLength(post_body) : 0;
  if( access_token && !('Authorization' in realHeaders)) {
    if( ! parsedUrl.query ) parsedUrl.query= {};
    parsedUrl.query[this._accessTokenName]= access_token;
  }

  var options = {
    uri: URL.format(parsedUrl),
    method: method,
    headers: realHeaders,
    body: post_body
  };

  if (this._proxy) {
    options.proxy = this._proxy;
  }

  if (this._strictSSL) {
    options.strictSSL = this._strictSSL;
  }

  this._executeRequest( options, callback );
}

exports.OAuth2.prototype._executeRequest= function( options, callback ) {

  request(options, function ( err, response, result ) {
    if (err) {
      callback(err);
      return;
    }
    if( response.statusCode != 200 && (response.statusCode != 301) && (response.statusCode != 302) ) {
      callback({ statusCode: response.statusCode, data: result });
    } else {
      callback(null, result, response);
    }
  });
}

exports.OAuth2.prototype.getAuthorizeUrl= function( params ) {
  var params= params || {};
  params['client_id'] = this._clientId;
  return this._baseSite + this._authorizeUrl + "?" + querystring.stringify(params);
}

exports.OAuth2.prototype.getOAuthAccessToken= function(code, params, callback) {
  var params= params || {};
  params['client_id'] = this._clientId;
  params['client_secret'] = this._clientSecret;
  var codeParam = (params.grant_type === 'refresh_token') ? 'refresh_token' : 'code';
  params[codeParam]= code;

  var post_data= querystring.stringify( params );
  var post_headers= {
       'Content-Type': 'application/x-www-form-urlencoded'
   };

  this._request("POST", this._getAccessTokenUrl(), post_headers, post_data, null, function(error, data, response) {
    if( error )  callback(error);
    else {
      var results;
      try {
        // As of http://tools.ietf.org/html/draft-ietf-oauth-v2-07
        // responses should be in JSON
        results= JSON.parse( data );
      }
      catch(e) {
        // .... However both Facebook + Github currently use rev05 of the spec
        // and neither seem to specify a content-type correctly in their response headers :(
        // clients of these services will suffer a *minor* performance cost of the exception
        // being thrown
        results= querystring.parse( data );
      }
      var access_token= results["access_token"];
      var refresh_token= results["refresh_token"];
      delete results["refresh_token"];
      callback(null, access_token, refresh_token, results); // callback results =-=
    }
  });
}

// Deprecated
exports.OAuth2.prototype.getProtectedResource= function(url, access_token, callback) {
  this._request("GET", url, {}, "", access_token, callback );
}

exports.OAuth2.prototype.get= function(url, access_token, callback) {
  if( this._useAuthorizationHeaderForGET ) {
    var headers= {'Authorization': this.buildAuthHeader(access_token) }
    access_token= null;
  }
  else {
    headers= {};
  }
  this._request("GET", url, headers, "", access_token, callback );
}
<commit_msg>feature(request options): propagate rejectUnauthorized and strictSSL<commit_after>var querystring= require('querystring'),
    crypto= require('crypto'),
    request= require('request'),
    URL= require('url');

exports.OAuth2= function(clientId, clientSecret, baseSite, authorizePath, accessTokenPath, customHeaders, proxy, strictSSL, rejectUnauthorized) {
  this._clientId= clientId;
  this._clientSecret= clientSecret;
  this._baseSite= baseSite;
  this._authorizeUrl= authorizePath || "/oauth/authorize";
  this._accessTokenUrl= accessTokenPath || "/oauth/access_token";
  this._accessTokenName= "access_token";
  this._authMethod= "Bearer";
  this._customHeaders = customHeaders || {};
  this._useAuthorizationHeaderForGET= false;
  this._proxy = proxy;
  this._strictSSL = strictSSL;
  this._rejectUnauthorized = rejectUnauthorized;
}

// This 'hack' method is required for sites that don't use
// 'access_token' as the name of the access token (for requests).
// ( http://tools.ietf.org/html/draft-ietf-oauth-v2-16#section-7 )
// it isn't clear what the correct value should be atm, so allowing
// for specific (temporary?) override for now.
exports.OAuth2.prototype.setAccessTokenName= function ( name ) {
  this._accessTokenName= name;
}

// Sets the authorization method for Authorization header.
// e.g. Authorization: Bearer <token>  # "Bearer" is the authorization method.
exports.OAuth2.prototype.setAuthMethod = function ( authMethod ) {
  this._authMethod = authMethod;
};

// If you use the OAuth2 exposed 'get' method (and don't construct your own _request call )
// this will specify whether to use an 'Authorize' header instead of passing the access_token as a query parameter
exports.OAuth2.prototype.useAuthorizationHeaderforGET = function(useIt) {
  this._useAuthorizationHeaderForGET= useIt;
}

exports.OAuth2.prototype._getAccessTokenUrl= function() {
  return this._baseSite + this._accessTokenUrl; /* + "?" + querystring.stringify(params); */
}

// Build the authorization header. In particular, build the part after the colon.
// e.g. Authorization: Bearer <token>  # Build "Bearer <token>"
exports.OAuth2.prototype.buildAuthHeader= function(token) {
  return this._authMethod + ' ' + token;
};

exports.OAuth2.prototype._chooseHttpLibrary= function( parsedUrl ) {
  var http_library= https;
  // As this is OAUth2, we *assume* https unless told explicitly otherwise.
  if( parsedUrl.protocol != "https:" ) {
    http_library= http;
  }
  return http_library;
};

exports.OAuth2.prototype._request= function(method, url, headers, post_body, access_token, callback) {

  var parsedUrl= URL.parse( url, true );

  var realHeaders= {};
  for( var key in this._customHeaders ) {
    realHeaders[key]= this._customHeaders[key];
  }
  if( headers ) {
    for(var key in headers) {
      realHeaders[key] = headers[key];
    }
  }

  if (!realHeaders['User-Agent']) {
    realHeaders['User-Agent'] = 'Node-oauth';
  }

  realHeaders['Content-Length']= post_body ? Buffer.byteLength(post_body) : 0;
  if( access_token && !('Authorization' in realHeaders)) {
    if( ! parsedUrl.query ) parsedUrl.query= {};
    parsedUrl.query[this._accessTokenName]= access_token;
  }

  var options = {
    uri: URL.format(parsedUrl),
    method: method,
    headers: realHeaders,
    body: post_body
  };

  if (this._proxy) {
    options.proxy = this._proxy;
  }

  options.strictSSL = this._strictSSL;

  options.rejectUnauthorized = this._rejectUnauthorized;

  this._executeRequest( options, callback );
}

exports.OAuth2.prototype._executeRequest= function( options, callback ) {

  request(options, function ( err, response, result ) {
    if (err) {
      callback(err);
      return;
    }
    if( response.statusCode != 200 && (response.statusCode != 301) && (response.statusCode != 302) ) {
      callback({ statusCode: response.statusCode, data: result });
    } else {
      callback(null, result, response);
    }
  });
}

exports.OAuth2.prototype.getAuthorizeUrl= function( params ) {
  var params= params || {};
  params['client_id'] = this._clientId;
  return this._baseSite + this._authorizeUrl + "?" + querystring.stringify(params);
}

exports.OAuth2.prototype.getOAuthAccessToken= function(code, params, callback) {
  var params= params || {};
  params['client_id'] = this._clientId;
  params['client_secret'] = this._clientSecret;
  var codeParam = (params.grant_type === 'refresh_token') ? 'refresh_token' : 'code';
  params[codeParam]= code;

  var post_data= querystring.stringify( params );
  var post_headers= {
       'Content-Type': 'application/x-www-form-urlencoded'
   };

  this._request("POST", this._getAccessTokenUrl(), post_headers, post_data, null, function(error, data, response) {
    if( error )  callback(error);
    else {
      var results;
      try {
        // As of http://tools.ietf.org/html/draft-ietf-oauth-v2-07
        // responses should be in JSON
        results= JSON.parse( data );
      }
      catch(e) {
        // .... However both Facebook + Github currently use rev05 of the spec
        // and neither seem to specify a content-type correctly in their response headers :(
        // clients of these services will suffer a *minor* performance cost of the exception
        // being thrown
        results= querystring.parse( data );
      }
      var access_token= results["access_token"];
      var refresh_token= results["refresh_token"];
      delete results["refresh_token"];
      callback(null, access_token, refresh_token, results); // callback results =-=
    }
  });
}

// Deprecated
exports.OAuth2.prototype.getProtectedResource= function(url, access_token, callback) {
  this._request("GET", url, {}, "", access_token, callback );
}

exports.OAuth2.prototype.get= function(url, access_token, callback) {
  if( this._useAuthorizationHeaderForGET ) {
    var headers= {'Authorization': this.buildAuthHeader(access_token) }
    access_token= null;
  }
  else {
    headers= {};
  }
  this._request("GET", url, headers, "", access_token, callback );
}
<|endoftext|>


<commit_before>//Object class for Noodles
//otherwise just make sure that the browser version loads before this file.
if(typeof process !== "undefined"){
	var requirejs = require('requirejs');
	var define = requirejs.define;
}

define(function(require, exports, module){
var _String = require('./string').String,
	Utilities = require('./utilities');
/**--Noodles--
name:Object
description: Object class
@param {Noodles.Template}
@param{string}
@return {Noodles.Object}
*/
var _Object = exports.Object = function(Template, expression){
	if(expression.length === 0){
		this.skip = true;
		return;
	}
	expression = expression.trim().toLowerCase();
	this.needs = {};

	var reObjParser = /([^\[\.]+)(\.|\[)?(.+)*/,
		reQuote = /^('|")[^'"]+\1{1}$/,
		reNumber = /^\d+$/,
		order = [],
		bracket = false,
		error = false,
		needsArr = [],
		remainder = expression,
		obj,identfier,temp;

	temp = reObjParser.exec(remainder)[1];
	this.needs[temp.toLowerCase()] = true;
	do{
		obj = reObjParser.exec(remainder);
		identifier = obj[1];
		remainder = obj[3];

		if(bracket){
			if(identifier.slice(-1) !== "]"){
				error = true;
				break;
			}
			identifier = identifier.slice(0,-1);
			if(reQuote.test(identifier)){
				identifier = identifier.slice(1,-1)
			}
			else if(reIdentifier.test(identifier)){
				temp = new _Object(identifier);
				this.needs = Utilities.mergeObjectWith(this.needs,temp.needs);
				order.push(temp.trim());
				continue;
			}
			else if(reNumber.test(identifier)){
				order.push(parseInt(identifier,10));
				continue;
			}
			else{
				error = true;
				break;
			}
		}

		if(bracket || reIdentifier.test(identifier)){
			order.push(identifier.trim());
		}
		else{
			error = true;
			break;
		}
		bracket = obj[2] === "[";
	} while(remainder)

	if(error === true){
		Utilities.warning(Template,'Invalid object syntax');
		this._skip = true;
		return;
	}

	this.order = order;
	this.olength = order.length;
	this.meta = false;

	if(this.olength === 1 && typeof order[0] === "string" && typeof Template._metaData !== "undefined" && typeof Template._metaData[order[0]] !== "undefined"){
		this.meta = true;
		this.metaKey = order[0];
		this.needs = Utilities.mergeObjectWith({},Template._metaData[order[0]].needs);
	}

	temp = Utilities.stringOnly(this.order);

	if(temp.stringOnly){
		this._stringOnly = true;
		this.meta = false;
		this.order = [new _String(temp.string)];
		this.olength = 1
		this.needs = {};
	}
};
/**--module--
name:reIdentifier
description: regular expression to determine Identifier worthiness
@type{RegExp}
*/
var reIdentifier = _Object.reIdentifier = /[^\d\.\['"\s]{1}.*/;
/**--Noodles.Object--
name:execute/get
description: executes the object sequence to return it's value
@param{Noodle.Template}
@param{Noodles.Context}
@return {*}
*/
_Object.prototype.execute = function(Template,Context,override){
	if(!this._stringOnly){
		try{
			return Context.getObject(Template,this.order,override);
		}
		catch(e){
			if(Context.debugMode) Context.error(Template, 'Was unable to get object ' + this.modifies().join('.'));
			return '';
		}
	}
	else{
		return this.order[0].execute(Template,Context);
	}
};
/**--Noodles.Object--
name:set
description: sets the value of an object in a particular context
@param{Noodles.Template}
@param{Noodles.Context}
@param {*}
*/
_Object.prototype.set = function(Template,Context,value){
	if(!this.meta){
		try{
			value = typeof value.execute !== "undefined" ? value.execute(Template,Context) : value;
			Context.setObject(Template,this.order,value);
		}
		catch(e){
			if(Context.debugMode) Context.error(Template, 'Was unable to set object ' + this.modifies().join('.'));
		}
	}
	else {
		if(Context.debugMode) Context.error(Template,'Meta Data variable cannot be set at run time');
	}
	return '';
};
/**--Noodles.Object--
name:delete
description: deletes an object in a particular context
@param{Noodles.Template}
@param{Noodles.Context}
@param {*}
*/
_Object.prototype.delete = function(Template,Context){
	if(!this.meta){
		try{
			Context.deleteObject(Template,this.order);
		}
		catch(e){
			if(Context.debugMode) Context.error(Template, 'Was unable to delete object ' + this.modifies().join('.'));
		}
	}
	else {
		if(Context.debugMode) Context.error(Template,'Meta Data variable cannot be deleted at run time');
	}
	return '';
};
/**--Noodles.Object--
name:modifies
description: returns a string that says to the best of the objects,
	ability what it modifies in context, this usually means until
	it rungs into an object within itself.
@return {string}
*/
_Object.prototype.modifies = function(){
	if(typeof this._modifies !== "undefined") return this._modifies;
	var order = this.order,
		i = 0,
		l = order.length,
		arr = [];
	while(i < l){
		if(typeof order[i] === "string" || typeof order[i] === "number"){
			arr.push(order[i]);
		}
		else{
			break;
		}
		i++;
	}
	this._modifies = arr;
	return this._modifies
};
/**--Noodles.Object--
name:type
description: descripes the type of object
@type{string}
*/
_Object.prototype.type = "object";
});<commit_msg>fixed object in object bug<commit_after>//Object class for Noodles
//otherwise just make sure that the browser version loads before this file.
if(typeof process !== "undefined"){
	var requirejs = require('requirejs');
	var define = requirejs.define;
}

define(function(require, exports, module){
var _String = require('./string').String,
	Utilities = require('./utilities');
/**--Noodles--
name:Object
description: Object class
@param {Noodles.Template}
@param{string}
@return {Noodles.Object}
*/
var _Object = exports.Object = function(Template, expression){
	if(expression.length === 0){
		this.skip = true;
		return;
	}
	expression = expression.trim().toLowerCase();
	this.needs = {};

	var reObjParser = /([^\[\.]+)(\.|\[)?(.+)*/,
		reQuote = /^('|")[^'"]+\1{1}$/,
		reNumber = /^\d+$/,
		order = [],
		bracket = false,
		error = false,
		needsArr = [],
		remainder = expression,
		obj,identfier,temp;

	temp = reObjParser.exec(remainder)[1];
	this.needs[temp.toLowerCase()] = true;
	do{
		obj = reObjParser.exec(remainder);
		identifier = obj[1];
		remainder = obj[3];

		if(bracket){
			if(identifier.slice(-1) !== "]"){
				error = true;
				break;
			}
			identifier = identifier.slice(0,-1);
			if(reQuote.test(identifier)){
				identifier = identifier.slice(1,-1)
			}
			else if(reIdentifier.test(identifier)){
				temp = new _Object(Template,identifier);
				this.needs = Utilities.mergeObjectWith(this.needs,temp.needs);
				order.push(temp);
				continue;
			}
			else if(reNumber.test(identifier)){
				order.push(parseInt(identifier,10));
				continue;
			}
			else{
				error = true;
				break;
			}
		}

		if(bracket || reIdentifier.test(identifier)){
			order.push(identifier.trim());
		}
		else{
			error = true;
			break;
		}
		bracket = obj[2] === "[";
	} while(remainder)

	if(error === true){
		Utilities.warning(Template,'Invalid object syntax');
		this._skip = true;
		return;
	}

	this.order = order;
	this.olength = order.length;
	this.meta = false;

	if(this.olength === 1 && typeof order[0] === "string" && typeof Template._metaData !== "undefined" && typeof Template._metaData[order[0]] !== "undefined"){
		this.meta = true;
		this.metaKey = order[0];
		this.needs = Utilities.mergeObjectWith({},Template._metaData[order[0]].needs);
	}

	temp = Utilities.stringOnly(this.order);

	if(temp.stringOnly){
		this._stringOnly = true;
		this.meta = false;
		this.order = [new _String(temp.string)];
		this.olength = 1
		this.needs = {};
	}
};
/**--module--
name:reIdentifier
description: regular expression to determine Identifier worthiness
@type{RegExp}
*/
var reIdentifier = _Object.reIdentifier = /[^\d\.\['"\s]{1}.*/;
/**--Noodles.Object--
name:execute/get
description: executes the object sequence to return it's value
@param{Noodle.Template}
@param{Noodles.Context}
@return {*}
*/
_Object.prototype.execute = function(Template,Context,override){
	if(!this._stringOnly){
		try{
			return Context.getObject(Template,this.order,override);
		}
		catch(e){
			if(Context.debugMode) Context.error(Template, 'Was unable to get object ' + this.modifies().join('.'));
			return '';
		}
	}
	else{
		return this.order[0].execute(Template,Context);
	}
};
/**--Noodles.Object--
name:set
description: sets the value of an object in a particular context
@param{Noodles.Template}
@param{Noodles.Context}
@param {*}
*/
_Object.prototype.set = function(Template,Context,value){
	if(!this.meta){
		try{
			value = typeof value.execute !== "undefined" ? value.execute(Template,Context) : value;
			Context.setObject(Template,this.order,value);
		}
		catch(e){
			if(Context.debugMode) Context.error(Template, 'Was unable to set object ' + this.modifies().join('.'));
		}
	}
	else {
		if(Context.debugMode) Context.error(Template,'Meta Data variable cannot be set at run time');
	}
	return '';
};
/**--Noodles.Object--
name:delete
description: deletes an object in a particular context
@param{Noodles.Template}
@param{Noodles.Context}
@param {*}
*/
_Object.prototype.delete = function(Template,Context){
	if(!this.meta){
		try{
			Context.deleteObject(Template,this.order);
		}
		catch(e){
			if(Context.debugMode) Context.error(Template, 'Was unable to delete object ' + this.modifies().join('.'));
		}
	}
	else {
		if(Context.debugMode) Context.error(Template,'Meta Data variable cannot be deleted at run time');
	}
	return '';
};
/**--Noodles.Object--
name:modifies
description: returns a string that says to the best of the objects,
	ability what it modifies in context, this usually means until
	it rungs into an object within itself.
@return {string}
*/
_Object.prototype.modifies = function(){
	if(typeof this._modifies !== "undefined") return this._modifies;
	var order = this.order,
		i = 0,
		l = order.length,
		arr = [];
	while(i < l){
		if(typeof order[i] === "string" || typeof order[i] === "number"){
			arr.push(order[i]);
		}
		else{
			break;
		}
		i++;
	}
	this._modifies = arr;
	return this._modifies
};
/**--Noodles.Object--
name:type
description: descripes the type of object
@type{string}
*/
_Object.prototype.type = "object";
});<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var util = require('util');
var colors = require('colors');
var debuglog = require('debuglog');
var _ = require('lodash');
var map = require('./map');
var pkg = require('../package.json');

/**
 * Creates a new parser
 * @constructor
 */
var Parser = function(options) {
    var defaults = {
        // Provides a list of supported languages by setting the lngs option.
        lngs: ['en'],

        // Sorts the keys in ascending order.
        sort: false,

        // Provides a default value if a value is not specified.
        defaultValue: '',

        // The resGetPath is the source i18n path, it is relative to current working directory.
        resGetPath: 'i18n/__lng__/__ns__.json',

        // The resGetPath is the target i18n path, it is relative to your gulp.dest path.
        resSetPath: 'i18n/__lng__/__ns__.json',

        // Changes namespace and/or key separator by setting nsseparator and/or keyseparator options.
        nsseparator: ':',
        keyseparator: '.',

        // Changes pre-/suffix for variables by setting interpolationPrefix and interpolationSuffix options.
        interpolationPrefix: '__',
        interpolationSuffix: '__',

        ns: {
            // Provides a list of namespaces by setting the namespaces option.
            namespaces: [],
            // Changes the default namespace by setting the ns.defaultNs option.
            defaultNs: 'translation'
        }
    };
    var resStore;

    this.options = _.clone(options);
    this.resStore = resStore = {};

    _.defaults(this.options, defaults);

    options = this.options;

    if ( ! _.isArray(options.ns.namespaces)) {
        options.ns.namespaces = [];
    }
    console.assert(_.isArray(options.ns.namespaces), 'The ns.namespaces option should be an array of strings');

    options.ns.namespaces = _.chain(options.ns.namespaces.concat([options.ns.defaultNs]))
        .flatten()
        .union()
        .value();

    _.each(options.lngs, function(lng) {
        resStore[lng] = resStore[lng] || {};
        _.each(options.ns.namespaces, function(ns) {
            var regex = {
                'lng': new RegExp(_.escapeRegExp(options.interpolationPrefix + 'lng' + options.interpolationSuffix), 'g'),
                'ns': new RegExp(_.escapeRegExp(options.interpolationPrefix + 'ns' + options.interpolationSuffix), 'g')
            };
            var resPath = options.resGetPath
                .replace(regex.lng, lng)
                .replace(regex.ns, ns);

            resStore[lng][ns] = {};

            try {
                var stat = fs.statSync(resPath);
                if (stat.isFile()) {
                    resStore[lng][ns] = JSON.parse(fs.readFileSync(resPath, 'utf-8'));
                }
            }
            catch (err) {
                debuglog('Unable to load ' + JSON.stringify(resPath));
            }
        });
    });

    debuglog(JSON.stringify({
        options: this.options,
        resStore: this.resStore
    }));
};

/**
 * Parses translation keys from `data-i18n` attribute in HTML
 * @param {string} attrs A semicolon-separated list of attributes
 */
Parser.prototype.parseAttrs = function(attrs) {
    var _self = this;

    var keys = [];
    if (attrs.indexOf(';') <= attrs.length-1) {
        keys = attrs.split(';');
    } else {
        keys = [ attrs ];
    }

    _.each(keys, function(key) {
        var attr = 'text';

        key = _.trim(key);

        if (key.length === 0) {
            return;
        }

        if (key.indexOf('[') === 0) {
            var parts = key.split(']');
            key = parts[1];
            attr = parts[0].substr(1, parts[0].length-1);
        }

        if (key.indexOf(';') === key.length-1) {
            key = key.substr(0, key.length-2);
        }

        _self.parseKey(key);
    });
};

/**
 * Parses a key string and stores the key-value pairs to i18n resource store
 * @param {string} key The translation key
 * @param {string} [defaultValue] The key's value
 */
Parser.prototype.parseKey = function(key, defaultValue) {
    var options = this.options;
    var resStore = this.resStore;

    var ns = _.isString(options.ns) ? options.ns : options.ns.defaultNs;
    console.assert(_.isString(ns) && !!ns.length, 'ns is not a valid string', ns);

    if (key.indexOf(options.nsseparator) > -1) {
        var parts = key.split(options.nsseparator);
        ns = parts[0];
        key = parts[1];
    }

    var keys = key.split(options.keyseparator);
    _.each(options.lngs, function(lng) {
        var lookupKey;
        var value = resStore[lng] && resStore[lng][ns];
        var x = 0;
        while (keys[x]) {
            value = value && value[keys[x]];
            x++;
        }

        if ( ! _.isUndefined(value)) {
            // Reuse the key existed in the resStore
            lookupKey = '[' + lng + '][' + ns + '][' + keys.join('][') + ']';
            debuglog('[v] resStore' + lookupKey + '="' + map(resStore, lookupKey) + '"');
        } else if (_.isObject(resStore[lng][ns])) {
            var res = resStore[lng][ns];
            _.each(keys, function(elem, index) {
                if (index >= (keys.length - 1)) {
                    res[elem] = _.isUndefined(defaultValue) ? options.defaultValue : defaultValue;
                } else {
                    res[elem] = res[elem] || {};
                    res = res[elem];
                }
            });

            // Add new key to the resStore
            lookupKey = '[' + lng + '][' + ns + '][' + keys.join('][') + ']';
            debuglog('[+] resStore' + lookupKey + '="' + map(resStore, lookupKey) + '"');
        } else { // skip the namespace that is not defined in the i18next options
            var msg = 'Please ensure the namespace "' + ns + '" exists in the ns.namespaces[] of your ' + pkg.name + ' options: ' + JSON.stringify({
                ns: ns,
                key: key,
                defaultValue: defaultValue
            });
            console.error(msg.red);
        }
    });
};

/**
 * Parses a value string and stores the key-value pairs to i18n resource store
 * @param {string} value The key's value
 * @param {string} defaultKey The translation key
 */
Parser.prototype.parseValue = function(value, defaultKey) {
    var options = this.options;
    var resStore = this.resStore;

    var ns = _.isString(options.ns) ? options.ns : options.ns.defaultNs;
    console.assert(_.isString(ns) && !!ns.length, 'ns is not a valid string', ns);

    var key = defaultKey;
    console.assert(_.isString(key) && !!key.length, 'defaultKey is not a valid string', key);

    _.each(options.lngs, function(lng) {
        var lookupKey = '[' + lng + '][' + ns + '][' + key + ']';

        // Verify existing value
        var _value = map(resStore, lng + '.' + ns + '.' + key);
        if (_.isUndefined(_value)) {
            map(resStore, lng + '.' + ns + '.' + key, value);
            debuglog('[+] resStore' + lookupKey + '="' + map(resStore, lookupKey) + '"');
        } else if (_value === value) {
            debuglog('[v] resStore' + lookupKey + '="' + map(resStore, lookupKey) + '"');
        } else {
            console.error('[x] Key conflict in ' + lookupKey + '="' + _value + '"\n' + 'sha1' + '("' + value + '")=' + key);
        }
    });
};

/**
 * Parses hash arguments
 * @see [Regular expression for parsing name value pairs]{@link http://stackoverflow.com/questions/168171/regular-expression-for-parsing-name-value-pairs}
 * @example
Example usage:

 * // it will output ["id=nav-bar", "class = "top"", "foo = "bar\"baz""]
 * var str = ' id=nav-bar class = "top" foo = "bar\\"baz" ';
 * str.match(/([^=,\s]*)\s*=\s*((?:"(?:\\.|[^"\\]+)*"|'(?:\\.|[^'\\]+)*')|[^'"\s]*)/igm) || [];
 * @param [string] hashArguments A string representation of hash arguments
 */
Parser.prototype.parseHashArguments = function(hashArguments) {
    var hash = {};
    var params = hashArguments.match(/([^=,\s]*)\s*=\s*((?:"(?:\\.|[^"\\]+)*"|'(?:\\.|[^'\\]+)*')|[^'"\s]*)/igm) || [];
    var unquote = function(str, quoteChar) {
        quoteChar = quoteChar || '"';
        if (str[0] === quoteChar && str[str.length - 1] === quoteChar) {
            return str.slice(1, str.length - 1);
        }
        return str;
    };

    _.each(params, function(param) {
        param = _.trim(param);
        var r = param.match(/([^=,\s]*)\s*=\s*((?:"(?:\\.|[^"\\]+)*"|'(?:\\.|[^'\\]+)*')|[^'"\s]*)/) || [];

        if (r.length < 3 || _.isUndefined(r[1]) || _.isUndefined(r[2])) {
            return;
        }

        var key = _.trim(r[1]);
        var value = (function(value) { // value is enclosed with either single quote (') or double quote (") characters
            value = _.trim(value);

            var quoteChars = '\'"';
            var quoteChar = _.find(quoteChars, function(quoteChar) {
                return value.charAt(0) === quoteChar;
            });

            if (quoteChar) { // single quote (') or double quote (")
                value = unquote(value, quoteChar);
            }

            return value;
        }(r[2]));

        hash[key] = value;
    });
    return hash;
};

/**
 * Returns a JSON string containing translation information
 * @param {object} [opts] The options object
 * @param {boolean} [opts.sort] True to sort object by key
 * @param {function|string[]|number[]} [opts.replacer] The same as the JSON.stringify()
 * @param {string|number} [opts.space] The same as the JSON.stringify() method
 * @return {string}
 */
Parser.prototype.toJSON = function(opts) {
    opts = opts || {};
    return JSON.stringify(this.toObject(opts), opts.replacer, opts.space);
};

/**
 * Returns an Object containing translation information
 * @param {object} [opts] The options object
 * @param {boolean} [opts.sort] True to sort object by key
 * @return {object}
 */
Parser.prototype.toObject = function(opts) {
    opts = opts || {};
    opts.sort = !!opts.sort;

    var resStore = _.clone(this.resStore);

    if (opts.sort) {
        _.each(resStore, function(namespaces, lng) {
            _.each(namespaces, function(obj, ns) {
                // Sorted by key
                resStore[lng][ns] = _.chain(obj)
                    .pairs()
                    .sortBy(function(pair) { var key = pair[0]; return key; })
                    .reduce(function(memo, pair) { var key = pair[0], value = pair[1]; memo[key] = value; return memo; }, {})
                    .value();
            });
        });
    }

    return resStore;
};

module.exports = function(options) {
    return new Parser(options);
};
<commit_msg>Bug fixes<commit_after>var fs = require('fs');
var path = require('path');
var util = require('util');
var colors = require('colors');
var debuglog = require('debuglog');
var _ = require('lodash');
var map = require('./map');
var pkg = require('../package.json');

/**
 * Creates a new parser
 * @constructor
 */
var Parser = function(options) {
    var defaults = {
        // Provides a list of supported languages by setting the lngs option.
        lngs: ['en'],

        // Sorts the keys in ascending order.
        sort: false,

        // Provides a default value if a value is not specified.
        defaultValue: '',

        // The resGetPath is the source i18n path, it is relative to current working directory.
        resGetPath: 'i18n/__lng__/__ns__.json',

        // The resSetPath is the target i18n path, it is relative to your gulp.dest path.
        resSetPath: 'i18n/__lng__/__ns__.json',

        // Changes namespace and/or key separator by setting nsseparator and/or keyseparator options.
        nsseparator: ':',
        keyseparator: '.',

        // Changes pre-/suffix for variables by setting interpolationPrefix and interpolationSuffix options.
        interpolationPrefix: '__',
        interpolationSuffix: '__',

        ns: {
            // Provides a list of namespaces by setting the namespaces option.
            namespaces: [],
            // Changes the default namespace by setting the ns.defaultNs option.
            defaultNs: 'translation'
        }
    };
    var resStore;

    this.options = _.clone(options);
    this.resStore = resStore = {};

    _.defaults(this.options, defaults);

    options = this.options;

    if (_.isString(options.ns)) {
        options.ns = {
            namespaces: [],
            defaultNs: options.ns
        };
    }

    if ( ! _.isArray(options.ns.namespaces)) {
        options.ns.namespaces = [];
    }
    console.assert(_.isArray(options.ns.namespaces), 'The ns.namespaces option should be an array of strings');

    options.ns.namespaces = _.chain(options.ns.namespaces.concat([options.ns.defaultNs]))
        .flatten()
        .union()
        .value();

    _.each(options.lngs, function(lng) {
        resStore[lng] = resStore[lng] || {};
        _.each(options.ns.namespaces, function(ns) {
            var regex = {
                'lng': new RegExp(_.escapeRegExp(options.interpolationPrefix + 'lng' + options.interpolationSuffix), 'g'),
                'ns': new RegExp(_.escapeRegExp(options.interpolationPrefix + 'ns' + options.interpolationSuffix), 'g')
            };
            var resPath = options.resGetPath
                .replace(regex.lng, lng)
                .replace(regex.ns, ns);

            resStore[lng][ns] = {};

            try {
                var stat = fs.statSync(resPath);
                if (stat.isFile()) {
                    resStore[lng][ns] = JSON.parse(fs.readFileSync(resPath, 'utf-8'));
                }
            }
            catch (err) {
                debuglog('Unable to load ' + JSON.stringify(resPath));
            }
        });
    });

    debuglog(JSON.stringify({
        options: this.options,
        resStore: this.resStore
    }));
};

/**
 * Parses translation keys from `data-i18n` attribute in HTML
 * @param {string} attrs A semicolon-separated list of attributes
 */
Parser.prototype.parseAttrs = function(attrs) {
    var _self = this;

    var keys = [];
    if (attrs.indexOf(';') <= attrs.length-1) {
        keys = attrs.split(';');
    } else {
        keys = [ attrs ];
    }

    _.each(keys, function(key) {
        var attr = 'text';

        key = _.trim(key);

        if (key.length === 0) {
            return;
        }

        if (key.indexOf('[') === 0) {
            var parts = key.split(']');
            key = parts[1];
            attr = parts[0].substr(1, parts[0].length-1);
        }

        if (key.indexOf(';') === key.length-1) {
            key = key.substr(0, key.length-2);
        }

        _self.parseKey(key);
    });
};

/**
 * Parses a key string and stores the key-value pairs to i18n resource store
 * @param {string} key The translation key
 * @param {string} [defaultValue] The key's value
 */
Parser.prototype.parseKey = function(key, defaultValue) {
    var options = this.options;
    var resStore = this.resStore;

    var ns = _.isString(options.ns) ? options.ns : options.ns.defaultNs;
    console.assert(_.isString(ns) && !!ns.length, 'ns is not a valid string', ns);

    if (key.indexOf(options.nsseparator) > -1) {
        var parts = key.split(options.nsseparator);
        ns = parts[0];
        key = parts[1];
    }

    var keys = key.split(options.keyseparator);
    _.each(options.lngs, function(lng) {
        var lookupKey;
        var value = resStore[lng] && resStore[lng][ns];
        var x = 0;
        while (keys[x]) {
            value = value && value[keys[x]];
            x++;
        }

        if ( ! _.isUndefined(value)) {
            // Reuse the key existed in the resStore
            lookupKey = '[' + lng + '][' + ns + '][' + keys.join('][') + ']';
            debuglog('[v] resStore' + lookupKey + '="' + map(resStore, lookupKey) + '"');
        } else if (_.isObject(resStore[lng][ns])) {
            var res = resStore[lng][ns];
            _.each(keys, function(elem, index) {
                if (index >= (keys.length - 1)) {
                    res[elem] = _.isUndefined(defaultValue) ? options.defaultValue : defaultValue;
                } else {
                    res[elem] = res[elem] || {};
                    res = res[elem];
                }
            });

            // Add new key to the resStore
            lookupKey = '[' + lng + '][' + ns + '][' + keys.join('][') + ']';
            debuglog('[+] resStore' + lookupKey + '="' + map(resStore, lookupKey) + '"');
        } else { // skip the namespace that is not defined in the i18next options
            var msg = 'Please ensure the namespace "' + ns + '" exists in the ns.namespaces[] of your ' + pkg.name + ' options: ' + JSON.stringify({
                ns: ns,
                key: key,
                defaultValue: defaultValue
            });
            console.error(msg.red);
        }
    });
};

/**
 * Parses a value string and stores the key-value pairs to i18n resource store
 * @param {string} value The key's value
 * @param {string} defaultKey The translation key
 */
Parser.prototype.parseValue = function(value, defaultKey) {
    var options = this.options;
    var resStore = this.resStore;

    var ns = _.isString(options.ns) ? options.ns : options.ns.defaultNs;
    console.assert(_.isString(ns) && !!ns.length, 'ns is not a valid string', ns);

    var key = defaultKey;
    console.assert(_.isString(key) && !!key.length, 'defaultKey is not a valid string', key);

    _.each(options.lngs, function(lng) {
        var lookupKey = '[' + lng + '][' + ns + '][' + key + ']';

        // Verify existing value
        var _value = map(resStore, lng + '.' + ns + '.' + key);
        if (_.isUndefined(_value)) {
            map(resStore, lng + '.' + ns + '.' + key, value);
            debuglog('[+] resStore' + lookupKey + '="' + map(resStore, lookupKey) + '"');
        } else if (_value === value) {
            debuglog('[v] resStore' + lookupKey + '="' + map(resStore, lookupKey) + '"');
        } else {
            console.error('[x] Key conflict in ' + lookupKey + '="' + _value + '"\n' + 'sha1' + '("' + value + '")=' + key);
        }
    });
};

/**
 * Parses hash arguments
 * @see [Regular expression for parsing name value pairs]{@link http://stackoverflow.com/questions/168171/regular-expression-for-parsing-name-value-pairs}
 * @example
Example usage:

 * // it will output ["id=nav-bar", "class = "top"", "foo = "bar\"baz""]
 * var str = ' id=nav-bar class = "top" foo = "bar\\"baz" ';
 * str.match(/([^=,\s]*)\s*=\s*((?:"(?:\\.|[^"\\]+)*"|'(?:\\.|[^'\\]+)*')|[^'"\s]*)/igm) || [];
 * @param [string] hashArguments A string representation of hash arguments
 */
Parser.prototype.parseHashArguments = function(hashArguments) {
    var hash = {};
    var params = hashArguments.match(/([^=,\s]*)\s*=\s*((?:"(?:\\.|[^"\\]+)*"|'(?:\\.|[^'\\]+)*')|[^'"\s]*)/igm) || [];
    var unquote = function(str, quoteChar) {
        quoteChar = quoteChar || '"';
        if (str[0] === quoteChar && str[str.length - 1] === quoteChar) {
            return str.slice(1, str.length - 1);
        }
        return str;
    };

    _.each(params, function(param) {
        param = _.trim(param);
        var r = param.match(/([^=,\s]*)\s*=\s*((?:"(?:\\.|[^"\\]+)*"|'(?:\\.|[^'\\]+)*')|[^'"\s]*)/) || [];

        if (r.length < 3 || _.isUndefined(r[1]) || _.isUndefined(r[2])) {
            return;
        }

        var key = _.trim(r[1]);
        var value = (function(value) { // value is enclosed with either single quote (') or double quote (") characters
            value = _.trim(value);

            var quoteChars = '\'"';
            var quoteChar = _.find(quoteChars, function(quoteChar) {
                return value.charAt(0) === quoteChar;
            });

            if (quoteChar) { // single quote (') or double quote (")
                value = unquote(value, quoteChar);
            }

            return value;
        }(r[2]));

        hash[key] = value;
    });
    return hash;
};

/**
 * Returns a JSON string containing translation information
 * @param {object} [opts] The options object
 * @param {boolean} [opts.sort] True to sort object by key
 * @param {function|string[]|number[]} [opts.replacer] The same as the JSON.stringify()
 * @param {string|number} [opts.space] The same as the JSON.stringify() method
 * @return {string}
 */
Parser.prototype.toJSON = function(opts) {
    opts = opts || {};
    return JSON.stringify(this.toObject(opts), opts.replacer, opts.space);
};

/**
 * Returns an Object containing translation information
 * @param {object} [opts] The options object
 * @param {boolean} [opts.sort] True to sort object by key
 * @return {object}
 */
Parser.prototype.toObject = function(opts) {
    opts = opts || {};
    opts.sort = !!opts.sort;

    var resStore = _.clone(this.resStore);

    if (opts.sort) {
        _.each(resStore, function(namespaces, lng) {
            _.each(namespaces, function(obj, ns) {
                // Sorted by key
                resStore[lng][ns] = _.chain(obj)
                    .pairs()
                    .sortBy(function(pair) { var key = pair[0]; return key; })
                    .reduce(function(memo, pair) { var key = pair[0], value = pair[1]; memo[key] = value; return memo; }, {})
                    .value();
            });
        });
    }

    return resStore;
};

module.exports = function(options) {
    return new Parser(options);
};
<|endoftext|>


<commit_before>const exec = require('child_process').execSync

const portmap = {
  http: 80,
  https: 443,
  ssh: 22,
  dns: 53,
  ftp: 20,
  telnet: 23,
  smtp: 25,
  ntp: 37,
  pop2: 109,
  pop3: 110,
  sftp: 115,
  nntp: 119,
  snmp: 169,
  bgp: 179,
  gacp: 190,
  irc: 194,
  dls: 197,
  ldap: 389,
  snpp: 444,
  sldap: 689
}

let cr = '\n'

class Parser {
  static windows (port) {
    let results = {}
    let stdout

    cr = '\r' + cr

    try {
      stdout = exec('netstat -aon | findstr :' + port + ' | findstr LISTENING').toString().trim().split(cr)
    } catch (e) {
      stdout = []
    }

    stdout.forEach((row) => {
      let item = row.trim().split(/\s{1,500}/)
      let processport = item[1].split(':').pop()

      if (!isNaN(processport)) {
        processport = parseInt(processport, 10)

        if (processport === parseInt(port, 10)) {
          results[item.pop()] = {}
        }
      }
    })

    Object.keys(results).forEach((pid) => {
      let out = exec('tasklist /FI \"PID eq ' + pid + '\" /FO CSV /NH /V').toString().trim().split(cr)
      out.forEach((row) => {
        let col = row.split(',')

        results[pid] = {
          process: col[0].substr(1, col[0].length - 2),
          user: col[6].substr(1, col[6].length - 2)
        }
      })
    })

    return results
  }

  static linux (port) {
    // Attempt lsof first
    try {
      return this.ss(port)
    } catch (e) {
      console.log(e)
      // Attempt ss next
      try {
        return this.lsof(port)
      } catch (e) {
        // Attempt netstat last
        try {
          return this.netstat(port)
        } catch (e) {
          console.log('Could not find lsof, ss, or netstat to determine port usage.')
          return {}
        }
      }
    }
  }

  static lsof (port) {
    let stdout = exec('lsof -i :' + port).toString().trim().split('\n')
    let results = {}

    if (stdout.length === 0) {
      return {}
    }

    stdout.shift()

    stdout.forEach(row => {
      if (row.indexOf('(LISTEN)') > 0) {
        let item = row.split(/\s{1,500}/)

        item.pop()

        let processport = item.pop().replace(/[^0-9]/gi, '')

        if (!isNaN(processport)) {
          processport = parseInt(processport, 10)

          let detail = this.linuxProcessDetails(item[1])

          results[item[1]] = {
            process: processport === parseInt(port, 10) ? detail.title : item[0],
            user: detail.user
          }
        }
      }
    })

    return results
  }

  static ss (port = '') {
console.log('>>>', port)
    let stdout = exec('ss -ptls | grep LISTEN').toString().trim().split('\n')
    let results = {}

    if (stdout.length === 0) {
      return {}
    }

    port = port.toString().split(' ').filter(number => !isNaN(number))
console.log(port)
    stdout.forEach(row => {
      // Group 1 is port
      let data = /:{1,3}([A-Za-z0-9]+)/i.exec(row)
console.log(row, data)
      // Handle named ports
      if (data !== null) {
        if (isNaN(data[1]) && portmap.hasOwnProperty(data[1].toLowerCase())) {
          data[1] = portmap[data[1].toLowerCase()].toString()
        }
      }

      if (port.indexOf(data[1].toString()) >= 0) {
        let ct = 0
        let PID = /\(\"([A-Za-z]+)\".*\,[pid=]{0,4}([0-9]+)\,/i.exec(data.input)

        while (PID !== null && ct < 100) {
          let detail = this.linuxProcessDetails(PID[2])

          results[PID[2]] = {
            process: detail.title,
            user: detail.user
          }

          data.input = data.input.replace(`pid=${PID[2]}`)
          PID = /\(\"([A-Za-z]+)\".*pid=([0-9]+)/i.exec(data.input)
          ct++
        }
      }
    })

    return results
  }

  static netstat (port) {
    let stdout = exec('netstat -tulnp | grep ' + port)
    let results = {}

    if (stdout.length === 0) {
      return {}
    }

    stdout.split('\n').forEach(row => {
      let data = row.split(/\s+/).pop().split(/\/|\\/)
      let detail = this.linuxProcessDetails(data[0])

      results[data[0]] = {
        process: detail.title,
        user: detail.user
      }
    })

    return results
  }

  static linuxProcessDetails (pid) {
console.log(exec('ps axco pid,command | grep ' + pid))
    let processDetail = exec('ps axco pid,command | grep ' + pid)
      .toString()
      .split('\n')
      .filter(line => line.indexOf('grep') < 0)[0]
      .trim()
      .split(/\s+/)

    let user = processDetail[1]
console.log(processDetail)
    processDetail.splice(0, process.platform === 'darwin' ? 1 : 3)

    return {
      user,
      title: processDetail.join(' ')
    }
  }
}

module.exports = Parser
<commit_msg>Linux testing<commit_after>const exec = require('child_process').execSync

const portmap = {
  http: 80,
  https: 443,
  ssh: 22,
  dns: 53,
  ftp: 20,
  telnet: 23,
  smtp: 25,
  ntp: 37,
  pop2: 109,
  pop3: 110,
  sftp: 115,
  nntp: 119,
  snmp: 169,
  bgp: 179,
  gacp: 190,
  irc: 194,
  dls: 197,
  ldap: 389,
  snpp: 444,
  sldap: 689
}

let cr = '\n'

class Parser {
  static windows (port) {
    let results = {}
    let stdout

    cr = '\r' + cr

    try {
      stdout = exec('netstat -aon | findstr :' + port + ' | findstr LISTENING').toString().trim().split(cr)
    } catch (e) {
      stdout = []
    }

    stdout.forEach((row) => {
      let item = row.trim().split(/\s{1,500}/)
      let processport = item[1].split(':').pop()

      if (!isNaN(processport)) {
        processport = parseInt(processport, 10)

        if (processport === parseInt(port, 10)) {
          results[item.pop()] = {}
        }
      }
    })

    Object.keys(results).forEach((pid) => {
      let out = exec('tasklist /FI \"PID eq ' + pid + '\" /FO CSV /NH /V').toString().trim().split(cr)
      out.forEach((row) => {
        let col = row.split(',')

        results[pid] = {
          process: col[0].substr(1, col[0].length - 2),
          user: col[6].substr(1, col[6].length - 2)
        }
      })
    })

    return results
  }

  static linux (port) {
    // Attempt lsof first
    try {
      return this.ss(port)
    } catch (e) {
      console.log(e)
      // Attempt ss next
      try {
        return this.lsof(port)
      } catch (e) {
        // Attempt netstat last
        try {
          return this.netstat(port)
        } catch (e) {
          console.log('Could not find lsof, ss, or netstat to determine port usage.')
          return {}
        }
      }
    }
  }

  static lsof (port) {
    let stdout = exec('lsof -i :' + port).toString().trim().split('\n')
    let results = {}

    if (stdout.length === 0) {
      return {}
    }

    stdout.shift()

    stdout.forEach(row => {
      if (row.indexOf('(LISTEN)') > 0) {
        let item = row.split(/\s{1,500}/)

        item.pop()

        let processport = item.pop().replace(/[^0-9]/gi, '')

        if (!isNaN(processport)) {
          processport = parseInt(processport, 10)

          let detail = this.linuxProcessDetails(item[1])

          results[item[1]] = {
            process: processport === parseInt(port, 10) ? detail.title : item[0],
            user: detail.user
          }
        }
      }
    })

    return results
  }

  static ss (port = '') {
console.log('>>>', port)
    let stdout = exec('ss -ptls | grep LISTEN').toString().trim().split('\n')
    let results = {}

    if (stdout.length === 0) {
      return {}
    }

    port = port.toString().split(' ').filter(number => !isNaN(number))
console.log(port)
    stdout.forEach(row => {
      // Group 1 is port
      let data = /:{1,3}([A-Za-z0-9]+)/i.exec(row)
console.log(row, data)
      // Handle named ports
      if (data !== null) {
        if (isNaN(data[1]) && portmap.hasOwnProperty(data[1].toLowerCase())) {
          data[1] = portmap[data[1].toLowerCase()].toString()
        }
      }

      if (port.indexOf(data[1].toString()) >= 0) {
        let ct = 0
        let PID = /\(\"([A-Za-z]+)\".*\,[pid=]{0,4}([0-9]+)\,/i.exec(data.input)

        while (PID !== null && ct < 100) {
          let detail = this.linuxProcessDetails(PID[2])

          results[PID[2]] = {
            process: detail.title,
            user: detail.user
          }

          data.input = data.input.replace(`pid=${PID[2]}`)
          PID = /\(\"([A-Za-z]+)\".*pid=([0-9]+)/i.exec(data.input)
          ct++
        }
      }
    })

    return results
  }

  static netstat (port) {
    let stdout = exec('netstat -tulnp | grep ' + port)
    let results = {}

    if (stdout.length === 0) {
      return {}
    }

    stdout.split('\n').forEach(row => {
      let data = row.split(/\s+/).pop().split(/\/|\\/)
      let detail = this.linuxProcessDetails(data[0])

      results[data[0]] = {
        process: detail.title,
        user: detail.user
      }
    })

    return results
  }

  static linuxProcessDetails (pid) {
console.log(exec('ps axco pid,command | grep ' + pid).toString())
    let processDetail = exec('ps axco pid,command | grep ' + pid)
      .toString()
      .split('\n')
      .filter(line => line.indexOf('grep') < 0)[0]
      .trim()
      .split(/\s+/)

    let user = processDetail[1]
console.log(processDetail)
    processDetail.splice(0, process.platform === 'darwin' ? 1 : 3)

    return {
      user,
      title: processDetail.join(' ')
    }
  }
}

module.exports = Parser
<|endoftext|>


<commit_before>/*!
 * Lansa
 *
 * Eric Mann <eric@eamann.com>
 *
 * MIT License.
 */

'use strict';

/**
 * Module dependencies
 */
var path = require( 'path' ),
	fs = require( 'fs' ),
	Err = require( './error' );

var E_NO_APP_NAME_OR_ID = new Err( 1, 'No application name or ID.' ),
	E_NO_DESCRIPTION = new Err( 2, 'No deployment description.' ),
	E_NO_REVISION = new Err( 4, 'No revision hash or ID.' ),
	E_NO_USER = new Err( 8, 'No user for deployment.' ),
	E_NO_CONFIG = new Err( 16, 'No `.lansarc` file in project.' ),
	E_INVALID_ENVIRONMENT = new Err( 32, 'Invalid CLI invocation.' );

function Parser( program ) {
	var error = 0,
		app_config = {};

	// First things first, let's figure out if there is a `.lansarc` file.
	var config_file = path.resolve( '.lansarc' );
	if ( fs.existsSync( config_file ) ) {
		var config = JSON.parse( fs.readFileSync( config_file, 'utf8' ) );

		if ( ! config.projects ) {
			error = error ^ E_NO_CONFIG.code;
		} else {
			if ( program.args.length < 1 ) {
				error = error ^ E_INVALID_ENVIRONMENT.code;
			} else {
				var args = program.args[0].split( ':' );

				if ( args.length < 2 ) {
					error = error ^ E_INVALID_ENVIRONMENT.code;
				} else {
					try {
						app_config = config.projects[ args[0] ][ args[1] ];

						if ( ! app_config.name && ! app_config.nrid ) {
							error = error ^ E_NO_APP_NAME_OR_ID.code;
						}
					} catch ( e ) {
						error = error ^ E_NO_APP_NAME_OR_ID.code;
					}

				}
			}
		}
	} else {
		error = error ^ E_NO_CONFIG.code;
	}

	if ( ! program.desc ) {
		error = error ^ E_NO_DESCRIPTION.code;
	} else {
		app_config.desc = program.desc;
	}

	if ( ! program.rev ) {
		error = error ^ E_NO_REVISION.code;
	} else {
		app_config.rev = program.rev;
	}

	if ( ! program.user ) {
		error = error ^ E_NO_USER.code;
	} else {
		app_config.user = program.user;
	}

	/**
	 * Map some optional parameters
	 */

	if ( program.changelog ) {
		app_config.changelog = program.changelog;
	}

	if ( program.dispatcher ) {
		app_config.dispatcher = program.dispatcher;
	}

	if ( program.logfile ) {
		app_config.logfile = path.resolve( program.logfile );
	}

	return {
		error : error,
		config: app_config
	};
}

module.exports = Parser;<commit_msg>Make sure the parser is properly documented.<commit_after>/*!
 * Lansa
 *
 * Eric Mann <eric@eamann.com>
 *
 * MIT License.
 */

'use strict';

/**
 * Module dependencies
 */
var path = require( 'path' ),
	fs = require( 'fs' ),
	Err = require( './error' );

/**
 * Error message pseudo-constants
 */
var E_NO_APP_NAME_OR_ID   = new Err( 1,  'No application name or ID.' ),
	E_NO_DESCRIPTION      = new Err( 2,  'No deployment description.' ),
	E_NO_REVISION         = new Err( 4,  'No revision hash or ID.' ),
	E_NO_USER             = new Err( 8,  'No user for deployment.' ),
	E_NO_CONFIG           = new Err( 16, 'No `.lansarc` file in project.' ),
	E_INVALID_ENVIRONMENT = new Err( 32, 'Invalid CLI invocation.' );

/**
 * Main CLI parsing routine.
 *
 * @param {Object} program Parsed program configuration from Commander
 *
 * @returns {{error: number, config: {}}}
 *
 * @constructor
 */
function Parser( program ) {
	var error = 0,
		app_config = {};

	// First things first, let's figure out if there is a `.lansarc` file.
	var config_file = path.resolve( '.lansarc' );
	if ( fs.existsSync( config_file ) ) {
		var config = JSON.parse( fs.readFileSync( config_file, 'utf8' ) );

		// Make sure the .lansarc file is configured properly
		if ( ! config.projects ) {
			error = error ^ E_NO_CONFIG.code;
		} else {

			// Make sure .lansarc specifies at least one enviornment
			if ( program.args.length < 1 ) {
				error = error ^ E_INVALID_ENVIRONMENT.code;
			} else {

				// Split up the parameters passed in to identify the project:enviornment
				var args = program.args[0].split( ':' );

				// If we don't have the right specification, err
				if ( 2 !== args.length ) {
					error = error ^ E_INVALID_ENVIRONMENT.code;
				} else {
					try {
						// Try to grab the configuration for the application we're deploying
						app_config = config.projects[ args[0] ][ args[1] ];

						if ( ! app_config.name && ! app_config.nrid ) {
							error = error ^ E_NO_APP_NAME_OR_ID.code;
						}
					} catch ( e ) {
						// Something went wrong reading our configuration file!
						error = error ^ E_NO_APP_NAME_OR_ID.code;
					}

				}
			}
		}
	} else {
		error = error ^ E_NO_CONFIG.code;
	}

	/**
	 * Map required parameters and, if not set, add to our error bitmask
	 */

	if ( ! program.desc ) {
		error = error ^ E_NO_DESCRIPTION.code;
	} else {
		app_config.desc = program.desc;
	}

	if ( ! program.rev ) {
		error = error ^ E_NO_REVISION.code;
	} else {
		app_config.rev = program.rev;
	}

	if ( ! program.user ) {
		error = error ^ E_NO_USER.code;
	} else {
		app_config.user = program.user;
	}

	/**
	 * Map some optional parameters
	 */

	app_config.changelog = program.changelog;
	app_config.dispatcher = program.dispatcher;

	if ( program.logfile ) {
		app_config.logfile = path.resolve( program.logfile );
	}

	// Return our parsed configuration
	return {
		error : error,
		config: app_config
	};
}

// Export the module
module.exports = Parser;<|endoftext|>