| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 | 'use strict';var fs = require('fs');var LRU = require('lru-cache');var resolveCommand = require('./resolveCommand');var isWin = process.platform === 'win32';var shebangCache = new LRU({ max: 50, maxAge: 30 * 1000 });  // Cache just for 30secfunction readShebang(command) {    var buffer;    var fd;    var match;    var shebang;    // Check if it is in the cache first    if (shebangCache.has(command)) {        return shebangCache.get(command);    }    // Read the first 150 bytes from the file    buffer = new Buffer(150);    try {        fd = fs.openSync(command, 'r');        fs.readSync(fd, buffer, 0, 150, 0);        fs.closeSync(fd);    } catch (e) { /* empty */ }    // Check if it is a shebang    match = buffer.toString().trim().match(/#!(.+)/i);    if (match) {        shebang = match[1].replace(/\/usr\/bin\/env\s+/i, '');   // Remove /usr/bin/env    }    // Store the shebang in the cache    shebangCache.set(command, shebang);    return shebang;}function escapeArg(arg, quote) {    // Convert to string    arg = '' + arg;    // If we are not going to quote the argument,    // escape shell metacharacters, including double and single quotes:    if (!quote) {        arg = arg.replace(/([\(\)%!\^<>&|;,"'\s])/g, '^$1');    } else {        // Sequence of backslashes followed by a double quote:        // double up all the backslashes and escape the double quote        arg = arg.replace(/(\\*)"/g, '$1$1\\"');        // Sequence of backslashes followed by the end of the string        // (which will become a double quote later):        // double up all the backslashes        arg = arg.replace(/(\\*)$/, '$1$1');        // All other backslashes occur literally        // Quote the whole thing:        arg = '"' + arg + '"';    }    return arg;}function escapeCommand(command) {    // Do not escape if this command is not dangerous..    // We do this so that commands like "echo" or "ifconfig" work    // Quoting them, will make them unaccessible    return /^[a-z0-9_-]+$/i.test(command) ? command : escapeArg(command, true);}function parse(command, args, options) {    var shebang;    var applyQuotes;    var file;    var original;    // Normalize arguments, similar to nodejs    if (args && !Array.isArray(args)) {        options = args;        args = null;    }    args = args ? args.slice(0) : [];  // Clone array to avoid changing the original    options = options || {};    original = command;    if (isWin) {        // Detect & add support for shebangs        file = resolveCommand(command);        file = file || resolveCommand(command, true);        shebang = file && readShebang(file);        if (shebang) {            args.unshift(file);            command = shebang;        }        // Escape command & arguments        applyQuotes = command !== 'echo';  // Do not quote arguments for the special "echo" command        command = escapeCommand(command);        args = args.map(function (arg) {            return escapeArg(arg, applyQuotes);        });        // Use cmd.exe        args = ['/s', '/c', '"' + command + (args.length ? ' ' + args.join(' ') : '') + '"'];        command = process.env.comspec || 'cmd.exe';        // Tell node's spawn that the arguments are already escaped        options.windowsVerbatimArguments = true;    }    return {        command: command,        args: args,        options: options,        file: file,        original: original,    };}module.exports = parse;
 |