<commit_before>var http = require('http'),
    https = require('https'),
    EventEmitter = require('events').EventEmitter,
    inherits = require('util').inherits,
    extend = require('util')._extend,
    fs = require('fs'),
    path = require('path'),
    express = require('express'),
    favicon = require('serve-favicon'),
    WebSocketServer = require('ws').Server,
    Session = require('./session'),
    buildUrl = require('../index.js').buildInspectorUrl,
    OVERRIDES = path.join(__dirname, '../front-end-node'),
    WEBROOT = path.join(__dirname, '../front-end');

function debugAction(req, res) {
  if (!req.query.ws) {
    var newUrl = this.address().url;
    return res.redirect(newUrl);
  }
  res.sendFile(path.join(WEBROOT, 'inspector.html'));
}

function inspectorJson(req, res) {
  res.sendFile(path.join(OVERRIDES, 'inspector.json'));
}

function handleWebSocketConnection(socket) {
  if (socket.upgradeReq.url === '/?poll') { return; }
  var debugPort = this._getDebuggerPort(socket.upgradeReq.url);
  this._createSession(debugPort, socket);
}

function handleServerListening() {
  this.emit('listening');
}

function handleServerError(err) {
  if (err._handledByInspector) return;
  err._handledByInspector = true;
  this.emit('error', err);
}

function DebugServer() {}

inherits(DebugServer, EventEmitter);

DebugServer.prototype.start = function(options) {
  this._config = extend({}, options);
  this._isHTTPS = this._config.sslKey && this._config.sslCert ? true : false;

  var app = express();
  var httpServer;

  if (this._isHTTPS) {
    httpServer = https.createServer({
      key: fs.readFileSync(this._config.sslKey, {encoding: 'utf8'}),
      cert: fs.readFileSync(this._config.sslCert, {encoding: 'utf8'})
    }, app);
  } else {
    httpServer = http.createServer(app);
  }

  this._httpServer = httpServer;

  app.use(favicon(path.join(__dirname, '../front-end-node/Images/favicon.png')));
  app.get('/', debugAction.bind(this));
  app.get('/inspector.json', inspectorJson);
  app.use('/node', express.static(OVERRIDES));
  app.use(express.static(WEBROOT));

  this.wsServer = new WebSocketServer({
    server: httpServer
  });
  this.wsServer.on('connection', handleWebSocketConnection.bind(this));
  this.wsServer.on('error', handleServerError.bind(this));

  httpServer.on('listening', handleServerListening.bind(this));
  httpServer.on('error', handleServerError.bind(this));
  httpServer.listen(this._config.webPort, this._config.webHost);
};

DebugServer.prototype._getDebuggerPort = function(url) {
  return parseInt((/[\?\&]port=(\d+)/.exec(url) || [null, this._config.debugPort])[1], 10);
};

DebugServer.prototype._createSession = function(debugPort, wsConnection) {
  return new Session(this._config, debugPort, wsConnection);
};

DebugServer.prototype.close = function() {
  if (this.wsServer) {
    this.wsServer.close();
    this.emit('close');
  }
};

DebugServer.prototype.address = function() {
  var address = this._httpServer.address();
  var config = this._config;
  address.url = buildUrl(config.webHost, address.port, config.debugPort, null, this._isHTTPS);
  return address;
};

exports.DebugServer = DebugServer;
<commit_msg>Fixed #667<commit_after>var http = require('http'),
    https = require('https'),
    EventEmitter = require('events').EventEmitter,
    inherits = require('util').inherits,
    extend = require('util')._extend,
    fs = require('fs'),
    path = require('path'),
    express = require('express'),
    favicon = require('serve-favicon'),
    WebSocketServer = require('ws').Server,
    Session = require('./session'),
    buildUrl = require('../index.js').buildInspectorUrl,
    OVERRIDES = path.join(__dirname, '../front-end-node'),
    WEBROOT = path.join(__dirname, '../front-end');

function debugAction(req, res) {
  if (!req.query.ws) {
    var urlParts = req.headers.host.split(':'),
      debugPort = this._config.debugPort;

    var newUrl = buildUrl(urlParts[0], urlParts[1], debugPort, null, this._isHTTPS);
    return res.redirect(newUrl);
  }
  res.sendFile(path.join(WEBROOT, 'inspector.html'));
}

function inspectorJson(req, res) {
  res.sendFile(path.join(OVERRIDES, 'inspector.json'));
}

function handleWebSocketConnection(socket) {
  if (socket.upgradeReq.url === '/?poll') { return; }
  var debugPort = this._getDebuggerPort(socket.upgradeReq.url);
  this._createSession(debugPort, socket);
}

function handleServerListening() {
  this.emit('listening');
}

function handleServerError(err) {
  if (err._handledByInspector) return;
  err._handledByInspector = true;
  this.emit('error', err);
}

function DebugServer() {}

inherits(DebugServer, EventEmitter);

DebugServer.prototype.start = function(options) {
  this._config = extend({}, options);
  this._isHTTPS = this._config.sslKey && this._config.sslCert ? true : false;

  var app = express();
  var httpServer;

  if (this._isHTTPS) {
    httpServer = https.createServer({
      key: fs.readFileSync(this._config.sslKey, {encoding: 'utf8'}),
      cert: fs.readFileSync(this._config.sslCert, {encoding: 'utf8'})
    }, app);
  } else {
    httpServer = http.createServer(app);
  }

  this._httpServer = httpServer;

  app.use(favicon(path.join(__dirname, '../front-end-node/Images/favicon.png')));
  app.get('/', debugAction.bind(this));
  app.get('/inspector.json', inspectorJson);
  app.use('/node', express.static(OVERRIDES));
  app.use(express.static(WEBROOT));

  this.wsServer = new WebSocketServer({
    server: httpServer
  });
  this.wsServer.on('connection', handleWebSocketConnection.bind(this));
  this.wsServer.on('error', handleServerError.bind(this));

  httpServer.on('listening', handleServerListening.bind(this));
  httpServer.on('error', handleServerError.bind(this));
  httpServer.listen(this._config.webPort, this._config.webHost);
};

DebugServer.prototype._getDebuggerPort = function(url) {
  return parseInt((/[\?\&]port=(\d+)/.exec(url) || [null, this._config.debugPort])[1], 10);
};

DebugServer.prototype._createSession = function(debugPort, wsConnection) {
  return new Session(this._config, debugPort, wsConnection);
};

DebugServer.prototype.close = function() {
  if (this.wsServer) {
    this.wsServer.close();
    this.emit('close');
  }
};

DebugServer.prototype.address = function() {
  var address = this._httpServer.address();
  var config = this._config;
  address.url = buildUrl(config.webHost, address.port, config.debugPort, null, this._isHTTPS);
  return address;
};

exports.DebugServer = DebugServer;
<|endoftext|>


<commit_before>var _   = require('underscore'),
    fs  = require('fs'),
    path = require('path');

class Host{
    constructor() {
        this.tlsVerify = _.has(process.env, 'DOCKER_TLS_VERIFY');
        this.addr      = this._getAddr();
        this.certs     = this._getCerts();
    }
    /**
     * We are following the same format used by the Docker client:
     *  `tcp://[host][:port]` or `unix://path`
     * If there isn't a host available in env, fallback to:
     *  unix:///var/run/docker.sock
     * We are then parsing this host to request format:
     *  `http://unix:/absolute/path/to/unix.socket:/request/path`
     */
    _getAddr() {
        var protocol = this.tlsVerify ? 'https' : 'http',
            host = process.env.DOCKER_HOST || 'unix:///var/run/docker.sock';

        if (host.indexOf('unix://') === 0) {
            host = 'unix:'+host.substring(7)+':';
        }
        else if (host.indexOf('tcp://') === 0) {
            host = host.substring(6);
        }
        return protocol+'://'+host;
    }
    _getCerts() {
        if (!this.tlsVerify) return;

        return _.mapObject({ca: '', cert: '', key: ''}, function(val, key) {
            var filepath = path.resolve(process.env.DOCKER_CERT_PATH, key+'.pem');

            return fs.readFileSync(filepath);
        });
    }
}

module.exports = Host;<commit_msg>add string interpolation<commit_after>var _   = require('underscore'),
    fs  = require('fs'),
    path = require('path');

class Host{
    constructor() {
        this.tlsVerify = _.has(process.env, 'DOCKER_TLS_VERIFY');
        this.addr      = this._getAddr();
        this.certs     = this._getCerts();
    }
    /**
     * We are following the same format used by the Docker client:
     *  `tcp://[host][:port]` or `unix://path`
     * If there isn't a host available in env, fallback to:
     *  unix:///var/run/docker.sock
     * We are then parsing this host to request format:
     *  `http://unix:/absolute/path/to/unix.socket:/request/path`
     */
    _getAddr() {
        var protocol = this.tlsVerify ? 'https' : 'http',
            host = process.env.DOCKER_HOST || 'unix:///var/run/docker.sock';

        if (host.indexOf('unix://') === 0) {
            host = `unix:${host.substring(7)}:`;
        }
        else if (host.indexOf('tcp://') === 0) {
            host = host.substring(6);
        }
        return `${protocol}://${host}`;
    }
    _getCerts() {
        if (!this.tlsVerify) return;

        return _.mapObject({ca: '', cert: '', key: ''}, function(val, key) {
            var filepath = path.resolve(process.env.DOCKER_CERT_PATH, `${key}.pem`);

            return fs.readFileSync(filepath);
        });
    }
}

module.exports = Host;<|endoftext|>


<commit_before>var internals = {};

internals.mod = internals.mod || {};
internals.mod.log = require('../log');
internals.mod.type = require('../data_type');
internals.mod.Class = require('../class');
var Shadow = require('./shadow');
var log = internals.mod.log;
var tunnel = require('tunnel-ssh');

var ShadowProto = {

  createTable: function() { return Promise.resolve(); },
  addForeignKey: function() { return Promise.resolve(); },
  createCollection: function() { return Promise.resolve(); }
};

exports.connect = function (config, intern, callback) {
  var driver, req;

  var mod = internals.mod;
  internals = intern;
  internals.mod = mod;

  if ( !config.user && config.username )
    config.user = config.username;

  if (config.driver === undefined) {
    throw new Error(
      'config must include a driver key specifing which driver to use');
  }

  if (config.driver && typeof (config.driver) === 'object') {

    log.verbose('require:', config.driver.require);
    driver = require(config.driver.require);

  }
  else {
    try {

      req = 'db-migrate-' + config.driver;
      log.verbose('require:', req);

      try {

        driver = require(req);
      }
      catch (Exception) {

        driver = require('../../../' + req);
      }
    }
    catch (Exception) {

      //Fallback to internal drivers, while moving drivers to new repos
      req = './' + config.driver;
      log.verbose('require:', req);
      driver = require(req);
    }
  }

  log.verbose('connecting');

  var connect = function(config) {
    driver.connect(config, intern, function (err, db) {

      if (err) {

        callback(err);
        return;
      }
      log.verbose('connected');

      if (!global.immunity)
        db = Shadow.infect(db, internals, ShadowProto);

      callback(null, db);
    });
  };

  if (config.tunnel) {
    var tunnelConfig = JSON.parse(JSON.stringify(config.tunnel));
    tunnelConfig.dstHost = config.host;
    tunnelConfig.dstPort = config.port;

    if (tunnelConfig.privateKeyPath) {
      tunnelConfig.privateKey = require('fs').readFileSync(tunnelConfig.privateKeyPath);
    }

    // Reassign the db host/port to point to our local ssh tunnel
    config.host = '127.0.0.1';
    config.port = tunnelConfig.localPort;

    tunnel(tunnelConfig, function (err) {

      if (err) {
        callback(err);
        return;
      }
      log.verbose('SSH tunnel connected on port ', tunnelConfig.localPort);

      connect(config);
    });
  }
  else {
    connect(config);
  }
};<commit_msg>add missing dependency to drivers index.js<commit_after>var internals = {};

internals.mod = internals.mod || {};
internals.mod.log = require('../log');
internals.mod.type = require('../data_type');
internals.mod.Class = require('../class');
var Shadow = require('./shadow');
var log = internals.mod.log;
var tunnel = require('tunnel-ssh'),
    Promise = require('bluebird');

var ShadowProto = {

  createTable: function() { return Promise.resolve(); },
  addForeignKey: function() { return Promise.resolve(); },
  createCollection: function() { return Promise.resolve(); }
};

exports.connect = function (config, intern, callback) {
  var driver, req;

  var mod = internals.mod;
  internals = intern;
  internals.mod = mod;

  if ( !config.user && config.username )
    config.user = config.username;

  if (config.driver === undefined) {
    throw new Error(
      'config must include a driver key specifing which driver to use');
  }

  if (config.driver && typeof (config.driver) === 'object') {

    log.verbose('require:', config.driver.require);
    driver = require(config.driver.require);

  }
  else {
    try {

      req = 'db-migrate-' + config.driver;
      log.verbose('require:', req);

      try {

        driver = require(req);
      }
      catch (Exception) {

        driver = require('../../../' + req);
      }
    }
    catch (Exception) {

      //Fallback to internal drivers, while moving drivers to new repos
      req = './' + config.driver;
      log.verbose('require:', req);
      driver = require(req);
    }
  }

  log.verbose('connecting');

  var connect = function(config) {
    driver.connect(config, intern, function (err, db) {

      if (err) {

        callback(err);
        return;
      }
      log.verbose('connected');

      if (!global.immunity)
        db = Shadow.infect(db, internals, ShadowProto);

      callback(null, db);
    });
  };

  if (config.tunnel) {
    var tunnelConfig = JSON.parse(JSON.stringify(config.tunnel));
    tunnelConfig.dstHost = config.host;
    tunnelConfig.dstPort = config.port;

    if (tunnelConfig.privateKeyPath) {
      tunnelConfig.privateKey = require('fs').readFileSync(tunnelConfig.privateKeyPath);
    }

    // Reassign the db host/port to point to our local ssh tunnel
    config.host = '127.0.0.1';
    config.port = tunnelConfig.localPort;

    tunnel(tunnelConfig, function (err) {

      if (err) {
        callback(err);
        return;
      }
      log.verbose('SSH tunnel connected on port ', tunnelConfig.localPort);

      connect(config);
    });
  }
  else {
    connect(config);
  }
};<|endoftext|>


<commit_before>const React = require('react'); // eslint-disable-line import/no-extraneous-dependencies

function styled() {
  throw new Error(
    'Using the "styled" tag in runtime is not supported. Make sure you have set up the Babel plugin correctly.'
  );
}

styled.component = (tag, options) => {
  const Result = function Result(props) {
    const next = Object.assign({}, props, {
      className: props.className
        ? `${options.class} ${props.className}`
        : options.class,
    });

    if (options.vars) {
      const style = {};

      Object.keys(options.vars).forEach(name => {
        const value = options.vars[name];
        style[`--${name}`] = typeof value === 'function' ? value(props) : value;
      });

      next.style = Object.assign(style, next.style);
    }

    return React.createElement(tag, next);
  };

  Result.displayName = options.name;
  Result.className = options.class;

  return Result;
};

module.exports = styled;
<commit_msg>fix: use forwardRef for styled<commit_after>const React = require('react'); // eslint-disable-line import/no-extraneous-dependencies

function styled() {
  throw new Error(
    'Using the "styled" tag in runtime is not supported. Make sure you have set up the Babel plugin correctly.'
  );
}

styled.component = (tag, options) => {
  const Result = React.forwardRef((props, ref) => {
    const next = Object.assign({}, props, {
      ref,
      className: props.className
        ? `${options.class} ${props.className}`
        : options.class,
    });

    if (options.vars) {
      const style = {};

      Object.keys(options.vars).forEach(name => {
        const value = options.vars[name];
        style[`--${name}`] = typeof value === 'function' ? value(props) : value;
      });

      next.style = Object.assign(style, next.style);
    }

    return React.createElement(tag, next);
  });

  Result.displayName = options.name;
  Result.className = options.class;

  return Result;
};

module.exports = styled;
<|endoftext|>


<commit_before>function OAuthServiceOAuthSandbox(options) {
    var parent = OAuthServiceOAuthSandbox.prototype;

    var _private = {
        debug : false
    };

    this.init = function(options) {
        _private.debug = 'debug' in options ? options.debug : _private.debug;
        parent.init.apply(this, arguments);
    };

    this.signature_method = 'PLAINTEXT';

    this.realm = 'http://oauth-sandbox.sevengoslings.net/';
    this.requestTokenUrl = this.realm + 'request_token';
    this.authorizationUrl = this.realm + 'authorize';
    this.accessTokenUrl = this.realm + 'access_token';

    this.twoLegged = function() {
        this.authenticatedRequest(
                'http://oauth-sandbox.sevengoslings.net/two_legged', 'GET', {},
                function(data) {
                    console.log(data);
                });
    };

    this.threeLegged = function() {
        this.authenticatedRequest(
                'http://oauth-sandbox.sevengoslings.net/three_legged', 'GET', {},
                function(data) {
                    console.log(data);
                });
    };

    if (arguments.length > 0) {
        this.init(options);
    }
}

OAuthServiceOAuthSandbox.prototype = new OAuthService();
<commit_msg>updated to use HMAC-SHA1 for testing<commit_after>function OAuthServiceOAuthSandbox(options) {
    var parent = OAuthServiceOAuthSandbox.prototype;

    var _private = {
        debug : false
    };

    this.init = function(options) {
        _private.debug = 'debug' in options ? options.debug : _private.debug;
        parent.init.apply(this, arguments);
    };

    this.signature_method = 'HMAC-SHA1';

    this.realm = 'http://oauth-sandbox.sevengoslings.net/';
    this.requestTokenUrl = this.realm + 'request_token';
    this.authorizationUrl = this.realm + 'authorize';
    this.accessTokenUrl = this.realm + 'access_token';

    this.twoLegged = function() {
        this.authenticatedRequest(
                'http://oauth-sandbox.sevengoslings.net/two_legged', 'GET', {},
                function(data) {
                    console.log(data);
                });
    };

    this.threeLegged = function() {
        this.authenticatedRequest(
                'http://oauth-sandbox.sevengoslings.net/three_legged', 'GET', {},
                function(data) {
                    console.log(data);
                });
    };

    if (arguments.length > 0) {
        this.init(options);
    }
}

OAuthServiceOAuthSandbox.prototype = new OAuthService();
<|endoftext|>


<commit_before>/*! uDomainFlag | Copyright 2015 Thomas Bella */

// Extension related stuff
var selfhost 	  = "eklbfdpploakpkdakoielobggbhemlnm";		// Unique ID of this extension
var data_domain   = "udfdata.unterhaltungsbox.com";			// Domain which gets the data
var data_protocol =	"http";									// Protocol to use (http|https)
var lookup_domain = "domainflag.unterhaltungsbox.com";
var lookup_protocol = "http";

var backup_domain = data_domain;							// Secound domain, if first is offline | TODO: create secound domain with other server

// Security related stuff
var securityKey   = (typeof localStorage["securityKey"] !== "undefined") ? localStorage["securityKey"] : "";			// Security Key
var localID		  = (typeof localStorage["localID"] !== "undefined") ? localStorage["localID"] : "";					// Local ID

// Development related stuff
var errorReports  = (typeof localStorage["errorReports"] !== "undefined") ? localStorage["errorReports"] : "true";	// Send error reports?
var usageData	  = (typeof localStorage["usageData"] !== "undefined") ? localStorage["usageData"] : "true";		// Analyse data with Google Analytics

var loglevel	  = (typeof localStorage["loglevel"] !== "undefined") ? parseInt(localStorage["loglevel"]) : 1;		// Loglevel
	// 0 => Only error
	// 1 => 0 & warning
	// 2 => 1 & info
	// 3 => 2 & notice
	// 4 => 3 & debug

/*		User choise		*/
var popupWebsite  		= (typeof localStorage["popupWebsite"] !== "undefined") ? localStorage["popupWebsite"] : "false"; 				// Open information as new window/tab
var updateNotification  = (typeof localStorage["updateNotification"] !== "undefined") ? localStorage["updateNotification"] : "false"; 	// Nofification after plugin update
var socialData	  		= (typeof localStorage["socialData"] !== "undefined") ? localStorage["socialData"] : "false";					// Display socialData? (Google +1, Facebook likes, ...)
var usageData			= (typeof localStorage["usageData"] !== "undefined") ? localStorage["usageData"] : "true";						// Send usage data like language, online users and local time

var DBopen = false;

var remSync = false;
setTimeout(function(){ remSync = true; }, 1000 * 3); // Set remSync to true after 3 secounds -> we need a new security key

// Get data from global Google sync
if (typeof chrome.storage !== "undefined" && typeof chrome.storage.sync !== "undefined")
{
	chrome.storage.sync.get(["securityKey", "popupWebsite", "socialData", "updateNotification"], function(ret) {
		if (!$.isEmptyObject(ret))
		{
			if (typeof ret.securityKey !== "undefined")
				securityKey = localStorage["securityKey"] = ret.securityKey;

			if (typeof ret.popupWebsite !== "undefined")
				popupWebsite = localStorage["popupWebsite"] = ret.popupWebsite;

			if (typeof ret.socialData !== "undefined")
				socialData = localStorage["socialData"] = ret.socialData;

			if (typeof ret.updateNotification !== "undefined")
				updateNotification = localStorage["updateNotification"] = ret.updateNotification;
		}
		remSync = true;
	});
}
else
	debug.notice("Chrome.storage is not available!");

// Set loglevel to maximum, if extension doesn't have the right id
if (typeof selfhost === "undefined" || selfhost !== chrome.i18n.getMessage("@@extension_id"))
{
	loglevel = localStorage["loglevel"] = 4;
}

// Generate new localID if it is empty
if (localID === "")
{
	localID = localStorage["localID"] = Math.floor( Math.random() * 1000000000 ).toString(16);
}
<commit_msg>Encrypt all the things<commit_after>/*! uDomainFlag | Copyright 2015 Thomas Bella */

// Extension related stuff
var selfhost 	  = "eklbfdpploakpkdakoielobggbhemlnm";		// Unique ID of this extension
var data_domain   = "udfdata.unterhaltungsbox.com";			// Domain which gets the data
var data_protocol =	"https";								// Protocol to use (http|https)
var lookup_domain = "domainflag.unterhaltungsbox.com";
var lookup_protocol = "http";

var backup_domain = data_domain;							// Secound domain, if first is offline | TODO: create secound domain with other server

// Security related stuff
var securityKey   = (typeof localStorage["securityKey"] !== "undefined") ? localStorage["securityKey"] : "";			// Security Key
var localID		  = (typeof localStorage["localID"] !== "undefined") ? localStorage["localID"] : "";					// Local ID

// Development related stuff
var errorReports  = (typeof localStorage["errorReports"] !== "undefined") ? localStorage["errorReports"] : "true";	// Send error reports?
var usageData	  = (typeof localStorage["usageData"] !== "undefined") ? localStorage["usageData"] : "true";		// Analyse data with Google Analytics

var loglevel	  = (typeof localStorage["loglevel"] !== "undefined") ? parseInt(localStorage["loglevel"]) : 1;		// Loglevel
	// 0 => Only error
	// 1 => 0 & warning
	// 2 => 1 & info
	// 3 => 2 & notice
	// 4 => 3 & debug

/*		User choise		*/
var popupWebsite  		= (typeof localStorage["popupWebsite"] !== "undefined") ? localStorage["popupWebsite"] : "false"; 				// Open information as new window/tab
var updateNotification  = (typeof localStorage["updateNotification"] !== "undefined") ? localStorage["updateNotification"] : "false"; 	// Nofification after plugin update
var socialData	  		= (typeof localStorage["socialData"] !== "undefined") ? localStorage["socialData"] : "false";					// Display socialData? (Google +1, Facebook likes, ...)
var usageData			= (typeof localStorage["usageData"] !== "undefined") ? localStorage["usageData"] : "true";						// Send usage data like language, online users and local time

var DBopen = false;

var remSync = false;
setTimeout(function(){ remSync = true; }, 1000 * 3); // Set remSync to true after 3 secounds -> we need a new security key

// Get data from global Google sync
if (typeof chrome.storage !== "undefined" && typeof chrome.storage.sync !== "undefined")
{
	chrome.storage.sync.get(["securityKey", "popupWebsite", "socialData", "updateNotification"], function(ret) {
		if (!$.isEmptyObject(ret))
		{
			if (typeof ret.securityKey !== "undefined")
				securityKey = localStorage["securityKey"] = ret.securityKey;

			if (typeof ret.popupWebsite !== "undefined")
				popupWebsite = localStorage["popupWebsite"] = ret.popupWebsite;

			if (typeof ret.socialData !== "undefined")
				socialData = localStorage["socialData"] = ret.socialData;

			if (typeof ret.updateNotification !== "undefined")
				updateNotification = localStorage["updateNotification"] = ret.updateNotification;
		}
		remSync = true;
	});
}
else
	debug.notice("Chrome.storage is not available!");

// Set loglevel to maximum, if extension doesn't have the right id
if (typeof selfhost === "undefined" || selfhost !== chrome.i18n.getMessage("@@extension_id"))
{
	loglevel = localStorage["loglevel"] = 4;
}

// Generate new localID if it is empty
if (localID === "")
{
	localID = localStorage["localID"] = Math.floor( Math.random() * 1000000000 ).toString(16);
}
<|endoftext|>


<commit_before>
Express = { version: '0.0.1' }<commit_msg>Started new routing system<commit_after>
// Express - Core - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)

;(function(){

  // --- Express

  Express = { version: '0.0.1' }

  // --- Locals

  var plugins = [],
      routes = []

  /**
   * Return a routing function for _method_.
   *
   * @param  {string} method
   * @return {function}
   * @api private
   */

  function route(method) {
    // return function(path, options, callback) {
    //   if (options.constructor == Function) callback = options, options = {}
    //   path = Express.pathToRegexp(Express.normalizePath(path))
    //   var route = {
    //     keys : Express.regexpKeys,
    //     path : path,
    //     method : method,
    //     options : options,
    //     callback : callback
    //   }
    //   Express.routes.push(route)
    //   Express.hook('onRouteAdded', route)
    }

    // --- Routing API

    get = view = route('get')
    post = create = route('post')
    del = destroy = route('delete')
    put = update = route('put')

})()<|endoftext|>


<commit_before>
/*!
 * Express - View
 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var extname = require('path').extname,
    mime = require('connect/utils').mime,
    utils = require('connect/utils'),
    http = require('http'),
    sys = require('sys'),
    fs = require('fs');

/**
 * Cache supported template engine exports to
 * increase performance by lowering the number
 * of calls to `require()`.
 *
 * @type Object
 */

var cache = {};

/**
 * Cache view contents to prevent I/O hits.
 *
 * @type Object
 */

var viewCache = {};

/**
 * Clear the view cache.
 *
 * @api public
 */

exports.clearCache = function(){
    viewCache = {};
};

/**
 * View helpers merged with each render's locals.
 *
 * @type Object
 */

var helpers = exports.helpers = {};

/**
 * Cache view at the given `path`.
 *
 * @param {String} path
 * @return {String}
 * @api private
 */

function cacheView(path) {
    fs.readFile(path, 'utf8', function(err, data){
        if (!err) {
            viewCache[path] = data;
        }
    });
}

/**
 * Synchronously cache view at the given `path`.
 *
 * @param {String} path
 * @return {String}
 * @api private
 */

function cacheViewSync(path) {
    return viewCache[path] = fs.readFileSync(path, 'utf8');
}

/**
 * Return view root path for the given `app`.
 *
 * @param {express.Server} app
 * @return {String}
 * @api private
 */

function viewRoot(app) {
    return app.set('views') || process.cwd() + '/views';
}

/**
 * Setup view reloading, checking at the given `interval`
 * which defaults to 5 minutes.
 *
 * @param {Numbers} interval
 * @api private
 */

exports.watcher = function(interval){
    interval = interval === true
        ? 300000
        : interval;
    (function cache(dir){
        fs.readdir(dir, function(err, files){
            if (!err) {
                files.forEach(function(file){
                    file = dir + '/' + file;
                    fs.stat(file, function(err, stats){
                        if (!err) {
                            if (stats.isFile()) {
                                fs.watchFile(file, { interval: interval }, function(curr, prev){
                                    if (curr.mtime > prev.mtime) {
                                        cacheView(file);
                                    }
                                });
                            } else if (stats.isDirectory()) {
                                cache(file);
                            }
                        }
                    });
                });
            }
        });
    })(viewRoot(this));
};

/**
 * Render `view` partial with the given `options`.
 *
 * Options:
 *   - `object` Single object with name derived from the view (unless `as` is present)
 *
 *   - `as` Variable name for each `collection` value, defaults to the view name.
 *     * as: 'something' will add the `something` local variable
 *     * as: this will use the collection value as the template context
 *     * as: global will merge the collection value's properties with `locals`
 *
 *   - `collection` Array of objects, the name is derived from the view name itself.
 *     For example _video.html_ will have a object _video_ available to it.
 *
 * @param  {String} view
 * @param  {Object|Array} options or collection
 * @return {String}
 * @api public
 */

http.ServerResponse.prototype.partial = function(view, options, ext){
    if (ext && view.indexOf('.') < 0) {
        view += ext;
    }
    if (options instanceof Array) {
        options = { collection: options };
    }
    options = options || {};
    options.partial = true;
    options.layout = false;
    var collection = options.collection;
    if (collection) {
        var name = options.as || view.split('.')[0],
            len = collection.length;
        var locals = options.locals = options.locals || {};
        locals.collectionLength = len;
        return collection.map(function(val, i){
            if (typeof name === 'string') {
                locals[name] = val;
            } else if (name === global) {
                utils.merge(locals, val);
            } else {
                options.context = val;
            }
            locals.firstInCollection = i === 0;
            locals.indexInCollection = i;
            locals.lastInCollection = i === len - 1;
            return this.render(view, options);
        }, this).join('');
    } else {
        options.locals = options.locals || {};
        if (options.object) {
            var name = options.as || view.split('.')[0];
            if (typeof name === 'string') {
                options.locals[name] = options.object;
            } else if (name === global) {
                utils.merge(options.locals, options.object);
            } else {
                options.context = options.object;
            }
        }
        return this.render(view, options);
    }
};

/**
 * Render `view` with the given `options` and optional callback `fn`.
 * When a callback function is given a response will _not_ be made
 * automatically, however otherwise a response of _200_ and _text/html_ is given.
 *
 * Options:
 *
 *  Most engines accept one or more of the following options,
 *  both _haml_ and _jade_ accept all:
 *
 *  - `context|scope`   Template evaluation context (`this`)
 *  - `locals`    Object containing local variables
 *  - `filename`  Filename used for the `cache` option
 *  - `cache`     Cache intermediate JavaScript in memory
 *  - `debug`     Output debugging information
 *
 * @param  {String} view
 * @param  {Object} options
 * @param  {Function} fn
 * @api public
 */

http.ServerResponse.prototype.render = function(view, options, fn){
    options = options || {};
    var defaultEngine = this.app.set('view engine');

    // Support "view engine" setting
    if (view.indexOf('.') < 0 && defaultEngine) {
        view += '.' + defaultEngine;
    }

    // Defaults
    var self = this,
        root = viewRoot(this.app),
        ext = extname(view),
        partial = options.partial,
        layout = options.layout === undefined ? true : options.layout,
        layout = layout === true
            ? 'layout' + ext
            : layout;

    // Normalize "context" to "scope"
    options.scope = options.scope || options.context;

    // Auto-cache in production
    if (this.app.set('env') === 'production') {
        options.cache = true;
    }

    // Partials support
    if (options.partial) {
        root += '/partials';
    }

    // View path
    var path = root + '/' + view;

    // Send response
    function send(str) {
        self.writeHead(200, {
            'Content-Type': 'text/html',
            'Content-Length': str.length
        });
        self.end(str);
    }

    // Pass filename to the engine and view
    options.locals = options.locals || {};
    options.locals.__filename = options.filename = path;

    // Always expose partial() as a local
    options.locals.partial = function(view, options){
        return self.partial.call(self, view, options, ext);
    };

    // Merge view helpers
    options.locals.__proto__ = helpers;

    function error(err) {
        if (fn) {
            fn(err);
        } else {
            throw err;
        }
    }

    // Cache contents
    try {
        var str = viewCache[path] || cacheViewSync(path);
    } catch (err) {
        return error(err);
    }

    // Cache template engine exports
    var engine = cache[ext] || (cache[ext] = require(ext.substr(1)));

    // Attempt render
    try {
        var str = engine.render(str, options);
    } catch (err) {
        return error(err);
    }

    // Layout support
    if (layout) {
        options.layout = false;
        options.locals.body = str;
        self.render(layout, options);
    } else if (partial) {
        return str;
    } else if (fn) {
        fn(null, str);
    } else {
        send(str);
    }
};
<commit_msg>Refactored res.partial()<commit_after>
/*!
 * Express - View
 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var extname = require('path').extname,
    mime = require('connect/utils').mime,
    utils = require('connect/utils'),
    http = require('http'),
    sys = require('sys'),
    fs = require('fs');

/**
 * Cache supported template engine exports to
 * increase performance by lowering the number
 * of calls to `require()`.
 *
 * @type Object
 */

var cache = {};

/**
 * Cache view contents to prevent I/O hits.
 *
 * @type Object
 */

var viewCache = {};

/**
 * Clear the view cache.
 *
 * @api public
 */

exports.clearCache = function(){
    viewCache = {};
};

/**
 * View helpers merged with each render's locals.
 *
 * @type Object
 */

var helpers = exports.helpers = {};

/**
 * Cache view at the given `path`.
 *
 * @param {String} path
 * @return {String}
 * @api private
 */

function cacheView(path) {
    fs.readFile(path, 'utf8', function(err, data){
        if (!err) {
            viewCache[path] = data;
        }
    });
}

/**
 * Synchronously cache view at the given `path`.
 *
 * @param {String} path
 * @return {String}
 * @api private
 */

function cacheViewSync(path) {
    return viewCache[path] = fs.readFileSync(path, 'utf8');
}

/**
 * Return view root path for the given `app`.
 *
 * @param {express.Server} app
 * @return {String}
 * @api private
 */

function viewRoot(app) {
    return app.set('views') || process.cwd() + '/views';
}

/**
 * Setup view reloading, checking at the given `interval`
 * which defaults to 5 minutes.
 *
 * @param {Numbers} interval
 * @api private
 */

exports.watcher = function(interval){
    interval = interval === true
        ? 300000
        : interval;
    (function cache(dir){
        fs.readdir(dir, function(err, files){
            if (!err) {
                files.forEach(function(file){
                    file = dir + '/' + file;
                    fs.stat(file, function(err, stats){
                        if (!err) {
                            if (stats.isFile()) {
                                fs.watchFile(file, { interval: interval }, function(curr, prev){
                                    if (curr.mtime > prev.mtime) {
                                        cacheView(file);
                                    }
                                });
                            } else if (stats.isDirectory()) {
                                cache(file);
                            }
                        }
                    });
                });
            }
        });
    })(viewRoot(this));
};

/**
 * Render `view` partial with the given `options`.
 *
 * Options:
 *   - `object` Single object with name derived from the view (unless `as` is present)
 *
 *   - `as` Variable name for each `collection` value, defaults to the view name.
 *     * as: 'something' will add the `something` local variable
 *     * as: this will use the collection value as the template context
 *     * as: global will merge the collection value's properties with `locals`
 *
 *   - `collection` Array of objects, the name is derived from the view name itself.
 *     For example _video.html_ will have a object _video_ available to it.
 *
 * @param  {String} view
 * @param  {Object|Array} options or collection
 * @return {String}
 * @api public
 */

http.ServerResponse.prototype.partial = function(view, options, ext){
    // Inherit parent view extension when not present
    if (ext && view.indexOf('.') < 0) {
        view += ext;
    }

    // Allow collection to be passed as second param
    if (options instanceof Array) {
        options = { collection: options };
    }

    // Defaults
    options = options || {};
    options.locals = options.locals || {};
    options.partial = true;
    options.layout = false;

    // Collection support
    var collection = options.collection;
    if (collection) {
        var name = options.as || view.split('.')[0],
            len = collection.length;
        delete options.collection;
        options.locals.collectionLength = len;
        return collection.map(function(val, i){
            options.locals.firstInCollection = i === 0;
            options.locals.indexInCollection = i;
            options.locals.lastInCollection = i === len - 1;
            options.object = val;
            return this.partial(view, options);
        }, this).join('');
    } else {
        if (options.object) {
            var name = options.as || view.split('.')[0];
            if (typeof name === 'string') {
                options.locals[name] = options.object;
            } else if (name === global) {
                utils.merge(options.locals, options.object);
            } else {
                options.context = options.object;
            }
        }
        return this.render(view, options);
    }
};

/**
 * Render `view` with the given `options` and optional callback `fn`.
 * When a callback function is given a response will _not_ be made
 * automatically, however otherwise a response of _200_ and _text/html_ is given.
 *
 * Options:
 *
 *  Most engines accept one or more of the following options,
 *  both _haml_ and _jade_ accept all:
 *
 *  - `context|scope`   Template evaluation context (`this`)
 *  - `locals`    Object containing local variables
 *  - `filename`  Filename used for the `cache` option
 *  - `cache`     Cache intermediate JavaScript in memory
 *  - `debug`     Output debugging information
 *
 * @param  {String} view
 * @param  {Object} options
 * @param  {Function} fn
 * @api public
 */

http.ServerResponse.prototype.render = function(view, options, fn){
    options = options || {};
    var defaultEngine = this.app.set('view engine');

    // Support "view engine" setting
    if (view.indexOf('.') < 0 && defaultEngine) {
        view += '.' + defaultEngine;
    }

    // Defaults
    var self = this,
        root = viewRoot(this.app),
        ext = extname(view),
        partial = options.partial,
        layout = options.layout === undefined ? true : options.layout,
        layout = layout === true
            ? 'layout' + ext
            : layout;

    // Normalize "context" to "scope"
    options.scope = options.scope || options.context;

    // Auto-cache in production
    if (this.app.set('env') === 'production') {
        options.cache = true;
    }

    // Partials support
    if (options.partial) {
        root += '/partials';
    }

    // View path
    var path = root + '/' + view;

    // Send response
    function send(str) {
        self.writeHead(200, {
            'Content-Type': 'text/html',
            'Content-Length': str.length
        });
        self.end(str);
    }

    // Pass filename to the engine and view
    options.locals = options.locals || {};
    options.locals.__filename = options.filename = path;

    // Always expose partial() as a local
    options.locals.partial = function(view, options){
        return self.partial.call(self, view, options, ext);
    };

    // Merge view helpers
    options.locals.__proto__ = helpers;

    function error(err) {
        if (fn) {
            fn(err);
        } else {
            throw err;
        }
    }

    // Cache contents
    try {
        var str = viewCache[path] || cacheViewSync(path);
    } catch (err) {
        return error(err);
    }

    // Cache template engine exports
    var engine = cache[ext] || (cache[ext] = require(ext.substr(1)));

    // Attempt render
    try {
        var str = engine.render(str, options);
    } catch (err) {
        return error(err);
    }

    // Layout support
    if (layout) {
        options.layout = false;
        options.locals.body = str;
        self.render(layout, options);
    } else if (partial) {
        return str;
    } else if (fn) {
        fn(null, str);
    } else {
        send(str);
    }
};
<|endoftext|>


<commit_before>'use strict';

/*
  fb-report.js

  Incident report process
*/

const FBProcess = require('./fb-process');
const util = require('util');
const ExifImage = require('exif').ExifImage;

// States
const STATE = {
  INITIAL: FBProcess.CONST.STATE.INITIAL,
  PHOTO: 'state_photo'
};

function FBReport(options) {
  if (!(this instanceof FBReport)) {
    return new FBReport(options);
  }

  options = options || {};
  options.name = FBProcess.CONST.PROCESS.REPORT;
  FBProcess.call(this, options);
}

util.inherits(FBReport, FBProcess);

FBReport.prototype.handleMessageState = function(options) {
  options = options || {};

  switch (options.state) {
    case STATE.INITIAL:
      this.sendPhotoRequest(options);
      break;
    case STATE.PHOTO:
      switch (options.type) {
        case 'message':
          this.handleUserMessage(options);
          break;
        case 'postback':
          // TODO: handle incoming photo
          break;
        default:
          this.unknownCommand(options);
      }
      break;
    default:
      this.unknownCommand(options);
  }
};

/*Handle the incoming photo*/
FBReport.prototype.handleUserMessage = function(options) {
  options = options || {};
  const images = null;
  if(options.data.attachment) {
    images = options.data.attachment.image;
  }
  if(images != null) {
    images.forEach(function(image_url) {
      this.check_image(image_url);
    })
  }
};

// Ask the user to upload a picture of the incident
FBReport.prototype.sendPhotoRequest = function(options) {
  options = options || {};

  // TODO: change photo request's message
  /*
    NOTE: there's no need to send a form. Facebook will take care of
    the photo, we just have to expect a photo attachment.
  */

  this.bot.botly.sendText({
    id: options.user_id,
    text: 'Veuillez prendre en photo l\'incident'
  });

  options.state = STATE.PHOTO;
  this.transitionState(options);
};

// Check if the GPS data of the image provided is correct
FBReport.prototype.check_image = function(image_url) {
  let position = { };
  console.log(image_url);
  try {
    new ExifImage({ image : image_url }, function (error, exifData) {
      if (error)
        console.log('Error: '+error.message);
      else
        console.log(exifData); // Do something with your data!
    });
  } catch (error) {
    console.log('Error: ' + error.message);
  }

};

// Unknown/Unexpected command
FBReport.prototype.unknownCommand = function(options) {
  options = options || {};

  options.proc = FBProcess.CONST.PROCESS.GREETING;
  this.transitionProcess(options);
};

module.exports = FBReport;<commit_msg>Debug Analyse d'image #2<commit_after>'use strict';

/*
  fb-report.js

  Incident report process
*/

const FBProcess = require('./fb-process');
const util = require('util');
const ExifImage = require('exif').ExifImage;

// States
const STATE = {
  INITIAL: FBProcess.CONST.STATE.INITIAL,
  PHOTO: 'state_photo'
};

function FBReport(options) {
  if (!(this instanceof FBReport)) {
    return new FBReport(options);
  }

  options = options || {};
  options.name = FBProcess.CONST.PROCESS.REPORT;
  FBProcess.call(this, options);
}

util.inherits(FBReport, FBProcess);

FBReport.prototype.handleMessageState = function(options) {
  options = options || {};

  switch (options.state) {
    case STATE.INITIAL:
      this.sendPhotoRequest(options);
      break;
    case STATE.PHOTO:
      switch (options.type) {
        case 'message':
          this.handleUserMessage(options);
          break;
        case 'postback':
          // TODO: handle incoming photo
          break;
        default:
          this.unknownCommand(options);
      }
      break;
    default:
      this.unknownCommand(options);
  }
};

/*Handle the incoming photo*/
FBReport.prototype.handleUserMessage = function(options) {
  options = options || {};
  const images = null;
  console.log(options.data.attachment);
  console.log(options.data.attachment.image);
  console.log(options.data.attachment.image[0]);
  if(options.data.attachment) {
    images = options.data.attachment.image;
  }
  if(images != null) {
    images.forEach(function(image_url) {
      this.check_image(image_url);
    })
  }
};

// Ask the user to upload a picture of the incident
FBReport.prototype.sendPhotoRequest = function(options) {
  options = options || {};

  // TODO: change photo request's message
  /*
    NOTE: there's no need to send a form. Facebook will take care of
    the photo, we just have to expect a photo attachment.
  */

  this.bot.botly.sendText({
    id: options.user_id,
    text: 'Veuillez prendre en photo l\'incident'
  });

  options.state = STATE.PHOTO;
  this.transitionState(options);
};

// Check if the GPS data of the image provided is correct
FBReport.prototype.check_image = function(image_url) {
  let position = { };
  console.log(image_url);
  try {
    new ExifImage({ image : image_url }, function (error, exifData) {
      if (error)
        console.log('Error: '+error.message);
      else
        console.log(exifData); // Do something with your data!
    });
  } catch (error) {
    console.log('Error: ' + error.message);
  }

};

// Unknown/Unexpected command
FBReport.prototype.unknownCommand = function(options) {
  options = options || {};

  options.proc = FBProcess.CONST.PROCESS.GREETING;
  this.transitionProcess(options);
};

module.exports = FBReport;<|endoftext|>


<commit_before>"use strict";

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

var url_module = require('url');
var fs_module = require('fs');
var https_module = require('https');
var http_module = require('http');

/**
 * This object facilitates resumable uploading
 *
 * @param {string} file_path       Path to the video file
 * @param {string} upload_endpoint upload URL provided with an upload ticket
 */
var FileStreamer = module.exports = function FileStreamer(file_path, upload_endpoint, ticket_id, progress_callback) {
    if (!file_path) {
        throw new Error('You must provide a file path');
    }

    if (!upload_endpoint) {
        throw new Error('You must provide an upload endpoint');
    }

    this._endpoint = url_module.parse(upload_endpoint);

    if (this._endpoint.protocol === 'https:' && !this._endpoint.port) {
        this._endpoint.port = 443;
    }

    this._ticket_id = ticket_id
    this._path = file_path;
	this.progress_callback = progress_callback;
};

FileStreamer.prototype._endpoint = null;
FileStreamer.prototype._ticket_id = null;
FileStreamer.prototype._path = null;
FileStreamer.prototype._fd = null;
FileStreamer.prototype._file_size = 0;
FileStreamer.prototype.percentage = 0;
FileStreamer.prototype.sequential = true;
FileStreamer.prototype._readStreamFd = null;
FileStreamer.prototype.progress_callback = null;

// hack by Johnny. We count the numbers of errors and if they are greater than 10, only then will we abort the upload
FileStreamer.prototype._streamUploadMaxErrors = 0;
FileStreamer.prototype._sentBytes = 0;

/**
 * Holds the user defined ready function. Do not call this outside of the library
 */
FileStreamer.prototype._user_ready = function () {
    this.ready = function (fn) {
        fn();
    }
};

/**
 * Called internally whenever the upload might be complete.
 * If the upload is complete it will call _user_ready, if not it will attempt to upload from where it left off.
 *
 * Do not call this outside of the library.
 */
FileStreamer.prototype._ready = function () {
    var _self = this;

    // If we think we are ready to complete, check with the server and see if they have the whole file
    this._getNewStart(function (err, start) {
        if (err) {
            // If the check fails, close the file and error out immediately
            _self._cleanupFds();
            return _self._error(err);
        }

        if (start >= _self._file_size) {
            // If the server says they have the whole file, close it and then return back to the user
            _self._cleanupFds();
            _self._user_ready();
        } else {
            // If the server does not have the whole file, upload from where we left off
            _self._streamChunk(start);
        }
    });
};

/**
 * Assign a callback to be called whenever the file is done uploading.
 *
 * @param  {Function} fn The ready callback
 */
FileStreamer.prototype.ready = function (fn) {
    this._user_ready = fn;
};

/**
 * Holds the error callback. Do not call this outside of the library
 *
 * @param  {Error} error The error that was thrown
 * @return {[type]}       [description]
 */
FileStreamer.prototype._error = function (error) {
    this.error = function (fn) {
        fn(error);
    };
};

/**
 * Assign a callback to be called whenever an error occurs.
 *
 * @param  {Function} fn The error callback
 */
FileStreamer.prototype.error = function (fn) {
    this._error = fn;
};

/**
 * Start uploading the file
 */
FileStreamer.prototype.upload = function () {
    var _self = this;

    fs_module.stat(_self._path, function (stat_err, stats) {
        if (stat_err) {
            return _self._error(stat_err);
        }

        _self._file_size = stats.size;

        fs_module.open(_self._path, 'r', function(open_err, fd) {
            if (open_err) {
                return _self._error(open_err);
            }

            _self._fd = fd;
            _self._streamChunk(0);
        });
    });
};

/**
 * Send a file chunk, starting at byte [start] and ending at the end of the file
 *
 * @param  {Number} start
 */
FileStreamer.prototype._streamChunk = function (start) {
    var _self = this;

    _self._sentBytes = start
    _self._putFile(start, function (put_err, code, headers) {

        // Catches a rare vimeo server bug and exits out early
        if (put_err && code && ++_self._streamUploadMaxErrors >= 100) {
            _self._cleanupFds();
            return _self._error(new Error(put_err.message + " streamErrors: 100, successfulBytes: " + _self._sentBytes));
        }

        _self._ready();
    });
};

/**
 * Make the HTTP put request sending a part of a file up to the upload server
 *
 * @param  {Number}   start    The first byte of the file
 * @param  {Function} callback A function which is called once the upload is complete, or has failed
 */
FileStreamer.prototype._putFile = function (start, callback) {
    var _self = this;

    // cleanup any remaining read stream file descriptor
    this._closeReadStreamFd();

    var file = fs_module.createReadStream(_self._path, {
        start : start,
        autoClose: true
    });

    file.on('open', function (fd) {
       _self._readStreamFd = fd;
    });

    file.on('error', function (err) {
        callback(err);
    });

    var uploaded_size = start || 0;

    file.on('data', function(chunk) {
        uploaded_size += chunk.length || 0;
        if (_self.progress_callback) {
            _self.progress_callback(uploaded_size, _self._file_size);
        }
    });

    var headers =  {
        'Content-Length' : _self._file_size,
        'Content-Type' : 'video/mp4'
    };

    headers['Content-Range'] = 'bytes ' + start + '-' + _self._file_size + '/' + _self._file_size;

    var req = _self._upload_endpoint_request({
        method : 'PUT',
        headers : headers
    }, callback);

    file.pipe(req);
};

FileStreamer.prototype._cleanupFds = function () {
    this._closeFile();
    this._closeReadStreamFd();
};

/**
 * Cleanup the read stream of the file, if there's still one
 */
FileStreamer.prototype._closeReadStreamFd = function () {
    if (this._readStreamFd) {
        fs_module.close(this._readStreamFd, function (e) {});
        this._readStreamFd = null;
    }
};

/**
 * Close the file
 */
FileStreamer.prototype._closeFile = function () {
    if (this._fd) {
        fs_module.close(this._fd, function (e) {});
        this._fd = null;
    }
};

/**
 * Verify the file upload and determine the last most byte the server has received
 * @param  {Function} next A callback that will be called when the check is complete, or has errored
 */
FileStreamer.prototype._getNewStart = function (next) {
    var _self = this;

    this._upload_endpoint_request({
        method : 'PUT',
        headers : {
            'Content-Range' : 'bytes */*',
            'Content-Type' : 'application/octet-stream'
        }
    }, function (err, status, headers) {
        if (err) {
            return next(new Error('Error when getting new start:' + err.message));
        }

        if (status === 308) {
            return next(null, parseInt(headers.range.split('-')[1] + 1));
        } else {
            return next(new Error('Invalid http status returned from range query: [' + status + ']'));
        }
    }).end();
};

/**
 * Makes an http request to the upload server, and sends the response through the callback
 *
 * @param  {Object}   options  Request options, pumped into https.request(options);
 * @param  {Function} callback Called when the upload is complete, or has failed
 */
FileStreamer.prototype._upload_endpoint_request = function (options, callback) {
    var request_options = {
        protocol : this._endpoint.protocol,
        host : this._endpoint.hostname,
        port : this._endpoint.port,
        query : this._endpoint.query,
        headers : options.headers,
        path : this._endpoint.path,
        method : options.method
    };

    var client = request_options.protocol === 'https:' ? https_module : http_module;
    var req = client.request(request_options);

    req.on('response', function (res) {
        res.setEncoding('utf8');

        var buffer = '';
        res.on('readable', function () {
            buffer += res.read();
        });

        if (res.statusCode > 399) {
            // failed api calls should wait for the response to end and then call the callback with an error.
            res.on('end', function () {
                callback(new Error('[' + buffer + ']'), res.statusCode, res.headers);
            });
        } else {
            // successful api calls should wait for the response to end and then call the callback with the response body
            res.on('end', function () {
                callback(null, res.statusCode, res.headers);
            });
        }
    });

    // notify user of any weird connection/request errors
    req.on('error', function(e) {
        callback(e);
    });

    return req;
};
<commit_msg>file streamer max errors to 10<commit_after>"use strict";

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

var url_module = require('url');
var fs_module = require('fs');
var https_module = require('https');
var http_module = require('http');

/**
 * This object facilitates resumable uploading
 *
 * @param {string} file_path       Path to the video file
 * @param {string} upload_endpoint upload URL provided with an upload ticket
 */
var FileStreamer = module.exports = function FileStreamer(file_path, upload_endpoint, ticket_id, progress_callback) {
    if (!file_path) {
        throw new Error('You must provide a file path');
    }

    if (!upload_endpoint) {
        throw new Error('You must provide an upload endpoint');
    }

    this._endpoint = url_module.parse(upload_endpoint);

    if (this._endpoint.protocol === 'https:' && !this._endpoint.port) {
        this._endpoint.port = 443;
    }

    this._ticket_id = ticket_id
    this._path = file_path;
	this.progress_callback = progress_callback;
};

FileStreamer.prototype._endpoint = null;
FileStreamer.prototype._ticket_id = null;
FileStreamer.prototype._path = null;
FileStreamer.prototype._fd = null;
FileStreamer.prototype._file_size = 0;
FileStreamer.prototype.percentage = 0;
FileStreamer.prototype.sequential = true;
FileStreamer.prototype._readStreamFd = null;
FileStreamer.prototype.progress_callback = null;

// hack by Johnny. We count the numbers of errors and if they are greater than 10, only then will we abort the upload
FileStreamer.prototype._streamUploadMaxErrors = 0;
FileStreamer.prototype._sentBytes = 0;

/**
 * Holds the user defined ready function. Do not call this outside of the library
 */
FileStreamer.prototype._user_ready = function () {
    this.ready = function (fn) {
        fn();
    }
};

/**
 * Called internally whenever the upload might be complete.
 * If the upload is complete it will call _user_ready, if not it will attempt to upload from where it left off.
 *
 * Do not call this outside of the library.
 */
FileStreamer.prototype._ready = function () {
    var _self = this;

    // If we think we are ready to complete, check with the server and see if they have the whole file
    this._getNewStart(function (err, start) {
        if (err) {
            // If the check fails, close the file and error out immediately
            _self._cleanupFds();
            return _self._error(err);
        }

        if (start >= _self._file_size) {
            // If the server says they have the whole file, close it and then return back to the user
            _self._cleanupFds();
            _self._user_ready();
        } else {
            // If the server does not have the whole file, upload from where we left off
            _self._streamChunk(start);
        }
    });
};

/**
 * Assign a callback to be called whenever the file is done uploading.
 *
 * @param  {Function} fn The ready callback
 */
FileStreamer.prototype.ready = function (fn) {
    this._user_ready = fn;
};

/**
 * Holds the error callback. Do not call this outside of the library
 *
 * @param  {Error} error The error that was thrown
 * @return {[type]}       [description]
 */
FileStreamer.prototype._error = function (error) {
    this.error = function (fn) {
        fn(error);
    };
};

/**
 * Assign a callback to be called whenever an error occurs.
 *
 * @param  {Function} fn The error callback
 */
FileStreamer.prototype.error = function (fn) {
    this._error = fn;
};

/**
 * Start uploading the file
 */
FileStreamer.prototype.upload = function () {
    var _self = this;

    fs_module.stat(_self._path, function (stat_err, stats) {
        if (stat_err) {
            return _self._error(stat_err);
        }

        _self._file_size = stats.size;

        fs_module.open(_self._path, 'r', function(open_err, fd) {
            if (open_err) {
                return _self._error(open_err);
            }

            _self._fd = fd;
            _self._streamChunk(0);
        });
    });
};

/**
 * Send a file chunk, starting at byte [start] and ending at the end of the file
 *
 * @param  {Number} start
 */
FileStreamer.prototype._streamChunk = function (start) {
    var _self = this;

    _self._sentBytes = start
    _self._putFile(start, function (put_err, code, headers) {

        // Catches a rare vimeo server bug and exits out early
        if (put_err && code && ++_self._streamUploadMaxErrors >= 10) {
            _self._cleanupFds();
            return _self._error(new Error(put_err.message + " streamErrors: 10, successfulBytes: " + _self._sentBytes));
        }

        _self._ready();
    });
};

/**
 * Make the HTTP put request sending a part of a file up to the upload server
 *
 * @param  {Number}   start    The first byte of the file
 * @param  {Function} callback A function which is called once the upload is complete, or has failed
 */
FileStreamer.prototype._putFile = function (start, callback) {
    var _self = this;

    // cleanup any remaining read stream file descriptor
    this._closeReadStreamFd();

    var file = fs_module.createReadStream(_self._path, {
        start : start,
        autoClose: true
    });

    file.on('open', function (fd) {
       _self._readStreamFd = fd;
    });

    file.on('error', function (err) {
        callback(err);
    });

    var uploaded_size = start || 0;

    file.on('data', function(chunk) {
        uploaded_size += chunk.length || 0;
        if (_self.progress_callback) {
            _self.progress_callback(uploaded_size, _self._file_size);
        }
    });

    var headers =  {
        'Content-Length' : _self._file_size,
        'Content-Type' : 'video/mp4'
    };

    headers['Content-Range'] = 'bytes ' + start + '-' + _self._file_size + '/' + _self._file_size;

    var req = _self._upload_endpoint_request({
        method : 'PUT',
        headers : headers
    }, callback);

    file.pipe(req);
};

FileStreamer.prototype._cleanupFds = function () {
    this._closeFile();
    this._closeReadStreamFd();
};

/**
 * Cleanup the read stream of the file, if there's still one
 */
FileStreamer.prototype._closeReadStreamFd = function () {
    if (this._readStreamFd) {
        fs_module.close(this._readStreamFd, function (e) {});
        this._readStreamFd = null;
    }
};

/**
 * Close the file
 */
FileStreamer.prototype._closeFile = function () {
    if (this._fd) {
        fs_module.close(this._fd, function (e) {});
        this._fd = null;
    }
};

/**
 * Verify the file upload and determine the last most byte the server has received
 * @param  {Function} next A callback that will be called when the check is complete, or has errored
 */
FileStreamer.prototype._getNewStart = function (next) {
    var _self = this;

    this._upload_endpoint_request({
        method : 'PUT',
        headers : {
            'Content-Range' : 'bytes */*',
            'Content-Type' : 'application/octet-stream'
        }
    }, function (err, status, headers) {
        if (err) {
            return next(new Error('Error when getting new start:' + err.message));
        }

        if (status === 308) {
            return next(null, parseInt(headers.range.split('-')[1] + 1));
        } else {
            return next(new Error('Invalid http status returned from range query: [' + status + ']'));
        }
    }).end();
};

/**
 * Makes an http request to the upload server, and sends the response through the callback
 *
 * @param  {Object}   options  Request options, pumped into https.request(options);
 * @param  {Function} callback Called when the upload is complete, or has failed
 */
FileStreamer.prototype._upload_endpoint_request = function (options, callback) {
    var request_options = {
        protocol : this._endpoint.protocol,
        host : this._endpoint.hostname,
        port : this._endpoint.port,
        query : this._endpoint.query,
        headers : options.headers,
        path : this._endpoint.path,
        method : options.method
    };

    var client = request_options.protocol === 'https:' ? https_module : http_module;
    var req = client.request(request_options);

    req.on('response', function (res) {
        res.setEncoding('utf8');

        var buffer = '';
        res.on('readable', function () {
            buffer += res.read();
        });

        if (res.statusCode > 399) {
            // failed api calls should wait for the response to end and then call the callback with an error.
            res.on('end', function () {
                callback(new Error('[' + buffer + ']'), res.statusCode, res.headers);
            });
        } else {
            // successful api calls should wait for the response to end and then call the callback with the response body
            res.on('end', function () {
                callback(null, res.statusCode, res.headers);
            });
        }
    });

    // notify user of any weird connection/request errors
    req.on('error', function(e) {
        callback(e);
    });

    return req;
};
<|endoftext|>


<commit_before>/* BOF */
;
DOMPurify = {};
DOMPurify.sanitize = function(dirty, cfg){

  /******* /***************************************************************
   ****** / * Don't allow script elements. Or event handlers.             *
   ***** /  * And careful with SVG's "values" attribute.                  *
   **** /   * Other than that, you can basically allow whatever you want. *
   *** /    * We'll make it safe for you.                                 *
   ** / *******************************************************************
   * /
    /* allowed element names */
    var ALLOWED_TAGS = [

        // HTML
        'a','abbr','acronym','address','area','article','aside','audio','b',
        'bdi','bdo','big','blink','blockquote','body','br','button','canvas',
        'caption','center','cite','code','col','colgroup','content','data',
        'datalist','dd','decorator','del','details','dfn','dir','div','dl','dt',
        'element','em','fieldset','figcaption','figure','font','footer','form',
        'h1','h2','h3','h4','h5','h6','header','hgroup','hr','html','i','img',
        'input','ins','kbd','label','legend','li','main','map','mark','marquee',
        'menu','menuitem','meter','nav','nobr','ol','optgroup','option','output'
        ,'p','pre','progress','q','rp','rt','ruby','s','samp','section',
        'select','shadow','small','source','spacer','span','strike','strong',
        'style','sub','summary','sup','table','tbody','td','template',
        'textarea','tfoot','th','thead','time','tr','track','tt','u','ul','var',
        'video','wbr',

        // SVG
        'svg','altglyph','altglyphdef','altglyphitem','animatecolor',
        'animatemotion','animatetransform','circle','clippath','defs','desc',
        'ellipse','font','g','glyph','glyphref','hkern','image','line',
        'lineargradient','marker','mask','metadata','mpath','path','pattern',
        'polygon','polyline','radialgradient','rect','stop','switch','symbol',
        'text','textpath','title','tref','tspan','view','vkern',

        //MathML
        'math','menclose','merror','mfenced','mfrac','mglyph','mi','mlabeledtr',
        'mmuliscripts','mn','mo','mover','mpadded','mphantom','mroot','mrow',
        'ms','mpspace','msqrt','mystyle','msub','msup','msubsup','mtable','mtd',
        'mtext','mtr','munder','munderover'
    ];

    /* Decide if custom data attributes are okay */
    var ALLOW_DATA_ATTRIBUTES = true;

    /* Output should be safe for jQuery's $() factory? */
    var SAFE_FOR_JQUERY = true;

    /* Allowed attribute names */
    var ALLOWED_ATTR = [

        // HTML
        'name', 'id','href','action','class','title','alt','src', 'type',
        'height','width', 'method','rev','rel','accept','align','autocomplete',
        'xmlns','bgcolor','border','checked','cite','color','cols','colspan',
        'coords','datetime','default','dir','disabled','download','enctype',
        'for','headers','hidden','high','hreflang','ismap','label','lang',
        'list','loop', 'low','max','maxlength','media','min','multiple',
        'novalidate','open','optimum','pattern','placeholder','poster',
        'preload','pubdate','radiogroup','readonly','required','reversed',
        'rows','rowspan','spellcheck','scope','selected','shape','size','span',
        'srclang','start','step','style','summary','tabindex','usemap','value',

        // SVG
        'wrap','clip','cx','cy','d','dy','dy','in','in2','k1','k2','k3','k4',
        'mask','mode','opacity','order','overflow','path','points','radius',
        'rx','ry','scale','stroke','stroke-width','transform','u1','u2','r','x',
        'y','x1','viewbox','x2','y1','y2','z','fill',

        // MathML
        'accent','accentunder','bevelled','close','columnsalign','columnlines',
        'columnspan','denomalign','depth','display','displaystyle','fence',
        'frame','largeop','length','linethickness','lspace','lquote',
        'mathbackground','mathcolor','mathsize','mathvariant','maxsize',
        'minsize','movablelimits','notation','numalign','open','rowalign',
        'rowlines','rowspacing','rowspan','rspace','rquote','scriptlevel',
        'scriptminsize','scriptsizemultiplier','selection','separator',
        'separators','stretchy','subscriptshift','supscriptshift','symmetric',
        'voffset'
    ];

    /* Ideally, do not touch anything below this line */
    /* ______________________________________________ */

   /**
    * _parseConfig
    *
    * @param  optional config literal
    */
    var _parseConfig = function(cfg){
        cfg.ALLOWED_ATTR ? ALLOWED_ATTR = cfg.ALLOWED_ATTR : null;
        cfg.ALLOWED_TAGS ? ALLOWED_TAGS = cfg.ALLOWED_TAGS : null;
        cfg.ALLOW_DATA_ATTR ? ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR : null;
        cfg.SAFE_FOR_JQUERY ? SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY : null;
    }

    /**
     * _createIterator
     *
     * @param  document/fragment to create iterator for
     * @return iterator instance
     */
    var _createIterator = function(doc){
        return document.createNodeIterator(
            doc, 129, function() { return NodeFilter.FILTER_ACCEPT }, false
        );
    }

    /**
     * _isClobbered
     *
     * @param  element to check for clobbering attacks
     * @return true if clobbered, false if safe
     */
    var _isClobbered = function(elm){
        if((elm.children && !(elm.children instanceof HTMLCollection))
            || typeof elm.nodeName !== 'string'
            || typeof elm.textContent !== 'string'
            || typeof elm.nodeType !== 'number'
            || typeof elm.setAttribute !== 'function'
            || typeof elm.removeAttributeNode !== 'function'
            || typeof elm.attributes.item !== 'function'){
            return true;
        }
        return false;
    }

    /**
     * _sanitizeElements
     *
     * @protect removeChild
     * @protect nodeType
     * @protect nodeName
     * @protect textContent
     * @protect currentNode
     *
     * @param   node to check for permission to exist
     * @return  true if node was killed, false if left alive
     */
    var _sanitizeElements = function(currentNode){
        if(_isClobbered(currentNode) || currentNode.nodeType === 8
                || ALLOWED_TAGS.indexOf(currentNode.nodeName.toLowerCase()
            ) === -1) {
            currentNode.parentNode.removeChild(currentNode);
            return true;
        }
        if(SAFE_FOR_JQUERY && !currentNode.firstElementChild){
            currentNode.textContent
                = currentNode.textContent.replace(/\/+>/g, '>');
        }
        return false;
    }

    /**
     * _sanitizeAttributes
     *
     * @protect attributes
     * @protect removeAttribiuteNode
     * @protect setAttribute
     *
     * @param   node to sanitize
     * @return  void
     */
    var _sanitizeAttributes = function(currentNode){
        var regex = /^(\w+script|data):/gi;
        for(var attr = currentNode.attributes.length-1; attr>=0; attr--){
            var tmp  = currentNode.attributes[attr];
            currentNode.removeAttribute(currentNode.attributes[attr].name);
            if(tmp instanceof Attr) {
                if((ALLOWED_ATTR.indexOf(tmp.name.toLowerCase()) > -1 ||
                 (ALLOW_DATA_ATTRIBUTES && tmp.name.match(/^data-[\w-]+/i)))
                    && !tmp.value.replace(/[\x00-\x20]/g,'').match(regex)) {
                    currentNode.setAttribute(tmp.name, tmp.value);
                }
            }
        }
    }

    /**
     * _sanitizeShadowDOM
     *
     * @param  fragment to iterate over recursively
     * @return void
     */
    var _sanitizeShadowDOM = function(fragment){
        var shadowNode;
        var shadowIterator = _createIterator(fragment);
        while(shadowNode   = shadowIterator.nextNode()) {
            /* Sanitize tags and elements */
            if(_sanitizeElements(shadowNode)){
                continue;
            }
            /* Deep shadow DOM detected */
            if(shadowNode.content instanceof DocumentFragment){
                _sanitizeShadowDOM(shadowNode.content);

            }
            /* Check attributes, sanitize if necessary */
            _sanitizeAttributes(shadowNode);
        }
    }

    /* Assign config vars */
    cfg ? _parseConfig(cfg) : null;

    /* Create documents to map markup to */
    var dom = document.implementation.createHTMLDocument('');
        dom.body.outerHTML=dirty;
        var body = dom.body;
    if(!(dom.body instanceof HTMLBodyElement)){
        var freshdom = document.implementation.createHTMLDocument('');
        body = freshdom.getElementsByTagName.call(dom,'body')[0];
    }

    /* Get node iterator */
    var currentNode;
    var nodeIterator = _createIterator(body);

    /* Now start iterating over the created document */
    while(currentNode = nodeIterator.nextNode()) {
        /* Sanitize tags and elements */
        if(_sanitizeElements(currentNode)){
            continue;
        }
        /* Shadow DOM detected, sanitize it */
        if(currentNode.content instanceof DocumentFragment){
            _sanitizeShadowDOM(currentNode.content);
        }
        /* Check attributes, sanitize if necessary */
        _sanitizeAttributes(currentNode);
    }

    /* Serialize sanitized document, return a string */
    return body.innerHTML;
};
/* EOF */<commit_msg># fixed a label<commit_after>/* BOF */
;
DOMPurify = {};
DOMPurify.sanitize = function(dirty, cfg){

  /******* /***************************************************************
   ****** / * Don't allow script elements. Or event handlers.             *
   ***** /  * And careful with SVG's "values" attribute.                  *
   **** /   * Other than that, you can basically allow whatever you want. *
   *** /    * We'll make it safe for you.                                 *
   ** / *******************************************************************
   * /
    /* allowed element names */
    var ALLOWED_TAGS = [

        // HTML
        'a','abbr','acronym','address','area','article','aside','audio','b',
        'bdi','bdo','big','blink','blockquote','body','br','button','canvas',
        'caption','center','cite','code','col','colgroup','content','data',
        'datalist','dd','decorator','del','details','dfn','dir','div','dl','dt',
        'element','em','fieldset','figcaption','figure','font','footer','form',
        'h1','h2','h3','h4','h5','h6','header','hgroup','hr','html','i','img',
        'input','ins','kbd','label','legend','li','main','map','mark','marquee',
        'menu','menuitem','meter','nav','nobr','ol','optgroup','option','output'
        ,'p','pre','progress','q','rp','rt','ruby','s','samp','section',
        'select','shadow','small','source','spacer','span','strike','strong',
        'style','sub','summary','sup','table','tbody','td','template',
        'textarea','tfoot','th','thead','time','tr','track','tt','u','ul','var',
        'video','wbr',

        // SVG
        'svg','altglyph','altglyphdef','altglyphitem','animatecolor',
        'animatemotion','animatetransform','circle','clippath','defs','desc',
        'ellipse','font','g','glyph','glyphref','hkern','image','line',
        'lineargradient','marker','mask','metadata','mpath','path','pattern',
        'polygon','polyline','radialgradient','rect','stop','switch','symbol',
        'text','textpath','title','tref','tspan','view','vkern',

        //MathML
        'math','menclose','merror','mfenced','mfrac','mglyph','mi','mlabeledtr',
        'mmuliscripts','mn','mo','mover','mpadded','mphantom','mroot','mrow',
        'ms','mpspace','msqrt','mystyle','msub','msup','msubsup','mtable','mtd',
        'mtext','mtr','munder','munderover'
    ];

    /* Decide if custom data attributes are okay */
    var ALLOW_DATA_ATTR = true;

    /* Output should be safe for jQuery's $() factory? */
    var SAFE_FOR_JQUERY = true;

    /* Allowed attribute names */
    var ALLOWED_ATTR = [

        // HTML
        'name', 'id','href','action','class','title','alt','src', 'type',
        'height','width', 'method','rev','rel','accept','align','autocomplete',
        'xmlns','bgcolor','border','checked','cite','color','cols','colspan',
        'coords','datetime','default','dir','disabled','download','enctype',
        'for','headers','hidden','high','hreflang','ismap','label','lang',
        'list','loop', 'low','max','maxlength','media','min','multiple',
        'novalidate','open','optimum','pattern','placeholder','poster',
        'preload','pubdate','radiogroup','readonly','required','reversed',
        'rows','rowspan','spellcheck','scope','selected','shape','size','span',
        'srclang','start','step','style','summary','tabindex','usemap','value',

        // SVG
        'wrap','clip','cx','cy','d','dy','dy','in','in2','k1','k2','k3','k4',
        'mask','mode','opacity','order','overflow','path','points','radius',
        'rx','ry','scale','stroke','stroke-width','transform','u1','u2','r','x',
        'y','x1','viewbox','x2','y1','y2','z','fill',

        // MathML
        'accent','accentunder','bevelled','close','columnsalign','columnlines',
        'columnspan','denomalign','depth','display','displaystyle','fence',
        'frame','largeop','length','linethickness','lspace','lquote',
        'mathbackground','mathcolor','mathsize','mathvariant','maxsize',
        'minsize','movablelimits','notation','numalign','open','rowalign',
        'rowlines','rowspacing','rowspan','rspace','rquote','scriptlevel',
        'scriptminsize','scriptsizemultiplier','selection','separator',
        'separators','stretchy','subscriptshift','supscriptshift','symmetric',
        'voffset'
    ];

    /* Ideally, do not touch anything below this line */
    /* ______________________________________________ */

   /**
    * _parseConfig
    *
    * @param  optional config literal
    */
    var _parseConfig = function(cfg){
        cfg.ALLOWED_ATTR ? ALLOWED_ATTR = cfg.ALLOWED_ATTR : null;
        cfg.ALLOWED_TAGS ? ALLOWED_TAGS = cfg.ALLOWED_TAGS : null;
        cfg.ALLOW_DATA_ATTR ? ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR : null;
        cfg.SAFE_FOR_JQUERY ? SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY : null;
    }

    /**
     * _createIterator
     *
     * @param  document/fragment to create iterator for
     * @return iterator instance
     */
    var _createIterator = function(doc){
        return document.createNodeIterator(
            doc, 129, function() { return NodeFilter.FILTER_ACCEPT }, false
        );
    }

    /**
     * _isClobbered
     *
     * @param  element to check for clobbering attacks
     * @return true if clobbered, false if safe
     */
    var _isClobbered = function(elm){
        if((elm.children && !(elm.children instanceof HTMLCollection))
            || typeof elm.nodeName !== 'string'
            || typeof elm.textContent !== 'string'
            || typeof elm.nodeType !== 'number'
            || typeof elm.setAttribute !== 'function'
            || typeof elm.removeAttributeNode !== 'function'
            || typeof elm.attributes.item !== 'function'){
            return true;
        }
        return false;
    }

    /**
     * _sanitizeElements
     *
     * @protect removeChild
     * @protect nodeType
     * @protect nodeName
     * @protect textContent
     * @protect currentNode
     *
     * @param   node to check for permission to exist
     * @return  true if node was killed, false if left alive
     */
    var _sanitizeElements = function(currentNode){
        if(_isClobbered(currentNode) || currentNode.nodeType === 8
                || ALLOWED_TAGS.indexOf(currentNode.nodeName.toLowerCase()
            ) === -1) {
            currentNode.parentNode.removeChild(currentNode);
            return true;
        }
        if(SAFE_FOR_JQUERY && !currentNode.firstElementChild){
            currentNode.textContent
                = currentNode.textContent.replace(/\/+>/g, '>');
        }
        return false;
    }

    /**
     * _sanitizeAttributes
     *
     * @protect attributes
     * @protect removeAttribiuteNode
     * @protect setAttribute
     *
     * @param   node to sanitize
     * @return  void
     */
    var _sanitizeAttributes = function(currentNode){
        var regex = /^(\w+script|data):/gi;
        for(var attr = currentNode.attributes.length-1; attr>=0; attr--){
            var tmp  = currentNode.attributes[attr];
            currentNode.removeAttribute(currentNode.attributes[attr].name);
            if(tmp instanceof Attr) {
                if((ALLOWED_ATTR.indexOf(tmp.name.toLowerCase()) > -1 ||
                 (ALLOW_DATA_ATTR && tmp.name.match(/^data-[\w-]+/i)))
                    && !tmp.value.replace(/[\x00-\x20]/g,'').match(regex)) {
                    currentNode.setAttribute(tmp.name, tmp.value);
                }
            }
        }
    }

    /**
     * _sanitizeShadowDOM
     *
     * @param  fragment to iterate over recursively
     * @return void
     */
    var _sanitizeShadowDOM = function(fragment){
        var shadowNode;
        var shadowIterator = _createIterator(fragment);
        while(shadowNode   = shadowIterator.nextNode()) {
            /* Sanitize tags and elements */
            if(_sanitizeElements(shadowNode)){
                continue;
            }
            /* Deep shadow DOM detected */
            if(shadowNode.content instanceof DocumentFragment){
                _sanitizeShadowDOM(shadowNode.content);

            }
            /* Check attributes, sanitize if necessary */
            _sanitizeAttributes(shadowNode);
        }
    }

    /* Assign config vars */
    cfg ? _parseConfig(cfg) : null;

    /* Create documents to map markup to */
    var dom = document.implementation.createHTMLDocument('');
        dom.body.outerHTML=dirty;
        var body = dom.body;
    if(!(dom.body instanceof HTMLBodyElement)){
        var freshdom = document.implementation.createHTMLDocument('');
        body = freshdom.getElementsByTagName.call(dom,'body')[0];
    }

    /* Get node iterator */
    var currentNode;
    var nodeIterator = _createIterator(body);

    /* Now start iterating over the created document */
    while(currentNode = nodeIterator.nextNode()) {
        /* Sanitize tags and elements */
        if(_sanitizeElements(currentNode)){
            continue;
        }
        /* Shadow DOM detected, sanitize it */
        if(currentNode.content instanceof DocumentFragment){
            _sanitizeShadowDOM(currentNode.content);
        }
        /* Check attributes, sanitize if necessary */
        _sanitizeAttributes(currentNode);
    }

    /* Serialize sanitized document, return a string */
    return body.innerHTML;
};
/* EOF */<|endoftext|>


<commit_before>var cheerio = require('cheerio');
var urllib = require('url');
var colors = require('colors');
var fs = require('fs');

var program = require('commander');
program
  .version('0.2.4')
  .option('-d, --directory <directory>', 'specify the fetch directory,',
          String, 'fetch/')
  .option('-r, --urlregexp <urlregexp>', 'an expression that matches the URLs to follow',
          String, '^n')
  .option('-s, --starturl <starturl>',
          'specify the relative URL path to start fetching from',
          String, '/')
  .parse(process.argv);

var directory = program.directory;
if (directory.slice(-1) != '/')
  directory += '/';
if (!fs.existsSync(directory)) { // or fs.existsSync
  fs.mkdirSync(directory);
}

var startURL = program.starturl;
var host = program.hostname;
var discoveredURLs = [startURL];
var crawledURLs = [];

function skipping (statusCode, contentType, url) {
  console.log(statusCode.toString().magenta + ' ' + contentType
              + ': ' + url.toString().red + ' (SKIPPING)'.red);
}

function download(url, callback) {
//  console.log(url);
  var urlBits = urllib.parse(url);
  var protolib;
  debugger;
  if (urlBits.protocol == 'https:') {
    protolib = require('https');
  }
  else
    protolib = require('http');

  protolib.get(url, function(res) {
    if (res.statusCode != '200') {
      skipping(res.statusCode, res.headers['content-type'], url);
      callback(null);
    }
    else if (!res.headers['content-type']) {
      skipping(res.statusCode, 'no content type', url);
      callback(null);
    }
    else if (res.headers['content-type'].indexOf('html') == -1) {
      skipping(res.statusCode, res.headers['content-type'], url);
      callback(null);
    }
    else {
      var data = '';
      res.on('data', function (chunk) {
        data += chunk;
      });
      res.on('end', function() {
        console.log(res.statusCode.toString().magenta
                    + ' ' + res.headers["content-type"]
                    + ': ' + url.toString().green);
        callback(data);
      });
    }
  }).on("error", function() {
    callback(null);
  });
}

crawlPage = function(url) {
  download(url, function(data) {
    if (data) {
      var $ = cheerio.load(data);
      $("a").each(function(i, e) {
        var link = $(e);
        if (!link.attr('href'))
          return
        var thisURL = relToAbs(url, link.attr('href'));
        if (crawledURLs.indexOf(thisURL) != -1)
          return
//        console.log(thisURL);
        crawledURLs.push(thisURL);
        discoveredURLs.push(thisURL);
      });
      fs.writeFile(program.directory + encodeURIComponent(url), data, function(err) {
        if(err) {
          console.log(err);
        } else {
          //success
        }
      });
    }
    if (discoveredURLs.length > 0) {
      var nextUrl = discoveredURLs.shift();
      if (regexpIsTrue(nextUrl))
        crawlPage(nextUrl);
    }
    else
      console.log('finished fetch');
  });
}

regexpIsTrue = function(url) {
  var r = new RegExp(program.urlregexp);
  console.log('regexp ' + program.urlregexp + ' on ' + url + ' is ' + r.test(url));
  if (r.test(url)) return true
  else return false
}

function relToAbs(loc, url){
    /* Only accept commonly trusted protocols:
     * Only data-image URLs are accepted, Exotic flavours (escaped
     /* slash,
     * html-entitied characters) are not supported to keep the
     /* function fast */
  if(/^(https?|file|ftps?|mailto|javascript|data:image\/[^;]{2,9};):/i.test(url))
    return url; //Url is already absolute
  var location = urllib.parse(loc);
  var base_url = loc;
  if(url.substring(0,2) == "//")
    return location.protocol + url;
  else if(url.charAt(0) == "/")
    return location.protocol + "//" + location.host + url;
  else if(url.substring(0,2) == "./")
    url = "." + url;
  else if(/^\s*$/.test(url))
    return ""; //Empty = Return nothing
  else url = "../" + url;
  url = base_url + url;
    var i=0
  while(/\/\.\.\//.test(url = url.replace(/[^\/]+\/+\.\.\//g,"")));
  /* Escape certain characters to prevent XSS */
  url = url.replace(/\.$/,"").replace(/\/\./g,"").replace(/"/g,"%22")
            .replace(/'/g,"%27").replace(/</g,"%3C").replace(/>/g,"%3E");
    return url;
}

//console.log(startURL);

crawlPage(startURL);

<commit_msg>added regexp support<commit_after>var cheerio = require('cheerio');
var urllib = require('url');
var colors = require('colors');
var fs = require('fs');

var program = require('commander');
program
  .version('0.2.4')
  .option('-d, --directory <directory>', 'specify the fetch directory,',
          String, 'fetch/')
  .option('-r, --urlregexp <urlregexp>', 'an expression that matches the URLs to follow',
          String, '^n')
  .option('-s, --starturl <starturl>',
          'specify the relative URL path to start fetching from',
          String, '/')
  .parse(process.argv);

var directory = program.directory;
if (directory.slice(-1) != '/')
  directory += '/';
if (!fs.existsSync(directory)) { // or fs.existsSync
  fs.mkdirSync(directory);
}

var startURL = program.starturl;
var host = program.hostname;
var discoveredURLs = [];
var crawledURLs = [];

function skipping (statusCode, contentType, url) {
  console.log(statusCode.toString().magenta + ' ' + contentType
              + ': ' + url.toString().red + ' (SKIPPING)'.red);
}

function download(url, callback) {
//  console.log(url);
  var urlBits = urllib.parse(url);
  var protolib;
  debugger;
  if (urlBits.protocol == 'https:') {
    protolib = require('https');
  }
  else
    protolib = require('http');

  protolib.get(url, function(res) {
    if (res.statusCode != '200') {
      skipping(res.statusCode, res.headers['content-type'], url);
      callback(null);
    }
    else if (!res.headers['content-type']) {
      skipping(res.statusCode, 'no content type', url);
      callback(null);
    }
    else if (res.headers['content-type'].indexOf('html') == -1) {
      skipping(res.statusCode, res.headers['content-type'], url);
      callback(null);
    }
    else {
      var data = '';
      res.on('data', function (chunk) {
        data += chunk;
      });
      res.on('end', function() {
        console.log(res.statusCode.toString().magenta
                    + ' ' + res.headers["content-type"]
                    + ': ' + url.toString().green);
        callback(data);
      });
    }
  }).on("error", function() {
    callback(null);
  });
}

crawlPage = function(url) {
  //startup doesnt have to abide by the regexp filter
  if ((!regexpIsTrue(url)) && (url != program.starturl)) {
    if (discoveredURLs.length > 0)
      crawlPage(discoveredURLs.shift());
    else
      console.log('finished fetch');
  }
  else {
    download(url, function(data) {
      if (data) {
        var $ = cheerio.load(data);
        $("a").each(function(i, e) {
          var link = $(e);
          if (!link.attr('href'))
            return
          var thisURL = relToAbs(url, link.attr('href'));
          if (crawledURLs.indexOf(thisURL) != -1)
            return
//          console.log(thisURL);
          crawledURLs.push(thisURL);
          if (thisURL != program.starturl)
          discoveredURLs.push(thisURL);
        });
        fs.writeFile(program.directory + encodeURIComponent(url), data, function(err) {
          if(err) {
            console.log(err);
          } else {
            //success
          }
        });
      }
      if (discoveredURLs.length > 0)
        crawlPage(discoveredURLs.shift());
      else
        console.log('finished fetch');
    });
  }
}

regexpIsTrue = function(url) {
  var r = new RegExp(program.urlregexp);
//  console.log('regexp ' + program.urlregexp + ' on ' + url + ' is ' + r.test(url));
  if (r.test(url)) return true
  else return false
}

function relToAbs(loc, url){
    /* Only accept commonly trusted protocols:
     * Only data-image URLs are accepted, Exotic flavours (escaped
     /* slash,
     * html-entitied characters) are not supported to keep the
     /* function fast */
  if(/^(https?|\/[^;]{2,9};):/i.test(url))
    return url; //Url is already absolute
  var location = urllib.parse(loc);
  var base_url = loc;
  if(url.substring(0,2) == "//")
    return location.protocol + url;
  else if(url.charAt(0) == "/")
    return location.protocol + "//" + location.host + url;
  else if(url.substring(0,2) == "./")
    url = "." + url;
  else if(/^\s*$/.test(url))
    return ""; //Empty = Return nothing
  else url = "../" + url;
  url = base_url + url;
    var i=0
  while(/\/\.\.\//.test(url = url.replace(/[^\/]+\/+\.\.\//g,"")));
  /* Escape certain characters to prevent XSS */
  url = url.replace(/\.$/,"").replace(/\/\./g,"").replace(/"/g,"%22")
            .replace(/'/g,"%27").replace(/</g,"%3C").replace(/>/g,"%3E");
    return url;
}

//console.log(startURL);

crawlPage(startURL);

<|endoftext|>