diff --git a/src/Service/Share/Exception/InvalidPathException.php b/src/Service/Share/Exception/InvalidPathException.php new file mode 100644 index 0000000..49d1280 --- /dev/null +++ b/src/Service/Share/Exception/InvalidPathException.php @@ -0,0 +1,9 @@ +normalizeRelative($relativePath); + + $parts = array_values(array_filter([$base, $relative], static fn (string $p): bool => '' !== $p)); + + return '/'.implode('/', $parts); + } +} diff --git a/tests/Unit/Service/SharePathResolverTest.php b/tests/Unit/Service/SharePathResolverTest.php new file mode 100644 index 0000000..bc344ee --- /dev/null +++ b/tests/Unit/Service/SharePathResolverTest.php @@ -0,0 +1,64 @@ +resolver = new SharePathResolver(); + } + + public function testNormalizeRelativeKeepsSimplePath(): void + { + self::assertSame('a/b', $this->resolver->normalizeRelative('a/b')); + } + + public function testNormalizeRelativeStripsDotsAndSlashes(): void + { + self::assertSame('a/b', $this->resolver->normalizeRelative('/a/./b/')); + } + + public function testNormalizeRelativeConvertsBackslashes(): void + { + self::assertSame('a/b', $this->resolver->normalizeRelative('a\b')); + } + + public function testNormalizeRelativeRejectsParentTraversal(): void + { + $this->expectException(InvalidPathException::class); + $this->resolver->normalizeRelative('a/../b'); + } + + public function testNormalizeRelativeRejectsLeadingParent(): void + { + $this->expectException(InvalidPathException::class); + $this->resolver->normalizeRelative('../etc/passwd'); + } + + public function testFullPathJoinsBaseAndRelative(): void + { + self::assertSame('/Projets/a/b', $this->resolver->fullPath('/Projets', 'a/b')); + } + + public function testFullPathWithEmptyBaseAndEmptyRelativeIsRoot(): void + { + self::assertSame('/', $this->resolver->fullPath('', '')); + } + + public function testFullPathTrimsBaseSlashes(): void + { + self::assertSame('/Projets/a', $this->resolver->fullPath('/Projets/', 'a')); + } +}