!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache/2.4.41 (Ubuntu). PHP/8.0.30 

uname -a: Linux apirnd 5.4.0-204-generic #224-Ubuntu SMP Thu Dec 5 13:38:28 UTC 2024 x86_64 

uid=33(www-data) gid=33(www-data) groups=33(www-data) 

Safe-mode: OFF (not secure)

/var/www/html/node-red/node_modules/simple-cli/test/   drwxr-xr-x
Free 13.21 GB of 57.97 GB (22.8%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     builder.js (20.14 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
const chalk = require('chalk');
const util = require('util');
const path = require('path');
const proxyquire = require('proxyquire').noCallThru();
const sinon = require('sinon');
const async = require('async');

describe('builder', () => {
  const spawn = sinon.stub();
  const readline = { createInterface: sinon.stub() };
  const resolve = sinon.stub().withArgs('cmd').returns(path.resolve(__dirname, '../node_modules/cmd/index.js'));
  const Builder = proxyquire('../lib/builder', {
    'cross-spawn': spawn,
    readline: readline,
    './resolve': resolve
  });

  describe('constructor', () => {
    let options, context, grunt, builder, p, originalPlatform;

    afterEach(() => {
      Builder.prototype.setConfig.restore();
      Builder.prototype.buildArgs.restore();
    });

    beforeEach(() => {
      p = process.env.PATH;
      sinon.stub(Builder.prototype, 'setConfig').callsFake(function() {
        this.config = {
          debug: 'config debug',
          env: {
            foo: 'bar'
          }
        };
      });

      sinon.stub(Builder.prototype, 'buildArgs').returns('args');

      options = {
        cmd: 'cmd',
        singleDash: true,
        custom: 'options!'
      };

      context = {
        async: () => 'done',
        options: sinon.stub().withArgs({}).returns('options')
      };
      grunt = { option: sinon.stub() };

      originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
      Object.defineProperty(process, 'platform', { value: 'linux' });
    });

    afterEach(() => {
      process.env.PATH = p;
      Object.defineProperty(process, 'platform', originalPlatform);
    });

    it('should accept options.cmd', () => {
      process.env.PATH = '/a/b/c:/d/e/f';
      builder = new Builder(options, context, grunt);
      builder.cmd.should.equal('cmd');
      builder.singleDash.should.be.true();
      builder.done.should.equal('done');
      builder.callback.should.equal('done');
      builder.options.should.equal('options');
      builder.context.should.equal(context);
      builder.setConfig.should.have.been.calledWith(context);
      builder.debugOn.should.equal('config debug');
      builder.grunt.should.equal(grunt);
      builder.custom.should.equal('options!');
      builder.env.foo.should.equal('bar');
      builder.env.PATH.should.equal(`${path.resolve(__dirname, '../node_modules/.bin')}:/a/b/c:/d/e/f`);
      builder.args = 'args';
    });

    describe('on win32', () => {
      let originalPlatform;

      beforeEach(() => {
        delete process.env.PATH;
        originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
        Object.defineProperty(process, 'platform', { value: 'win32' });
      });

      afterEach(() => Object.defineProperty(process, 'platform', originalPlatform));

      it('should build the PATH using semicolon ;', () => {
        process.env.Path = '/a/b/c;/d/e/f';
        builder = new Builder(options, context, grunt);
        builder.env.Path.should.equal(`${path.resolve(__dirname, '../node_modules/.bin')};/a/b/c;/d/e/f`);
      });
    });

    describe('on non-win32 platforms', () => {
      let originalPlatform;
      beforeEach(() => {
        originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
        Object.defineProperty(process, 'platform', { value: 'linux' });
      });

      afterEach(() => Object.defineProperty(process, 'platform', originalPlatform));

      it('should build the PATH using colon :', () => {
        process.env.PATH = '/a/b/c:/d/e/f';
        builder = new Builder(options, context, grunt);
        builder.env.PATH.should.equal(`${path.resolve(__dirname, '../node_modules/.bin')}:/a/b/c:/d/e/f`);
      });
    });
  });

  describe('.setConfig', () => {
    let ctx;

    beforeEach(() => {
      ctx = {};
    });

    it('should accept data as an array', () => {
      const context = {
        data: [ 'foo', 'bar' ],
        target: 'revParse'
      };
      Builder.prototype.setConfig.call(ctx, context);
      ctx.config.should.eql({
        args: [ 'foo', 'bar' ],
        rawArgs: [],
        env: {}
      });
      ctx.target.should.equal('rev-parse');
    });

    it('should accept data as a string', () => {
      const context = {
        data: 'foo bar',
        target: 'revParse'
      };

      Builder.prototype.setConfig.call(ctx, context);
      ctx.config.should.eql({
        args: [ 'foo', 'bar' ],
        rawArgs: [],
        env: {}
      });
      ctx.target.should.equal('rev-parse');
    });

    it('should accept data as an object with a cmd', () => {
      const context = {
        data: {
          options: {
            foo: 'bar'
          },
          args: [ 'foo', 'bar' ],
          cmd: 'blah'
        },
        target: 'revParse'
      };
      Builder.prototype.setConfig.call(ctx, context);
      ctx.config.should.eql({
        cmd: 'blah',
        args: [ 'foo', 'bar' ],
        rawArgs: [],
        env: {}
      });
      ctx.target.should.equal('blah');
    });

    it('should accept data as an object without a cmd', () => {
      const context = {
        data: {
          options: {
            foo: 'bar'
          },
          args: 'foo bar',
          env: {
            baz: 'quux'
          }
        },
        target: 'revParse'
      };
      Builder.prototype.setConfig.call(ctx, context);
      ctx.config.should.eql({
        cmd: null,
        args: [ 'foo', 'bar' ],
        rawArgs: [],
        env: {
          baz: 'quux'
        }
      });
      ctx.target.should.equal('rev-parse');
    });
  });

  describe('.buildArgs', () => {
    it('should work with no singleDash', () => {
      const context = {
        config: {
          args: [ 'foo', 'bar' ],
          rawArgs: [ 'hello', 'world' ]
        },
        options: {
          a: true,
          b: 'b',
          bool: true,
          long: 'baz',
          'name=': 'Andrew',
          list: [ 'rope', 'jelly' ]
        }
      };
      Builder.prototype.buildArgs.apply(context).should.eql([
        'foo', 'bar',
        '-a', '-b', 'b',
        '--bool', '--long', 'baz',
        '--name=Andrew',
        '--list', 'rope',
        '--list', 'jelly',
        'hello', 'world'
      ]);
    });

    it('should work with singleDash', () => {
      const context = {
        singleDash: true,
        config: {
          args: [ 'foo', 'bar' ],
          rawArgs: [ 'hello', 'world' ]
        },
        options: {
          a: true,
          b: 'b',
          bool: true,
          long: 'baz',
          'name=': 'Andrew',
          list: [ 'rope', 'jelly' ]
        }
      };
      Builder.prototype.buildArgs.apply(context).should.eql([
        'foo', 'bar',
        '-a', '-b', 'b',
        '-bool', '-long', 'baz',
        '-name=Andrew',
        '-list', 'rope',
        '-list', 'jelly',
        'hello', 'world'
      ]);
    });

    it('should invert args and flags when flags is "before"', () => {
      const context = {
        flags: 'before',
        config: {
          args: [ 'foo', 'bar' ]
        },
        options: {
          baz: 'quux'
        }
      };
      Builder.prototype.buildArgs.apply(context).should.eql([
        '--baz', 'quux',
        'foo', 'bar'
      ]);
    });
  });

  describe('.getDynamicValues', () => {
    let cb, context;
    beforeEach(() => {
      cb = sinon.stub();
      context = {
        populateFromGrunt: sinon.stub(),
        template: sinon.stub(),
        getReadlineValues: sinon.stub()
      };
    });

    it('should no keys', () => {
      context.args = [ 'a', 'b' ];
      Builder.prototype.getDynamicValues.call(context, cb);
      cb.should.have.been.called;
      context.populateFromGrunt.should.not.have.been.called;
    });

    it('should all keys filled by grunt', () => {
      context.args = [ '{{ a }}', '{{ b }}' ];
      context.populateFromGrunt.returns({ a: 'b', b: 'c' });
      Builder.prototype.getDynamicValues.call(context, cb);
      context.populateFromGrunt.should.have.been.calledWith([ 'a', 'b' ]);
      context.template.should.have.been.calledWith('{{ a }}||{{ b }}', {
        a: 'b',
        b: 'c'
      });
      cb.should.have.been.called;
    });

    it('should some keys missing', () => {
      context.args = [ '{{ a }}', '{{ b }}' ];
      context.populateFromGrunt.returns({ a: 'b', b: null });
      Builder.prototype.getDynamicValues.call(context, cb);
      context.populateFromGrunt.should.have.been.calledWith([ 'a', 'b' ]);
      context.template.should.not.have.been.called;
      context.getReadlineValues.should.have.been.calledWith(['b'], { a: 'b', b: null }, '{{ a }}||{{ b }}', cb);
    });
  });

  describe('.getReadlineValues', () => {
    // There are ridiculous shenanigans involved in
    // stubbing console.log only SOMETIMES. But . . .
    // I really hate noise in test output, so
    // I'm doing it anyway.

    /* Commense shenanigans */
    afterEach(() => {
      console.log.restore();
    });

    beforeEach(() => {
      let log = console.log; // Store a reference to log, so we can stub it but still call it

      sinon.stub(console, 'log').callsFake((...args) => {
        // If this a log generated by the test itself, ignore it.
        // If it's generated by the test framework . . . these aren't thre droids we're looking for.
        if (args[0] && args[0].indexOf('Enter values for') === -1) {
          log.apply(console, args);
        }
      });
    });
    /* End shenanigans */

    let cb, context, rl;

    beforeEach(() => {
      cb = sinon.stub();
      context = {
        config: {},
        populateFromGrunt: sinon.stub(),
        getSubcommand: sinon.stub(),
        template: sinon.stub(),
        prompt: sinon.stub(),
        args: [ '{{ a }}', '{{ b }}' ],
        grunt: {
          fail: {
            fatal: sinon.stub()
          }
        }
      };
      rl = { close: sinon.stub() };
      readline.createInterface.withArgs({
        input: process.stdin,
        output: process.stdout
      }).returns(rl);
    });

    it('should prompt for values', () => {
      context.prompt.callsArgWith(1, 'answer');
      context.populateFromGrunt.returns({ a: 'b', b: null });
      context.getSubcommand.returns(['b']);
      Builder.prototype.getReadlineValues.call(context, ['b'], { a: 'b', b: null }, '{{ a }}||{{ b }}', cb);
      context.prompt.should.have.been.calledWith('b', sinon.match.func);
      rl.close.should.have.been.called;
      context.template.should.have.been.calledWith('{{ a }}||{{ b }}', {
        a: 'b',
        b: 'answer'
      });
      cb.should.have.been.called;
    });

    it('should handle errors in readline', () => {
      sinon.stub(async, 'reduce');
      async.reduce.callsArgWith(3, 'error');
      context.getSubcommand.returns(['b']);
      Builder.prototype.getReadlineValues.call(context, ['b'], { a: 'b', b: null }, '{{ a }}||{{ b }}', cb);
      rl.close.should.have.been.called;
      context.grunt.fail.fatal.should.have.been.calledWith('error');
    });
  });

  describe('.populateFromGrunt', () => {
    it('should populate missing args', () => {
      const context = {
        grunt: {
          option: sinon.stub(),
          config: {
            get: sinon.stub()
          }
        }
      };

      context.grunt.option.withArgs('foo').returns('banana');
      context.grunt.config.get.withArgs('bar').returns('kiwi');
      context.grunt.config.get.withArgs('hello.world').returns('blah');
      const obj = Builder.prototype.populateFromGrunt.call(context, [ 'foo', 'bar', 'baz', 'hello.world' ]);
      obj.should.eql({
        foo: 'banana',
        bar: 'kiwi',
        baz: null,
        hello: {
          world: 'blah'
        }
      });
    });
  });

  describe('.template', () => {
    it('should populate the template', () => {
      const context = {};
      Builder.prototype.template.call(context, '{{ foo }}||{{ bar }}', { foo: 'banana', bar: 'cream pie' });
      context.args.should.eql([ 'banana', 'cream pie' ]);
    });
  });

  describe('.prompt', () => {
    it('should prompt the user for values', () => {
      const context = {
        rl: {
          question: sinon.stub()
        }
      };
      Builder.prototype.prompt.call(context, 'blah', 'cb');
      context.rl.question.should.have.been.calledWith('   blah: ', 'cb');
    });
  });

  describe('.handleCustomOption', () => {
    it('should allow options', () => {
      const context = {
        config: {
          foo: 'bar'
        },
        custom: {
          foo: sinon.stub()
        }
      };
      const cb = sinon.stub();
      Builder.prototype.handleCustomOption.call(context, 'foo', cb);
      context.custom.foo.should.have.been.calledWith('bar', cb);
      context.custom.foo.should.have.been.calledOn(context);
    });

    it('should allow no options', () => {
      const context = {
        config: {},
        custom: {
          foo: sinon.stub()
        }
      };
      const cb = sinon.stub();
      Builder.prototype.handleCustomOption.call(context, 'foo', cb);
      cb.should.have.been.called;
    });
  });

  describe('getSubcommand', () => {
    it('should return only cmd when standalone is true', () => {
      const context = {
        cmd: 'cmd',
        standalone: true
      };
      Builder.prototype.getSubcommand.call(context).should.eql(['cmd']);
    });

    it('should return only cmd when config.cmd is false', () => {
      const context = {
        config: {
          cmd: false
        },
        cmd: 'cmd'
      };
      Builder.prototype.getSubcommand.call(context).should.eql(['cmd']);
    });

    it('should return cmd and target otherwise', () => {
      const context = {
        config: {},
        cmd: 'cmd',
        target: 'target'
      };
      Builder.prototype.getSubcommand.call(context).should.eql([ 'cmd', 'target' ]);
    });

    it('should return only target when excludeCmd is passed in', () => {
      const context = {
        config: {},
        cmd: 'cmd',
        target: 'target'
      };
      Builder.prototype.getSubcommand.call(context, true).should.eql(['target']);
    });
  });

  describe('.debug', () => {
    let ctx;

    beforeEach(() => {
      ctx = {
        callComplete: sinon.stub(),
        getSubcommand: sinon.stub().returns([ 'cmd', 'target' ]),
        grunt: {
          log: {
            writeln: sinon.stub()
          }
        },
        config: {
          cwd: 'cwd',
          onComplete: true,
          debug: {
            stdout: 'stdout',
            stderr: 'stderr'
          },
        },
        cmd: 'cmd',
        target: 'target',
        args: [ 'foo', 'bar' ],
        env: 'env',
        callback: sinon.stub()
      };
    });

    context('with onComplete', () => {
      it('should call the function when debug is an object', () => {
        Builder.prototype.debug.call(ctx);
        ctx.grunt.log.writeln.should.have.been.calledWith(`Command: ${chalk.cyan('cmd target foo bar')}`);
        ctx.grunt.log.writeln.should.have.been.calledWith();
        ctx.grunt.log.writeln.should.have.been.calledWith(`Options: ${chalk.cyan(util.inspect({
          env: 'env',
          cwd: 'cwd'
        }))}`);
        ctx.callComplete.should.have.been.calledWith(1, 'stderr', 'stdout');
      });

      it('should allow debug as a boolean', () => {
        ctx.config.debug = true;
        Builder.prototype.debug.call(ctx);
        ctx.grunt.log.writeln.should.have.been.calledWith(`Command: ${chalk.cyan('cmd target foo bar')}`);
        ctx.grunt.log.writeln.should.have.been.calledWith();
        ctx.grunt.log.writeln.should.have.been.calledWith(`Options: ${chalk.cyan(util.inspect({
          env: 'env',
          cwd: 'cwd'
        }))}`);
        ctx.callComplete.should.have.been.calledWith(1, '[DEBUG]: stderr', '[DEBUG]: stdout');
      });
    });

    context('wihout onComplete', () => {
      it('should call a default', () => {
        delete ctx.config.onComplete;
        Builder.prototype.debug.call(ctx);
        ctx.grunt.log.writeln.should.have.been.calledWith(`Command: ${chalk.cyan('cmd target foo bar')}`);
        ctx.grunt.log.writeln.should.have.been.calledWith();
        ctx.grunt.log.writeln.should.have.been.calledWith(`Options: ${chalk.cyan(util.inspect({
          env: 'env',
          cwd: 'cwd'
        }))}`);
        ctx.callback.should.have.been.called;
      });
    });
  });

  describe('.callComplete', () => {
    let context;

    beforeEach(() => {
      context = {
        callback: 'done',
        config: {
          onComplete: sinon.stub()
        }
      };
    });

    it('should handle a code', () => {
      Builder.prototype.callComplete.call(context, 1, 'err', 'out');
      context.config.onComplete.should.have.been.calledWith(sinon.match({ message: 'err', code: 1 }), 'out', 'done');
    });

    it('should handle no code but stderr', () => {
      Builder.prototype.callComplete.call(context, null, 'err', 'out');
      context.config.onComplete.should.have.been.calledWith(sinon.match({ message: 'err', code: null }), 'out', 'done');
    });

    it('should handle no error', () => {
      Builder.prototype.callComplete.call(context, null, null, 'out');
      context.config.onComplete.should.have.been.calledWith(null, 'out', 'done');
    });
  });

  describe('.spawn', () => {
    let child, ctx, close;

    beforeEach(() => {
      child = {
        stdout: {
          on: sinon.stub()
        },
        stderr: {
          on: sinon.stub()
        },
        on: sinon.stub()
      };

      ctx = {
        callComplete: sinon.stub(),
        getSubcommand: sinon.stub().returns(['target']),
        callback: sinon.stub(),
        cmd: 'cmd',
        target: 'target',
        args: [ 'foo', 'bar' ],
        env: 'env',
        config: {
          cwd: 'cwd',
          onComplete: true
        },
        grunt: {
          log: {
            writeln: sinon.stub()
          }
        }
      };
    });

    context('with onComplete', () => {
      beforeEach(() => {
        spawn.withArgs('cmd', [ 'target', 'foo', 'bar' ], { env: 'env', cwd: 'cwd' }).returns(child);
        Builder.prototype.spawn.call(ctx);
        child.stdout.on.getCall(0).args[1]('data');
        child.stderr.on.getCall(0).args[1]('error');
        close = child.on.getCall(0).args[1];
      });

      it('should call onComplete on success', () => {
        close();
        ctx.callComplete.should.have.been.calledWith(undefined, 'error', 'data');
        ctx.grunt.log.writeln.should.not.have.been.called;
      });

      it('should call onComplete on error', () => {
        close(1);
        ctx.callComplete.should.have.been.calledWith(1, 'error', 'data');
        ctx.grunt.log.writeln.should.not.have.been.called;
      });
    });

    context('without onComplete', () => {
      beforeEach(() => {
        spawn.withArgs('cmd', [ 'target', 'foo', 'bar' ], { env: 'env', cwd: 'cwd' }).returns(child);
        Builder.prototype.spawn.call(ctx);
        child.stdout.on.getCall(0).args[1]('data');
        child.stderr.on.getCall(0).args[1]('error');
        close = child.on.getCall(0).args[1];
        delete ctx.config.onComplete;
      });

      it('should call the callback on success', () => {
        close(0);
        ctx.callback.should.have.been.calledWith(0);
        ctx.grunt.log.writeln.should.not.have.been.called;
      });

      it('should call the callback on error', () => {
        close(1);
        ctx.callback.should.have.been.calledWith(1);
        ctx.grunt.log.writeln.should.not.have.been.called;
      });
    });

    context('with force', () => {
      beforeEach(() => {
        spawn.withArgs('cmd', [ 'target', 'foo', 'bar' ], { env: 'env', cwd: 'cwd' }).returns(child);
        Builder.prototype.spawn.call(ctx);
        child.stdout.on.getCall(0).args[1]('data');
        child.stderr.on.getCall(0).args[1]('error');
        close = child.on.getCall(0).args[1];
        ctx.config.force = true;
      });

      it('should ignore the error and call onComplete if available', () => {
        close(1);
        ctx.grunt.log.writeln.should.have.been.calledWith('cmd:target returned code 1. Ignoring...');
        ctx.callComplete.should.have.been.calledWith(0, 'error', 'data');
      });

      it('should ignore the error and call the callback when onComplete is unavailable', () => {
        delete ctx.config.onComplete;
        close(1);
        ctx.grunt.log.writeln.should.have.been.calledWith('cmd:target returned code 1. Ignoring...');
        ctx.callback.should.have.been.calledWith(0);
      });
    });
  });
});

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0143 ]--