<commit_before>'use strict';

/*
 * @fileoverview Content system routing
 *
 */
const config = require('config');
const content = require('punchcard-content-types');
const multipart = require('connect-multiparty');
const uuid = require('uuid');
const _ = require('lodash');

const utils = require('../utils');
const database = require('../database');
const workflows = require('../workflows');

const multipartMiddleware = multipart();

/*
 * Content Route Resolution
 *
 * @param {object} application - Express Application
 * @returns {object} - Configured Express Application
 */
const routes = application => {
  return new Promise(resolve => {
    const app = application;
    const types = app.get('content-types');
    const allflows = app.get('workflows');

    /*
     * @name Content Home Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
    */
    app.get(`/${config.content.base}`, (req, res) => {
      res.render('content/home', {
        content: {
          home: config.content.home,
          base: config.content.base,
          types,
        },
      });
    });

    /*
     * @name Individual Content Type Landing Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type`, (req, res, next) => {
      const type = utils.singleItem('id', req.params.type.toLowerCase(), types);

      // check type exists
      if (!utils.content.check.type(req, type)) {
        return next();
      }

      return database
        .distinct(database.raw('ON (id) id'))
        .select('*')
        .from(`content-type--${type.id}`)
        .orderBy('id', 'DESC')
        .orderBy('revision', 'DESC').then(rws => {
          // add itentifier to each row
          const rows = utils.routes.identifier(rws, type);

          res.render('content/landing', {
            title: config.content.base,
            content: rows,
            type,
            config: config.content,
          });
        });
    });

    /*
     * @name Individual Content Type Add Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/${config.content.actions.add}`, (req, res, next) => {
      const type = utils.singleItem('id', req.params.type.toLowerCase(), types);
      const workflow = workflows.workflow(type, allflows, config, req);
      const errors = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].errors`, {});
      const values = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].content`, {});

      _.unset(req.session, 'form.content.add');

      // check type exists
      if (!utils.content.check.type(req, type)) {
        return next();
      }

      // check workflow exists
      if (!workflow) {
        return next();
      }

      const steps = (JSON.parse(JSON.stringify(workflow.steps))).reverse();
      const step = steps[steps.length - 1];

      return content.only(req.params.type.toLowerCase(), values, [type]).then(merged => {
        return content.form(merged, errors).then(form => {
          res.render('content/add', {
            form,
            action: req.url.replace(config.content.actions.add, config.content.actions.save),
            type,
            config: config.content,
            step,
          });
        });
      }).catch(e => {
        next(e);
      });
    });

    /*
     * @name Individual Piece of Content
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/:id`, (req, res, next) => {
      const type = utils.singleItem('id', req.params.type.toLowerCase(), types);
      const workflow = workflows.workflow(type, allflows, config);

      // check type exists
      if (!utils.content.check.type(req, type)) {
        return next();
      }

      // id in url is not UUID
      if (!utils.content.check.id(req)) {
        return next();
      }

      return database
        .select('*')
        .from(`content-type--${type.id}`)
        .where('id', req.params.id)
        .orderBy('revision', 'DESC').then(rws => {
          if (rws.length < 1) {
            _.set(req.session, '404', {
              message: config.content.messages.missing.id.replace('%type', req.params.type).replace('%id', req.params.id),
              safe: `/${config.content.base}/${req.params.type}`,
            });

            return next();
          }

          // add itentifier to each row
          const rows = utils.routes.identifier(rws, type);

          res.render('content/content', {
            title: config.content.messages.content.title.replace('%id', req.params.id),
            content: rows,
            type,
            workflow: _.cloneDeep(workflow).steps.reverse(),
            config: config.content,
          });

          return true;
        });
    });

    /*
     * @name Specific revision of an Individual Piece of Content
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/:id/:revision`, (req, res, next) => {
      const type = utils.singleItem('id', req.params.type.toLowerCase(), types);

      // check type exists
      if (!utils.content.check.type(req, type)) {
        return next();
      }

      // id in url is not UUID
      if (!utils.content.check.id(req)) {
        return next();
      }

      // revision in url is not a number
      if (!utils.content.check.revision(req)) {
        return next();
      }

      return database
        .select('*')
        .from(`content-type--${type.id}`)
        .where('revision', req.params.revision)
        .orderBy('revision', 'DESC').then(rws => {
          if (rws.length < 1) {
            _.set(req.session, '404', {
              message: config.content.messages.missing.revision.replace('%revision', req.params.revision).replace('%type', req.params.type).replace('%id', req.params.id),
              safe: `/${config.content.base}/${req.params.type}`,
            });

            return next();
          }

          // add itentifier to each row
          const rows = utils.routes.identifier(rws, type);

          res.render('content/content', {
            title: config.content.messages.revisions.title.replace('%revision', req.params.revision).replace('%id', req.params.id),
            content: rows,
            type,
            config: config.content,
          });

          return true;
        });
    });

    /*
     * @name Individual Content Type Edit Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/:id/:revision/${config.content.actions.edit}`, (req, res, next) => {
      const type = utils.singleItem('id', req.params.type.toLowerCase(), types);
      const workflow = workflows.workflow(type, allflows, config, req);
      const errors = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].errors`, {});
      const idSess = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].id`, {});
      const revisionSess = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].revision`, {});
      const values = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].content`, {});
      let data = {};

      // check type exists
      if (!utils.content.check.type(req, type)) {
        return next();
      }

      // id in url is not UUID
      if (!utils.content.check.id(req)) {
        return next();
      }

      // revision in url is not a number
      if (!utils.content.check.revision(req)) {
        return next();
      }

      // check workflow exists
      if (!workflow) {
        return next();
      }

      const steps = (JSON.parse(JSON.stringify(workflow.steps))).reverse();

      // new revision, re-start workflow process
      const step = steps[steps.length - 1];

      _.unset(req.session, 'form.content.add');
      _.set(req.session, 'referrer', req.get('Referrer'));

      // something went wrong on save:
      if (Object.keys(values).length > 0) {
        // add the previous session data back in
        _.set(req.session, 'form.content.add', {
          [req.params.type.toLowerCase()]: {
            id: idSess,
            revision: revisionSess,
          },
        });

        return content.only(req.params.type.toLowerCase(), values, [type]).then(merged => {
          return content.form(merged, errors).then(form => {
            res.render('content/add', {
              form,
              action: `/${config.content.base}/${req.params.type}/${config.content.actions.save}`,
              type,
              step,
              config: config.content,
            });
          });
        }).catch(e => {
          next(e);
        });
      }

      // eslint mad if no return, then mad at this else if it is there
      else { // eslint-disable-line no-else-return
        // Search for the revision
        return database(`content-type--${type.id}`).where({
          id: req.params.id,
          revision: req.params.revision,
        }).then(rows => {
          if (rows.length < 1) {
            _.set(req.session, '404', {
              message: config.content.messages.missing.revision.replace('%type', req.params.type).replace('%id', req.params.id).replace('%revision', req.params.revision),
              safe: `/${config.content.base}/${req.params.type}`,
            });

            return next();
          }
          data = rows[0].value;

          // add session data for this content
          _.set(req.session, 'form.content.add', {
            [req.params.type.toLowerCase()]: {
              id: rows[0].id,
              revision: rows[0].revision,
            },
          });

          return content.only(type.id, data);
        }).then(only => {
          return content.form(only);
        }).then(form => {
          res.render('content/add', {
            form,
            action: `/${config.content.base}/${req.params.type.toLowerCase()}/${config.content.actions.save}`,
            type,
            data,
            step,
            config: config.content,
          });
        }).catch(e => {
          next(e);
        });
      }
    });

    /*
     * @name Save - Post to Content Type
     * Save content type to db
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.post(`/${config.content.base}/:type/${config.content.actions.save}`, multipartMiddleware, (req, res, next) => {
      const type = utils.singleItem('id', req.params.type.toLowerCase(), types);
      const workflow = workflows.workflow(type, allflows, config);
      const referrer = _.get(req.session, 'referrer') || `/${config.content.base}/${req.params.type.toLowerCase()}`;
      let audits;
      let publishable = false;
      let check = 'publish';

      _.unset(req.session, 'referrer');

      // check type exists
      if (!utils.content.check.type(req, type)) {
        return next();
      }

      // check workflow exists
      if (!workflow) {
        return next();
      }

      if (req.body.submit === config.content.actions.new) {
        check = 'save';
      }

      // Validation
      const validated = content.form.validate(req.body, type, check);

      if (validated === true) {
        // Publishable
        if (check === 'publish') {
          publishable = true;
        }
        else if (content.form.validate(req.body, type, 'publish') === true) {
          publishable = true;
        }

        // id
        let id = uuid.v4();
        const sessionId = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].id`, '');
        if (sessionId) {
          id = sessionId;
        }

        // Sunrise/Sunset
        const sunrise = utils.time.iso(req.body['sunrise-date'], req.body['sunrise-time'], 'America/New_York');
        const sunset = utils.time.iso(req.body['sunset-date'], req.body['sunset-time'], 'America/New_York');

        // language
        let language = 'us-en';
        if (req.body.hasOwnProperty('language')) {
          language = req.body.language;
        }

        // approval step returns to first step after saving a new revision
        const steps = (JSON.parse(JSON.stringify(workflow.steps))).reverse();
        const approval = steps.length - 1;
        const request = _.clone(req, true);
        const rev = {
          approval,
        };
        const self = workflow.steps[approval].hasOwnProperty('self') && workflow.steps[approval].self === true;

        if (self) {
          rev.approval++;
        }

        if (check === 'publish') {
          if (self) {
            request.body['comment-textarea'] = 'Self published';
            request.body['action--select'] = 'self-published';
          }
          else {
            request.body['comment-textarea'] = 'content submitted';
            request.body['action--select'] = 'submit';
          }
        }

        audits = workflows.audits(rev, workflow, request);

        const data = utils.format(req.body);

        const insert = {
          id,
          language,
          sunrise,
          sunset,
          publishable,
          value: data,
          author: req.user.id,
        };

        return database(`content-type--${req.params.type.toLowerCase()}`).insert(_.merge({}, insert, audits)).returning(['id', 'revision']).then((latest) => {
          _.set(req.session, 'form.content.recent', {
            [req.params.type.toLowerCase()]: {
              id: latest.id,
              revision: latest.revision,
            },
          });
          res.redirect(referrer);
        }).catch(e => {
          next(e);
        });
      }

      // eslint mad if no return, then mad at this else if it is there
      else { // eslint-disable-line no-else-return
        _.set(req.session, 'form.content.add', {
          [req.params.type.toLowerCase()]: {
            errors: validated,
            content: utils.format(req.body),
          },
        });
        res.redirect(referrer);
      }

      return true;
    });

    resolve(app);
  });
};

module.exports = routes;
<commit_msg>:bug: Fix edit referrer issue<commit_after>'use strict';

/*
 * @fileoverview Content system routing
 *
 */
const config = require('config');
const content = require('punchcard-content-types');
const multipart = require('connect-multiparty');
const uuid = require('uuid');
const _ = require('lodash');

const utils = require('../utils');
const database = require('../database');
const workflows = require('../workflows');

const multipartMiddleware = multipart();

/*
 * Content Route Resolution
 *
 * @param {object} application - Express Application
 * @returns {object} - Configured Express Application
 */
const routes = application => {
  return new Promise(resolve => {
    const app = application;
    const types = app.get('content-types');
    const allflows = app.get('workflows');

    /*
     * @name Content Home Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
    */
    app.get(`/${config.content.base}`, (req, res) => {
      res.render('content/home', {
        content: {
          home: config.content.home,
          base: config.content.base,
          types,
        },
      });
    });

    /*
     * @name Individual Content Type Landing Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type`, (req, res, next) => {
      const type = utils.singleItem('id', req.params.type.toLowerCase(), types);

      // check type exists
      if (!utils.content.check.type(req, type)) {
        return next();
      }

      return database
        .distinct(database.raw('ON (id) id'))
        .select('*')
        .from(`content-type--${type.id}`)
        .orderBy('id', 'DESC')
        .orderBy('revision', 'DESC').then(rws => {
          // add itentifier to each row
          const rows = utils.routes.identifier(rws, type);

          res.render('content/landing', {
            title: config.content.base,
            content: rows,
            type,
            config: config.content,
          });
        });
    });

    /*
     * @name Individual Content Type Add Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/${config.content.actions.add}`, (req, res, next) => {
      const type = utils.singleItem('id', req.params.type.toLowerCase(), types);
      const workflow = workflows.workflow(type, allflows, config, req);
      const errors = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].errors`, {});
      const values = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].content`, {});

      _.unset(req.session, 'form.content.add');

      // check type exists
      if (!utils.content.check.type(req, type)) {
        return next();
      }

      // check workflow exists
      if (!workflow) {
        return next();
      }

      const steps = (JSON.parse(JSON.stringify(workflow.steps))).reverse();
      const step = steps[steps.length - 1];

      return content.only(req.params.type.toLowerCase(), values, [type]).then(merged => {
        return content.form(merged, errors).then(form => {
          res.render('content/add', {
            form,
            action: req.url.replace(config.content.actions.add, config.content.actions.save),
            type,
            config: config.content,
            step,
          });
        });
      }).catch(e => {
        next(e);
      });
    });

    /*
     * @name Individual Piece of Content
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/:id`, (req, res, next) => {
      const type = utils.singleItem('id', req.params.type.toLowerCase(), types);
      const workflow = workflows.workflow(type, allflows, config);

      // check type exists
      if (!utils.content.check.type(req, type)) {
        return next();
      }

      // id in url is not UUID
      if (!utils.content.check.id(req)) {
        return next();
      }

      return database
        .select('*')
        .from(`content-type--${type.id}`)
        .where('id', req.params.id)
        .orderBy('revision', 'DESC').then(rws => {
          if (rws.length < 1) {
            _.set(req.session, '404', {
              message: config.content.messages.missing.id.replace('%type', req.params.type).replace('%id', req.params.id),
              safe: `/${config.content.base}/${req.params.type}`,
            });

            return next();
          }

          // add itentifier to each row
          const rows = utils.routes.identifier(rws, type);

          res.render('content/content', {
            title: config.content.messages.content.title.replace('%id', req.params.id),
            content: rows,
            type,
            workflow: _.cloneDeep(workflow).steps.reverse(),
            config: config.content,
          });

          return true;
        });
    });

    /*
     * @name Specific revision of an Individual Piece of Content
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/:id/:revision`, (req, res, next) => {
      const type = utils.singleItem('id', req.params.type.toLowerCase(), types);

      // check type exists
      if (!utils.content.check.type(req, type)) {
        return next();
      }

      // id in url is not UUID
      if (!utils.content.check.id(req)) {
        return next();
      }

      // revision in url is not a number
      if (!utils.content.check.revision(req)) {
        return next();
      }

      return database
        .select('*')
        .from(`content-type--${type.id}`)
        .where('revision', req.params.revision)
        .orderBy('revision', 'DESC').then(rws => {
          if (rws.length < 1) {
            _.set(req.session, '404', {
              message: config.content.messages.missing.revision.replace('%revision', req.params.revision).replace('%type', req.params.type).replace('%id', req.params.id),
              safe: `/${config.content.base}/${req.params.type}`,
            });

            return next();
          }

          // add itentifier to each row
          const rows = utils.routes.identifier(rws, type);

          res.render('content/content', {
            title: config.content.messages.revisions.title.replace('%revision', req.params.revision).replace('%id', req.params.id),
            content: rows,
            type,
            config: config.content,
          });

          return true;
        });
    });

    /*
     * @name Individual Content Type Edit Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/:id/:revision/${config.content.actions.edit}`, (req, res, next) => {
      const type = utils.singleItem('id', req.params.type.toLowerCase(), types);
      const workflow = workflows.workflow(type, allflows, config, req);
      const errors = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].errors`, {});
      const idSess = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].id`, {});
      const revisionSess = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].revision`, {});
      const values = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].content`, {});
      let data = {};

      // check type exists
      if (!utils.content.check.type(req, type)) {
        return next();
      }

      // id in url is not UUID
      if (!utils.content.check.id(req)) {
        return next();
      }

      // revision in url is not a number
      if (!utils.content.check.revision(req)) {
        return next();
      }

      // check workflow exists
      if (!workflow) {
        return next();
      }

      const steps = (JSON.parse(JSON.stringify(workflow.steps))).reverse();

      // new revision, re-start workflow process
      const step = steps[steps.length - 1];

      _.unset(req.session, 'form.content.add');
      _.set(req.session, 'referrer', req.get('Referrer'));

      // something went wrong on save:
      if (Object.keys(values).length > 0) {
        // add the previous session data back in
        _.set(req.session, 'form.content.add', {
          [req.params.type.toLowerCase()]: {
            id: idSess,
            revision: revisionSess,
          },
        });

        return content.only(req.params.type.toLowerCase(), values, [type]).then(merged => {
          return content.form(merged, errors).then(form => {
            res.render('content/add', {
              form,
              action: `/${config.content.base}/${req.params.type}/${config.content.actions.save}`,
              type,
              step,
              config: config.content,
            });
          });
        }).catch(e => {
          next(e);
        });
      }

      // eslint mad if no return, then mad at this else if it is there
      else { // eslint-disable-line no-else-return
        // Search for the revision
        return database(`content-type--${type.id}`).where({
          id: req.params.id,
          revision: req.params.revision,
        }).then(rows => {
          if (rows.length < 1) {
            _.set(req.session, '404', {
              message: config.content.messages.missing.revision.replace('%type', req.params.type).replace('%id', req.params.id).replace('%revision', req.params.revision),
              safe: `/${config.content.base}/${req.params.type}`,
            });

            return next();
          }
          data = rows[0].value;

          // add session data for this content
          _.set(req.session, 'form.content.add', {
            [req.params.type.toLowerCase()]: {
              id: rows[0].id,
              revision: rows[0].revision,
            },
          });

          return content.only(type.id, data);
        }).then(only => {
          return content.form(only);
        }).then(form => {
          res.render('content/add', {
            form,
            action: `/${config.content.base}/${req.params.type.toLowerCase()}/${config.content.actions.save}`,
            type,
            data,
            step,
            config: config.content,
          });
        }).catch(e => {
          next(e);
        });
      }
    });

    /*
     * @name Save - Post to Content Type
     * Save content type to db
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.post(`/${config.content.base}/:type/${config.content.actions.save}`, multipartMiddleware, (req, res, next) => {
      const type = utils.singleItem('id', req.params.type.toLowerCase(), types);
      const workflow = workflows.workflow(type, allflows, config);
      const referrer = _.get(req.session, 'referrer') || `/${config.content.base}/${req.params.type.toLowerCase()}`;
      let audits;
      let publishable = false;
      let check = 'publish';

      _.unset(req.session, 'referrer');

      // check type exists
      if (!utils.content.check.type(req, type)) {
        return next();
      }

      // check workflow exists
      if (!workflow) {
        return next();
      }

      if (req.body.submit === config.content.actions.new) {
        check = 'save';
      }

      // Validation
      const validated = content.form.validate(req.body, type, check);

      if (validated === true) {
        // Publishable
        if (check === 'publish') {
          publishable = true;
        }
        else if (content.form.validate(req.body, type, 'publish') === true) {
          publishable = true;
        }

        // id
        let id = uuid.v4();
        const sessionId = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].id`, '');
        if (sessionId) {
          id = sessionId;
        }

        // Sunrise/Sunset
        const sunrise = utils.time.iso(req.body['sunrise-date'], req.body['sunrise-time'], 'America/New_York');
        const sunset = utils.time.iso(req.body['sunset-date'], req.body['sunset-time'], 'America/New_York');

        // language
        let language = 'us-en';
        if (req.body.hasOwnProperty('language')) {
          language = req.body.language;
        }

        // approval step returns to first step after saving a new revision
        const steps = (JSON.parse(JSON.stringify(workflow.steps))).reverse();
        const approval = steps.length - 1;
        const request = _.clone(req, true);
        const rev = {
          approval,
        };
        const self = workflow.steps[approval].hasOwnProperty('self') && workflow.steps[approval].self === true;

        if (self) {
          rev.approval++;
        }

        if (check === 'publish') {
          if (self) {
            request.body['comment-textarea'] = 'Self published';
            request.body['action--select'] = 'self-published';
          }
          else {
            request.body['comment-textarea'] = 'content submitted';
            request.body['action--select'] = 'submit';
          }
        }

        audits = workflows.audits(rev, workflow, request);

        const data = utils.format(req.body);

        const insert = {
          id,
          language,
          sunrise,
          sunset,
          publishable,
          value: data,
          author: req.user.id,
        };

        return database(`content-type--${req.params.type.toLowerCase()}`).insert(_.merge({}, insert, audits)).returning(['id', 'revision']).then((latest) => {
          _.set(req.session, 'form.content.recent', {
            [req.params.type.toLowerCase()]: {
              id: latest.id,
              revision: latest.revision,
            },
          });
          res.redirect(referrer);
        }).catch(e => {
          next(e);
        });
      }

      // eslint mad if no return, then mad at this else if it is there
      else { // eslint-disable-line no-else-return
        _.set(req.session, 'form.content.add', {
          [req.params.type.toLowerCase()]: {
            errors: validated,
            content: utils.format(req.body),
          },
        });
        res.redirect(req.get('Referrer'));
      }

      return true;
    });

    resolve(app);
  });
};

module.exports = routes;
<|endoftext|>


<commit_before>//node >  rename-me file version outputpath
//demo > node rename-me src/app.js public/

var fs = require('fs');
var filePath = process.argv[2]; //SOURCE FILE PATH ex: Desktop/excel.xlsx;
var version = process.argv[3]; //OUTPUT PATH ex: 1.2.3 - could be anything'
var outputfolder = process.argv[4]; //OUTPUT PATH ex: Desktop/'

var fileName = '',
    fileExtension = '',
    tempNameNoExtension = '',
    fileRenamed = '',
    finalOutputPath = '';

try {
    setup();
    rename();
    fs.stat(finalOutputPath, (err, stats) => {
        if (err) throw err;
        console.log('sucess:', `stats: ${JSON.stringify(stats)}`);
    });
} catch (ex) {
    console.log('ex:', ex.message());
}

function setup() {
    fileName = removePathFromFileName(filePath);
    fileExtension = getFileExtension(fileName);
    tempNameNoExtension = getFileNameWithoutExtension(fileName);
    fileRenamed = concatNamedVersion({
        name: tempNameNoExtension,
        version: version,
        extension: fileExtension
    });
    finalOutputPath = outputfolder + fileRenamed;
}

function rename() {
    fs.createReadStream(filePath).pipe(fs.createWriteStream(finalOutputPath));
};

function removePathFromFileName(input) {
    var output = input;

    //src/js/hello.js -> hello.js
    output = input.replace(/\w+\//g, '');

    return output;
};

function getFileExtension(input) {
    var output = input;

    //hello.js -> .js
    output = input.replace(/[0-9a-z-0-1]{1,}/, '');

    return output;
};

function getFileNameWithoutExtension(input) {
    var output = input;

    // hello.js -> hello.
    output = input.replace(/[0-9a-z]+$/, '');

    return output;
};

function concatNamedVersion(options) {
    var output = '';

    output = options.name + options.version + options.extension;

    return output;
};<commit_msg>Enable calling via require()<commit_after>'use-strict';
//node >  rename-me file version outputpath
//demo > node rename-me src/app.js 1.1.1 public/
//output > public/app.1.1.1.js

var fs = require('fs');
var filePath = process.argv[2]; //SOURCE FILE PATH ex: Desktop/excel.xlsx;
var version = process.argv[3]; //OUTPUT PATH ex: 1.2.3 - could be anything'
var outputfolder = process.argv[4]; //OUTPUT PATH ex: Desktop/'

var fileName = '',
    fileExtension = '',
    tempNameNoExtension = '',
    fileRenamed = '',
    finalOutputPath = '';

var renameMe = function (options) {

    filePath = options.filePath;
    version = options.version;
    outputfolder = options.outputfolder;

    try {
        setup();
        rename();
        fs.stat(finalOutputPath, (err, stats) => {
            if (err) throw err;
            console.log('sucess:', `stats: ${JSON.stringify(stats)}`);
        });
    } catch (ex) {
        console.log('ex:', ex.message());
    }

    function setup() {
        fileName = removePathFromFileName(filePath);
        fileExtension = getFileExtension(fileName);
        tempNameNoExtension = getFileNameWithoutExtension(fileName);
        fileRenamed = concatNamedVersion({
            name: tempNameNoExtension,
            version: version,
            extension: fileExtension
        });
        finalOutputPath = outputfolder + fileRenamed;
    }

    function rename() {
        fs.createReadStream(filePath)
            .pipe(fs.createWriteStream(finalOutputPath));
    };

    function removePathFromFileName(input) {
        var output = input;

        //src/js/hello.js -> hello.js
        output = input.replace(/.+([^\/])\//g, '');

        return output;
    };

    function getFileExtension(input) {
        var output = input;

        //hello.js -> .js
        output = input.replace(/[0-9a-z-0-1]{1,}/, '');

        return output;
    };

    function getFileNameWithoutExtension(input) {
        var output = input;

        // hello.js -> hello.
        output = input.replace(/[0-9a-z]+$/, '');

        return output;
    };

    function concatNamedVersion(options) {
        var output = '';

        output = options.name + options.version + options.extension;

        return output;
    };
}

//execute if called manually via terminal
if (process.argv[4]) {
    var options = {};
    options.filePath = filePath;
    options.version = version;
    options.outputfolder = outputfolder;
    renameMe(options);
}

module.exports = renameMe;<|endoftext|>


<commit_before>var
	extend              = req('/lib/utilities/extend'),
	has                 = req('/lib/utilities/has'),
	add                 = req('/lib/utilities/add'),
	remove              = req('/lib/utilities/remove'),
	getCurrentTimestamp = req('/lib/utilities/get-current-timestamp');

var
	Channel        = req('/lib/channel'),
	MessageBuilder = req('/lib/message-builder'),
	ModeActions    = req('/lib/constants/mode-actions'),
	ErrorReasons   = req('/lib/constants/error-reasons'),
	Commands       = req('/lib/constants/commands'),
	ErrorCodes     = req('/lib/constants/error-codes'),
	TargetTypes    = req('/lib/constants/target-types');

var
	NotOnChannelMessage        = req('/lib/messages/replies/not-on-channel'),
	BannedFromChannelMessage   = req('/lib/messages/replies/banned-from-channel'),
	InviteOnlyChannelMessage   = req('/lib/messages/replies/invite-only-channel'),
	ChannelTopicMessage        = req('/lib/messages/replies/channel-topic'),
	ChannelNoTopicMessage      = req('/lib/messages/replies/no-channel-topic'),
	ChannelTopicDetailsMessage = req('/lib/messages/replies/channel-topic-details'),
	NamesReplyMessage          = req('/lib/messages/replies/names-reply'),
	EndOfNamesMessage          = req('/lib/messages/replies/end-of-names'),
	ChannelIsFullMessage       = req('/lib/messages/replies/channel-is-full'),
	NoChannelModesMessage      = req('/lib/messages/replies/no-channel-modes'),
	UnknownModeMessage         = req('/lib/messages/replies/unknown-mode'),
	NeedMoreParametersMessage  = req('/lib/messages/replies/need-more-parameters');

var
	JoinMessage    = req('/lib/messages/commands/join'),
	ModeMessage    = req('/lib/messages/commands/mode'),
	PartMessage    = req('/lib/messages/commands/part'),
	PrivateMessage = req('/lib/messages/commands/private');

var
	InvalidModeActionError = req('/lib/errors/invalid-mode-action');

class ServerChannel extends Channel {

	constructor(name) {
		super(name);

		this.clients         = [ ];
		this.banned_clients  = [ ];
		this.invited_clients = [ ];
	}

	isClientBanned(client) {
		return has(this.banned_clients, client);
	}

	handleBannedClient(client) {
		var message = new BannedFromChannelMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	isInviteOnly() {
		return this.getChannelDetails().isInviteOnly();
	}

	isClientInvited(client) {
		return has(this.invited_clients, client);
	}

	revokeClientInvitation(client) {
		remove(client).from(this.invited_clients);
	}

	handleUninvitedClient(client) {
		var message = new InviteOnlyChannelMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	isKeyProtected() {
		return this.getChannelDetails().isKeyProtected();
	}

	doesKeyMatch(key) {
		return key === this.key;
	}

	isPublic() {
		return !this.isSecret() && !this.isKeyProtected();
	}

	isSecret() {
		return this.getChannelDetails().isSecret();
	}

	allowsModes() {
		return this.getChannelDetails().allowsModes();
	}

	isFull() {
		var channel_details = this.getChannelDetails();

		if (!channel_details.hasLimit()) {
			return false;
		}

		var limit = channel_details.getLimit();

		return this.clients.length >= limit;
	}

	hasTopic() {
		return this.topic !== null;
	}

	sendTopicToClient(client) {
		if (!this.hasTopic()) {
			return this.sendNoTopicMessageToClient(client);
		}

		var topic_message =  new ChannelTopicMessage();

		topic_message.setChannelName(this.getName());
		topic_message.setChannelTopic(this.topic);

		client.sendMessage(topic_message);

		var topic_details_message = new ChannelTopicDetailsMessage();

		topic_details_message.setChannelName(this.getName());
		topic_details_message.setAuthorUserId(this.getTopicAuthorUserId());
		topic_details_message.setTimestamp(this.getTopicTimestamp());

		client.sendMessage(topic_details_message);
	}

	sendNoTopicMessageToClient(client) {
		var message = new ChannelNoTopicMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	sendNotOnChannelMessageToClient(client) {
		var message = new NotOnChannelMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	getClientNames() {
		return this.clients.map(function map(client) {
			var
				user_details = client.getUserDetails(),
				nickname     = user_details.getNickname(),
				prefix       = user_details.getPrefixForChannel(this);

			return prefix + nickname;
		}, this);
	}

	getPrivacySignifier() {
		return this.getChannelDetails().getPrivacySignifier();
	}

	createNamesReplyMessageForClient(client) {
		var message = new NamesReplyMessage();

		message.setChannelName(this.getName());
		message.setOriginHostname(this.getHostname());
		message.setChannelPrivacySignifier(this.getPrivacySignifier());

		// Normally, the client is added as a target automatically when the
		// message is sent, but we want to add it upfront in order to ensure
		// that the character limit isn't exceeded.
		message.setTarget(client.getNickname());

		return message;
	}

	sendNamesToClient(client) {
		var
			names = this.getClientNames(),
			body  = names.join(' ');

		var messages = MessageBuilder.buildMultipleMessages(
			body,
			this.createNamesReplyMessageForClient.bind(this, client)
		);

		messages.forEach(client.sendMessage, client);

		this.sendEndOfNamesMessageToClient(client);
	}

	sendEndOfNamesMessageToClient(client) {
		var message = new EndOfNamesMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	dispatchJoinMessagesForClient(joining_client) {
		this.clients.forEach(function each(client) {
			var message = new JoinMessage();

			message.setOriginUserId(joining_client.getUserId());
			message.addChannelName(this.getName());

			client.sendMessage(message);
		}, this);
	}

	dispatchPartMessagesForClient(parting_client) {
		this.clients.forEach(function each(client) {
			var message = new PartMessage();

			message.setOriginUserId(parting_client.getUserId());
			message.addChannelName(this.getName());

			client.sendMessage(message);
		}, this);
	}

	addClient(client, key) {
		if (this.hasClient(client)) {
			// Er... The spec is actually not clear on what should happen
			// in this specific case. Maybe we should return ERR_USERONCHANNEL?
			return;
		}

		if (this.isClientBanned(client)) {
			return void this.handleBannedClient(client);
		}

		if (this.isInviteOnly() && !this.isClientInvited(client)) {
			return void this.handleUninvitedClient(client);
		}

		if (this.isKeyProtected() && !this.doesKeyMatch(key)) {
			this.handleClientWithBadKey(client);
		}

		if (this.isFull()) {
			return void this.handleExcessClient(client);
		}

		// TODO: BADCHANMASK

		add(client).to(this.clients);

		var
			user_details = client.getUserDetails(),
			channel_name = this.getName();

		user_details.addChannelName(channel_name);

		// If the user is the first to join this channel,
		// flag them as the channel operator:
		if (this.clients.length === 1) {
			user_details.setIsOperatorForChannelName(channel_name, true);
		}

		this.dispatchJoinMessagesForClient(client);

		if (this.hasTopic()) {
			this.sendTopicToClient(client);
		}

		this.sendNamesToClient(client);

		if (this.isClientInvited(client)) {
			this.revokeClientInvitation(client);
		}
	}

	removeClient(client) {
		if (!this.hasClient(client)) {
			return void this.sendNotOnChannelMessageToClient(client);
		}

		this.dispatchPartMessagesForClient(client);

		remove(client).from(this.clients);
		client.getUserDetails().removeChannelName(this.getName());
	}

	hasClient(client) {
		return has(this.clients, client);
	}

	isEmpty() {
		return this.clients.length === 0;
	}

	/**
	 * Allows hard-coding the list of clients for a specific channel.
	 * This is used for one-off channels, where we really just need
	 * to tap into this class's logic for a group of users at a fixed point
	 * in time.
	 *
	 * @param   {ClientConnection[]} clients
	 * @returns {self}
	 */
	setClients(clients) {
		this.clients = clients;
		return this;
	}

	handleClientMessage(client, message) {
		// TODO: permissions

		this.clients.forEach(function each(current_client) {
			if (client === current_client) {
				return;
			}

			var outbound_message = new PrivateMessage();

			outbound_message.setOriginUserId(client.getUserId());
			outbound_message.setMessageBody(message.getMessageBody());
			outbound_message.setMessageTarget(this.getName());

			current_client.sendMessage(outbound_message);
		});
	}

	handleClientTopicMessage(client, message) {
		if (!this.hasClient(client)) {
			return void this.sendNotOnChannelMessageToClient(client);
		}

		// TODO: permissions

		if (!message.hasChannelTopic()) {
			return this.sendTopicToClient(client);
		}

		this.setTopic(message.getChannelTopic());

		var user_id = message.getOriginUserId();

		this.setTopicAuthorUserId(user_id);

		this.setTopicTimestamp(getCurrentTimestamp());

		this.clients.forEach(function each(target_client) {
			target_client.sendMessage(message);
		}, this);
	}

	handleClientModeMessage(client, message) {
		if (!this.allowsModes()) {
			return void this.sendModesNotAllowedMessageToClient(client);
		}

		var
			mode_changes       = message.getModeChanges(),
			successful_changes = [ ];

		mode_changes.forEach(function each(mode_change) {
			var was_successful = this.handleClientModeChange(
				client,
				mode_change
			);

			if (was_successful) {
				successful_changes.push(mode_change);
			}
		}, this);

		if (successful_changes.length > 0) {
			this.dispatchModeMessageForClientModeChanges(
				client,
				successful_changes
			);
		}
	}

	dispatchModeMessageForClientModeChanges(changing_client, mode_changes) {
		this.clients.forEach(function each(client) {
			var message = new ModeMessage();

			message.setOriginUserId(changing_client.getUserId());
			message.setTargetType(TargetTypes.CHANNEL);
			message.setChannelName(this.getName());

			mode_changes.forEach(function each(mode_change) {
				message.addModeChange(mode_change);
			});

			client.sendMessage(message);
		}, this);
	}

	sendModesNotAllowedMessageToClient(client) {
		var message = new NoChannelModesMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	handleClientModeChange(client, mode_change) {
		var
			mode           = mode_change.getMode(),
			server_details = this.getServerDetails();

		if (
			   !server_details.hasChannelMode(mode)
			&& !server_details.hasChannelUserMode(mode)
		) {
			this.sendUnknownModeMessageToClientForModeChange(
				client,
				mode_change
			);

			return false;
		}

		try {
			mode_change.validate();
		} catch (error) {
			this.handleClientModeChangeError(client, error);
			return false;
		}

		if (!this.clientHasPermissionToSetMode(client, mode)) {
			this.sendNoPrivilegesMessageToClientForModeChange(
				client,
				mode_change
			);
			return false;
		}

		var
			channel_details = this.getChannelDetails(),
			action          = mode_change.getAction();

		switch (action) {
			case ModeActions.ADD:
				return channel_details.applyAdditionModeChange(mode_change);

			case ModeActions.REMOVE:
				return channel_details.applyRemovalModeChange(mode_change);

			default:
				throw new InvalidModeActionError(mode, ErrorReasons.WRONG_TYPE);
		}
	}

	clientHasPermissionToSetMode(client, mode) {
		return client.getUserDetails().isOperatorForChannel(this);
	}

	handleClientModeChangeError(client, error) {
		var code = error.getCode();

		switch (code) {
			case ErrorCodes.INVALID_MODE_PARAMETERS:
				return this.handleClientModeChangeInvalidParametersError(
					client,
					error
				);

			default:
				throw error;
		}
	}

	handleClientModeChangeInvalidParametersError(client, error) {
		var reason = error.getReason();

		if (reason === ErrorReasons.NOT_ENOUGH_PARAMETERS) {
			let message = new NeedMoreParametersMessage();

			message.setAttemptedCommand(Commands.MODE);

			client.sendMessage(message);
			return;
		}

		throw error;
	}

	sendUnknownModeMessageToClientForModeChange(client, mode_change) {
		var message = new UnknownModeMessage();

		message.setMode(mode_change.getMode());
		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	handleExcessClient(client) {
		var message = new ChannelIsFullMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	getObserversForClient(client) {
		if (!this.hasClient(client)) {
			return [ ];
		}

		// TODO: More fine-grained logic here; ie, determine when the
		// user is invisible to other clients based on modes etc.
		return this.clients.slice(0);
	}

	setServerDetails(server_details) {
		this.server_details = server_details;
	}

	getServerDetails() {
		return this.server_details;
	}

	getHostname() {
		return this.getServerDetails().getHostname();
	}

	destroy() {
		super.destroy();

		this.clients         = null;
		this.banned_clients  = null;
		this.invited_clients = null;
		this.server_details  = null;
	}

}

extend(ServerChannel.prototype, {

	clients:         null,
	banned_clients:  null,
	invited_clients: null,
	key:             null,
	server_details:  null

});

module.exports = ServerChannel;
<commit_msg>Use correct execution context when forwarding channel messages to clients<commit_after>var
	extend              = req('/lib/utilities/extend'),
	has                 = req('/lib/utilities/has'),
	add                 = req('/lib/utilities/add'),
	remove              = req('/lib/utilities/remove'),
	getCurrentTimestamp = req('/lib/utilities/get-current-timestamp');

var
	Channel        = req('/lib/channel'),
	MessageBuilder = req('/lib/message-builder'),
	ModeActions    = req('/lib/constants/mode-actions'),
	ErrorReasons   = req('/lib/constants/error-reasons'),
	Commands       = req('/lib/constants/commands'),
	ErrorCodes     = req('/lib/constants/error-codes'),
	TargetTypes    = req('/lib/constants/target-types');

var
	NotOnChannelMessage        = req('/lib/messages/replies/not-on-channel'),
	BannedFromChannelMessage   = req('/lib/messages/replies/banned-from-channel'),
	InviteOnlyChannelMessage   = req('/lib/messages/replies/invite-only-channel'),
	ChannelTopicMessage        = req('/lib/messages/replies/channel-topic'),
	ChannelNoTopicMessage      = req('/lib/messages/replies/no-channel-topic'),
	ChannelTopicDetailsMessage = req('/lib/messages/replies/channel-topic-details'),
	NamesReplyMessage          = req('/lib/messages/replies/names-reply'),
	EndOfNamesMessage          = req('/lib/messages/replies/end-of-names'),
	ChannelIsFullMessage       = req('/lib/messages/replies/channel-is-full'),
	NoChannelModesMessage      = req('/lib/messages/replies/no-channel-modes'),
	UnknownModeMessage         = req('/lib/messages/replies/unknown-mode'),
	NeedMoreParametersMessage  = req('/lib/messages/replies/need-more-parameters');

var
	JoinMessage    = req('/lib/messages/commands/join'),
	ModeMessage    = req('/lib/messages/commands/mode'),
	PartMessage    = req('/lib/messages/commands/part'),
	PrivateMessage = req('/lib/messages/commands/private');

var
	InvalidModeActionError = req('/lib/errors/invalid-mode-action');

class ServerChannel extends Channel {

	constructor(name) {
		super(name);

		this.clients         = [ ];
		this.banned_clients  = [ ];
		this.invited_clients = [ ];
	}

	isClientBanned(client) {
		return has(this.banned_clients, client);
	}

	handleBannedClient(client) {
		var message = new BannedFromChannelMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	isInviteOnly() {
		return this.getChannelDetails().isInviteOnly();
	}

	isClientInvited(client) {
		return has(this.invited_clients, client);
	}

	revokeClientInvitation(client) {
		remove(client).from(this.invited_clients);
	}

	handleUninvitedClient(client) {
		var message = new InviteOnlyChannelMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	isKeyProtected() {
		return this.getChannelDetails().isKeyProtected();
	}

	doesKeyMatch(key) {
		return key === this.key;
	}

	isPublic() {
		return !this.isSecret() && !this.isKeyProtected();
	}

	isSecret() {
		return this.getChannelDetails().isSecret();
	}

	allowsModes() {
		return this.getChannelDetails().allowsModes();
	}

	isFull() {
		var channel_details = this.getChannelDetails();

		if (!channel_details.hasLimit()) {
			return false;
		}

		var limit = channel_details.getLimit();

		return this.clients.length >= limit;
	}

	hasTopic() {
		return this.topic !== null;
	}

	sendTopicToClient(client) {
		if (!this.hasTopic()) {
			return this.sendNoTopicMessageToClient(client);
		}

		var topic_message =  new ChannelTopicMessage();

		topic_message.setChannelName(this.getName());
		topic_message.setChannelTopic(this.topic);

		client.sendMessage(topic_message);

		var topic_details_message = new ChannelTopicDetailsMessage();

		topic_details_message.setChannelName(this.getName());
		topic_details_message.setAuthorUserId(this.getTopicAuthorUserId());
		topic_details_message.setTimestamp(this.getTopicTimestamp());

		client.sendMessage(topic_details_message);
	}

	sendNoTopicMessageToClient(client) {
		var message = new ChannelNoTopicMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	sendNotOnChannelMessageToClient(client) {
		var message = new NotOnChannelMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	getClientNames() {
		return this.clients.map(function map(client) {
			var
				user_details = client.getUserDetails(),
				nickname     = user_details.getNickname(),
				prefix       = user_details.getPrefixForChannel(this);

			return prefix + nickname;
		}, this);
	}

	getPrivacySignifier() {
		return this.getChannelDetails().getPrivacySignifier();
	}

	createNamesReplyMessageForClient(client) {
		var message = new NamesReplyMessage();

		message.setChannelName(this.getName());
		message.setOriginHostname(this.getHostname());
		message.setChannelPrivacySignifier(this.getPrivacySignifier());

		// Normally, the client is added as a target automatically when the
		// message is sent, but we want to add it upfront in order to ensure
		// that the character limit isn't exceeded.
		message.setTarget(client.getNickname());

		return message;
	}

	sendNamesToClient(client) {
		var
			names = this.getClientNames(),
			body  = names.join(' ');

		var messages = MessageBuilder.buildMultipleMessages(
			body,
			this.createNamesReplyMessageForClient.bind(this, client)
		);

		messages.forEach(client.sendMessage, client);

		this.sendEndOfNamesMessageToClient(client);
	}

	sendEndOfNamesMessageToClient(client) {
		var message = new EndOfNamesMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	dispatchJoinMessagesForClient(joining_client) {
		this.clients.forEach(function each(client) {
			var message = new JoinMessage();

			message.setOriginUserId(joining_client.getUserId());
			message.addChannelName(this.getName());

			client.sendMessage(message);
		}, this);
	}

	dispatchPartMessagesForClient(parting_client) {
		this.clients.forEach(function each(client) {
			var message = new PartMessage();

			message.setOriginUserId(parting_client.getUserId());
			message.addChannelName(this.getName());

			client.sendMessage(message);
		}, this);
	}

	addClient(client, key) {
		if (this.hasClient(client)) {
			// Er... The spec is actually not clear on what should happen
			// in this specific case. Maybe we should return ERR_USERONCHANNEL?
			return;
		}

		if (this.isClientBanned(client)) {
			return void this.handleBannedClient(client);
		}

		if (this.isInviteOnly() && !this.isClientInvited(client)) {
			return void this.handleUninvitedClient(client);
		}

		if (this.isKeyProtected() && !this.doesKeyMatch(key)) {
			this.handleClientWithBadKey(client);
		}

		if (this.isFull()) {
			return void this.handleExcessClient(client);
		}

		// TODO: BADCHANMASK

		add(client).to(this.clients);

		var
			user_details = client.getUserDetails(),
			channel_name = this.getName();

		user_details.addChannelName(channel_name);

		// If the user is the first to join this channel,
		// flag them as the channel operator:
		if (this.clients.length === 1) {
			user_details.setIsOperatorForChannelName(channel_name, true);
		}

		this.dispatchJoinMessagesForClient(client);

		if (this.hasTopic()) {
			this.sendTopicToClient(client);
		}

		this.sendNamesToClient(client);

		if (this.isClientInvited(client)) {
			this.revokeClientInvitation(client);
		}
	}

	removeClient(client) {
		if (!this.hasClient(client)) {
			return void this.sendNotOnChannelMessageToClient(client);
		}

		this.dispatchPartMessagesForClient(client);

		remove(client).from(this.clients);
		client.getUserDetails().removeChannelName(this.getName());
	}

	hasClient(client) {
		return has(this.clients, client);
	}

	isEmpty() {
		return this.clients.length === 0;
	}

	/**
	 * Allows hard-coding the list of clients for a specific channel.
	 * This is used for one-off channels, where we really just need
	 * to tap into this class's logic for a group of users at a fixed point
	 * in time.
	 *
	 * @param   {ClientConnection[]} clients
	 * @returns {self}
	 */
	setClients(clients) {
		this.clients = clients;
		return this;
	}

	handleClientMessage(client, message) {
		// TODO: permissions

		this.clients.forEach(function each(current_client) {
			if (client === current_client) {
				return;
			}

			var outbound_message = new PrivateMessage();

			outbound_message.setOriginUserId(client.getUserId());
			outbound_message.setMessageBody(message.getMessageBody());
			outbound_message.setMessageTarget(this.getName());

			current_client.sendMessage(outbound_message);
		}, this);
	}

	handleClientTopicMessage(client, message) {
		if (!this.hasClient(client)) {
			return void this.sendNotOnChannelMessageToClient(client);
		}

		// TODO: permissions

		if (!message.hasChannelTopic()) {
			return this.sendTopicToClient(client);
		}

		this.setTopic(message.getChannelTopic());

		var user_id = message.getOriginUserId();

		this.setTopicAuthorUserId(user_id);

		this.setTopicTimestamp(getCurrentTimestamp());

		this.clients.forEach(function each(target_client) {
			target_client.sendMessage(message);
		}, this);
	}

	handleClientModeMessage(client, message) {
		if (!this.allowsModes()) {
			return void this.sendModesNotAllowedMessageToClient(client);
		}

		var
			mode_changes       = message.getModeChanges(),
			successful_changes = [ ];

		mode_changes.forEach(function each(mode_change) {
			var was_successful = this.handleClientModeChange(
				client,
				mode_change
			);

			if (was_successful) {
				successful_changes.push(mode_change);
			}
		}, this);

		if (successful_changes.length > 0) {
			this.dispatchModeMessageForClientModeChanges(
				client,
				successful_changes
			);
		}
	}

	dispatchModeMessageForClientModeChanges(changing_client, mode_changes) {
		this.clients.forEach(function each(client) {
			var message = new ModeMessage();

			message.setOriginUserId(changing_client.getUserId());
			message.setTargetType(TargetTypes.CHANNEL);
			message.setChannelName(this.getName());

			mode_changes.forEach(function each(mode_change) {
				message.addModeChange(mode_change);
			});

			client.sendMessage(message);
		}, this);
	}

	sendModesNotAllowedMessageToClient(client) {
		var message = new NoChannelModesMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	handleClientModeChange(client, mode_change) {
		var
			mode           = mode_change.getMode(),
			server_details = this.getServerDetails();

		if (
			   !server_details.hasChannelMode(mode)
			&& !server_details.hasChannelUserMode(mode)
		) {
			this.sendUnknownModeMessageToClientForModeChange(
				client,
				mode_change
			);

			return false;
		}

		try {
			mode_change.validate();
		} catch (error) {
			this.handleClientModeChangeError(client, error);
			return false;
		}

		if (!this.clientHasPermissionToSetMode(client, mode)) {
			this.sendNoPrivilegesMessageToClientForModeChange(
				client,
				mode_change
			);
			return false;
		}

		var
			channel_details = this.getChannelDetails(),
			action          = mode_change.getAction();

		switch (action) {
			case ModeActions.ADD:
				return channel_details.applyAdditionModeChange(mode_change);

			case ModeActions.REMOVE:
				return channel_details.applyRemovalModeChange(mode_change);

			default:
				throw new InvalidModeActionError(mode, ErrorReasons.WRONG_TYPE);
		}
	}

	clientHasPermissionToSetMode(client, mode) {
		return client.getUserDetails().isOperatorForChannel(this);
	}

	handleClientModeChangeError(client, error) {
		var code = error.getCode();

		switch (code) {
			case ErrorCodes.INVALID_MODE_PARAMETERS:
				return this.handleClientModeChangeInvalidParametersError(
					client,
					error
				);

			default:
				throw error;
		}
	}

	handleClientModeChangeInvalidParametersError(client, error) {
		var reason = error.getReason();

		if (reason === ErrorReasons.NOT_ENOUGH_PARAMETERS) {
			let message = new NeedMoreParametersMessage();

			message.setAttemptedCommand(Commands.MODE);

			client.sendMessage(message);
			return;
		}

		throw error;
	}

	sendUnknownModeMessageToClientForModeChange(client, mode_change) {
		var message = new UnknownModeMessage();

		message.setMode(mode_change.getMode());
		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	handleExcessClient(client) {
		var message = new ChannelIsFullMessage();

		message.setChannelName(this.getName());

		client.sendMessage(message);
	}

	getObserversForClient(client) {
		if (!this.hasClient(client)) {
			return [ ];
		}

		// TODO: More fine-grained logic here; ie, determine when the
		// user is invisible to other clients based on modes etc.
		return this.clients.slice(0);
	}

	setServerDetails(server_details) {
		this.server_details = server_details;
	}

	getServerDetails() {
		return this.server_details;
	}

	getHostname() {
		return this.getServerDetails().getHostname();
	}

	destroy() {
		super.destroy();

		this.clients         = null;
		this.banned_clients  = null;
		this.invited_clients = null;
		this.server_details  = null;
	}

}

extend(ServerChannel.prototype, {

	clients:         null,
	banned_clients:  null,
	invited_clients: null,
	key:             null,
	server_details:  null

});

module.exports = ServerChannel;
<|endoftext|>


<commit_before>var LRUCache = Npm.require('lru-cache');

AppConfig = {
  env: getAppEnv(),
  authKey: getDebugAuthKey(),
  accessToken: new LRUCache({max: 1000}),
  _authorizedSessions: {}
};

var UAParser = Npm.require('ua-parser-js');
// Remove `Kadira.aa` once properly connected
var traceStore = Kadira.aa = new TraceStore();
traceStore.start();

SubHandlers = {
  timeline: [],
  listeners: []
};
var uniqueId = 0;
var serverId = Random.id();

Meteor.publish('kadira.debug.init', function(browserId, clientId, accessToken) {
  check(browserId, String);
  check(clientId, String);
  check(accessToken, Match.Any);

  var kadiraInfo = Kadira._getInfo();
  if(kadiraInfo) {
    var sessionId = kadiraInfo.session;

    if(AppConfig.env === 'production') {
      var tokenKey = AppConfig.authKey + "_" + accessToken;
      if(AppConfig.accessToken.get(tokenKey) !== accessToken) {
        // If the subcription request with an invalid accessToken
        // return without subscribe
        return;
      }

      AppConfig._authorizedSessions[sessionId] = true;
    }

    traceStore.registerSession(sessionId, browserId, clientId);

    this.onStop(function() {
      delete AppConfig._authorizedSessions[sessionId];
      traceStore.unregisterSession(browserId, clientId);
    });
  }
  this.ready();
});

Meteor.methods({
  'kadira.debug.updateTimeline': function(browserId, clientId, data) {
    check(browserId, String);
    check(clientId, String);
    check(data, Object);

    if(AppConfig.env === 'production') {
      // get session id from kadiraInfo Object
      var kadiraInfo = Kadira._getInfo();
      var sessionId = kadiraInfo.session;

      if(!AppConfig._authorizedSessions[sessionId]) {
        // not a valid session
        // return without proceed
        return;
      }
    }

    // Pick tracked server time events and push them to the
    // client's payload
    // So, we can send them back to the server
    var serverTimeEvents = traceStore.pickTimeEvents(browserId, clientId);
    serverTimeEvents.forEach(function(ev) {
      data.times.push(ev);
    });

    // set unique id for each server sessions
    data.serverId = serverId;

    // update timeline
    SubHandlers.timeline.forEach(function(sub) {
      var id = 'id' + ++uniqueId;
      sub.added('kdTimeline', id, {
        browserId: browserId,
        clientId: clientId,
        data: data
      });
      sub.removed('kdTimeline', id);
    });
  },

  'kadira.debug.getBrowserName': function(userAgent) {
    check(userAgent, String);
    var parser = new UAParser(userAgent);
    return parser.getResult().browser.name;
  },

  'kadira.debug.getTrace': function(browserId, clientId, type, id) {
    check(browserId, String);
    check(clientId, String);
    check(type, String);
    check(id, String);

    return traceStore.getTrace(browserId, clientId, type, id);
  },

  'kadira.debug.getAppEnv': function() {
    return AppConfig.env;
  },

  'kadira.debug.createAccessToken': function(authKey) {
    // when invalid auth key
    // return without proceed
    if(authKey !== AppConfig.authKey) {
      throw new Meteor.Error("Unauthorized");
      return;
    }

    var accessToken = generateToken(4);
    var tokenKey = authKey + "_" + accessToken;
    AppConfig.accessToken.set(tokenKey, accessToken);

    return accessToken;
  },

  'kadira.debug.reset': function() {
    AppConfig.accessToken.reset();
    AppConfig._authorizedSessions = {};
  }
});

Meteor.publish('kadira.debug.timeline', function(authKey) {
  // we check autKey only for production apps
  if(AppConfig.env === 'production') {
    if(authKey === AppConfig.authKey) {
      // authorize the session (timeline)
      var kadiraInfo = Kadira._getInfo();
      var sessionId = kadiraInfo.session;

      AppConfig._authorizedSessions[sessionId] = true;
    } else {
      // return when invalid authKey
      return;
    }
  }

  this.ready();
  var sub = this;

  SubHandlers.timeline.push(sub);
  updateListenersCount();
  sub.onStop(function() {
    var index = SubHandlers.timeline.indexOf(sub);
    SubHandlers.timeline.splice(index, 1);
    updateListenersCount();
  });
});

Meteor.publish('kadira.debug.listeners', function() {
  var sub = this;
  var timelineCount = SubHandlers.timeline.length;
  sub.added('kdInfo', 'listeners-count', {count: timelineCount});
  sub.ready();

  SubHandlers.listeners.push(sub);
  sub.onStop(function() {
    var index = SubHandlers.listeners.indexOf(sub);
    SubHandlers.listeners.splice(index, 1);
  });
});

function getAppEnv() {
  var env = 'development';
  if(!Package['kadira:runtime-dev']) {
    env = 'production';
  }
  return env;
}

function getDebugAuthKey() {
  // var defaultAuthKey = generateToken(4);
  var defaultAuthKey = 'AuthKey';
  var authKey = process.env.KADIRA_DEBUG_AUTH_KEY || defaultAuthKey;
  return authKey;
}

function generateToken(length) {
  var str = '';
  var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

  for( var i=0; i < length; i++ )
    str += possible.charAt(Math.floor(Math.random() * possible.length));

  return str;
}

function updateListenersCount() {
  SubHandlers.listeners.forEach(function(sub) {
    var timelineCount = SubHandlers.timeline.length;
    sub.changed('kdInfo', 'listeners-count', {count: timelineCount});
  });
}<commit_msg>remove test authKey<commit_after>var LRUCache = Npm.require('lru-cache');

AppConfig = {
  env: getAppEnv(),
  authKey: getDebugAuthKey(),
  accessToken: new LRUCache({max: 1000}),
  _authorizedSessions: {}
};

var UAParser = Npm.require('ua-parser-js');
// Remove `Kadira.aa` once properly connected
var traceStore = Kadira.aa = new TraceStore();
traceStore.start();

SubHandlers = {
  timeline: [],
  listeners: []
};
var uniqueId = 0;
var serverId = Random.id();

Meteor.publish('kadira.debug.init', function(browserId, clientId, accessToken) {
  check(browserId, String);
  check(clientId, String);
  check(accessToken, Match.Any);

  var kadiraInfo = Kadira._getInfo();
  if(kadiraInfo) {
    var sessionId = kadiraInfo.session;

    if(AppConfig.env === 'production') {
      var tokenKey = AppConfig.authKey + '_' + accessToken;
      if(AppConfig.accessToken.get(tokenKey) !== accessToken) {
        // If the subcription request with an invalid accessToken
        // return without subscribe
        return;
      }

      AppConfig._authorizedSessions[sessionId] = true;
    }

    traceStore.registerSession(sessionId, browserId, clientId);

    this.onStop(function() {
      delete AppConfig._authorizedSessions[sessionId];
      traceStore.unregisterSession(browserId, clientId);
    });
  }
  this.ready();
});

Meteor.methods({
  'kadira.debug.updateTimeline': function(browserId, clientId, data) {
    check(browserId, String);
    check(clientId, String);
    check(data, Object);

    if(AppConfig.env === 'production') {
      // get session id from kadiraInfo Object
      var kadiraInfo = Kadira._getInfo();
      var sessionId = kadiraInfo.session;

      if(!AppConfig._authorizedSessions[sessionId]) {
        // not a valid session
        // return without proceed
        return;
      }
    }

    // Pick tracked server time events and push them to the
    // client's payload
    // So, we can send them back to the server
    var serverTimeEvents = traceStore.pickTimeEvents(browserId, clientId);
    serverTimeEvents.forEach(function(ev) {
      data.times.push(ev);
    });

    // set unique id for each server sessions
    data.serverId = serverId;

    // update timeline
    SubHandlers.timeline.forEach(function(sub) {
      var id = 'id' + ++uniqueId;
      sub.added('kdTimeline', id, {
        browserId: browserId,
        clientId: clientId,
        data: data
      });
      sub.removed('kdTimeline', id);
    });
  },

  'kadira.debug.getBrowserName': function(userAgent) {
    check(userAgent, String);
    var parser = new UAParser(userAgent);
    return parser.getResult().browser.name;
  },

  'kadira.debug.getTrace': function(browserId, clientId, type, id) {
    check(browserId, String);
    check(clientId, String);
    check(type, String);
    check(id, String);

    return traceStore.getTrace(browserId, clientId, type, id);
  },

  'kadira.debug.getAppEnv': function() {
    return AppConfig.env;
  },

  'kadira.debug.createAccessToken': function(authKey) {
    // when invalid auth key
    // return without proceed
    if(authKey !== AppConfig.authKey) {
      throw new Meteor.Error("Unauthorized");
      return;
    }

    var accessToken = generateToken(4);
    var tokenKey = authKey + '_' + accessToken;
    AppConfig.accessToken.set(tokenKey, accessToken);

    return accessToken;
  },

  'kadira.debug.reset': function() {
    AppConfig.accessToken.reset();
    AppConfig._authorizedSessions = {};
  }
});

Meteor.publish('kadira.debug.timeline', function(authKey) {
  // check authKey only for production apps
  if(AppConfig.env === 'production') {
    if(authKey === AppConfig.authKey) {
      // authorize the session (timeline)
      var kadiraInfo = Kadira._getInfo();
      var sessionId = kadiraInfo.session;

      AppConfig._authorizedSessions[sessionId] = true;
    } else {
      // return when invalid authKey
      return;
    }
  }

  this.ready();
  var sub = this;

  SubHandlers.timeline.push(sub);
  updateListenersCount();
  sub.onStop(function() {
    var index = SubHandlers.timeline.indexOf(sub);
    SubHandlers.timeline.splice(index, 1);
    updateListenersCount();
  });
});

Meteor.publish('kadira.debug.listeners', function() {
  var sub = this;
  var timelineCount = SubHandlers.timeline.length;
  sub.added('kdInfo', 'listeners-count', {count: timelineCount});
  sub.ready();

  SubHandlers.listeners.push(sub);
  sub.onStop(function() {
    var index = SubHandlers.listeners.indexOf(sub);
    SubHandlers.listeners.splice(index, 1);
  });
});

function getAppEnv() {
  var env = 'development';
  if(!Package['kadira:runtime-dev']) {
    env = 'production';
  }
  return env;
}

function getDebugAuthKey() {
  var authKey = process.env.KADIRA_DEBUG_AUTH_KEY || null;
  return authKey;
}

function generateToken(length) {
  var str = '';
  var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

  for( var i=0; i < length; i++ )
    str += possible.charAt(Math.floor(Math.random() * possible.length));

  return str;
}

function updateListenersCount() {
  SubHandlers.listeners.forEach(function(sub) {
    var timelineCount = SubHandlers.timeline.length;
    sub.changed('kdInfo', 'listeners-count', {count: timelineCount});
  });
}<|endoftext|>


<commit_before>var parsers = {
  html: {
    jade: function(html) {
      return require('jade').render(html, {pretty: true, doctype: 'html'})
    }
  },
  css: {
    stylus: function(tag, css) {
      stylus = require('stylus')
      try {
        // optional nib support
        return stylus(str).include(require('nib').path).render()
      } catch(e) {
        return stylus.render(css)
      }
    }
  },
  js: {
    none: function(js) {
      return js
    },
    livescript: function(js) {
      return require('livescript').compile(js, { bare: true, header: false })
    },
    typescript: function(js) {
      return require('typescript-simple')(js)
    },
    es6: function(js) {
      return require('babel').transform(js, { blacklist: ['useStrict'] }).code
    },
    coffee: function(js) {
      return require('coffee-script').compile(js, { bare: true })
    }
  }
}

// fix 913
parsers.js.javascript = parsers.js.none
// 4 the nostalgics
parsers.js.coffeescript = parsers.js.coffee

module.exports = parsers
<commit_msg>added stylus and nib support<commit_after>var parsers = {
  html: {
    jade: function(html) {
      return require('jade').render(html, {pretty: true, doctype: 'html'})
    }
  },
  css: {
    stylus: function(tag, css) {
      var stylus = require('stylus')
      try {
        // optional nib support
        return stylus(css).use(require('nib')()).import('nib').render()
      } catch(e) {
        console.log(e)
        return stylus.render(css)
      }
    }
  },
  js: {
    none: function(js) {
      return js
    },
    livescript: function(js) {
      return require('livescript').compile(js, { bare: true, header: false })
    },
    typescript: function(js) {
      return require('typescript-simple')(js)
    },
    es6: function(js) {
      return require('babel').transform(js, { blacklist: ['useStrict'] }).code
    },
    coffee: function(js) {
      return require('coffee-script').compile(js, { bare: true })
    }
  }
}

// fix 913
parsers.js.javascript = parsers.js.none
// 4 the nostalgics
parsers.js.coffeescript = parsers.js.coffee

module.exports = parsers
<|endoftext|>


<commit_before>
//
//  editor.js
//
//  - class that handles the timestamps and whatnot on the server side.
//
//  Copyright (c) 2015 Visionist, Inc.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

var rooms   = require ('../models/Room.js');
var authors = require ('../models/Author.js');

var connectionHandler = function (socket) {
  socket.on('change', function(data) {
    var room   = rooms.getOrCreate (data.room);

    room.diffPatch (data.diff);

    // console.info (data.diff);
    // console.info (room.lines);
    // console.info ("\n\n");

    var payload = room.lines;

    for (var i = 0; i < payload.length; i++) {
      console.info (payload[i].client);

      var author = authors.getOrCreate (payload[i].client).id;
      payload[i].client = author;

      if (payload[i].client.id instanceof Object) {
        console.error (payload[i].client.id);
      }
    }

    //console.info (payload);

    socket.emit ('change', {
      payload : room.lines
    });
  });

  /*
   *  Subscribe to the given room.
   */
  socket.on ('subscribe', function(roomId) {
    socket.join (roomId, function (error) {
      if (error) {
        console.error ("an error occurred joining room with id " + roomId);
      } else {
        socket.emit ('connected', rooms.getOrCreate (roomId));
      }
    });
  });

  /*
   *  Required --
   *  -- not including it would cause the server to crash on socket error.
   */
  socket.on ('error', function (error) {
    console.error (error);
  });
};

module.exports = connectionHandler;
<commit_msg>Cleaning up editor.js<commit_after>
//
//  editor.js
//
//  - class that handles the timestamps and whatnot on the server side.
//
//  Copyright (c) 2015 Visionist, Inc.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

var rooms   = require ('../models/Room.js');
var authors = require ('../models/Author.js');

var connectionHandler = function (socket) {
  socket.on('change', function(data) {
    var room   = rooms.getOrCreate (data.room);

    room.diffPatch (data.diff);

    // console.info (data.diff);
    // console.info (room.lines);
    // console.info ("\n\n");

    var payload = room.lines;

    for (var i = 0; i < payload.length; i++) {
      // console.info (payload[i].client);

      var author = authors.getOrCreate (payload[i].client).id;
      payload[i].client = author;

      if (payload[i].client.id instanceof Object) {
        // console.error (payload[i].client.id);
      }
    }

    // console.info (payload);
    socket.emit ('change', {
      payload : room.lines
    });
  });

  /*
   *  Subscribe to the given room.
   */
  socket.on ('subscribe', function(roomId) {
    socket.join (roomId, function (error) {
      if (error) {
        console.error ("an error occurred joining room with id " + roomId);
      } else {
        socket.emit ('connected', rooms.getOrCreate (roomId));
      }
    });
  });

  /*
   *  Required --
   *  -- not including it would cause the server to crash on socket error.
   */
  socket.on ('error', function (error) {
    console.error (error);
  });
};

module.exports = connectionHandler;
<|endoftext|>


<commit_before>var EventEmitter = require("events").EventEmitter,
    crypto = require("crypto"),
    util = require("util"),
    debug = require("debug")("SOEInputStream");

function SOEInputStream(cryptoKey) {
    EventEmitter.call(this);

    this._sequences = [];
    this._nextSequence = 0;
    this._nextFragment = 0;
    this._lastFragment = -1;
    this._fragments = [];
    this._useEncryption = false;
    this._rc4 = crypto.createDecipheriv("rc4", cryptoKey, "");
}
util.inherits(SOEInputStream, EventEmitter);

function ZeroBuffer(length) {
    var buffer = new Buffer(length);
    for (var i=0;i<length;i++) {
        buffer[i] = 0;
    }
    return buffer;
}

function readDataLength(data, offset) {
    var dataLength = data.readUInt8(offset),
        n;
    if (dataLength == 0xFF) {
        if (data[offset+1] == 0xFF && data[offset+2] == 0xFF) {
            dataLength = data.readUInt32BE(offset+3);
            n = 7;
        } else {
            dataLength = data.readUInt16BE(offset+1);
            n = 3;
        }
    } else {
        n = 1;
    }
    return {
        value: dataLength,
        numBytes: n
    };
}

function parseChannelPacketData(data) {
    var appData = [],
        offset, dataLength;
    if (data[0] === 0x00 && data[1] == 0x19) {
        offset = 2;
        while (offset < data.length) {
            dataLength = readDataLength(data, offset);
            offset += dataLength.numBytes;
            appData.push(data.slice(offset, offset+dataLength.value));
            offset += dataLength.value;
        }
    } else {
        appData = [data];
    }
    return appData;
}

SOEInputStream.prototype._processDataFragments = function() {
    var nextFragment = this._nextFragment,
        lastFragment = this._lastFragment,
        fragments = this._fragments,
        head = fragments[nextFragment],
        data, totalSize,
        i = nextFragment,
        offset, fragment,
        appData = [];

    if (head) {
        if (head.singlePacket) {
            this._nextFragment = i + 1;
            appData = parseChannelPacketData(head);
        } else {
            totalSize = head.readUInt32BE(0);

            data = ZeroBuffer(totalSize);
            head.copy(data, 0, 4);
            offset = head.length - 4;
            for (i=i+1;i<=lastFragment;i++) {
                fragment = fragments[i];
                if (fragment) {
                    fragment.copy(data, offset);
                    offset += fragment.length;
                    if (offset > totalSize) {
                        throw "processDataFragments: offset > totalSize: " + offset + " > " + totalSize + " (sequence " + i + ") (fragment length " + fragment.length + ")";
                    }
                    if (offset == totalSize) {
                        this._nextFragment = i + 1;
                        appData = parseChannelPacketData(data);
                        break;
                    }
                } else {
                    break;
                }
            }
        }
    }

    if (appData.length) {
        for (i=0;i<appData.length;i++) {
            data = appData[i];
            if (this._useEncryption) {
                if (data.length > 1 && data.readUInt16LE(0) === 0) {
                    this._rc4.write(data.slice(1));
                } else {
                    this._rc4.write(data);
                }
                data = this._rc4.read();
            }
            this.emit("data", null, data);
        }
        this._processDataFragments();
    }
};

SOEInputStream.prototype.write = function(data, sequence, fragment) {
    var sequences = this._sequences;

    if (!sequences.length) {
        this._nextSequence = sequence;
        this._nextFragment = sequence;
        this._lastFragment = sequence - 1;
    }

    if (sequence < this._nextSequence) {
        // repeat packet, do nothing
        return;
    }

    if (sequence > this._lastFragment) {
        this._lastFragment = sequence;
    }

    this._fragments[sequence] = data;
    if (!fragment) {
        this._fragments[sequence].singlePacket = true;
    }

    if (sequence > this._nextSequence) {
        this.emit("outoforder", null, this._nextSequence, sequence);
        sequences[sequence] = true;
    } else {
        sequences[sequence] = true;
        while (sequences[sequence]) {
            sequence++;
        }
        this._nextSequence = sequence;

        this.emit("ack", null, sequence - 1);

        this._processDataFragments();
    }
};

SOEInputStream.prototype.toggleEncryption = function(value) {
    this._useEncryption = !!value;
};

exports.SOEInputStream = SOEInputStream;
<commit_msg>rework sequence handling to allow for > 65535 sequence ids<commit_after>var EventEmitter = require("events").EventEmitter,
    crypto = require("crypto"),
    util = require("util"),
    debug = require("debug")("SOEInputStream");

function SOEInputStream(cryptoKey) {
    EventEmitter.call(this);

    this._sequences = [];
    this._sequenceAdd = 0;
    this._nextSequence = -1;
    this._lastAck = -1;
    this._nextFragment = 0;
    this._lastProcessedFragment = -1;
    this._fragments = new Array(0x10000);
    this._useEncryption = false;
    this._rc4 = crypto.createDecipheriv("rc4", cryptoKey, "");
}
util.inherits(SOEInputStream, EventEmitter);

function ZeroBuffer(length) {
    var buffer = new Buffer(length);
    for (var i=0;i<length;i++) {
        buffer[i] = 0;
    }
    return buffer;
}

function readDataLength(data, offset) {
    var dataLength = data.readUInt8(offset),
        n;
    if (dataLength == 0xFF) {
        if (data[offset+1] == 0xFF && data[offset+2] == 0xFF) {
            dataLength = data.readUInt32BE(offset+3);
            n = 7;
        } else {
            dataLength = data.readUInt16BE(offset+1);
            n = 3;
        }
    } else {
        n = 1;
    }
    return {
        value: dataLength,
        numBytes: n
    };
}

function parseChannelPacketData(data) {
    var appData = [],
        offset, dataLength;
    if (data[0] === 0x00 && data[1] == 0x19) {
        offset = 2;
        while (offset < data.length) {
            dataLength = readDataLength(data, offset);
            offset += dataLength.numBytes;
            appData.push(data.slice(offset, offset+dataLength.value));
            offset += dataLength.value;
        }
    } else {
        appData = [data];
    }
    return appData;
}

SOEInputStream.prototype._processDataFragments = function() {
    var nextFragment = (this._lastProcessedFragment + 1) & 0xFFFF,
        fragments = this._fragments,
        head = fragments[nextFragment],
        data, totalSize, dataSize,
        offset, fragment,
        appData = [],
        i, j, k;
    if (head) {

        if (head.singlePacket) {
            this._lastProcessedFragment = nextFragment;
            appData = parseChannelPacketData(head);
            fragments[nextFragment] = null;
        } else {
            totalSize = head.readUInt32BE(0);
            dataSize = head.length - 4;

            data = ZeroBuffer(totalSize);
            head.copy(data, 0, 4);

            var fragmentIndices = [nextFragment];
            for (var i=1;i<65536;i++) {
                var j = (nextFragment + i) % 0xFFFF;
                fragment = fragments[j];
                if (fragment) {
                    fragmentIndices.push(j);
                    fragment.copy(data, dataSize);
                    dataSize += fragment.length;

                    if (dataSize > totalSize) {
                        throw "processDataFragments: offset > totalSize: " + dataSize + " > " + totalSize + " (sequence " + j + ") (fragment length " + fragment.length + ")";
                    }
                    if (dataSize == totalSize) {
                        for (k=0;k<fragmentIndices.length;k++) {
                            fragments[fragmentIndices[k]] = null;
                        }
                        this._lastProcessedFragment = j;
                        appData = parseChannelPacketData(data);
                        break;
                    }
                } else {
                    break;
                }
            }
        }
    }

    if (appData.length) {

        for (i=0;i<appData.length;i++) {
            data = appData[i];
            if (this._useEncryption) {
                // sometimes there's an extra 0x00 byte in the beginning that trips up the RC4 decyption
                if (data.length > 1 && data.readUInt16LE(0) === 0) {
                    this._rc4.write(data.slice(1));
                } else {
                    this._rc4.write(data);
                }
                data = this._rc4.read();
            }
            this.emit("data", null, data);
        }
        var me = this;
        setTimeout(function() {
            me._processDataFragments();
        },0);
        //this._processDataFragments();
    }
};

SOEInputStream.prototype.write = function(data, sequence, fragment) {
    if (this._nextSequence == -1) {
        this._nextSequence = sequence;
    }

    this._fragments[sequence] = data;
    if (!fragment) {
        this._fragments[sequence].singlePacket = true;
    }

    //console.log(sequence, this._nextSequence);
    if (sequence > this._nextSequence) {
        this.emit("outoforder", null, this._nextSequence, sequence);
    } else {

        var ack = sequence;
        for (var i=1;i<65536;i++) {
            var j = (this._lastAck + i) % 0xFFFF;
            if (this._fragments[j]) {
                ack = j;
            } else {
                break;
            }
        }
        if (ack > this._lastAck) {
            this._lastAck = ack;
            this.emit("ack", null, ack);
        }
        this._nextSequence = (ack + 1) & 0xFFFF;

        this._processDataFragments();
    }
};

SOEInputStream.prototype.toggleEncryption = function(value) {
    this._useEncryption = !!value;
};

exports.SOEInputStream = SOEInputStream;
<|endoftext|>


<commit_before>const fs = require('fs')
const glob = require('glob-fs')
const AstParser = require('./AstParser')

class FileReader {
  constructor (globber = glob({ gitignore: true }),
               reader = fs,
               astParser = new AstParser()) {
    this.globber = globber
    this.reader = reader
    this.astParser = astParser
  }

  read (pattern) {
    return new Promise((resolve, reject) => {
      const projectModules = {}
      this.globber.readdirStream(pattern)
        .on('data', file => {
          const { path } = file
          this.reader.readFile(path, 'utf-8', (err, text) => {
            if (err) {
              reject(err)
              return
            }
            const modules = this.astParser.parse(text)
            projectModules[path] = modules
            resolve(projectModules)
          })
        })
        .on('error', reject)
    })
  }
}

module.exports = FileReader
<commit_msg>fix: read all files from example<commit_after>const fs = require('fs')
const glob = require('glob-fs')
const AstParser = require('./AstParser')

class FileReader {
  constructor (globber = glob({ gitignore: true }),
               reader = fs,
               astParser = new AstParser()) {
    this.globber = globber
    this.reader = reader
    this.astParser = astParser
  }

  read (pattern) {
    return new Promise((resolve, reject) => {
      this.globber.readdirPromise(pattern)
        .then(filePaths => {
          const projectModules = {}
          filePaths.forEach(filePath => {
            const text = this.reader.readFileSync(filePath, 'utf-8')
            const modules = this.astParser.parse(text)
            projectModules[filePath] = modules
            resolve(projectModules)
          })
        })
        .catch(reject)
    })
  }
}

module.exports = FileReader
<|endoftext|>


<commit_before>function PostProcessor(renderer, oldRenderTarget, size, tonemap, opts) {

    opts = opts || {};
	this.superSample = opts.superSample;
	this.dither = opts.dither;

    this.renderer = renderer;
    this.oldRenderTarget = oldRenderTarget;

	this.size = size;

	var renderTarget = new THREE.WebGLRenderTarget(size.width, size.height);
    renderTarget.flipY = false;
    renderTarget.generateMipMaps = false;
    renderTarget.minFilter = THREE.NearestFilter;
    renderTarget.magFilter = THREE.NearestFilter;

    this.renderTarget = renderTarget;

    var scene = new THREE.Scene();
    var camera = new THREE.OrthographicCamera( -1, 1, -1, 1, -1, 1 );

    this.scene = scene;
    this.camera = camera;

    this.tonemap = tonemap;

	this.material = new THREE.ShaderMaterial({
    	side: THREE.DoubleSide,
		uniforms: {
			pixelSize: { type: 'v2', value: new THREE.Vector2(1.0 / oldRenderTarget.width, 1.0 / oldRenderTarget.height) },
			time: {type: 'f', value: 0.0},
			ditherStrength: {type: 'f', value: 0.007},
			texture1: {type: 't', value: oldRenderTarget},
			tonemap: {type: 't', value: tonemap},
			renderOriginal: {type: 'i', value: 0}
		},
		vertexShader:
		[
		'varying vec2 vUv;',
		'void main() {',
		'	vUv = uv;',
		'	gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); ',
		'}'
		].join('\n'),
		fragmentShader:
		[
		'uniform sampler2D texture1;',
		'uniform sampler2D tonemap;',
		'uniform vec2 pixelSize; ',
		'uniform float time;',
		'uniform float ditherStrength;',
		'uniform int renderOriginal;',

		'varying vec2 vUv; ',

		'#define LUT_FLIP_Y',

		'vec4 lookup(in vec4 textureColor, in sampler2D lookupTable1) {',
        '	textureColor = clamp(textureColor, 0.0, 1.0);',

        '	float blueColor = floor(textureColor.b * 64.0);',

        '	vec2 quad1;',
        '	quad1.y = floor(blueColor / 8.0) / 8.0;',
        '	quad1.x = mod(blueColor, 8.0) / 8.0;',

        '	vec2 texPos1;',
        '	texPos1.x = quad1.x + textureColor.r * (1.0 / 8.0 - 1.0 / 512.0) ;',
        '	texPos1.y = quad1.y + textureColor.g * (1.0 / 8.0 - 1.0 / 512.0) ;',

        '	#ifdef LUT_FLIP_Y',
        '		texPos1.y = 1.0-texPos1.y;',
        '	#endif',

        '	mediump vec4 newColor1 = texture2D(lookupTable1, texPos1);',
        '	return newColor1;',
        '}',

		'  void main() {',

		'    vec4 color;',
		'    color = texture2D(texture1, vUv); ',

		this.superSample ?
		[
		'    color += texture2D(texture1, vUv + vec2(pixelSize.x, 0.0) ); ',
		'    color += texture2D(texture1, vUv + vec2(0.0, pixelSize.y) ); ',
		'    color += texture2D(texture1, vUv + vec2(pixelSize.x, pixelSize.y) ); ',
		'    color *= 0.25; '
		].join('\n') : '',

		this.dither ?
		[
		'	float gridX = mod(gl_FragCoord.x - 0.5, 2.0); ',
		'	float gridY = mod(gl_FragCoord.y - 0.5, 2.0); ',
		'   color.rgb += vec3(abs(gridX - gridY)) * ditherStrength; ',

		].join('\n') : '',

		'    color = clamp(color, ' + (0.5/256.0) + ', ' + (255.5/256.0) + ');',

		'    gl_FragColor = lookup(color, tonemap);',

		'    if (renderOriginal != 0)',
		'    	gl_FragColor = color;',
		'  }'
		].join('\n')
	});

	var quad = new THREE.Mesh(
		new THREE.PlaneBufferGeometry( 2, 2 ),
		this.material
	);
	this.quad = quad;
	scene.add(quad);
}

PostProcessor.prototype.setTonemap = function(tonemap) {

	// if (this.material.uniforms.tonemap.value) {
	//     this.material.uniforms.tonemap.value.dispose();
	//     delete this.material.uniforms.tonemap.value;
	// }

	if (this.tonemap) {
		this.tonemap.dispose();
		delete this.tonemap;
	}

	this.material.uniforms.tonemap.value = tonemap;
	this.tonemap = tonemap;
};

PostProcessor.prototype.update = function(renderOriginal, dontIncreaseTime) {

	if (!dontIncreaseTime) {
		this.material.uniforms.time.value += 0.025;
	}
	this.material.uniforms.renderOriginal.value = renderOriginal;
	this.renderer.render(this.scene, this.camera, this.renderTarget);
};

PostProcessor.prototype.dispose = function() {

	this.renderTarget.dispose();
	delete this.renderTarget;

	this.oldRenderTarget.dispose();
	delete this.oldRenderTarget;

	if (this.tonemap) {
	    this.tonemap.dispose();
		delete this.tonemap;
	}

	if (this.material.uniforms.tonemap.value) {
	    this.material.uniforms.tonemap.value.dispose();
	    delete this.material.uniforms.tonemap.value;
	}

	if (this.material.uniforms.texture1.value) {
	    this.material.uniforms.texture1.value.dispose();
	    delete this.material.uniforms.texture1.value;
	}

	this.scene.remove(this.quad);
	this.quad.geometry.dispose();
	this.quad.material.dispose();
	delete this.quad.geometry;
	delete this.quad.material;
	delete this.quad;

	delete this.scene;
	delete this.camera;

	delete this.material;
};
module.exports = PostProcessor;
<commit_msg>extra<commit_after>function PostProcessor(renderer, oldRenderTarget, size, tonemap, opts) {

    opts = opts || {};
	this.superSample = opts.superSample;
	this.dither = opts.dither;

    this.renderer = renderer;
    this.oldRenderTarget = oldRenderTarget;

	this.size = size;

	var renderTarget = new THREE.WebGLRenderTarget(size.width, size.height);
    renderTarget.flipY = false;
    renderTarget.generateMipMaps = false;
    renderTarget.minFilter = THREE.NearestFilter;
    renderTarget.magFilter = THREE.NearestFilter;

    this.renderTarget = renderTarget;

    var scene = new THREE.Scene();
    var camera = new THREE.OrthographicCamera( -1, 1, -1, 1, -1, 1 );

    this.scene = scene;
    this.camera = camera;

    this.tonemap = tonemap;

	this.material = new THREE.ShaderMaterial({
    	side: THREE.DoubleSide,
		uniforms: {
			pixelSize: { type: 'v2', value: new THREE.Vector2(1.0 / oldRenderTarget.width, 1.0 / oldRenderTarget.height) },
			time: {type: 'f', value: 0.0},
			ditherStrength: {type: 'f', value: 0.007},
			texture1: {type: 't', value: oldRenderTarget},
			tonemap: {type: 't', value: tonemap},
			renderOriginal: {type: 'i', value: 0}
		},
		vertexShader:
		[
		'varying vec2 vUv;',
		'void main() {',
		'	vUv = uv;',
		'	gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); ',
		'}'
		].join('\n'),
		fragmentShader:
		[
		'uniform sampler2D texture1;',
		'uniform sampler2D tonemap;',
		'uniform vec2 pixelSize; ',
		'uniform float time;',
		'uniform float ditherStrength;',
		'uniform int renderOriginal;',

		'varying vec2 vUv; ',

		'#define LUT_FLIP_Y',

		'vec4 lookup(in vec4 textureColor, in sampler2D lookupTable1) {',
        '	textureColor = clamp(textureColor, 0.0, 1.0);',

        '	float blueColor = floor(textureColor.b * 64.0);',

        '	vec2 quad1;',
        '	quad1.y = floor(blueColor / 8.0) / 8.0;',
        '	quad1.x = mod(blueColor, 8.0) / 8.0;',

        '	vec2 texPos1;',
        '	texPos1.x = quad1.x + textureColor.r * (1.0 / 8.0 - 1.0 / 512.0) ;',
        '	texPos1.y = quad1.y + textureColor.g * (1.0 / 8.0 - 1.0 / 512.0) ;',

        '	#ifdef LUT_FLIP_Y',
        '		texPos1.y = 1.0-texPos1.y;',
        '	#endif',

        '	mediump vec4 newColor1 = texture2D(lookupTable1, texPos1);',
        '	return newColor1;',
        '}',

		'  void main() {',

		'    vec4 color;',
		'    color = texture2D(texture1, vUv); ',

		this.superSample ?
		[
		'    color += texture2D(texture1, vUv + vec2(pixelSize.x, 0.0) ); ',
		'    color += texture2D(texture1, vUv + vec2(0.0, pixelSize.y) ); ',
		'    color += texture2D(texture1, vUv + vec2(pixelSize.x, pixelSize.y) ); ',
		'    color *= 0.25; '
		].join('\n') : '',

		this.dither ?
		[
		'	float gridX = mod(gl_FragCoord.x - 0.5, 2.0); ',
		'	float gridY = mod(gl_FragCoord.y - 0.5, 2.0); ',
		'   color.rgb += vec3(abs(gridX - gridY)) * ditherStrength; ',

		].join('\n') : '',

		'	 if (ditherStrength > 0.0)',
		'    	color = clamp(color, ' + (0.5/256.0) + ', ' + (255.5/256.0) + ');',

		'    gl_FragColor = lookup(color, tonemap);',

		'    if (renderOriginal != 0)',
		'    	gl_FragColor = color;',
		'  }'
		].join('\n')
	});

	var quad = new THREE.Mesh(
		new THREE.PlaneBufferGeometry( 2, 2 ),
		this.material
	);
	this.quad = quad;
	scene.add(quad);
}

PostProcessor.prototype.setTonemap = function(tonemap) {

	// if (this.material.uniforms.tonemap.value) {
	//     this.material.uniforms.tonemap.value.dispose();
	//     delete this.material.uniforms.tonemap.value;
	// }

	if (this.tonemap) {
		this.tonemap.dispose();
		delete this.tonemap;
	}

	this.material.uniforms.tonemap.value = tonemap;
	this.tonemap = tonemap;
};

PostProcessor.prototype.update = function(renderOriginal, dontIncreaseTime) {

	if (!dontIncreaseTime) {
		this.material.uniforms.time.value += 0.025;
	}
	this.material.uniforms.renderOriginal.value = renderOriginal;
	this.renderer.render(this.scene, this.camera, this.renderTarget);
};

PostProcessor.prototype.dispose = function() {

	this.renderTarget.dispose();
	delete this.renderTarget;

	this.oldRenderTarget.dispose();
	delete this.oldRenderTarget;

	if (this.tonemap) {
	    this.tonemap.dispose();
		delete this.tonemap;
	}

	if (this.material.uniforms.tonemap.value) {
	    this.material.uniforms.tonemap.value.dispose();
	    delete this.material.uniforms.tonemap.value;
	}

	if (this.material.uniforms.texture1.value) {
	    this.material.uniforms.texture1.value.dispose();
	    delete this.material.uniforms.texture1.value;
	}

	this.scene.remove(this.quad);
	this.quad.geometry.dispose();
	this.quad.material.dispose();
	delete this.quad.geometry;
	delete this.quad.material;
	delete this.quad;

	delete this.scene;
	delete this.camera;

	delete this.material;
};
module.exports = PostProcessor;
<|endoftext|>