From ca03dc1880820811d3d01e293ccf6227dda8765d Mon Sep 17 00:00:00 2001 From: alexpozzi Date: Wed, 13 Sep 2023 08:38:20 +0200 Subject: [PATCH 1/2] fix: allowed output file protocols on Windows --- .github/workflows/build.yaml | 42 ++++++++++++++++++++++++++++ src/Knp/Snappy/AbstractGenerator.php | 12 ++++++-- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a5a30901..ba7cde3b 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -83,3 +83,45 @@ jobs: - run: composer update --prefer-dist --no-interaction --no-progress --ansi ${{ matrix.composer_option }} - run: vendor/bin/phpunit - run: vendor/bin/phpstan analyse --ansi --no-progress + tests-windows: + runs-on: windows-2022 + strategy: + fail-fast: false + matrix: + include: + - description: 'Symfony 6.4 DEV' + php: '8.2' + symfony: '6.4.*@dev' + - description: 'Symfony 6.3' + php: '8.3' + symfony: '6.3.*' + - description: 'Symfony 6.3' + php: '8.2' + symfony: '6.3.*' + name: "[WINDOWS] PHP ${{ matrix.php }} tests (${{ matrix.description }})" + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Cache + uses: actions/cache@v3 + with: + path: ~/.composer/cache/files + key: composer-${{ matrix.php }}-${{ matrix.symfony }}-${{ matrix.composer_option }} + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + - run: | + (Get-Content composer.json) -replace '("symfony/[^"]+": )"[^"]+"', '$1"${{ matrix.symfony }}"' | Out-File -encoding ASCII composer.json + if: matrix.symfony + - run: | + composer config minimum-stability dev + composer config prefer-stable true + if: matrix.beta + - name: remove cs-fixer for Symfony 6 + if: contains(matrix.symfony, '6.4.*@dev') + run: | + composer remove --dev friendsofphp/php-cs-fixer pedrotroller/php-cs-custom-fixer --no-update + - run: composer update --prefer-dist --no-interaction --no-progress --ansi ${{ matrix.composer_option }} + - run: vendor/bin/phpunit + - run: vendor/bin/phpstan analyse --ansi --no-progress diff --git a/src/Knp/Snappy/AbstractGenerator.php b/src/Knp/Snappy/AbstractGenerator.php index 1189e95a..c2aad853 100644 --- a/src/Knp/Snappy/AbstractGenerator.php +++ b/src/Knp/Snappy/AbstractGenerator.php @@ -630,8 +630,16 @@ protected function prepareOutput($filename, $overwrite) } $scheme = isset($parsedFilename['scheme']) ? \mb_strtolower($parsedFilename['scheme']) : ''; - if ($scheme !== '' && $scheme !== 'file') { - throw new InvalidArgumentException(\sprintf('The output file scheme is not supported. Expected \'\' or \'file\' but got \'%s\'.', $scheme)); + if (!( + $scheme === '' || + $scheme === 'file' || + ( + // Check if it's a Windows path + \strlen($scheme) === 1 && + \preg_match('/^[a-z]:(?:[\\\\\/]?(?:[\w\s!#()-]+|[\.]{1,2})+)*[\\\\\/]?/i', $filename) === 1 + ) + )) { + throw new InvalidArgumentException(\sprintf('The output file scheme is not supported. Expected \'file\' but got \'%s\'.', $scheme)); } $directory = \dirname($filename); From 63f18db8f36198acc4de7c9c9a779a063ef80a69 Mon Sep 17 00:00:00 2001 From: alexpozzi Date: Wed, 13 Sep 2023 11:46:21 +0200 Subject: [PATCH 2/2] fix: review --- src/Knp/Snappy/AbstractGenerator.php | 49 +++++++++++++++++++--------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/Knp/Snappy/AbstractGenerator.php b/src/Knp/Snappy/AbstractGenerator.php index c2aad853..2a93529b 100644 --- a/src/Knp/Snappy/AbstractGenerator.php +++ b/src/Knp/Snappy/AbstractGenerator.php @@ -21,6 +21,10 @@ abstract class AbstractGenerator implements GeneratorInterface, LoggerAwareInter { use LoggerAwareTrait; + protected const ALLOWED_PROTOCOLS = ['file']; + + protected const WINDOWS_LOCAL_FILENAME_REGEX = '/^[a-z]:(?:[\\\\\/]?(?:[\w\s!#()-]+|[\.]{1,2})+)*[\\\\\/]?/i'; + /** * @var array */ @@ -625,21 +629,8 @@ protected function executeCommand($command) */ protected function prepareOutput($filename, $overwrite) { - if (false === $parsedFilename = \parse_url($filename)) { - throw new InvalidArgumentException('The output filename is invalid.'); - } - - $scheme = isset($parsedFilename['scheme']) ? \mb_strtolower($parsedFilename['scheme']) : ''; - if (!( - $scheme === '' || - $scheme === 'file' || - ( - // Check if it's a Windows path - \strlen($scheme) === 1 && - \preg_match('/^[a-z]:(?:[\\\\\/]?(?:[\w\s!#()-]+|[\.]{1,2})+)*[\\\\\/]?/i', $filename) === 1 - ) - )) { - throw new InvalidArgumentException(\sprintf('The output file scheme is not supported. Expected \'file\' but got \'%s\'.', $scheme)); + if (!$this->isProtocolAllowed($filename)) { + throw new InvalidArgumentException(\sprintf('The output file scheme is not supported. Expected one of [\'%s\'].', \implode('\', \'', self::ALLOWED_PROTOCOLS))); } $directory = \dirname($filename); @@ -659,6 +650,34 @@ protected function prepareOutput($filename, $overwrite) } } + /** + * Verifies if the given filename has a supported protocol. + * + * @param string $filename + * + * @throws InvalidArgumentException + * + * @return bool + */ + protected function isProtocolAllowed($filename) + { + if (false === $parsedFilename = \parse_url($filename)) { + throw new InvalidArgumentException('The filename is not valid.'); + } + + $protocol = isset($parsedFilename['scheme']) ? \mb_strtolower($parsedFilename['scheme']) : 'file'; + + if ( + \PHP_OS_FAMILY === 'Windows' + && \strlen($protocol) === 1 + && \preg_match(self::WINDOWS_LOCAL_FILENAME_REGEX, $filename) + ) { + $protocol = 'file'; + } + + return \in_array($protocol, self::ALLOWED_PROTOCOLS, true); + } + /** * Wrapper for the "file_get_contents" function. *