Skip to content

Commit

Permalink
OXDEV-5511 Add file name validation
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Fedurtsya <[email protected]>
  • Loading branch information
Sieg committed Jun 19, 2024
1 parent f82026f commit 704d95e
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 5 deletions.
52 changes: 52 additions & 0 deletions src/Validation/Validator/FileNameValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\MediaLibrary\Validation\Validator;

use OxidEsales\MediaLibrary\Media\DataType\FilePathInterface;
use OxidEsales\MediaLibrary\Validation\Exception\ValidationFailedException;

class FileNameValidator implements FilePathValidatorInterface
{
//@todo: setting
public const FORBIDDEN_CHARACTERS = '/<>:"|?*\\';

public function validateFile(FilePathInterface $filePath): void
{
$fileName = $filePath->getFileName();

$this->checkFilenameNotEmpty($fileName);
$this->checkFilenameDoesNotStartWithDot($fileName);
$this->checkForbiddenCharacters($fileName);
}

private function checkForbiddenCharacters(string $fileName): void
{
$forbiddenCharacters = str_split(self::FORBIDDEN_CHARACTERS);
foreach ($forbiddenCharacters as $oneForbiddenCharacter) {
if (strpos($fileName, $oneForbiddenCharacter) !== false) {
throw new ValidationFailedException("Forbidden character found: " . $oneForbiddenCharacter);
}
}
}

public function checkFilenameNotEmpty(string $fileName): void
{
if (!$fileName) {
throw new ValidationFailedException("Filename cannot be empty");
}
}

public function checkFilenameDoesNotStartWithDot(string $fileName): void
{
if ($fileName[0] === '.') {
throw new ValidationFailedException("Filename cannot start with .");
}
}
}
5 changes: 4 additions & 1 deletion src/Validation/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ services:
public: true
arguments:
$fileValidators:
- '@OxidEsales\MediaLibrary\Validation\Validator\FileNameValidator'
- '@OxidEsales\MediaLibrary\Validation\Validator\FileExtensionValidator'

OxidEsales\MediaLibrary\Validation\Service\UploadedFileValidatorChainInterface:
class: OxidEsales\MediaLibrary\Validation\Service\UploadedFileValidatorChain
public: true
arguments:
$fileValidators:
- '@OxidEsales\MediaLibrary\Validation\Validator\FileNameValidator'
- '@OxidEsales\MediaLibrary\Validation\Validator\FileUploadStatusValidator'
- '@OxidEsales\MediaLibrary\Validation\Validator\FileExtensionValidator'

OxidEsales\MediaLibrary\Validation\Validator\FileUploadStatusValidator: ~
OxidEsales\MediaLibrary\Validation\Validator\FileExtensionValidator: ~
OxidEsales\MediaLibrary\Validation\Validator\FileNameValidator: ~
OxidEsales\MediaLibrary\Validation\Validator\FileUploadStatusValidator: ~
8 changes: 4 additions & 4 deletions tests/Unit/Validation/Service/FileNameValidatorChainTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use PHPUnit\Framework\TestCase;

/**
* @covers \OxidEsales\MediaLibrary\Validation\Service\UploadedFileValidatorChain
* @covers \OxidEsales\MediaLibrary\Validation\Service\FileNameValidatorChain
*/
class FileNameValidatorChainTest extends TestCase
{
Expand All @@ -42,12 +42,12 @@ public function testExceptionOnValidatorException(): void
{
$fileName = uniqid();

$validatorStub = $this->createMock(FilePathValidatorInterface::class);
$validatorStub->method('validateFile')->willThrowException(new ValidationFailedException());
$validatorMock = $this->createMock(FilePathValidatorInterface::class);
$validatorMock->method('validateFile')->willThrowException(new ValidationFailedException());

$this->expectException(ValidationFailedException::class);

$sut = new FileNameValidatorChain([$validatorStub]);
$sut = new FileNameValidatorChain([$validatorMock]);
$sut->validateFileName($fileName);
}
}
74 changes: 74 additions & 0 deletions tests/Unit/Validation/Validator/FileNameValidatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\MediaLibrary\Tests\Unit\Validation\Validator;

use OxidEsales\MediaLibrary\Media\DataType\FilePath;
use OxidEsales\MediaLibrary\Validation\Exception\ValidationFailedException;
use OxidEsales\MediaLibrary\Validation\Validator\FileNameValidator;
use PHPUnit\Framework\TestCase;

class FileNameValidatorTest extends TestCase
{
public function testRegularFileNameDoesntThrowExceptions(): void
{
$filePathStub = $this->createConfiguredStub(FilePath::class, [
'getFileName' => uniqid()
]);

$sut = new FileNameValidator();
$sut->validateFile($filePathStub);

$this->addToAssertionCount(1);
}

public static function goodFileNamesDataProvider(): \Generator
{
yield "regular file name" => [
'baseName' => uniqid(),
'extension' => uniqid()
];
}

public static function badFileNamesDataProvider(): \Generator
{
yield "empty" => [
'fileName' => ''
];

yield "starts with dot" => [
'fileName' => '.' . uniqid()
];
}

public static function forbiddenCharactersDataProvider(): \Generator
{
$characters = str_split(FileNameValidator::FORBIDDEN_CHARACTERS);

foreach ($characters as $character) {
yield ['fileName' => uniqid() . $character . uniqid()];
}
}

/**
* @dataProvider badFileNamesDataProvider
* @dataProvider forbiddenCharactersDataProvider
*/
public function testFileNameEmptyThrowsException(string $fileName): void
{
$filePathStub = $this->createConfiguredStub(FilePath::class, [
'getFileName' => $fileName
]);

$this->expectException(ValidationFailedException::class);

$sut = new FileNameValidator();
$sut->validateFile($filePathStub);
}
}

0 comments on commit 704d95e

Please sign in to comment.