CasperSecurity

Current Path : /usr/share/npm/lib/
Upload File :
Current File : //usr/share/npm/lib/npm.js

const EventEmitter = require('events')
const { resolve, dirname } = require('path')
const Config = require('@npmcli/config')

// Patch the global fs module here at the app level
require('graceful-fs').gracefulify(require('fs'))

const { definitions, flatten, shorthands } = require('./utils/config/index.js')
const { shellouts } = require('./utils/cmd-list.js')
const usage = require('./utils/npm-usage.js')

const which = require('which')

const deref = require('./utils/deref-command.js')
const LogFile = require('./utils/log-file.js')
const Timers = require('./utils/timers.js')
const Display = require('./utils/display.js')
const log = require('./utils/log-shim')
const replaceInfo = require('./utils/replace-info.js')

let warnedNonDashArg = false
const _load = Symbol('_load')
const _tmpFolder = Symbol('_tmpFolder')
const _title = Symbol('_title')
const pkg = require('../package.json')

class Npm extends EventEmitter {
  static get version () {
    return pkg.version
  }

  #unloaded = false
  #timers = null
  #logFile = null
  #display = null

  constructor () {
    super()
    this.command = null
    this.#logFile = new LogFile()
    this.#display = new Display()
    this.#timers = new Timers({
      start: 'npm',
      listener: (name, ms) => {
        const args = ['timing', name, `Completed in ${ms}ms`]
        this.#logFile.log(...args)
        this.#display.log(...args)
      },
    })
    this.config = new Config({
      npmPath: dirname(__dirname),
      definitions,
      flatten,
      shorthands,
      log,
    })
    this[_title] = process.title
    this.updateNotification = null
  }

  get version () {
    return this.constructor.version
  }

  get shelloutCommands () {
    return shellouts
  }

  deref (c) {
    return deref(c)
  }

  // Get an instantiated npm command
  // npm.command is already taken as the currently running command, a refactor
  // would be needed to change this
  async cmd (cmd) {
    await this.load()
    const command = this.deref(cmd)
    if (!command) {
      throw Object.assign(new Error(`Unknown command ${cmd}`), {
        code: 'EUNKNOWNCOMMAND',
      })
    }
    const Impl = require(`./commands/${command}.js`)
    const impl = new Impl(this)
    return impl
  }

  // Call an npm command
  async exec (cmd, args) {
    const command = await this.cmd(cmd)
    process.emit('time', `command:${cmd}`)

    // since 'test', 'start', 'stop', etc. commands re-enter this function
    // to call the run-script command, we need to only set it one time.
    if (!this.command) {
      process.env.npm_command = command.name
      this.command = command.name
    }

    // Options are prefixed by a hyphen-minus (-, \u2d).
    // Other dash-type chars look similar but are invalid.
    if (!warnedNonDashArg) {
      args
        .filter(arg => /^[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/.test(arg))
        .forEach(arg => {
          warnedNonDashArg = true
          log.error(
            'arg',
            'Argument starts with non-ascii dash, this is probably invalid:',
            arg
          )
        })
    }

    const workspacesEnabled = this.config.get('workspaces')
    const workspacesFilters = this.config.get('workspace')
    if (workspacesEnabled === false && workspacesFilters.length > 0) {
      throw new Error('Can not use --no-workspaces and --workspace at the same time')
    }

    const filterByWorkspaces = workspacesEnabled || workspacesFilters.length > 0
    // normally this would go in the constructor, but our tests don't
    // actually use a real npm object so this.npm.config isn't always
    // populated.  this is the compromise until we can make that a reality
    // and then move this into the constructor.
    command.workspaces = this.config.get('workspaces')
    command.workspacePaths = null
    // normally this would be evaluated in base-command#setWorkspaces, see
    // above for explanation
    command.includeWorkspaceRoot = this.config.get('include-workspace-root')

    if (this.config.get('usage')) {
      this.output(command.usage)
      return
    }
    if (filterByWorkspaces) {
      if (this.config.get('global')) {
        throw new Error('Workspaces not supported for global packages')
      }

      return command.execWorkspaces(args, this.config.get('workspace')).finally(() => {
        process.emit('timeEnd', `command:${cmd}`)
      })
    } else {
      return command.exec(args).finally(() => {
        process.emit('timeEnd', `command:${cmd}`)
      })
    }
  }

  async load () {
    if (!this.loadPromise) {
      process.emit('time', 'npm:load')
      this.loadPromise = new Promise((resolve, reject) => {
        this[_load]()
          .catch(er => er)
          .then(er => {
            this.loadErr = er
            if (!er && this.config.get('force')) {
              log.warn('using --force', 'Recommended protections disabled.')
            }

            process.emit('timeEnd', 'npm:load')
            if (er) {
              return reject(er)
            }
            resolve()
          })
      })
    }
    return this.loadPromise
  }

  get loaded () {
    return this.config.loaded
  }

  // This gets called at the end of the exit handler and
  // during any tests to cleanup all of our listeners
  // Everything in here should be synchronous
  unload () {
    // Track if we've already unloaded so we dont
    // write multiple timing files. This is only an
    // issue in tests right now since we unload
    // in both tap teardowns and the exit handler
    if (this.#unloaded) {
      return
    }
    this.#timers.off()
    this.#display.off()
    this.#logFile.off()
    if (this.loaded && this.config.get('timing')) {
      this.#timers.writeFile({
        command: process.argv.slice(2),
        // We used to only ever report a single log file
        // so to be backwards compatible report the last logfile
        // XXX: remove this in npm 9 or just keep it forever
        logfile: this.logFiles[this.logFiles.length - 1],
        logfiles: this.logFiles,
        version: this.version,
      })
    }
    this.#unloaded = true
  }

  get title () {
    return this[_title]
  }

  set title (t) {
    process.title = t
    this[_title] = t
  }

  async [_load] () {
    process.emit('time', 'npm:load:whichnode')
    let node
    try {
      node = which.sync(process.argv[0])
    } catch {
      // TODO should we throw here?
    }
    process.emit('timeEnd', 'npm:load:whichnode')
    if (node && node.toUpperCase() !== process.execPath.toUpperCase()) {
      log.verbose('node symlink', node)
      process.execPath = node
      this.config.execPath = node
    }

    process.emit('time', 'npm:load:configload')
    await this.config.load()
    process.emit('timeEnd', 'npm:load:configload')

    this.argv = this.config.parsedArgv.remain
    // note: this MUST be shorter than the actual argv length, because it
    // uses the same memory, so node will truncate it if it's too long.
    // if it's a token revocation, then the argv contains a secret, so
    // don't show that.  (Regrettable historical choice to put it there.)
    // Any other secrets are configs only, so showing only the positional
    // args keeps those from being leaked.
    process.emit('time', 'npm:load:setTitle')
    const tokrev = deref(this.argv[0]) === 'token' && this.argv[1] === 'revoke'
    this.title = tokrev
      ? 'npm token revoke' + (this.argv[2] ? ' ***' : '')
      : replaceInfo(['npm', ...this.argv].join(' '))
    process.emit('timeEnd', 'npm:load:setTitle')

    process.emit('time', 'npm:load:display')
    this.#display.load({
      // Use logColor since that is based on stderr
      color: this.logColor,
      progress: this.flatOptions.progress,
      timing: this.config.get('timing'),
      loglevel: this.config.get('loglevel'),
      unicode: this.config.get('unicode'),
      heading: this.config.get('heading'),
    })
    process.emit('timeEnd', 'npm:load:display')
    process.env.COLOR = this.color ? '1' : '0'

    process.emit('time', 'npm:load:logFile')
    this.#logFile.load({
      dir: resolve(this.cache, '_logs'),
      logsMax: this.config.get('logs-max'),
    })
    log.verbose('logfile', this.#logFile.files[0])
    process.emit('timeEnd', 'npm:load:logFile')

    process.emit('time', 'npm:load:timers')
    this.#timers.load({
      dir: this.cache,
    })
    process.emit('timeEnd', 'npm:load:timers')

    process.emit('time', 'npm:load:configScope')
    const configScope = this.config.get('scope')
    if (configScope && !/^@/.test(configScope)) {
      this.config.set('scope', `@${configScope}`, this.config.find('scope'))
    }
    process.emit('timeEnd', 'npm:load:configScope')
  }

  get flatOptions () {
    const { flat } = this.config
    if (this.command) {
      flat.npmCommand = this.command
    }
    return flat
  }

  // color and logColor are a special derived values that takes into
  // consideration not only the config, but whether or not we are operating
  // in a tty with the associated output (stdout/stderr)
  get color () {
    return this.flatOptions.color
  }

  get logColor () {
    return this.flatOptions.logColor
  }

  get lockfileVersion () {
    return 2
  }

  get unfinishedTimers () {
    return this.#timers.unfinished
  }

  get finishedTimers () {
    return this.#timers.finished
  }

  get started () {
    return this.#timers.started
  }

  get logFiles () {
    return this.#logFile.files
  }

  get cache () {
    return this.config.get('cache')
  }

  set cache (r) {
    this.config.set('cache', r)
  }

  get globalPrefix () {
    return this.config.globalPrefix
  }

  set globalPrefix (r) {
    this.config.globalPrefix = r
  }

  get localPrefix () {
    return this.config.localPrefix
  }

  set localPrefix (r) {
    this.config.localPrefix = r
  }

  get globalDir () {
    return process.platform !== 'win32'
      ? resolve(this.globalPrefix, 'lib', 'node_modules')
      : resolve(this.globalPrefix, 'node_modules')
  }

  get localDir () {
    return resolve(this.localPrefix, 'node_modules')
  }

  get dir () {
    return this.config.get('global') ? this.globalDir : this.localDir
  }

  get globalBin () {
    const b = this.globalPrefix
    return process.platform !== 'win32' ? resolve(b, 'bin') : b
  }

  get localBin () {
    return resolve(this.dir, '.bin')
  }

  get bin () {
    return this.config.get('global') ? this.globalBin : this.localBin
  }

  get prefix () {
    return this.config.get('global') ? this.globalPrefix : this.localPrefix
  }

  set prefix (r) {
    const k = this.config.get('global') ? 'globalPrefix' : 'localPrefix'
    this[k] = r
  }

  get usage () {
    return usage(this)
  }

  // XXX add logging to see if we actually use this
  get tmp () {
    if (!this[_tmpFolder]) {
      const rand = require('crypto').randomBytes(4).toString('hex')
      this[_tmpFolder] = `npm-${process.pid}-${rand}`
    }
    return resolve(this.config.get('tmp'), this[_tmpFolder])
  }

  // output to stdout in a progress bar compatible way
  output (...msg) {
    log.clearProgress()
    // eslint-disable-next-line no-console
    console.log(...msg)
    log.showProgress()
  }
}
module.exports = Npm
Hacker Blog, Shell İndir, Sql İnjection, XSS Attacks, LFI Attacks, Social Hacking, Exploit Bot, Proxy Tools, Web Shell, PHP Shell, Alfa Shell İndir, Hacking Training Set, DDoS Script, Denial Of Service, Botnet, RFI Attacks, Encryption
Telegram @BIBIL_0DAY