diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 42a452c..3e1d638 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: name: 'Tests' steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: @@ -21,12 +21,12 @@ jobs: extensions: mbstring, intl coverage: xdebug - name: Composer - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: dependency-versions: ${{ matrix.dependencies }} - name: PHPUnit run: vendor/bin/phpunit --coverage-clover=coverage.clover --exclude-group=fixtures - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} fixtures: @@ -39,7 +39,7 @@ jobs: name: 'Fixtures' steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: @@ -47,12 +47,12 @@ jobs: extensions: mbstring, intl coverage: xdebug - name: Composer - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: dependency-versions: ${{ matrix.dependencies }} - name: PHPUnit run: vendor/bin/phpunit --coverage-clover=coverage.clover --group=fixtures - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} psalm: @@ -64,14 +64,14 @@ jobs: name: 'Psalm' steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} extensions: mbstring, intl - name: Composer - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: dependency-versions: ${{ matrix.dependencies }} - name: Psalm @@ -84,13 +84,13 @@ jobs: name: 'CS' steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} extensions: mbstring, intl - name: Composer - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" - name: CS run: vendor/bin/php-cs-fixer fix --diff --dry-run diff --git a/CHANGELOG.md b/CHANGELOG.md index 748e621..8217b64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 4.3.1 - 2024-10-19 + +### Changed + +- `Innmind\Url\Authority\UserInformation\Password` inner value is now stored inside a `\SensitiveParameterValue` to prevent a password being accidently displayed in a dump/log. + ## 4.3.0 - 2023-09-16 ### Added diff --git a/composer.json b/composer.json index 8802173..3316a88 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,7 @@ }, "require-dev": { "phpunit/phpunit": "~10.2", - "vimeo/psalm": "~5.13", + "vimeo/psalm": "~5.26", "innmind/black-box": "~5.0", "innmind/coding-standard": "~2.0" }, diff --git a/src/Authority.php b/src/Authority.php index e8c91e8..873b3b5 100644 --- a/src/Authority.php +++ b/src/Authority.php @@ -45,9 +45,9 @@ public static function of( public static function none(): self { return new self( - Authority\UserInformation::none(), - Authority\Host::none(), - Authority\Port::none(), + UserInformation::none(), + Host::none(), + Port::none(), ); } diff --git a/src/Authority/Port.php b/src/Authority/Port.php index 015d86e..8c77133 100644 --- a/src/Authority/Port.php +++ b/src/Authority/Port.php @@ -53,7 +53,10 @@ public function format(): string public function value(): int { - return $this->value ?: 0; + return match ($this->value) { + null => 0, + default => $this->value, + }; } public function toString(): string diff --git a/src/Authority/UserInformation/Password.php b/src/Authority/UserInformation/Password.php index e373bdc..adb0315 100644 --- a/src/Authority/UserInformation/Password.php +++ b/src/Authority/UserInformation/Password.php @@ -15,11 +15,12 @@ final class Password { private const PATTERN = '/^[\pL\pN-]+$/'; - private string $value; + /** @var \SensitiveParameterValue */ + private \SensitiveParameterValue $value; private function __construct(string $value) { - $this->value = $value; + $this->value = new \SensitiveParameterValue($value); } /** @@ -44,12 +45,12 @@ public static function none(): self public function equals(self $password): bool { - return $this->value === $password->value; + return $this->value->getValue() === $password->value->getValue(); } public function format(User $user): string { - if ($this->value === '') { + if ($this->value->getValue() === '') { return $user->toString(); } @@ -57,11 +58,11 @@ public function format(User $user): string throw new PasswordCannotBeSpecifiedWithoutAUser; } - return $user->toString().':'.$this->value; + return $user->toString().':'.(string) $this->value->getValue(); } public function toString(): string { - return $this->value; + return $this->value->getValue(); } } diff --git a/src/Url.php b/src/Url.php index ef9cc73..a4d502f 100644 --- a/src/Url.php +++ b/src/Url.php @@ -55,18 +55,42 @@ public static function of(string $string): self } return new self( - $data['scheme'] ? Scheme::of($data['scheme']) : Scheme::none(), + match ($data['scheme']) { + null, '' => Scheme::none(), + default => Scheme::of($data['scheme']), + }, Authority::of( UserInformation::of( - $data['user'] ? User::of($data['user']) : User::none(), - $data['pass'] ? Password::of($data['pass']) : Password::none(), + match ($data['user']) { + null, '' => User::none(), + default => User::of($data['user']), + }, + match ($data['pass']) { + null, '' => Password::none(), + default => Password::of($data['pass']), + }, ), - $data['host'] ? Host::of($data['host']) : Host::none(), - $data['port'] ? Port::of((int) $data['port']) : Port::none(), + match ($data['host']) { + null, '' => Host::none(), + default => Host::of($data['host']), + }, + match ($data['port']) { + null, '' => Port::none(), + default => Port::of((int) $data['port']), + }, ), - $data['path'] && !empty($data['path']) ? Path::of($data['path']) : Path::none(), - $data['query'] ? Query::of($data['query']) : Query::none(), - $data['fragment'] ? Fragment::of($data['fragment']) : Fragment::none(), + match ($data['path']) { + null, '' => Path::none(), + default => Path::of($data['path']), + }, + match ($data['query']) { + null, '' => Query::none(), + default => Query::of($data['query']), + }, + match ($data['fragment']) { + null, '' => Fragment::none(), + default => Fragment::of($data['fragment']), + }, ); } diff --git a/tests/AuthorityTest.php b/tests/AuthorityTest.php index b617a67..266627e 100644 --- a/tests/AuthorityTest.php +++ b/tests/AuthorityTest.php @@ -219,7 +219,7 @@ public function testEquals() { $this ->forAll(Fixture::any(), Fixture::any()) - ->filter(fn($a, $b) => $a->toString() !== $b->toString()) + ->filter(static fn($a, $b) => $a->toString() !== $b->toString()) ->then(function($a, $b) { $this->assertTrue($a->equals($a)); $this->assertTrue( diff --git a/tests/UrlTest.php b/tests/UrlTest.php index 61f2c3f..a63440b 100644 --- a/tests/UrlTest.php +++ b/tests/UrlTest.php @@ -285,7 +285,7 @@ public function testEquals() { $this ->forAll(Fixture::any(), Fixture::any()) - ->filter(fn($a, $b) => $a->toString() !== $b->toString()) + ->filter(static fn($a, $b) => $a->toString() !== $b->toString()) ->then(function($a, $b) { $this->assertTrue($a->equals($a)); $this->assertTrue($a->equals(new Url(