From 0d361d9e5add4be67722201fa7ebf1a24f8a7ed3 Mon Sep 17 00:00:00 2001 From: Katherine Wu Date: Tue, 8 Oct 2024 17:35:48 -0700 Subject: [PATCH] add check --- src/shellEscape.ts | 27 +++++++++++++++++++++++++++ src/stripeTerminal.ts | 7 +++++-- test/suite/shellEscape.test.ts | 30 ++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 src/shellEscape.ts create mode 100644 test/suite/shellEscape.test.ts diff --git a/src/shellEscape.ts b/src/shellEscape.ts new file mode 100644 index 00000000..76cff1a6 --- /dev/null +++ b/src/shellEscape.ts @@ -0,0 +1,27 @@ +import {OSType, getOSType} from './utils'; + +export function shellEscape(args: Array): string { + var output: Array = []; + + if (getOSType() === OSType.windows) { + args.forEach(function(arg) { + if (/[^A-Za-z0-9_\/:=-]/.test(arg)) { + arg = '"' + arg.replace(/"/g, '\\"') + '"'; + arg = arg.replace(/^(?:"")+/g, '') // unduplicate double-quote at the beginning + .replace(/\\"""/g, '\\"'); // remove non-escaped double-quote if there are enclosed between 2 escaped + } + output.push(arg); + }); + return output.join(' '); + } else { + args.forEach(function(arg) { + if (/[^A-Za-z0-9_\/:=-]/.test(arg)) { + arg = "'" + arg.replace(/'/g,"'\\''") + "'"; + arg = arg.replace(/^(?:'')+/g, '') // unduplicate single-quote at the beginning + .replace(/\\'''/g, "\\'"); // remove non-escaped single-quote if there are enclosed between 2 escaped + }; + output.push(arg); + }); + return output.join(' '); + }; +}; diff --git a/src/stripeTerminal.ts b/src/stripeTerminal.ts index 1a7d3014..97265359 100644 --- a/src/stripeTerminal.ts +++ b/src/stripeTerminal.ts @@ -1,5 +1,6 @@ import * as vscode from 'vscode'; import {StripeClient} from './stripeClient'; +import {shellEscape} from './shellEscape'; type SupportedStripeCommand = 'events' | 'listen' | 'logs' | 'login' | 'trigger'; @@ -29,9 +30,11 @@ export class StripeTerminal { } } - const globalCLIFLags = this.getGlobalCLIFlags(); + const globalCLIFlags = this.getGlobalCLIFlags(); + + const commandString = shellEscape([cliPath, command, ...args, ...globalCLIFlags]); + - const commandString = [cliPath, command, ...args, ...globalCLIFLags].join(' '); try { const terminal = await this.createTerminal(); diff --git a/test/suite/shellEscape.test.ts b/test/suite/shellEscape.test.ts new file mode 100644 index 00000000..3cfe043b --- /dev/null +++ b/test/suite/shellEscape.test.ts @@ -0,0 +1,30 @@ +import * as assert from 'assert'; +import * as shellEscape from '../../src/shellEscape'; +import * as sinon from 'sinon'; +import * as utils from '../../src/utils'; + + +suite('shellEscape', () => { + let sandbox: sinon.SinonSandbox; + + setup(() => { + sandbox = sinon.createSandbox(); + }); + + teardown(() => { + sandbox.restore(); + }); + + suite('shellEscape', () => { + test('non windows case: flag with spaces', () => { + sandbox.stub(utils, 'getOSType').returns(utils.OSType.macOSarm); + const output = shellEscape.shellEscape(['--project-name', 'test | whoami']); + assert.strictEqual(output, '--project-name \'test | whoami\''); + }); + test.only('windows case: flag with space', () => { + sandbox.stub(utils, 'getOSType').returns(utils.OSType.windows); + const output = shellEscape.shellEscape(['--project-name', 'test | whoami']); + assert.strictEqual(output, '--project-name \"test | whoami\"'); + }) + }); +});