Skip to content

Commit

Permalink
Add tests for filesystem
Browse files Browse the repository at this point in the history
Add normalization for parent dir path
  • Loading branch information
untone-survive committed Sep 28, 2023
1 parent 7179e51 commit 333cb8d
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 5 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
}
},
"require-dev": {
"mikey179/vfsstream": "^1.6",
"phpunit/phpunit": "^10",
"psr/log": "^2.0",
"slevomat/coding-standard": "^8.8.0",
Expand Down
55 changes: 53 additions & 2 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 14 additions & 3 deletions src/WappMatchers/UpLevelMatcherTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace Plesk\Wappspector\WappMatchers;

use League\Flysystem\Filesystem;
use League\Flysystem\PathTraversalDetected;
use League\Flysystem\UnableToListContents;
use League\Flysystem\WhitespacePathNormalizer;

trait UpLevelMatcherTrait
{
Expand All @@ -19,10 +21,19 @@ private function safeScanDir(Filesystem $fs, string $path): array
$result = [];
try {
$result = $this->doMatch($fs, $path);
} catch (UnableToListContents) {
// skip dir if it is inaccessible
} catch (UnableToListContents | PathTraversalDetected) {
// skip dir if it is inaccessible
}

return $result;
return $this->normalizeMatcherPath($result);
}

private function normalizeMatcherPath(array $matcher): array
{
if (array_key_exists('path', $matcher)) {
$matcher['path'] = (new WhitespacePathNormalizer())->normalizePath($matcher['path']);
}

return $matcher;
}
}
99 changes: 99 additions & 0 deletions tests/WappMatchers/UpLevelMatcherTraitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

declare(strict_types=1);


namespace Test\WappMatchers;

use League\Flysystem\Filesystem;
use League\Flysystem\StorageAttributes;
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
use Plesk\Wappspector\FileSystemFactory;
use Plesk\Wappspector\WappMatchers\UpLevelMatcherTrait;
use Plesk\Wappspector\WappMatchers\WappMatcherInterface;

#[CoversClass(UpLevelMatcherTrait::class)]
class UpLevelMatcherTraitTest extends TestCase
{
protected vfsStreamDirectory $root;
protected Filesystem $fs;

protected function setUp(): void
{
$this->root = vfsStream::setup();
$this->fs = (new FileSystemFactory())($this->root->url());
}

public function testNoParentDir(): void
{
vfsStream::create([
'readme.txt' => '',
]);

$result = $this->getTestMatcher()->match($this->fs, '');
$this->assertIsArray($result);
$this->assertEmpty($result);
}

public function testInaccessibleParentDir(): void
{
vfsStream::create([
'unreadable' => [
'readable' => [
'readme.txt' => '',
],
'readme.md' => '',
],
]);

$this->root->getChild('unreadable')->chmod(0000)->chown(0);

$result = $this->getTestMatcher()->match($this->fs, 'unreadable/readable');
$this->assertIsArray($result);
$this->assertEmpty($result);
}

public function testParentDirNormalization(): void
{
vfsStream::create([
'parent' => [
'child' => [
'readme.txt' => '',
],
'readme.md' => '',
],
]);

$result = $this->getTestMatcher()->match($this->fs, 'parent/child');
$this->assertIsArray($result);
$this->assertArrayHasKey('path', $result);
$this->assertStringNotContainsString('..', $result['path']);
}

public function getTestMatcher(): WappMatcherInterface
{
return new class () implements WappMatcherInterface {
use UpLevelMatcherTrait;

protected function doMatch(Filesystem $fs, string $path): array
{
$list = $fs->listContents($path);
foreach ($list as $item) {
/** @var StorageAttributes $item */
if ($item->isFile() && str_ends_with($item->path(), '.md')) {
return [
'matcher' => 'markdown',
'path' => $path,
'version' => null,
];
}
}

return [];
}
};
}
}

0 comments on commit 333cb8d

Please sign in to comment.