<commit_before>/*
 * net.js: Wrapper around node.js core `net` module for observing relevant events
 *
 * (C) 2011 Nodejitsu Inc.
 *
 */

var net = require('net'),
    semver = require('semver'),
    carapace = require('./carapace');

//
// ### function toPort(x)
// #### @x {Number|String} Object to convert to a port number.
// Helper function from Node code to parse port arguments
// passed to net.prototype.Server.listen
//
function toPort(x) {
  return (x = Number(x)) >= 0 ? x : false;
}

//
// ### function nextPort (port)
// #### @port {Number} Port to increment from.
// Gets the next port in sequence from the
// specified `port`.
//
function nextPort(port) {
  if (!port) {
    return 8000;
  }

  //
  // Find the next port that we are not supposed to ignore or cause errors on
  //
  var unavailable = carapace.ports.ignore.concat(carapace.ports.throw);
  do {
    port = port + 1;
  } while (unavailable.indexOf(port) !== -1);

  return port;
}

//
// ### functon reservedPort
// #### @desired {Number} Desired port to bind to.
// Helper function which will emit an error if the
// server (the `this` argument) is in `carapace.ports.throw`
//
function reservedPort(desired) {
  if (carapace.ports.throw.indexOf(desired) !== -1) {
    this.close();
    //
    // Build fake error
    //
    var err = new Error('EADDRINUSE, Address already in use');
    err.code = 'EADDRINUSE';
    err.syscall = 'bind';
    err.errno = 100;
    this.emit('error', err);
    return true;
  }

  return false;
}

//
// ### function _doListen ()
// Override for `node@0.4.x`.
//
exports._doListen = function overrideNet() {
  var binding = process.binding('net'),
      socket = binding.socket,
      listen = binding.listen,
      dummyFD = null;

  //
  // Helper function from node.js core for
  // working with `dummyFD`
  //
  function getDummyFD() {
    if (!dummyFD) {
      try { dummyFD = socket('tcp') }
      catch (e) { dummyFD = null }
    }
  }

  //
  // Separate since net.Server uses a cached bind function
  //
  net.Server.prototype._doListen = function ourListen() {
    var self = this,
        desired = toPort(arguments[0]),
        addr = arguments[1],
        current,
        actual,
        err;

    // Ensure we have a dummy fd for EMFILE conditions.
    getDummyFD();

    //
    // Always throw if our desired port was one that should always throw
    //
    if (reservedPort.call(this, desired)) {
      return;
    }

    //
    // Since desired is not on a throwing port
    // we want to skip ports in both throw and ignore
    //
    current = desired ? desired : nextPort(desired);

    for (;;) {
      try {
        binding.bind(self.fd, current, addr);
        break;
      }
      catch (err) {
        //
        // Find the next port we are not supposed to throw up on or ignore
        //
        current = nextPort(current);

        //
        // If this is not an `EADDRINUSE` error or the port is in
        // `carapace.ports.throw` which should always throw an error,
        // then throw the error.
        //
        if (err.code !== 'EADDRINUSE') {
          self.close();
          self.emit('error', err);
          return;
        }
      }
    }

    actual = this.address().port;
    if (!desired) {
      desired = actual;
    }

    //
    // Need to the listening in the nextTick so that people potentially have
    // time to register 'listening' listeners.
    //
    process.nextTick(function () {
      //
      // It could be that server.close() was called between the time the
      // original listen command was issued and this. Bail if that's the case.
      // See test/simple/test-net-eaddrinuse.js
      //
      if (typeof self.fd !== 'number') {
        return;
      }

      try {
        listen(self.fd, self._backlog || 128);

        //
        // Store the server that has listened on the `desired` port
        // on the carapace itself, indexed by port.
        //
        carapace.servers[desired] = self;

        carapace.emit('port', {
          id: carapace.id,
          addr: addr,
          desired: desired,
          port: actual
        });
      }
      catch (err) {
        if (err.code !== 'EADDRINUSE') {
          self.close();
          self.emit('error', err);
        }
        else {
          //
          // Generate a new socket of the same type since we cannot use an already bound one
          //
          self.fd = socket(self.type);
          self._doListen(desired, addr);
        }

        return;
      }

      self._startWatcher();
    });
  };
}

//
// ### function _listen2 ()
// Override for `node@0.5.x` and `node@0.6.x`.
//
exports._listen2 = function overrideNet() {
  var _listen2 = net.Server.prototype._listen2;

  net.Server.prototype._listen2 = function ourListen(address, port, addressType, desired) {
    var self = this;

    port = toPort(port);
    desired || (desired = port);

    //
    // Always throw if our desired port was one that should always throw
    //
    if (reservedPort.call(this, port)) {
      return;
    }

    //
    // Since desired is not on a throwing port
    // we want to skip ports in both throw and ignore
    //
    port || (port = nextPort(port));

    //
    // We rely on `error` event to check if address it taken/available, however
    // user may want to hook up to `error` in his application as well (and
    // usually exit when it's emitted). This messes things up. Here we store
    // `error` event listeners and remove them. They will be restored after we
    // start listening or get an error which is not `EADDRINUSE`.
    //
    var errorListeners = self.listeners('error');
    self.removeAllListeners('error');

    function restoreErrorListeners() {
      errorListeners.forEach(function (listener) {
        self.on('error', listener);
      });
    }

    //
    // Problem with `listening` events is a bit different. We want to ensure
    // that we first emit `carapace::port` and *then* the proper `listening`
    // event (which can be consumed by user's app).
    //
    // (Also, not doing so breaks `net/net-multiple-servers-test` test.)
    //
    var listeningListeners = self.listeners('listening');
    self.removeAllListeners('listening');

    function restoreListeningListeners() {
      listeningListeners.forEach(function (listener) {
        self.on('listening', listener);
      });
    }

    function onListen() {
      //
      // Yay, we made it! Lets restore `error` listeners and tell the world
      // that we totally owned this port.
      //

      self.removeListener('error', onError);

      restoreErrorListeners();
      restoreListeningListeners();

      //
      // Store the server that has listened on the `desired` port
      // on the carapace itself, indexed by port.
      //
      carapace.servers[desired] = self;

      carapace.emit('port', {
        id: carapace.id,
        addr: address,
        port: port,
        desired: desired
      });

      process.nextTick(function () {
        self.emit('listening');
      });
    }

    function onError(err) {
      //
      // We failed to listen. Unless it's not EADDRINUSE lets try doing the
      // same thing, just with next port.
      //

      self.removeListener('listening', onListen);

      //
      // We can safely restore these listeners here. We're going to call
      // `ourFunction`, so they will be removed again anyway.
      //
      restoreErrorListeners();
      restoreListeningListeners();

      if (err.code !== 'EADDRINUSE') {
        try { self.close() }
        catch (ex) { }

        return self.emit('error', err);
      }

      ourListen.call(self, address, nextPort(port), addressType, desired);
    }

    self.once('listening', onListen);
    self.once('error', onError);

    //
    // Call original _listen2 function.
    //
    process.nextTick(function () {
      _listen2.call(self, address, port, addressType);
    });
  };
};

//
// Setup the valid `nodeVersion` for all of the
// monkey patches to `require('net')`.
//
exports._listen2.nodeVersion = '0.5.x || 0.6.x';
exports._doListen.nodeVersion = '0.4.x';

//
// ### function getOverride (version)
// #### @version {string} Node version to get `net` override.
// Helper function which responds with the correct `net` module
// override for the specified `version`.
//
exports.getOverride = function (version) {
  var matches = Object.keys(exports).filter(function (method) {
    if (!exports[method].nodeVersion) {
      return false;
    }

    return semver.satisfies(version, exports[method].nodeVersion);
  }).map(function (method) {
    return exports[method];
  });

  if (!matches.length) {
    return null;
  }

  return matches.length > 1
    ? matches
    : matches[0];
};
<commit_msg>[fix] always listen to wildcard address<commit_after>/*
 * net.js: Wrapper around node.js core `net` module for observing relevant events
 *
 * (C) 2011 Nodejitsu Inc.
 *
 */

var net = require('net'),
    semver = require('semver'),
    carapace = require('./carapace');

//
// ### function toPort(x)
// #### @x {Number|String} Object to convert to a port number.
// Helper function from Node code to parse port arguments
// passed to net.prototype.Server.listen
//
function toPort(x) {
  return (x = Number(x)) >= 0 ? x : false;
}

//
// ### function nextPort (port)
// #### @port {Number} Port to increment from.
// Gets the next port in sequence from the
// specified `port`.
//
function nextPort(port) {
  return 0;

  //
  // Find the next port that we are not supposed to ignore or cause errors on
  //
  var unavailable = carapace.ports.ignore.concat(carapace.ports.throw);
  do {
    port = port + 1;
  } while (unavailable.indexOf(port) !== -1);

  return port;
}

//
// ### functon reservedPort
// #### @desired {Number} Desired port to bind to.
// Helper function which will emit an error if the
// server (the `this` argument) is in `carapace.ports.throw`
//
function reservedPort(desired) {
  if (carapace.ports.throw.indexOf(desired) !== -1) {
    this.close();
    //
    // Build fake error
    //
    var err = new Error('EADDRINUSE, Address already in use');
    err.code = 'EADDRINUSE';
    err.syscall = 'bind';
    err.errno = 100;
    this.emit('error', err);
    return true;
  }

  return false;
}

//
// ### function _doListen ()
// Override for `node@0.4.x`.
//
exports._doListen = function overrideNet() {
  var binding = process.binding('net'),
      socket = binding.socket,
      listen = binding.listen,
      dummyFD = null;

  //
  // Helper function from node.js core for
  // working with `dummyFD`
  //
  function getDummyFD() {
    if (!dummyFD) {
      try { dummyFD = socket('tcp') }
      catch (e) { dummyFD = null }
    }
  }

  //
  // Separate since net.Server uses a cached bind function
  //
  net.Server.prototype._doListen = function ourListen() {
    var self = this,
        desired = toPort(arguments[0]),
        addr = arguments[1],
        current,
        actual,
        err;

    // Ensure we have a dummy fd for EMFILE conditions.
    getDummyFD();

    //
    // Always throw if our desired port was one that should always throw
    //
    if (reservedPort.call(this, desired)) {
      return;
    }

    //
    // Since desired is not on a throwing port
    // we want to skip ports in both throw and ignore
    //
    current = 0;

    for (;;) {
      try {
        binding.bind(self.fd, 0, '0.0.0.0');
        break;
      }
      catch (err) {
        //
        // Find the next port we are not supposed to throw up on or ignore
        //
        current = 0;

        //
        // If this is not an `EADDRINUSE` error or the port is in
        // `carapace.ports.throw` which should always throw an error,
        // then throw the error.
        //
        if (err.code !== 'EADDRINUSE') {
          self.close();
          self.emit('error', err);
          return;
        }
      }
    }

    actual = this.address().port;
    if (!desired) {
      desired = actual;
    }

    //
    // Need to the listening in the nextTick so that people potentially have
    // time to register 'listening' listeners.
    //
    process.nextTick(function () {
      //
      // It could be that server.close() was called between the time the
      // original listen command was issued and this. Bail if that's the case.
      // See test/simple/test-net-eaddrinuse.js
      //
      if (typeof self.fd !== 'number') {
        return;
      }

      try {
        listen(self.fd, self._backlog || 128);

        //
        // Store the server that has listened on the `desired` port
        // on the carapace itself, indexed by port.
        //
        carapace.servers[desired] = self;

        carapace.emit('port', {
          id: carapace.id,
          addr: addr,
          desired: desired,
          port: actual
        });
      }
      catch (err) {
        if (err.code !== 'EADDRINUSE') {
          self.close();
          self.emit('error', err);
        }
        else {
          //
          // Generate a new socket of the same type since we cannot use an already bound one
          //
          self.fd = socket(self.type);
          self._doListen(desired, addr);
        }

        return;
      }

      self._startWatcher();
    });
  };
}

//
// ### function _listen2 ()
// Override for `node@0.5.x` and `node@0.6.x`.
//
exports._listen2 = function overrideNet() {
  var _listen2 = net.Server.prototype._listen2;

  net.Server.prototype._listen2 = function ourListen(address, port, addressType, desired) {
    var self = this;

    port = toPort(port);
    desired || (desired = port);

    //
    // Always throw if our desired port was one that should always throw
    //
    if (reservedPort.call(this, port)) {
      return;
    }

    //
    // Since desired is not on a throwing port
    // we want to skip ports in both throw and ignore
    //
    port || (port = nextPort(port));

    //
    // We rely on `error` event to check if address it taken/available, however
    // user may want to hook up to `error` in his application as well (and
    // usually exit when it's emitted). This messes things up. Here we store
    // `error` event listeners and remove them. They will be restored after we
    // start listening or get an error which is not `EADDRINUSE`.
    //
    var errorListeners = self.listeners('error');
    self.removeAllListeners('error');

    function restoreErrorListeners() {
      errorListeners.forEach(function (listener) {
        self.on('error', listener);
      });
    }

    //
    // Problem with `listening` events is a bit different. We want to ensure
    // that we first emit `carapace::port` and *then* the proper `listening`
    // event (which can be consumed by user's app).
    //
    // (Also, not doing so breaks `net/net-multiple-servers-test` test.)
    //
    var listeningListeners = self.listeners('listening');
    self.removeAllListeners('listening');

    function restoreListeningListeners() {
      listeningListeners.forEach(function (listener) {
        self.on('listening', listener);
      });
    }

    function onListen() {
      //
      // Yay, we made it! Lets restore `error` listeners and tell the world
      // that we totally owned this port.
      //

      self.removeListener('error', onError);

      restoreErrorListeners();
      restoreListeningListeners();

      //
      // Store the server that has listened on the `desired` port
      // on the carapace itself, indexed by port.
      //
      carapace.servers[desired] = self;

      carapace.emit('port', {
        id: carapace.id,
        addr: address,
        port: port,
        desired: desired
      });

      process.nextTick(function () {
        self.emit('listening');
      });
    }

    function onError(err) {
      //
      // We failed to listen. Unless it's not EADDRINUSE lets try doing the
      // same thing, just with next port.
      //

      self.removeListener('listening', onListen);

      //
      // We can safely restore these listeners here. We're going to call
      // `ourFunction`, so they will be removed again anyway.
      //
      restoreErrorListeners();
      restoreListeningListeners();

      if (err.code !== 'EADDRINUSE') {
        try { self.close() }
        catch (ex) { }

        return self.emit('error', err);
      }

      ourListen.call(self, address, nextPort(port), addressType, desired);
    }

    self.once('listening', onListen);
    self.once('error', onError);

    //
    // Call original _listen2 function.
    //
    process.nextTick(function () {
      _listen2.call(self, '0.0.0.0', 0, addressType);
    });
  };
};

//
// Setup the valid `nodeVersion` for all of the
// monkey patches to `require('net')`.
//
exports._listen2.nodeVersion = '0.5.x || 0.6.x';
exports._doListen.nodeVersion = '0.4.x';

//
// ### function getOverride (version)
// #### @version {string} Node version to get `net` override.
// Helper function which responds with the correct `net` module
// override for the specified `version`.
//
exports.getOverride = function (version) {
  var matches = Object.keys(exports).filter(function (method) {
    if (!exports[method].nodeVersion) {
      return false;
    }

    return semver.satisfies(version, exports[method].nodeVersion);
  }).map(function (method) {
    return exports[method];
  });

  if (!matches.length) {
    return null;
  }

  return matches.length > 1
    ? matches
    : matches[0];
};
<|endoftext|>


<commit_before>;(function(){
// windows: running "npm blah" in this folder will invoke WSH, not node.
if (typeof WScript !== "undefined") {
  WScript.echo("npm does not work when run\n"
              +"with the Windows Scripting Host\n\n"
              +"'cd' to a different directory,\n"
              +"or type 'npm.cmd <args>',\n"
              +"or type 'node npm <args>'.")
  WScript.quit(1)
  return
}

// FIXME there really ought to be a path.split in node core
require("path").SPLIT_CHAR = process.platform === "win32" ? "\\" : "/"

var EventEmitter = require("events").EventEmitter
  , npm = module.exports = new EventEmitter
  , config = require("./config.js")
  , npmconf = require("npmconf")
  , log = require("npmlog")
  , fs = require("graceful-fs")
  , path = require("path")
  , abbrev = require("abbrev")
  , which = require("which")
  , semver = require("semver")
  , findPrefix = require("./utils/find-prefix.js")
  , getUid = require("uid-number")
  , mkdirp = require("mkdirp")
  , slide = require("slide")
  , chain = slide.chain
  , RegClient = require("npm-registry-client")

npm.config = {loaded: false}

// /usr/local is often a read-only fs, which is not
// well handled by node or mkdirp.  Just double-check
// in the case of errors when making the prefix dirs.
function mkdir (p, cb) {
  mkdirp(p, function (er, made) {
    // it could be that we couldn't create it, because it
    // already exists, and is on a read-only fs.
    if (er) {
      return fs.stat(p, function (er2, st) {
        if (er2 || !st.isDirectory()) return cb(er)
        return cb(null, made)
      })
    }
    return cb(er, made)
  })
}

npm.commands = {}

try {
  // startup, ok to do this synchronously
  var j = JSON.parse(fs.readFileSync(
    path.join(__dirname, "../package.json"))+"")
  npm.version = j.version
  npm.nodeVersionRequired = j.engines.node
  if (!semver.satisfies(process.version, j.engines.node)) {
    log.warn("unsupported version", [""
            ,"npm requires node version: "+j.engines.node
            ,"And you have: "+process.version
            ,"which is not satisfactory."
            ,""
            ,"Bad things will likely happen.  You have been warned."
            ,""].join("\n"))
  }
} catch (ex) {
  try {
    log.info("error reading version", ex)
  } catch (er) {}
  npm.version = ex
}

var commandCache = {}
  // short names for common things
  , aliases = { "rm" : "uninstall"
              , "r" : "uninstall"
              , "un" : "uninstall"
              , "unlink" : "uninstall"
              , "remove" : "uninstall"
              , "rb" : "rebuild"
              , "list" : "ls"
              , "la" : "ls"
              , "ll" : "ls"
              , "ln" : "link"
              , "i" : "install"
              , "up" : "update"
              , "c" : "config"
              , "info" : "view"
              , "show" : "view"
              , "find" : "search"
              , "s" : "search"
              , "se" : "search"
              , "author" : "owner"
              , "home" : "docs"
              , "unstar": "star" // same function
              , "apihelp" : "help"
              , "login": "adduser"
              , "add-user": "adduser"
              , "tst": "test"
              , "find-dupes": "dedupe"
              , "ddp": "dedupe"
              }

  , aliasNames = Object.keys(aliases)
  // these are filenames in .
  , cmdList = [ "install"
              , "uninstall"
              , "cache"
              , "config"
              , "set"
              , "get"
              , "update"
              , "outdated"
              , "prune"
              , "submodule"
              , "pack"
              , "dedupe"

              , "rebuild"
              , "link"

              , "publish"
              , "star"
              , "tag"
              , "adduser"
              , "unpublish"
              , "owner"
              , "deprecate"
              , "shrinkwrap"

              , "help"
              , "help-search"
              , "ls"
              , "search"
              , "view"
              , "init"
              , "version"
              , "edit"
              , "explore"
              , "docs"
              , "bugs"
              , "faq"
              , "root"
              , "prefix"
              , "bin"
              , "whoami"

              , "test"
              , "stop"
              , "start"
              , "restart"
              , "run-script"
              , "completion"
              ]
  , plumbing = [ "build"
               , "unbuild"
               , "xmas"
               , "substack"
               ]
  , fullList = npm.fullList = cmdList.concat(aliasNames).filter(function (c) {
      return plumbing.indexOf(c) === -1
    })
  , abbrevs = abbrev(fullList)

Object.keys(abbrevs).concat(plumbing).forEach(function addCommand (c) {
  Object.defineProperty(npm.commands, c, { get : function () {
    if (!loaded) throw new Error(
      "Call npm.load(conf, cb) before using this command.\n"+
      "See the README.md or cli.js for example usage.")
    var a = npm.deref(c)
    if (c === "la" || c === "ll") {
      npm.config.set("long", true)
    }
    npm.command = c
    if (commandCache[a]) return commandCache[a]
    var cmd = require(__dirname+"/"+a+".js")
    commandCache[a] = function () {
      var args = Array.prototype.slice.call(arguments, 0)
      if (typeof args[args.length - 1] !== "function") {
        args.push(defaultCb)
      }
      if (args.length === 1) args.unshift([])
      cmd.apply(npm, args)
    }
    Object.keys(cmd).forEach(function (k) {
      commandCache[a][k] = cmd[k]
    })
    return commandCache[a]
  }, enumerable: fullList.indexOf(c) !== -1 })

  // make css-case commands callable via camelCase as well
  if (c.match(/\-([a-z])/)) {
    addCommand(c.replace(/\-([a-z])/g, function (a, b) {
      return b.toUpperCase()
    }))
  }
})

function defaultCb (er, data) {
  if (er) console.error(er.stack || er.message)
  else console.log(data)
}

npm.deref = function (c) {
  if (!c) return ""
  if (c.match(/[A-Z]/)) c = c.replace(/([A-Z])/g, function (m) {
    return "-" + m.toLowerCase()
  })
  if (plumbing.indexOf(c) !== -1) return c
  var a = abbrevs[c]
  if (aliases[a]) a = aliases[a]
  return a
}

var loaded = false
  , loading = false
  , loadErr = null
  , loadListeners = []

function loadCb (er) {
  loadListeners.forEach(function (cb) {
    process.nextTick(cb.bind(npm, er, npm))
  })
  loadListeners.length = 0
}

npm.load = function (cli, cb_) {
  if (!cb_ && typeof cli === "function") cb_ = cli , cli = {}
  if (!cb_) cb_ = function () {}
  if (!cli) cli = {}
  loadListeners.push(cb_)
  if (loaded || loadErr) return cb(loadErr)
  if (loading) return
  loading = true
  var onload = true

  function cb (er) {
    if (loadErr) return
    npm.config.loaded = true
    loaded = true
    loadCb(loadErr = er)
    if (onload = onload && npm.config.get("onload-script")) {
      require(onload)
      onload = false
    }
  }

  log.pause()

  load(npm, cli, cb)
}

function load (npm, cli, cb) {
  which(process.argv[0], function (er, node) {
    if (!er && node.toUpperCase() !== process.execPath.toUpperCase()) {
      log.verbose("node symlink", node)
      process.execPath = node
      process.installPrefix = path.resolve(node, "..", "..")
    }

    // look up configs
    //console.error("about to look up configs")

    var builtin = path.resolve(__dirname, "..", "npmrc")
    npmconf.load(cli, builtin, function (er, conf) {
      if (er === conf) er = null

      npm.config = conf

      var color = conf.get("color")

      log.level = conf.get("loglevel")
      log.heading = "npm"
      log.stream = conf.get("logstream")
      switch (color) {
        case "always": log.enableColor(); break
        case false: log.disableColor(); break
      }
      log.resume()

      if (er) return cb(er)

      // see if we need to color normal output
      switch (color) {
        case "always":
          npm.color = true
          break
        case false:
          npm.color = false
          break
        default:
          var tty = require("tty")
          if (process.stdout.isTTY) npm.color = true
          else if (!tty.isatty) npm.color = true
          else if (tty.isatty(1)) npm.color = true
          else npm.color = false
          break
      }

      // at this point the configs are all set.
      // go ahead and spin up the registry client.
      var token = conf.get("_token")
      if (typeof token === "string") {
        try {
          token = JSON.parse(token)
          conf.set("_token", token, "user")
          conf.save("user")
        } catch (e) { token = null }
      }

      npm.registry = new RegClient(npm.config)

      // save the token cookie in the config file
      if (npm.registry.couchLogin) {
        npm.registry.couchLogin.tokenSet = function (tok) {
          npm.config.set("_token", tok, "user")
          // ignore save error.  best effort.
          npm.config.save("user")
        }
      }

      var umask = parseInt(cli.umask, 8)
      npm.modes = { exec: 0777 & (~umask)
                  , file: 0666 & (~umask)
                  , umask: umask }

      chain([ [ loadPrefix, npm, cli ]
            , [ setUser, conf, conf.root ]
            , [ loadUid, npm ]
            ], cb)
    })
  })
}

function loadPrefix (npm, conf, cb) {
  // try to guess at a good node_modules location.
  var p
    , gp
  if (!Object.prototype.hasOwnProperty.call(conf, "prefix")) {
    p = process.cwd()
  } else {
    p = npm.config.get("prefix")
  }
  gp = npm.config.get("prefix")

  findPrefix(p, function (er, p) {
    Object.defineProperty(npm, "localPrefix",
      { get : function () { return p }
      , set : function (r) { return p = r }
      , enumerable : true
      })
    // the prefix MUST exist, or else nothing works.
    if (!npm.config.get("global")) {
      mkdir(p, next)
    } else {
      next(er)
    }
  })

  gp = path.resolve(gp)
  Object.defineProperty(npm, "globalPrefix",
    { get : function () { return gp }
    , set : function (r) { return gp = r }
    , enumerable : true
    })
  // the prefix MUST exist, or else nothing works.
  mkdir(gp, next)

  var i = 2
    , errState = null
  function next (er) {
    if (errState) return
    if (er) return cb(errState = er)
    if (--i === 0) return cb()
  }
}

function loadUid (npm, cb) {
  // if we're not in unsafe-perm mode, then figure out who
  // to run stuff as.  Do this first, to support `npm update npm -g`
  if (!npm.config.get("unsafe-perm")) {
    getUid(npm.config.get("user"), npm.config.get("group"), cb)
  } else {
    process.nextTick(cb)
  }
}

function setUser (cl, dc, cb) {
  // If global, leave it as-is.
  // If not global, then set the user to the owner of the prefix folder.
  // Just set the default, so it can be overridden.
  if (cl.get("global")) return cb()
  if (process.env.SUDO_UID) {
    dc.user = +(process.env.SUDO_UID)
    return cb()
  }

  var prefix = path.resolve(cl.get("prefix"))
  mkdir(prefix, function (er) {
    if (er) {
      log.error("could not create prefix dir", prefix)
      return cb(er)
    }
    fs.stat(prefix, function (er, st) {
      dc.user = st && st.uid
      return cb(er)
    })
  })
}

Object.defineProperty(npm, "prefix",
  { get : function () {
      return npm.config.get("global") ? npm.globalPrefix : npm.localPrefix
    }
  , set : function (r) {
      var k = npm.config.get("global") ? "globalPrefix" : "localPrefix"
      return npm[k] = r
    }
  , enumerable : true
  })

Object.defineProperty(npm, "bin",
  { get : function () {
      if (npm.config.get("global")) return npm.globalBin
      return path.resolve(npm.root, ".bin")
    }
  , enumerable : true
  })

Object.defineProperty(npm, "globalBin",
  { get : function () {
      var b = npm.globalPrefix
      if (process.platform !== "win32") b = path.resolve(b, "bin")
      return b
    }
  })

Object.defineProperty(npm, "dir",
  { get : function () {
      if (npm.config.get("global")) return npm.globalDir
      return path.resolve(npm.prefix, "node_modules")
    }
  , enumerable : true
  })

Object.defineProperty(npm, "globalDir",
  { get : function () {
      return (process.platform !== "win32")
           ? path.resolve(npm.globalPrefix, "lib", "node_modules")
           : path.resolve(npm.globalPrefix, "node_modules")
    }
  , enumerable : true
  })

Object.defineProperty(npm, "root",
  { get : function () { return npm.dir } })

Object.defineProperty(npm, "cache",
  { get : function () { return npm.config.get("cache") }
  , set : function (r) { return npm.config.set("cache", r) }
  , enumerable : true
  })

var tmpFolder
Object.defineProperty(npm, "tmp",
  { get : function () {
      if (!tmpFolder) tmpFolder = "npm-" + process.pid
      return path.resolve(npm.config.get("tmp"), tmpFolder)
    }
  , enumerable : true
  })

// the better to repl you with
Object.getOwnPropertyNames(npm.commands).forEach(function (n) {
  if (npm.hasOwnProperty(n) || n === "config") return

  Object.defineProperty(npm, n, { get: function () {
    return function () {
      var args = Array.prototype.slice.call(arguments, 0)
        , cb = defaultCb

      if (args.length === 1 && Array.isArray(args[0])) {
        args = args[0]
      }

      if (typeof args[args.length - 1] === "function") {
        cb = args.pop()
      }

      npm.commands[n](args, cb)
    }
  }, enumerable: false, configurable: true })
})

if (require.main === module) {
  require("../bin/npm-cli.js")
}
})()
<commit_msg>umask is already an int, don't re-parse it<commit_after>;(function(){
// windows: running "npm blah" in this folder will invoke WSH, not node.
if (typeof WScript !== "undefined") {
  WScript.echo("npm does not work when run\n"
              +"with the Windows Scripting Host\n\n"
              +"'cd' to a different directory,\n"
              +"or type 'npm.cmd <args>',\n"
              +"or type 'node npm <args>'.")
  WScript.quit(1)
  return
}

// FIXME there really ought to be a path.split in node core
require("path").SPLIT_CHAR = process.platform === "win32" ? "\\" : "/"

var EventEmitter = require("events").EventEmitter
  , npm = module.exports = new EventEmitter
  , config = require("./config.js")
  , npmconf = require("npmconf")
  , log = require("npmlog")
  , fs = require("graceful-fs")
  , path = require("path")
  , abbrev = require("abbrev")
  , which = require("which")
  , semver = require("semver")
  , findPrefix = require("./utils/find-prefix.js")
  , getUid = require("uid-number")
  , mkdirp = require("mkdirp")
  , slide = require("slide")
  , chain = slide.chain
  , RegClient = require("npm-registry-client")

npm.config = {loaded: false}

// /usr/local is often a read-only fs, which is not
// well handled by node or mkdirp.  Just double-check
// in the case of errors when making the prefix dirs.
function mkdir (p, cb) {
  mkdirp(p, function (er, made) {
    // it could be that we couldn't create it, because it
    // already exists, and is on a read-only fs.
    if (er) {
      return fs.stat(p, function (er2, st) {
        if (er2 || !st.isDirectory()) return cb(er)
        return cb(null, made)
      })
    }
    return cb(er, made)
  })
}

npm.commands = {}

try {
  // startup, ok to do this synchronously
  var j = JSON.parse(fs.readFileSync(
    path.join(__dirname, "../package.json"))+"")
  npm.version = j.version
  npm.nodeVersionRequired = j.engines.node
  if (!semver.satisfies(process.version, j.engines.node)) {
    log.warn("unsupported version", [""
            ,"npm requires node version: "+j.engines.node
            ,"And you have: "+process.version
            ,"which is not satisfactory."
            ,""
            ,"Bad things will likely happen.  You have been warned."
            ,""].join("\n"))
  }
} catch (ex) {
  try {
    log.info("error reading version", ex)
  } catch (er) {}
  npm.version = ex
}

var commandCache = {}
  // short names for common things
  , aliases = { "rm" : "uninstall"
              , "r" : "uninstall"
              , "un" : "uninstall"
              , "unlink" : "uninstall"
              , "remove" : "uninstall"
              , "rb" : "rebuild"
              , "list" : "ls"
              , "la" : "ls"
              , "ll" : "ls"
              , "ln" : "link"
              , "i" : "install"
              , "up" : "update"
              , "c" : "config"
              , "info" : "view"
              , "show" : "view"
              , "find" : "search"
              , "s" : "search"
              , "se" : "search"
              , "author" : "owner"
              , "home" : "docs"
              , "unstar": "star" // same function
              , "apihelp" : "help"
              , "login": "adduser"
              , "add-user": "adduser"
              , "tst": "test"
              , "find-dupes": "dedupe"
              , "ddp": "dedupe"
              }

  , aliasNames = Object.keys(aliases)
  // these are filenames in .
  , cmdList = [ "install"
              , "uninstall"
              , "cache"
              , "config"
              , "set"
              , "get"
              , "update"
              , "outdated"
              , "prune"
              , "submodule"
              , "pack"
              , "dedupe"

              , "rebuild"
              , "link"

              , "publish"
              , "star"
              , "tag"
              , "adduser"
              , "unpublish"
              , "owner"
              , "deprecate"
              , "shrinkwrap"

              , "help"
              , "help-search"
              , "ls"
              , "search"
              , "view"
              , "init"
              , "version"
              , "edit"
              , "explore"
              , "docs"
              , "bugs"
              , "faq"
              , "root"
              , "prefix"
              , "bin"
              , "whoami"

              , "test"
              , "stop"
              , "start"
              , "restart"
              , "run-script"
              , "completion"
              ]
  , plumbing = [ "build"
               , "unbuild"
               , "xmas"
               , "substack"
               ]
  , fullList = npm.fullList = cmdList.concat(aliasNames).filter(function (c) {
      return plumbing.indexOf(c) === -1
    })
  , abbrevs = abbrev(fullList)

Object.keys(abbrevs).concat(plumbing).forEach(function addCommand (c) {
  Object.defineProperty(npm.commands, c, { get : function () {
    if (!loaded) throw new Error(
      "Call npm.load(conf, cb) before using this command.\n"+
      "See the README.md or cli.js for example usage.")
    var a = npm.deref(c)
    if (c === "la" || c === "ll") {
      npm.config.set("long", true)
    }
    npm.command = c
    if (commandCache[a]) return commandCache[a]
    var cmd = require(__dirname+"/"+a+".js")
    commandCache[a] = function () {
      var args = Array.prototype.slice.call(arguments, 0)
      if (typeof args[args.length - 1] !== "function") {
        args.push(defaultCb)
      }
      if (args.length === 1) args.unshift([])
      cmd.apply(npm, args)
    }
    Object.keys(cmd).forEach(function (k) {
      commandCache[a][k] = cmd[k]
    })
    return commandCache[a]
  }, enumerable: fullList.indexOf(c) !== -1 })

  // make css-case commands callable via camelCase as well
  if (c.match(/\-([a-z])/)) {
    addCommand(c.replace(/\-([a-z])/g, function (a, b) {
      return b.toUpperCase()
    }))
  }
})

function defaultCb (er, data) {
  if (er) console.error(er.stack || er.message)
  else console.log(data)
}

npm.deref = function (c) {
  if (!c) return ""
  if (c.match(/[A-Z]/)) c = c.replace(/([A-Z])/g, function (m) {
    return "-" + m.toLowerCase()
  })
  if (plumbing.indexOf(c) !== -1) return c
  var a = abbrevs[c]
  if (aliases[a]) a = aliases[a]
  return a
}

var loaded = false
  , loading = false
  , loadErr = null
  , loadListeners = []

function loadCb (er) {
  loadListeners.forEach(function (cb) {
    process.nextTick(cb.bind(npm, er, npm))
  })
  loadListeners.length = 0
}

npm.load = function (cli, cb_) {
  if (!cb_ && typeof cli === "function") cb_ = cli , cli = {}
  if (!cb_) cb_ = function () {}
  if (!cli) cli = {}
  loadListeners.push(cb_)
  if (loaded || loadErr) return cb(loadErr)
  if (loading) return
  loading = true
  var onload = true

  function cb (er) {
    if (loadErr) return
    npm.config.loaded = true
    loaded = true
    loadCb(loadErr = er)
    if (onload = onload && npm.config.get("onload-script")) {
      require(onload)
      onload = false
    }
  }

  log.pause()

  load(npm, cli, cb)
}

function load (npm, cli, cb) {
  which(process.argv[0], function (er, node) {
    if (!er && node.toUpperCase() !== process.execPath.toUpperCase()) {
      log.verbose("node symlink", node)
      process.execPath = node
      process.installPrefix = path.resolve(node, "..", "..")
    }

    // look up configs
    //console.error("about to look up configs")

    var builtin = path.resolve(__dirname, "..", "npmrc")
    npmconf.load(cli, builtin, function (er, conf) {
      if (er === conf) er = null

      npm.config = conf

      var color = conf.get("color")

      log.level = conf.get("loglevel")
      log.heading = "npm"
      log.stream = conf.get("logstream")
      switch (color) {
        case "always": log.enableColor(); break
        case false: log.disableColor(); break
      }
      log.resume()

      if (er) return cb(er)

      // see if we need to color normal output
      switch (color) {
        case "always":
          npm.color = true
          break
        case false:
          npm.color = false
          break
        default:
          var tty = require("tty")
          if (process.stdout.isTTY) npm.color = true
          else if (!tty.isatty) npm.color = true
          else if (tty.isatty(1)) npm.color = true
          else npm.color = false
          break
      }

      // at this point the configs are all set.
      // go ahead and spin up the registry client.
      var token = conf.get("_token")
      if (typeof token === "string") {
        try {
          token = JSON.parse(token)
          conf.set("_token", token, "user")
          conf.save("user")
        } catch (e) { token = null }
      }

      npm.registry = new RegClient(npm.config)

      // save the token cookie in the config file
      if (npm.registry.couchLogin) {
        npm.registry.couchLogin.tokenSet = function (tok) {
          npm.config.set("_token", tok, "user")
          // ignore save error.  best effort.
          npm.config.save("user")
        }
      }

      var umask = npm.config.get("umask")
      npm.modes = { exec: 0777 & (~umask)
                  , file: 0666 & (~umask)
                  , umask: umask }

      chain([ [ loadPrefix, npm, cli ]
            , [ setUser, conf, conf.root ]
            , [ loadUid, npm ]
            ], cb)
    })
  })
}

function loadPrefix (npm, conf, cb) {
  // try to guess at a good node_modules location.
  var p
    , gp
  if (!Object.prototype.hasOwnProperty.call(conf, "prefix")) {
    p = process.cwd()
  } else {
    p = npm.config.get("prefix")
  }
  gp = npm.config.get("prefix")

  findPrefix(p, function (er, p) {
    Object.defineProperty(npm, "localPrefix",
      { get : function () { return p }
      , set : function (r) { return p = r }
      , enumerable : true
      })
    // the prefix MUST exist, or else nothing works.
    if (!npm.config.get("global")) {
      mkdir(p, next)
    } else {
      next(er)
    }
  })

  gp = path.resolve(gp)
  Object.defineProperty(npm, "globalPrefix",
    { get : function () { return gp }
    , set : function (r) { return gp = r }
    , enumerable : true
    })
  // the prefix MUST exist, or else nothing works.
  mkdir(gp, next)

  var i = 2
    , errState = null
  function next (er) {
    if (errState) return
    if (er) return cb(errState = er)
    if (--i === 0) return cb()
  }
}

function loadUid (npm, cb) {
  // if we're not in unsafe-perm mode, then figure out who
  // to run stuff as.  Do this first, to support `npm update npm -g`
  if (!npm.config.get("unsafe-perm")) {
    getUid(npm.config.get("user"), npm.config.get("group"), cb)
  } else {
    process.nextTick(cb)
  }
}

function setUser (cl, dc, cb) {
  // If global, leave it as-is.
  // If not global, then set the user to the owner of the prefix folder.
  // Just set the default, so it can be overridden.
  if (cl.get("global")) return cb()
  if (process.env.SUDO_UID) {
    dc.user = +(process.env.SUDO_UID)
    return cb()
  }

  var prefix = path.resolve(cl.get("prefix"))
  mkdir(prefix, function (er) {
    if (er) {
      log.error("could not create prefix dir", prefix)
      return cb(er)
    }
    fs.stat(prefix, function (er, st) {
      dc.user = st && st.uid
      return cb(er)
    })
  })
}

Object.defineProperty(npm, "prefix",
  { get : function () {
      return npm.config.get("global") ? npm.globalPrefix : npm.localPrefix
    }
  , set : function (r) {
      var k = npm.config.get("global") ? "globalPrefix" : "localPrefix"
      return npm[k] = r
    }
  , enumerable : true
  })

Object.defineProperty(npm, "bin",
  { get : function () {
      if (npm.config.get("global")) return npm.globalBin
      return path.resolve(npm.root, ".bin")
    }
  , enumerable : true
  })

Object.defineProperty(npm, "globalBin",
  { get : function () {
      var b = npm.globalPrefix
      if (process.platform !== "win32") b = path.resolve(b, "bin")
      return b
    }
  })

Object.defineProperty(npm, "dir",
  { get : function () {
      if (npm.config.get("global")) return npm.globalDir
      return path.resolve(npm.prefix, "node_modules")
    }
  , enumerable : true
  })

Object.defineProperty(npm, "globalDir",
  { get : function () {
      return (process.platform !== "win32")
           ? path.resolve(npm.globalPrefix, "lib", "node_modules")
           : path.resolve(npm.globalPrefix, "node_modules")
    }
  , enumerable : true
  })

Object.defineProperty(npm, "root",
  { get : function () { return npm.dir } })

Object.defineProperty(npm, "cache",
  { get : function () { return npm.config.get("cache") }
  , set : function (r) { return npm.config.set("cache", r) }
  , enumerable : true
  })

var tmpFolder
Object.defineProperty(npm, "tmp",
  { get : function () {
      if (!tmpFolder) tmpFolder = "npm-" + process.pid
      return path.resolve(npm.config.get("tmp"), tmpFolder)
    }
  , enumerable : true
  })

// the better to repl you with
Object.getOwnPropertyNames(npm.commands).forEach(function (n) {
  if (npm.hasOwnProperty(n) || n === "config") return

  Object.defineProperty(npm, n, { get: function () {
    return function () {
      var args = Array.prototype.slice.call(arguments, 0)
        , cb = defaultCb

      if (args.length === 1 && Array.isArray(args[0])) {
        args = args[0]
      }

      if (typeof args[args.length - 1] === "function") {
        cb = args.pop()
      }

      npm.commands[n](args, cb)
    }
  }, enumerable: false, configurable: true })
})

if (require.main === module) {
  require("../bin/npm-cli.js")
}
})()
<|endoftext|>


<commit_before>News={
	DropDownMenu: {
		fade:function(button){
			var list = $(button).parent().find('ul#fademenu');
			if (list.css('display') == 'none')
				list.fadeIn();
			else
				list.fadeOut();

			return false;
		},
		dropdown:function(button){
			var list = $(button).parent().find('ul#dropdownmenu');
			if (list.css('display') == 'none')
				list.slideDown('fast').show();
			else
				list.slideUp('fast');

			return false;
		},
		selectItem:function(item, folderid){
			var parent = $(item).parent().parent();
			parent.find('#dropdownBtn').text($(item).text());
			parent.find(':input[name="folderid"]').val(folderid);
			parent.find('ul#dropdown').slideUp('fast');
		}
	},
	UI: {
		overview:function(dialogtype, dialogfile){
		    	if($(dialogtype).dialog('isOpen') == true){
				$(dialogtype).dialog('moveToTop');
			}else{
				$('#dialog_holder').load(OC.filePath('news', 'ajax', dialogfile), function(jsondata){
					if(jsondata.status != 'error'){
						$(dialogtype).dialog({
							dialogClass:'dialog',
							minWidth: 600,
							close: function(event, ui) {
								$(this).dialog('destroy').remove();
							}
						}).css('overflow','visible');
					} else {
						alert(jsondata.data.message);
					}
				});
			}
			return false;
		}
	},
	Folder: {
		submit:function(button){
			var displayname = $("#folder_add_name").val().trim();

			if(displayname.length == 0) {
				OC.dialogs.alert(t('news', 'Displayname cannot be empty.'), t('news', 'Error'));
				return false;
			}

			$(button).attr("disabled", true);
			//translation here!!!
			$(button).prop('value', 'Adding...');

			var folderid = $('#folder_parentfolder').find(':input[name="folderid"]').val();

			var url;
			url = OC.filePath('news', 'ajax', 'createfolder.php');

			$.post(url, { name: displayname, parentid: folderid },
				function(jsondata){
					if(jsondata.status == 'success'){
						//$(button).closest('tr').prev().html(jsondata.page).show().next().remove();
						OC.dialogs.alert(jsondata.data.message, t('news', 'Success!'));
					} else {
						OC.dialogs.alert(jsondata.data.message, t('news', 'Error'));
					}
					$("#folder_add_name").val('');
					$(button).attr("disabled", false);
					//translation here!!!
					$(button).prop('value', 'Add folder');
			});
		},
		delete:function(folderid) {
			$('#feeds_delete').tipsy('hide');
			OC.dialogs.confirm(t('news', 'Are you sure you want to delete this folder and all its feeds?'), t('news', 'Warning'), function(answer) {
				if(answer == true) {
					$.post(OC.filePath('news', 'ajax', 'deletefolder.php'),{'folderid':folderid},function(jsondata){
						if(jsondata.status == 'success'){
							alert('removed!');
						}
						else{
							OC.dialogs.alert(jsondata.data.message, t('news', 'Error'));
						}
					});
				}
			});
			return false;
		}
	},
	Feed: {
		id:'',
		submit:function(button){
			var feedurl = $("#feed_add_url").val().trim();

			if(feedurl.length == 0) {
				OC.dialogs.alert(t('news', 'URL cannot be empty.'), t('news', 'Error'));
				return false;
			}

			$(button).attr("disabled", true);
			//translation here!!!
			$(button).prop('value', 'Adding...');

			var folderid = $('#feed_parentfolder').find(':input[name="folderid"]').val();

			var url;
			url = OC.filePath('news', 'ajax', 'createfeed.php');

			$.post(url, { feedurl: feedurl, folderid: folderid },
				function(jsondata){
					if(jsondata.status == 'success'){
						OC.dialogs.alert(jsondata.data.message, t('news', 'Success!'));
					} else {
						OC.dialogs.alert(jsondata.data.message, t('news', 'Error'));
					}
				$("#feed_add_url").val('');
				$(button).attr("disabled", false);
				//translation here!!!
				$(button).prop('value', 'Add feed');
			});
		},
		delete:function(feedid) {
			$('#feeds_delete').tipsy('hide');
			OC.dialogs.confirm(t('news', 'Are you sure you want to delete this feed?'), t('news', 'Warning'), function(answer) {
				if(answer == true) {
					$.post(OC.filePath('news', 'ajax', 'deletefeed.php'),{'feedid':feedid},function(jsondata){
						if(jsondata.status == 'success'){
							$('#leftcontent [data-id="'+jsondata.data.feedid+'"]').remove();
							//change the right view too (maybe a message to subscribe, like in Google Reader?)
						}
						else{
							OC.dialogs.alert(jsondata.data.message, t('news', 'Error'));
						}
					});
				}
			});
			return false;
		},
		markItem:function(itemid) {
			$.post(OC.filePath('news', 'ajax', 'markitem.php'),{'itemid':itemid},function(jsondata){
				if(jsondata.status == 'success'){
					var $currentitem = $('#rightcontent [data-id="'+jsondata.data.itemid+'"]');
					$currentitem.removeClass('title_unread');
					$currentitem.addClass('title_read');
					//set a timeout for this
				}
				else{
					OC.dialogs.alert(jsondata.data.message, t('news', 'Error'));
				}
			});
		}
	}
}

$(document).ready(function(){

	$('#addfeed').click(function() {
		News.UI.overview('#addfeed_dialog','feeddialog.php');
	});
	$('#addfolder').click(function() {
		News.UI.overview('#addfolder_dialog','folderdialog.php');
	});

	$('.collapsable').click(function(){
		$(this).parent().children().toggle();
		$(this).toggle();
	});

	$('.accordion .title_unread').click(function() {
		$(this).next().toggle();
		return false;
	}).next().hide();

	$('.accordion .title_read').click(function() {
		$(this).next().toggle();
		return false;
	}).next().hide();

        var list = $('.collapsable,.feeds_list').hover(function() {
                var elem = $(this).find('#feeds_delete,#feeds_edit');
                if(elem.css('display') == 'none')
                        elem.css('display', 'inline');
                else
                        elem.css('display', 'none');

                return false;
        });
        list.find('#feeds_delete').hide();
        list.find('#feeds_edit').hide();
});
<commit_msg>dropdown menu needs to slide up when you select an item.<commit_after>News={
	DropDownMenu: {
		fade:function(button){
			var list = $(button).parent().find('ul#fademenu');
			if (list.css('display') == 'none')
				list.fadeIn();
			else
				list.fadeOut();

			return false;
		},
		dropdown:function(button){
			var list = $(button).parent().find('ul#dropdownmenu');
			if (list.css('display') == 'none')
				list.slideDown('fast').show();
			else
				list.slideUp('fast');

			return false;
		},
		selectItem:function(item, folderid){
			var parent = $(item).parent().parent();
			parent.find('#dropdownBtn').text($(item).text());
			parent.find(':input[name="folderid"]').val(folderid);
			parent.find('ul#dropdownmenu').slideUp('fast');
		}
	},
	UI: {
		overview:function(dialogtype, dialogfile){
		    	if($(dialogtype).dialog('isOpen') == true){
				$(dialogtype).dialog('moveToTop');
			}else{
				$('#dialog_holder').load(OC.filePath('news', 'ajax', dialogfile), function(jsondata){
					if(jsondata.status != 'error'){
						$(dialogtype).dialog({
							dialogClass:'dialog',
							minWidth: 600,
							close: function(event, ui) {
								$(this).dialog('destroy').remove();
							}
						}).css('overflow','visible');
					} else {
						alert(jsondata.data.message);
					}
				});
			}
			return false;
		}
	},
	Folder: {
		submit:function(button){
			var displayname = $("#folder_add_name").val().trim();

			if(displayname.length == 0) {
				OC.dialogs.alert(t('news', 'Displayname cannot be empty.'), t('news', 'Error'));
				return false;
			}

			$(button).attr("disabled", true);
			//translation here!!!
			$(button).prop('value', 'Adding...');

			var folderid = $('#folder_parentfolder').find(':input[name="folderid"]').val();

			var url;
			url = OC.filePath('news', 'ajax', 'createfolder.php');

			$.post(url, { name: displayname, parentid: folderid },
				function(jsondata){
					if(jsondata.status == 'success'){
						//$(button).closest('tr').prev().html(jsondata.page).show().next().remove();
						OC.dialogs.alert(jsondata.data.message, t('news', 'Success!'));
					} else {
						OC.dialogs.alert(jsondata.data.message, t('news', 'Error'));
					}
					$("#folder_add_name").val('');
					$(button).attr("disabled", false);
					//translation here!!!
					$(button).prop('value', 'Add folder');
			});
		},
		delete:function(folderid) {
			$('#feeds_delete').tipsy('hide');
			OC.dialogs.confirm(t('news', 'Are you sure you want to delete this folder and all its feeds?'), t('news', 'Warning'), function(answer) {
				if(answer == true) {
					$.post(OC.filePath('news', 'ajax', 'deletefolder.php'),{'folderid':folderid},function(jsondata){
						if(jsondata.status == 'success'){
							alert('removed!');
						}
						else{
							OC.dialogs.alert(jsondata.data.message, t('news', 'Error'));
						}
					});
				}
			});
			return false;
		}
	},
	Feed: {
		id:'',
		submit:function(button){
			var feedurl = $("#feed_add_url").val().trim();

			if(feedurl.length == 0) {
				OC.dialogs.alert(t('news', 'URL cannot be empty.'), t('news', 'Error'));
				return false;
			}

			$(button).attr("disabled", true);
			//translation here!!!
			$(button).prop('value', 'Adding...');

			var folderid = $('#feed_parentfolder').find(':input[name="folderid"]').val();

			var url;
			url = OC.filePath('news', 'ajax', 'createfeed.php');

			$.post(url, { feedurl: feedurl, folderid: folderid },
				function(jsondata){
					if(jsondata.status == 'success'){
						OC.dialogs.alert(jsondata.data.message, t('news', 'Success!'));
					} else {
						OC.dialogs.alert(jsondata.data.message, t('news', 'Error'));
					}
				$("#feed_add_url").val('');
				$(button).attr("disabled", false);
				//translation here!!!
				$(button).prop('value', 'Add feed');
			});
		},
		delete:function(feedid) {
			$('#feeds_delete').tipsy('hide');
			OC.dialogs.confirm(t('news', 'Are you sure you want to delete this feed?'), t('news', 'Warning'), function(answer) {
				if(answer == true) {
					$.post(OC.filePath('news', 'ajax', 'deletefeed.php'),{'feedid':feedid},function(jsondata){
						if(jsondata.status == 'success'){
							$('#leftcontent [data-id="'+jsondata.data.feedid+'"]').remove();
							//change the right view too (maybe a message to subscribe, like in Google Reader?)
						}
						else{
							OC.dialogs.alert(jsondata.data.message, t('news', 'Error'));
						}
					});
				}
			});
			return false;
		},
		markItem:function(itemid) {
			$.post(OC.filePath('news', 'ajax', 'markitem.php'),{'itemid':itemid},function(jsondata){
				if(jsondata.status == 'success'){
					var $currentitem = $('#rightcontent [data-id="'+jsondata.data.itemid+'"]');
					$currentitem.removeClass('title_unread');
					$currentitem.addClass('title_read');
					//set a timeout for this
				}
				else{
					OC.dialogs.alert(jsondata.data.message, t('news', 'Error'));
				}
			});
		}
	}
}

$(document).ready(function(){

	$('#addfeed').click(function() {
		News.UI.overview('#addfeed_dialog','feeddialog.php');
	});
	$('#addfolder').click(function() {
		News.UI.overview('#addfolder_dialog','folderdialog.php');
	});

	$('.collapsable').click(function(){
		$(this).parent().children().toggle();
		$(this).toggle();
	});

	$('.accordion .title_unread').click(function() {
		$(this).next().toggle();
		return false;
	}).next().hide();

	$('.accordion .title_read').click(function() {
		$(this).next().toggle();
		return false;
	}).next().hide();

        var list = $('.collapsable,.feeds_list').hover(function() {
                var elem = $(this).find('#feeds_delete,#feeds_edit');
                if(elem.css('display') == 'none')
                        elem.css('display', 'inline');
                else
                        elem.css('display', 'none');

                return false;
        });
        list.find('#feeds_delete').hide();
        list.find('#feeds_edit').hide();
});
<|endoftext|>


<commit_before>'use strict';

var async = require('async'),
    glob = require('glob'),
    path = require('path'),
    fs = require('fs'),
    _ = require('underscore'),
    changeDetector = require('./utils/changeDetector'),
    providedLayouts = {
        'diagonal': require('./layout/diagonal'),
        'horizontal': require('./layout/horizontal'),
        'vertical': require('./layout/vertical')
    },
    providedCompositors = {},
    providedStylesheets = {
        'css': require('./stylesheet/css'),
        'stylus': require('./stylesheet/stylus'),
        'less': require('./stylesheet/less')
    },
    defaults = {
        src: [],
        spritePath: '',
        stylesheetPath: '',
        layout: 'vertical',
        stylesheet: 'stylus',
        compositor: 'canvas',
        layoutOptions: {},
        compositorOptions: {},
        stylesheetOptions: {}
    };

try {
    providedCompositors.canvas = require('./compositor/canvas');
} catch (e) {
    defaults.compositor = 'gm';
}
try {
    providedCompositors.gm = require('./compositor/gm');
} catch (e) {}

function generateSprite(options, callback) {
    var layout,
        stylesheet,
        compositor,
        generatedLayout;

    options = options || {};

    options = _.extend({}, defaults, options);

    // require the files if they are provided as strings
    layout = _.isString(options.layout) ? providedLayouts[options.layout] : options.layout;
    compositor = _.isString(options.compositor) ? providedCompositors[options.compositor] : options.compositor;
    stylesheet = _.isString(options.stylesheet) ? providedStylesheets[options.stylesheet] : options.stylesheet;

    if (!compositor) {
        return callback(new Error('Either you defined a bad compositor or you dont have the correct dependencies installed.'));
    }

    // do glob pattern matching
    async.map(options.src, glob, function (err, fileNames) {
        if (err) {
            callback(err);
            return;
        }

        // filter duplicates from glob pattern matching
        fileNames = _(fileNames).chain().flatten().uniq().value();

        async.waterfall([
            function (callback) {
                compositor.readImages(fileNames, callback);
            },
            function (images, callback) {
                layout(images, options.layoutOptions, callback);
            },
            function (newLayout, callback) {
                // store layout so it can be used for stylesheet generation
                generatedLayout = newLayout;
                compositor.render(generatedLayout, options.spritePath, options.outputOptions, callback);
            },
            function (callback) {
                stylesheet(generatedLayout, options.stylesheetPath, options.spritePath, options.stylesheetOptions, callback);
            }
        ], function (err) {
            if (callback) {
                callback(err);
            }
        });
    });
}

generateSprite.middleware = function (options) {
    var changes = changeDetector(options);

    return function (req, res, next) {
        changes.detect(function (err, changesDetected) {
            if (changesDetected) {
                generateSprite(options, function () {
                    changes.register(function () {
                        return next(err);
                    });
                });
            } else {
                return next();
            }
        });
    };
};

module.exports = generateSprite;<commit_msg>Fixed: compositor options were not being passed to the compositor.<commit_after>'use strict';

var async = require('async'),
    glob = require('glob'),
    path = require('path'),
    fs = require('fs'),
    _ = require('underscore'),
    changeDetector = require('./utils/changeDetector'),
    providedLayouts = {
        'diagonal': require('./layout/diagonal'),
        'horizontal': require('./layout/horizontal'),
        'vertical': require('./layout/vertical')
    },
    providedCompositors = {},
    providedStylesheets = {
        'css': require('./stylesheet/css'),
        'stylus': require('./stylesheet/stylus'),
        'less': require('./stylesheet/less')
    },
    defaults = {
        src: [],
        spritePath: '',
        stylesheetPath: '',
        layout: 'vertical',
        stylesheet: 'stylus',
        compositor: 'canvas',
        layoutOptions: {},
        compositorOptions: {},
        stylesheetOptions: {}
    };

try {
    providedCompositors.canvas = require('./compositor/canvas');
} catch (e) {
    defaults.compositor = 'gm';
}
try {
    providedCompositors.gm = require('./compositor/gm');
} catch (e) {}

function generateSprite(options, callback) {
    var layout,
        stylesheet,
        compositor,
        generatedLayout;

    options = options || {};

    options = _.extend({}, defaults, options);

    // require the files if they are provided as strings
    layout = _.isString(options.layout) ? providedLayouts[options.layout] : options.layout;
    compositor = _.isString(options.compositor) ? providedCompositors[options.compositor] : options.compositor;
    stylesheet = _.isString(options.stylesheet) ? providedStylesheets[options.stylesheet] : options.stylesheet;

    if (!compositor) {
        return callback(new Error('Either you defined a bad compositor or you dont have the correct dependencies installed.'));
    }

    // do glob pattern matching
    async.map(options.src, glob, function (err, fileNames) {
        if (err) {
            callback(err);
            return;
        }

        // filter duplicates from glob pattern matching
        fileNames = _(fileNames).chain().flatten().uniq().value();

        async.waterfall([
            function (callback) {
                compositor.readImages(fileNames, callback);
            },
            function (images, callback) {
                layout(images, options.layoutOptions, callback);
            },
            function (newLayout, callback) {
                // store layout so it can be used for stylesheet generation
                generatedLayout = newLayout;
                compositor.render(generatedLayout, options.spritePath, options.compositorOptions, callback);
            },
            function (callback) {
                stylesheet(generatedLayout, options.stylesheetPath, options.spritePath, options.stylesheetOptions, callback);
            }
        ], function (err) {
            if (callback) {
                callback(err);
            }
        });
    });
}

generateSprite.middleware = function (options) {
    var changes = changeDetector(options);

    return function (req, res, next) {
        changes.detect(function (err, changesDetected) {
            if (changesDetected) {
                generateSprite(options, function () {
                    changes.register(function () {
                        return next(err);
                    });
                });
            } else {
                return next();
            }
        });
    };
};

module.exports = generateSprite;<|endoftext|>


<commit_before>var files = [];
var curidx = 0;

var msgs = ['', '', '', '', ''];

function set_msg(str) {
    msgs[0] = msgs[1];
    msgs[1] = msgs[2];
    msgs[2] = msgs[3];
    msgs[3] = msgs[4];
    msgs[4] = str;
    document.getElementById('msg1').firstChild.nodeValue = msgs[0];
    document.getElementById('msg2').firstChild.nodeValue = msgs[1];
    document.getElementById('msg3').firstChild.nodeValue = msgs[2];
    document.getElementById('msg4').firstChild.nodeValue = msgs[3];
    document.getElementById('msg5').firstChild.nodeValue = msgs[4];
}

var storage = navigator.getDeviceStorage('music');
var cursor = storage.enumerate();
cursor.onsuccess = function() {
    if (this.result) {
	var file = this.result;
	// set_msg(file.name);
	files.push(file);
	this.continue();
    } else {
	set_msg('done.');
	curidx = 0;
	play_cur();
    }
}
cursor.onerror = function() {
    document.write('error.');
}

function play() {
    var audio = document.getElementById('audio');
    audio.play();
}

function play_cur() {
    var audio = document.getElementById('audio');
    set_msg('' + audio);
    audio.src = window.URL.createObjectURL(files[curidx]);
    set_msg('' + audio.src);
    audio.play();
    audio.addEventListener('ended', play_next);
}

function play_next() {
    if (++curidx >= files.length)
	curidx = 0;
    play_cur();
}

function pause() {
set_msg('stop1');
    var audio = document.getElementById('audio');
set_msg('stop2');
    audio.pause();
set_msg('stop3');
}

var radio = navigator.mozFMRadio;

function play_or_stop() {
set_msg('r1');
    if (radio.antennaAvailable) {
set_msg('r2');
	play_cur();
set_msg('r3');
    } else {
set_msg('r4');
	pause();
set_msg('r5');
    }
}

radio.addEventListener('antennaavailablechange', play_or_stop);

/*
function a(obj)
{
    set_msg('a: ' + obj);
}

// navigator.mozSetMessageHandler('bluetooth-pairedstatuschanged', a);
// navigator.mozSetMessageHandler('headset-button', a);
// navigator.mozSetMessageHandler('notification', a);
*/

function play_on_click(id) {
    var mid = id;
    return function() {
	curidx = mid;
	play_cur();
    }
}

/*
 * ul:
ノード
 * prefix: /.../ の文字列
 * idx: files[idx]
 */

function make_select_screen_iter(ul, prefix, idx)
{
    set_msg('make_select_screen_iter: 0');
    while (idx < files.length) {
	set_msg('make_select_screen_iter: idx=' + idx);

	if (files[idx].name.lastIndexOf(prefix, 0) != 0)	// if startsWith(prefix)
	    return idx;
	set_msg('make_select_screen_iter: prefix matches.');

	var slash = files[idx].name.indexOf('/', prefix.length);
	set_msg('make_select_screen_iter: slash=' + slash);
	if (slash == -1) {
	    // これ以上 '/' がない。
	    set_msg('make_select_screen_iter: 1');

	    var li = document.createElement("li");
	    ul.appendChild(li);

	    var a = document.createElement("a");
	    li.appendChild(a);
	    a.addEventListener('click', play_on_click(idx));

	    var fname = document.createTextNode(files[idx].name.substring(prefix.length));
	    a.appendChild(fname);

	    var br1 = document.createElement("br");
	    a.appendChild(br1);

	    var title = document.createTextNode('title');
	    a.appendChild(title);

	    var br2 = document.createElement("br");
	    a.appendChild(br2);

	    var artist = document.createTextNode('artist');
	    a.appendChild(artist);

	    idx++;
	    set_msg('make_select_screen_iter: 2');
	} else {
	    // '/' を発見。
	    set_msg('make_select_screen_iter: 3');

	    var new_pfx = files[idx].name.substring(0, slash + 1);

	    var li = document.createElement("li");
	    ul.appendChild(li);

	    var txt = document.createTextNode(files[idx].name.slice(prefix.length, new_pfx.length - 1));
	    li.appendChild(txt);

	    var new_ul = document.createElement("ul");
	    ul.appendChild(new_ul);
	    idx = make_select_screen_iter(new_ul, new_pfx, idx);
	    set_msg('make_select_screen_iter: 4');
	}
	set_msg('make_select_screen_iter: 5');
    }
}

function make_select_screen() {
    set_msg('make_select_screen: start.');
    var ul = document.getElementsByTagName("ul")[0];
    make_select_screen_iter(ul, '/sdcard/Music/', 0);
    set_msg('make_select_screen: done.');
}

window.onload = function() {
    set_msg('a2dp set 1');
    var bt = window.navigator.mozBluetooth;
    set_msg('a2dp set 2 ' + bt);
    var r = bt.getDefaultAdapter();
    set_msg('a2dp set 3');
    r.onsuccess = function() {
	set_msg('a2dp. success.1');
	// 反応する時としない時がある。条件不明。
	this.result.addEventListener('a2dpstatuschanged', function(ev) {
	    set_msg('a2dp: ' + ev.address + ', ' + ev.status);
	    if (ev.status) {
		play();
	    } else {
		pause();
	    }
	    return true;
	});
	this.result.addEventListener('devicefound', function(o) {
	    set_msg('dev found: ' + o);
	    return true;
	});
	this.result.addEventListener('hfpstatuschanged', function(o) {
	    set_msg('hfp: ' + o);
	    return true;
	});
	this.result.addEventListener('pairedstatuschanged', function(o) {
	    set_msg('pair: ' + o);
	    return true;
	});
	this.result.addEventListener('requestmediaplaystatus', function(o) {
	    set_msg('media: ' + o);
	    return true;
	});
	this.result.addEventListener('scostatuschanged', function(o) {
	    set_msg('sco: ' + o);
	    return true;
	});
	set_msg('a2dp. success.4');
    };
    set_msg('a2dp set 4');
    r.onerror = function() {
	set_msg('a2dp. error');
    };
    set_msg('a2dp set 5');

    set_msg('onload4');
    var sel = document.getElementById('select')
    set_msg('onload5');
    sel.addEventListener('click', make_select_screen, false);
    set_msg('onload6');
};
<commit_msg>ファイル名をソート。<commit_after>var files = [];
var curidx = 0;

var msgs = ['', '', '', '', ''];

function set_msg(str) {
    msgs[0] = msgs[1];
    msgs[1] = msgs[2];
    msgs[2] = msgs[3];
    msgs[3] = msgs[4];
    msgs[4] = str;
    document.getElementById('msg1').firstChild.nodeValue = msgs[0];
    document.getElementById('msg2').firstChild.nodeValue = msgs[1];
    document.getElementById('msg3').firstChild.nodeValue = msgs[2];
    document.getElementById('msg4').firstChild.nodeValue = msgs[3];
    document.getElementById('msg5').firstChild.nodeValue = msgs[4];
}

function cmp_files(f1, f2) {
    if (f1.name < f2.name)
	return -1;
    if (f1.name > f2.name)
	return 1;
    return 0;
}

var storage = navigator.getDeviceStorage('music');
var cursor = storage.enumerate();
cursor.onsuccess = function() {
    if (this.result) {
	var file = this.result;
	// set_msg(file.name);
	files.push(file);
	this.continue();
    } else {
	set_msg('sort');
	files.sort(cmp_files);
	set_msg('done.');
	curidx = 0;
	play_cur();
    }
}
cursor.onerror = function() {
    document.write('error.');
}

function play() {
    var audio = document.getElementById('audio');
    audio.play();
}

function play_cur() {
    var audio = document.getElementById('audio');
    set_msg('' + audio);
    audio.src = window.URL.createObjectURL(files[curidx]);
    set_msg('' + audio.src);
    audio.play();
    audio.addEventListener('ended', play_next);
}

function play_next() {
    if (++curidx >= files.length)
	curidx = 0;
    play_cur();
}

function pause() {
set_msg('stop1');
    var audio = document.getElementById('audio');
set_msg('stop2');
    audio.pause();
set_msg('stop3');
}

var radio = navigator.mozFMRadio;

function play_or_stop() {
set_msg('r1');
    if (radio.antennaAvailable) {
set_msg('r2');
	play_cur();
set_msg('r3');
    } else {
set_msg('r4');
	pause();
set_msg('r5');
    }
}

radio.addEventListener('antennaavailablechange', play_or_stop);

/*
function a(obj)
{
    set_msg('a: ' + obj);
}

// navigator.mozSetMessageHandler('bluetooth-pairedstatuschanged', a);
// navigator.mozSetMessageHandler('headset-button', a);
// navigator.mozSetMessageHandler('notification', a);
*/

function play_on_click(id) {
    var mid = id;
    return function() {
	curidx = mid;
	play_cur();
    }
}

/*
 * ul:
ノード
 * prefix: /.../ の文字列
 * idx: files[idx]
 */

function make_select_screen_iter(ul, prefix, idx)
{
    set_msg('make_select_screen_iter: 0');
    while (idx < files.length) {
	set_msg('make_select_screen_iter: idx=' + idx);

	if (files[idx].name.lastIndexOf(prefix, 0) != 0)	// if startsWith(prefix)
	    return idx;
	set_msg('make_select_screen_iter: prefix matches.');

	var slash = files[idx].name.indexOf('/', prefix.length);
	set_msg('make_select_screen_iter: slash=' + slash);
	if (slash == -1) {
	    // これ以上 '/' がない。
	    set_msg('make_select_screen_iter: 1');

	    var li = document.createElement("li");
	    ul.appendChild(li);

	    var a = document.createElement("a");
	    li.appendChild(a);
	    a.addEventListener('click', play_on_click(idx));

	    var fname = document.createTextNode(files[idx].name.substring(prefix.length));
	    a.appendChild(fname);

	    var br1 = document.createElement("br");
	    a.appendChild(br1);

	    var title = document.createTextNode('title');
	    a.appendChild(title);

	    var br2 = document.createElement("br");
	    a.appendChild(br2);

	    var artist = document.createTextNode('artist');
	    a.appendChild(artist);

	    idx++;
	    set_msg('make_select_screen_iter: 2');
	} else {
	    // '/' を発見。
	    set_msg('make_select_screen_iter: 3');

	    var new_pfx = files[idx].name.substring(0, slash + 1);

	    var li = document.createElement("li");
	    ul.appendChild(li);

	    var txt = document.createTextNode(files[idx].name.slice(prefix.length, new_pfx.length - 1));
	    li.appendChild(txt);

	    var new_ul = document.createElement("ul");
	    ul.appendChild(new_ul);
	    idx = make_select_screen_iter(new_ul, new_pfx, idx);
	    set_msg('make_select_screen_iter: 4');
	}
	set_msg('make_select_screen_iter: 5');
    }
}

function make_select_screen() {
    set_msg('make_select_screen: start.');
    var ul = document.getElementsByTagName("ul")[0];
    make_select_screen_iter(ul, '/sdcard/Music/', 0);
    set_msg('make_select_screen: done.');
}

window.onload = function() {
    set_msg('a2dp set 1');
    var bt = window.navigator.mozBluetooth;
    set_msg('a2dp set 2 ' + bt);
    var r = bt.getDefaultAdapter();
    set_msg('a2dp set 3');
    r.onsuccess = function() {
	set_msg('a2dp. success.1');
	// 反応する時としない時がある。条件不明。
	this.result.addEventListener('a2dpstatuschanged', function(ev) {
	    set_msg('a2dp: ' + ev.address + ', ' + ev.status);
	    if (ev.status) {
		play();
	    } else {
		pause();
	    }
	    return true;
	});
	this.result.addEventListener('devicefound', function(o) {
	    set_msg('dev found: ' + o);
	    return true;
	});
	this.result.addEventListener('hfpstatuschanged', function(o) {
	    set_msg('hfp: ' + o);
	    return true;
	});
	this.result.addEventListener('pairedstatuschanged', function(o) {
	    set_msg('pair: ' + o);
	    return true;
	});
	this.result.addEventListener('requestmediaplaystatus', function(o) {
	    set_msg('media: ' + o);
	    return true;
	});
	this.result.addEventListener('scostatuschanged', function(o) {
	    set_msg('sco: ' + o);
	    return true;
	});
	set_msg('a2dp. success.4');
    };
    set_msg('a2dp set 4');
    r.onerror = function() {
	set_msg('a2dp. error');
    };
    set_msg('a2dp set 5');

    set_msg('onload4');
    var sel = document.getElementById('select')
    set_msg('onload5');
    sel.addEventListener('click', make_select_screen, false);
    set_msg('onload6');
};
<|endoftext|>


<commit_before>"use strict";
(function() {
  var baseURL = "https://dl.dropboxusercontent.com/s/";
  var chapterInfo = [{},
    {
      "number": "1",
      "title": "One Punch",
      "extension": "jpg",
      "pages": ["",
        "cadz9o1zrnftgjd/OPM_1_01.jpg",
        "tm10u82i6fisd8c/OPM_1_02-03.jpg",
        "dnccp9idmwlbj82/OPM_1_04.jpg",
        "1ppjf2cdj708zku/OPM_1_05.jpg",
        "q46jiur8xkmtrxv/OPM_1_06.jpg",
        "yf2ch4b9m9pxtyp/OPM_1_07.jpg",
        "b8n0t27zf0ruzt7/OPM_1_08.jpg",
        "efcfbrw4jzglpyz/OPM_1_09.jpg",
        "gtowm1j5qrtbgm5/OPM_1_10.jpg",
        "r4ajxgkmfzr0xa3/OPM_1_11.jpg",
        "a6znj0s5zsp5we4/OPM_1_12.jpg",
        "trzmatbr9s1rpdm/OPM_1_13.jpg",
        "xm05vuha9g3mdo6/OPM_1_14-15.jpg",
        "ng0x19z2r740hf5/OPM_1_16.jpg",
        "41yx5va4bwyk9i4/OPM_1_17.jpg",
        "d1pc2ruexmo8box/OPM_1_18-19.jpg",
        "98rx0erbl7boqnh/OPM_1_20-21.jpg",
        "9gsjxzy85na9h0q/OPM_1_22.jpg"
      ]
    }
  ]

  var lastChapter = chapterInfo.length - 1;

  var currentChapter = -1;
  var currentTitle = "";
  var currentNumber = "";
  var currentPage = -1;
  var chapterSize = -1;
  var currentExtension = "";

  var imageElement = null;
  var loadingElement = null;
  var leftElement = null;
  var rightElement = null;

  function switchChapter(chapterIndex) {
    currentChapter = chapterIndex;
    currentExtension = "." + chapterInfo[currentChapter].extension;
    currentTitle = chapterInfo[currentChapter].title;
    currentNumber = chapterInfo[currentChapter].number;
    chapterSize = chapterInfo[currentChapter].pages.length - 1;
    loadPage(1);
  }

  function loadPage(pageIndex) {
    startLoading();
    currentPage = pageIndex;
    document.title = seriesTitle + "Ch " + currentNumber + ": " + currentTitle + " p" + currentPage;
    var newURL = baseURL + chapterInfo[currentChapter].pages[currentPage];
    if (currentPage < 2 && currentChapter < 2) {
      leftElement.className = "side";
    }
    else {
      leftElement.className = "side hand";
    }
    if (currentPage >= chapterSize && currentChapter >= lastChapter) {
      rightElement.className = "side";
    }
    else {
      rightElement.className = "side hand";
    }
    loadingElement.innerHTML = "Loading... 0.00%";
    var xhr = new XMLHttpRequest();
    xhr.open("GET", newURL);
    xhr.responseType = "arraybuffer";
    xhr.onprogress = function(data) {
      var percentDisplay = (data.loaded / data.total * 100).toFixed(2);
      loadingElement.innerHTML = "Loading..." + percentDisplay + "%";
    };
    xhr.onload = function(data) {
      loadingElement.innerHTML = "Loading... 100.00%";
      var blob = new Blob([this.response], {type: "image/" + currentExtension});
      imageElement.src = window.URL.createObjectURL(blob);
    };
    xhr.send();
  }

  function startLoading() {
    loadingElement.className = "";
  }

  function stopLoading() {
    imageElement.className = "";
    loadingElement.className = "hidden";
  }

  function pageBack() {
    if (currentPage < 2) {
      if (currentChapter > 1) {
        switchChapter(currentChapter - 1);
      }
    }
    else {
      loadPage(currentPage - 1);
    }
  }

  function pageForward() {
    if (currentPage >= chapterSize) {
      if (currentChapter < lastChapter) {
        switchChapter(currentChapter + 1);
      }
    }
    else {
      loadPage(currentPage + 1);
    }
  }

  function keyCheck(e) {
    if (e.keyCode === 37) { // Left Arrow
      pageBack();
    }
    else if (e.keyCode === 39) { // Right Arrow
      pageForward();
    }
  }

  function setup() {
    document.removeEventListener("DOMContentLoaded", setup);
    imageElement = document.getElementById("image");
    loadingElement = document.getElementById("loading");
    leftElement = document.getElementById("left")
    rightElement = document.getElementById("right");
    leftElement.addEventListener("click", pageBack);
    rightElement.addEventListener("click", pageForward);
    imageElement.addEventListener("load", stopLoading);
    document.addEventListener("keydown", keyCheck);
    switchChapter(1);
  }

  document.addEventListener("DOMContentLoaded", setup);
  var seriesTitle = "One-Punch Man";
  document.title = seriesTitle;
}).call(this);
<commit_msg>Update read.js<commit_after>"use strict";
(function() {
  var baseURL = "https://dl.dropboxusercontent.com/s/";
  var chapterInfo = [{},
    {
      "number": "1",
      "title": "One Punch",
      "extension": "jpg",
      "pages": ["",
        "cadz9o1zrnftgjd/OPM_1_01.jpg",
        "tm10u82i6fisd8c/OPM_1_02-03.jpg",
        "dnccp9idmwlbj82/OPM_1_04.jpg",
        "1ppjf2cdj708zku/OPM_1_05.jpg",
        "q46jiur8xkmtrxv/OPM_1_06.jpg",
        "yf2ch4b9m9pxtyp/OPM_1_07.jpg",
        "b8n0t27zf0ruzt7/OPM_1_08.jpg",
        "efcfbrw4jzglpyz/OPM_1_09.jpg",
        "gtowm1j5qrtbgm5/OPM_1_10.jpg",
        "r4ajxgkmfzr0xa3/OPM_1_11.jpg",
        "a6znj0s5zsp5we4/OPM_1_12.jpg",
        "trzmatbr9s1rpdm/OPM_1_13.jpg",
        "xm05vuha9g3mdo6/OPM_1_14-15.jpg",
        "ng0x19z2r740hf5/OPM_1_16.jpg",
        "41yx5va4bwyk9i4/OPM_1_17.jpg",
        "d1pc2ruexmo8box/OPM_1_18-19.jpg",
        "98rx0erbl7boqnh/OPM_1_20-21.jpg",
        "9gsjxzy85na9h0q/OPM_1_22.jpg"
      ]
    }
  ]

  var lastChapter = chapterInfo.length - 1;

  var currentChapter = -1;
  var currentTitle = "";
  var currentNumber = "";
  var currentPage = -1;
  var chapterSize = -1;
  var currentExtension = "";

  var imageElement = null;
  var loadingElement = null;
  var leftElement = null;
  var rightElement = null;

  function switchChapter(chapterIndex, pageIndex) {
    currentChapter = chapterIndex;
    currentExtension = "." + chapterInfo[currentChapter].extension;
    currentTitle = chapterInfo[currentChapter].title;
    currentNumber = chapterInfo[currentChapter].number;
    chapterSize = chapterInfo[currentChapter].pages.length - 1;
    loadPage(pageIndex > 0 ? pageIndex : 1); // handles not-passed case too becuase lol Javascript
  }

  function loadPage(pageIndex) {
    startLoading();
    currentPage = pageIndex;
    document.title = seriesTitle + " Ch " + currentNumber + ": " + currentTitle + " p" + currentPage;
    setFragment();
    var newURL = baseURL + chapterInfo[currentChapter].pages[currentPage];
    if (currentPage < 2 && currentChapter < 2) {
      leftElement.className = "side";
    }
    else {
      leftElement.className = "side hand";
    }
    if (currentPage >= chapterSize && currentChapter >= lastChapter) {
      rightElement.className = "side";
    }
    else {
      rightElement.className = "side hand";
    }
    loadingElement.innerHTML = "Loading... 0.00%";
    var xhr = new XMLHttpRequest();
    xhr.open("GET", newURL);
    xhr.responseType = "arraybuffer";
    xhr.onprogress = function(data) {
      var percentDisplay = (data.loaded / data.total * 100).toFixed(2);
      loadingElement.innerHTML = "Loading..." + percentDisplay + "%";
    };
    xhr.onload = function(data) {
      loadingElement.innerHTML = "Loading... 100.00%";
      var blob = new Blob([this.response], {type: "image/" + currentExtension});
      imageElement.src = window.URL.createObjectURL(blob);
    };
    xhr.send();
  }

  function startLoading() {
    loadingElement.className = "";
  }

  function stopLoading() {
    imageElement.className = "";
    loadingElement.className = "hidden";
  }

  function pageBack() {
    if (currentPage < 2) {
      if (currentChapter > 1) {
        switchChapter(currentChapter - 1);
      }
    }
    else {
      loadPage(currentPage - 1);
    }
  }

  function pageForward() {
    if (currentPage >= chapterSize) {
      if (currentChapter < lastChapter) {
        switchChapter(currentChapter + 1);
      }
    }
    else {
      loadPage(currentPage + 1);
    }
  }

  function keyCheck(e) {
    if (e.keyCode === 37) { // Left Arrow
      pageBack();
    }
    else if (e.keyCode === 39) { // Right Arrow
      pageForward();
    }
  }

  function setFragment() {
    window.location.hash = currentChapter + "," + currentPage;
  }

  function parseFragment() {
    var split = window.location.hash.split("#")[1].split(",");
    var chapterIndex = split[0] ? split[0] : 1;
    var pageIndex = split[1] ? split[1] : 1;
    switchChpater(chapterIndex, pageIndex);
  }

  function setup() {
    document.removeEventListener("DOMContentLoaded", setup);
    imageElement = document.getElementById("image");
    loadingElement = document.getElementById("loading");
    leftElement = document.getElementById("left")
    rightElement = document.getElementById("right");
    leftElement.addEventListener("click", pageBack);
    rightElement.addEventListener("click", pageForward);
    imageElement.addEventListener("load", stopLoading);
    document.addEventListener("keydown", keyCheck);
    if (window.location.hash === "") {
      switchChapter(1);
    }
    else {
      parseFragment();
    }
  }

  document.addEventListener("DOMContentLoaded", setup);
  var seriesTitle = "One-Punch Man";
  document.title = seriesTitle;
}).call(this);
<|endoftext|>


<commit_before>/**
 * pty.js
 * Copyright (c) 2012, Christopher Jeffrey (MIT License)
 * Binding to the pseudo terminals.
 */

var net = require('net');
var pty = require('../build/Release/pty.node');

/**
 * Terminal
 */

// Example:
//  var term = new Terminal('bash', [], {
//    name: 'xterm-color',
//    cols: 80,
//    rows: 30,
//    cwd: process.env.HOME,
//    env: process.env
//  });

function Terminal(file, args, opt) {
  if (!(this instanceof Terminal)) {
    return new Terminal(file, args, opt);
  }

  var self = this
    , env
    , cwd
    , name
    , cols
    , rows
    , term;

  // backward compatibility
  if (typeof args === 'string') {
    opt = {
      name: arguments[1],
      cols: arguments[2],
      rows: arguments[3],
      cwd: process.env.HOME
    };
    args = [];
  }

  // arguments
  args = args || [];
  file = file || 'sh';
  opt = opt || {};

  cols = opt.cols || 80;
  rows = opt.rows || 30;
  env = clone(opt.env || process.env);
  cwd = opt.cwd || process.cwd();
  name = opt.name || env.TERM || 'xterm';

  env.TERM = name;
  env = environ(env);

  // fork
  term = pty.fork(file, args, env, cwd, cols, rows);
  this.socket = new net.Socket(term.fd);
  this.socket.setEncoding('utf8');
  this.socket.resume();

  // setup
  this.socket.on('error', function(err) {
    // close
    self._close();

    // EIO, happens when someone closes our child
    // process: the only process in the terminal.
    if (err.code && ~err.code.indexOf('errno 5')) return;

    // node >= 0.6.14 ?
    if (err.code && ~err.code.indexOf('read EIO')) return;
    if (err.code && ~err.code.indexOf('EIO')) return;

    // throw anything else
    if (self.listeners('error').length < 2) {
      throw err;
    }
  });

  this.pid = term.pid;
  this.fd = term.fd;
  this.pty = term.pty;

  this.file = file;
  this.name = name;
  this.cols = cols;
  this.rows = rows;

  this.readable = true;
  this.writable = true;

  Terminal.total++;
  this.socket.on('close', function() {
    Terminal.total--;
    self._close();
    self.emit('exit', null);
  });

  env = null;
}

Terminal.fork =
Terminal.spawn =
Terminal.createTerminal = function(file, args, opt) {
  return new Terminal(file, args, opt);
};

/**
 * openpty
 */

Terminal.open = function(opt) {
  var self = Object.create(Terminal.prototype)
    , opt = opt || {};

  if (arguments.length > 1) {
    opt = {
      cols: arguments[1],
      rows: arguments[2]
    };
  }

  var cols = opt.cols || 80
    , rows = opt.rows || 30
    , term;

  // open
  term = pty.open(cols, rows);

  self.master = new net.Socket(term.master);
  self.master.setEncoding('utf8');
  self.master.resume();

  self.slave = new net.Socket(term.slave);
  self.slave.setEncoding('utf8');
  self.slave.resume();

  self.socket = self.master;
  self.pid = null;
  self.fd = term.master;
  self.pty = term.pty;

  self.file = process.argv[0] || 'node';
  self.name = process.env.TERM || '';
  self.cols = cols;
  self.rows = rows;

  self.readable = true;
  self.writable = true;

  self.socket.on('error', function(err) {
    self._close();
    if (self.listeners('error').length < 2) {
      throw err;
    }
  });

  Terminal.total++;
  self.socket.on('close', function() {
    Terminal.total--;
    self._close();
  });

  return self;
};

/**
 * Total
 */

// Keep track of the total
// number of terminals for
// the process.
Terminal.total = 0;

/**
 * Events
 */

// Don't inherit from net.Socket in
// order to avoid collisions.

Terminal.prototype.write = function(data) {
  return this.socket.write(data);
};

Terminal.prototype.end = function(data) {
  return this.socket.end(data);
};

Terminal.prototype.pipe = function(dest, options) {
  return this.socket.pipe(dest, options);
};

Terminal.prototype.pause = function() {
  this.socket.pause();
};

Terminal.prototype.resume = function() {
  this.socket.resume();
};

Terminal.prototype.setEncoding = function(enc) {
  if (this.socket._decoder) {
    delete this.socket._decoder;
  }
  if (enc) {
    this.socket.setEncoding(enc);
  }
};

Terminal.prototype.addListener =
Terminal.prototype.on = function(type, func) {
  this.socket.on(type, func);
  return this;
};

Terminal.prototype.emit = function() {
  return this.socket.emit.apply(this.socket, arguments);
};

Terminal.prototype.listeners = function(type) {
  return this.socket.listeners(type);
};

Terminal.prototype.removeListener = function(type, func) {
  this.socket.removeListener(type, func);
  return this;
};

Terminal.prototype.removeAllListeners = function(type) {
  this.socket.removeAllListeners(type);
  return this;
};

Terminal.prototype.once = function(type, func) {
  this.socket.once(type, func);
  return this;
};

Terminal.prototype.__defineGetter__('stdin', function() {
  return this;
});

Terminal.prototype.__defineGetter__('stdout', function() {
  return this;
});

Terminal.prototype.__defineGetter__('stderr', function() {
  throw new Error('No stderr.');
});

/**
 * TTY
 */

Terminal.prototype.resize = function(cols, rows) {
  cols = cols || 80;
  rows = rows || 30;

  this.cols = cols;
  this.rows = rows;

  pty.resize(this.fd, cols, rows);
};

Terminal.prototype.destroy = function() {
  var self = this;

  // close
  this._close();

  // Need to close the read stream so
  // node stops reading a dead file descriptor.
  // Then we can safely SIGTERM the shell.
  this.socket.once('close', function() {
    self.kill('SIGTERM');
  });

  this.socket.destroy();
};

Terminal.prototype.kill = function(sig) {
  try {
    process.kill(this.pid, sig || 'SIGTERM');
  } catch(e) {
    ;
  }
};

Terminal.prototype.__defineGetter__('process', function() {
  return pty.process(this.fd, this.pty) || this.file;
});

Terminal.prototype._close = function() {
  this.socket.writable = false;
  this.socket.readable = false;
  this.write = function() {};
  this.end = function() {};
  this.writable = false;
  this.readable = false;
};

/**
 * Helpers
 */

function clone(a) {
  var keys = Object.keys(a || {})
    , l = keys.length
    , i = 0
    , b = {};

  for (; i < l; i++) {
    b[keys[i]] = a[keys[i]];
  }

  return b;
}

function environ(env) {
  var keys = Object.keys(env || {})
    , l = keys.length
    , i = 0
    , pairs = [];

  for (; i < l; i++) {
    pairs.push(keys[i] + '=' + env[keys[i]]);
  }

  return pairs;
}

/**
 * Expose
 */

exports = Terminal;
exports.Terminal = Terminal;
exports.native = pty;
module.exports = exports;
<commit_msg>refactor EIO handling<commit_after>/**
 * pty.js
 * Copyright (c) 2012, Christopher Jeffrey (MIT License)
 * Binding to the pseudo terminals.
 */

var net = require('net');
var pty = require('../build/Release/pty.node');

/**
 * Terminal
 */

// Example:
//  var term = new Terminal('bash', [], {
//    name: 'xterm-color',
//    cols: 80,
//    rows: 30,
//    cwd: process.env.HOME,
//    env: process.env
//  });

function Terminal(file, args, opt) {
  if (!(this instanceof Terminal)) {
    return new Terminal(file, args, opt);
  }

  var self = this
    , env
    , cwd
    , name
    , cols
    , rows
    , term;

  // backward compatibility
  if (typeof args === 'string') {
    opt = {
      name: arguments[1],
      cols: arguments[2],
      rows: arguments[3],
      cwd: process.env.HOME
    };
    args = [];
  }

  // arguments
  args = args || [];
  file = file || 'sh';
  opt = opt || {};

  cols = opt.cols || 80;
  rows = opt.rows || 30;
  env = clone(opt.env || process.env);
  cwd = opt.cwd || process.cwd();
  name = opt.name || env.TERM || 'xterm';

  env.TERM = name;
  env = environ(env);

  // fork
  term = pty.fork(file, args, env, cwd, cols, rows);
  this.socket = new net.Socket(term.fd);
  this.socket.setEncoding('utf8');
  this.socket.resume();

  // setup
  this.socket.on('error', function(err) {
    // close
    self._close();

    // EIO, happens when someone closes our child
    // process: the only process in the terminal.
    // node < 0.6.14: errno 5
    // node >= 0.6.14: read EIO
    if (err.code) {
      if (~err.code.indexOf('errno 5')
          || ~err.code.indexOf('EIO')) return;
    }

    // throw anything else
    if (self.listeners('error').length < 2) {
      throw err;
    }
  });

  this.pid = term.pid;
  this.fd = term.fd;
  this.pty = term.pty;

  this.file = file;
  this.name = name;
  this.cols = cols;
  this.rows = rows;

  this.readable = true;
  this.writable = true;

  Terminal.total++;
  this.socket.on('close', function() {
    Terminal.total--;
    self._close();
    self.emit('exit', null);
  });

  env = null;
}

Terminal.fork =
Terminal.spawn =
Terminal.createTerminal = function(file, args, opt) {
  return new Terminal(file, args, opt);
};

/**
 * openpty
 */

Terminal.open = function(opt) {
  var self = Object.create(Terminal.prototype)
    , opt = opt || {};

  if (arguments.length > 1) {
    opt = {
      cols: arguments[1],
      rows: arguments[2]
    };
  }

  var cols = opt.cols || 80
    , rows = opt.rows || 30
    , term;

  // open
  term = pty.open(cols, rows);

  self.master = new net.Socket(term.master);
  self.master.setEncoding('utf8');
  self.master.resume();

  self.slave = new net.Socket(term.slave);
  self.slave.setEncoding('utf8');
  self.slave.resume();

  self.socket = self.master;
  self.pid = null;
  self.fd = term.master;
  self.pty = term.pty;

  self.file = process.argv[0] || 'node';
  self.name = process.env.TERM || '';
  self.cols = cols;
  self.rows = rows;

  self.readable = true;
  self.writable = true;

  self.socket.on('error', function(err) {
    self._close();
    if (self.listeners('error').length < 2) {
      throw err;
    }
  });

  Terminal.total++;
  self.socket.on('close', function() {
    Terminal.total--;
    self._close();
  });

  return self;
};

/**
 * Total
 */

// Keep track of the total
// number of terminals for
// the process.
Terminal.total = 0;

/**
 * Events
 */

// Don't inherit from net.Socket in
// order to avoid collisions.

Terminal.prototype.write = function(data) {
  return this.socket.write(data);
};

Terminal.prototype.end = function(data) {
  return this.socket.end(data);
};

Terminal.prototype.pipe = function(dest, options) {
  return this.socket.pipe(dest, options);
};

Terminal.prototype.pause = function() {
  this.socket.pause();
};

Terminal.prototype.resume = function() {
  this.socket.resume();
};

Terminal.prototype.setEncoding = function(enc) {
  if (this.socket._decoder) {
    delete this.socket._decoder;
  }
  if (enc) {
    this.socket.setEncoding(enc);
  }
};

Terminal.prototype.addListener =
Terminal.prototype.on = function(type, func) {
  this.socket.on(type, func);
  return this;
};

Terminal.prototype.emit = function() {
  return this.socket.emit.apply(this.socket, arguments);
};

Terminal.prototype.listeners = function(type) {
  return this.socket.listeners(type);
};

Terminal.prototype.removeListener = function(type, func) {
  this.socket.removeListener(type, func);
  return this;
};

Terminal.prototype.removeAllListeners = function(type) {
  this.socket.removeAllListeners(type);
  return this;
};

Terminal.prototype.once = function(type, func) {
  this.socket.once(type, func);
  return this;
};

Terminal.prototype.__defineGetter__('stdin', function() {
  return this;
});

Terminal.prototype.__defineGetter__('stdout', function() {
  return this;
});

Terminal.prototype.__defineGetter__('stderr', function() {
  throw new Error('No stderr.');
});

/**
 * TTY
 */

Terminal.prototype.resize = function(cols, rows) {
  cols = cols || 80;
  rows = rows || 30;

  this.cols = cols;
  this.rows = rows;

  pty.resize(this.fd, cols, rows);
};

Terminal.prototype.destroy = function() {
  var self = this;

  // close
  this._close();

  // Need to close the read stream so
  // node stops reading a dead file descriptor.
  // Then we can safely SIGTERM the shell.
  this.socket.once('close', function() {
    self.kill('SIGTERM');
  });

  this.socket.destroy();
};

Terminal.prototype.kill = function(sig) {
  try {
    process.kill(this.pid, sig || 'SIGTERM');
  } catch(e) {
    ;
  }
};

Terminal.prototype.__defineGetter__('process', function() {
  return pty.process(this.fd, this.pty) || this.file;
});

Terminal.prototype._close = function() {
  this.socket.writable = false;
  this.socket.readable = false;
  this.write = function() {};
  this.end = function() {};
  this.writable = false;
  this.readable = false;
};

/**
 * Helpers
 */

function clone(a) {
  var keys = Object.keys(a || {})
    , l = keys.length
    , i = 0
    , b = {};

  for (; i < l; i++) {
    b[keys[i]] = a[keys[i]];
  }

  return b;
}

function environ(env) {
  var keys = Object.keys(env || {})
    , l = keys.length
    , i = 0
    , pairs = [];

  for (; i < l; i++) {
    pairs.push(keys[i] + '=' + env[keys[i]]);
  }

  return pairs;
}

/**
 * Expose
 */

exports = Terminal;
exports.Terminal = Terminal;
exports.native = pty;
module.exports = exports;
<|endoftext|>