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

'use strict';

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

var utilsCore = require('./util/utilsCore');

var cacheOfPlugins = null;
var cacheOfPluginsForMode = null;

function CmdLoader(topCmd, mode) {
  this.topCmd = topCmd;
  this.cmdMode = mode;
  this.cmdMetadataFile = path.join(__dirname, 'plugins.' + this.cmdMode + '.json');
  this.cmdBasePath = __dirname;
}

_.extend(CmdLoader.prototype, {
  harvestPlugins: function (topLevelOnly) {
    var self = this;
    var plugins = this._loadCmdsFromFolder(path.join(this.cmdBasePath, 'commands'), false);
    plugins.forEach(function (plugin) { plugin.init(self.topCmd); });

    if (!topLevelOnly) {
      // Load mode specific plugins
      var modePlugins = this._loadCmdsFromFolder(path.join(this.cmdBasePath, 'commands', this.cmdMode), true);
      modePlugins.forEach(function (plugin) { plugin.init(self.topCmd); });
    }
  },

  harvestModules: function () {
    var self = this;

    var basePath = path.dirname(__filename);

    var walkPath = path.join(basePath, '../node_modules');
    var harvestPaths = [walkPath];

    while (path.basename(walkPath) === 'node_modules' && path.dirname(walkPath) !== 'npm') {
      var nextPath = path.join(walkPath, '../..');
      if (nextPath === walkPath) {
        break;
      }
      harvestPaths.push(nextPath);
      walkPath = nextPath;
    }

    var modules = [];
    harvestPaths.forEach(function (harvestPath) {
      modules = modules.concat(self._loadCmdsFromNodeModules(harvestPath));
    });

    modules.forEach(function (module) {
      module.plugin.init(self.topCmd);
    });
  },

  initFromCmdMetadata: function (AzureCli) {
    var self = this;
    var initCategory = function (category, parent) {
      function process(entity, entityParent) {
        var newEntity = new AzureCli(entity.name, entityParent);

        if (entity.description) {
          newEntity._description = entity.description;
        }

        //TODO, for some fields, we create wrapper functions here,
        //so that existing code won't break. We should get rid of them soon.
        newEntity.description = function () {
          return newEntity._description;
        };

        newEntity.fullName = function () {
          return entity.fullName;
        };

        newEntity._usage = entity.usage;
        newEntity.usage = function () {
          return newEntity._usage;
        };

        newEntity.filePath = entity.filePath ?
          path.resolve(self.cmdBasePath, entity.filePath) : entity.filePath;
        newEntity.stub = true;

        if (entity.options) {
          for (var o in entity.options) {
            newEntity.option(entity.options[o].flags, entity.options[o].description);
          }
        }

        return newEntity;
      }

      var newCategory = category;
      //can't invoke "process" for top category, which would new
      //up a top AzureCli and get us into an infinite loop.
      if (parent) {
        newCategory = process(category, parent);
      }

      for (var i = 0 ; i < category.commands.length; i++) {
        newCategory.commands[i] = (process(category.commands[i], newCategory));
      }

      if (!newCategory.categories) {
        newCategory.categories = {};
      }

      for (var j in category.categories) {
        newCategory.categories[j] = initCategory(category.categories[j], newCategory);
      }

      return newCategory;
    };
    if (!cacheOfPlugins || cacheOfPluginsForMode !== this.cmdMode) {
      var data = fs.readFileSync(this.cmdMetadataFile, {encoding: "utf8"});
      cacheOfPlugins = JSON.parse(data);
      cacheOfPluginsForMode = this.cmdMode;
    }
    var plugins = initCategory(cacheOfPlugins);

    this.topCmd.commands = plugins.commands;
    this.topCmd.categories = plugins.categories;
  },

  saveCmdMetadata: function () {
    var metadate = this._serializeCategory(this.topCmd);
    fs.writeFileSync(this.cmdMetadataFile, JSON.stringify(metadate, null, 2));
  },

  cmdMetadataExists: function () {
    return utilsCore.pathExistsSync(this.cmdMetadataFile);
  },

  _loadCmdsFromFolder: function (scanPath, recursively) {
    var results = utilsCore.getFiles(scanPath, recursively);

    results = results.filter(function (filePath) {
      var extname = path.extname(filePath);
      if (filePath.substring(0, 5) === 'tmp--') {
        return false;
      } else if (extname !== '.js' && extname !== '._js') {
        //Skip unrelated/temp files
        return false;
      }
      return true;
    });

    if (process.env.PRECOMPILE_STREAMLINE_FILES) {
      results = results.filter(function (filePath) {
        if (filePath.substring(filePath.length - 4) === '._js') {
          return false;
        }
        return true;
      });
    }

    // sort them so they load in a predictable order
    results = results.sort();

    // skip directories
    results = results.filter(function (filePath) {
      return fs.statSync(filePath).isFile();
    });

    // load modules
    results = results.map(function (filePath) {
      return require(filePath);
    });

    // look for exports.init
    results = results.filter(function (entry) {
      return entry.init !== undefined;
    });
    return results;
  },

  _loadCmdsFromNodeModules: function (scanPath) {
    var results = fs.readdirSync(scanPath);

    results = results.map(function (moduleName) {
      return {
        moduleName: moduleName,
        modulePath: path.join(scanPath, moduleName)
      };
    });

    results = results.filter(function (item) {
      try {
        item.moduleStat = fs.statSync(item.modulePath);
      } catch (error) {
        return false;
      }
      return item.moduleStat.isDirectory();
    });

    results = results.filter(function (item) {
      item.packagePath = path.join(item.modulePath, 'package.json');
      item.packageStat = utilsCore.pathExistsSync(item.packagePath) ? fs.statSync(item.packagePath) : undefined;
      return item.packageStat && item.packageStat.isFile();
    });

    results = results.filter(function (item) {
      try {
        item.packageInfo = JSON.parse(fs.readFileSync(item.packagePath));
        return item.packageInfo && item.packageInfo.plugins && item.packageInfo.plugins['azure-cli'];
      }
        catch (err) {
        return false;
      }
    });

    results = this._flatten(results.map(function (item) {
      var plugins = item.packageInfo.plugins['azure-cli'];
      if (!_.isArray(plugins)) {
        plugins = [plugins];
      }

      return plugins.map(function (relativePath) {
        return {
          context: item,
          pluginPath: path.join(item.modulePath, relativePath)
        };
      });
    }));

    results = results.filter(function (item) {
      item.plugin = require(item.pluginPath);
      return item.plugin.init;
    });

    return results;
  },

  _flatten: function (arrays) {
    var result = [];
    arrays.forEach(function (array) {
      result = result.concat(array);
    });
    return result;
  },

  _serializeIndividualEntity: function (entity) {
    //TODO: split out the concept of category or command
    var cmdOrCat = {};

    if (entity.name) {
      cmdOrCat.name = entity.name;
    }

    if (entity.description) {
      cmdOrCat.description = entity.description();
    }

    if (entity.fullName) {
      cmdOrCat.fullName = entity.fullName();
    }

    if (entity.usage) {
      cmdOrCat.usage = entity.usage();
    }

    if (entity.filePath) {
      //Normalize the file path, so that it can be used for both linux and windows.
      cmdOrCat.filePath = path.relative(this.cmdBasePath, entity.filePath).split('\\').join('/');
    }

    if (entity.options) {
      cmdOrCat.options = entity.options;
    }

    return cmdOrCat;
  },

  _serializeCategory: function (category) {
    var cat = this._serializeIndividualEntity(category);
    cat.commands = [];
    cat.categories = {};

    if (category.commands) {
      for (var i in category.commands) {
        cat.commands.push(this._serializeIndividualEntity(category.commands[i]));
      }
    }

    if (category.categories) {
      for (var j in category.categories) {
        var currentCategory = this._serializeCategory(category.categories[j]);
        cat.categories[currentCategory.name] = currentCategory;
      }
    }

    return cat;
  }

});

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

'use strict';

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

var utilsCore = require('./util/utilsCore');

var cacheOfPlugins = null;
var cacheOfPluginsForMode = null;

function CmdLoader(topCmd, mode) {
  this.topCmd = topCmd;
  this.cmdMode = mode;
  this.cmdMetadataFile = path.join(__dirname, 'plugins.' + this.cmdMode + '.json');
  this.cmdBasePath = __dirname;
}

_.extend(CmdLoader.prototype, {
  harvestPlugins: function (topLevelOnly) {
    var self = this;
    var plugins = this._loadCmdsFromFolder(path.join(this.cmdBasePath, 'commands'), false);
    plugins.forEach(function (plugin) { plugin.init(self.topCmd); });

    if (!topLevelOnly) {
      // Load mode specific plugins
      var modePlugins = this._loadCmdsFromFolder(path.join(this.cmdBasePath, 'commands', this.cmdMode), true);
      modePlugins.forEach(function (plugin) { plugin.init(self.topCmd); });
    }
  },

  harvestModules: function () {
    var self = this;

    var basePath = path.dirname(__filename);

    var walkPath = path.join(basePath, '../node_modules');
    var harvestPaths = [walkPath];

    while (path.basename(walkPath) === 'node_modules' && path.dirname(walkPath) !== 'npm') {
      var nextPath = path.join(walkPath, '../..');
      if (nextPath === walkPath) {
        break;
      }
      harvestPaths.push(nextPath);
      walkPath = nextPath;
    }

    var modules = [];
    harvestPaths.forEach(function (harvestPath) {
      modules = modules.concat(self._loadCmdsFromNodeModules(harvestPath));
    });

    modules.forEach(function (module) {
      module.plugin.init(self.topCmd);
    });
  },

  initFromCmdMetadata: function (AzureCli) {
    var self = this;
    var initCategory = function (category, parent) {
      function process(entity, entityParent) {
        var newEntity = new AzureCli(entity.name, entityParent);

        if (entity.description) {
          newEntity._description = entity.description;
        }

        //TODO, for some fields, we create wrapper functions here,
        //so that existing code won't break. We should get rid of them soon.
        newEntity.description = function () {
          return newEntity._description;
        };

        newEntity.fullName = function () {
          return entity.fullName;
        };

        newEntity._usage = entity.usage;
        newEntity.usage = function () {
          return newEntity._usage;
        };

        newEntity.filePath = entity.filePath ?
          path.resolve(self.cmdBasePath, entity.filePath) : entity.filePath;
        newEntity.stub = true;

        if (entity.options) {
          for (var o in entity.options) {
            newEntity.option(entity.options[o].flags, entity.options[o].description);
          }
        }

        return newEntity;
      }

      var newCategory = category;
      //can't invoke "process" for top category, which would new
      //up a top AzureCli and get us into an infinite loop.
      if (parent) {
        newCategory = process(category, parent);
      }

      for (var i = 0 ; i < category.commands.length; i++) {
        newCategory.commands[i] = (process(category.commands[i], newCategory));
      }

      if (!newCategory.categories) {
        newCategory.categories = {};
      }

      for (var j in category.categories) {
        newCategory.categories[j] = initCategory(category.categories[j], newCategory);
      }

      return newCategory;
    };
    if (!cacheOfPlugins || cacheOfPluginsForMode !== this.cmdMode) {
      var data = fs.readFileSync(this.cmdMetadataFile, {encoding: 'utf8'});
      cacheOfPlugins = JSON.parse(data);
      cacheOfPluginsForMode = this.cmdMode;
    }
    var plugins = initCategory(cacheOfPlugins);

    this.topCmd.commands = plugins.commands;
    this.topCmd.categories = plugins.categories;
  },

  saveCmdMetadata: function () {
    var metadate = this._serializeCategory(this.topCmd);
    fs.writeFileSync(this.cmdMetadataFile, JSON.stringify(metadate, null, 2));
  },

  cmdMetadataExists: function () {
    return utilsCore.pathExistsSync(this.cmdMetadataFile);
  },

  _loadCmdsFromFolder: function (scanPath, recursively) {
    var results = utilsCore.getFiles(scanPath, recursively);

    results = results.filter(function (filePath) {
      var extname = path.extname(filePath);
      if (filePath.substring(0, 5) === 'tmp--') {
        return false;
      } else if (extname !== '.js' && extname !== '._js') {
        //Skip unrelated/temp files
        return false;
      }
      return true;
    });

    if (process.env.PRECOMPILE_STREAMLINE_FILES) {
      results = results.filter(function (filePath) {
        if (filePath.substring(filePath.length - 4) === '._js') {
          return false;
        }
        return true;
      });
    }

    // sort them so they load in a predictable order
    results = results.sort();

    // skip directories
    results = results.filter(function (filePath) {
      return fs.statSync(filePath).isFile();
    });

    // load modules
    results = results.map(function (filePath) {
      return require(filePath);
    });

    // look for exports.init
    results = results.filter(function (entry) {
      return entry.init !== undefined;
    });
    return results;
  },

  _loadCmdsFromNodeModules: function (scanPath) {
    var results = fs.readdirSync(scanPath);

    results = results.map(function (moduleName) {
      return {
        moduleName: moduleName,
        modulePath: path.join(scanPath, moduleName)
      };
    });

    results = results.filter(function (item) {
      try {
        item.moduleStat = fs.statSync(item.modulePath);
      } catch (error) {
        return false;
      }
      return item.moduleStat.isDirectory();
    });

    results = results.filter(function (item) {
      item.packagePath = path.join(item.modulePath, 'package.json');
      item.packageStat = utilsCore.pathExistsSync(item.packagePath) ? fs.statSync(item.packagePath) : undefined;
      return item.packageStat && item.packageStat.isFile();
    });

    results = results.filter(function (item) {
      try {
        item.packageInfo = JSON.parse(fs.readFileSync(item.packagePath));
        return item.packageInfo && item.packageInfo.plugins && item.packageInfo.plugins['azure-cli'];
      }
        catch (err) {
        return false;
      }
    });

    results = this._flatten(results.map(function (item) {
      var plugins = item.packageInfo.plugins['azure-cli'];
      if (!_.isArray(plugins)) {
        plugins = [plugins];
      }

      return plugins.map(function (relativePath) {
        return {
          context: item,
          pluginPath: path.join(item.modulePath, relativePath)
        };
      });
    }));

    results = results.filter(function (item) {
      item.plugin = require(item.pluginPath);
      return item.plugin.init;
    });

    return results;
  },

  _flatten: function (arrays) {
    var result = [];
    arrays.forEach(function (array) {
      result = result.concat(array);
    });
    return result;
  },

  _serializeIndividualEntity: function (entity) {
    //TODO: split out the concept of category or command
    var cmdOrCat = {};

    if (entity.name) {
      cmdOrCat.name = entity.name;
    }

    if (entity.description) {
      cmdOrCat.description = entity.description();
    }

    if (entity.fullName) {
      cmdOrCat.fullName = entity.fullName();
    }

    if (entity.usage) {
      cmdOrCat.usage = entity.usage();
    }

    if (entity.filePath) {
      //Normalize the file path, so that it can be used for both linux and windows.
      cmdOrCat.filePath = path.relative(this.cmdBasePath, entity.filePath).split('\\').join('/');
    }

    if (entity.options) {
      cmdOrCat.options = entity.options;
    }

    return cmdOrCat;
  },

  _serializeCategory: function (category) {
    var cat = this._serializeIndividualEntity(category);
    cat.commands = [];
    cat.categories = {};

    if (category.commands) {
      for (var i in category.commands) {
        cat.commands.push(this._serializeIndividualEntity(category.commands[i]));
      }
    }

    if (category.categories) {
      for (var j in category.categories) {
        var currentCategory = this._serializeCategory(category.categories[j]);
        cat.categories[currentCategory.name] = currentCategory;
      }
    }

    return cat;
  }

});

module.exports = CmdLoader;<|endoftext|>


<commit_before>const bs58check = require('bs58check')
const _ = require('lodash/fp')

module.exports = {depositUrl, parseUrl, formatAddress}

function parseUrl (network, url) {
  const res = /^([bB]itcoin:\/{0,2})?(\w+)/.exec(url)
  const address = res && res[2]

  console.log('DEBUG16: [%s] *%s*', network, address)

  if (!validate(network, address)) return null

  return address
}

function depositUrl (address, amount) {
  const parts = _.split(':', address)

  const isLightning = _.size(parts) === 2

  if (isLightning) {
    const paymentRequest = _.nth(1, parts)
    return paymentRequest
  }

  return `bitcoin:${address}?amount=${amount}`
}

function formatAddress (address) {
  const parts = _.split(':', address)
  const isLightning = _.size(parts) === 2

  if (isLightning) return 'Lightning Network'
  return address
}

function validate (network, address) {
  try {
    if (!network) throw new Error('No network supplied.')
    if (!address) throw new Error('No address supplied.')

    const buf = bs58check.decode(address)
    const addressType = buf[0]

    if (buf.length !== 21) throw new Error(`Invalid length: ${buf.length}`)

    if (network === 'main' && _.includes(addressType, [0x00, 0x05])) return true
    if (network === 'test' && _.includes(addressType, [0x6f, 0xc4])) return true

    throw new Error('General error')
  } catch (err) {
    console.log(err)
    console.log('Invalid bitcoin address: [%s] %s', network, address)
    return false
  }
}
<commit_msg>support Strike payments<commit_after>const bs58check = require('bs58check')
const _ = require('lodash/fp')

module.exports = {depositUrl, parseUrl, formatAddress}

function parseUrl (network, url) {
  const res = /^([bB]itcoin:\/{0,2})?(\w+)/.exec(url)
  const address = res && res[2]

  console.log('DEBUG16: [%s] *%s*', network, address)

  if (!validate(network, address)) return null

  return address
}

function depositUrl (address, amount) {
  const parts = _.split(':', address)

  // Strike LN payment
  if (parts[0] === 'strike') return _.nth(3, parts)

  // Regular LN payment
  if (_.size(parts) === 2) return _.nth(1, parts)

  return `bitcoin:${address}?amount=${amount}`
}

function formatAddress (address) {
  const parts = _.split(':', address)
  const isLightning = _.size(parts) >= 2

  if (isLightning) return 'Lightning Network'
  return address
}

function validate (network, address) {
  try {
    if (!network) throw new Error('No network supplied.')
    if (!address) throw new Error('No address supplied.')

    const buf = bs58check.decode(address)
    const addressType = buf[0]

    if (buf.length !== 21) throw new Error(`Invalid length: ${buf.length}`)

    if (network === 'main' && _.includes(addressType, [0x00, 0x05])) return true
    if (network === 'test' && _.includes(addressType, [0x6f, 0xc4])) return true

    throw new Error('General error')
  } catch (err) {
    console.log(err)
    console.log('Invalid bitcoin address: [%s] %s', network, address)
    return false
  }
}
<|endoftext|>


<commit_before>const ss = require("simple-storage");
const tabs = require("tabs");
const data = require("self").data;
var reportTab = null;

if (!ss.storage.requests) {
 ss.storage.requests = [];
 ss.storage.data = {};
}

function collectRequest(requestData){
  ss.storage.requests.push(requestData);
}

function reportToConsole(){
  for (var r in ss.storage.requests) {
    console.log(JSON.stringify(ss.storage.requests[r]));
  }
}

function reportToHTML(){
  var found = false;
  for each (var tab in tabs){
    if (tab.title == 'Zogger Report') {
      found = true;
      tab.activate();
    }
  }
  if (!found) {
    tabs.open(data.url("ui/report.html"));
  }
}

tabs.on('ready', function(tab) {
  worker = tab.attach({contentScriptFile: [data.url("ui/jquery.min.js"), data.url("submits-handler.js")]});
  worker.port.on("collectRequest", function(requestData){
    collectRequest(requestData);
  });
});

exports.collectRequest = collectRequest;
exports.reportToConsole = reportToConsole;
exports.reportToHTML = reportToHTML;
<commit_msg>Added timestamp to all collected data<commit_after>const ss = require("simple-storage");
const tabs = require("tabs");
const data = require("self").data;
var reportTab = null;

if (!ss.storage.requests) {
 ss.storage.requests = [];
 ss.storage.data = {};
}

function collectRequest(requestData){
  requestData.timestamp = new Date().getTime();
  ss.storage.requests.push(requestData);
}

function reportToConsole(){
  for (var r in ss.storage.requests) {
    console.log(JSON.stringify(ss.storage.requests[r]));
  }
}

function reportToHTML(){
  var found = false;
  for each (var tab in tabs){
    if (tab.title == 'Zogger Report') {
      found = true;
      tab.activate();
    }
  }
  if (!found) {
    tabs.open(data.url("ui/report.html"));
  }
}

tabs.on('ready', function(tab) {
  worker = tab.attach({contentScriptFile: [data.url("ui/jquery.min.js"), data.url("submits-handler.js")]});
  worker.port.on("collectRequest", function(requestData){
    collectRequest(requestData);
  });
});

exports.collectRequest = collectRequest;
exports.reportToConsole = reportToConsole;
exports.reportToHTML = reportToHTML;
<|endoftext|>


<commit_before>(function() {
    'use strict';

    /*
        '# commander.js'                                    + '\n'  +
        '# -----------'                                     + '\n'  +
        '# Module is part of Cloud Commander,'              + '\n'  +
        '# used for getting dir content.'                   + '\n'  +
        '# and forming html content'                        + '\n'  +
        '# http://cloudcmd.io'                              + '\n');
    */

    var fs                  = require('fs'),

        DIR                 = '../',
        DIR_SERVER          = DIR + 'lib/',

        Util                = require('util-io'),
        format              = require('format-io'),
        users               = require(DIR_SERVER    + 'users'),

        WIN32               = process.platform === 'win32';

    exports.getDirContent = function(path, callback) {
        Util.checkArgs(arguments, ['path', 'callback'])
            .checkType('path', path, 'string')
            .checkType('callback', callback, 'function');

        fs.readdir(path, function(error, names) {
            if (error)
                callback(error);
            else
                getAllStats(path, names, callback);
        });
    };

    /**
     * @param path
     * @param names
     */
    function getAllStats(path, names, callback) {
        var length  = names.length,
            funcs   = {},
            dir     = format.addSlashToEnd(path);

        if (!length)
            funcs.exec = Util.exec.ret;
        else
            names.forEach(function(name) {
                var path    = dir + name;

                funcs[name] = Util.exec.with(getStat, name, path);
            });

        Util.exec.parallel(funcs, function(error, files) {
            fillJSON(dir, files || {}, callback);
        });
    }

    function getStat(name, path, callback) {
        fs.lstat(path, function(error, data) {
            callback(null, data || {
                'mode'          : 0,
                'size'          : 0,
                'isDirectory'   : Util.retFalse
            });
        });
    }

    function parseStats(stats) {
        var files;

        Util.checkArgs(arguments, ['stats']);

        files = Object.keys(stats).map(function(name) {
            var file, isDir, size, mode, modeStr,
                stat    = stats[name],
                owner   = stat.uid;

            if (stat) {
                /* Переводим права доступа в 8-ричную систему */
                modeStr = Number(stat.mode).toString(8);
                mode    = Number(modeStr);
                isDir   = stat.isDirectory();
                size    = isDir ? 'dir' : stat.size;
            }

            file = {
                'name'  : name,
                'size'  : format.size(size),
                'owner' : owner,
                'mode'  : format.permissions.symbolic(mode)
            };

            return file;
        });

        return files;
    }

    /**
     * Function fill JSON by file stats
     *
     * @param params - { files, stats, path }
     */
    function fillJSON(path, stats, callback) {
        var files,

            json    = {
                path    : '',
                files   : []
            };

        Util.checkArgs(arguments, ['params']);

        files       = parseStats(stats);
        json.files  = changeOrder(files);
        json.path   = format.addSlashToEnd(path);

        changeUIDToName(json, function(error) {
            callback(error, json);
        });
    }

    function changeUIDToName(json, callback) {
        if (WIN32)
            callback();
        else
            users.getNames(function(error, names) {
                var files = json.files;

                if (error)
                    callback(error);
                else
                    files.forEach(function(file) {
                        var owner   = file.owner;
                            owner   = names[owner];

                        if (owner)
                            file.owner   = owner;
                    });

                callback();
            });
    }

    function changeOrder(json) {
        var files   = [],
            dirs    = [],
            sorted  = [];

        json.forEach(function(current) {
            if (current.size === 'dir')
                dirs.push(current);
            else
                files.push(current);
        });

        sorted = dirs.concat(files);

        return sorted;
    }

})();
<commit_msg>fix(commander) getAllStats: empty directory<commit_after>(function() {
    'use strict';

    /*
        '# commander.js'                                    + '\n'  +
        '# -----------'                                     + '\n'  +
        '# Module is part of Cloud Commander,'              + '\n'  +
        '# used for getting dir content.'                   + '\n'  +
        '# and forming html content'                        + '\n'  +
        '# http://cloudcmd.io'                              + '\n');
    */

    var fs                  = require('fs'),

        DIR                 = '../',
        DIR_SERVER          = DIR + 'lib/',

        Util                = require('util-io'),
        format              = require('format-io'),
        users               = require(DIR_SERVER    + 'users'),

        WIN32               = process.platform === 'win32';

    exports.getDirContent = function(path, callback) {
        Util.checkArgs(arguments, ['path', 'callback'])
            .checkType('path', path, 'string')
            .checkType('callback', callback, 'function');

        fs.readdir(path, function(error, names) {
            if (error)
                callback(error);
            else
                getAllStats(path, names, callback);
        });
    };

    /**
     * @param path
     * @param names
     */
    function getAllStats(path, names, callback) {
        var length  = names.length,
            funcs   = names.length ? {} : [],
            dir     = format.addSlashToEnd(path);

        if (!length)
            funcs.push(Util.exec);
        else
            names.forEach(function(name) {
                var path    = dir + name;

                funcs[name] = Util.exec.with(getStat, name, path);
            });

        Util.exec.parallel(funcs, function(error, files) {
            fillJSON(dir, files || {}, callback);
        });
    }

    function getStat(name, path, callback) {
        fs.lstat(path, function(error, data) {
            callback(null, data || {
                'mode'          : 0,
                'size'          : 0,
                'isDirectory'   : Util.retFalse
            });
        });
    }

    function parseStats(stats) {
        var files;

        Util.checkArgs(arguments, ['stats']);

        files = Object.keys(stats).map(function(name) {
            var file, isDir, size, mode, modeStr,
                stat    = stats[name],
                owner   = stat.uid;

            if (stat) {
                /* Переводим права доступа в 8-ричную систему */
                modeStr = Number(stat.mode).toString(8);
                mode    = Number(modeStr);
                isDir   = stat.isDirectory();
                size    = isDir ? 'dir' : stat.size;
            }

            file = {
                'name'  : name,
                'size'  : format.size(size),
                'owner' : owner,
                'mode'  : format.permissions.symbolic(mode)
            };

            return file;
        });

        return files;
    }

    /**
     * Function fill JSON by file stats
     *
     * @param params - { files, stats, path }
     */
    function fillJSON(path, stats, callback) {
        var files,

            json    = {
                path    : '',
                files   : []
            };

        Util.checkArgs(arguments, ['params']);

        files       = parseStats(stats);
        json.files  = changeOrder(files);
        json.path   = format.addSlashToEnd(path);

        changeUIDToName(json, function(error) {
            callback(error, json);
        });
    }

    function changeUIDToName(json, callback) {
        if (WIN32)
            callback();
        else
            users.getNames(function(error, names) {
                var files = json.files;

                if (error)
                    callback(error);
                else
                    files.forEach(function(file) {
                        var owner   = file.owner;
                            owner   = names[owner];

                        if (owner)
                            file.owner   = owner;
                    });

                callback();
            });
    }

    function changeOrder(json) {
        var files   = [],
            dirs    = [],
            sorted  = [];

        json.forEach(function(current) {
            if (current.size === 'dir')
                dirs.push(current);
            else
                files.push(current);
        });

        sorted = dirs.concat(files);

        return sorted;
    }

})();
<|endoftext|>


<commit_before>/**
 * Movim Javascript Template functions

 * Look at the comments for help.
 */

var MovimTpl = {
    dragged : false,
    moving : false,
    percent : false,
    init : function() {
        if(document.getElementById('back') != null)
            MovimUtils.hideElement(document.getElementById('back'));
    },
    append : function(selector, html) {
        target = document.querySelector(selector);
        if(target) {
            target.insertAdjacentHTML('beforeend', html);
        }
    },
    back : function() {
        // If the context menu is shown
        var cm = document.querySelector('ul.context_menu');
        if(cm != null && cm.className.includes('shown')) {
            MovimTpl.toggleContextMenu(document);
            // If a drawer is shown
        } else if(Drawer.filled()) {
            Drawer.clear();
            // If a dialog box is shown
        } else if(Dialog.filled()) {
            Dialog.clear();
            // If the menu is shown
        } else if(MovimUtils.hasClass('body > nav', 'active')) {
            MovimUtils.removeClass('body > nav', 'active');
            // If the panel is shown
        } else if(MovimTpl.isPanel()) {
            MovimTpl.hidePanel();
            window.history.back();
        } else {
            history.back();
        }
    },
    fill : function(selector, html) {
        target = document.querySelector(selector);
        if(target) {
            target.innerHTML = html;
        }
    },
    hideContextMenu : function() {
        MovimUtils.removeClass('ul.context_menu', 'shown');
    },
    hideMenu: function() {
        MovimUtils.removeClass('body > nav', 'active');
    },
    showPanel: function() {
        MovimUtils.addClass('main section', 'enabled');
        MovimTpl.scrollPanelTop();
    },
    hidePanel: function() {
        MovimUtils.removeClass('main section', 'enabled');
    },
    isPanel: function() {
        return MovimUtils.hasClass('main section', 'enabled');
    },
    isPanelScrolled: function() {
        var selector = document.querySelector('main section > div:first-child:nth-last-child(2) ~ div div');

        if(selector != null) {
            return (selector.scrollHeight - Math.floor(selector.scrollTop) <= selector.clientHeight + 3);
        }
    },
    prepend: function(selector, html) {
        target = document.querySelector(selector);
        if(target) {
            target.insertAdjacentHTML('afterbegin', html);
        }
    },
    remove: function(selector) {
        target = document.querySelector(selector);
        if(target)
            target.parentNode.removeChild(target);
    },
    replace: function (selector, html) {
        target = document.querySelector(selector);
        if(target) {
            var div = document.createElement('div');
            div.innerHTML = html;
            var element = div.firstChild;
            replacedNode = target.parentNode.replaceChild(element, target);
        }
    },
    scrollPanel : function() {
        var selector = document.querySelector('main section > div:first-child:nth-last-child(2) ~ div div');

        if(selector != null) {
            selector.scrollTop = selector.scrollHeight;
        }
    },
    scrollPanelTop : function() {
        var selector = document.querySelector('main section > div:first-child:nth-last-child(2) ~ div');

        if(selector != null) {
            selector.scrollTop = 0;
        }
    },
    toggleActionButton : function() {
        MovimUtils.toggleClass('.button.action', 'active');
    },
    toggleContextMenu : function(e) {
        var element = 'ul.context_menu';
        var classname = 'shown';

        if(document.querySelector(element) == null) {
            return;
        }

        if(document.querySelector('.show_context_menu').contains(e.target)) {
            MovimUtils.addClass(element, classname);
            return;
        }

        //if(!document.querySelector(element).contains(e.target))
        MovimUtils.removeClass(element, classname);
    },
    toggleMenu : function() {
        MovimUtils.toggleClass('body > nav', 'active');
    },
    touchEvents: function() {
        nav = document.querySelector('body > nav');

        document.body.addEventListener('touchstart', function(event) {
            startX = event.targetTouches[0].pageX;

            if(
            (
                startX < 10 ||
                (nav.classList.contains('active') && startX > document.body.clientWidth - 25)
            )
            && MovimTpl.dragged == false) {
                nav.classList.add('moving');
                MovimTpl.dragged = true;
            }
        }, true);

        document.body.addEventListener('touchmove', function(event) {
            moveX = event.targetTouches[0].pageX;

            if(MovimTpl.dragged) {
                event.preventDefault();
                event.stopPropagation();

                position = moveX - document.body.clientWidth;

                MovimTpl.percent = 1 - Math.abs(moveX) / Math.abs(document.body.clientWidth);
                nav.style.transform = 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+position+', 0, 0, 1)';
            }
        }, true);

        document.body.addEventListener('touchend', function(event) {
            nav.style.transform = '';

            if(MovimTpl.dragged) {
                nav.classList.remove('moving');

                if(!nav.classList.contains('active')
                && MovimTpl.percent < 0.80) {
                    nav.classList.add('active');
                } else if(MovimTpl.percent > 0.20) {
                    nav.classList.remove('active');
                }
            }

            MovimTpl.dragged = false;
        }, true);
    }
};

movim_add_onload(function() {
    MovimTpl.init();
    MovimTpl.touchEvents();
    document.body.addEventListener('click', MovimTpl.toggleContextMenu, false);
});
<commit_msg>Small fix for the menu on mobile<commit_after>/**
 * Movim Javascript Template functions

 * Look at the comments for help.
 */

var MovimTpl = {
    dragged : false,
    moving : false,
    percent : false,
    init : function() {
        if(document.getElementById('back') != null)
            MovimUtils.hideElement(document.getElementById('back'));
    },
    append : function(selector, html) {
        target = document.querySelector(selector);
        if(target) {
            target.insertAdjacentHTML('beforeend', html);
        }
    },
    back : function() {
        // If the context menu is shown
        var cm = document.querySelector('ul.context_menu');
        if(cm != null && cm.className.includes('shown')) {
            MovimTpl.toggleContextMenu(document);
            // If a drawer is shown
        } else if(Drawer.filled()) {
            Drawer.clear();
            // If a dialog box is shown
        } else if(Dialog.filled()) {
            Dialog.clear();
            // If the menu is shown
        } else if(MovimUtils.hasClass('body > nav', 'active')) {
            MovimUtils.removeClass('body > nav', 'active');
            // If the panel is shown
        } else if(MovimTpl.isPanel()) {
            MovimTpl.hidePanel();
            window.history.back();
        } else {
            history.back();
        }
    },
    fill : function(selector, html) {
        target = document.querySelector(selector);
        if(target) {
            target.innerHTML = html;
        }
    },
    hideContextMenu : function() {
        MovimUtils.removeClass('ul.context_menu', 'shown');
    },
    hideMenu: function() {
        MovimUtils.removeClass('body > nav', 'active');
    },
    showPanel: function() {
        MovimUtils.addClass('main section', 'enabled');
        MovimTpl.scrollPanelTop();
    },
    hidePanel: function() {
        MovimUtils.removeClass('main section', 'enabled');
    },
    isPanel: function() {
        return MovimUtils.hasClass('main section', 'enabled');
    },
    isPanelScrolled: function() {
        var selector = document.querySelector('main section > div:first-child:nth-last-child(2) ~ div div');

        if(selector != null) {
            return (selector.scrollHeight - Math.floor(selector.scrollTop) <= selector.clientHeight + 3);
        }
    },
    prepend: function(selector, html) {
        target = document.querySelector(selector);
        if(target) {
            target.insertAdjacentHTML('afterbegin', html);
        }
    },
    remove: function(selector) {
        target = document.querySelector(selector);
        if(target)
            target.parentNode.removeChild(target);
    },
    replace: function (selector, html) {
        target = document.querySelector(selector);
        if(target) {
            var div = document.createElement('div');
            div.innerHTML = html;
            var element = div.firstChild;
            replacedNode = target.parentNode.replaceChild(element, target);
        }
    },
    scrollPanel : function() {
        var selector = document.querySelector('main section > div:first-child:nth-last-child(2) ~ div div');

        if(selector != null) {
            selector.scrollTop = selector.scrollHeight;
        }
    },
    scrollPanelTop : function() {
        var selector = document.querySelector('main section > div:first-child:nth-last-child(2) ~ div');

        if(selector != null) {
            selector.scrollTop = 0;
        }
    },
    toggleActionButton : function() {
        MovimUtils.toggleClass('.button.action', 'active');
    },
    toggleContextMenu : function(e) {
        var element = 'ul.context_menu';
        var classname = 'shown';

        if(document.querySelector(element) == null) {
            return;
        }

        if(document.querySelector('.show_context_menu').contains(e.target)) {
            MovimUtils.addClass(element, classname);
            return;
        }

        //if(!document.querySelector(element).contains(e.target))
        MovimUtils.removeClass(element, classname);
    },
    toggleMenu : function() {
        MovimUtils.toggleClass('body > nav', 'active');
    },
    touchEvents: function() {
        nav = document.querySelector('body > nav');

        document.body.addEventListener('touchstart', function(event) {
            startX = event.targetTouches[0].pageX;

            if(
            (
                startX < 5 ||
                (nav.classList.contains('active') && startX > document.body.clientWidth - 25)
            )
            && MovimTpl.dragged == false) {
                nav.classList.add('moving');
                MovimTpl.dragged = true;
            }
        }, true);

        document.body.addEventListener('touchmove', function(event) {
            moveX = event.targetTouches[0].pageX;

            if(MovimTpl.dragged) {
                event.preventDefault();
                event.stopPropagation();

                position = moveX - document.body.clientWidth;

                MovimTpl.percent = 1 - Math.abs(moveX) / Math.abs(document.body.clientWidth);
                nav.style.transform = 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+position+', 0, 0, 1)';
            }
        }, true);

        document.body.addEventListener('touchend', function(event) {
            nav.style.transform = '';

            if(MovimTpl.dragged) {
                nav.classList.remove('moving');

                if(!nav.classList.contains('active')
                && MovimTpl.percent < 0.80) {
                    nav.classList.add('active');
                } else if(MovimTpl.percent > 0.20) {
                    nav.classList.remove('active');
                }
            }

            MovimTpl.dragged = false;
        }, true);
    }
};

movim_add_onload(function() {
    MovimTpl.init();
    MovimTpl.touchEvents();
    document.body.addEventListener('click', MovimTpl.toggleContextMenu, false);
});
<|endoftext|>


<commit_before>describe("build", function () {
  var build = require("../index");
  var fs = require("fs-extra");

  global.test.blog();

  beforeEach(function () {
    this.buildAndCheck = ({ path, contents }, expectedEntry, cb) => {
      fs.outputFileSync(this.blogDirectory + path, contents);
      build(this.blog, path, {}, function (err, entry) {
        for (let key in expectedEntry)
          expect(expectedEntry[key]).toEqual(entry[key]);
        cb();
      });
    };
  });

  it("will convert wikilinks if plugin is enabled", function (done) {
    const contents = "A [[wikilink]]";
    const path = "/hello.txt";
    const html = '
A wikilink
';

    this.blog.plugins.wikilinks = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });

  it("will convert multiple wikilinks on one line", function (done) {
    const contents = "A [[wikilink]] and [[another|one]]";
    const path = "/hello.txt";
    const html =
      '
A wikilink and one
';

    this.blog.plugins.wikilinks = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });

  it("will ignore wikilinks spanning multiple lines", function (done) {
    const contents = "[[wiki\n\nhey]]";
    const path = "/hello.txt";
    const html =
      '
[[wiki
\n
hey]]
';

    this.blog.plugins.wikilinks = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });

  it("will convert wikilinks inside other nodes", function (done) {
    const contents = "- A **[[wikilink]]** in a list";
    const path = "/hello.txt";
    const html =
      '
\n
A wikilink in a list
\n
';

    this.blog.plugins.wikilinks = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });

  it("will convert wikilinks whose path contains square brackets", function (done) {
    const contents = "[[../[snips]/wikilink]]";
    const path = "/hello.txt";
    const html =
      '
../[snips]/wikilink
';

    this.blog.plugins.wikilinks = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });

  it("will turn titles into title case if plugin is enabled", function (done) {
    const contents = "# Title goes here";
    const path = "/hello.txt";
    const html = '
Title Goes Here
';

    this.blog.plugins.titlecase = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });
});
<commit_msg>Adds test case for new titlecase behaviour<commit_after>describe("build", function () {
  var build = require("../index");
  var fs = require("fs-extra");

  global.test.blog();

  beforeEach(function () {
    this.buildAndCheck = ({ path, contents }, expectedEntry, cb) => {
      fs.outputFileSync(this.blogDirectory + path, contents);
      build(this.blog, path, {}, function (err, entry) {
        for (let key in expectedEntry)
          expect(expectedEntry[key]).toEqual(entry[key]);
        cb();
      });
    };
  });

  it("will convert wikilinks if plugin is enabled", function (done) {
    const contents = "A [[wikilink]]";
    const path = "/hello.txt";
    const html = '
A wikilink
';

    this.blog.plugins.wikilinks = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });

  it("will convert multiple wikilinks on one line", function (done) {
    const contents = "A [[wikilink]] and [[another|one]]";
    const path = "/hello.txt";
    const html =
      '
A wikilink and one
';

    this.blog.plugins.wikilinks = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });

  it("will ignore wikilinks spanning multiple lines", function (done) {
    const contents = "[[wiki\n\nhey]]";
    const path = "/hello.txt";
    const html =
      '
[[wiki
\n
hey]]
';

    this.blog.plugins.wikilinks = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });

  it("will convert wikilinks inside other nodes", function (done) {
    const contents = "- A **[[wikilink]]** in a list";
    const path = "/hello.txt";
    const html =
      '
\n
A wikilink in a list
\n
';

    this.blog.plugins.wikilinks = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });

  it("will convert wikilinks whose path contains square brackets", function (done) {
    const contents = "[[../[snips]/wikilink]]";
    const path = "/hello.txt";
    const html =
      '
../[snips]/wikilink
';

    this.blog.plugins.wikilinks = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });

  it("will turn titles into title case if plugin is enabled", function (done) {
    const contents = "# Title goes here";
    const path = "/hello.txt";
    const html = '
Title Goes Here
';

    this.blog.plugins.titlecase = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });

  it("will turn titles with nested children into title case if plugin is enabled", function (done) {
    const contents = "# Title *goes [with](/here)* children";
    const path = "/hello.txt";
    const html = '
Title Goes With Children
';

    this.blog.plugins.titlecase = { enabled: true, options: {} };
    this.buildAndCheck({ path, contents }, { html }, done);
  });
});
<|endoftext|>


<commit_before>"use strict";

module.exports = exports = configure;

exports.usage = 'Attempts to configure node-gyp or nw-gyp build';

var compile = require('./util/compile.js');
var handle_gyp_opts = require('./util/handle_gyp_opts.js');

function configure(gyp, argv, callback) {
    handle_gyp_opts(gyp,argv,function(err,result) {
        var final_args = result.gyp.concat(result.pre);
        // pull select node-gyp configure options out of the npm environ
        var known_gyp_args = ['dist-url','python','nodedir','msvs_version'];
        known_gyp_args.forEach(function(key) {
            var val = gyp.opts[key] || gyp.opts[key.replace('-','_')];
            if (val) {
               final_args.push('--'+key+'='+val);
            }
        });
        // --ensure=false tell node-gyp to re-install node development headers
        // but it is only respected by node-gyp install, so we have to call install
        // as a separate step if the user passes it
        if (gyp.opts.ensure === false) {
            var install_args = final_args.concat(['install','--ensure=false'])
            compile.run_gyp(install_args,result.opts,function(err) {
                if (err) return callback(err);
                if (result.unparsed.length > 0) {
                    final_args = final_args.
                                  concat(['--']).
                                  concat(result.unparsed);
                }
                compile.run_gyp(['configure'].concat(final_args),result.opts,function(err) {
                    return callback(err);
                });
            });
        } else {
            if (result.unparsed.length > 0) {
                final_args = final_args.
                              concat(['--']).
                              concat(result.unparsed);
            }
            compile.run_gyp(['configure'].concat(final_args),result.opts,function(err) {
                return callback(err);
            });
        }
    });
}
<commit_msg>fix jshint errors<commit_after>"use strict";

module.exports = exports = configure;

exports.usage = 'Attempts to configure node-gyp or nw-gyp build';

var compile = require('./util/compile.js');
var handle_gyp_opts = require('./util/handle_gyp_opts.js');

function configure(gyp, argv, callback) {
    handle_gyp_opts(gyp,argv,function(err,result) {
        var final_args = result.gyp.concat(result.pre);
        // pull select node-gyp configure options out of the npm environ
        var known_gyp_args = ['dist-url','python','nodedir','msvs_version'];
        known_gyp_args.forEach(function(key) {
            var val = gyp.opts[key] || gyp.opts[key.replace('-','_')];
            if (val) {
               final_args.push('--'+key+'='+val);
            }
        });
        // --ensure=false tell node-gyp to re-install node development headers
        // but it is only respected by node-gyp install, so we have to call install
        // as a separate step if the user passes it
        if (gyp.opts.ensure === false) {
            var install_args = final_args.concat(['install','--ensure=false']);
            compile.run_gyp(install_args,result.opts,function(err) {
                if (err) return callback(err);
                if (result.unparsed.length > 0) {
                    final_args = final_args.
                                  concat(['--']).
                                  concat(result.unparsed);
                }
                compile.run_gyp(['configure'].concat(final_args),result.opts,function(err) {
                    return callback(err);
                });
            });
        } else {
            if (result.unparsed.length > 0) {
                final_args = final_args.
                              concat(['--']).
                              concat(result.unparsed);
            }
            compile.run_gyp(['configure'].concat(final_args),result.opts,function(err) {
                return callback(err);
            });
        }
    });
}
<|endoftext|>


<commit_before>var pathname = window.location.pathname;
var chatChannels = "#"+pathname.split('/')[3];
//var chatChannels = $("#chatframe").attr('chatroom');//"#cs1691x";
var urlPrefix = 'https://cs1692x.moocforums.org/chatlog/edxframe/CS169.1x/3T2013/';

var onChatTab = false;
if (document.title.indexOf("Chat") != -1) {
  onChatTab = true;
}

chatframeContent =
['Open Chat',
 '',
 '<link rel="stylesheet" href="https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />',
 ''
].join('\n');

$("#chatframe").hide();
$("#chatframe").html(chatframeContent);
$("#chatiframe").on('load', function() {
	showDelayed(5, this, 'loadingchat');
});

function getContentInContainer(matchClass) {
    var elems = document.getElementsByTagName('*'), i;
    for (i in elems) {
        if((' ' + elems[i].className + ' ').indexOf(' ' + matchClass + ' ')
                > -1) {
            return elems[i].textContent;
        }
    }
}

function getUsername() {
  var n = getContentInContainer("user-link").replace("Dashboard for:", "").replace(/^\s+|\s+$/g, '');
  if (!isNaN(n[0])) {
     n = "_" + n;
  }
  return n;
}

function updateChatUrl() {
  username = getUsername();
  document.getElementById('chatiframe').src =
      'https://cs1692x.moocforums.org:9001/' +
      '?channels=' + encodeURIComponent(chatChannels) +
      '&nick=' + encodeURI(username);
}

if (document.getElementById('chatiframe')) {
  init();
} else {
  window.onload = init;
}

function updateReviewMessage() {
  // Based on http://www.jquery4u.com/json/jsonp-examples/
  $.ajax({
      url: urlPrefix + 'getdate/',
      dataType: 'jsonp',
      type: 'GET',
      async: false,
      contentType: "application/json",
      jsonpCallback: 'jsonCallback',
      success: function (json) {
	  if (json.year == 2013 &&
	      json.month == 12 &&
	      json.day >= 12 && json.day <= 15 &&
	      (json.day > 12 || json.hour >= 12) &&
	      (json.day < 15 || json.hour < 12) &&
	      json.minute >= 50)
	  {
	      $("#reviewstarting").show();
	  } else {
	      $("#reviewstarting").hide();
	  }
      }
  });
}

function init() {
  updateChatUrl();

  if (onChatTab) {
      document.getElementById('chatiframe').height = 600;
  }
  $("#chatframe").show();

  username = getUsername();

  messageContent =
  ['
',
   '
',
   'The next Interactive Review session is starting in less than 10 minutes. Please arrive in advance in order to complete the consent form.',
   '
',
   '

'
  ].join('\n');

  if ($('#reviewstarting').length == 0) {
    $(".sequence-nav").after(messageContent);
  }

  updateReviewMessage();
  timer = setInterval(function() {
      updateReviewMessage();
  }, 30 * 1000);
}

function showDelayed(delaySeconds, element, elementHide) {
  setTimeout(function(){
    element.style.position='static';
    element.style.visibility='visible';
    //document.getElementById(elementHide).style.display='none';
                $("#chatframe").removeClass('minimized');
                $("#chat-button").html("Hide Chat");
                $.cookie('chat_default', 'open', { expires: 7 });
                $('#chat-button').on("click", function () {
                    $('#chatframe').toggleClass("minimized");
                    if ($('#chatframe').hasClass("minimized")) {
                        $.cookie('chat_default', 'closed', { expires: 7 });
                        $("#chat-button").html("Open Chat");
                    } else {
                        $.cookie('chat_default', 'open', { expires: 7 });
                        $("#chat-button").html("Hide Chat");
                    }
                });
  }, 1000*delaySeconds);
}
<commit_msg>Update chatframe_toggleBtn.js<commit_after>var pathname = window.location.pathname;
var chatChannels = "#"+pathname.split('/')[3];
//var chatChannels = $("#chatframe").attr('chatroom');//"#cs1691x";
var urlPrefix = 'https://cs1692x.moocforums.org/chatlog/edxframe/CS169.1x/3T2013/';

var onChatTab = false;
if (document.title.indexOf("Chat") != -1) {
  onChatTab = true;
}

chatframeContent =
['Open Chat',
 '',
 '<link rel="stylesheet" href="https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />',
 ''
].join('\n');

$("#chatframe").html(chatframeContent);
$("#chatiframe").on('load', function() {
	showDelayed(5, this, 'loadingchat');
});

if (document.getElementById('chatiframe')) {
  init();
} else {
  window.onload = init;
}

function getContentInContainer(matchClass) {
    var elems = document.getElementsByTagName('*'), i;
    for (i in elems) {
        if((' ' + elems[i].className + ' ').indexOf(' ' + matchClass + ' ')
                > -1) {
            return elems[i].textContent;
        }
    }
}

function getUsername() {
  var n = getContentInContainer("user-link").replace("Dashboard for:", "").replace(/^\s+|\s+$/g, '');
  if (!isNaN(n[0])) {
     n = "_" + n;
  }
  return n;
}

function updateChatUrl() {
  username = getUsername();
  document.getElementById('chatiframe').src =
      'https://cs1692x.moocforums.org:9001/' +
      '?channels=' + encodeURIComponent(chatChannels) +
      '&nick=' + encodeURI(username);
}

function updateReviewMessage() {
  // Based on http://www.jquery4u.com/json/jsonp-examples/
  $.ajax({
      url: urlPrefix + 'getdate/',
      dataType: 'jsonp',
      type: 'GET',
      async: false,
      contentType: "application/json",
      jsonpCallback: 'jsonCallback',
      success: function (json) {
	  if (json.year == 2013 &&
	      json.month == 12 &&
	      json.day >= 12 && json.day <= 15 &&
	      (json.day > 12 || json.hour >= 12) &&
	      (json.day < 15 || json.hour < 12) &&
	      json.minute >= 50)
	  {
	      $("#reviewstarting").show();
	  } else {
	      $("#reviewstarting").hide();
	  }
      }
  });
}

function init() {
  updateChatUrl();

  if (onChatTab) {
      document.getElementById('chatiframe').height = 600;
  }
  $("#chatframe").show();

  username = getUsername();

  messageContent =
  ['
',
   '
',
   'The next Interactive Review session is starting in less than 10 minutes. Please arrive in advance in order to complete the consent form.',
   '
',
   '

'
  ].join('\n');

  if ($('#reviewstarting').length == 0) {
    $(".sequence-nav").after(messageContent);
  }

  updateReviewMessage();
  timer = setInterval(function() {
      updateReviewMessage();
  }, 30 * 1000);
}

function showDelayed(delaySeconds, element, elementHide) {
  setTimeout(function(){
    element.style.position='static';
    element.style.visibility='visible';
    //document.getElementById(elementHide).style.display='none';
                $("#chatframe").removeClass('minimized');
                $("#chat-button").html("Hide Chat");
                $.cookie('chat_default', 'open', { expires: 7 });
                $('#chat-button').on("click", function () {
                    $('#chatframe').toggleClass("minimized");
                    if ($('#chatframe').hasClass("minimized")) {
                        $.cookie('chat_default', 'closed', { expires: 7 });
                        $("#chat-button").html("Open Chat");
                    } else {
                        $.cookie('chat_default', 'open', { expires: 7 });
                        $("#chat-button").html("Hide Chat");
                    }
                });
  }, 1000*delaySeconds);
}
<|endoftext|>


<commit_before>const os = require('os');

module.exports = {
  DEBUG: true,

  STATES: {
    UNSUPPORTED: 0,
    UNINSTALLED: 1,
    INSTALLED: 2,
    RUNNING: 3,
    REACHABLE: 4,
    AUTHENTICATED: 5,
    WHITELISTED: 6,
  },

  SUPPORTS: {
    getSupport() {
      switch (os.platform()) {
        case 'darwin': return require('./support/osx');
        case 'win32': return require('./support/windows');
        default: return require('./support/no-support');
      }
    },
  },
};
<commit_msg>Disable debug mode<commit_after>const os = require('os');

module.exports = {
  DEBUG: false,

  STATES: {
    UNSUPPORTED: 0,
    UNINSTALLED: 1,
    INSTALLED: 2,
    RUNNING: 3,
    REACHABLE: 4,
    AUTHENTICATED: 5,
    WHITELISTED: 6,
  },

  SUPPORTS: {
    getSupport() {
      switch (os.platform()) {
        case 'darwin': return require('./support/osx');
        case 'win32': return require('./support/windows');
        default: return require('./support/no-support');
      }
    },
  },
};
<|endoftext|>


<commit_before>var kafka       = require('kafka-node');
var uuid        = require('uuid');
var config      = require('../config');
var logger      = require('../logger').logger;
var consumers   = {};

function createConsumer(group, topic, autocommit, instanceId) {
    var client = new kafka.Client(config.kafka.zkConnect, config.kafka.clientId.http);
    return new kafka.HighLevelConsumer(client, [{
        topic: topic
    }], {
        groupId: group,
        id: !!instanceId ? group + '_' + instanceId : undefined,
        // Auto commit config
        autoCommit: autocommit,
        // The max wait time is the maximum amount of time in milliseconds to block waiting if insufficient data is available at the time the request is issued, default 100ms
        fetchMaxWaitMs: 100,
        // This is the minimum number of bytes of messages that must be available to give a response, default 1 byte
        fetchMinBytes: 1,
        // The maximum bytes to include in the message set for this partition. This helps bound the size of the response.
        fetchMaxBytes: 4 * 1024 * 1024, // 4MB
        // If set true, consumer will fetch message from the given offset in the payloads
        fromOffset: false,
        // If set to 'buffer', values will be returned as raw buffer objects.
        encoding: 'utf8'
    });
}

var get = function (group, id, callback) {
        if (arguments.length < 1) {
            throw new Error('Group and Instance ID or ID required.');
        }

        if (typeof id === 'string'){
            group += '/' + id;
        }
        else if (typeof id === 'function') {
            callback = id;
        }

        var consumer = consumers[group];
        if (!consumer) {
            return callback( {message: 'consumer not found'}, null);
        }

        if (callback) {
            return callback(null, consumer);
        }

        return consumer;
    },

    add = function (consumer, callback) {
        consumer.instanceId = consumer.instanceId || uuid.v4();
        consumer.id = consumer.group + '/' + consumer.instanceId;
        if (!!consumers[consumer.id]) {
            var message = 'Consumer with ID ' + consumer.id + ' already exists.';
            if (!!callback){
                return callback({
                    name: 'Error',
                    message: message});
            }

            throw Error(message);
        }

        consumer.autoOffsetReset = consumer.autoOffsetReset || 'largest';
        consumer.autoCommitEnable = typeof consumer.autoCommitEnable === 'undefined' ? config.consumer.autoCommitEnable : consumer.autoCommitEnable;
        consumer.instance = undefined;
        consumer.topics = [];
        consumer.messages = [];
        consumer.created = new Date();
        consumer.lastPoll = Date.now();
        consumer.lock = false;
        consumer.byteSize = 0;
        consumer.offsetMap = [];

        consumers[consumer.id] = consumer;
        logger.debug({consumer: consumer}, 'lib/consumerManager : consumer added');

        if (!!callback) {
            callback(null, consumer);
        }
    },

    createConsumerInstance = function (consumer, topic) {
        if (consumer.lock) {
            logger.debug('lib/consumerManager : consumer is locked, return as there is already an instance or its being recreated');
            return;
        }

        logger.debug('lib/consumerManager : creating a kafka client');
        var client = new kafka.Client(config.kafka.zkConnect, config.kafka.clientId.http);
        logger.debug('lib/consumerManager : creating a new consumer');
        consumer.instance = createConsumer(consumer.group, topic, config.kafka.autocommit.http, consumer.instanceId);

        logger.debug('lib/consumerManager : consumer created');
        consumer.instance.on('message', function (m) {
            logger.trace({messages: consumer.messages, message: m}, 'lib/consumerManager : consumer message received');
            consumer.messages.push(m);
            consumer.byteSize += Buffer.byteLength(m.value);

            if (consumer.byteSize > (16 * 1024 * 1024)) {
                logger.info('lib/consumerManager : consumer message queue greater than acceptable size, pausing consumer');
                consumer.instance.pause();
            }
        });

        consumer.instance.on('rebalancing', function(event){
            logger.info('lib/consumerManager : Consumer rebalancing');
            consumer.messages = [];
        });

        consumer.instance.on('rebalanced', function () {
            logger.info({consumer : consumer.id, topicsPayloads: consumer.instance.topicPayloads},'lib/consumerManager : rebalanced consumer');
        });

        consumer.instance.on('error', function (e) {
            logger.error({ error: e, consumer: consumer.id }, 'lib/consumerManager : Error in consumer instance. Closing and recreating...');
            if (!consumer.lock) {
                consumer.lock = true;
                logger.debug({ consumer: consumer.id }, 'lock enabled on consumer');
                consumer.instance.close(false, function () {
                    setTimeout(function () {
                        logger.info({consumer: consumer.id}, 'lib/consumerManager : Recreating consumer');
                        createConsumerInstance(consumer, topic);
                        consumer.lock = false;
                        logger.debug({ consumer: consumer.id }, 'lock released on consumer');
                    }, 1000);
                });
            }
        });

        consumer.instance.on('offsetOutOfRange', function (e) {
            logger.warn({ error: e }, 'lib/consumerManager : Received alert for offset out of range.');
        });
    },

    findOffsetInMap = function(map, searchItem) {
        logger.trace({map : map}, 'searching the offset map');
        var results = map.filter(function(item) {
            return  item.topic === searchItem.topic &&
                    item.partition === searchItem.partition;
        });
        return results && results.length ? results[0] : undefined;
    },

    createOffsetItem = function(message) {
        // note : metadata is an arbitrary value for kafka-node clients
        return {
            topic : message.topic || '',
            partition: message.partition || 0,
            offset : (message.offset !== undefined) ? message.offset + 1 : 0,
            metadata : 'm'
        };
    },

    createOffsetMap = function(messages) {
        return messages.reduce(function(map, message){
            logger.trace(message, 'creating offset map for message');
            var offsetItem = findOffsetInMap(map, message);

            logger.trace({offsetItem: offsetItem || 'nothing'}, 'offset item from map');
            if (offsetItem === undefined) {
                map.push(createOffsetItem(message));
            } else {
                if (message.offset > offsetItem.offset) {
                    offsetItem.offset = message.offset;
                }
            }
            return map;
        }, []);
    },

    getMessages = function (consumer, callback) {

        consumer.lastPoll = Date.now();

        logger.trace({buffer: consumer.messages, id: consumer.id}, 'consumer message buffer');
        var messages = consumer.messages.slice(0);

        if (messages.length === 0) {
            logger.trace({consumer: consumer.id}, 'no messages in the buffer');
            return callback(null, []);
        }

        if (consumer.autoCommitEnable) {
            logger.trace({ consumer: consumer.id }, 'lib/consumerManager : Autocommit.');
            consumer.instance.commit(true);
        }

        if (consumer.instance.paused) {
            logger.info({ consumer: consumer.id }, 'lib/consumerManager : resuming consumer');
            consumer.instance.resume();
        }

        function getValidKeyFromBuffer(buffer) {
            var key = buffer.toString();
            if (!key.match(/^[\w-]+$/g)) {
                key = '';
                logger.trace('key was not valid, returning empty string');
            };

            logger.trace({key: key}, 'returned key from kafka');
            return key;
        }

        logger.trace({ consumer: consumer.id }, 'lib/consumerManager : returning ' + messages.length + ' messages.');
        callback(null, messages.map(function (m) {
            return {
                topic: m.topic,
                partition: m.partition,
                offset: m.offset,
                key: getValidKeyFromBuffer(m.key),
                value: m.value
            };
        }));

        consumer.messages.splice(0, messages.length);
        consumer.offsetMap = createOffsetMap(messages);
    },

    commitOffsets = function(consumer, callback) {
        consumer.instance.client.sendOffsetCommitRequest(
            consumer.groupid,
            consumer.offsetMap.map(function(item){
                item.fetchMaxBytes = consumer.options.fetchMaxBytes;
                return item;
            }),
            callback);
    },

    deleteConsumer = function (consumer, callback) {
        logger.debug({ consumer: consumer.id }, 'lib/consumerManager : Removing consumer from set.');
        delete consumers[consumer.id];
        logger.debug({ consumer: consumer.id }, 'lib/consumerManager : Closing consumer...');
        if (!!consumer.instance) {
            consumer.instance.close(false, function () {
                logger.debug({ consumer: consumer.id }, 'lib/consumerManager : Consumer closed.');
                if (!!callback) {
                    callback();
                }
            });
        }

        if (!!callback) {
            callback();
        }
        return;
    },

    timeoutConsumers = function () {
        logger.debug('lib/consumerManager : Looking for timed-out consumers.');
        var timeoutTime = Date.now() - config.consumer.timeoutMs;
        for (var i in consumers) {
            var consumer = consumers[i];
            if (consumer.instance && consumer.lastPoll < timeoutTime) {
                logger.debug({ consumer : consumer.id }, 'lib/consumerManager : Consumer timed-out.');
                deleteConsumer(consumer);
            }
        }
        logger.debug('lib/consumerManager : Done looking for timed-out consumers.');
    };

module.exports = {
    get: get,
    add: add,
    createInstance: createConsumerInstance,
    getMessages: getMessages,
    commitOffsets: commitOffsets,
    delete: deleteConsumer,
    timeout: timeoutConsumers,
    create: createConsumer
};
<commit_msg>resume consumer on any get or commit<commit_after>var kafka       = require('kafka-node');
var uuid        = require('uuid');
var config      = require('../config');
var logger      = require('../logger').logger;
var consumers   = {};

function createConsumer(group, topic, autocommit, instanceId) {
    var client = new kafka.Client(config.kafka.zkConnect, config.kafka.clientId.http);
    return new kafka.HighLevelConsumer(client, [{
        topic: topic
    }], {
        groupId: group,
        id: !!instanceId ? group + '_' + instanceId : undefined,
        // Auto commit config
        autoCommit: autocommit,
        // The max wait time is the maximum amount of time in milliseconds to block waiting if insufficient data is available at the time the request is issued, default 100ms
        fetchMaxWaitMs: 100,
        // This is the minimum number of bytes of messages that must be available to give a response, default 1 byte
        fetchMinBytes: 1,
        // The maximum bytes to include in the message set for this partition. This helps bound the size of the response.
        fetchMaxBytes: 4 * 1024 * 1024, // 4MB
        // If set true, consumer will fetch message from the given offset in the payloads
        fromOffset: false,
        // If set to 'buffer', values will be returned as raw buffer objects.
        encoding: 'utf8'
    });
}

var get = function (group, id, callback) {
        if (arguments.length < 1) {
            throw new Error('Group and Instance ID or ID required.');
        }

        if (typeof id === 'string'){
            group += '/' + id;
        }
        else if (typeof id === 'function') {
            callback = id;
        }

        var consumer = consumers[group];
        if (!consumer) {
            return callback( {message: 'consumer not found'}, null);
        }

        if (callback) {
            return callback(null, consumer);
        }

        return consumer;
    },

    add = function (consumer, callback) {
        consumer.instanceId = consumer.instanceId || uuid.v4();
        consumer.id = consumer.group + '/' + consumer.instanceId;
        if (!!consumers[consumer.id]) {
            var message = 'Consumer with ID ' + consumer.id + ' already exists.';
            if (!!callback){
                return callback({
                    name: 'Error',
                    message: message});
            }

            throw Error(message);
        }

        consumer.autoOffsetReset = consumer.autoOffsetReset || 'largest';
        consumer.autoCommitEnable = typeof consumer.autoCommitEnable === 'undefined' ? config.consumer.autoCommitEnable : consumer.autoCommitEnable;
        consumer.instance = undefined;
        consumer.topics = [];
        consumer.messages = [];
        consumer.created = new Date();
        consumer.lastPoll = Date.now();
        consumer.lock = false;
        consumer.byteSize = 0;
        consumer.offsetMap = [];

        consumers[consumer.id] = consumer;
        logger.debug({consumer: consumer}, 'lib/consumerManager : consumer added');

        if (!!callback) {
            callback(null, consumer);
        }
    },

    createConsumerInstance = function (consumer, topic) {
        if (consumer.lock) {
            logger.debug('lib/consumerManager : consumer is locked, return as there is already an instance or its being recreated');
            return;
        }

        logger.debug('lib/consumerManager : creating a kafka client');
        var client = new kafka.Client(config.kafka.zkConnect, config.kafka.clientId.http);
        logger.debug('lib/consumerManager : creating a new consumer');
        consumer.instance = createConsumer(consumer.group, topic, config.kafka.autocommit.http, consumer.instanceId);

        logger.debug('lib/consumerManager : consumer created');
        consumer.instance.on('message', function (m) {
            logger.trace({messages: consumer.messages, message: m}, 'lib/consumerManager : consumer message received');
            consumer.messages.push(m);
            consumer.byteSize += Buffer.byteLength(m.value);

            if (consumer.byteSize > (16 * 1024 * 1024) && !consumer.instance.paused) {
                logger.info({consumer: consumer.id }, 'lib/consumerManager : consumer message queue greater than acceptable size, pausing consumer');
                consumer.instance.pause();
            }
        });

        consumer.instance.on('rebalancing', function(event){
            logger.info('lib/consumerManager : Consumer rebalancing');
            consumer.messages = [];
        });

        consumer.instance.on('rebalanced', function () {
            logger.info({consumer : consumer.id, topicsPayloads: consumer.instance.topicPayloads},'lib/consumerManager : rebalanced consumer');
        });

        consumer.instance.on('error', function (e) {
            logger.error({ error: e, consumer: consumer.id }, 'lib/consumerManager : Error in consumer instance. Closing and recreating...');
            if (!consumer.lock) {
                consumer.lock = true;
                logger.debug({ consumer: consumer.id }, 'lock enabled on consumer');
                consumer.instance.close(false, function () {
                    setTimeout(function () {
                        logger.info({consumer: consumer.id}, 'lib/consumerManager : Recreating consumer');
                        createConsumerInstance(consumer, topic);
                        consumer.lock = false;
                        logger.debug({ consumer: consumer.id }, 'lock released on consumer');
                    }, 1000);
                });
            }
        });

        consumer.instance.on('offsetOutOfRange', function (e) {
            logger.warn({ error: e }, 'lib/consumerManager : Received alert for offset out of range.');
        });
    },

    findOffsetInMap = function(map, searchItem) {
        logger.trace({map : map}, 'searching the offset map');
        var results = map.filter(function(item) {
            return  item.topic === searchItem.topic &&
                    item.partition === searchItem.partition;
        });
        return results && results.length ? results[0] : undefined;
    },

    createOffsetItem = function(message) {
        // note : metadata is an arbitrary value for kafka-node clients
        return {
            topic : message.topic || '',
            partition: message.partition || 0,
            offset : (message.offset !== undefined) ? message.offset + 1 : 0,
            metadata : 'm'
        };
    },

    createOffsetMap = function(messages) {
        return messages.reduce(function(map, message){
            logger.trace(message, 'creating offset map for message');
            var offsetItem = findOffsetInMap(map, message);

            logger.trace({offsetItem: offsetItem || 'nothing'}, 'offset item from map');
            if (offsetItem === undefined) {
                map.push(createOffsetItem(message));
            } else {
                if (message.offset > offsetItem.offset) {
                    offsetItem.offset = message.offset;
                }
            }
            return map;
        }, []);
    },

    getMessages = function (consumer, callback) {

        consumer.lastPoll = Date.now();

        logger.trace({buffer: consumer.messages, id: consumer.id}, 'consumer message buffer');
        var messages = consumer.messages.slice(0);

        if (consumer.instance.paused) {
            logger.info({ consumer: consumer.id }, 'resuming consumer');
            consumer.instance.resume();
        }

        if (messages.length === 0) {
            logger.trace({consumer: consumer.id}, 'no messages in the buffer');
            return callback(null, []);
        }

        if (consumer.autoCommitEnable) {
            logger.trace({ consumer: consumer.id }, 'lib/consumerManager : Autocommit.');
            consumer.instance.commit(true);
        }

        function getValidKeyFromBuffer(buffer) {
            var key = buffer.toString();
            if (!key.match(/^[\w-]+$/g)) {
                key = '';
                logger.trace('key was not valid, returning empty string');
            };

            logger.trace({key: key}, 'returned key from kafka');
            return key;
        }

        logger.trace({ consumer: consumer.id }, 'lib/consumerManager : returning ' + messages.length + ' messages.');
        callback(null, messages.map(function (m) {
            return {
                topic: m.topic,
                partition: m.partition,
                offset: m.offset,
                key: getValidKeyFromBuffer(m.key),
                value: m.value
            };
        }));

        consumer.messages.splice(0, messages.length);
        consumer.offsetMap = createOffsetMap(messages);
    },

    commitOffsets = function(consumer, callback) {

        if (consumer.instance.paused) {
            logger.info({ consumer: consumer.id }, 'resuming consumer');
            consumer.instance.resume();
        }

        consumer.instance.client.sendOffsetCommitRequest(
            consumer.groupid,
            consumer.offsetMap.map(function(item){
                item.fetchMaxBytes = consumer.options.fetchMaxBytes;
                return item;
            }),
            callback);
    },

    deleteConsumer = function (consumer, callback) {
        logger.debug({ consumer: consumer.id }, 'lib/consumerManager : Removing consumer from set.');
        delete consumers[consumer.id];
        logger.debug({ consumer: consumer.id }, 'lib/consumerManager : Closing consumer...');
        if (!!consumer.instance) {
            consumer.instance.close(false, function () {
                logger.debug({ consumer: consumer.id }, 'lib/consumerManager : Consumer closed.');
                if (!!callback) {
                    callback();
                }
            });
        }

        if (!!callback) {
            callback();
        }
        return;
    },

    timeoutConsumers = function () {
        logger.debug('lib/consumerManager : Looking for timed-out consumers.');
        var timeoutTime = Date.now() - config.consumer.timeoutMs;
        for (var i in consumers) {
            var consumer = consumers[i];
            if (consumer.instance && consumer.lastPoll < timeoutTime) {
                logger.debug({ consumer : consumer.id }, 'lib/consumerManager : Consumer timed-out.');
                deleteConsumer(consumer);
            }
        }
        logger.debug('lib/consumerManager : Done looking for timed-out consumers.');
    };

module.exports = {
    get: get,
    add: add,
    createInstance: createConsumerInstance,
    getMessages: getMessages,
    commitOffsets: commitOffsets,
    delete: deleteConsumer,
    timeout: timeoutConsumers,
    create: createConsumer
};
<|endoftext|>