<commit_before>'use strict';

var major = require('./package.json').version.split('.').shift()
  , Registry = require('npm-registry')
  , resolve = require('./resolve')
  , licenses = require('licenses')
  , Pagelet = require('pagelet')
  , Contour = require('contour')
  , moment = require('moment')
  , brand = Contour.get('npm')
  , async = require('async')
  , ms = require('ms');

Pagelet.extend({
  //
  // Specify the locations of our UI components.
  //
  view: 'view.ejs',       // The template that gets rendered.
  css:  'css.styl',       // All CSS required to render this component.
  js:   'client.js',      // Progressive enhancements for the UI.
  resolve: resolve,       // Expose the resolver so it can be overridden.

  //
  // External dependencies that should be included on the page using a regular
  // script tag. This dependency is needed for the `package.js` client file.
  //
  dependencies: [
    '//code.jquery.com/jquery-2.1.0.min.js',
    brand.normalize,
    brand.global,
    brand.grid,
    brand.icons,
    brand.typography,
    brand.animations,
    brand.tables
  ],

  /**
   * The different expirations:
   *
   * - latest: This expires the latest version number of a given package.
   * - data: This expires the resolved data for a given version number.
   *
   * @type {Object}
   * @api public
   */
  expire: {
    latest: ms('1 hours') / 1000,
    data: ms('7 days') / 1000
  },

  /**
   * There are parts of page that could require Github API access. As you might
   * know there is rate limiting in place for API calls. Unauthorized calls are
   * 60 RPH (requests per hour) and authorized is 5000 RPH. You can create an
   * authorized GitHulk instance which we will be used instead of a default
   * unauthorized GitHulk.
   *
   * @type {Githulk|Null}
   * @api public
   */
  githulk: null,

  /**
   * The default registry we should use when resolving package information.
   *
   * @type {String}
   * @api public
   */
  registry: Registry.mirrors.nodejitsu,

  /**
   * Return the cache key for a given module. By default we are prefixing the
   * names with the major version number of this module. As we want to be able
   * to change the structure of the data without creating potential cache
   * conflicts. In addition to that this prevent potential dictionary attacks
   * where people use __proto__ as package name.
   *
   * @param {String} name The name of the module.
   * @param {String} version The version number of the module.
   * @returns {String} The cache key.
   * @api public
   */
  key: function key(name, version) {
    return 'v'+ major +':'+ name +'@'+ version;
  },

  /**
   * Do we have a dedicated dependencies pagelet?
   *
   * @type {Boolean}
   * @api public
   */
  dependenciesPagelet: false,

  /**
   * Final post processing step on the data before it gets rendered.
   *
   * @param {Object} data The resolved data from cache or directly from the resolver.
   * @returns {Object} data Modified data.
   * @api private
   */
  postprocess: function postproces(data) {
    //
    // Make all dates human readable.
    //
    if (data.package.time) Object.keys(data.package.time).forEach(function (time) {
      var date = data.package.time[time];

      if ('string' !== typeof date && date.full) date = date.full;

      data.package.time[time] = {
        human: moment(date).format('MMM Do YYYY'),
        ago: moment(date).fromNow(),
        full: date
      };
    });

    ['created', 'modified'].forEach(function (time) {
      var date = data.package[time];

      if ('string' !== typeof date && date.full) date = date.full;

      data.package[time] = {
        human: moment(date).format('MMM Do YYYY'),
        ago: moment(date).fromNow(),
        full: date
      };
    });

    //
    // Not yet fetched if stats is undefined.
    //
    data.stats = data.stats || { downloads: 'Unknown' };

    //
    // Expose helper method.
    //
    data.licenses = licenses.info;

    return data;
  },

  /**
   * Get the latest version of a module.
   *
   * @param {String} name The name of the module.
   * @param {Function} fn The callback.
   * @api private
   */
  latest: function latest(name, fn) {
    var key = this.key(name, 'latest')
      , pagelet = this;

    this.fireforget('get', key, function cached(err, data) {
      if (!err && data) return fn(err, data);

      var registry = 'string' !== typeof pagelet.registry
        ? pagelet.registry
        : new Registry({ registry: pagelet.registry });

      registry.packages.get(name +'/latest', function latest(err, data) {
        if (err) return fn(err);

        if (Array.isArray(data)) data = data[0];
        pagelet.fireforget('set', key, data.version, pagelet.expire.latest);

        fn(undefined, data.version);
      });
    });
  },

  /**
   * Simple wrapper around a possible cache interface.
   *
   * @param {String} method The cache method we went to invoke.
   * @param {String} key The key we want to retrieve.
   * @param {Object} obj The data we want to store.
   * @param {Number} expire Optional expiration for the set data.
   * @param {Function} fn An optional callback.
   * @api private
   */
  fireforget: function (method, key, obj, expire, fn) {
    if ('function' === typeof obj) {
      fn = obj;
      obj = null;
    }

    if ('function' === typeof expire) {
      fn = expire;
      expire = 0;
    }

    fn = fn || function nope() {};

    var pagelet = this;

    //
    // Force asynchronous execution of cache retrieval without starving I/O
    //
    (
      global.setImmediate   // Only available since node 0.10
      ? global.setImmediate
      : global.setTimeout
    )(function immediate() {
      if (key && pagelet.cache) {
        if ('get' === method) {
          if (pagelet.cache.get.length === 1) {
            return fn(undefined, pagelet.cache.get(key));
          } else {
            return pagelet.cache.get(key, fn);
          }
        } else if ('set' === method) {
          if (pagelet.cache.set.length === 2) {
            return fn(undefined, pagelet.cache.set(key, obj));
          } else {
            if (!expire) return pagelet.cache.set(key, obj, fn);
            return pagelet.cache.set(key, obj, expire, fn);
          }
        }
      }

      //
      // Nothing, no cache or matching methods.
      //
      fn();
    });

    return this;
  },

  /**
   * Get the current download stats for the given package.
   *
   * @param {String} name The name of the package.
   * @param {Function} next Completion callback.
   * @api private
   */
  downloads: function downloads(name, next) {
    var npm = this.resolve.clients(this).npm;

    if (!npm.downloads) return next(undefined, { downloads: 0 });

    npm.downloads.totals('last-day', name, function handle(err, data) {
      next(err, data = Array.isArray(data) ? data[0] : data);
    });
  },

  /**
   * Prepare the data for rendering. All the data that is send to the callback
   * is exposed in the template.
   *
   * @param {Function} render Completion callback.
   * @api private
   */
  get: function get(render) {
    var name = this.params.name
      , pagelet = this
      , key;

    async.parallel({
      data: function datas(next) {
        pagelet.latest(name, function latest(err, version) {
          if (err) return next(err);

          key = pagelet.key(name, version);

          pagelet.fireforget('get', key, function cached(err, data) {
            if (!err && data) return next(err, data);

            //
            // No data or an error, resolve the data structure and attempt to
            // store it again.
            //
            pagelet.resolve(name, {
              registry: pagelet.registry,
              githulk: pagelet.githulk
            }, function resolved(err, data) {
              //
              // Store and forget, we should delay the rendering procedure any
              // longer as manually resolving took to damn much time.
              //
              if (!err && data) pagelet.fireforget('set', key, data, pagelet.expire.data);
              if (!data && !err) err = new Error('Missing data, resolving failed');

              next(err, data);
            });
          });
        });
      },
      stats: this.downloads.bind(this, name)
    }, function next(err, dataset) {
      if (err) return render(err);

      var data = dataset.data;
      data.stats = dataset.stats;
      data.dependenciesPagelet = pagelet.dependenciesPagelet;

      render(undefined, pagelet.postprocess(data));
    });
  },

  /**
   * Add some extra pagelets to the page so we can spead the loading time of
   * this page better.
   *
   * @type {Object}
   * @api private
   */
  pagelets: {
    sparklet: require('sparklet').extend({
      xaxis: true,
      yaxis: true,

      fetch: function fetch(next) {
        var name = this.params.name;

        resolve.clients().npm.downloads.range('last-month', name, function downloads(err, data) {
          data = Array.isArray(data) ? data[0] : data;
          if (err) return next(err);
          if (!data.downloads) console.error('ERR: No data.downloads for '+ name);

          return next(err, (data.downloads || []).map(function map(row) {
            return {
              value: row.downloads,
              date: row.day
            };
          }));
        });
      }
    })
  }
}).on(module);

//
// Also expose the `resolve` method on the Pagelet instance so we can use this
// to pre-populate a cache.
//
module.exports.resolve = resolve;
<commit_msg>[fix] safety measure<commit_after>'use strict';

var major = require('./package.json').version.split('.').shift()
  , Registry = require('npm-registry')
  , resolve = require('./resolve')
  , licenses = require('licenses')
  , Pagelet = require('pagelet')
  , Contour = require('contour')
  , moment = require('moment')
  , brand = Contour.get('npm')
  , async = require('async')
  , ms = require('ms');

Pagelet.extend({
  //
  // Specify the locations of our UI components.
  //
  view: 'view.ejs',       // The template that gets rendered.
  css:  'css.styl',       // All CSS required to render this component.
  js:   'client.js',      // Progressive enhancements for the UI.
  resolve: resolve,       // Expose the resolver so it can be overridden.

  //
  // External dependencies that should be included on the page using a regular
  // script tag. This dependency is needed for the `package.js` client file.
  //
  dependencies: [
    '//code.jquery.com/jquery-2.1.0.min.js',
    brand.normalize,
    brand.global,
    brand.grid,
    brand.icons,
    brand.typography,
    brand.animations,
    brand.tables
  ],

  /**
   * The different expirations:
   *
   * - latest: This expires the latest version number of a given package.
   * - data: This expires the resolved data for a given version number.
   *
   * @type {Object}
   * @api public
   */
  expire: {
    latest: ms('1 hours') / 1000,
    data: ms('7 days') / 1000
  },

  /**
   * There are parts of page that could require Github API access. As you might
   * know there is rate limiting in place for API calls. Unauthorized calls are
   * 60 RPH (requests per hour) and authorized is 5000 RPH. You can create an
   * authorized GitHulk instance which we will be used instead of a default
   * unauthorized GitHulk.
   *
   * @type {Githulk|Null}
   * @api public
   */
  githulk: null,

  /**
   * The default registry we should use when resolving package information.
   *
   * @type {String}
   * @api public
   */
  registry: Registry.mirrors.nodejitsu,

  /**
   * Return the cache key for a given module. By default we are prefixing the
   * names with the major version number of this module. As we want to be able
   * to change the structure of the data without creating potential cache
   * conflicts. In addition to that this prevent potential dictionary attacks
   * where people use __proto__ as package name.
   *
   * @param {String} name The name of the module.
   * @param {String} version The version number of the module.
   * @returns {String} The cache key.
   * @api public
   */
  key: function key(name, version) {
    return 'v'+ major +':'+ name +'@'+ version;
  },

  /**
   * Do we have a dedicated dependencies pagelet?
   *
   * @type {Boolean}
   * @api public
   */
  dependenciesPagelet: false,

  /**
   * Final post processing step on the data before it gets rendered.
   *
   * @param {Object} data The resolved data from cache or directly from the resolver.
   * @returns {Object} data Modified data.
   * @api private
   */
  postprocess: function postproces(data) {
    //
    // Make all dates human readable.
    //
    if (data.package.time) Object.keys(data.package.time).forEach(function (time) {
      var date = data.package.time[time];

      if ('string' !== typeof date && date.full) date = date.full;

      data.package.time[time] = {
        human: moment(date).format('MMM Do YYYY'),
        ago: moment(date).fromNow(),
        full: date
      };
    });

    ['created', 'modified'].forEach(function (time) {
      var date = data.package[time];

      if ('string' !== typeof date && date.full) date = date.full;

      data.package[time] = {
        human: moment(date).format('MMM Do YYYY'),
        ago: moment(date).fromNow(),
        full: date
      };
    });

    //
    // Not yet fetched if stats is undefined.
    //
    data.stats = data.stats || { downloads: 'Unknown' };

    //
    // Expose helper method.
    //
    data.licenses = licenses.info;

    return data;
  },

  /**
   * Get the latest version of a module.
   *
   * @param {String} name The name of the module.
   * @param {Function} fn The callback.
   * @api private
   */
  latest: function latest(name, fn) {
    var key = this.key(name, 'latest')
      , pagelet = this;

    this.fireforget('get', key, function cached(err, data) {
      if (!err && data) return fn(err, data);

      var registry = 'string' !== typeof pagelet.registry
        ? pagelet.registry
        : new Registry({ registry: pagelet.registry });

      registry.packages.get(name +'/latest', function latest(err, data) {
        if (err) return fn(err);

        if (Array.isArray(data)) data = data[0];
        pagelet.fireforget('set', key, data.version, pagelet.expire.latest);

        fn(undefined, data.version);
      });
    });
  },

  /**
   * Simple wrapper around a possible cache interface.
   *
   * @param {String} method The cache method we went to invoke.
   * @param {String} key The key we want to retrieve.
   * @param {Object} obj The data we want to store.
   * @param {Number} expire Optional expiration for the set data.
   * @param {Function} fn An optional callback.
   * @api private
   */
  fireforget: function (method, key, obj, expire, fn) {
    if ('function' === typeof obj) {
      fn = obj;
      obj = null;
    }

    if ('function' === typeof expire) {
      fn = expire;
      expire = 0;
    }

    fn = fn || function nope() {};

    var pagelet = this;

    //
    // Force asynchronous execution of cache retrieval without starving I/O
    //
    (
      global.setImmediate   // Only available since node 0.10
      ? global.setImmediate
      : global.setTimeout
    )(function immediate() {
      if (key && pagelet.cache) {
        if ('get' === method) {
          if (pagelet.cache.get.length === 1) {
            return fn(undefined, pagelet.cache.get(key));
          } else {
            return pagelet.cache.get(key, fn);
          }
        } else if ('set' === method) {
          if (pagelet.cache.set.length === 2) {
            return fn(undefined, pagelet.cache.set(key, obj));
          } else {
            if (!expire) return pagelet.cache.set(key, obj, fn);
            return pagelet.cache.set(key, obj, expire, fn);
          }
        }
      }

      //
      // Nothing, no cache or matching methods.
      //
      fn();
    });

    return this;
  },

  /**
   * Get the current download stats for the given package.
   *
   * @param {String} name The name of the package.
   * @param {Function} next Completion callback.
   * @api private
   */
  downloads: function downloads(name, next) {
    var npm = this.resolve.clients(this).npm;

    if (!npm.downloads) return next(undefined, { downloads: 0 });

    npm.downloads.totals('last-day', name, function handle(err, data) {
      next(err, data = Array.isArray(data) ? data[0] : data);
    });
  },

  /**
   * Prepare the data for rendering. All the data that is send to the callback
   * is exposed in the template.
   *
   * @param {Function} render Completion callback.
   * @api private
   */
  get: function get(render) {
    var name = this.params.name
      , pagelet = this
      , key;

    //
    // Defensive fallback if the parameter was parsed to undefined value.
    //
    if (!name) return render(new Error('Missing package name, resolving failed'));

    async.parallel({
      data: function datas(next) {
        pagelet.latest(name, function latest(err, version) {
          if (err) return next(err);

          key = pagelet.key(name, version);

          pagelet.fireforget('get', key, function cached(err, data) {
            if (!err && data) return next(err, data);

            //
            // No data or an error, resolve the data structure and attempt to
            // store it again.
            //
            pagelet.resolve(name, {
              registry: pagelet.registry,
              githulk: pagelet.githulk
            }, function resolved(err, data) {
              //
              // Store and forget, we should delay the rendering procedure any
              // longer as manually resolving took to damn much time.
              //
              if (!err && data) pagelet.fireforget('set', key, data, pagelet.expire.data);
              if (!data && !err) err = new Error('Missing data, resolving failed');

              next(err, data);
            });
          });
        });
      },
      stats: this.downloads.bind(this, name)
    }, function next(err, dataset) {
      if (err) return render(err);

      var data = dataset.data;
      data.stats = dataset.stats;
      data.dependenciesPagelet = pagelet.dependenciesPagelet;

      render(undefined, pagelet.postprocess(data));
    });
  },

  /**
   * Add some extra pagelets to the page so we can spead the loading time of
   * this page better.
   *
   * @type {Object}
   * @api private
   */
  pagelets: {
    sparklet: require('sparklet').extend({
      xaxis: true,
      yaxis: true,

      fetch: function fetch(next) {
        var name = this.params.name;

        resolve.clients().npm.downloads.range('last-month', name, function downloads(err, data) {
          data = Array.isArray(data) ? data[0] : data;
          if (err) return next(err);
          if (!data.downloads) console.error('ERR: No data.downloads for '+ name);

          return next(err, (data.downloads || []).map(function map(row) {
            return {
              value: row.downloads,
              date: row.day
            };
          }));
        });
      }
    })
  }
}).on(module);

//
// Also expose the `resolve` method on the Pagelet instance so we can use this
// to pre-populate a cache.
//
module.exports.resolve = resolve;
<|endoftext|>


<commit_before>module.exports = createTorrent

module.exports.announceList = [
  [ 'udp://tracker.openbittorrent.com:80' ],
  [ 'udp://tracker.internetwarriors.net:1337' ],
  [ 'udp://tracker.leechers-paradise.org:6969' ],
  [ 'udp://tracker.coppersurfer.tk:6969' ],
  [ 'udp://exodus.desync.com:6969' ],
  [ 'wss://tracker.webtorrent.io' ] // For WebRTC peers (see: WebTorrent.io)
]

module.exports.parseInput = parseInput

var bencode = require('bencode')
var BlockStream = require('block-stream2')
var calcPieceLength = require('piece-length')
var corePath = require('path')
var dezalgo = require('dezalgo')
var FileReadStream = require('filestream/read')
var flatten = require('flatten')
var fs = require('fs')
var isFile = require('is-file')
var junk = require('junk')
var MultiStream = require('multistream')
var once = require('once')
var parallel = require('run-parallel')
var sha1 = require('simple-sha1')
var stream = require('stream')

/**
 * Create a torrent.
 * @param  {string|File|FileList|Buffer|Stream|Array.<string|File|Buffer|Stream>} input
 * @param  {Object} opts
 * @param  {string=} opts.name
 * @param  {Date=} opts.creationDate
 * @param  {string=} opts.comment
 * @param  {string=} opts.createdBy
 * @param  {boolean|number=} opts.private
 * @param  {number=} opts.pieceLength
 * @param  {Array.<Array.<string>>=} opts.announceList
 * @param  {Array.<string>=} opts.urlList
 * @param  {function} cb
 * @return {Buffer} buffer of .torrent file data
 */
function createTorrent (input, opts, cb) {
  if (typeof opts === 'function') {
    cb = opts
    opts = {}
  }
  if (!opts) opts = {}
  parseInput(input, opts, function (err, files, singleFileTorrent) {
    if (err) return cb(err)
    opts.singleFileTorrent = singleFileTorrent
    onFiles(files, opts, cb)
  })
}

function parseInput (input, opts, cb) {
  if (typeof opts === 'function') {
    cb = opts
    opts = {}
  }
  if (!opts) opts = {}
  cb = dezalgo(cb)

  if (Array.isArray(input) && input.length === 0) throw new Error('invalid input type')

  if (isFileList(input)) input = Array.prototype.slice.call(input)
  if (!Array.isArray(input)) input = [ input ]

  // If there's just one file, allow the name to be set by `opts.name`
  if (input.length === 1 && typeof input[0] !== 'string' && !input[0].name) input[0].name = opts.name

  var commonPrefix = null
  input.forEach(function (item, i) {
    if (typeof item === 'string') return

    var path = item.fullPath || item.name
    if (!path) throw new Error('missing required `fullPath` or `name` property on input')

    item.path = path.split('/')

    if (!item.path[0]) item.path.shift() // Remove initial slash

    if (item.path.length < 2) { // No real prefix
      commonPrefix = null
    } else if (i === 0) { // The first file has a prefix
      commonPrefix = item.path[0]
    } else if (item.path[0] !== commonPrefix) { // The prefix doesn't match
      commonPrefix = null
    }
  })

  // remove junk files
  input = input.filter(function (item) {
    if (typeof item === 'string') return true
    var filename = item.path[item.path.length - 1]
    return notHidden(filename) && junk.not(filename)
  })

  if (commonPrefix) {
    input.forEach(function (item) {
      if (typeof item === 'string') return
      item.path.shift()
    })
  }

  if (!opts.name && commonPrefix) opts.name = commonPrefix
  if (!opts.name && input[0] && input[0].name) opts.name = input[0].name
  if (!opts.name && typeof input[0] === 'string') opts.name = corePath.basename(input[0])

  if (opts.name === undefined) {
    throw new Error('missing option \'name\' and unable to infer it from input[0].name')
  }

  var numPaths = input.reduce(function (sum, item) {
    return sum + Number(typeof item === 'string')
  }, 0)

  var isSingleFileTorrent = (input.length === 1)

  if (input.length === 1 && typeof input[0] === 'string') {
    if (typeof fs.stat !== 'function') {
      throw new Error('filesystem paths do not work in the browser')
    }
    // If there's a single path, verify it's a file before deciding this is a single
    // file torrent
    isFile(input[0], function (err, pathIsFile) {
      if (err) return cb(err)
      isSingleFileTorrent = pathIsFile
      processInput()
    })
  } else {
    processInput()
  }

  function processInput () {
    parallel(input.map(function (item) {
      return function (cb) {
        var file = {}

        if (isBlob(item)) {
          file.getStream = getBlobStream(item)
          file.length = item.size
        } else if (Buffer.isBuffer(item)) {
          file.getStream = getBufferStream(item)
          file.length = item.length
        } else if (isReadable(item)) {
          if (!opts.pieceLength) {
            throw new Error('must specify `pieceLength` option if input is Stream')
          }
          file.getStream = getStreamStream(item, file)
          file.length = 0
        } else if (typeof item === 'string') {
          if (typeof fs.stat !== 'function') {
            throw new Error('filesystem paths do not work in the browser')
          }
          var keepRoot = numPaths > 1 || isSingleFileTorrent
          getFiles(item, keepRoot, cb)
          return // early return!
        } else {
          throw new Error('invalid input type')
        }
        file.path = item.path
        cb(null, file)
      }
    }), function (err, files) {
      if (err) return cb(err)
      files = flatten(files)
      cb(null, files, isSingleFileTorrent)
    })
  }
}

function getFiles (path, keepRoot, cb) {
  traversePath(path, getFileInfo, function (err, files) {
    if (err) return cb(err)

    if (Array.isArray(files)) files = flatten(files)
    else files = [ files ]

    path = corePath.normalize(path)
    if (keepRoot) {
      path = path.slice(0, path.lastIndexOf(corePath.sep) + 1)
    }
    if (path[path.length - 1] !== corePath.sep) path += corePath.sep

    files.forEach(function (file) {
      file.getStream = getFilePathStream(file.path)
      file.path = file.path.replace(path, '').split(corePath.sep)
    })
    cb(null, files)
  })
}

function getFileInfo (path, cb) {
  cb = once(cb)
  fs.stat(path, function (err, stat) {
    if (err) return cb(err)
    var info = {
      length: stat.size,
      path: path
    }
    cb(null, info)
  })
}

function traversePath (path, fn, cb) {
  fs.readdir(path, function (err, entries) {
    if (err && err.code === 'ENOTDIR') {
      // this is a file
      fn(path, cb)
    } else if (err) {
      // real error
      cb(err)
    } else {
      // this is a folder
      parallel(entries.filter(notHidden).filter(junk.not).map(function (entry) {
        return function (cb) {
          traversePath(corePath.join(path, entry), fn, cb)
        }
      }), cb)
    }
  })
}

function notHidden (file) {
  return file[0] !== '.'
}

function getPieceList (files, pieceLength, cb) {
  cb = once(cb)
  var pieces = []
  var length = 0

  var streams = files.map(function (file) {
    return file.getStream
  })

  var remainingHashes = 0
  var pieceNum = 0
  var ended = false

  var multistream = new MultiStream(streams)
  var blockstream = new BlockStream(pieceLength, { zeroPadding: false })

  multistream.on('error', onError)

  multistream
    .pipe(blockstream)
    .on('data', onData)
    .on('end', onEnd)
    .on('error', onError)

  function onData (chunk) {
    length += chunk.length

    var i = pieceNum
    sha1(chunk, function (hash) {
      pieces[i] = hash
      remainingHashes -= 1
      maybeDone()
    })
    remainingHashes += 1
    pieceNum += 1
  }

  function onEnd () {
    ended = true
    maybeDone()
  }

  function onError (err) {
    cleanup()
    cb(err)
  }

  function cleanup () {
    multistream.removeListener('error', onError)
    blockstream.removeListener('data', onData)
    blockstream.removeListener('end', onEnd)
    blockstream.removeListener('error', onError)
  }

  function maybeDone () {
    if (ended && remainingHashes === 0) {
      cleanup()
      cb(null, new Buffer(pieces.join(''), 'hex'), length)
    }
  }
}

function onFiles (files, opts, cb) {
  var announceList = opts.announceList

  if (!announceList) {
    if (typeof opts.announce === 'string') announceList = [ [ opts.announce ] ]
    else if (Array.isArray(opts.announce)) {
      announceList = opts.announce.map(function (u) { return [ u ] })
    }
  }

  if (!announceList) announceList = []

  if (global.WEBTORRENT_ANNOUNCE) {
    if (typeof global.WEBTORRENT_ANNOUNCE === 'string') {
      announceList.push([ [ global.WEBTORRENT_ANNOUNCE ] ])
    } else if (Array.isArray(global.WEBTORRENT_ANNOUNCE)) {
      announceList = announceList.concat(global.WEBTORRENT_ANNOUNCE.map(function (u) {
        return [ u ]
      }))
    }
  }

  // When no trackers specified, use some reasonable defaults
  if (announceList.length === 0) {
    announceList = announceList.concat(module.exports.announceList)
  }

  if (typeof opts.urlList === 'string') opts.urlList = [ opts.urlList ]

  var torrent = {
    info: {
      name: opts.name
    },
    announce: announceList[0][0],
    'announce-list': announceList,
    'creation date': Number(opts.creationDate) || Date.now(),
    encoding: 'UTF-8'
  }

  if (opts.comment !== undefined) torrent.comment = opts.comment

  if (opts.createdBy !== undefined) torrent['created by'] = opts.createdBy

  if (opts.private !== undefined) torrent.info.private = Number(opts.private)

  // "ssl-cert" key is for SSL torrents, see:
  //   - http://blog.libtorrent.org/2012/01/bittorrent-over-ssl/
  //   - http://www.libtorrent.org/manual-ref.html#ssl-torrents
  //   - http://www.libtorrent.org/reference-Create_Torrents.html
  if (opts.sslCert !== undefined) torrent.info['ssl-cert'] = opts.sslCert

  if (opts.urlList !== undefined) torrent['url-list'] = opts.urlList

  var pieceLength = opts.pieceLength || calcPieceLength(files.reduce(sumLength, 0))
  torrent.info['piece length'] = pieceLength

  getPieceList(files, pieceLength, function (err, pieces, torrentLength) {
    if (err) return cb(err)
    torrent.info.pieces = pieces

    files.forEach(function (file) {
      delete file.getStream
    })

    if (opts.singleFileTorrent) {
      torrent.info.length = torrentLength
    } else {
      torrent.info.files = files
    }

    cb(null, bencode.encode(torrent))
  })
}

/**
 * Accumulator to sum file lengths
 * @param  {number} sum
 * @param  {Object} file
 * @return {number}
 */
function sumLength (sum, file) {
  return sum + file.length
}

/**
 * Check if `obj` is a W3C `Blob` object (which `File` inherits from)
 * @param  {*} obj
 * @return {boolean}
 */
function isBlob (obj) {
  return typeof Blob !== 'undefined' && obj instanceof Blob
}

/**
 * Check if `obj` is a W3C `FileList` object
 * @param  {*} obj
 * @return {boolean}
 */
function isFileList (obj) {
  return typeof FileList === 'function' && obj instanceof FileList
}

/**
 * Check if `obj` is a node Readable stream
 * @param  {*} obj
 * @return {boolean}
 */
function isReadable (obj) {
  return typeof obj === 'object' && typeof obj.pipe === 'function'
}

/**
 * Convert a `File` to a lazy readable stream.
 * @param  {File|Blob} file
 * @return {function}
 */
function getBlobStream (file) {
  return function () {
    return new FileReadStream(file)
  }
}

/**
 * Convert a `Buffer` to a lazy readable stream.
 * @param  {Buffer} buffer
 * @return {function}
 */
function getBufferStream (buffer) {
  return function () {
    var s = new stream.PassThrough()
    s.end(buffer)
    return s
  }
}

/**
 * Convert a file path to a lazy readable stream.
 * @param  {string} path
 * @return {function}
 */
function getFilePathStream (path) {
  return function () {
    return fs.createReadStream(path)
  }
}

/**
 * Convert a readable stream to a lazy readable stream. Adds instrumentation to track
 * the number of bytes in the stream and set `file.length`.
 *
 * @param  {Stream} stream
 * @param  {Object} file
 * @return {function}
 */
function getStreamStream (readable, file) {
  return function () {
    var counter = new stream.Transform()
    counter._transform = function (buf, enc, done) {
      file.length += buf.length
      this.push(buf)
      done()
    }
    readable.pipe(counter)
    return counter
  }
}
<commit_msg>style<commit_after>module.exports = createTorrent
module.exports.parseInput = parseInput

module.exports.announceList = [
  [ 'udp://tracker.openbittorrent.com:80' ],
  [ 'udp://tracker.internetwarriors.net:1337' ],
  [ 'udp://tracker.leechers-paradise.org:6969' ],
  [ 'udp://tracker.coppersurfer.tk:6969' ],
  [ 'udp://exodus.desync.com:6969' ],
  [ 'wss://tracker.webtorrent.io' ] // For WebRTC peers (see: WebTorrent.io)
]

var bencode = require('bencode')
var BlockStream = require('block-stream2')
var calcPieceLength = require('piece-length')
var corePath = require('path')
var dezalgo = require('dezalgo')
var FileReadStream = require('filestream/read')
var flatten = require('flatten')
var fs = require('fs')
var isFile = require('is-file')
var junk = require('junk')
var MultiStream = require('multistream')
var once = require('once')
var parallel = require('run-parallel')
var sha1 = require('simple-sha1')
var stream = require('stream')

/**
 * Create a torrent.
 * @param  {string|File|FileList|Buffer|Stream|Array.<string|File|Buffer|Stream>} input
 * @param  {Object} opts
 * @param  {string=} opts.name
 * @param  {Date=} opts.creationDate
 * @param  {string=} opts.comment
 * @param  {string=} opts.createdBy
 * @param  {boolean|number=} opts.private
 * @param  {number=} opts.pieceLength
 * @param  {Array.<Array.<string>>=} opts.announceList
 * @param  {Array.<string>=} opts.urlList
 * @param  {function} cb
 * @return {Buffer} buffer of .torrent file data
 */
function createTorrent (input, opts, cb) {
  if (typeof opts === 'function') {
    cb = opts
    opts = {}
  }
  if (!opts) opts = {}
  parseInput(input, opts, function (err, files, singleFileTorrent) {
    if (err) return cb(err)
    opts.singleFileTorrent = singleFileTorrent
    onFiles(files, opts, cb)
  })
}

function parseInput (input, opts, cb) {
  if (typeof opts === 'function') {
    cb = opts
    opts = {}
  }
  if (!opts) opts = {}
  cb = dezalgo(cb)

  if (Array.isArray(input) && input.length === 0) throw new Error('invalid input type')

  if (isFileList(input)) input = Array.prototype.slice.call(input)
  if (!Array.isArray(input)) input = [ input ]

  // If there's just one file, allow the name to be set by `opts.name`
  if (input.length === 1 && typeof input[0] !== 'string' && !input[0].name) input[0].name = opts.name

  var commonPrefix = null
  input.forEach(function (item, i) {
    if (typeof item === 'string') return

    var path = item.fullPath || item.name
    if (!path) throw new Error('missing required `fullPath` or `name` property on input')

    item.path = path.split('/')

    if (!item.path[0]) item.path.shift() // Remove initial slash

    if (item.path.length < 2) { // No real prefix
      commonPrefix = null
    } else if (i === 0) { // The first file has a prefix
      commonPrefix = item.path[0]
    } else if (item.path[0] !== commonPrefix) { // The prefix doesn't match
      commonPrefix = null
    }
  })

  // remove junk files
  input = input.filter(function (item) {
    if (typeof item === 'string') return true
    var filename = item.path[item.path.length - 1]
    return notHidden(filename) && junk.not(filename)
  })

  if (commonPrefix) {
    input.forEach(function (item) {
      if (typeof item === 'string') return
      item.path.shift()
    })
  }

  if (!opts.name && commonPrefix) opts.name = commonPrefix
  if (!opts.name && input[0] && input[0].name) opts.name = input[0].name
  if (!opts.name && typeof input[0] === 'string') opts.name = corePath.basename(input[0])

  if (opts.name === undefined) {
    throw new Error('missing option \'name\' and unable to infer it from input[0].name')
  }

  var numPaths = input.reduce(function (sum, item) {
    return sum + Number(typeof item === 'string')
  }, 0)

  var isSingleFileTorrent = (input.length === 1)

  if (input.length === 1 && typeof input[0] === 'string') {
    if (typeof fs.stat !== 'function') {
      throw new Error('filesystem paths do not work in the browser')
    }
    // If there's a single path, verify it's a file before deciding this is a single
    // file torrent
    isFile(input[0], function (err, pathIsFile) {
      if (err) return cb(err)
      isSingleFileTorrent = pathIsFile
      processInput()
    })
  } else {
    processInput()
  }

  function processInput () {
    parallel(input.map(function (item) {
      return function (cb) {
        var file = {}

        if (isBlob(item)) {
          file.getStream = getBlobStream(item)
          file.length = item.size
        } else if (Buffer.isBuffer(item)) {
          file.getStream = getBufferStream(item)
          file.length = item.length
        } else if (isReadable(item)) {
          if (!opts.pieceLength) {
            throw new Error('must specify `pieceLength` option if input is Stream')
          }
          file.getStream = getStreamStream(item, file)
          file.length = 0
        } else if (typeof item === 'string') {
          if (typeof fs.stat !== 'function') {
            throw new Error('filesystem paths do not work in the browser')
          }
          var keepRoot = numPaths > 1 || isSingleFileTorrent
          getFiles(item, keepRoot, cb)
          return // early return!
        } else {
          throw new Error('invalid input type')
        }
        file.path = item.path
        cb(null, file)
      }
    }), function (err, files) {
      if (err) return cb(err)
      files = flatten(files)
      cb(null, files, isSingleFileTorrent)
    })
  }
}

function getFiles (path, keepRoot, cb) {
  traversePath(path, getFileInfo, function (err, files) {
    if (err) return cb(err)

    if (Array.isArray(files)) files = flatten(files)
    else files = [ files ]

    path = corePath.normalize(path)
    if (keepRoot) {
      path = path.slice(0, path.lastIndexOf(corePath.sep) + 1)
    }
    if (path[path.length - 1] !== corePath.sep) path += corePath.sep

    files.forEach(function (file) {
      file.getStream = getFilePathStream(file.path)
      file.path = file.path.replace(path, '').split(corePath.sep)
    })
    cb(null, files)
  })
}

function getFileInfo (path, cb) {
  cb = once(cb)
  fs.stat(path, function (err, stat) {
    if (err) return cb(err)
    var info = {
      length: stat.size,
      path: path
    }
    cb(null, info)
  })
}

function traversePath (path, fn, cb) {
  fs.readdir(path, function (err, entries) {
    if (err && err.code === 'ENOTDIR') {
      // this is a file
      fn(path, cb)
    } else if (err) {
      // real error
      cb(err)
    } else {
      // this is a folder
      parallel(entries.filter(notHidden).filter(junk.not).map(function (entry) {
        return function (cb) {
          traversePath(corePath.join(path, entry), fn, cb)
        }
      }), cb)
    }
  })
}

function notHidden (file) {
  return file[0] !== '.'
}

function getPieceList (files, pieceLength, cb) {
  cb = once(cb)
  var pieces = []
  var length = 0

  var streams = files.map(function (file) {
    return file.getStream
  })

  var remainingHashes = 0
  var pieceNum = 0
  var ended = false

  var multistream = new MultiStream(streams)
  var blockstream = new BlockStream(pieceLength, { zeroPadding: false })

  multistream.on('error', onError)

  multistream
    .pipe(blockstream)
    .on('data', onData)
    .on('end', onEnd)
    .on('error', onError)

  function onData (chunk) {
    length += chunk.length

    var i = pieceNum
    sha1(chunk, function (hash) {
      pieces[i] = hash
      remainingHashes -= 1
      maybeDone()
    })
    remainingHashes += 1
    pieceNum += 1
  }

  function onEnd () {
    ended = true
    maybeDone()
  }

  function onError (err) {
    cleanup()
    cb(err)
  }

  function cleanup () {
    multistream.removeListener('error', onError)
    blockstream.removeListener('data', onData)
    blockstream.removeListener('end', onEnd)
    blockstream.removeListener('error', onError)
  }

  function maybeDone () {
    if (ended && remainingHashes === 0) {
      cleanup()
      cb(null, new Buffer(pieces.join(''), 'hex'), length)
    }
  }
}

function onFiles (files, opts, cb) {
  var announceList = opts.announceList

  if (!announceList) {
    if (typeof opts.announce === 'string') announceList = [ [ opts.announce ] ]
    else if (Array.isArray(opts.announce)) {
      announceList = opts.announce.map(function (u) { return [ u ] })
    }
  }

  if (!announceList) announceList = []

  if (global.WEBTORRENT_ANNOUNCE) {
    if (typeof global.WEBTORRENT_ANNOUNCE === 'string') {
      announceList.push([ [ global.WEBTORRENT_ANNOUNCE ] ])
    } else if (Array.isArray(global.WEBTORRENT_ANNOUNCE)) {
      announceList = announceList.concat(global.WEBTORRENT_ANNOUNCE.map(function (u) {
        return [ u ]
      }))
    }
  }

  // When no trackers specified, use some reasonable defaults
  if (announceList.length === 0) {
    announceList = announceList.concat(module.exports.announceList)
  }

  if (typeof opts.urlList === 'string') opts.urlList = [ opts.urlList ]

  var torrent = {
    info: {
      name: opts.name
    },
    announce: announceList[0][0],
    'announce-list': announceList,
    'creation date': Number(opts.creationDate) || Date.now(),
    encoding: 'UTF-8'
  }

  if (opts.comment !== undefined) torrent.comment = opts.comment

  if (opts.createdBy !== undefined) torrent['created by'] = opts.createdBy

  if (opts.private !== undefined) torrent.info.private = Number(opts.private)

  // "ssl-cert" key is for SSL torrents, see:
  //   - http://blog.libtorrent.org/2012/01/bittorrent-over-ssl/
  //   - http://www.libtorrent.org/manual-ref.html#ssl-torrents
  //   - http://www.libtorrent.org/reference-Create_Torrents.html
  if (opts.sslCert !== undefined) torrent.info['ssl-cert'] = opts.sslCert

  if (opts.urlList !== undefined) torrent['url-list'] = opts.urlList

  var pieceLength = opts.pieceLength || calcPieceLength(files.reduce(sumLength, 0))
  torrent.info['piece length'] = pieceLength

  getPieceList(files, pieceLength, function (err, pieces, torrentLength) {
    if (err) return cb(err)
    torrent.info.pieces = pieces

    files.forEach(function (file) {
      delete file.getStream
    })

    if (opts.singleFileTorrent) {
      torrent.info.length = torrentLength
    } else {
      torrent.info.files = files
    }

    cb(null, bencode.encode(torrent))
  })
}

/**
 * Accumulator to sum file lengths
 * @param  {number} sum
 * @param  {Object} file
 * @return {number}
 */
function sumLength (sum, file) {
  return sum + file.length
}

/**
 * Check if `obj` is a W3C `Blob` object (which `File` inherits from)
 * @param  {*} obj
 * @return {boolean}
 */
function isBlob (obj) {
  return typeof Blob !== 'undefined' && obj instanceof Blob
}

/**
 * Check if `obj` is a W3C `FileList` object
 * @param  {*} obj
 * @return {boolean}
 */
function isFileList (obj) {
  return typeof FileList === 'function' && obj instanceof FileList
}

/**
 * Check if `obj` is a node Readable stream
 * @param  {*} obj
 * @return {boolean}
 */
function isReadable (obj) {
  return typeof obj === 'object' && typeof obj.pipe === 'function'
}

/**
 * Convert a `File` to a lazy readable stream.
 * @param  {File|Blob} file
 * @return {function}
 */
function getBlobStream (file) {
  return function () {
    return new FileReadStream(file)
  }
}

/**
 * Convert a `Buffer` to a lazy readable stream.
 * @param  {Buffer} buffer
 * @return {function}
 */
function getBufferStream (buffer) {
  return function () {
    var s = new stream.PassThrough()
    s.end(buffer)
    return s
  }
}

/**
 * Convert a file path to a lazy readable stream.
 * @param  {string} path
 * @return {function}
 */
function getFilePathStream (path) {
  return function () {
    return fs.createReadStream(path)
  }
}

/**
 * Convert a readable stream to a lazy readable stream. Adds instrumentation to track
 * the number of bytes in the stream and set `file.length`.
 *
 * @param  {Stream} stream
 * @param  {Object} file
 * @return {function}
 */
function getStreamStream (readable, file) {
  return function () {
    var counter = new stream.Transform()
    counter._transform = function (buf, enc, done) {
      file.length += buf.length
      this.push(buf)
      done()
    }
    readable.pipe(counter)
    return counter
  }
}
<|endoftext|>


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

	var utils = require('./utils.js');
	var commands_services = require('../main/register-commands.js').services;

	var NOTIFICATION_TYPES = Object.freeze(['info', 'success', 'warning', 'error']);
	var NOTIFICATION_TYPES_STR = listArrayElementsAsQuoted(NOTIFICATION_TYPES);

	class SpecialCommands {

		ClearScreen(param) {
			if (getCmdArg(param.command).trim()) {
				return true;
			}
			var outputpre = param.elements.outputpre;
			outputpre.hidden = true;
			utils.clearChildren(outputpre);
		}

		ExitProcess(param) {
			if (getCmdArg(param.command).trim()) {
				return true;
			}
			param.closePaneItem();
		}

		Notification(param) {
			var arg = getCmdArg(param.command).trim();
			var type = getCmdKey(arg).trim();
			if (NOTIFICATION_TYPES.indexOf(type) !== -1) {
				atom.notifications.add(type, getCmdArg(arg).trim());
			} else {
				handleError(param)(`Syntax:\n\t${getCmdKey(param.command)} <type> <message>\n - <type> must be one of ${NOTIFICATION_TYPES_STR}`);
			}
		}

		MessageBox(param) {
			alert(getCmdArg(param.command).trim(), 'Message');
		}

		WriteStdIn(param) {
			var data = getCmdArg(param.command);
			data && param.writeStdIn(param.process.stdin, new Buffer(`${data}\n`), 'utf8', param.elements.outputpre);
		}

		WriteStdOut(param) {
			param.handleData(param.elements, getCmdArg(param.command).trim());
		}

		WriteStdErr(param) {
			param.handleError(param.elements, getCmdArg(param.command).trim());
		}

		SpawnNewProcess(param) {
			var path = getCmdArg(param.command);
			if (!path.trim()) {
				handleError(`Syntax:\n\t${getCmdKey(param.command)} <command>\n - <command> must not be empty.`);
				return;
			}
			commands_services.createExecutor(Object.assign({}, param.fromConfig, {
				path: path,
				type: 'spawn'
			}))(new commands_services.ExecutorParam(null, handleError(param)));
		}

		ExecuteNewProcess(param) {
			var path = getCmdArg(param.command);
			if (!path.trim()) {
				handleError(`Syntax:\n\t${getCmdKey(param.command)} <command>\n - <command> must not be empty.`);
			}
			require('child_process').exec(path, {
				encoding: 'utf8',
				cwd: param.fromScript.input.options.cwd
			}, (error, stdout, stderr) => {
				param.handleData(param.elements, `STDOUT: ${stdout}\n`);
				param.handleData(param.elements, `STDERR: ${stderr}\n`);
				error && handleError(param)(`${error}\n`);
			})
		}

		ListEnvironmentVariables(param) {
			if (getCmdArg(param.command)) {
				return true;
			}
			var json = new Buffer(`${JSON.stringify(process.env, '', '\t')}\n`);
			param.handleData(param.elements, json);
		}

		beep() {
			atom.beep();
		}

	}

	((proto) => {
		makeAliases('ClearScreen', ['clear', 'cls', 'clear-screen', 'clrscr', 'clear-console']);
		makeAliases('ExitProcess', ['exit', 'terminate', 'end', 'escape', 'close', 'end-process', 'exit-process']);
		makeAliases('Notification', ['notice', 'popup', 'open-notification', 'show-notification']);
		makeAliases('MessageBox', ['message', 'msgbox', 'dialog', 'alert', 'show-message', 'message-box']);
		makeAliases('WriteStdIn', ['in', 'input', 'enter', 'tell', 'stdin', 'write-stdin'])
		makeAliases('WriteStdOut', ['out', 'output', 'print', 'text', 'echo', 'log', 'write', 'stdout', 'write-stdout']);
		makeAliases('WriteStdErr', ['err', 'error', 'throw', 'exception', 'stderr', 'write-stderr']);
		makeAliases('SpawnNewProcess', ['spawn', 'start', 'new', 'open', 'run', 'new-process', 'create-process', 'start-process', 'spawn-process', 'spawn-new-process', 'CreateProcess', 'SpawnProcess']);
		makeAliases('ExecuteNewProcess', ['exec', 'system', 'exec-process', 'exec-cmd', 'execute', 'execute-command', 'execute-process', 'Execute', 'ExecuteCommand', 'ExecuteProcess'])
		makeAliases('ListEnvironmentVariables', ['var', 'env', 'environ', 'environment', 'environment-variable', 'list-environment-variable', 'EnvironmentVariable'])
		function makeAliases(fname, aliases) {
			aliases.forEach((alias) => proto[alias] = proto[fname]);
		}
	})(SpecialCommands.prototype);

	module.exports = new SpecialCommands();

	function getCmdKey(command) {
		var sp = command.indexOf('\x20');
		return sp === -1 ? command : command.substr(0, sp);
	}

	function getCmdArg(command) {
		var sp = command.indexOf('\x20');
		return sp === -1 ? '' : command.slice(sp + 1);
	}

	function handleError(param) {
		return (error) =>
			param.handleError(param.elements, String(error));
	}

	function listArrayElementsAsQuoted(array) {
		return array.map((element) => `'${element}'`).join(', ');
	}

})(module);
<commit_msg>improve clear-screen<commit_after>
(function (module) {
	'use strict';

	var utils = require('./utils.js');
	var commands_services = require('../main/register-commands.js').services;

	var NOTIFICATION_TYPES = Object.freeze(['info', 'success', 'warning', 'error']);
	var NOTIFICATION_TYPES_STR = listArrayElementsAsQuoted(NOTIFICATION_TYPES);

	class SpecialCommands {

		ClearScreen(param) {
			if (getCmdArg(param.command).trim()) {
				return true;
			}
			var outputpre = param.elements.outputpre;
			outputpre.hidden = true;
			utils.clearChildren(outputpre);
			param.writeString.target = null;
		}

		ExitProcess(param) {
			if (getCmdArg(param.command).trim()) {
				return true;
			}
			param.closePaneItem();
		}

		Notification(param) {
			var arg = getCmdArg(param.command).trim();
			var type = getCmdKey(arg).trim();
			if (NOTIFICATION_TYPES.indexOf(type) !== -1) {
				atom.notifications.add(type, getCmdArg(arg).trim());
			} else {
				handleError(param)(`Syntax:\n\t${getCmdKey(param.command)} <type> <message>\n - <type> must be one of ${NOTIFICATION_TYPES_STR}`);
			}
		}

		MessageBox(param) {
			alert(getCmdArg(param.command).trim(), 'Message');
		}

		WriteStdIn(param) {
			var data = getCmdArg(param.command);
			data && param.writeStdIn(param.process.stdin, new Buffer(`${data}\n`), 'utf8', param.elements.outputpre);
		}

		WriteStdOut(param) {
			param.handleData(param.elements, getCmdArg(param.command).trim());
		}

		WriteStdErr(param) {
			param.handleError(param.elements, getCmdArg(param.command).trim());
		}

		SpawnNewProcess(param) {
			var path = getCmdArg(param.command);
			if (!path.trim()) {
				handleError(`Syntax:\n\t${getCmdKey(param.command)} <command>\n - <command> must not be empty.`);
				return;
			}
			commands_services.createExecutor(Object.assign({}, param.fromConfig, {
				path: path,
				type: 'spawn'
			}))(new commands_services.ExecutorParam(null, handleError(param)));
		}

		ExecuteNewProcess(param) {
			var path = getCmdArg(param.command);
			if (!path.trim()) {
				handleError(`Syntax:\n\t${getCmdKey(param.command)} <command>\n - <command> must not be empty.`);
			}
			require('child_process').exec(path, {
				encoding: 'utf8',
				cwd: param.fromScript.input.options.cwd
			}, (error, stdout, stderr) => {
				param.handleData(param.elements, `STDOUT: ${stdout}\n`);
				param.handleData(param.elements, `STDERR: ${stderr}\n`);
				error && handleError(param)(`${error}\n`);
			})
		}

		ListEnvironmentVariables(param) {
			if (getCmdArg(param.command)) {
				return true;
			}
			var json = new Buffer(`${JSON.stringify(process.env, '', '\t')}\n`);
			param.handleData(param.elements, json);
		}

		beep() {
			atom.beep();
		}

	}

	((proto) => {
		makeAliases('ClearScreen', ['clear', 'cls', 'clear-screen', 'clrscr', 'clear-console']);
		makeAliases('ExitProcess', ['exit', 'terminate', 'end', 'escape', 'close', 'end-process', 'exit-process']);
		makeAliases('Notification', ['notice', 'popup', 'open-notification', 'show-notification']);
		makeAliases('MessageBox', ['message', 'msgbox', 'dialog', 'alert', 'show-message', 'message-box']);
		makeAliases('WriteStdIn', ['in', 'input', 'enter', 'tell', 'stdin', 'write-stdin'])
		makeAliases('WriteStdOut', ['out', 'output', 'print', 'text', 'echo', 'log', 'write', 'stdout', 'write-stdout']);
		makeAliases('WriteStdErr', ['err', 'error', 'throw', 'exception', 'stderr', 'write-stderr']);
		makeAliases('SpawnNewProcess', ['spawn', 'start', 'new', 'open', 'run', 'new-process', 'create-process', 'start-process', 'spawn-process', 'spawn-new-process', 'CreateProcess', 'SpawnProcess']);
		makeAliases('ExecuteNewProcess', ['exec', 'system', 'exec-process', 'exec-cmd', 'execute', 'execute-command', 'execute-process', 'Execute', 'ExecuteCommand', 'ExecuteProcess'])
		makeAliases('ListEnvironmentVariables', ['var', 'env', 'environ', 'environment', 'environment-variable', 'list-environment-variable', 'EnvironmentVariable'])
		function makeAliases(fname, aliases) {
			aliases.forEach((alias) => proto[alias] = proto[fname]);
		}
	})(SpecialCommands.prototype);

	module.exports = new SpecialCommands();

	function getCmdKey(command) {
		var sp = command.indexOf('\x20');
		return sp === -1 ? command : command.substr(0, sp);
	}

	function getCmdArg(command) {
		var sp = command.indexOf('\x20');
		return sp === -1 ? '' : command.slice(sp + 1);
	}

	function handleError(param) {
		return (error) =>
			param.handleError(param.elements, String(error));
	}

	function listArrayElementsAsQuoted(array) {
		return array.map((element) => `'${element}'`).join(', ');
	}

})(module);
<|endoftext|>


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

var Stream = require('stream')
var bytes = require('bytes')
var zlib = require('zlib')

/**
 * Encoding methods supported.
 */

var encodingMethods = {
  gzip: zlib.createGzip,
  deflate: zlib.createDeflate
}

/**
 * Compress middleware.
 *
 * @param {Object} [options]
 * @return {Function}
 * @api public
 */

module.exports = function (options) {
  options = options || {}

  var filter = options.filter
    || /json|text|javascript|dart/i

  var threshold = !options.threshold ? 1024
    : typeof options.threshold === 'number' ? options.threshold
    : typeof options.threshold === 'string' ? bytes(options.threshold)
    : 1024

  return function compress(next) {
    return function *() {
      yield next

      this.vary('Accept-Encoding')

      var body = this.body

      if (this.compress === false
        || this.method === 'HEAD'
        || this.status === 204
        || this.status === 304
        // Assumes you either always set a body or always don't
        || body == null
      ) return

      var length = this.responseLength;

      // set Content-Type for filtering
      if (Buffer.isBuffer(body)) {
        if (!this.responseHeader['content-type'])
          this.set('Content-Type', 'application/octet-stream')
      } else if (typeof body === 'string') {
        if (!this.responseHeader['content-type'])
          this.set('Content-Type', 'text/plain; charset=utf-8')
      } else if (body instanceof Stream) {
        if (!this.responseHeader['content-type'])
          this.set('Content-Type', 'application/octet-stream')
      } else {
        // JSON
        body = JSON.stringify(body, null, this.app.jsonSpaces)
        this.set('Content-Type', 'application/json')
      }

      // forced compression or implied
      var contentType = this.responseHeader['content-type']
      if (!(this.compress === true || filter.test(contentType)))
        return

      // identity
      var encoding = this.acceptedEncodings[0]
      if (encoding === 'identity') return

      // threshold
      if (threshold && length < threshold) return

      this.set('Content-Encoding', encoding)
      this.res.removeHeader('Content-Length')

      var stream = encodingMethods[encoding](options)

      if (body instanceof Stream) {
        body.on('error', this.onerror)
        body.pipe(stream)
      } else {
        stream.end(body)
      }

      this.body = stream
    }
  }
}
<commit_msg>this.onerror.bind(this) when not attaching to `this`<commit_after>
/**
 * Module dependencies.
 */

var Stream = require('stream')
var bytes = require('bytes')
var zlib = require('zlib')

/**
 * Encoding methods supported.
 */

var encodingMethods = {
  gzip: zlib.createGzip,
  deflate: zlib.createDeflate
}

/**
 * Compress middleware.
 *
 * @param {Object} [options]
 * @return {Function}
 * @api public
 */

module.exports = function (options) {
  options = options || {}

  var filter = options.filter
    || /json|text|javascript|dart/i

  var threshold = !options.threshold ? 1024
    : typeof options.threshold === 'number' ? options.threshold
    : typeof options.threshold === 'string' ? bytes(options.threshold)
    : 1024

  return function compress(next) {
    return function *() {
      yield next

      this.vary('Accept-Encoding')

      var body = this.body

      if (this.compress === false
        || this.method === 'HEAD'
        || this.status === 204
        || this.status === 304
        // Assumes you either always set a body or always don't
        || body == null
      ) return

      var length = this.responseLength;

      // set Content-Type for filtering
      if (Buffer.isBuffer(body)) {
        if (!this.responseHeader['content-type'])
          this.set('Content-Type', 'application/octet-stream')
      } else if (typeof body === 'string') {
        if (!this.responseHeader['content-type'])
          this.set('Content-Type', 'text/plain; charset=utf-8')
      } else if (body instanceof Stream) {
        if (!this.responseHeader['content-type'])
          this.set('Content-Type', 'application/octet-stream')
      } else {
        // JSON
        body = JSON.stringify(body, null, this.app.jsonSpaces)
        this.set('Content-Type', 'application/json')
      }

      // forced compression or implied
      var contentType = this.responseHeader['content-type']
      if (!(this.compress === true || filter.test(contentType)))
        return

      // identity
      var encoding = this.acceptedEncodings[0]
      if (encoding === 'identity') return

      // threshold
      if (threshold && length < threshold) return

      this.set('Content-Encoding', encoding)
      this.res.removeHeader('Content-Length')

      var stream = encodingMethods[encoding](options)

      if (body instanceof Stream) {
        body.on('error', this.onerror.bind(this))
        body.pipe(stream)
      } else {
        stream.end(body)
      }

      this.body = stream
    }
  }
}
<|endoftext|>


<commit_before>'use strict';

/* jshint unused: false */
let lib = require('./lib'),
    argv = process.argv.slice(2),
    bco = require('bco'),
    os = require('os'),
    fs = require('fs-extra');

global.pose = {};

lib.utils(pose);

if(!fs.existsSync(pose.getPoseHome())) {
   lib.install();
   return;
}

let commands = [
   'save',
   'delete',
   'update',
   'create',
   'list-saves',
   'help'
];

let args = argv;
if(commands.indexOf(args[0]) > -1) {
   lib[args[0]].call(null, args.slice(1));
} else {
   console.log('Unknown Command');
   pose.close();
}
<commit_msg>No longer needed<commit_after><|endoftext|>


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

var express = require("express"),
    app = express(),
    bodyParser = require('body-parser'),
    errorHandler = require('errorhandler'),
    methodOverride = require('method-override'),
    port = parseInt(process.env.PORT, 10) || 15304;

app.get("/", function(req, res) {
    res.redirect("index.html");
});
app.use(methodOverride());
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(express.static(__dirname + '/src'));
app.use(errorHandler({
    dumpExceptions: true,
    showStack: true
}));

app.listen(port);
<commit_msg>Fixed index.js for deploy<commit_after>/*jslint node: true */
'use strict';

var express = require("express"),
    app = express(),
    bodyParser = require('body-parser'),
    errorHandler = require('errorhandler'),
    methodOverride = require('method-override'),
    port = parseInt(process.env.PORT, 10) || 15304;

app.get("/", function(req, res) {
    res.redirect("index.html");
});
app.use(methodOverride());
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(express.static(__dirname + '/public'));
app.use(errorHandler({
    dumpExceptions: true,
    showStack: true
}));

app.listen(port);
<|endoftext|>


<commit_before>'use strict'

module.exports = (pluginContext) => {
	//to access context of app
	const app = pluginContext.app;
	//to open File/Folder
	const shell = pluginContext.shell;
	//to access filesystem
	const fs = require('fs');
	//to format filepath
	const path = require('path');

	const commandHeader = "/fp";

	function initAvailableDrives(){
		var innnerAvailableDrives = [];
		const ASCIICodeOfA = 65 , ASCIICodeOfZ = 90;
		for (var ASCIICode = ASCIICodeOfA; ASCIICode <= ASCIICodeOfZ ; ASCIICode++){
			var checkingDrive = String.fromCharCode(ASCIICode) + ":";
			innnerAvailableDrives.push(
				{
					driveName:checkingDrive,
					isAvailable:false,
					failureOfAccess:0
				}
			);
		}
		return innnerAvailableDrives;
	}
	var availableDrives = initAvailableDrives();
	//init availableDrives
	const failureThreshold = 10;

	//check if the file or folder exists
	//return 1:File 2:Folder -1,0:Invalid path
	function checkFileOrFolder(path) {
		try {
			var stat = fs.statSync(path);
			if(stat.isFile() == true){
				return 1;//file
			}else if(stat.isDirectory() == true){
				return 2;//folder
			}else{//unreachable
				return 0;//invalid
			}
		} catch(err) {
			if(err.code === 'ENOENT'){
				return -1;//invalid
			}
		}
	}

	//remove all specified characters from string
	//return string (removed characters).
	//arguments are not modified.
	function removeCharacters(targetString,removingCharacterArray){
		var copyOfTargetString = targetString;
		for(var index = 0 ; index < removingCharacterArray.length ; index++){
			var removingCharacter = removingCharacterArray[index];
			switch(removingCharacter){
				case "*":
				case "?":
				case "|":
					//add '\' to characters which need '\'
					removingCharacter = "\\" + removingCharacter;
				default:
					//do nothing.
					break;
			}
			copyOfTargetString =
				copyOfTargetString.replace(
					new RegExp(removingCharacter,"g")
					,""
				);
		}
		return copyOfTargetString;
	}

	//check the position of space(' ' or '　').
	//return array of positions.
	function checkPositionOfSpaces(targetString){
		var positionOfSpaces = [];
		for(var index = 0 , len = targetString.length ; index < len; index++){
			if((targetString[index] == ' ') || (targetString[index] == '　' )){
				positionOfSpaces.push(index);
			}
		}
		return positionOfSpaces;
	}

	function searchAvailablePathConsideringUnnecessarySpace(
		availableFullPathes, availableCurrentPath , splittedRemainingPath
	){
		searchAvailablePathConsideringUnnecessarySpaceWithDistance(
			availableFullPathes, availableCurrentPath , splittedRemainingPath , 0 , []
		);
	}

	function searchAvailablePathConsideringUnnecessarySpaceWithDistance(
		availableFullPathes, availableCurrentPath , splittedRemainingPath ,
		 currentDistance , alreadyCheckedPathes
	){
		if(splittedRemainingPath.length > 0){
			var targetPath = splittedRemainingPath[0];
			var checkingPath = "";
			if(availableCurrentPath == ""){
				checkingPath = targetPath;
			}else{
				checkingPath = availableCurrentPath + "\\" + targetPath;
			}
			//check the path if it is checked at first
			var alreadyCheckedFlag = false;
			for(var index = 0 , len = alreadyCheckedPathes.length ; index < len ; index++){
				if(alreadyCheckedPathes[index] == checkingPath){
					alreadyCheckedFlag = true;
				}
			}
			//check only when the path is checked at first
			if(alreadyCheckedFlag == false){
				alreadyCheckedPathes.push(checkingPath);
				switch(checkFileOrFolder(checkingPath)){
					case -1:
					case 0:
						//do nothing
						break;
					case 1://Available File
					case 2://Available Folder
						var shiftedSplittedRemainingPath = splittedRemainingPath.slice();
						shiftedSplittedRemainingPath.shift();
						var nextAvailableCurrentPath = checkingPath;
						var nextDistance = currentDistance;
						searchAvailablePathConsideringUnnecessarySpaceWithDistance(
							availableFullPathes, nextAvailableCurrentPath,
							shiftedSplittedRemainingPath, nextDistance , alreadyCheckedPathes
						);
						break;
					default:
						//do nothing
						break;
				}
			}else{
				//do nothing
			}

			//count the number of ' ' and '　'.
			var positionOfSpaces = checkPositionOfSpaces(targetPath);
			var numberOfSpaces = positionOfSpaces.length;
			if(numberOfSpaces > 0){
				//remove one of spaces and check the path.
				for(var index = 0; index < numberOfSpaces; index++){
					var nextSplittedRemainingPath = splittedRemainingPath;
					var firstHalfOfTargetPathRemovedSpace = targetPath;
					var latterHalfOfTargetPathRemovedSpace = targetPath;
					var targetPathRemovedSpace =
						firstHalfOfTargetPathRemovedSpace.slice(0,positionOfSpaces[index]) +
						latterHalfOfTargetPathRemovedSpace.slice(positionOfSpaces[index]+1);
					nextSplittedRemainingPath[0] = targetPathRemovedSpace;
					var nextDistance = currentDistance + 1;
					var nextAvailableCurrentPath = availableCurrentPath;

					//check the path if it is checked at first
					var alreadyCheckedFlag = false;
					for(var index = 0 , len = alreadyCheckedPathes.length ; index < len ; index++){
						if(alreadyCheckedPathes[index] == checkingPath){
							alreadyCheckedFlag = true;
						}
					}
					//check only when the path is checked at first
					var alreadyCheckedFlag = false;
					for(var index = 0 , len = alreadyCheckedPathes.length ; index < len ; index++){
						if(alreadyCheckedPathes[index] == nextAvailableCurrentPath + "\\" + targetPathRemovedSpace){
							alreadyCheckedFlag = true;
						}
					}
					if(alreadyCheckedFlag == false){
						searchAvailablePathConsideringUnnecessarySpaceWithDistance(
							availableFullPathes, nextAvailableCurrentPath,
							nextSplittedRemainingPath, nextDistance , alreadyCheckedPathes
						);
					}
				}
			}
		}else{
			//check if the availableCurrentPath is already added.
			var alreadyExistFlag = false;
			for(var index = 0, len = availableFullPathes.length; index < len ; index++){
				if(availableFullPathes[index][0] == availableCurrentPath){
					alreadyExistFlag = true;
				}
			}
			if(alreadyExistFlag == false){
				availableFullPathes.push([availableCurrentPath , currentDistance]);
			}
		}
	}

	//format query as below.
	//remove spaces attached on head and bottom.
	//normalize
	function formatQuery(query){
		//remove spaces attached on head and bottom.
		var trimmedQuery = query.trim();

		//remove unavailable characters.
		var queryRemovedUnavailableCharacters =
			removeCharacters(trimmedQuery,['*','/','?',"\"","<",">","|","\t"]);

		//normalize
		var normalizedQuery = path.normalize(queryRemovedUnavailableCharacters);
		if(normalizedQuery == "."){
			normalizedQuery = "";
		}

		//return result
		return normalizedQuery;
	}

	//search available drives.
	function searchAvailableDrivesAsync(){
		//{
		//	driveName:checkingDrive + "\\",
		//	isAvailable:false,
		//	failureOfAccess:0
		//}
		for (var index = 0, len = availableDrives.length ; index < len ; index++){
			let checkingDriveObj = availableDrives[index];
			fs.stat(checkingDriveObj.driveName, function(err,stats){
				if(err){
					if(checkingDriveObj.isAvailable == true){
						checkingDriveObj.failureOfAccess++;
						if(checkingDriveObj.failureOfAccess > failureThreshold){
							checkingDriveObj.isAvailable = false;
							checkingDriveObj.failureOfAccess = 0;
						}
					}
					return;
				}else{
					if(stats.isDirectory() == true){
						if(checkingDriveObj.isAvailable == true){
							checkingDriveObj.failureOfAccess = 0;
						}else{
							checkingDriveObj.isAvailable = true;
						}
					}
				}
			});
		}
	}

	function refreshAvailableDrives(){
		searchAvailableDrivesAsync();
	}

	function startup(){
		//Search Available Drives.
		searchAvailableDrivesAsync();
	}

	function search (query, res) {
		//format query.
		var normalizedQuery = formatQuery(query);

		//check if the path is file server.
		//if the path is file server, remove "\\" attached on head.
		var isFileServer = false;
		if(normalizedQuery.indexOf("\\\\") == 0){
			isFileServer = true;
			normalizedQuery.substring(("\\\\").length);
		}

		//split by separator('\' or '/').
		var splittedQuery = normalizedQuery.split(path.sep);

		//if isFileServer is true, combine 1st and 2nd element.
		if(isFileServer == true){
			if(splittedQuery.length >= 2){
				splittedQuery[1] = "\\\\" + splittedQuery[0] + "\\" + splittedQuery[1];
				splittedQuery.shift();
			}else if (splittedQuery.length == 1){
				splittedQuery[0] = "\\\\" + splittedQuery[0];
			}
		}
		//remove empty element in splittedQuery.
		var splittedQueryRemovedUnnecessaryElement = splittedQuery.filter(function(e){return e !== "";});

		//search available file/folder name. (considering unnecessary space)
		var availableFullPathes = [];
		searchAvailablePathConsideringUnnecessarySpace(availableFullPathes,"",splittedQueryRemovedUnnecessaryElement.slice());

		//sort available path candidates by distance between them and query.
		var sortedAvailableFullPathes = availableFullPathes.slice();
		sortedAvailableFullPathes.sort(
			function(a,b){
				//compare the distance
				return ( (a[1] - b[1]) );
			}
		);

		//add to result (when no available path is found)
		if(sortedAvailableFullPathes.length == 0){
			//do nothing
		}else{//add to result (when no available path is found)
			for(var index = 0 , len = sortedAvailableFullPathes.length ; index < len ; index++){
				//Check state of formatted path (File or Folder or not).
				//and set Description Message according to the state.
				var descriptionMessage = "";
				var availableFullPath = sortedAvailableFullPathes[index][0].slice();
				var distance = sortedAvailableFullPathes[index][1];
				var addToResFlag = false;
				switch(checkFileOrFolder(availableFullPath)){
					case -1://invalid
					case 0://invalid
						//descriptionMessage = "Not File/Folder. Cannot open."
						break;
					case 1://file
						//extract file name
						//(todo) extract BBB from "C:\AAA\BBB\" <- when unnecessary "\" exists.
						var filename = availableFullPath.slice().split("\\").pop();
						descriptionMessage = "Open this File : \"" + filename +
							"\" ( Distance = " + distance + " )";
						addToResFlag = true;
						break;
					case 2://folder
						//extract folder name
						//(todo) extract BBB from "C:\AAA\BBB\" <- when unnecessary "\" exists.
						var foldername = availableFullPath.slice().split("\\").pop();
						descriptionMessage = "Open this Folder : \"" + foldername +
							"\" ( Distance = " + distance + " )";
						addToResFlag = true;
						break;
					default:
						break;
				}
				//add to res.
				if(addToResFlag == true){
					res.add(
						{
							id: availableFullPath,
							payload: 'open',
							title: availableFullPath,
							desc: descriptionMessage
						}
					);
				}
			}
		}

		//search available path to complement
		var foundCandidates = [];
		//check if the current path is empty
		var searchingSplittedQueryBase = splittedQuery.slice();
		var lengthOfsearchingSplittedQueryBase = searchingSplittedQueryBase.length
		var currentDirectory;
		var searchKeyword;
		if(lengthOfsearchingSplittedQueryBase == 0){
			currentDirectory = "";
			searchKeyword = "";
		}else if(lengthOfsearchingSplittedQueryBase == 1){
			currentDirectory = "";
			searchKeyword = searchingSplittedQueryBase[0];
		}else{// length >= 2
			currentDirectory = "";
			for(index = 0 ; index < lengthOfsearchingSplittedQueryBase - 1 ; index++){
				currentDirectory = currentDirectory + searchingSplittedQueryBase[index] + "\\";
			}
			//currentDirectory.pop();
			searchKeyword = searchingSplittedQueryBase[lengthOfsearchingSplittedQueryBase - 1];
		}

		//check the existence of currentDirectory.
		if(currentDirectory == "" || checkFileOrFolder(currentDirectory) == 2){
			//find candidates
			if(currentDirectory == ""){
				for (var index = 0, len = availableDrives.length ; index < len ; index++){
					if(availableDrives[index].isAvailable == true){
						foundCandidates.push(availableDrives[index].driveName);
					}
				}
			}else{// when checkFileOrFolder(currentDirectory) == 2
				//(todo) make async (use fs.readdir)
				foundCandidates = fs.readdirSync(currentDirectory);
			}

			//filter with searchKeyword
			for(var index = 0, len = foundCandidates.length ; index < len ; index++){
				//check if candidates contains searchKeyword on head
				if(foundCandidates[index].indexOf(searchKeyword) == 0){
					//add to res.
					var descriptionMessage = "Set this path : \"" + foundCandidates[index] + "\"";
					//var redirect;
					res.add(
						{
							//id: checkingDrive,
							id: commandHeader + " " + foundCandidates[index],
							payload: 'complement',
							title: ".\\" + "<b>" + foundCandidates[index].substring(0,searchKeyword.length) + "</b>" + foundCandidates[index].substring(searchKeyword.length),
							desc: descriptionMessage,
							redirect:commandHeader + " " + currentDirectory + foundCandidates[index] + "\\"
						}
					);
				}
			}

		}

		//refresh command to the end of list
		res.add(
			{
				id: commandHeader + query,
				payload: 'refresh',
				title: "Refresh",
				desc: "Search Available Drives Again."
			}
		);
	}

	function execute (id, payload) {
		//open file or folder.
		switch (payload){
			case 'open':
				//open file/folder
				shell.openItem(`${id}`);
				break;
			case 'complement':
				//complement path (set id to query)
				app.setQuery(id);
				break;
			case 'refresh':
				//search available drives again.
				refreshAvailableDrives();
				app.setQuery(id);
				break;
			case 'pending':
			default:
				return;
		}
	}

	return { startup, search, execute };
}
<commit_msg>identify the path's status(file/folder/drive)<commit_after>'use strict'

module.exports = (pluginContext) => {
	//to access context of app
	const app = pluginContext.app;
	//to open File/Folder
	const shell = pluginContext.shell;
	//to access filesystem
	const fs = require('fs');
	//to format filepath
	const path = require('path');

	const commandHeader = "/fp";

	function initAvailableDrives(){
		var innnerAvailableDrives = [];
		const ASCIICodeOfA = 65 , ASCIICodeOfZ = 90;
		for (var ASCIICode = ASCIICodeOfA; ASCIICode <= ASCIICodeOfZ ; ASCIICode++){
			var checkingDrive = String.fromCharCode(ASCIICode) + ":";
			innnerAvailableDrives.push(
				{
					driveName:checkingDrive,
					isAvailable:false,
					failureOfAccess:0
				}
			);
		}
		return innnerAvailableDrives;
	}
	var availableDrives = initAvailableDrives();
	//init availableDrives
	const failureThreshold = 10;

	//check if the file or folder exists
	//return 1:File 2:Folder -1,0:Invalid path
	function checkFileOrFolder(path) {
		try {
			var stat = fs.statSync(path);
			if(stat.isFile() == true){
				return 1;//file
			}else if(stat.isDirectory() == true){
				return 2;//folder
			}else{//unreachable
				return 0;//invalid
			}
		} catch(err) {
			if(err.code === 'ENOENT'){
				return -1;//invalid
			}
		}
	}

	//remove all specified characters from string
	//return string (removed characters).
	//arguments are not modified.
	function removeCharacters(targetString,removingCharacterArray){
		var copyOfTargetString = targetString;
		for(var index = 0 ; index < removingCharacterArray.length ; index++){
			var removingCharacter = removingCharacterArray[index];
			switch(removingCharacter){
				case "*":
				case "?":
				case "|":
					//add '\' to characters which need '\'
					removingCharacter = "\\" + removingCharacter;
				default:
					//do nothing.
					break;
			}
			copyOfTargetString =
				copyOfTargetString.replace(
					new RegExp(removingCharacter,"g")
					,""
				);
		}
		return copyOfTargetString;
	}

	//check the position of space(' ' or '　').
	//return array of positions.
	function checkPositionOfSpaces(targetString){
		var positionOfSpaces = [];
		for(var index = 0 , len = targetString.length ; index < len; index++){
			if((targetString[index] == ' ') || (targetString[index] == '　' )){
				positionOfSpaces.push(index);
			}
		}
		return positionOfSpaces;
	}

	function searchAvailablePathConsideringUnnecessarySpace(
		availableFullPathes, availableCurrentPath , splittedRemainingPath
	){
		searchAvailablePathConsideringUnnecessarySpaceWithDistance(
			availableFullPathes, availableCurrentPath , splittedRemainingPath , 0 , []
		);
	}

	function searchAvailablePathConsideringUnnecessarySpaceWithDistance(
		availableFullPathes, availableCurrentPath , splittedRemainingPath ,
		 currentDistance , alreadyCheckedPathes
	){
		if(splittedRemainingPath.length > 0){
			var targetPath = splittedRemainingPath[0];
			var checkingPath = "";
			if(availableCurrentPath == ""){
				checkingPath = targetPath;
			}else{
				checkingPath = availableCurrentPath + "\\" + targetPath;
			}
			//check the path if it is checked at first
			var alreadyCheckedFlag = false;
			for(var index = 0 , len = alreadyCheckedPathes.length ; index < len ; index++){
				if(alreadyCheckedPathes[index] == checkingPath){
					alreadyCheckedFlag = true;
				}
			}
			//check only when the path is checked at first
			if(alreadyCheckedFlag == false){
				alreadyCheckedPathes.push(checkingPath);
				switch(checkFileOrFolder(checkingPath)){
					case -1:
					case 0:
						//do nothing
						break;
					case 1://Available File
					case 2://Available Folder
						var shiftedSplittedRemainingPath = splittedRemainingPath.slice();
						shiftedSplittedRemainingPath.shift();
						var nextAvailableCurrentPath = checkingPath;
						var nextDistance = currentDistance;
						searchAvailablePathConsideringUnnecessarySpaceWithDistance(
							availableFullPathes, nextAvailableCurrentPath,
							shiftedSplittedRemainingPath, nextDistance , alreadyCheckedPathes
						);
						break;
					default:
						//do nothing
						break;
				}
			}else{
				//do nothing
			}

			//count the number of ' ' and '　'.
			var positionOfSpaces = checkPositionOfSpaces(targetPath);
			var numberOfSpaces = positionOfSpaces.length;
			if(numberOfSpaces > 0){
				//remove one of spaces and check the path.
				for(var index = 0; index < numberOfSpaces; index++){
					var nextSplittedRemainingPath = splittedRemainingPath;
					var firstHalfOfTargetPathRemovedSpace = targetPath;
					var latterHalfOfTargetPathRemovedSpace = targetPath;
					var targetPathRemovedSpace =
						firstHalfOfTargetPathRemovedSpace.slice(0,positionOfSpaces[index]) +
						latterHalfOfTargetPathRemovedSpace.slice(positionOfSpaces[index]+1);
					nextSplittedRemainingPath[0] = targetPathRemovedSpace;
					var nextDistance = currentDistance + 1;
					var nextAvailableCurrentPath = availableCurrentPath;

					//check the path if it is checked at first
					var alreadyCheckedFlag = false;
					for(var index = 0 , len = alreadyCheckedPathes.length ; index < len ; index++){
						if(alreadyCheckedPathes[index] == checkingPath){
							alreadyCheckedFlag = true;
						}
					}
					//check only when the path is checked at first
					var alreadyCheckedFlag = false;
					for(var index = 0 , len = alreadyCheckedPathes.length ; index < len ; index++){
						if(alreadyCheckedPathes[index] == nextAvailableCurrentPath + "\\" + targetPathRemovedSpace){
							alreadyCheckedFlag = true;
						}
					}
					if(alreadyCheckedFlag == false){
						searchAvailablePathConsideringUnnecessarySpaceWithDistance(
							availableFullPathes, nextAvailableCurrentPath,
							nextSplittedRemainingPath, nextDistance , alreadyCheckedPathes
						);
					}
				}
			}
		}else{
			//check if the availableCurrentPath is already added.
			var alreadyExistFlag = false;
			for(var index = 0, len = availableFullPathes.length; index < len ; index++){
				if(availableFullPathes[index][0] == availableCurrentPath){
					alreadyExistFlag = true;
				}
			}
			if(alreadyExistFlag == false){
				availableFullPathes.push([availableCurrentPath , currentDistance]);
			}
		}
	}

	//format query as below.
	//remove spaces attached on head and bottom.
	//normalize
	function formatQuery(query){
		//remove spaces attached on head and bottom.
		var trimmedQuery = query.trim();

		//remove unavailable characters.
		var queryRemovedUnavailableCharacters =
			removeCharacters(trimmedQuery,['*','/','?',"\"","<",">","|","\t"]);

		//normalize
		var normalizedQuery = path.normalize(queryRemovedUnavailableCharacters);
		if(normalizedQuery == "."){
			normalizedQuery = "";
		}

		//return result
		return normalizedQuery;
	}

	//search available drives.
	function searchAvailableDrivesAsync(){
		//{
		//	driveName:checkingDrive + "\\",
		//	isAvailable:false,
		//	failureOfAccess:0
		//}
		for (var index = 0, len = availableDrives.length ; index < len ; index++){
			let checkingDriveObj = availableDrives[index];
			fs.stat(checkingDriveObj.driveName, function(err,stats){
				if(err){
					if(checkingDriveObj.isAvailable == true){
						checkingDriveObj.failureOfAccess++;
						if(checkingDriveObj.failureOfAccess > failureThreshold){
							checkingDriveObj.isAvailable = false;
							checkingDriveObj.failureOfAccess = 0;
						}
					}
					return;
				}else{
					if(stats.isDirectory() == true){
						if(checkingDriveObj.isAvailable == true){
							checkingDriveObj.failureOfAccess = 0;
						}else{
							checkingDriveObj.isAvailable = true;
						}
					}
				}
			});
		}
	}

	function refreshAvailableDrives(){
		searchAvailableDrivesAsync();
	}

	function startup(){
		//Search Available Drives.
		searchAvailableDrivesAsync();
	}

	function search (query, res) {
		//format query.
		var normalizedQuery = formatQuery(query);

		//check if the path is file server.
		//if the path is file server, remove "\\" attached on head.
		var isFileServer = false;
		if(normalizedQuery.indexOf("\\\\") == 0){
			isFileServer = true;
			normalizedQuery.substring(("\\\\").length);
		}

		//split by separator('\' or '/').
		var splittedQuery = normalizedQuery.split(path.sep);

		//if isFileServer is true, combine 1st and 2nd element.
		if(isFileServer == true){
			if(splittedQuery.length >= 2){
				splittedQuery[1] = "\\\\" + splittedQuery[0] + "\\" + splittedQuery[1];
				splittedQuery.shift();
			}else if (splittedQuery.length == 1){
				splittedQuery[0] = "\\\\" + splittedQuery[0];
			}
		}
		//remove empty element in splittedQuery.
		var splittedQueryRemovedUnnecessaryElement = splittedQuery.filter(function(e){return e !== "";});

		//search available file/folder name. (considering unnecessary space)
		var availableFullPathes = [];
		searchAvailablePathConsideringUnnecessarySpace(availableFullPathes,"",splittedQueryRemovedUnnecessaryElement.slice());

		//sort available path candidates by distance between them and query.
		var sortedAvailableFullPathes = availableFullPathes.slice();
		sortedAvailableFullPathes.sort(
			function(a,b){
				//compare the distance
				return ( (a[1] - b[1]) );
			}
		);

		//add to result (when no available path is found)
		if(sortedAvailableFullPathes.length == 0){
			//do nothing
		}else{//add to result (when no available path is found)
			for(var index = 0 , len = sortedAvailableFullPathes.length ; index < len ; index++){
				//Check state of formatted path (File or Folder or not).
				//and set Description Message according to the state.
				var descriptionMessage = "";
				var availableFullPath = sortedAvailableFullPathes[index][0].slice();
				var distance = sortedAvailableFullPathes[index][1];
				var addToResFlag = false;
				switch(checkFileOrFolder(availableFullPath)){
					case -1://invalid
					case 0://invalid
						//descriptionMessage = "Not File/Folder. Cannot open."
						break;
					case 1://file
						//extract file name
						//(todo) extract BBB from "C:\AAA\BBB\" <- when unnecessary "\" exists.
						var filename = availableFullPath.slice().split("\\").pop();
						descriptionMessage = "Open this File : \"" + filename +
							"\" ( Distance = " + distance + " )";
						addToResFlag = true;
						break;
					case 2://folder
						//extract folder name
						//(todo) extract BBB from "C:\AAA\BBB\" <- when unnecessary "\" exists.
						var foldername = availableFullPath.slice().split("\\").pop();
						descriptionMessage = "Open this Folder : \"" + foldername +
							"\" ( Distance = " + distance + " )";
						addToResFlag = true;
						break;
					default:
						break;
				}
				//add to res.
				if(addToResFlag == true){
					res.add(
						{
							id: availableFullPath,
							payload: 'open',
							title: availableFullPath,
							desc: descriptionMessage
						}
					);
				}
			}
		}

		//search available path to complement
		var foundCandidates = [];
		//check if the current path is empty
		var searchingSplittedQueryBase = splittedQuery.slice();
		var lengthOfsearchingSplittedQueryBase = searchingSplittedQueryBase.length
		var currentDirectory;
		var searchKeyword;
		if(lengthOfsearchingSplittedQueryBase == 0){
			currentDirectory = "";
			searchKeyword = "";
		}else if(lengthOfsearchingSplittedQueryBase == 1){
			currentDirectory = "";
			searchKeyword = searchingSplittedQueryBase[0];
		}else{// length >= 2
			currentDirectory = "";
			for(index = 0 ; index < lengthOfsearchingSplittedQueryBase - 1 ; index++){
				currentDirectory = currentDirectory + searchingSplittedQueryBase[index] + "\\";
			}
			//currentDirectory.pop();
			searchKeyword = searchingSplittedQueryBase[lengthOfsearchingSplittedQueryBase - 1];
		}

		//check the existence of currentDirectory.
		if(currentDirectory == "" || checkFileOrFolder(currentDirectory) == 2){
			//find candidates
			if(currentDirectory == ""){
				for (var index = 0, len = availableDrives.length ; index < len ; index++){
					if(availableDrives[index].isAvailable == true){
						foundCandidates.push(
							{
								path:availableDrives[index].driveName,
								state:"drive"
							}
						);
					}
				}
			}else{// when checkFileOrFolder(currentDirectory) == 2
				//(todo) make async (use fs.readdir)
				var foundList = fs.readdirSync(currentDirectory);
				//foundCandidates = fs.readdirSync(currentDirectory);
				for(var index = 0, len = foundList.length ; index < len ; index++){
					switch(checkFileOrFolder(currentDirectory + foundList[index])){
						case 1://file
							foundCandidates.push(
								{
									path:foundList[index],
									state:"file"
								}
							);
							break;
						case 2://folder
							foundCandidates.push(
								{
									path:foundList[index],
									state:"folder"
								}
							);
							break;
						default:
							//do nothing
							break;
					}
				}
			}

			//filter with searchKeyword and add to res
			for(var index = 0, len = foundCandidates.length ; index < len ; index++){
				//check if candidates contains searchKeyword on head
				if(foundCandidates[index].path.indexOf(searchKeyword) == 0){
					//add to res.
					var descriptionMessage =
						"Set this path : \"" + foundCandidates[index].path + "\"";
					//var redirect;
					var innerTitle,innerRedirect;
					switch(foundCandidates[index].state){
						case "drive":
							innerTitle = "";
							break;
						case "file":
						case "folder":
							innerTitle = ".\\";
							break;
					}
					innerTitle =
						innerTitle +
						"<b>" + foundCandidates[index].path.substring(0,searchKeyword.length) + "</b>" +
						foundCandidates[index].path.substring(searchKeyword.length);
					innerRedirect =
						commandHeader + " " +
						currentDirectory + foundCandidates[index].path + "\\";
					res.add(
						{
							//id: checkingDrive,
							id: commandHeader + " " + foundCandidates[index].path,
							payload: 'complement',
							title: innerTitle,
							desc: descriptionMessage,
							redirect:innerRedirect
						}
					);
				}
			}
		}

		//refresh command to the end of list
		res.add(
			{
				id: commandHeader + query,
				payload: 'refresh',
				title: "Refresh",
				desc: "Search Available Drives Again."
			}
		);
	}

	function execute (id, payload) {
		//open file or folder.
		switch (payload){
			case 'open':
				//open file/folder
				shell.openItem(`${id}`);
				break;
			case 'complement':
				//complement path (set id to query)
				app.setQuery(id);
				break;
			case 'refresh':
				//search available drives again.
				refreshAvailableDrives();
				app.setQuery(id);
				break;
			case 'pending':
			default:
				return;
		}
	}

	return { startup, search, execute };
}
<|endoftext|>


<commit_before>/*global $, Hammer*/
/*jslint newcap:true*/
$.fn.simpleDraggableContainer = function () {
	'use strict';
	var currentDragObject,
		originalDragObjectPosition,
		drag = function (event) {
			if (currentDragObject && event.gesture) {
				var newpos = {
						top: parseInt(originalDragObjectPosition.top, 10) + event.gesture.deltaY,
						left: parseInt(originalDragObjectPosition.left, 10) + event.gesture.deltaX
					};
				currentDragObject.css(newpos).trigger('mm:drag');
				event.preventDefault();
				if (event.gesture) {
					event.gesture.preventDefault();
				}
			}
		},
		rollback = function () {
			var target = currentDragObject; // allow it to be cleared while animating
			target.animate(originalDragObjectPosition, {
				complete: function () {
					target.trigger('mm:cancel-dragging');
				},
				progress: function () {
					target.trigger('mm:drag');
				}
			});
		};
	return Hammer($(this), {'drag_min_distance': 2}).on('mm:start-dragging', function (event) {
		if (!currentDragObject) {
			currentDragObject = $(event.relatedTarget);
			originalDragObjectPosition = {
				top: currentDragObject.css('top'),
				left: currentDragObject.css('left')
			};
			$(this).on('drag', drag);
		}
	}).on('dragend', function (e) {
		var evt = $.Event('mm:stop-dragging', {gesture: e.gesture});
		$(this).off('drag', drag);
		if (currentDragObject) {
			currentDragObject.trigger(evt);
			if (evt.result === false) {
				rollback();
			}
			currentDragObject = undefined;
		}
	}).on('mouseleave', function () {
		if (currentDragObject) {
			$(this).off('drag', drag);
			rollback();
			currentDragObject = undefined;
		}
	}).attr('data-drag-role', 'container');
};
$.fn.simpleDraggable = function () {
	'use strict';
	return $(this).on('dragstart', function (e) {
		$(this).trigger(
			$.Event('mm:start-dragging', {
				relatedTarget: this
			})
		);
		e.stopPropagation();
		if (e.gesture) {
			e.gesture.stopPropagation();
		}
	});
};

<commit_msg>drag at scale<commit_after>/*global $, Hammer*/
/*jslint newcap:true*/
$.fn.simpleDraggableContainer = function () {
	'use strict';
	var currentDragObject,
		originalDragObjectPosition,
		drag = function (event) {
			if (currentDragObject && event.gesture) {
				var scale = currentDragObject.parent().data('scale') || 1,
					newpos = {
						top: Math.round(parseInt(originalDragObjectPosition.top, 10) + event.gesture.deltaY / scale),
						left: Math.round(parseInt(originalDragObjectPosition.left, 10) + event.gesture.deltaX / scale)
					};
				currentDragObject.css(newpos).trigger('mm:drag');
				event.preventDefault();
				if (event.gesture) {
					event.gesture.preventDefault();
				}
			}
		},
		rollback = function () {
			var target = currentDragObject; // allow it to be cleared while animating
			target.animate(originalDragObjectPosition, {
				complete: function () {
					target.trigger('mm:cancel-dragging');
				},
				progress: function () {
					target.trigger('mm:drag');
				}
			});
		};
	return Hammer($(this), {'drag_min_distance': 2}).on('mm:start-dragging', function (event) {
		if (!currentDragObject) {
			currentDragObject = $(event.relatedTarget);
			originalDragObjectPosition = {
				top: currentDragObject.css('top'),
				left: currentDragObject.css('left')
			};
			$(this).on('drag', drag);
		}
	}).on('dragend', function (e) {
		var evt = $.Event('mm:stop-dragging', {gesture: e.gesture});
		$(this).off('drag', drag);
		if (currentDragObject) {
			currentDragObject.trigger(evt);
			if (evt.result === false) {
				rollback();
			}
			currentDragObject = undefined;
		}
	}).on('mouseleave', function () {
		if (currentDragObject) {
			$(this).off('drag', drag);
			rollback();
			currentDragObject = undefined;
		}
	}).attr('data-drag-role', 'container');
};
$.fn.simpleDraggable = function () {
	'use strict';
	return $(this).on('dragstart', function (e) {
		$(this).trigger(
			$.Event('mm:start-dragging', {
				relatedTarget: this
			})
		);
		e.stopPropagation();
		if (e.gesture) {
			e.gesture.stopPropagation();
		}
	});
};

<|endoftext|>


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

module.exports = {

  name: 'ember-cli-sentry',

  contentFor: function(type, config){
    if (type === 'body') {
      return '<script src="' + config.sentry.cdn + '/' + config.sentry.version + '/jquery,native/raven.min.js"></script>';
    }
  }

};
<commit_msg>Add support for to avoid cdn on local load<commit_after>/* jshint node: true */
'use strict';

module.exports = {

  name: 'ember-cli-sentry',

  contentFor: function(type, config){
    if (type === 'body' && !config.sentry.loadLocal) {
      return '<script src="' + config.sentry.cdn + '/' + config.sentry.version + '/jquery,native/raven.min.js"></script>';
    }
  }

};
<|endoftext|>


<commit_before>var http = require('http');
var chalk = require('chalk');

// Process args
var names = process.argv.slice(2);

if (!names.length) {
  console.log('what name(s) should I search for?');
  process.exit(1);
}

var checked = [],
    pos = 0;

names.forEach(function(name, i){
  http.request({
    method: 'HEAD',
    hostname: 'registry.npmjs.org',
    path: '/' + name
  })
  .on('response', function (res) {
    collectResult(null, res, i, name);
  })
  .on('error', function (err) {
    collectResult(err, null, i, name);
  })
  .end();
});

function collectResult (err, res, i, name) {
  if (checked[i]) return;
  checked[i] = res || {};
  checked[i].name = name;
  checked[i].err = err;
  report();
}

function report () {
  var current;
  for (; checked[pos]; pos++) {
    current = checked[pos];
    if (current.statusCode === 200) {
      console.log(current.name, 'is unavailable: https://www.npmjs.org/package/' + current.name);
    } else if (current.statusCode === 404) {
      console.log(chalk.green(current.name), 'is available!');
    } else if (current.err) {
      console.error(chalk.red('error checking'), current.name);
      console.error(chalk.gray(current.err));
    } else if (current.timeout) {
      console.error(chalk.yellow(current.name, 'timed out'));
    } else {
      console.error(chalk.blue(current.name, 'had status code', current.statusCode));
    }
    if (pos === names.length - 1) process.exit(0);
  }
}

var TIME = 3000;
setTimeout(function(){
  console.error(chalk.yellow('\nTimed out after', TIME / 1000, 'seconds\n'));
  for (var i = pos; i < names.length; i++) {
    if (!checked[i]) checked[i] = { timeout: true, name: names[i] };
  }
  report();
  process.exit(1);
}, TIME);
<commit_msg>better colors<commit_after>var http = require('http');
var chalk = require('chalk');

// Process args
var names = process.argv.slice(2);

if (!names.length) {
  console.log('what name(s) should I search for?');
  process.exit(1);
}

var checked = [],
    pos = 0;

names.forEach(function(name, i){
  http.request({
    method: 'HEAD',
    hostname: 'registry.npmjs.org',
    path: '/' + name
  })
  .on('response', function (res) {
    collectResult(null, res, i, name);
  })
  .on('error', function (err) {
    collectResult(err, null, i, name);
  })
  .end();
});

function collectResult (err, res, i, name) {
  if (checked[i]) return;
  checked[i] = res || {};
  checked[i].name = name;
  checked[i].err = err;
  report();
}

function report () {
  var current;
  for (; checked[pos]; pos++) {
    current = checked[pos];
    if (current.statusCode === 200) {
      console.log(chalk.grey(current.name, 'is unavailable: https://www.npmjs.org/package/' + current.name));
    } else if (current.statusCode === 404) {
      console.log(chalk.green(current.name), 'is available!');
    } else if (current.err) {
      console.error(current.name, chalk.red(current.err));
    } else if (current.timeout) {
      console.error(current.name, chalk.yellow('timed out'));
    } else {
      console.error(current.name, chalk.magenta(current.statusCode, http.STATUS_CODES[current.statusCode]));
    }
    if (pos === names.length - 1) process.exit(0);
  }
}

var TIME = 3000;
setTimeout(function(){
  console.error(chalk.yellow('\nTimed out after', TIME / 1000, 'seconds\n'));
  for (var i = pos; i < names.length; i++) {
    if (!checked[i]) checked[i] = { timeout: true, name: names[i] };
  }
  report();
  process.exit(1);
}, TIME);
<|endoftext|>