<commit_before>var config = require('./config.js');
var ip = config.ip;
var port = config.port;
var express = require('express');
var app = express();
var server = app.listen(port);
var ejs = require('ejs');
var bbcode = require('bbcode');
var io = require('socket.io').listen(server);
io.set('log level', 1);
var sys = require('sys')
var exec = require('child_process').exec;

app.set("view options", {layout: false});
app.use(express.static(__dirname + '/public'));

process.on('SIGINT', function() {
  console.log( "\nShutting down from manual SIGINT (Ctrl-C), NOW." );
  io.sockets.emit('annouce', {message : 'SHUTTING DOWN, NOW!'});
  process.exit();
});

process.once('SIGUSR2', function () {
  gracefulShutdown(function () {
    process.kill(process.pid, 'SIGUSR2');
  });
});

function gracefulShutdown(kill){
  console.log( "\nShutting down from nodemon SIGUSR2 (RESTART) in 10 seconds..." );
  io.sockets.emit('annouce', {message : 'RESTARTING IN 10 SECONDS!'});
  setTimeout(function(){kill()}, 10000);
}

app.post('/gitpull', function(req, res) {
  //GitHub push hook
  res.end();
  function puts(error, stdout, stderr) {sys.puts(stdout)}
  exec("git reset --hard HEAD", puts);
  exec("git pull", puts);
});

app.get('*', function(req, res) {
  res.render('index.ejs', {
   ip: ip
 });
});

var users = [];

process.stdin.resume();
process.stdin.setEncoding('utf8');

process.stdin.on('data', function (chunk) {
 io.sockets.emit('annouce', {message : '' + chunk.toUpperCase() + ''});
});

io.sockets.on('connection', function (socket) {
  function broadcast(data) {
    io.sockets.emit('annouce', {message : data});
  }

  function parseServerCommand(data) {
    var res = data.message.trim().split(" ");

    if(res[0].toLowerCase() == "/nick"){
      updateName(res.slice(1,res.length).join(' '));
      return;
    }

    if(res[0].toLowerCase() == "/pm"){
      if(res.length >= 3){
        if(res[1] == 'SERVER'){
          var help = "You cannot PM the server.";
          socket.emit('annouce', {message : help});
          return;
        }
        if(findUser(res[1])){
          pm(res[1], res.slice(2, res.length).join(' '));
          return;
        } else if (findUser(res.slice(1 ,3).join(' '))){
          pm(res.slice(1 ,3).join(' '), res.slice(3, res.length).join(' '));
          return;
        } else {
          var help = "User not found for command '" + res.join(' ') + "'";
          socket.emit('annouce', {message : help});
        }
      } else {
          var help = "You must add a PM message.";
          socket.emit('annouce', {message : help});
      }
    }

    if(res[0].toLowerCase() == "/disconnect"){
      socket.disconnect();
    }

    if(res[0].toLowerCase() == "/help"){
      sendHelp();
      return;
    }

    unrecognized(res[0]);
    sendHelp();
  }

  var entityMap = {
    "&": "&",
    "<": "<",
    ">": ">",
    '"': '"',
    "'": ''',
    "/": '/'
  };

  function escapeHtml(string) {
    return String(string).replace(/[&<>"'\/]/g, function (s) {
      return entityMap[s];
    });
  }

  function removeItem(arr, item) {
    for(var i = arr.length; i--;) {
      if(arr[i][0].toString() === item[0].toString()) {
        arr.splice(i, 1);
      }
    }
  }

  function findUser(user) {
    for(var i = users.length; i--;) {
      if(users[i][0] == user) {
        return true;
      }
    }
    return false;
  }

  function findSocket(user) {
    for(var i = users.length; i--;) {
      if(users[i][0] == user) {
        return users[i][1];
      }
    }
    return 0;
  }

  function pm(dest, data){
    if(dest == name){
      var help = "You cannot PM yourself.";
      socket.emit('annouce', {message : help});
      return;
    }
    data = '<to ' + dest + '> ' + data + '</span';
    io.sockets.socket(findSocket(dest)).emit('broadcast', {client : name, message : data});
    socket.emit('broadcast', {client : name, message : data});
  }

  function updateName(data){
    if(findUser(data)){
      socket.emit('annouce', {message : "The nick '" + data + "' is taken!"});
      return;
    }
    if(data.toLowerCase() == "admin" || data.toLowerCase() == "server"){
      socket.emit('annouce', {message : "That nick is reserved!"});
      return;
    }
    oldName = name;
    name = data;
    removeItem(users, [oldName, socket.id]);
    users.push([name, socket.id, true]);
    io.sockets.emit('users', users);
    socket.emit('name', {name : name});
    broadcast('' + oldName + ' has changed name to ' + data + '.');
  }

  function disconnect(data){
    socket.disconnect();
  }

  function unrecognized(data){
    var help = "Unknown command '" + data + "'.";
    socket.emit('annouce', {message : help});
  }

  function sendHelp(){
    var help = "HardOrange IRC Help - Commands:
/nick nick
/pm nick message
/clear
/disconnect
/help";
    socket.emit('annouce', {message : help});
  }

  function multiArrayIndex(arr, item){
    for(var i = 0; i < arr.length; i++) {
      if(arr[i].toString() == item.toString()) {
          return i;
       }
     }
  }

  //Set name and notify clients
  sendHelp();
  var name = 'Guest' + Math.floor(100 + Math.random() * 900);
  broadcast('' + name + ' has entered chat.');
  users.push([name, socket.id, true]);
  io.sockets.emit('users', users);
  socket.emit('name', {name : name});

  //Begin Handlers
  socket.on('broadcast', function (data) {
    if(data.message[0] == "/") {
      parseServerCommand(data);
    } else {
      bbcode.parse(escapeHtml(data.message), function(content){
        io.sockets.emit('broadcast', {client : name, message : content});
      });
    }
  });

  socket.on('status', function (data) {
    var index = multiArrayIndex(users, [name, socket.id, !data.status]);
    if(index === undefined){console.log('missing user');console.log(data);return;}
    users[index][2] = data.status;
    io.sockets.emit('users', users);
  });

  socket.on('disconnect', function (data) {
    removeItem(users, [name, socket.id]);
    io.sockets.emit('users', users);
    broadcast('' + name + ' has exited chat.');
  });
});
<commit_msg>Extended info<commit_after>var config = require('./config.js');
var ip = config.ip;
var port = config.port;
var express = require('express');
var app = express();
var server = app.listen(port);
var ejs = require('ejs');
var bbcode = require('bbcode');
var io = require('socket.io').listen(server);
io.set('log level', 1);
var sys = require('sys')
var exec = require('child_process').exec;

app.set("view options", {layout: false});
app.use(express.static(__dirname + '/public'));

process.on('SIGINT', function() {
  console.log( "\nShutting down from manual SIGINT (Ctrl-C), NOW." );
  io.sockets.emit('annouce', {message : 'SHUTTING DOWN, NOW!'});
  process.exit();
});

process.once('SIGUSR2', function () {
  gracefulShutdown(function () {
    process.kill(process.pid, 'SIGUSR2');
  });
});

function gracefulShutdown(kill){
  console.log( "\nShutting down from nodemon SIGUSR2 (RESTART) in 10 seconds..." );
  io.sockets.emit('annouce', {message : 'RESTARTING IN 10 SECONDS!'});
  setTimeout(function(){kill()}, 10000);
}

app.post('/gitpull', function(req, res) {
  //GitHub push hook
  res.end();
  function puts(error, stdout, stderr) {sys.puts(stdout)}
  exec("git reset --hard HEAD", puts);
  exec("git pull", puts);
});

app.get('*', function(req, res) {
  res.render('index.ejs', {
   ip: ip
 });
});

var users = [];

process.stdin.resume();
process.stdin.setEncoding('utf8');

process.stdin.on('data', function (chunk) {
 io.sockets.emit('annouce', {message : '' + chunk.toUpperCase() + ''});
});

io.sockets.on('connection', function (socket) {
  function broadcast(data) {
    io.sockets.emit('annouce', {message : data});
  }

  function parseServerCommand(data) {
    var res = data.message.trim().split(" ");

    if(res[0].toLowerCase() == "/nick"){
      updateName(res.slice(1,res.length).join(' '));
      return;
    }

    if(res[0].toLowerCase() == "/pm"){
      if(res.length >= 3){
        if(res[1] == 'SERVER'){
          var help = "You cannot PM the server.";
          socket.emit('annouce', {message : help});
          return;
        }
        if(findUser(res[1])){
          pm(res[1], res.slice(2, res.length).join(' '));
          return;
        } else if (findUser(res.slice(1 ,3).join(' '))){
          pm(res.slice(1 ,3).join(' '), res.slice(3, res.length).join(' '));
          return;
        } else {
          var help = "User not found for command '" + res.join(' ') + "'";
          socket.emit('annouce', {message : help});
        }
      } else {
          var help = "You must add a PM message.";
          socket.emit('annouce', {message : help});
      }
    }

    if(res[0].toLowerCase() == "/disconnect"){
      socket.disconnect();
    }

    if(res[0].toLowerCase() == "/help"){
      sendHelp();
      return;
    }

    unrecognized(res[0]);
    sendHelp();
  }

  var entityMap = {
    "&": "&",
    "<": "<",
    ">": ">",
    '"': '"',
    "'": ''',
    "/": '/'
  };

  function escapeHtml(string) {
    return String(string).replace(/[&<>"'\/]/g, function (s) {
      return entityMap[s];
    });
  }

  function removeItem(arr, item) {
    for(var i = arr.length; i--;) {
      if(arr[i][0].toString() === item[0].toString()) {
        arr.splice(i, 1);
      }
    }
  }

  function findUser(user) {
    for(var i = users.length; i--;) {
      if(users[i][0] == user) {
        return true;
      }
    }
    return false;
  }

  function findSocket(user) {
    for(var i = users.length; i--;) {
      if(users[i][0] == user) {
        return users[i][1];
      }
    }
    return 0;
  }

  function pm(dest, data){
    if(dest == name){
      var help = "You cannot PM yourself.";
      socket.emit('annouce', {message : help});
      return;
    }
    data = '<to ' + dest + '> ' + data + '</span';
    io.sockets.socket(findSocket(dest)).emit('broadcast', {client : name, message : data});
    socket.emit('broadcast', {client : name, message : data});
  }

  function updateName(data){
    if(findUser(data)){
      socket.emit('annouce', {message : "The nick '" + data + "' is taken!"});
      return;
    }
    if(data.toLowerCase() == "admin" || data.toLowerCase() == "server"){
      socket.emit('annouce', {message : "That nick is reserved!"});
      return;
    }
    oldName = name;
    name = data;
    removeItem(users, [oldName, socket.id]);
    users.push([name, socket.id, true]);
    io.sockets.emit('users', users);
    socket.emit('name', {name : name});
    broadcast('' + oldName + ' has changed name to ' + data + '.');
  }

  function disconnect(data){
    socket.disconnect();
  }

  function unrecognized(data){
    var help = "Unknown command '" + data + "'.";
    socket.emit('annouce', {message : help});
  }

  function sendHelp(){
    var help = "HardOrange IRC Help - Commands:
/nick nick
/pm nick message
/clear
/disconnect
/help";
    socket.emit('annouce', {message : help});
  }

  function multiArrayIndex(arr, item){
    for(var i = 0; i < arr.length; i++) {
      if(arr[i].toString() == item.toString()) {
          return i;
       }
     }
  }

  //Set name and notify clients
  sendHelp();
  var name = 'Guest' + Math.floor(100 + Math.random() * 900);
  broadcast('' + name + ' has entered chat.');
  users.push([name, socket.id, true]);
  io.sockets.emit('users', users);
  socket.emit('name', {name : name});

  //Begin Handlers
  socket.on('broadcast', function (data) {
    if(data.message[0] == "/") {
      parseServerCommand(data);
    } else {
      bbcode.parse(escapeHtml(data.message), function(content){
        io.sockets.emit('broadcast', {client : name, message : content});
      });
    }
  });

  socket.on('status', function (data) {
    var index = multiArrayIndex(users, [name, socket.id, !data.status]);
    if(index === undefined){console.log('missing user');console.log(name + ' ' + data);return;}
    users[index][2] = data.status;
    io.sockets.emit('users', users);
  });

  socket.on('disconnect', function (data) {
    removeItem(users, [name, socket.id]);
    io.sockets.emit('users', users);
    broadcast('' + name + ' has exited chat.');
  });
});
<|endoftext|>


<commit_before>import React from 'react';
import classNames from 'classnames';
import BootstrapMixin from './BootstrapMixin';
import CustomPropTypes from './utils/CustomPropTypes';

const Tooltip = React.createClass({
  mixins: [BootstrapMixin],

  propTypes: {
    /**
     * An html id attribute, necessary for accessibility
     * @type {string}
     * @required
     */
    id: CustomPropTypes.isRequiredForA11y(
      React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.number
      ])
    ),

    /**
     * Sets the direction the Tooltip is positioned towards.
     */
    placement: React.PropTypes.oneOf(['top', 'right', 'bottom', 'left']),

    /**
     * The "left" position value for the Tooltip.
     */
    positionLeft: React.PropTypes.number,
    /**
     * The "top" position value for the Tooltip.
     */
    positionTop: React.PropTypes.number,
    /**
     * The "left" position value for the Tooltip arrow.
     */
    arrowOffsetLeft: React.PropTypes.oneOfType([
      React.PropTypes.number, React.PropTypes.string
    ]),
    /**
     * The "top" position value for the Tooltip arrow.
     */
    arrowOffsetTop: React.PropTypes.oneOfType([
      React.PropTypes.number, React.PropTypes.string
    ]),
    /**
     * Title text
     */
    title: React.PropTypes.node
  },

  getDefaultProps() {
    return {
      placement: 'right'
    };
  },

  render() {
    const classes = {
      'tooltip': true,
      [this.props.placement]: true
    };

    const style = {
      'left': this.props.positionLeft,
      'top': this.props.positionTop,
      ...this.props.style
    };

    const arrowStyle = {
      'left': this.props.arrowOffsetLeft,
      'top': this.props.arrowOffsetTop
    };

    return (

            {this.props.children}

      );
  }
});

export default Tooltip;
<commit_msg>Remove extraneous Tooltip prop types<commit_after>import classNames from 'classnames';
import React from 'react';

import CustomPropTypes from './utils/CustomPropTypes';

export default class Tooltip extends React.Component {
  render() {
    const {
      placement,
      positionLeft,
      positionTop,
      arrowOffsetLeft,
      arrowOffsetTop,
      className,
      style,
      children,
      ...props
    } = this.props;

    return (

          {children}

    );
  }
}

Tooltip.propTypes = {
  /**
   * An html id attribute, necessary for accessibility
   * @type {string}
   * @required
   */
  id: CustomPropTypes.isRequiredForA11y(
    React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.number
    ])
  ),

  /**
   * The direction the tooltip is positioned towards
   */
  placement: React.PropTypes.oneOf(['top', 'right', 'bottom', 'left']),

  /**
   * The `left` position value for the tooltip
   */
  positionLeft: React.PropTypes.number,
  /**
   * The `top` position value for the tooltip
   */
  positionTop: React.PropTypes.number,
  /**
   * The `left` position value for the tooltip arrow
   */
  arrowOffsetLeft: React.PropTypes.oneOfType([
    React.PropTypes.number, React.PropTypes.string
  ]),
  /**
   * The `top` position value for the tooltip arrow
   */
  arrowOffsetTop: React.PropTypes.oneOfType([
    React.PropTypes.number, React.PropTypes.string
  ])
};

Tooltip.defaultProps = {
  placement: 'right'
};
<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./back/routes/index');
var db = require('./back/models/index');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'front/views'));
app.set('view engine', 'jade');

app.use(favicon(path.join(__dirname, 'front/static', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'front/static')));

app.use('/', routes);
// app.use('/:user', routes);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;
<commit_msg>comment out favicon<commit_after>var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./back/routes/index');
var db = require('./back/models/index');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'front/views'));
app.set('view engine', 'jade');

// app.use(favicon(path.join(__dirname, 'front/static', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'front/static')));

app.use('/', routes);
// app.use('/:user', routes);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;
<|endoftext|>


<commit_before>L.Tooltip = L.Class.extend({
	initialize: function (map) {
		this._map = map;
		this._popupPane = map._panes.popupPane;

		this._container = map.options.drawControlTooltips ? L.DomUtil.create('div', 'leaflet-draw-tooltip', this._popupPane) : null;
		this._singleLineLabel = false;
	},

	dispose: function () {
		if (this._container) {
			this._popupPane.removeChild(this._container);
			this._container = null;
		}
	},

	updateContent: function (labelText) {
		if (!this._container) {
			return this;
		}
		labelText.subtext = labelText.subtext || '';

		// update the vertical position (only if changed)
		if (labelText.subtext.length === 0 && !this._singleLineLabel) {
			L.DomUtil.addClass(this._container, 'leaflet-draw-tooltip-single');
			this._singleLineLabel = true;
		}
		else if (labelText.subtext.length > 0 && this._singleLineLabel) {
			L.DomUtil.removeClass(this._container, 'leaflet-draw-tooltip-single');
			this._singleLineLabel = false;
		}

		this._container.innerHTML =
			(labelText.subtext.length > 0 ? '' + labelText.subtext + '' + '
' : '') +
			'' + labelText.text + '';

		return this;
	},

	updatePosition: function (latlng) {
		var pos = this._map.latLngToLayerPoint(latlng);

		if (this._container) {
			L.DomUtil.setPosition(this._container, pos);
		}

		return this;
	},

	showAsError: function () {
		if (this._container) {
			L.DomUtil.addClass(this._container, 'leaflet-error-draw-tooltip');
		}
		return this;
	},

	removeError: function () {
		if (this._container) {
			L.DomUtil.removeClass(this._container, 'leaflet-error-draw-tooltip');
		}
		return this;
	}
});<commit_msg>hide tooltip without position<commit_after>L.Tooltip = L.Class.extend({
	initialize: function (map) {
		this._map = map;
		this._popupPane = map._panes.popupPane;

		if (map.options.drawControlTooltips) {
			this._container = L.DomUtil.create('div', 'leaflet-draw-tooltip', this._popupPane);
			this._container.style.visibility = 'hidden';
		}
		this._singleLineLabel = false;
	},

	dispose: function () {
		if (this._container) {
			this._popupPane.removeChild(this._container);
			this._container = null;
		}
	},

	updateContent: function (labelText) {
		if (!this._container) {
			return this;
		}
		labelText.subtext = labelText.subtext || '';

		// update the vertical position (only if changed)
		if (labelText.subtext.length === 0 && !this._singleLineLabel) {
			L.DomUtil.addClass(this._container, 'leaflet-draw-tooltip-single');
			this._singleLineLabel = true;
		}
		else if (labelText.subtext.length > 0 && this._singleLineLabel) {
			L.DomUtil.removeClass(this._container, 'leaflet-draw-tooltip-single');
			this._singleLineLabel = false;
		}

		this._container.innerHTML =
			(labelText.subtext.length > 0 ? '' + labelText.subtext + '' + '
' : '') +
			'' + labelText.text + '';

		return this;
	},

	updatePosition: function (latlng) {
		var pos = this._map.latLngToLayerPoint(latlng);

		if (this._container) {
			this._container.style.visibility = 'inherit';
			L.DomUtil.setPosition(this._container, pos);
		}

		return this;
	},

	showAsError: function () {
		if (this._container) {
			L.DomUtil.addClass(this._container, 'leaflet-error-draw-tooltip');
		}
		return this;
	},

	removeError: function () {
		if (this._container) {
			L.DomUtil.removeClass(this._container, 'leaflet-error-draw-tooltip');
		}
		return this;
	}
});
<|endoftext|>


<commit_before>var app = {
    onDeviceReady : function () {
        //console.log('deviceready');
        app.showIt('info', 'deviceready');
        if (device.platform === "iOS") {
            alert("got iOS.");
            // hide Exit button. They don't have one on iOS devices.
            // http://www.mzcart.com/javascript-how-to-addremove-css-class-from-a-dom-element/
            document.getElementById('exitApp').classList.add("hidden");
            // deals with post-iOS-7 change that covers the status bar
            // http://coenraets.org/blog/2013/09/phonegap-and-cordova-with-ios-7/
            document.body.style.marginTop = "20px";
        } else if (device.platform == 'Android') {
            // Get rid of 300ms delay
            document.addEventListener('DOMContentLoaded', function() {
                FastClick.attach(document.body); },
                false);
            //
            document.getElementById('exitApp').addEventListener('click', function() {
                navigator.app.exitApp();
            });
        }
        if (device.platform == 'browser') {
            // hide Exit button. Browser does not exit.
            document.getElementById('exitApp').classList.add("hidden");
        } else {
            //app.pluginTest();
        }
        //console.log('deviceready done.');
        app.showIt('info', 'deviceready done.');
    },
    showIt : function (id, msg) {
        document.getElementById(id).innerHTML = msg;
    },
    pluginTest() {
        //window.MacAddress.getMacAddress();
    }
};

alert('app.js loaded');
//document.addEventListener("deviceready", app.onDeviceReady, false);
//
//    Entry Point
//
document.addEventListener('DOMContentLoaded', function() {
    // Detect if we are using Cordova/Phonegap or a browser.
    // https://videlais.com/2014/08/21/lessons-learned-from-detecting-apache-cordova/
    var isCordovaApp = (typeof window.cordova !== "undefined");

    // Is it a device we know?
    if ( isCordovaApp === true ) {
        // Wait for PhoneGap to load
        document.addEventListener("deviceready", app.onDeviceReady, false);
    } else {
        // This needs to be global so other modules can see it.
        device = {platform:'browser'};
        // Force the function.
        app.onDeviceReady();
    }
});
<commit_msg>try is<commit_after>var app = {
    onDeviceReady : function () {
        //console.log('deviceready');
        app.showIt('info', 'deviceready');
        if (device.platform === "iOS") {
            alert("got iOS.");
            // hide Exit button. They don't have one on iOS devices.
            // http://www.mzcart.com/javascript-how-to-addremove-css-class-from-a-dom-element/
            document.getElementById('exitApp').classList.add("hidden");
            // deals with post-iOS-7 change that covers the status bar
            // http://coenraets.org/blog/2013/09/phonegap-and-cordova-with-ios-7/
            document.body.style.marginTop = "20px";
        } else if (device.platform == 'Android') {
            // Get rid of 300ms delay
            document.addEventListener('DOMContentLoaded', function() {
                FastClick.attach(document.body); },
                false);
            //
            document.getElementById('exitApp').addEventListener('click', function() {
                navigator.app.exitApp();
            });
        }
        if (device.platform == 'browser') {
            // hide Exit button. Browser does not exit.
            document.getElementById('exitApp').classList.add("hidden");
        } else {
            //app.pluginTest();
        }
        //console.log('deviceready done.');
        app.showIt('info', 'deviceready done.');
    },
    showIt : function (id, msg) {
        document.getElementById(id).innerHTML = msg;
    }
};

alert('app.js loaded');
//document.addEventListener("deviceready", app.onDeviceReady, false);
//
//    Entry Point
//
document.addEventListener('DOMContentLoaded', function() {
    // Detect if we are using Cordova/Phonegap or a browser.
    // https://videlais.com/2014/08/21/lessons-learned-from-detecting-apache-cordova/
    var isCordovaApp = (typeof window.cordova !== "undefined");

    // Is it a device we know?
    if ( isCordovaApp === true ) {
        // Wait for PhoneGap to load
        document.addEventListener("deviceready", app.onDeviceReady, false);
    } else {
        // This needs to be global so other modules can see it.
        device = {platform:'browser'};
        // Force the function.
        app.onDeviceReady();
    }
});
<|endoftext|>


<commit_before>var express        = require('express');
var cors           = require('cors');
var morgan         = require('morgan');
var bodyParser     = require('body-parser');
var mongoose       = require('mongoose');
var passport       = require('passport');
var cookieParser   = require("cookie-parser");
var methodOverride = require("method-override");
var jwt            = require('jsonwebtoken');
var expressJWT     = require('express-jwt');
var app            = express();

var secret = process.env.ANIME_SECRET;

if(!secret) throw new Error('No secret in zshrc file');

// Database
var config = require('./config/config');
mongoose.connect(config.database);

// Require passport
require('./config/passport')(passport);

// Method Ovveride
app.use(methodOverride(function(req, res){
  if (req.body && typeof req.body === 'object' && '_method' in req.body) {
    var method = req.body._method
    delete req.body._method
    return method
  }
}));

//Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(morgan('dev'));
app.use(cors());
app.use(passport.initialize());

//Protect Routes with token
// app.use('/api', expressJWT({ secret: secret })
//   .unless({
//     path: [
//       { url: '/api/login', methods: ['POST'] },
//       { url: '/api/signup', methods: ['POST'] }
//     ]
//   }));

// Routes
var routes = require('./config/routes');
app.use("/api", routes);

// Port
app.listen(process.env.PORT || 3000 );
console.log('listening to 3000')<commit_msg>protecting routes<commit_after>var express        = require('express');
var cors           = require('cors');
var morgan         = require('morgan');
var bodyParser     = require('body-parser');
var mongoose       = require('mongoose');
var passport       = require('passport');
var cookieParser   = require("cookie-parser");
var methodOverride = require("method-override");
var jwt            = require('jsonwebtoken');
var expressJWT     = require('express-jwt');
var app            = express();

var secret = process.env.ANIME_SECRET;

if(!secret) throw new Error('No secret in zshrc file');

// Database
var config = require('./config/config');
mongoose.connect(config.database);

// Require passport
require('./config/passport')(passport);

// Method Ovveride
app.use(methodOverride(function(req, res){
  if (req.body && typeof req.body === 'object' && '_method' in req.body) {
    var method = req.body._method
    delete req.body._method
    return method
  }
}));

//Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(morgan('dev'));
app.use(cors());
app.use(passport.initialize());

// Protect Routes with token
app.use('/api', expressJWT({ secret: secret })
  .unless({
    path: [
      { url: '/api/login', methods: ['POST'] },
      { url: '/api/signup', methods: ['POST'] },
      { url: '/api/animes', methods: ['GET'] },
      { url: '/api/anime/:id', methods: ['GET'] },
    ]
  }));

// Routes
var routes = require('./config/routes');
app.use("/api", routes);

// Port
app.listen(process.env.PORT || 3000 );
console.log('listening to 3000')<|endoftext|>


<commit_before>const {app, BrowserWindow, Menu, dialog, ipcMain, protocol} = require('electron'),
    autoUpdater = require("electron-updater").autoUpdater,
    isDev = require('electron-is-dev'),
    path = require('path'),
    url = require('url'),
    fs = require('fs-extra'),
    Handlebars = require('handlebars');

// Automatically reloads view if source is changed
// require('electron-reload')(__dirname);

var Map = require('./classes/Map'),
    Window = require('./classes/Window'),
    Settings = require('./classes/Settings');

var mapObj; // Store Map in this object

// Global variables across windows
global.globals = {
    AppName: 'Ice-Sickle',
    AppPath: app.getAppPath(),
    isDevelopment: isDev
};

function OpenProjectWindow() {
    dialog.showOpenDialog({
        title: 'Open project',
        defaultPath: app.getAppPath(),
        properties: ['openDirectory']
    }, function(projects) {
        // should only be one project selected
        if(projects) {
            // Load and store the Map here in the app
            if(Map.Load(projects[0])) { // Map loaded successfully
                // Tell any renderer processes that a map load request has been initiated
                Window.SendMessage('root', 'open-project', projects[0]);
                Window.Broadcast('project-loaded', Map);

                // Store the project in recently-loaded settings
                if(Settings.recentMaps.indexOf(projects[0]) === -1) {
                    Settings.recentMaps.push(projects[0]);
                    Settings.Save();
                }

                return true;
            }
            else {
                return false;
            }
        }

        return false;
    });
}

function LoadProject(projectPath) {
    if(Map.Load(projectPath)) {
        Window.SendMessage('root', 'open-project', projectPath);
        return true;
    }
    else {
        return false;
    }
}

var template = [
  {
    label: 'File',
    submenu: [
      {
        label: 'New',
        sublabel: 'Create a new project',
        role: 'new',
        click () {
            Window.Open('newProject');
        }
      },
      {
        label: 'Open',
        sublabel: 'Open a project',
        role: 'open',
        click () {
            OpenProjectWindow();
        },
      },
      {
        label: 'Save',
        sublabel: 'Saves the current project',
        role: 'save',
        click () {
            Window.SendMessage('root', 'save-project');
        }
      },
      { type: 'separator' },
      /* Recent maps are generated here */
    ]
  },
  {
      label: 'Edit',
      submenu: [
          {
              label: 'Undo',
              enabled: false
          },
          {
              label: 'Redo',
              enabled: false
          },
          { type: 'separator' },
          {
              label: 'Cut',
              enabled: false
          },
          {
              label: 'Copy',
              enabled: false
          },
          {
              label: 'Paste',
              enabled: false
          },
          {
              label: 'Delete',
              enabled: false
          },
      ]
  },
  {
      label: 'View',
      enabled: false
  },
  {
      label: 'Scenario',
      submenu: [
          {
              label: 'Map Properties',
              click() {
                  Window.Open('mapProperties', mapObj.info);
              }
          }
      ]
  },
  {
      label: 'Editors',
      submenu: [
          {
              label: 'Trigger Editor',
              sublabel: '',
              click() {
                  Window.Open('triggerEditor');
              }
          },
          {
              label: 'Object Editor',
              sublabel: '',
              click() {
                  Window.Open('objectEditor');
              }
          },
          { type: 'separator' },
          {
              label: 'Import Manager',
              sublabel: '',
              click() {
                  Window.Open('importManager');
              }
          }
      ]
  },
  {
      label: 'Project',
      submenu: [
          {
              label: 'Compile',
              sublabel: 'Generates the .w3x file',
              click () {
                  Window.SendMessage('root', 'compile-project');
              }
          }
      ]
  },
  {
    role: 'help',
    submenu: [
      {
        label: 'GitHub',
        sublabel: 'View the application\'s source code',
        //icon: 'assets/img/github.png',
        click () { require('electron').shell.openExternal('https://github.com/ChiefOfGxBxL/Ice-Sickle') }
      },
      {
          label: 'Debug',
          submenu: [
              {
                  label: 'Open web console',
                  role: 'toggledevtools'
              },
              {
                  label: 'Reload window',
                  role: 'reload'
              }
          ]
      },
      { type: 'separator' },
      {
        label: 'About',
        click () {
            Window.Open('about', {
                appName: app.getName(),
                appVersion: app.getVersion()
            });
        }
      }
    ]
  }
];

Settings.Load(app.getAppPath());
if(Settings.recentMaps) {
    Settings.recentMaps.forEach((recentMap) => {
        var mapName = recentMap.split('\\').reverse()[0];

        template[0].submenu.push({
            label: mapName,
            sublabel: recentMap,
            click(entry) {
                LoadProject(entry.sublabel);
            }
        });
    })
}

var counter = 0;
function getNextIdCounter(type) {
    // TODO: respond based on data.type
    return ('0000' + (counter++)).substr(-4);
}

function applyPartialObjectUpdate(obj, updates) {
  Object.keys(updates).forEach((updateKey) => {
    if(typeof updates[updateKey] != 'object') {
      obj[updateKey] = updates[updateKey];
    }
    else {
      obj[updateKey] = obj[updateKey] || {};
      applyPartialObjectUpdate(obj[updateKey], updates[updateKey])
    }
  })
}

const EventHandlers = {
    'create-new-project': function(event, data) {
        mapObj = Map.Create(data.name);
        Window.Broadcast('project-created', mapObj);
        Window.Close('welcome'); // In case this window is still open, close it
    },
    'request-open-project': function() {
        OpenProjectWindow();
    },
    'request-save-project': function() {
        Map.Save(mapObj);
        Window.Broadcast('project-saved', mapObj);
    },
    'request-open-project-map': function(event, dir) {
        mapObj = Map.Load(dir);
    },
    'load-project': function(event, data) {
        if(LoadProject(data.path)) {
            Window.Broadcast('project-loaded', Map);
        }
    },
    'request-project': function(event, data) {
        // Send the Map back to the requesting window
        event.sender.webContents.send('response-project', mapObj);
    },
    'request-user-input': function(event, data) {
        var inputWindowName = 'input' + data.type[0].toUpperCase() + data.type.substr(1); // e.g. inputInt

        if(Window.availableWindows[inputWindowName]) {
            Window.Open(inputWindowName, data.context);
        }
        else {
            Window.Open('inputUnknown', data.context);
        }
    },
    'response-user-input': function(event, data) {
        Window.Broadcast('user-input-provided', data);
    },
    'patch-project-object': function(event, data) {
        // TODO: clean this mess up
        mapObj.objects[data.specType] = mapObj.objects[data.specType] || {};
        mapObj.objects[data.specType][data.table] = mapObj.objects[data.specType][data.table] || {};
        mapObj.objects[data.specType][data.table][data.entryId] = mapObj.objects[data.specType][data.table][data.entryId] || [];

        // Check if a modification already exists, in which case overwrite its value
        // TODO: this section is messy because of the poor WC3MapTranslator spec -- update it to use the object format
        var existingModificationIndex = mapObj.objects[data.specType][data.table][data.entryId].findIndex((mod) => {
            return mod.id === data.modification.id;
        });

        if(existingModificationIndex !== -1) {
            mapObj.objects[data.specType][data.table][data.entryId][existingModificationIndex].value = data.modification.value;
        }
        else {
            mapObj.objects[data.specType][data.table][data.entryId].push(data.modification);
        }
    },
    'request-open-window': function(event, data) {
        if(!data || !data.windowName) return false;

        Window.Open(data.windowName, data.template);
    },
    'new-custom-object': function(event, data) {
        // Add new object to mapObj, with custom name specified
        var mapObjName = data.type + 's'; // e.g. units, doodads, etc.
        mapObj.objects[mapObjName].custom[data.id] = [{
            id: 'unam', // TODO: unam, inam, etc.
            type: 'string',
            value: data.name
        }];

        // Send event to all windows
        Window.Broadcast('new-custom-object', data);
    },
    'request-id-counter': function(event, data) {
        event.sender.webContents.send('response-id-counter', getNextIdCounter(data.type));
    },
    'request-triggers': function(event, data) {
        event.sender.webContents.send('response-triggers', mapObj.triggers);
    },
    'update-trigger': function(event, data) {
        // Update a specified trigger's contents
        var triggerToUpdate = mapObj.triggers.find((t) => {
          return t.name === data.name;
        });

        if(triggerToUpdate) {
          triggerToUpdate.content = data.content;
        }
    },
    'new-trigger': function(event, data) {
        // TODO: check for conflicting trigger paths
        var newTriggerFilePath = path.resolve(mapObj.__Dir, 'triggers/', (data.name + '.' + data.type)),
            newTrigger = {
                name: data.name,
                path: newTriggerFilePath,
                type: data.type,
                content: ''
            };

        // Create a new file in the project
        fs.ensureFileSync(newTriggerFilePath);

        // Create a new trigger in the map
        mapObj.triggers.push(newTrigger)

        Window.Broadcast('new-trigger', newTrigger);
    },
    'update-map-info': function(event, newInfo) {
        // Applies a recursive, partial update to mapObj.info
        applyPartialObjectUpdate(mapObj.info, newInfo);
    },
    'request-import-list': function(event, data) {
        event.sender.webContents.send('response-import-list', mapObj.imports);
    },
    'import-file': function(event, file) {
        // First we copy the file into the project's /import folder
        const destinationPath = path.resolve(mapObj.__Dir, 'imports', file.name);
        fs.copySync(file.path, destinationPath, { overwrite: true });
        // TODO: alert user of path conflict, giving the option to overwrite

        // Then we add a record to the map object
        mapObj.imports.push({
            name: file.name,
            fullPath: 'war3mapImported\\' + file.name,
            path: file.path,
            size: file.size,
            type: file.type
        });
    },
    'update-import': function(event, file) {
        var importToUpdate = mapObj.imports.find(
            (imp) => { return imp.name == file.name; }
        );

        if(importToUpdate) {
            // This is the only attribute that can be changed
            // since size, name, and type are not modified by user
            if(file.fullPath) importToUpdate.fullPath = file.fullPath;
            Window.Broadcast('import-updated', importToUpdate);
        }
    }
}

// FUTURE:
// We can use app.addRecentDocument(path) and app.setUserTasks(tasks) in the future
// for enhanced Taskbar utility. See the `app` documentation for more details

// Auto-Updates
autoUpdater.on('checking-for-update',   () => { Window.Broadcast('checking-for-update'); })
autoUpdater.on('update-available',      (ev, info) => {
    // Open check-for-updates window
    Window.Open('update');

    Window.Broadcast('update-available', info);
})
autoUpdater.on('update-not-available',  (ev, info) => { Window.Broadcast('update-not-available', info); })
autoUpdater.on('error',                 (ev, err) => { Window.Broadcast('update-error', err); })
autoUpdater.on('download-progress',     (ev, progressObj) => { Window.Broadcast('download-progress', progressObj ); })
autoUpdater.on('update-downloaded',     (ev, info) => {
  Window.Broadcast('update-downloaded', info);

   // Wait 4 seconds, then quit and install
  setTimeout(function() {
    autoUpdater.quitAndInstall();
  }, 4000)
})

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', () => {
    if(isDev) {
        autoUpdater.logger = require("electron-log")
        autoUpdater.logger.transports.file.level = "info"
    }
    autoUpdater.checkForUpdates(); // Use the autoUpdater from electron-updater
    app.setName('Ice Sickle'); // From package.json it's icesickle (since npm init required lowercase, no spaces)

    // Create main window
    Window.Open('root');

    // Register IPC events
    Object.keys(EventHandlers).forEach((eventKey) => {
        ipcMain.on(eventKey, EventHandlers[eventKey]);
    });

    // Create the main menu from the template
    const menu = Menu.buildFromTemplate(template);
    Menu.setApplicationMenu(menu);

    // Open welcome dialog
    Window.Open('welcome', {
        recent: (Settings.recentMaps) ? Settings.recentMaps.map((dir) => {
            return {
                name: dir.split('\\').reverse()[0],
                path: dir.replace(/\\/g, "\\\\")
            }
        }) : []
    })

    // The hbs:// protocol is used to render handlebars files
    // See http://stackoverflow.com/a/41368514 for more details
    protocol.registerBufferProtocol('hbs', function (req, callback) {
        // The JSON context is passed through as uploaded POST data
        var context = (req.uploadData && req.uploadData[0]) ? JSON.parse(req.uploadData[0].bytes) : {},
            pathToFile = req.url.substr(7); // get rid of "hbs:///"

        // Sometimes the path is incorrect even now, but the file still exists
        // We check to see if the path can be salvaged: combine the app path
        // with the specified path without drive letter in front
        if(!fs.existsSync(pathToFile)) {
            if(fs.existsSync(path.resolve(app.getAppPath(), pathToFile.substr(3)))) {
                pathToFile = path.resolve(app.getAppPath(), pathToFile.substr(3));
            }
        }

        // If the file does not exist now then we cannot load it
        if(fs.existsSync(pathToFile)) {
          if(req.url.endsWith('.html') || req.url.endsWith('.hbs')) {
            // Use Handlebars to compile the template and render the context
            fs.readFile(pathToFile, 'utf8', function(err, data) {
                var template = Handlebars.compile(data),
                    page = template(context);

                callback({
                    mimeType: 'text/html',
                    data: new Buffer(page)
                });
            });
          }
          else {
            // Otherwise read the file normally and pass it through
            fs.readFile(pathToFile, 'utf8', function(err, data) {
              callback({
                  //mimeType: 'text/css',
                  data: new Buffer(data)
              });
            });
          }
        }
    });
});

// Quit when all windows are closed.
app.on('window-all-closed', () => {
    // Save any unsaved changes to settings
    Settings.Save();

    // On macOS it is common for applications and their menu bar
    // to stay active until the user quits explicitly with Cmd + Q
    if (process.platform !== 'darwin') {
        app.quit()
    }
})

// MacOS dock support
app.on('activate', () => {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (!Window.openWindows.root) {
        Window.Open('root');
    }
})
<commit_msg>Remove return statements on OpenProjectWindow method since no return value is needed<commit_after>const {app, BrowserWindow, Menu, dialog, ipcMain, protocol} = require('electron'),
    autoUpdater = require("electron-updater").autoUpdater,
    isDev = require('electron-is-dev'),
    path = require('path'),
    url = require('url'),
    fs = require('fs-extra'),
    Handlebars = require('handlebars');

// Automatically reloads view if source is changed
// require('electron-reload')(__dirname);

var Map = require('./classes/Map'),
    Window = require('./classes/Window'),
    Settings = require('./classes/Settings');

var mapObj; // Store Map in this object

// Global variables across windows
global.globals = {
    AppName: 'Ice-Sickle',
    AppPath: app.getAppPath(),
    isDevelopment: isDev
};

function OpenProjectWindow() {
    dialog.showOpenDialog({
        title: 'Open project',
        defaultPath: app.getAppPath(),
        properties: ['openDirectory']
    }, function(projects) {
        // should only be one project selected
        if(projects) {
            // Load and store the Map here in the app
            if(Map.Load(projects[0])) { // Map loaded successfully
                // Tell any renderer processes that a map load request has been initiated
                Window.SendMessage('root', 'open-project', projects[0]);
                Window.Broadcast('project-loaded', Map);

                // Store the project in recently-loaded settings
                if(Settings.recentMaps.indexOf(projects[0]) === -1) {
                    Settings.recentMaps.push(projects[0]);
                    Settings.Save();
                }
            }
        }
    });
}

function LoadProject(projectPath) {
    if(Map.Load(projectPath)) {
        Window.SendMessage('root', 'open-project', projectPath);
        return true;
    }
    else {
        return false;
    }
}

var template = [
  {
    label: 'File',
    submenu: [
      {
        label: 'New',
        sublabel: 'Create a new project',
        role: 'new',
        click () {
            Window.Open('newProject');
        }
      },
      {
        label: 'Open',
        sublabel: 'Open a project',
        role: 'open',
        click () {
            OpenProjectWindow();
        },
      },
      {
        label: 'Save',
        sublabel: 'Saves the current project',
        role: 'save',
        click () {
            Window.SendMessage('root', 'save-project');
        }
      },
      { type: 'separator' },
      /* Recent maps are generated here */
    ]
  },
  {
      label: 'Edit',
      submenu: [
          {
              label: 'Undo',
              enabled: false
          },
          {
              label: 'Redo',
              enabled: false
          },
          { type: 'separator' },
          {
              label: 'Cut',
              enabled: false
          },
          {
              label: 'Copy',
              enabled: false
          },
          {
              label: 'Paste',
              enabled: false
          },
          {
              label: 'Delete',
              enabled: false
          },
      ]
  },
  {
      label: 'View',
      enabled: false
  },
  {
      label: 'Scenario',
      submenu: [
          {
              label: 'Map Properties',
              click() {
                  Window.Open('mapProperties', mapObj.info);
              }
          }
      ]
  },
  {
      label: 'Editors',
      submenu: [
          {
              label: 'Trigger Editor',
              sublabel: '',
              click() {
                  Window.Open('triggerEditor');
              }
          },
          {
              label: 'Object Editor',
              sublabel: '',
              click() {
                  Window.Open('objectEditor');
              }
          },
          { type: 'separator' },
          {
              label: 'Import Manager',
              sublabel: '',
              click() {
                  Window.Open('importManager');
              }
          }
      ]
  },
  {
      label: 'Project',
      submenu: [
          {
              label: 'Compile',
              sublabel: 'Generates the .w3x file',
              click () {
                  Window.SendMessage('root', 'compile-project');
              }
          }
      ]
  },
  {
    role: 'help',
    submenu: [
      {
        label: 'GitHub',
        sublabel: 'View the application\'s source code',
        //icon: 'assets/img/github.png',
        click () { require('electron').shell.openExternal('https://github.com/ChiefOfGxBxL/Ice-Sickle') }
      },
      {
          label: 'Debug',
          submenu: [
              {
                  label: 'Open web console',
                  role: 'toggledevtools'
              },
              {
                  label: 'Reload window',
                  role: 'reload'
              }
          ]
      },
      { type: 'separator' },
      {
        label: 'About',
        click () {
            Window.Open('about', {
                appName: app.getName(),
                appVersion: app.getVersion()
            });
        }
      }
    ]
  }
];

Settings.Load(app.getAppPath());
if(Settings.recentMaps) {
    Settings.recentMaps.forEach((recentMap) => {
        var mapName = recentMap.split('\\').reverse()[0];

        template[0].submenu.push({
            label: mapName,
            sublabel: recentMap,
            click(entry) {
                LoadProject(entry.sublabel);
            }
        });
    })
}

var counter = 0;
function getNextIdCounter(type) {
    // TODO: respond based on data.type
    return ('0000' + (counter++)).substr(-4);
}

function applyPartialObjectUpdate(obj, updates) {
  Object.keys(updates).forEach((updateKey) => {
    if(typeof updates[updateKey] != 'object') {
      obj[updateKey] = updates[updateKey];
    }
    else {
      obj[updateKey] = obj[updateKey] || {};
      applyPartialObjectUpdate(obj[updateKey], updates[updateKey])
    }
  })
}

const EventHandlers = {
    'create-new-project': function(event, data) {
        mapObj = Map.Create(data.name);
        Window.Broadcast('project-created', mapObj);
        Window.Close('welcome'); // In case this window is still open, close it
    },
    'request-open-project': function() {
        OpenProjectWindow();
    },
    'request-save-project': function() {
        Map.Save(mapObj);
        Window.Broadcast('project-saved', mapObj);
    },
    'request-open-project-map': function(event, dir) {
        mapObj = Map.Load(dir);
    },
    'load-project': function(event, data) {
        if(LoadProject(data.path)) {
            Window.Broadcast('project-loaded', Map);
        }
    },
    'request-project': function(event, data) {
        // Send the Map back to the requesting window
        event.sender.webContents.send('response-project', mapObj);
    },
    'request-user-input': function(event, data) {
        var inputWindowName = 'input' + data.type[0].toUpperCase() + data.type.substr(1); // e.g. inputInt

        if(Window.availableWindows[inputWindowName]) {
            Window.Open(inputWindowName, data.context);
        }
        else {
            Window.Open('inputUnknown', data.context);
        }
    },
    'response-user-input': function(event, data) {
        Window.Broadcast('user-input-provided', data);
    },
    'patch-project-object': function(event, data) {
        // TODO: clean this mess up
        mapObj.objects[data.specType] = mapObj.objects[data.specType] || {};
        mapObj.objects[data.specType][data.table] = mapObj.objects[data.specType][data.table] || {};
        mapObj.objects[data.specType][data.table][data.entryId] = mapObj.objects[data.specType][data.table][data.entryId] || [];

        // Check if a modification already exists, in which case overwrite its value
        // TODO: this section is messy because of the poor WC3MapTranslator spec -- update it to use the object format
        var existingModificationIndex = mapObj.objects[data.specType][data.table][data.entryId].findIndex((mod) => {
            return mod.id === data.modification.id;
        });

        if(existingModificationIndex !== -1) {
            mapObj.objects[data.specType][data.table][data.entryId][existingModificationIndex].value = data.modification.value;
        }
        else {
            mapObj.objects[data.specType][data.table][data.entryId].push(data.modification);
        }
    },
    'request-open-window': function(event, data) {
        if(!data || !data.windowName) return false;

        Window.Open(data.windowName, data.template);
    },
    'new-custom-object': function(event, data) {
        // Add new object to mapObj, with custom name specified
        var mapObjName = data.type + 's'; // e.g. units, doodads, etc.
        mapObj.objects[mapObjName].custom[data.id] = [{
            id: 'unam', // TODO: unam, inam, etc.
            type: 'string',
            value: data.name
        }];

        // Send event to all windows
        Window.Broadcast('new-custom-object', data);
    },
    'request-id-counter': function(event, data) {
        event.sender.webContents.send('response-id-counter', getNextIdCounter(data.type));
    },
    'request-triggers': function(event, data) {
        event.sender.webContents.send('response-triggers', mapObj.triggers);
    },
    'update-trigger': function(event, data) {
        // Update a specified trigger's contents
        var triggerToUpdate = mapObj.triggers.find((t) => {
          return t.name === data.name;
        });

        if(triggerToUpdate) {
          triggerToUpdate.content = data.content;
        }
    },
    'new-trigger': function(event, data) {
        // TODO: check for conflicting trigger paths
        var newTriggerFilePath = path.resolve(mapObj.__Dir, 'triggers/', (data.name + '.' + data.type)),
            newTrigger = {
                name: data.name,
                path: newTriggerFilePath,
                type: data.type,
                content: ''
            };

        // Create a new file in the project
        fs.ensureFileSync(newTriggerFilePath);

        // Create a new trigger in the map
        mapObj.triggers.push(newTrigger)

        Window.Broadcast('new-trigger', newTrigger);
    },
    'update-map-info': function(event, newInfo) {
        // Applies a recursive, partial update to mapObj.info
        applyPartialObjectUpdate(mapObj.info, newInfo);
    },
    'request-import-list': function(event, data) {
        event.sender.webContents.send('response-import-list', mapObj.imports);
    },
    'import-file': function(event, file) {
        // First we copy the file into the project's /import folder
        const destinationPath = path.resolve(mapObj.__Dir, 'imports', file.name);
        fs.copySync(file.path, destinationPath, { overwrite: true });
        // TODO: alert user of path conflict, giving the option to overwrite

        // Then we add a record to the map object
        mapObj.imports.push({
            name: file.name,
            fullPath: 'war3mapImported\\' + file.name,
            path: file.path,
            size: file.size,
            type: file.type
        });
    },
    'update-import': function(event, file) {
        var importToUpdate = mapObj.imports.find(
            (imp) => { return imp.name == file.name; }
        );

        if(importToUpdate) {
            // This is the only attribute that can be changed
            // since size, name, and type are not modified by user
            if(file.fullPath) importToUpdate.fullPath = file.fullPath;
            Window.Broadcast('import-updated', importToUpdate);
        }
    }
}

// FUTURE:
// We can use app.addRecentDocument(path) and app.setUserTasks(tasks) in the future
// for enhanced Taskbar utility. See the `app` documentation for more details

// Auto-Updates
autoUpdater.on('checking-for-update',   () => { Window.Broadcast('checking-for-update'); })
autoUpdater.on('update-available',      (ev, info) => {
    // Open check-for-updates window
    Window.Open('update');

    Window.Broadcast('update-available', info);
})
autoUpdater.on('update-not-available',  (ev, info) => { Window.Broadcast('update-not-available', info); })
autoUpdater.on('error',                 (ev, err) => { Window.Broadcast('update-error', err); })
autoUpdater.on('download-progress',     (ev, progressObj) => { Window.Broadcast('download-progress', progressObj ); })
autoUpdater.on('update-downloaded',     (ev, info) => {
  Window.Broadcast('update-downloaded', info);

   // Wait 4 seconds, then quit and install
  setTimeout(function() {
    autoUpdater.quitAndInstall();
  }, 4000)
})

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', () => {
    if(isDev) {
        autoUpdater.logger = require("electron-log")
        autoUpdater.logger.transports.file.level = "info"
    }
    autoUpdater.checkForUpdates(); // Use the autoUpdater from electron-updater
    app.setName('Ice Sickle'); // From package.json it's icesickle (since npm init required lowercase, no spaces)

    // Create main window
    Window.Open('root');

    // Register IPC events
    Object.keys(EventHandlers).forEach((eventKey) => {
        ipcMain.on(eventKey, EventHandlers[eventKey]);
    });

    // Create the main menu from the template
    const menu = Menu.buildFromTemplate(template);
    Menu.setApplicationMenu(menu);

    // Open welcome dialog
    Window.Open('welcome', {
        recent: (Settings.recentMaps) ? Settings.recentMaps.map((dir) => {
            return {
                name: dir.split('\\').reverse()[0],
                path: dir.replace(/\\/g, "\\\\")
            }
        }) : []
    })

    // The hbs:// protocol is used to render handlebars files
    // See http://stackoverflow.com/a/41368514 for more details
    protocol.registerBufferProtocol('hbs', function (req, callback) {
        // The JSON context is passed through as uploaded POST data
        var context = (req.uploadData && req.uploadData[0]) ? JSON.parse(req.uploadData[0].bytes) : {},
            pathToFile = req.url.substr(7); // get rid of "hbs:///"

        // Sometimes the path is incorrect even now, but the file still exists
        // We check to see if the path can be salvaged: combine the app path
        // with the specified path without drive letter in front
        if(!fs.existsSync(pathToFile)) {
            if(fs.existsSync(path.resolve(app.getAppPath(), pathToFile.substr(3)))) {
                pathToFile = path.resolve(app.getAppPath(), pathToFile.substr(3));
            }
        }

        // If the file does not exist now then we cannot load it
        if(fs.existsSync(pathToFile)) {
          if(req.url.endsWith('.html') || req.url.endsWith('.hbs')) {
            // Use Handlebars to compile the template and render the context
            fs.readFile(pathToFile, 'utf8', function(err, data) {
                var template = Handlebars.compile(data),
                    page = template(context);

                callback({
                    mimeType: 'text/html',
                    data: new Buffer(page)
                });
            });
          }
          else {
            // Otherwise read the file normally and pass it through
            fs.readFile(pathToFile, 'utf8', function(err, data) {
              callback({
                  //mimeType: 'text/css',
                  data: new Buffer(data)
              });
            });
          }
        }
    });
});

// Quit when all windows are closed.
app.on('window-all-closed', () => {
    // Save any unsaved changes to settings
    Settings.Save();

    // On macOS it is common for applications and their menu bar
    // to stay active until the user quits explicitly with Cmd + Q
    if (process.platform !== 'darwin') {
        app.quit()
    }
})

// MacOS dock support
app.on('activate', () => {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (!Window.openWindows.root) {
        Window.Open('root');
    }
})
<|endoftext|>


<commit_before>/*jshint
  node: true,
  globalstrict: true,
  laxcomma: true
 */

'use strict';

/* Tiny */

var tiny = require('tiny');
var db;

tiny(__dirname + '/latest_tweets.tiny', function openDatabase (err, tinydb) {
  if (err) {
    console.error('Error opening database: %s\nQuitting!', err);
    process.exit(1);
  }

  db = tinydb;
});

function storeTweet (tweet) {
  db.set(tweet.id_str, {
    id: tweet.id_str,
    timestamp: Date.now(),
    tweet: tweet
  }, function afterSave (err) {
    if (err) {
      console.error('Error saving tweet: %s', err);
    }
  });
}

setInterval(function removeOldTweets () {
  db.find({
    timestamp: {
      $lt: Date.now() - 604800000 // One week
    }
  })
  .shallow()(function deleteTweets (err, tweets) {
    if (err) {
      console.error('Error getting tweets for deletion: %s', err);
    }

    var timer = Date.now();
    var size_before = db.size;

    function tweetDeleted (err) {
      if (err) {
        // Ignore error if no records were found
        if (err.toString() !== 'Error: No records.') {
          console.error('Error deleting tweet: %s', err);
        }
      }
    }

    for (var i = 0; i < tweets.length; i++) {
      db.remove(tweets[i].id, tweetDeleted);
    }

    console.log('Deleted %d old tweets in %d ms.',
        tweets.length,
        Date.now() - timer
    );
  });
}, 21600000); // Every six hours

/* Express */

var express = require('express');
var app = express.createServer();

app.use(express.logger());
app.use(express.static(__dirname + '/public'));

app.get('/', function (req, res) {
  res.sendfile(__dirname + '/public/index.html');
});

app.listen(process.env['app_port'] || 3000);

/* Socket.IO */

var io = require('socket.io').listen(app);
io.set('log', false);
io.enable('browser client minification');
io.enable('browser cilent gzip');

var clients = 0;

io.sockets.on('connection', function clientConnected (socket) {
  // Sends out new user count when a new client is connected
  clients++;
  socket.emit('users', { count: clients });
  socket.broadcast.emit('users', { count: clients });

  // Sends out the latest tweets (max 20) to new users
  db.find({
    timestamp: {
      $gt: Date.now() - 604800000 // One week
    }
  })
  .desc('timestamp')
  .limit(20)(function sendOldTweets (err, tweets) {
    for (var i = tweets.length - 1; i >= 0; i--) {
      var tweet = tweets[i].tweet;
      var timestamp = tweets[i].timestamp;
      var retweet = undefined;

      if (tweet.retweeted_status) {
        retweet = {
          name: tweet.user.name,
          screen_name: tweet.user.screen_name
        };
        tweet = tweet.retweeted_status;
      }

      socket.emit('tweet',
        {
          id: tweet.id_str,
          pic_url: tweet.user.profile_image_url,
          screen_name: tweet.user.screen_name,
          name: tweet.user.name,
          timestamp: new Date(timestamp).toJSON(),
          text: renderTweet(tweet),
          retweet: retweet
        }
      );
    }

    // Sends out the server time to the new client, this calls goFuzzy()
    socket.emit('time', { now: new Date().getTime() });
  });

  // Sends out new user count when a client disconnect
  socket.on('disconnect', function clientDisconnected () {
    clients--;
    socket.broadcast.emit('users', { count: clients });
  });
});

/* Twitter */

try {
  var t_opts = require(__dirname + '/twitter_options.json');
} catch (e) {
  console.error('Error reading twitter_options.json: %s\nQuitting!', e.message);
  process.exit(1);
}

var t = require('immortal-ntwitter').create(t_opts.oauth_credentials);

t.verifyCredentials(function testCredentials (err, data) {
  if (err) {
    console.error('Error verifying Twitter credentials: %s\nQuitting!', err);
    process.exit(1);
  }
});

t.immortalStream('statuses/filter', {
  follow: t_opts.follow.join(',')
}, function twitterStream (ts) {
  ts.on('data', function processNewTweet (tweet) {
    if (tweet.in_reply_to_user_id) {
      // Ignore replies
      return;
    }

    var retweet = undefined;
    if (tweet.retweeted_status) {
      retweet = {
        user: tweet.user.name,
        screen_name: tweet.user.screen_name
      };
      tweet = tweet.retweeted_status;
    }

    io.sockets.emit('tweet',
      {
        id: tweet.id_str,
        pic_url: tweet.user.profile_image_url,
        screen_name: tweet.user.screen_name,
        name: tweet.user.name,
        timestamp: new Date(tweet.created_at).toJSON(),
        text: renderTweet(tweet),
        retweet: tweet.retweet
      }
    );

    storeTweet(tweet);
  });

  ts.on('delete', function deleteTweet (tweet) {
    io.sockets.emit('delete', { id: tweet.status.id_str });

    db.remove(tweet.status.id_str, function deleteTweet (err) {
      if (err) {
        console.error('Error deleting tweet: %s', err);
      }
    });
  });

  ts.on('limit', function limitReceived (data) {
    console.log('Limit event received, content: %s', data);
  });

  ts.on('scrub_geo', function scrubGeoReceived (data) {
    console.log('Scrub Geo event received, content: %s', data);
  });
});

/* Rendering */

function renderTweet (tweet) {
  // URLs
  var i, entity;
  if (tweet.entities.urls && tweet.entities.urls.length > 0) {
    for (i = 0; i < tweet.entities.urls.length; i++) {
      entity = tweet.entities.urls[i];
      tweet.text = tweet.text.replace(entity.url, '' + entity.display_url + ''
      );
    }
  }

  // Media
  if (tweet.entities.media && tweet.entities.media.length > 0) {
    for (i = 0; i < tweet.entities.media.length; i++) {
      entity = tweet.entities.media[i];
      tweet.text = tweet.text.replace(entity.url, '' + entity.display_url + ''
      );
    }
  }

  // Users
  if (tweet.entities.user_mentions && tweet.entities.user_mentions.length > 0) {
    for (i = 0; i < tweet.entities.user_mentions.length; i++) {
      entity = tweet.entities.user_mentions[i];
      tweet.text = tweet.text.substring(0, entity.indices[0]) +
        '@' +
        entity.screen_name +
        '' +
        tweet.text.substring(entity.indices[1]);
    }
  }

  // Hashtags
  if (tweet.entities.hashtags && tweet.entities.hashtags.length > 0) {
    for (i = 0; i < tweet.entities.hashtags.length; i++) {
      entity = tweet.entities.hashtags[i];
      tweet.text = tweet.text.substring(0, entity.indices[0]) +
        '#' +
        entity.text +
        '' +
        tweet.text.substring(entity.indices[1]);
    }
  }

  return tweet.text;
}

/* Update time since */

// Time is pushed from the server to the clients
// This is in order to avoid clients with wrong time settings
setInterval(function updateTime() {
  io.sockets.emit('time', { now: new Date().getTime() });
}, 15000);
<commit_msg>Possibly fixed how renderTweet() works when there are multiple links<commit_after>/*jshint
  node: true,
  globalstrict: true,
  laxcomma: true
 */

'use strict';

/* Tiny */

var tiny = require('tiny');
var db;

tiny(__dirname + '/latest_tweets.tiny', function openDatabase (err, tinydb) {
  if (err) {
    console.error('Error opening database: %s\nQuitting!', err);
    process.exit(1);
  }

  db = tinydb;
});

function storeTweet (tweet) {
  db.set(tweet.id_str, {
    id: tweet.id_str,
    timestamp: Date.now(),
    tweet: tweet
  }, function afterSave (err) {
    if (err) {
      console.error('Error saving tweet: %s', err);
    }
  });
}

setInterval(function removeOldTweets () {
  db.find({
    timestamp: {
      $lt: Date.now() - 604800000 // One week
    }
  })
  .shallow()(function deleteTweets (err, tweets) {
    if (err) {
      console.error('Error getting tweets for deletion: %s', err);
    }

    var timer = Date.now();
    var size_before = db.size;

    function tweetDeleted (err) {
      if (err) {
        // Ignore error if no records were found
        if (err.toString() !== 'Error: No records.') {
          console.error('Error deleting tweet: %s', err);
        }
      }
    }

    for (var i = 0; i < tweets.length; i++) {
      db.remove(tweets[i].id, tweetDeleted);
    }

    console.log('Deleted %d old tweets in %d ms.',
        tweets.length,
        Date.now() - timer
    );
  });
}, 21600000); // Every six hours

/* Express */

var express = require('express');
var app = express.createServer();

app.use(express.logger());
app.use(express.static(__dirname + '/public'));

app.get('/', function (req, res) {
  res.sendfile(__dirname + '/public/index.html');
});

app.listen(process.env['app_port'] || 3000);

/* Socket.IO */

var io = require('socket.io').listen(app);
io.set('log', false);
io.enable('browser client minification');
io.enable('browser cilent gzip');

var clients = 0;

io.sockets.on('connection', function clientConnected (socket) {
  // Sends out new user count when a new client is connected
  clients++;
  socket.emit('users', { count: clients });
  socket.broadcast.emit('users', { count: clients });

  // Sends out the latest tweets (max 20) to new users
  db.find({
    timestamp: {
      $gt: Date.now() - 604800000 // One week
    }
  })
  .desc('timestamp')
  .limit(20)(function sendOldTweets (err, tweets) {
    for (var i = tweets.length - 1; i >= 0; i--) {
      var tweet = tweets[i].tweet;
      var timestamp = tweets[i].timestamp;
      var retweet = undefined;

      if (tweet.retweeted_status) {
        retweet = {
          name: tweet.user.name,
          screen_name: tweet.user.screen_name
        };
        tweet = tweet.retweeted_status;
      }

      socket.emit('tweet',
        {
          id: tweet.id_str,
          pic_url: tweet.user.profile_image_url,
          screen_name: tweet.user.screen_name,
          name: tweet.user.name,
          timestamp: new Date(timestamp).toJSON(),
          text: renderTweet(tweet),
          retweet: retweet
        }
      );
    }

    // Sends out the server time to the new client, this calls goFuzzy()
    socket.emit('time', { now: new Date().getTime() });
  });

  // Sends out new user count when a client disconnect
  socket.on('disconnect', function clientDisconnected () {
    clients--;
    socket.broadcast.emit('users', { count: clients });
  });
});

/* Twitter */

try {
  var t_opts = require(__dirname + '/twitter_options.json');
} catch (e) {
  console.error('Error reading twitter_options.json: %s\nQuitting!', e.message);
  process.exit(1);
}

var t = require('immortal-ntwitter').create(t_opts.oauth_credentials);

t.verifyCredentials(function testCredentials (err, data) {
  if (err) {
    console.error('Error verifying Twitter credentials: %s\nQuitting!', err);
    process.exit(1);
  }
});

t.immortalStream('statuses/filter', {
  follow: t_opts.follow.join(',')
}, function twitterStream (ts) {
  ts.on('data', function processNewTweet (tweet) {
    if (tweet.in_reply_to_user_id) {
      // Ignore replies
      return;
    }

    var retweet = undefined;
    if (tweet.retweeted_status) {
      retweet = {
        user: tweet.user.name,
        screen_name: tweet.user.screen_name
      };
      tweet = tweet.retweeted_status;
    }

    io.sockets.emit('tweet',
      {
        id: tweet.id_str,
        pic_url: tweet.user.profile_image_url,
        screen_name: tweet.user.screen_name,
        name: tweet.user.name,
        timestamp: new Date(tweet.created_at).toJSON(),
        text: renderTweet(tweet),
        retweet: tweet.retweet
      }
    );

    storeTweet(tweet);
  });

  ts.on('delete', function deleteTweet (tweet) {
    io.sockets.emit('delete', { id: tweet.status.id_str });

    db.remove(tweet.status.id_str, function deleteTweet (err) {
      if (err) {
        console.error('Error deleting tweet: %s', err);
      }
    });
  });

  ts.on('limit', function limitReceived (data) {
    console.log('Limit event received, content: %s', data);
  });

  ts.on('scrub_geo', function scrubGeoReceived (data) {
    console.log('Scrub Geo event received, content: %s', data);
  });
});

/* Rendering */

function renderTweet (tweet) {
  // URLs
  var i, entity;
  if (tweet.entities.urls && tweet.entities.urls.length > 0) {
    for (i = 0; i < tweet.entities.urls.length; i++) {
      entity = tweet.entities.urls[i];
      tweet.text = tweet.text.replace(entity.url, '' + entity.display_url + ''
      );
    }
  }

  // Media
  if (tweet.entities.media && tweet.entities.media.length > 0) {
    for (i = 0; i < tweet.entities.media.length; i++) {
      entity = tweet.entities.media[i];
      tweet.text = tweet.text.replace(entity.url, '' + entity.display_url + ''
      );
    }
  }

  // Users
  if (tweet.entities.user_mentions && tweet.entities.user_mentions.length > 0) {
    for (i = 0; i < tweet.entities.user_mentions.length; i++) {
      entity = tweet.entities.user_mentions[i];
      tweet.text = tweet.text.replace('@' + entity.screen_name,
        '@' + entity.screen_name + ''
      );
    }
  }

  // Hashtags
  if (tweet.entities.hashtags && tweet.entities.hashtags.length > 0) {
    for (i = 0; i < tweet.entities.hashtags.length; i++) {
      entity = tweet.entities.hashtags[i];
      tweet.text = tweet.text.replace('#' + entity.text,
        '#' +
        entity.text + ''
      );
    }
  }

  return tweet.text;
}

/* Update time since */

// Time is pushed from the server to the clients
// This is in order to avoid clients with wrong time settings
setInterval(function updateTime() {
  io.sockets.emit('time', { now: new Date().getTime() });
}, 15000);
<|endoftext|>


<commit_before>var app = new Vue({
  el: "#app",
  data: {
    title : "This is a title",
    message : "This is a default message",
    showHello : false,
    links : [
      {
        title : "Youtube",
        url : "http:youtube.de"
      },
      {
        title : "Twitter",
        url : "http:twitter.de"
      },
      {
        title : "Google",
        url : "http:google.de"
      }
    ],
    showHello : false
  },
  methods: {
    greet : function() {
      alert('Let´s go!');
    }
  }
})
<commit_msg>New link added<commit_after>var app = new Vue({
  el: "#app",
  data: {
    title : "This is a title",
    message : "This is a default message",
    showHello : false,
    links : [
      {
        title : "Youtube",
        url : "http:youtube.de"
      },
      {
        title : "Twitter",
        url : "http:twitter.de"
      },
      {
        title : "Google",
        url : "http:google.de"
      },
      {
        title : "Steam",
        url : "http:store.steampowered.com"
      }
    ],
    showHello : false
  },
  methods: {
    greet : function() {
      alert('Let´s go!');
    }
  }
})
<|endoftext|>


<commit_before>
console.log("===========================================================");
console.log("===========================================================");
console.log("===========================================================");

var config = require('./config.js');
var server = require('./main/server.js');

server.startServer(config.PORT);<commit_msg>testing<commit_after>
console.log("===========================================================");
console.log("===========================================================");
console.log("===========================================================");

var config = require('./ApplicationConstants.js');
var server = require('./main/server.js');

server.startServer(config.PORT);<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var express = require('express')
    , api = require('./src/routes.js')
    , http = require('http')
    , path = require('path');

var app = express();
var port = (process.env.VMC_APP_PORT || 3002);
var host = (process.env.VCAP_APP_HOST || 'localhost');

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
    app.use(express.errorHandler());
}

api.setup(app);

app.listen(port, host);
console.log("Express server listening on port %d in %s mode", port, app.settings.env);
<commit_msg>Adding production IP<commit_after>/**
 * Module dependencies.
 */

var express = require('express')
    , api = require('./src/routes.js')
    , http = require('http')
    , path = require('path');

var app = express();
var port = (process.env.VMC_APP_PORT || 3002);
var host = (process.env.VCAP_APP_HOST || 'localhost' || '66.111.33.250');

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
    app.use(express.errorHandler());
}

api.setup(app);

app.listen(port, host);
console.log("Express server listening on port %d in %s mode", port, app.settings.env);
<|endoftext|>


<commit_before>/* jslint node: true */
'use strict';

//  enigma-bbs
const { MenuModule }    = require('./menu_module.js');
const { resetScreen }   = require('./ansi_term.js');
const { Errors }        = require('./enig_error.js');
const {
    trackDoorRunBegin,
    trackDoorRunEnd
}                       = require('./door_util.js');

//  deps
const async         = require('async');
const SSHClient     = require('ssh2').Client;

exports.moduleInfo = {
    name    : 'DoorParty',
    desc    : 'DoorParty Access Module',
    author  : 'NuSkooler',
};

exports.getModule = class DoorPartyModule extends MenuModule {
    constructor(options) {
        super(options);

        //  establish defaults
        this.config             = options.menuConfig.config;
        this.config.host        = this.config.host || 'dp.throwbackbbs.com';
        this.config.sshPort     = this.config.sshPort || 2022;
        this.config.rloginPort  = this.config.rloginPort || 513;
    }

    initSequence() {
        let clientTerminated;
        const self = this;

        async.series(
            [
                function validateConfig(callback) {
                    return self.validateConfigFields(
                        {
                            host        : 'string',
                            username    : 'string',
                            password    : 'string',
                            bbsTag      : 'string',
                            sshPort     : 'number',
                            rloginPort  : 'number',
                        },
                        callback
                    );
                },
                function establishSecureConnection(callback) {
                    self.client.term.write(resetScreen());
                    self.client.term.write('Connecting to DoorParty, please wait...\n');

                    const sshClient = new SSHClient();

                    let pipeRestored = false;
                    let pipedStream;
                    let doorTracking;

                    const restorePipe = function() {
                        if(pipedStream && !pipeRestored && !clientTerminated) {
                            self.client.term.output.unpipe(pipedStream);
                            self.client.term.output.resume();

                            if(doorTracking) {
                                trackDoorRunEnd(doorTracking);
                            }
                        }
                    };

                    sshClient.on('ready', () => {
                        //  track client termination so we can clean up early
                        self.client.once('end', () => {
                            self.client.log.info('Connection ended. Terminating DoorParty connection');
                            clientTerminated = true;
                            sshClient.end();
                        });

                        //  establish tunnel for rlogin
                        sshClient.forwardOut('127.0.0.1', self.config.sshPort, self.config.host, self.config.rloginPort, (err, stream) => {
                            if(err) {
                                return callback(Errors.General('Failed to establish tunnel'));
                            }

                            doorTracking = trackDoorRunBegin(self.client);

                            //
                            //  Send rlogin
                            //  DoorParty wants the "server username" portion to be in the format of [BBS_TAG]USERNAME, e.g.
                            //  [XA]nuskooler
                            //
                            const rlogin = `\x00${self.client.user.username}\x00[${self.config.bbsTag}]${self.client.user.username}\x00${self.client.term.termType}\x00`;
                            stream.write(rlogin);

                            pipedStream = stream;   //  :TODO: this is hacky...
                            self.client.term.output.pipe(stream);

                            stream.on('data', d => {
                                //  :TODO: we should just pipe this...
                                self.client.term.rawWrite(d);
                            });

                            stream.on('close', () => {
                                restorePipe();
                                sshClient.end();
                            });
                        });
                    });

                    sshClient.on('error', err => {
                        self.client.log.info(`DoorParty SSH client error: ${err.message}`);
                        trackDoorRunEnd(doorTracking);
                    });

                    sshClient.on('close', () => {
                        restorePipe();
                        callback(null);
                    });

                    sshClient.connect( {
                        host        : self.config.host,
                        port        : self.config.sshPort,
                        username    : self.config.username,
                        password    : self.config.password,
                    });

                    //  note: no explicit callback() until we're finished!
                }
            ],
            err => {
                if(err) {
                    self.client.log.warn( { error : err.message }, 'DoorParty error');
                }

                //  if the client is still here, go to previous
                if(!clientTerminated) {
                    self.prevMenu();
                }
            }
        );
    }
};
<commit_msg>Hang after exiting DoorParty! #282<commit_after>/* jslint node: true */
'use strict';

//  enigma-bbs
const { MenuModule }    = require('./menu_module.js');
const { resetScreen }   = require('./ansi_term.js');
const { Errors }        = require('./enig_error.js');
const {
    trackDoorRunBegin,
    trackDoorRunEnd
}                       = require('./door_util.js');

//  deps
const async         = require('async');
const SSHClient     = require('ssh2').Client;

exports.moduleInfo = {
    name    : 'DoorParty',
    desc    : 'DoorParty Access Module',
    author  : 'NuSkooler',
};

exports.getModule = class DoorPartyModule extends MenuModule {
    constructor(options) {
        super(options);

        //  establish defaults
        this.config             = options.menuConfig.config;
        this.config.host        = this.config.host || 'dp.throwbackbbs.com';
        this.config.sshPort     = this.config.sshPort || 2022;
        this.config.rloginPort  = this.config.rloginPort || 513;
    }

    initSequence() {
        let clientTerminated;
        const self = this;

        async.series(
            [
                function validateConfig(callback) {
                    return self.validateConfigFields(
                        {
                            host        : 'string',
                            username    : 'string',
                            password    : 'string',
                            bbsTag      : 'string',
                            sshPort     : 'number',
                            rloginPort  : 'number',
                        },
                        callback
                    );
                },
                function establishSecureConnection(callback) {
                    self.client.term.write(resetScreen());
                    self.client.term.write('Connecting to DoorParty, please wait...\n');

                    const sshClient = new SSHClient();

                    let pipeRestored = false;
                    let pipedStream;
                    let doorTracking;

                    const restorePipe = function() {
                        if(pipedStream && !pipeRestored && !clientTerminated) {
                            self.client.term.output.unpipe(pipedStream);
                            self.client.term.output.resume();

                            if(doorTracking) {
                                trackDoorRunEnd(doorTracking);
                                doorTracking = null;
                            }
                        }
                    };

                    sshClient.on('ready', () => {
                        //  track client termination so we can clean up early
                        self.client.once('end', () => {
                            self.client.log.info('Connection ended. Terminating DoorParty connection');
                            clientTerminated = true;
                            sshClient.end();
                        });

                        //  establish tunnel for rlogin
                        sshClient.forwardOut('127.0.0.1', self.config.sshPort, self.config.host, self.config.rloginPort, (err, stream) => {
                            if(err) {
                                return callback(Errors.General('Failed to establish tunnel'));
                            }

                            doorTracking = trackDoorRunBegin(self.client);

                            //
                            //  Send rlogin
                            //  DoorParty wants the "server username" portion to be in the format of [BBS_TAG]USERNAME, e.g.
                            //  [XA]nuskooler
                            //
                            const rlogin = `\x00${self.client.user.username}\x00[${self.config.bbsTag}]${self.client.user.username}\x00${self.client.term.termType}\x00`;
                            stream.write(rlogin);

                            pipedStream = stream;   //  :TODO: this is hacky...
                            self.client.term.output.pipe(stream);

                            stream.on('data', d => {
                                //  :TODO: we should just pipe this...
                                self.client.term.rawWrite(d);
                            });

                            stream.on('end', () => {
                                sshClient.end();
                            });

                            stream.on('close', () => {
                                restorePipe();
                                sshClient.end();
                            });
                        });
                    });

                    sshClient.on('error', err => {
                        self.client.log.info(`DoorParty SSH client error: ${err.message}`);
                        trackDoorRunEnd(doorTracking);
                    });

                    sshClient.on('close', () => {
                        restorePipe();
                        callback(null);
                    });

                    sshClient.connect( {
                        host        : self.config.host,
                        port        : self.config.sshPort,
                        username    : self.config.username,
                        password    : self.config.password,
                    });

                    //  note: no explicit callback() until we're finished!
                }
            ],
            err => {
                if(err) {
                    self.client.log.warn( { error : err.message }, 'DoorParty error');
                }

                //  if the client is still here, go to previous
                if(!clientTerminated) {
                    self.prevMenu();
                }
            }
        );
    }
};
<|endoftext|>


<commit_before>var dot = require('graphlib-dot');
var types = require('./types');
var graph = require('./graph');
var linearize = require('./linearize');
var stream = require('./stream');
var stageLoader = require('./stage-loader');
var assert = require('chai').assert;

function mkPipe(nodeName, inGraph) {
  var options = inGraph.node(nodeName);
  var stageName = nodeName;
  if (options !== undefined) {
    if (options.stage) {
      stageName = options.stage;
    } else if (options.label) {
      stageName = options.label;
    }
  }
  var result = new graph.Pipe(stageName, options);
  result.nodeName = nodeName;
  return result;
}

function doExperiment() {
  return {
    impl: function(data, cb) {
      var inGraph = dot.read(data);
      var edges = inGraph.edges();
      var pipes = {};
      for (var i = 0; i < edges.length; i++) {
        var edge = edges[i];
        if (!pipes[edge.v])
          pipes[edge.v] = mkPipe(edge.v, inGraph);
        if (!pipes[edge.w])
          pipes[edge.w] = mkPipe(edge.w, inGraph);
        graph.connect(pipes[edge.v], pipes[edge.w]);
      }
      var linear = linearize(pipes[edges[0].v].graph);
      var linearNames = linear.map(function(x) { return x.map(function(a) { return a.nodeName; })});

      var linearGroups = linearNames.map(function(a) { return a.map(function(x) {
        var result = [];
        var parent = inGraph.parent(x);
        while (parent !== undefined) {
          if (inGraph.node(parent).strategy == 'pipeline')
            result.push(parent);
          parent = inGraph.parent(parent);
        }
        return result;
      }); });

      linearGroups = linearGroups.map(function(x) {
        var result = [];
        for (var i = 0; i < x[0].length; i++) {
          for (var j = 1; j < x.length; j++) {
            if (x[j].indexOf(x[0][i]) == -1)
              break;
          }
          if (j == x.length)
            result.push(x[0][i]);
        }
        return result;
      });

      var stageStack = [[]];
      var groupStack = [];

      for (var i = 0; i < linear.length; i++) {
         for (var j = 0; j < linearGroups[i].length; j++) {
          if (groupStack.indexOf(linearGroups[i][j]) == -1) {
            groupStack.push(linearGroups[i][j]);
            stageStack.push([]);
          }
        }

        var streams = linear[i].map(function(pipe, idx) {
          var thisStream = stageLoader.stageSpecificationToStage(pipe.stageName, pipe.options);
          thisStream.setInput('efrom', idx + '');
          thisStream.setOutput('eto', idx + '');
          return thisStream;
        });
        stageStack[stageStack.length - 1] = stageStack[stageStack.length - 1].concat(streams);

        if (i == linear.length - 1)
          break;

        while (groupStack.length > 0 && (linearGroups[i + 1].indexOf(groupStack[groupStack.length - 1]) == -1)) {
          // we've reached the end of this group stack
          groupStack.pop();
          var stages = stageStack.pop(); // do wrapping here
          var consolidated = stream.stageWrapper(stages);
          stageStack[stageStack.length - 1].push(consolidated);
        }

        var outgoing = linear[i].map(function(pipe) { return pipe.out; }).filter(function(v, i, s) { return s.indexOf(v) == i; });
        var ins = outgoing.map(function(con) { return con.fromPipes; });
        ins = ins.map(function(a) { return a.map(function(b) { return linearNames[i].indexOf(b.nodeName); })});
        var outs = outgoing.map(function(con) { return con.toPipes; });
        outs = outs.map(function(a) { return a.map(function(b) { return linearNames[i + 1].indexOf(b.nodeName); })});
        var routingStage = new stream.RoutingStage(ins, outs);
        stageStack[stageStack.length - 1].push(routingStage);

      }

      assert(stageStack.length == 1);
      stageLoader.processStages(stageStack[0], cb, function(e) { throw e; });
    },
    name: 'doExperiment',
    input: types.string,
    output: types.unit
  };
}

module.exports.doExperiment = doExperiment;
<commit_msg>Rename things in experiment.js "stage" -> "phase".<commit_after>var dot = require('graphlib-dot');
var types = require('./types');
var graph = require('./graph');
var linearize = require('./linearize');
var stream = require('./stream');
var stageLoader = require('./stage-loader');
var assert = require('chai').assert;

function mkPipe(nodeName, inGraph) {
  var options = inGraph.node(nodeName);
  var phaseName = nodeName;
  if (options !== undefined) {
    if (options.stage) {
      phaseName = options.stage;
    } else if (options.label) {
      phaseName = options.label;
    }
  }
  var result = new graph.Pipe(phaseName, options);
  result.nodeName = nodeName;
  return result;
}

function doExperiment() {
  return {
    impl: function(data, cb) {
      var inGraph = dot.read(data);
      var edges = inGraph.edges();
      var pipes = {};
      for (var i = 0; i < edges.length; i++) {
        var edge = edges[i];
        if (!pipes[edge.v])
          pipes[edge.v] = mkPipe(edge.v, inGraph);
        if (!pipes[edge.w])
          pipes[edge.w] = mkPipe(edge.w, inGraph);
        graph.connect(pipes[edge.v], pipes[edge.w]);
      }
      var linear = linearize(pipes[edges[0].v].graph);
      var linearNames = linear.map(function(x) { return x.map(function(a) { return a.nodeName; })});

      var linearGroups = linearNames.map(function(a) { return a.map(function(x) {
        var result = [];
        var parent = inGraph.parent(x);
        while (parent !== undefined) {
          if (inGraph.node(parent).strategy == 'pipeline')
            result.push(parent);
          parent = inGraph.parent(parent);
        }
        return result;
      }); });

      linearGroups = linearGroups.map(function(x) {
        var result = [];
        for (var i = 0; i < x[0].length; i++) {
          for (var j = 1; j < x.length; j++) {
            if (x[j].indexOf(x[0][i]) == -1)
              break;
          }
          if (j == x.length)
            result.push(x[0][i]);
        }
        return result;
      });

      var phaseStack = [[]];
      var groupStack = [];

      for (var i = 0; i < linear.length; i++) {
         for (var j = 0; j < linearGroups[i].length; j++) {
          if (groupStack.indexOf(linearGroups[i][j]) == -1) {
            groupStack.push(linearGroups[i][j]);
            phaseStack.push([]);
          }
        }

        var streams = linear[i].map(function(pipe, idx) {
          var thisStream = stageLoader.stageSpecificationToStage(pipe.stageName, pipe.options);
          thisStream.setInput('efrom', idx + '');
          thisStream.setOutput('eto', idx + '');
          return thisStream;
        });
        phaseStack[phaseStack.length - 1] = phaseStack[phaseStack.length - 1].concat(streams);

        if (i == linear.length - 1)
          break;

        while (groupStack.length > 0 && (linearGroups[i + 1].indexOf(groupStack[groupStack.length - 1]) == -1)) {
          // we've reached the end of this group stack
          groupStack.pop();
          var phases = phaseStack.pop(); // do wrapping here
          var consolidated = stream.stageWrapper(phases);
          phaseStack[phaseStack.length - 1].push(consolidated);
        }

        var outgoing = linear[i].map(function(pipe) { return pipe.out; }).filter(function(v, i, s) { return s.indexOf(v) == i; });
        var ins = outgoing.map(function(con) { return con.fromPipes; });
        ins = ins.map(function(a) { return a.map(function(b) { return linearNames[i].indexOf(b.nodeName); })});
        var outs = outgoing.map(function(con) { return con.toPipes; });
        outs = outs.map(function(a) { return a.map(function(b) { return linearNames[i + 1].indexOf(b.nodeName); })});
        var routingStage = new stream.RoutingStage(ins, outs);
        phaseStack[phaseStack.length - 1].push(routingStage);

      }

      assert(phaseStack.length == 1);
      stageLoader.processStages(phaseStack[0], cb, function(e) { throw e; });
    },
    name: 'doExperiment',
    input: types.string,
    output: types.unit
  };
}

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