⚝
One Hat Cyber Team
⚝
Your IP:
172.22.0.1
Server IP:
151.80.20.34
Server:
Linux 794f04d97d5e 5.15.0-143-generic #153-Ubuntu SMP Fri Jun 13 19:10:45 UTC 2025 x86_64
Server Software:
Apache/2.4.62 (Debian)
PHP Version:
8.2.28
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
nodejs
/
jackspeak
/
View File Name :
index.js
'use strict' const assert = require('assert') const cliui = require('cliui') const path = require('path') // only way to trigger is run as non-module, which can't be instrumented /* istanbul ignore next */ const $0 = require.main ? path.basename(require.main.filename) : '$0' const _flag = Symbol('flag') const flag = options => ({ [_env]: false, [_list]: false, ...(options || {}), [_num]: false, [_opt]: false, [_flag]: true }) const isFlag = arg => arg[_flag] const _opt = Symbol('opt') const opt = options => ({ [_num]: false, [_list]: false, [_env]: false, ...(options || {}), [_flag]: false, [_opt]: true }) const isOpt = arg => arg[_opt] const _num = Symbol('num') const num = options => (opt({ ...(options || {}), [_num]: true, })) const isNum = arg => arg[_num] const isArg = arg => isOpt(arg) || isFlag(arg) const _env = Symbol('env') const env = options => ({ [_flag]: false, [_list]: false, [_opt]: true, [_num]: false, ...(options || {}), [_env]: true, }) const isEnv = arg => arg[_env] const _list = Symbol('list') const list = options => ({ [_flag]: false, [_opt]: true, [_num]: false, [_env]: false, ...(options || {}), [_list]: true }) const isList = arg => arg[_list] const count = options => list(flag(options)) const isCount = arg => isList(arg) && isFlag(arg) const trim = string => string // remove single line breaks .replace(/([^\n])\n[ \t]*([^\n])/g, '$1 $2') // normalize mid-line whitespace .replace(/([^\n])[ \t]+([^\n])/g, '$1 $2') // two line breaks are enough .replace(/\n{3,}/g, '\n\n') .trim() const usageMemo = Symbol('usageMemo') const usage = j => { if (j[usageMemo]) return j[usageMemo] const width = Math.min( process && process.stdout && process.stdout.columns || 80, 80 ) const ui = cliui({ width }) if (!/^Usage:/.test(j.help[0].text)) { ui.div('Usage:') ui.div({ text: `${$0} <options>`, padding: [0, 0, 1, 2] }) } let maxMax = 26 let maxWidth = 8 let prev = null j.help.forEach(row => { // find the max width of left-hand sides, and decide whether or not // to skip a line based on the length of the next option if (row.left) { if (row.text.length > width - maxMax) { if (prev) prev.skipLine = true row.skipLine = true } prev = row const len = row.left.length + 4 if (len > maxWidth && len < maxMax) maxWidth = len } else { if (prev) prev.skipLine = true prev = null } }) j.help.forEach(row => { if (row.left) { // If the row is too long, don't wrap it // Bump the right-hand side down a line to make room if (row.left.length >= maxWidth - 2) { ui.div({ text: row.left, padding: [ 0, 0, 0, 2 ] }) ui.div({ text: row.text, padding: [ 0, 0, 0, maxWidth ] }) } else { ui.div({ text: row.left, padding: [0, 1, 0, 2], width: maxWidth, }, { text: row.text }) } if (row.skipLine) ui.div() } else ui.div(row) }) return j[usageMemo] = ui.toString() } // parse each section // Resulting internal object looks like: // { // help: [ // { text, padding, left }, ... // ], // // single-char shorthands // shortOpts: { char: name, ... } // shortFlags: { char: name, ... } // options: { all opts and flags } // main: mainFn or null, // argv: argument list being parsed, // result: parsed object passed to main function and returned // implies: all the implied variable values (set last) // } const jack = (...sections) => execute(parse_(buildParser(newObj(), sections))) const kvToArg = j => (k, v) => j.options[k] && isFlag(j.options[k]) ? (v ? `--${k}` : `--no-${k}`) : v === null || v === undefined ? `--${k}=` : `--${k}=${v}` const objToArgv = j => obj => Object.keys(obj).reduce((set, k) => { const toArg = kvToArg(j) const val = obj[k] if (Array.isArray(val)) set.push(...val.map(v => toArg(k, v))) else set.push(toArg(k, val)) return set }, []) const update = j => args => { const argv = [] const toArgv = objToArgv(j) if (typeof args === 'string') argv.push(args) else if (Array.isArray(args)) argv.push(...args) else if (args) argv.push(...toArgv(args)) const result = reparse(j)(argv) Object.keys(result) .filter(k => k !== '_' && !j.explicit.has(k)) .forEach(k => j.result[k] = result[k]) } const reparse = j => args => { const argv = Array.isArray(args) ? args : [args] return parse_({ ...j, explicit: new Set(), result: { _: [] }, help: [], main: null, argv, }).result } const newObj = () => ({ help: [], shortOpts: {}, shortFlags: {}, options: {}, result: { _: [] }, explicit: new Set(), main: null, argv: null, env: null, implies: {}, [usageMemo]: false, }) const execute = j => { if (j.result.help) console.log(usage(j)) else if (j.main) j.main(j.result) return j.result } const buildParser = (j, sections) => { let inHeader = true sections.forEach(section => { if (Array.isArray(section)) section = { argv: section } if (section.argv && !isArg(section.argv)) { !j.argv || assert(false, 'argv specified multiple times') j.argv = section.argv } if (section.env && !isArg(section.env)) { !j.env || assert(false, 'env specified multiple times\n' + '(did you set it after defining some environment args?)') j.env = section.env } if (section.usage && !isArg(section.usage)) { const val = section.usage typeof val === 'string' || Array.isArray(val) || assert(false, 'usage must be a string or array') j.help.push({ text: 'Usage:' }) j.help.push.apply(j.help, [].concat(val).map(text => ({ text, padding: [0, 0, 0, 2] }))) j.help.push({ text: '' }) } if (section.description && !isArg(section.description)) { typeof section.description === 'string' || assert(false, 'description must be string') inHeader = false j.help.push({ text: trim(`${section.description}:`), padding: [0, 0, 1, 0] }) } if (section.help && !isArg(section.help)) { typeof section.help === 'string' || assert(false, 'help must be a string') j.help.push({ text: trim(section.help) + '\n', padding: inHeader ? null : [ 0, 0, 0, 2 ] }) } if (section.main && !isArg(section.main)) addMain(j, section.main) !section._ || assert(false, '_ is reserved for positional arguments') const names = Object.keys(section) for (let n = 0; n < names.length; n++) { inHeader = false const name = names[n] const val = section[name] if (isEnv(val)) addEnv(j, name, val) else if (isArg(val)) addArg(j, name, val) else { switch (name) { case 'argv': case 'description': case 'usage': case 'help': case 'main': case 'env': continue default: assert(false, `${name} not flag, opt, or env`) } } } }) // if not already mentioned, add the note about -h and `--` ending parsing if (!j.options.help) addArg(j, 'help', flag({ description: 'Show this helpful output' })) if (!j.options['--']) { addHelpText(j, '', flag({ description: `Stop parsing flags and options, treat any additional command line arguments as positional arguments.` })) } return j } const envToNum = (name, spec) => e => { if (e === '') return undefined return toNum(e, `environment variable ${name}`, spec) } const envToBool = name => e => { typeof e === 'boolean' || e === '' || e === '1' || e === '0' || typeof e === 'number' || assert(false, `Environment variable ${name} must be set to 0 or 1 only`) return !!+e } const countBools = l => l.reduce((v, a) => v ? a + 1 : a - 1, 0) const envVal = (j, name, val) => { if (!j.env) j.env = process.env const def = val.default const has = Object.prototype.hasOwnProperty.call(j.env, name) const e = has && j.env[name] !== '' ? j.env[name] : def !== undefined ? def : '' if (isList(val)) { val.delimiter || assert(false, `env list ${name} lacks delimiter`) if (!has) return [] else { const split = e.split(val.delimiter) return isFlag(val) ? countBools(split.map(envToBool(name))) : isNum(val) ? split.map(envToNum(name, val)).filter(e => e !== undefined) : split } } else if (isFlag(val)) return envToBool(name)(e) else if (isNum(val)) return envToNum(name, val)(e) else return e } const addEnv = (j, name, val) => { assertNotDefined(j, name) const e = envVal(j, name, val) if (Object.prototype.hasOwnProperty.call(j.env, name)) set(j, name, val, e) else j.result[name] = e addHelpText(j, name, val) } const assertNotDefined = (j, name) => !j.options[name] && !j.shortOpts[name] && !j.shortFlags[name] || assert(false, `${name} defined multiple times`) const addArg = (j, name, val) => { assertNotDefined(j, name) if (val.envDefault) val.default = envVal(j, val.envDefault, val) if (isFlag(val)) addFlag(j, name, val) else addOpt(j, name, val) } const addOpt = (j, name, val) => { addShort(j, name, val) j.options[name] = val addHelpText(j, name, val) if (!val.alias) j.result[name] = isList(val) ? [] : val.default } const addFlag = (j, name, val) => { if (name === '--') { addHelpText(j, '', flag(val)) j.options['--'] = true return } if (name === 'help' && !val.short) val.short = 'h' const negate = name.substr(0, 3) === 'no-' // aliases can't be negated if (!negate && !val.alias) !j.options[`no-${name}`] || assert(false, `flag '${name}' specified, but 'no-${name}' already defined`) addShort(j, name, val) j.options[name] = val if (!negate && !val.alias) j.result[name] = isList(val) ? 0 : (val.default || false) addHelpText(j, name, val) // pick up the description and short arg if (!negate && !val.alias) addFlag(j, `no-${name}`, flag({ description: `${ isCount(val) ? 'decrement' : 'switch off' } the --${name} flag`, hidden: val.hidden, implies: val.implies, ...(val.negate || {}), [_list]: isList(val) })) } const addHelpText = (j, name, val) => { // help text if (val.hidden) return const desc = trim(val.description || ( val.alias ? `Alias for ${[].concat(val.alias).join(' ')}` : '[no description provided]' )) const mult = isList(val) && !isEnv(val) ? `${ desc.indexOf('\n') === -1 ? '\n' : '\n\n' }Can be set multiple times` : '' const text = `${desc}${mult}` const hint = val.hint || name const shortEq = val.short && val.short.length > 1 ? '=' : '' const short = val.short ? ( isFlag(val) ? `-${val.short} ` : `-${val.short}${shortEq}<${hint}> ` ) : '' const left = isEnv(val) ? name : isFlag(val) ? `${short}--${name}` : `${short}--${name}=<${hint}>` j.help.push({ text, left }) } const addShort = (j, name, val) => { if (!val.short) return assertNotDefined(j, val.short) val.short !== 'h' || name === 'help' || assert(false, `${name} using 'h' short val, reserved for --help`) if (isFlag(val)) j.shortFlags[val.short] = name else j.shortOpts[val.short] = name } const addMain = (j, main) => { typeof main === 'function' || assert(false, 'main must be function') !j.main || assert(false, 'main function specified multiple times') j.main = result => { main(result) return result } } const getArgv = j => { const argv = [...(j.argv || process.argv)] if (argv[0] === process.execPath) { argv.shift() argv.shift() } return argv } const toNum = (val, key, spec) => { !isNaN(val) || assert(false, `non-number '${val}' given for numeric ${key}`) val = +val isNaN(spec.max) || val <= spec.max || assert(false, `value ${val} for ${key} exceeds max (${spec.max})`) isNaN(spec.min) || val >= spec.min || assert(false, `value ${val} for ${key} below min (${spec.min})`) return val } const wrap = (text, padding) => { const ui = cliui() ui.div({ text, padding }) return ui.toString() } const assertValid = (val, key, spec) => !isOpt(spec) || !spec.valid || spec.valid.indexOf(val) !== -1 || assert(false, `Invalid value ${val} provided for ${key}. Must be one of: ${wrap(spec.valid.join(' '), [ 0, 2, 0, 8 ])}`) const parse_ = j => { const argv = getArgv(j) const original = [...argv] for (let i = 0; i < argv.length; i++) { const arg = argv[i] if (arg.charAt(0) !== '-' || arg === '-') { j.result._.push(arg) continue } if (arg === '--') { j.result._ = j.result._.concat(argv.slice(i + 1)) i = argv.length continue } // short-flags if (arg.charAt(1) !== '-') { const expand = [] for (let f = 1; f < arg.length; f++) { const fc = arg.charAt(f) const sf = j.shortFlags[fc] const so = j.shortOpts[fc] if (sf) expand.push(`--${sf}`) else if (so) { const soslice = arg.slice(f + 1) const soval = !soslice || soslice.charAt(0) === '=' ? soslice : '=' + soslice expand.push(`--${so}${soval}`) f = arg.length } else if (arg !== `-${fc}`) // this will trigger a failure with the appropriate message expand.push(`-${fc}`) } if (expand.length) { argv.splice.apply(argv, [i, 1].concat(expand)) i-- continue } } const argsplit = arg.split('=') const literalKey = argsplit.shift() // check if there's a >1 char shortopt/flag for this key, // and de-reference it as an alias const k = literalKey.replace(/^--?/, '') // pick up shorts that aren't single-char const key = j.shortOpts[k] || j.shortFlags[k] || k let val = argsplit.length ? argsplit.join('=') : null const spec = j.options[key] spec || assert(false, `invalid argument: ${literalKey}`) !isFlag(spec) || val === null || assert(false, `value provided for boolean flag: ${key}`) if (isOpt(spec) && val === null) { val = argv[++i] val !== undefined || assert(false, `no value provided for option: ${key}`) } if (spec.alias) { const alias = isFlag(spec) ? spec.alias : [].concat(spec.alias).map(a => a.replace(/\$\{value\}/g, val)) argv.splice.apply(argv, [i, 1].concat(alias)) i-- continue } const negate = isFlag(spec) && key.substr(0, 3) === 'no-' const name = negate ? key.substr(3) : key if (isNum(spec)) val = toNum(val, `arg ${literalKey}`, spec) assertValid(val, key, spec) if (isList(spec)) { if (isOpt(spec)) { if (!Array.isArray(j.result[name])) j.result[name] = [] set(j, name, spec, j.result[name].concat(val)) } else { const v = j.result[name] || 0 set(j, name, spec, negate ? v - 1 : v + 1) } } else { // either flag or opt set(j, name, spec, isFlag(spec) ? !negate : val) } } for (let i in j.implies) for (let k in j.implies[i]) j.result[k] = j.implies[i][k] Object.defineProperty(j.result._, 'usage', { value: () => console.log(usage(j)) }) Object.defineProperty(j.result._, 'update', { value: update(j) }) Object.defineProperty(j.result._, 'reparse', { value: reparse(j) }) Object.defineProperty(j.result._, 'explicit', { value: j.explicit }) Object.defineProperty(j.result._, 'parsed', { value: argv }) Object.defineProperty(j.result._, 'original', { value: original }) return j } const set = (j, key, spec, val) => { j.result[key] = val j.explicit.add(key) if (spec && spec.implies) { if (val === false) delete j.implies[key] else j.implies[key] = {...spec.implies} } // delete implications about this, since we have an explicit value for (const i in j.implies) delete j.implies[i][key] } // just parse the arguments and return the result const parse = (...sections) => parse_(buildParser(newObj(), sections)).result module.exports = { jack, flag, opt, list, count, env, parse, num }