From 45390b4cb10d03a675a19f52cc30d96ed736caff Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 16 Jan 2025 05:44:15 +0100 Subject: [PATCH 01/13] cs --- src/Http/RequestFactory.php | 2 +- tests/Http/Request.files.directory.phpt | 2 +- tests/Http/Request.files.phpt | 8 ++++---- tests/Http/Request.files2.phpt | 2 +- tests/Http/Request.invalidEncoding.phpt | 6 +++--- tests/Http/Request.request.phpt | 2 +- tests/Http/RequestFactory.scriptPath.phpt | 4 ++-- tests/bootstrap.php | 4 ++-- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Http/RequestFactory.php b/src/Http/RequestFactory.php index f44490e7..4dc78463 100644 --- a/src/Http/RequestFactory.php +++ b/src/Http/RequestFactory.php @@ -70,7 +70,7 @@ public function fromGlobals(): Request $this->getMethod(), $remoteAddr, $remoteHost, - fn(): string => file_get_contents('php://input') + fn(): string => file_get_contents('php://input'), ); } diff --git a/tests/Http/Request.files.directory.phpt b/tests/Http/Request.files.directory.phpt index 366c105a..d13db65f 100644 --- a/tests/Http/Request.files.directory.phpt +++ b/tests/Http/Request.files.directory.phpt @@ -19,7 +19,7 @@ $_FILES = [ 'name' => ['a.jpg', 'c.jpg'], 'type' => ['image/jpeg', 'image/jpeg'], 'full_path' => ['a.jpg', 'b/c.jpg'], - 'tmp_name' => ['C:\\PHP\\temp\\php1D5D.tmp', 'C:\\PHP\\temp\\php1D5E.tmp'], + 'tmp_name' => ['C:\PHP\temp\php1D5D.tmp', 'C:\PHP\temp\php1D5E.tmp'], 'error' => [0, 0], 'size' => [12345, 54321], ], diff --git a/tests/Http/Request.files.phpt b/tests/Http/Request.files.phpt index b369ead4..d2ee3405 100644 --- a/tests/Http/Request.files.phpt +++ b/tests/Http/Request.files.phpt @@ -17,7 +17,7 @@ $_FILES = [ 'file1' => [ 'name' => 'readme.txt', 'type' => 'text/plain', - 'tmp_name' => 'C:\\PHP\\temp\\php1D5B.tmp', + 'tmp_name' => 'C:\PHP\temp\php1D5B.tmp', 'error' => 0, 'size' => 209, ], @@ -32,7 +32,7 @@ $_FILES = [ ], 'tmp_name' => [ - 2 => 'C:\\PHP\\temp\\php1D5C.tmp', + 2 => 'C:\PHP\temp\php1D5C.tmp', ], 'error' => [ @@ -61,9 +61,9 @@ $_FILES = [ 'tmp_name' => [ 'y' => [ - 'z' => 'C:\\PHP\\temp\\php1D5D.tmp', + 'z' => 'C:\PHP\temp\php1D5D.tmp', ], - 1 => 'C:\\PHP\\temp\\php1D5E.tmp', + 1 => 'C:\PHP\temp\php1D5E.tmp', ], 'error' => [ diff --git a/tests/Http/Request.files2.phpt b/tests/Http/Request.files2.phpt index b4024960..b7d86458 100644 --- a/tests/Http/Request.files2.phpt +++ b/tests/Http/Request.files2.phpt @@ -17,7 +17,7 @@ $_FILES = [ 'files' => [ 'name' => ['1a.jpg'], 'type' => ['image/jpeg'], - 'tmp_name' => ['C:\\PHP\\temp\\php1D5D.tmp'], + 'tmp_name' => ['C:\PHP\temp\php1D5D.tmp'], 'error' => [0], 'size' => [12345], ], diff --git a/tests/Http/Request.invalidEncoding.phpt b/tests/Http/Request.invalidEncoding.phpt index 96410a3f..d906dcf6 100644 --- a/tests/Http/Request.invalidEncoding.phpt +++ b/tests/Http/Request.invalidEncoding.phpt @@ -44,21 +44,21 @@ $_FILES = [ INVALID => [ 'name' => 'readme.txt', 'type' => 'text/plain', - 'tmp_name' => 'C:\\PHP\\temp\\php1D5B.tmp', + 'tmp_name' => 'C:\PHP\temp\php1D5B.tmp', 'error' => 0, 'size' => 209, ], CONTROL_CHARACTERS => [ 'name' => 'readme.txt', 'type' => 'text/plain', - 'tmp_name' => 'C:\\PHP\\temp\\php1D5B.tmp', + 'tmp_name' => 'C:\PHP\temp\php1D5B.tmp', 'error' => 0, 'size' => 209, ], 'file1' => [ 'name' => INVALID, 'type' => 'text/plain', - 'tmp_name' => 'C:\\PHP\\temp\\php1D5B.tmp', + 'tmp_name' => 'C:\PHP\temp\php1D5B.tmp', 'error' => 0, 'size' => 209, ], diff --git a/tests/Http/Request.request.phpt b/tests/Http/Request.request.phpt index d51e7e07..5e4f6e01 100644 --- a/tests/Http/Request.request.phpt +++ b/tests/Http/Request.request.phpt @@ -19,7 +19,7 @@ $_SERVER = [ 'QUERY_STRING' => 'x param=val.&pa%%72am=val2¶m3=v%20a%26l%3Du%2Be)', 'REMOTE_ADDR' => '192.168.188.66', 'REQUEST_METHOD' => 'GET', - 'REQUEST_URI' => '/file.php?x param=val.&pa%%72am=val2"es\\"=\\"¶m3=v%20a%26l%3Du%2Be)', + 'REQUEST_URI' => '/file.php?x param=val.&pa%%72am=val2"es\"=\"¶m3=v%20a%26l%3Du%2Be)', 'SCRIPT_NAME' => '/file.php', ]; diff --git a/tests/Http/RequestFactory.scriptPath.phpt b/tests/Http/RequestFactory.scriptPath.phpt index 93a6896a..09fd45d6 100644 --- a/tests/Http/RequestFactory.scriptPath.phpt +++ b/tests/Http/RequestFactory.scriptPath.phpt @@ -117,7 +117,7 @@ test('', function () use ($factory) { test('', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/', - 'SCRIPT_NAME' => 'c:\\index.php', + 'SCRIPT_NAME' => 'c:\index.php', ]; Assert::same('/', $factory->fromGlobals()->getUrl()->getScriptPath()); @@ -127,7 +127,7 @@ test('', function () use ($factory) { test('', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => null, - 'SCRIPT_NAME' => 'c:\\index.php', + 'SCRIPT_NAME' => 'c:\index.php', ]; Assert::same('/', $factory->fromGlobals()->getUrl()->getScriptPath()); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index f1ff2142..f70c927f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -19,9 +19,9 @@ function getTempDir(): string { $dir = __DIR__ . '/tmp/' . getmypid(); - if (empty($GLOBALS['\\lock'])) { + if (empty($GLOBALS['\lock'])) { // garbage collector - $GLOBALS['\\lock'] = $lock = fopen(__DIR__ . '/lock', 'w'); + $GLOBALS['\lock'] = $lock = fopen(__DIR__ . '/lock', 'w'); if (rand(0, 100)) { flock($lock, LOCK_SH); @mkdir(dirname($dir)); From fea62b750ea65f891511f7381d9c9e86e54abe87 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 2 Feb 2025 03:28:41 +0100 Subject: [PATCH 02/13] tests: improved descriptions --- tests/Http.DI/HttpExtension.cookie.phpt | 4 +-- tests/Http.DI/HttpExtension.cookieSecure.phpt | 6 ++-- tests/Http/FileUpload.basic.phpt | 10 +++---- tests/Http/FileUpload.getSanitizedName.phpt | 6 ++-- tests/Http/Helpers.phpt | 6 ++-- tests/Http/Request.detectLanguage.phpt | 8 ++--- tests/Http/Request.getOrigin.phpt | 6 ++-- tests/Http/Request.getRawBody.phpt | 4 +-- tests/Http/Request.headers.phpt | 6 ++-- tests/Http/Request.invalidEncoding.phpt | 4 +-- tests/Http/Request.invalidType.phpt | 4 +-- tests/Http/Request.manipulation.phpt | 2 +- tests/Http/Request.request.phpt | 4 +-- tests/Http/RequestFactory.authorization.phpt | 6 ++-- .../Http/RequestFactory.proxy.forwarded.phpt | 10 +++---- .../RequestFactory.proxy.x-forwarded.phpt | 10 +++---- tests/Http/RequestFactory.query.phpt | 4 +-- tests/Http/RequestFactory.scriptPath.phpt | 30 +++++++++---------- .../Http/SessionSection.setExpiration().phpt | 4 +-- tests/Http/Url.fileScheme.phpt | 4 +-- tests/Http/Url.removeDotSegments.phpt | 8 ++--- tests/Http/UrlImmutable.manipulation.phpt | 8 ++--- tests/Http/UrlScript.manipulation.phpt | 2 +- tests/Http/UrlScript.usage.phpt | 10 +++---- 24 files changed, 83 insertions(+), 83 deletions(-) diff --git a/tests/Http.DI/HttpExtension.cookie.phpt b/tests/Http.DI/HttpExtension.cookie.phpt index 3635d81a..bfaa6823 100644 --- a/tests/Http.DI/HttpExtension.cookie.phpt +++ b/tests/Http.DI/HttpExtension.cookie.phpt @@ -10,7 +10,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('cookiePath & cookieDomain', function () { +test('cookie path and domain configuration', function () { $compiler = new DI\Compiler; $compiler->addExtension('http', new HttpExtension); $compiler->addExtension('session', new SessionExtension(false, PHP_SAPI === 'cli')); @@ -30,7 +30,7 @@ test('cookiePath & cookieDomain', function () { }); -test('cookieDomain = domain', function () { +test('cookie domain normalization based on request host', function () { $compiler = new DI\Compiler; $compiler->addExtension('http', new HttpExtension); $compiler->addExtension('session', new SessionExtension(false, PHP_SAPI === 'cli')); diff --git a/tests/Http.DI/HttpExtension.cookieSecure.phpt b/tests/Http.DI/HttpExtension.cookieSecure.phpt index 106ffc49..191051c3 100644 --- a/tests/Http.DI/HttpExtension.cookieSecure.phpt +++ b/tests/Http.DI/HttpExtension.cookieSecure.phpt @@ -10,7 +10,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('cookie secure flag disabled', function () { $compiler = new DI\Compiler; $compiler->addExtension('http', new HttpExtension); $compiler->addExtension('session', new SessionExtension(false, PHP_SAPI === 'cli')); @@ -30,7 +30,7 @@ test('', function () { }); -test('', function () { +test('cookie secure flag enabled', function () { $compiler = new DI\Compiler; $compiler->addExtension('http', new HttpExtension); $compiler->addExtension('session', new SessionExtension(false, PHP_SAPI === 'cli')); @@ -50,7 +50,7 @@ test('', function () { }); -test('', function () { +test('auto cookie secure flag based on HTTPS', function () { $compiler = new DI\Compiler; $compiler->addExtension('http', new HttpExtension); $compiler->addExtension('session', new SessionExtension(false, PHP_SAPI === 'cli')); diff --git a/tests/Http/FileUpload.basic.phpt b/tests/Http/FileUpload.basic.phpt index acce33f4..ec9157e4 100644 --- a/tests/Http/FileUpload.basic.phpt +++ b/tests/Http/FileUpload.basic.phpt @@ -12,7 +12,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('basic upload properties', function () { $upload = new FileUpload([ 'name' => 'readme.txt', 'full_path' => 'path/to/readme.txt', @@ -38,7 +38,7 @@ test('', function () { }); -test('', function () { +test('sanitizing name with image detection', function () { $upload = new FileUpload([ 'name' => '../.image.png', 'type' => 'text/plain', @@ -57,7 +57,7 @@ test('', function () { }); -test('', function () { +test('no file uploaded', function () { $upload = new FileUpload([ 'name' => '', 'type' => '', @@ -75,7 +75,7 @@ test('', function () { }); -test('', function () { +test('empty upload data', function () { $upload = new FileUpload([]); Assert::false($upload->isOk()); @@ -87,7 +87,7 @@ test('', function () { }); -test('', function () { +test('upload from file path', function () { $upload = new FileUpload($file = __DIR__ . '/files/file.txt'); Assert::same('file.txt', $upload->getName()); diff --git a/tests/Http/FileUpload.getSanitizedName.phpt b/tests/Http/FileUpload.getSanitizedName.phpt index 2245a101..c4a3a459 100644 --- a/tests/Http/FileUpload.getSanitizedName.phpt +++ b/tests/Http/FileUpload.getSanitizedName.phpt @@ -23,7 +23,7 @@ function getSanitizedName(string $name, ?string $type = null): string } -test('name', function () { +test('sanitized name without MIME', function () { Assert::same('unknown', getSanitizedName('')); Assert::same('unknown', getSanitizedName('--')); Assert::same('foo', getSanitizedName('foo')); @@ -36,7 +36,7 @@ test('name', function () { }); -test('name & extension', function () { +test('sanitized name with PDF type', function () { Assert::same('unknown', getSanitizedName('', 'application/pdf')); Assert::same('unknown', getSanitizedName('--', 'application/pdf')); Assert::same('foo', getSanitizedName('foo', 'application/pdf')); @@ -46,7 +46,7 @@ test('name & extension', function () { }); -test('image name & extension', function () { +test('sanitized name with JPEG type', function () { Assert::same('unknown.jpeg', getSanitizedName('', 'image/jpeg')); Assert::same('unknown.jpeg', getSanitizedName('--', 'image/jpeg')); Assert::same('foo.jpeg', getSanitizedName('foo', 'image/jpeg')); diff --git a/tests/Http/Helpers.phpt b/tests/Http/Helpers.phpt index 87b1a4dd..cf844fa6 100644 --- a/tests/Http/Helpers.phpt +++ b/tests/Http/Helpers.phpt @@ -12,7 +12,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('IPv4 address matching', function () { Assert::true(Helpers::ipMatch('192.168.68.233', '192.168.68.233')); Assert::false(Helpers::ipMatch('192.168.68.234', '192.168.68.233')); Assert::true(Helpers::ipMatch('192.168.64.0', '192.168.68.233/20')); @@ -27,7 +27,7 @@ test('', function () { -test('', function () { +test('IPv6 address matching', function () { Assert::true(Helpers::ipMatch('2001:db8:0:0:0:0:0:0', '2001:db8::')); Assert::false(Helpers::ipMatch('2001:db8:0:0:0:0:0:0', '2002:db8::')); Assert::false(Helpers::ipMatch('2001:db8:0:0:0:0:0:1', '2001:db8::')); @@ -40,7 +40,7 @@ test('', function () { -test('', function () { +test('date formatting', function () { Assert::same('Tue, 15 Nov 1994 08:12:31 GMT', Helpers::formatDate('1994-11-15T08:12:31+0000')); Assert::same('Tue, 15 Nov 1994 08:12:31 GMT', Helpers::formatDate('1994-11-15T10:12:31+0200')); Assert::same('Tue, 15 Nov 1994 08:12:31 GMT', Helpers::formatDate(new DateTime('1994-11-15T06:12:31-0200'))); diff --git a/tests/Http/Request.detectLanguage.phpt b/tests/Http/Request.detectLanguage.phpt index c1dea634..3e3e79c2 100644 --- a/tests/Http/Request.detectLanguage.phpt +++ b/tests/Http/Request.detectLanguage.phpt @@ -12,7 +12,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('basic language preference', function () { $headers = ['Accept-Language' => 'en, cs']; $request = new Http\Request(new Http\UrlScript, headers: $headers); @@ -22,7 +22,7 @@ test('', function () { }); -test('', function () { +test('language with quality weights', function () { $headers = ['Accept-Language' => 'da, en-gb;q=0.8, en;q=0.7']; $request = new Http\Request(new Http\UrlScript, headers: $headers); @@ -31,7 +31,7 @@ test('', function () { }); -test('', function () { +test('no Accept-Language header', function () { $headers = []; $request = new Http\Request(new Http\UrlScript, headers: $headers); @@ -39,7 +39,7 @@ test('', function () { }); -test('', function () { +test('invalid Accept-Language header', function () { $headers = ['Accept-Language' => 'garbage']; $request = new Http\Request(new Http\UrlScript, headers: $headers); diff --git a/tests/Http/Request.getOrigin.phpt b/tests/Http/Request.getOrigin.phpt index febebb89..65bdf535 100644 --- a/tests/Http/Request.getOrigin.phpt +++ b/tests/Http/Request.getOrigin.phpt @@ -9,13 +9,13 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('missing origin', function () { +test('no Origin header', function () { $request = new Http\Request(new Http\UrlScript); Assert::null($request->getOrigin()); }); -test('opaque origin', function () { +test('origin header \'null\'', function () { $request = new Http\Request(new Http\UrlScript, headers: [ 'Origin' => 'null', ]); @@ -23,7 +23,7 @@ test('opaque origin', function () { }); -test('normal origin', function () { +test('valid Origin header', function () { $request = new Http\Request(new Http\UrlScript, headers: [ 'Origin' => 'https://nette.org', ]); diff --git a/tests/Http/Request.getRawBody.phpt b/tests/Http/Request.getRawBody.phpt index 9d2f556f..76796de7 100644 --- a/tests/Http/Request.getRawBody.phpt +++ b/tests/Http/Request.getRawBody.phpt @@ -12,14 +12,14 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('raw body retrieval with callback', function () { $request = new Http\Request(new Http\UrlScript, rawBodyCallback: fn() => 'raw body'); Assert::same('raw body', $request->getRawBody()); }); -test('', function () { +test('raw body absence without callback', function () { $request = new Http\Request(new Http\UrlScript); Assert::null($request->getRawBody()); diff --git a/tests/Http/Request.headers.phpt b/tests/Http/Request.headers.phpt index 7c607151..39b97482 100644 --- a/tests/Http/Request.headers.phpt +++ b/tests/Http/Request.headers.phpt @@ -12,17 +12,17 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('empty headers by default', function () { $request = new Http\Request(new Http\UrlScript); Assert::same([], $request->getHeaders()); }); -test('', function () { +test('headers initialization without parameters', function () { $request = new Http\Request(new Http\UrlScript); Assert::same([], $request->getHeaders()); }); -test('', function () { +test('header normalization and case insensitivity', function () { $request = new Http\Request(new Http\UrlScript, headers: [ 'one' => '1', 'TWO' => '2', diff --git a/tests/Http/Request.invalidEncoding.phpt b/tests/Http/Request.invalidEncoding.phpt index d906dcf6..8d05275d 100644 --- a/tests/Http/Request.invalidEncoding.phpt +++ b/tests/Http/Request.invalidEncoding.phpt @@ -64,7 +64,7 @@ $_FILES = [ ], ]; -test('unfiltered data', function () { +test('binary data preservation with invalid encoding', function () { $factory = new Http\RequestFactory; $factory->setBinary(); $request = $factory->fromGlobals(); @@ -93,7 +93,7 @@ test('unfiltered data', function () { }); -test('filtered data', function () { +test('invalid encoding sanitization by default', function () { $factory = new Http\RequestFactory; $request = $factory->fromGlobals(); diff --git a/tests/Http/Request.invalidType.phpt b/tests/Http/Request.invalidType.phpt index 68875dca..b02d6169 100644 --- a/tests/Http/Request.invalidType.phpt +++ b/tests/Http/Request.invalidType.phpt @@ -12,7 +12,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('invalid POST', function () { +test('non-string type in POST data', function () { $_POST = [ 'int' => 1, ]; @@ -25,7 +25,7 @@ test('invalid POST', function () { }); -test('invalid COOKIE', function () { +test('non-string type in cookie array', function () { $_POST = []; $_COOKIE = ['x' => [1]]; diff --git a/tests/Http/Request.manipulation.phpt b/tests/Http/Request.manipulation.phpt index 7db214d6..ffee403a 100644 --- a/tests/Http/Request.manipulation.phpt +++ b/tests/Http/Request.manipulation.phpt @@ -8,7 +8,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('URL modification and query synchronization', function () { $url = new Http\UrlScript('http://nette.org/?arg=hello'); $request = new Http\Request($url); diff --git a/tests/Http/Request.request.phpt b/tests/Http/Request.request.phpt index 5e4f6e01..a86b5d73 100644 --- a/tests/Http/Request.request.phpt +++ b/tests/Http/Request.request.phpt @@ -23,7 +23,7 @@ $_SERVER = [ 'SCRIPT_NAME' => '/file.php', ]; -test('', function () { +test('URL parsing with custom filters', function () { $factory = new Http\RequestFactory; $factory->urlFilters['path'] = ['#%20#' => '']; $factory->urlFilters['url'] = ['#[.,)]\z#' => '']; @@ -54,7 +54,7 @@ test('', function () { }); -test('', function () { +test('URL components with special characters', function () { $factory = new Http\RequestFactory; $factory->urlFilters['path'] = []; $factory->urlFilters['url'] = []; diff --git a/tests/Http/RequestFactory.authorization.phpt b/tests/Http/RequestFactory.authorization.phpt index 7ddbb6d4..39316615 100644 --- a/tests/Http/RequestFactory.authorization.phpt +++ b/tests/Http/RequestFactory.authorization.phpt @@ -12,7 +12,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('Basic', function () { +test('basic authentication via PHP_AUTH_* variables', function () { $_SERVER = [ 'PHP_AUTH_USER' => 'user', 'PHP_AUTH_PW' => 'password', @@ -32,7 +32,7 @@ test('Basic', function () { -test('Digest', function () { +test('digest authentication header parsing', function () { $_SERVER = [ 'PHP_AUTH_DIGEST' => 'username="admin"', ]; @@ -47,7 +47,7 @@ test('Digest', function () { }); -test('empty', function () { +test('absence of authentication headers', function () { $_SERVER = []; $factory = new RequestFactory; $request = $factory->fromGlobals(); diff --git a/tests/Http/RequestFactory.proxy.forwarded.phpt b/tests/Http/RequestFactory.proxy.forwarded.phpt index 3805db12..30f9df86 100644 --- a/tests/Http/RequestFactory.proxy.forwarded.phpt +++ b/tests/Http/RequestFactory.proxy.forwarded.phpt @@ -11,7 +11,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('forwarded header handling with proxy', function () { $_SERVER = [ 'REMOTE_ADDR' => '127.0.0.3', 'REMOTE_HOST' => 'localhost', @@ -32,7 +32,7 @@ test('', function () { Assert::same('192.168.0.1', $url->getHost()); }); -test('', function () { +test('forwarded header with port numbers', function () { $_SERVER = [ 'REMOTE_ADDR' => '127.0.0.3', 'REMOTE_HOST' => 'localhost', @@ -51,7 +51,7 @@ test('', function () { }); -test('', function () { +test('IPv6 addresses in Forwarded header', function () { $_SERVER = [ 'REMOTE_ADDR' => '127.0.0.3', 'REMOTE_HOST' => 'localhost', @@ -68,7 +68,7 @@ test('', function () { Assert::same('[2001:db8:cafe::18]', $url->getHost()); }); -test('', function () { +test('IPv6 addresses and ports in Forwarded header', function () { $_SERVER = [ 'REMOTE_ADDR' => '127.0.0.3', 'REMOTE_HOST' => 'localhost', @@ -87,7 +87,7 @@ test('', function () { }); -test('', function () { +test('forwarded protocol (HTTPS) handling', function () { $_SERVER = [ 'REMOTE_ADDR' => '127.0.0.3', 'REMOTE_HOST' => 'localhost', diff --git a/tests/Http/RequestFactory.proxy.x-forwarded.phpt b/tests/Http/RequestFactory.proxy.x-forwarded.phpt index 7b3fa87b..58dca049 100644 --- a/tests/Http/RequestFactory.proxy.x-forwarded.phpt +++ b/tests/Http/RequestFactory.proxy.x-forwarded.phpt @@ -12,7 +12,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('X-Forwarded headers handling with proxy', function () { $_SERVER = [ 'REMOTE_ADDR' => '127.0.0.3', 'REMOTE_HOST' => 'localhost', @@ -34,7 +34,7 @@ test('', function () { Assert::same(80, $url->getPort()); }); -test('', function () { +test('X-Forwarded-Host with port', function () { $_SERVER = [ 'REMOTE_ADDR' => '127.0.0.3', 'REMOTE_HOST' => 'localhost', @@ -52,7 +52,7 @@ test('', function () { Assert::same(8080, $url->getPort()); }); -test('', function () { +test('X-Forwarded protocol and port', function () { $_SERVER = [ 'REMOTE_ADDR' => '127.0.0.3', 'HTTP_X_FORWARDED_FOR' => '23.75.45.200', @@ -70,7 +70,7 @@ test('', function () { Assert::same(8080, $url->getPort()); }); -test('', function () { +test('multiple proxies in X-Forwarded headers', function () { $_SERVER = [ 'REMOTE_ADDR' => '10.0.0.2', //proxy2 'REMOTE_HOST' => 'proxy2', @@ -96,7 +96,7 @@ test('', function () { Assert::same(80, $url->getPort()); }); -test('', function () { +test('X-Forwarded-Host with multiple entries and port', function () { $_SERVER = [ 'REMOTE_ADDR' => '10.0.0.2', //proxy2 'REMOTE_HOST' => 'proxy2', diff --git a/tests/Http/RequestFactory.query.phpt b/tests/Http/RequestFactory.query.phpt index 5d19df5e..5ab60f87 100644 --- a/tests/Http/RequestFactory.query.phpt +++ b/tests/Http/RequestFactory.query.phpt @@ -14,7 +14,7 @@ require __DIR__ . '/../bootstrap.php'; $factory = new RequestFactory; -test('', function () use ($factory) { +test('base URL without query parameters', function () use ($factory) { $_SERVER = [ 'HTTP_HOST' => 'nette.org', 'REQUEST_URI' => '/', @@ -24,7 +24,7 @@ test('', function () use ($factory) { }); -test('', function () use ($factory) { +test('URL with query parameters', function () use ($factory) { $_SERVER = [ 'HTTP_HOST' => 'nette.org', 'REQUEST_URI' => '/?a=b', diff --git a/tests/Http/RequestFactory.scriptPath.phpt b/tests/Http/RequestFactory.scriptPath.phpt index 09fd45d6..0c9c371e 100644 --- a/tests/Http/RequestFactory.scriptPath.phpt +++ b/tests/Http/RequestFactory.scriptPath.phpt @@ -14,7 +14,7 @@ require __DIR__ . '/../bootstrap.php'; $factory = new RequestFactory; -test('', function () use ($factory) { +test('script path detection from REQUEST_URI and SCRIPT_NAME', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/projects/modules-usage/www/', 'SCRIPT_NAME' => '/projects/modules-usage/www/index.php', @@ -24,7 +24,7 @@ test('', function () use ($factory) { }); -test('', function () use ($factory) { +test('URL-encoded path normalization in script path', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/projects/modules-usage/%77%77%77/', 'SCRIPT_NAME' => '/projects/modules-usage/www/index.php', @@ -34,7 +34,7 @@ test('', function () use ($factory) { }); -test('', function () use ($factory) { +test('nested path detection with script in subdirectory', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/projects/modules-usage/www/default/add-item', 'SCRIPT_NAME' => '/projects/modules-usage/www/index.php', @@ -44,7 +44,7 @@ test('', function () use ($factory) { }); -test('', function () use ($factory) { +test('script path when REQUEST_URI matches SCRIPT_NAME exactly', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/www/index.php', 'SCRIPT_NAME' => '/www/index.php', @@ -54,7 +54,7 @@ test('', function () use ($factory) { }); -test('', function () use ($factory) { +test('directory-like SCRIPT_NAME handling', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/www/', 'SCRIPT_NAME' => '/www/', @@ -64,7 +64,7 @@ test('', function () use ($factory) { }); -test('', function () use ($factory) { +test('path truncation to script directory', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/test/in', 'SCRIPT_NAME' => '/test/index.php', @@ -74,7 +74,7 @@ test('', function () use ($factory) { }); -test('', function () use ($factory) { +test('double slash normalization in script path', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/test//', 'SCRIPT_NAME' => '/test/index.php', @@ -84,7 +84,7 @@ test('', function () use ($factory) { }); -test('http://forum.nette.org/cs/5932-lepsi-detekce-requesturi-a-scriptpath', function () use ($factory) { +test('exact match of REQUEST_URI and SCRIPT_NAME as directory', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/sign/in/', 'SCRIPT_NAME' => '/sign/in/', @@ -94,7 +94,7 @@ test('http://forum.nette.org/cs/5932-lepsi-detekce-requesturi-a-scriptpath', fun }); -test('http://forum.nette.org/cs/9139-spatny-urlscript-scriptpath', function () use ($factory) { +test('mismatched directory levels between URI and script', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/configuration/', 'SCRIPT_NAME' => '/configuration/www/index.php', @@ -104,7 +104,7 @@ test('http://forum.nette.org/cs/9139-spatny-urlscript-scriptpath', function () u }); -test('', function () use ($factory) { +test('case sensitivity in script path components', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/blog/WWW/', 'SCRIPT_NAME' => '/blog/www/index.php', @@ -114,7 +114,7 @@ test('', function () use ($factory) { }); -test('', function () use ($factory) { +test('Windows-style SCRIPT_NAME handling', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/', 'SCRIPT_NAME' => 'c:\index.php', @@ -124,7 +124,7 @@ test('', function () use ($factory) { }); -test('', function () use ($factory) { +test('missing REQUEST_URI fallback', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => null, 'SCRIPT_NAME' => 'c:\index.php', @@ -134,7 +134,7 @@ test('', function () use ($factory) { }); -test('', function () use ($factory) { +test('missing SCRIPT_NAME fallback', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/', 'SCRIPT_NAME' => null, @@ -144,7 +144,7 @@ test('', function () use ($factory) { }); -test('', function () use ($factory) { +test('complete absence of URI and script data', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => null, 'SCRIPT_NAME' => null, @@ -153,7 +153,7 @@ test('', function () use ($factory) { Assert::same('/', $factory->fromGlobals()->getUrl()->getScriptPath()); }); -test('', function () use ($factory) { +test('root script path detection with deep URI', function () use ($factory) { $_SERVER = [ 'REQUEST_URI' => '/documents/show/5474', 'SCRIPT_NAME' => '/index.php', diff --git a/tests/Http/SessionSection.setExpiration().phpt b/tests/Http/SessionSection.setExpiration().phpt index 0328ad3b..9200cd73 100644 --- a/tests/Http/SessionSection.setExpiration().phpt +++ b/tests/Http/SessionSection.setExpiration().phpt @@ -16,7 +16,7 @@ $session = new Session(new Nette\Http\Request(new Nette\Http\UrlScript), new Net $session->setExpiration('+10 seconds'); -test('try to expire whole namespace', function () use ($session) { +test('global expiration of entire session section', function () use ($session) { $namespace = $session->getSection('expire'); $namespace->set('a', 'apple'); $namespace->set('p', 'pear'); @@ -31,7 +31,7 @@ test('try to expire whole namespace', function () use ($session) { }); -test('try to expire only 1 of the keys', function () use ($session) { +test('individual key expiration in session section', function () use ($session) { $namespace = $session->getSection('expireSingle'); $namespace->setExpiration('1 second', 'g'); $namespace->set('g', 'guava'); diff --git a/tests/Http/Url.fileScheme.phpt b/tests/Http/Url.fileScheme.phpt index 518d247b..abc1e2ba 100644 --- a/tests/Http/Url.fileScheme.phpt +++ b/tests/Http/Url.fileScheme.phpt @@ -12,7 +12,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('file URL parsing with explicit host', function () { $url = new Url('file://localhost/D:/dokumentace/rfc3986.txt'); Assert::same('file://localhost/D:/dokumentace/rfc3986.txt', (string) $url); Assert::same('file', $url->scheme); @@ -26,7 +26,7 @@ test('', function () { }); -test('', function () { +test('file URL parsing without host (local path)', function () { $url = new Url('file:///D:/dokumentace/rfc3986.txt'); Assert::same('file:D:/dokumentace/rfc3986.txt', (string) $url); Assert::same('file', $url->scheme); diff --git a/tests/Http/Url.removeDotSegments.phpt b/tests/Http/Url.removeDotSegments.phpt index 37da2c83..83d5fabc 100644 --- a/tests/Http/Url.removeDotSegments.phpt +++ b/tests/Http/Url.removeDotSegments.phpt @@ -8,7 +8,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('begins with /', function () { +test('dot segment removal in absolute paths', function () { Assert::same('/', Url::removeDotSegments('/')); Assert::same('/file', Url::removeDotSegments('/file')); Assert::same('/file/', Url::removeDotSegments('/file/')); @@ -23,7 +23,7 @@ test('begins with /', function () { }); -test('not begins with /', function () { +test('dot segment removal in relative paths', function () { Assert::same('', Url::removeDotSegments('')); Assert::same('file', Url::removeDotSegments('file')); Assert::same('file/', Url::removeDotSegments('file/')); @@ -38,7 +38,7 @@ test('not begins with /', function () { }); -test('incorrect ..', function () { +test('excessive parent directory traversal handling', function () { Assert::same('/', Url::removeDotSegments('/file/../..')); Assert::same('/', Url::removeDotSegments('/file/../../')); Assert::same('/bar', Url::removeDotSegments('/file/../../bar')); @@ -48,7 +48,7 @@ test('incorrect ..', function () { }); -test('double slash', function () { +test('double slash preservation', function () { Assert::same('//', Url::removeDotSegments('//')); Assert::same('//foo//', Url::removeDotSegments('//foo//')); Assert::same('//foo//', Url::removeDotSegments('//foo//..//')); diff --git a/tests/Http/UrlImmutable.manipulation.phpt b/tests/Http/UrlImmutable.manipulation.phpt index 06d66c41..4e36a7e7 100644 --- a/tests/Http/UrlImmutable.manipulation.phpt +++ b/tests/Http/UrlImmutable.manipulation.phpt @@ -8,7 +8,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('immutable URL component modifications', function () { $url = new UrlImmutable('http://username%3A:password%3A@hostn%61me:60/p%61th/script.php?%61rg=value#%61nchor'); $url = $url->withScheme(''); @@ -34,7 +34,7 @@ test('', function () { }); -test('', function () { +test('path manipulation in immutable URL', function () { $url = new UrlImmutable('http://username%3A:password%3A@hostn%61me:60/p%61th/script.php?%61rg=value#%61nchor'); $url = $url->withPath(''); @@ -60,7 +60,7 @@ test('', function () { }); -test('', function () { +test('query parameter replacement and removal', function () { $url = new UrlImmutable('http://hostname/path?arg=value'); Assert::same('arg=value', $url->query); @@ -78,7 +78,7 @@ test('', function () { }); -test('', function () { +test('individual query parameter manipulation', function () { $url = new UrlImmutable('http://hostname/path?arg=value'); Assert::same('arg=value', $url->query); diff --git a/tests/Http/UrlScript.manipulation.phpt b/tests/Http/UrlScript.manipulation.phpt index 11c098fa..94d9c001 100644 --- a/tests/Http/UrlScript.manipulation.phpt +++ b/tests/Http/UrlScript.manipulation.phpt @@ -8,7 +8,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('base and script path adjustments', function () { $url = new UrlScript('http://nette.org:8080/test/?q=search', '/test/index.php'); Assert::same('/test/', $url->basePath); Assert::same('/test/index.php', $url->scriptPath); diff --git a/tests/Http/UrlScript.usage.phpt b/tests/Http/UrlScript.usage.phpt index 8283c8a7..ce3db669 100644 --- a/tests/Http/UrlScript.usage.phpt +++ b/tests/Http/UrlScript.usage.phpt @@ -12,7 +12,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('script path detection in root directory', function () { $url = new UrlScript('http://nette.org:8080/file.php?q=search'); Assert::same('/file.php', $url->scriptPath); Assert::same('http://nette.org:8080/', $url->baseUrl); @@ -23,7 +23,7 @@ test('', function () { }); -test('', function () { +test('script path as root directory', function () { $url = new UrlScript('http://nette.org:8080/file.php?q=search', '/'); Assert::same('/', $url->scriptPath); Assert::same('http://nette.org:8080/', $url->baseUrl); @@ -34,7 +34,7 @@ test('', function () { }); -test('', function () { +test('subdirectory script path and URL components', function () { $url = new UrlScript('http://nette.org:8080/test/?q=search', '/test/index.php'); Assert::same('/test/index.php', $url->scriptPath); Assert::same('http://nette.org:8080/test/', $url->baseUrl); @@ -46,7 +46,7 @@ test('', function () { }); -test('', function () { +test('directory-based script path handling', function () { $url = new UrlScript('http://nette.org:8080/www/about', '/www/'); Assert::same('/www/about', $url->path); Assert::same('/www/', $url->scriptPath); @@ -55,7 +55,7 @@ test('', function () { }); -test('', function () { +test('exact script path match', function () { $url = new UrlScript('http://nette.org:8080/www/index.php', '/www/index.php'); Assert::same('/www/index.php', $url->path); Assert::same('/www/index.php', $url->scriptPath); From 86931e7993f76262619e2321a20591325bd3d71f Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 5 Nov 2024 04:18:45 +0100 Subject: [PATCH 03/13] Url, UrlImmutable: user & password are deprecated --- src/Http/Url.php | 4 ++++ src/Http/UrlImmutable.php | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/src/Http/Url.php b/src/Http/Url.php index de9860f0..447f5e63 100644 --- a/src/Http/Url.php +++ b/src/Http/Url.php @@ -100,6 +100,7 @@ public function getScheme(): string } + /** @deprecated */ public function setUser(string $user): static { $this->user = $user; @@ -107,12 +108,14 @@ public function setUser(string $user): static } + /** @deprecated */ public function getUser(): string { return $this->user; } + /** @deprecated */ public function setPassword(string $password): static { $this->password = $password; @@ -120,6 +123,7 @@ public function setPassword(string $password): static } + /** @deprecated */ public function getPassword(): string { return $this->password; diff --git a/src/Http/UrlImmutable.php b/src/Http/UrlImmutable.php index 9702135f..aa8e9992 100644 --- a/src/Http/UrlImmutable.php +++ b/src/Http/UrlImmutable.php @@ -78,6 +78,7 @@ public function getScheme(): string } + /** @deprecated */ public function withUser(string $user): static { $dolly = clone $this; @@ -87,12 +88,14 @@ public function withUser(string $user): static } + /** @deprecated */ public function getUser(): string { return $this->user; } + /** @deprecated */ public function withPassword(string $password): static { $dolly = clone $this; @@ -102,12 +105,14 @@ public function withPassword(string $password): static } + /** @deprecated */ public function getPassword(): string { return $this->password; } + /** @deprecated */ public function withoutUserInfo(): static { $dolly = clone $this; From eb4847daf495a35ce660b32e2aa5945196a0db45 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 19 Jun 2025 19:23:01 +0200 Subject: [PATCH 04/13] optimized global function calls --- src/Bridges/HttpDI/HttpExtension.php | 1 + src/Http/FileUpload.php | 2 ++ src/Http/Helpers.php | 1 + src/Http/Request.php | 2 ++ src/Http/RequestFactory.php | 2 ++ src/Http/Response.php | 2 ++ src/Http/Session.php | 2 ++ src/Http/SessionSection.php | 1 + src/Http/Url.php | 2 ++ src/Http/UrlImmutable.php | 2 ++ src/Http/UrlScript.php | 1 + src/Http/UserStorage.php | 1 + 12 files changed, 19 insertions(+) diff --git a/src/Bridges/HttpDI/HttpExtension.php b/src/Bridges/HttpDI/HttpExtension.php index 07f19c33..b2a96852 100644 --- a/src/Bridges/HttpDI/HttpExtension.php +++ b/src/Bridges/HttpDI/HttpExtension.php @@ -11,6 +11,7 @@ use Nette; use Nette\Schema\Expect; +use function is_array; /** diff --git a/src/Http/FileUpload.php b/src/Http/FileUpload.php index 76e48f75..55bacbe1 100644 --- a/src/Http/FileUpload.php +++ b/src/Http/FileUpload.php @@ -11,6 +11,8 @@ use Nette; use Nette\Utils\Image; +use function array_intersect_key, array_map, basename, chmod, dirname, file_get_contents, filesize, finfo_file, finfo_open, getimagesize, image_type_to_extension, in_array, is_string, is_uploaded_file, preg_replace, str_replace, trim, unlink; +use const FILEINFO_EXTENSION, FILEINFO_MIME_TYPE, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_OK; /** diff --git a/src/Http/Helpers.php b/src/Http/Helpers.php index f4b5fe78..9f9c359d 100644 --- a/src/Http/Helpers.php +++ b/src/Http/Helpers.php @@ -11,6 +11,7 @@ use Nette; use Nette\Utils\DateTime; +use function array_map, explode, implode, inet_pton, sprintf, strlen, strncmp, unpack; /** diff --git a/src/Http/Request.php b/src/Http/Request.php index 551a05b9..1da2c6fe 100644 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -10,6 +10,8 @@ namespace Nette\Http; use Nette; +use function array_change_key_case, base64_decode, count, explode, func_num_args, gethostbyaddr, implode, preg_match, preg_match_all, rsort, strcasecmp, strtolower, strtr; +use const CASE_LOWER; /** diff --git a/src/Http/RequestFactory.php b/src/Http/RequestFactory.php index 4dc78463..cfaceda3 100644 --- a/src/Http/RequestFactory.php +++ b/src/Http/RequestFactory.php @@ -12,6 +12,8 @@ use Nette; use Nette\Utils\Arrays; use Nette\Utils\Strings; +use function array_filter, base64_encode, count, end, explode, file_get_contents, filter_input_array, filter_var, function_exists, get_debug_type, in_array, ini_get, is_array, is_string, key, min, preg_last_error, preg_match, preg_replace, preg_split, rtrim, sprintf, str_contains, strcasecmp, strlen, strncmp, strpos, strrpos, strtolower, strtr, substr, trim; +use const FILTER_UNSAFE_RAW, FILTER_VALIDATE_IP, INPUT_COOKIE, INPUT_POST, PHP_SAPI, UPLOAD_ERR_NO_FILE; /** diff --git a/src/Http/Response.php b/src/Http/Response.php index 86de0b4c..631da9b3 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -11,6 +11,8 @@ use Nette; use Nette\Utils\DateTime; +use function array_filter, header, header_remove, headers_list, headers_sent, htmlspecialchars, http_response_code, ini_get, is_int, ltrim, ob_get_length, ob_get_status, preg_match, rawurlencode, setcookie, str_replace, strcasecmp, strlen, strncasecmp, strpos, substr, time; +use const ENT_IGNORE, ENT_QUOTES, PHP_SAPI; /** diff --git a/src/Http/Session.php b/src/Http/Session.php index 24229abd..cca3f132 100644 --- a/src/Http/Session.php +++ b/src/Http/Session.php @@ -10,6 +10,8 @@ namespace Nette\Http; use Nette; +use function array_keys, function_exists, headers_sent, ini_get, ini_get_all, ini_set, is_array, is_string, preg_match, preg_replace, preg_replace_callback, session_create_id, session_destroy, session_get_cookie_params, session_id, session_name, session_regenerate_id, session_set_cookie_params, session_set_save_handler, session_status, session_write_close, strncmp, strtolower, strtoupper, substr, time; +use const PHP_SESSION_ACTIVE; /** diff --git a/src/Http/SessionSection.php b/src/Http/SessionSection.php index f79b3025..06e6c24c 100644 --- a/src/Http/SessionSection.php +++ b/src/Http/SessionSection.php @@ -10,6 +10,7 @@ namespace Nette\Http; use Nette; +use function array_key_exists, func_num_args, ini_get, is_array, time; /** diff --git a/src/Http/Url.php b/src/Http/Url.php index 447f5e63..ec18a40a 100644 --- a/src/Http/Url.php +++ b/src/Http/Url.php @@ -10,6 +10,8 @@ namespace Nette\Http; use Nette; +use function array_pop, array_slice, bin2hex, chunk_split, defined, explode, function_exists, http_build_query, idn_to_utf8, implode, ini_get, ip2long, is_array, is_string, ksort, parse_str, parse_url, preg_match, preg_quote, preg_replace, preg_replace_callback, rawurldecode, rawurlencode, rtrim, str_contains, str_replace, str_starts_with, strcasecmp, strlen, strrpos, strtolower, strtoupper, substr; +use const IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, PHP_QUERY_RFC3986; /** diff --git a/src/Http/UrlImmutable.php b/src/Http/UrlImmutable.php index aa8e9992..0affad2e 100644 --- a/src/Http/UrlImmutable.php +++ b/src/Http/UrlImmutable.php @@ -10,6 +10,8 @@ namespace Nette\Http; use Nette; +use function array_slice, explode, http_build_query, implode, ip2long, is_array, is_string, rawurlencode, str_starts_with, strrpos, substr; +use const PHP_QUERY_RFC3986; /** diff --git a/src/Http/UrlScript.php b/src/Http/UrlScript.php index b3886508..820caf4e 100644 --- a/src/Http/UrlScript.php +++ b/src/Http/UrlScript.php @@ -10,6 +10,7 @@ namespace Nette\Http; use Nette; +use function strlen, strncmp, strrpos, substr; /** diff --git a/src/Http/UserStorage.php b/src/Http/UserStorage.php index bbcebfb8..4af77b10 100644 --- a/src/Http/UserStorage.php +++ b/src/Http/UserStorage.php @@ -11,6 +11,7 @@ use Nette; use Nette\Security\IIdentity; +use function is_bool, time; /** From 6867576fb261ddcd43f6da9c6098877fcbe2e52a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 15:28:42 +0100 Subject: [PATCH 05/13] opened 4.0-dev --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b39c2ddc..ccb47e6d 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,7 @@ }, "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.0-dev" } } } From 451c365409ac4b1943cb1454198af4d0597f9096 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 2 Mar 2021 14:59:23 +0100 Subject: [PATCH 06/13] removed deprecated stuff --- src/Http/Helpers.php | 3 - src/Http/UserStorage.php | 180 --------------------------------------- 2 files changed, 183 deletions(-) delete mode 100644 src/Http/UserStorage.php diff --git a/src/Http/Helpers.php b/src/Http/Helpers.php index 9f9c359d..3752b96a 100644 --- a/src/Http/Helpers.php +++ b/src/Http/Helpers.php @@ -24,9 +24,6 @@ final class Helpers /** @internal */ public const StrictCookieName = '_nss'; - /** @deprecated */ - public const STRICT_COOKIE_NAME = self::StrictCookieName; - /** * Returns HTTP valid date format. diff --git a/src/Http/UserStorage.php b/src/Http/UserStorage.php deleted file mode 100644 index 4af77b10..00000000 --- a/src/Http/UserStorage.php +++ /dev/null @@ -1,180 +0,0 @@ -getSessionSection(true); - $section->authenticated = $state; - - // Session Fixation defence - $this->sessionHandler->regenerateId(); - - if ($state) { - $section->reason = null; - $section->authTime = time(); // informative value - - } else { - $section->reason = self::MANUAL; - $section->authTime = null; - } - - return $this; - } - - - /** - * Is this user authenticated? - */ - public function isAuthenticated(): bool - { - $session = $this->getSessionSection(false); - return $session && $session->authenticated; - } - - - /** - * Sets the user identity. - */ - public function setIdentity(?IIdentity $identity): self - { - $this->getSessionSection(true)->identity = $identity; - return $this; - } - - - /** - * Returns current user identity, if any. - */ - public function getIdentity(): ?Nette\Security\IIdentity - { - $session = $this->getSessionSection(false); - return $session ? $session->identity : null; - } - - - /** - * Changes namespace; allows more users to share a session. - */ - public function setNamespace(string $namespace): self - { - if ($this->namespace !== $namespace) { - $this->namespace = $namespace; - $this->sessionSection = null; - } - - return $this; - } - - - /** - * Returns current namespace. - */ - public function getNamespace(): string - { - return $this->namespace; - } - - - /** - * Enables log out after inactivity. Accepts flag IUserStorage::CLEAR_IDENTITY. - */ - public function setExpiration(?string $time, int $flags = 0): self - { - $section = $this->getSessionSection(true); - if ($time) { - $time = Nette\Utils\DateTime::from($time)->format('U'); - $section->expireTime = $time; - $section->expireDelta = $time - time(); - - } else { - unset($section->expireTime, $section->expireDelta); - } - - $section->expireIdentity = (bool) ($flags & self::CLEAR_IDENTITY); - $section->setExpiration($time, 'foo'); // time check - return $this; - } - - - /** - * Why was user logged out? - */ - public function getLogoutReason(): ?int - { - $session = $this->getSessionSection(false); - return $session ? $session->reason : null; - } - - - /** - * Returns and initializes $this->sessionSection. - */ - protected function getSessionSection(bool $need): ?SessionSection - { - if ($this->sessionSection !== null) { - return $this->sessionSection; - } - - if (!$need && !$this->sessionHandler->exists()) { - return null; - } - - $this->sessionSection = $section = $this->sessionHandler->getSection('Nette.Http.UserStorage/' . $this->namespace); - - if (!$section->identity instanceof IIdentity || !is_bool($section->authenticated)) { - $section->remove(); - } - - if ($section->authenticated && $section->expireDelta > 0) { // check time expiration - if ($section->expireTime < time()) { - $section->reason = self::INACTIVITY; - $section->authenticated = false; - if ($section->expireIdentity) { - unset($section->identity); - } - } - - $section->expireTime = time() + $section->expireDelta; // sliding expiration - } - - if (!$section->authenticated) { - unset($section->expireTime, $section->expireDelta, $section->expireIdentity, $section->authTime); - } - - return $this->sessionSection; - } -} From 01970dcefc4e4589b7baf53c96b34a9bbe626464 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 30 Nov 2022 18:14:42 +0100 Subject: [PATCH 07/13] silently deprecated methods trigger E_USER_DEPRECATED --- src/Http/FileUpload.php | 1 + src/Http/Request.php | 1 + src/Http/RequestFactory.php | 3 ++- src/Http/SessionSection.php | 8 ++++++++ src/Http/Url.php | 7 +++++++ src/Http/UrlImmutable.php | 5 +++++ tests/Http/FileUpload.basic.phpt | 4 ++-- tests/Http/Request.invalidEncoding.phpt | 2 +- tests/Http/Request.request.phpt | 8 ++++---- tests/Http/RequestFactory.authorization.phpt | 4 ++-- tests/Http/Url.fileScheme.phpt | 8 ++++---- tests/Http/Url.ftpScheme.phpt | 4 ++-- tests/Http/Url.httpScheme.phpt | 4 ++-- tests/Http/UrlImmutable.Url.phpt | 4 ++-- tests/Http/UrlImmutable.manipulation.phpt | 6 +++--- tests/Http/UrlImmutable.usage.phpt | 4 ++-- 16 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/Http/FileUpload.php b/src/Http/FileUpload.php index 55bacbe1..684e5dde 100644 --- a/src/Http/FileUpload.php +++ b/src/Http/FileUpload.php @@ -69,6 +69,7 @@ public function __construct(array|string|null $value) */ public function getName(): string { + trigger_error(__METHOD__ . '() is deprecated, use getUntrustedName()', E_USER_DEPRECATED); return $this->name; } diff --git a/src/Http/Request.php b/src/Http/Request.php index 1da2c6fe..5720a160 100644 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -191,6 +191,7 @@ public function getHeaders(): array */ public function getReferer(): ?UrlImmutable { + trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED); return isset($this->headers['referer']) ? new UrlImmutable($this->headers['referer']) : null; diff --git a/src/Http/RequestFactory.php b/src/Http/RequestFactory.php index cfaceda3..29d53034 100644 --- a/src/Http/RequestFactory.php +++ b/src/Http/RequestFactory.php @@ -376,9 +376,10 @@ private function parseHostAndPort(string $s): ?array } - /** @deprecated */ + /** @deprecated use fromGlobals() */ public function createHttpRequest(): Request { + trigger_error(__METHOD__ . '() is deprecated, use fromGlobals()', E_USER_DEPRECATED); return $this->fromGlobals(); } } diff --git a/src/Http/SessionSection.php b/src/Http/SessionSection.php index 06e6c24c..df730e8e 100644 --- a/src/Http/SessionSection.php +++ b/src/Http/SessionSection.php @@ -98,6 +98,7 @@ public function remove(string|array|null $name = null): void */ public function __set(string $name, $value): void { + trigger_error("Writing to \$session->$name is deprecated, use \$session->set('$name', \$value) instead", E_USER_DEPRECATED); $this->session->autoStart(true); $this->getData()[$name] = $value; } @@ -109,6 +110,7 @@ public function __set(string $name, $value): void */ public function &__get(string $name): mixed { + trigger_error("Reading from \$session->$name is deprecated, use \$session->get('$name') instead", E_USER_DEPRECATED); $this->session->autoStart(true); $data = &$this->getData(); if ($this->warnOnUndefined && !array_key_exists($name, $data ?? [])) { @@ -125,6 +127,7 @@ public function &__get(string $name): mixed */ public function __isset(string $name): bool { + trigger_error("Using \$session->$name is deprecated, use \$session->get('$name') instead", E_USER_DEPRECATED); $this->session->autoStart(false); return isset($this->getData()[$name]); } @@ -136,6 +139,7 @@ public function __isset(string $name): bool */ public function __unset(string $name): void { + trigger_error("Unset(\$session->$name) is deprecated, use \$session->remove('$name') instead", E_USER_DEPRECATED); $this->remove($name); } @@ -146,6 +150,7 @@ public function __unset(string $name): void */ public function offsetSet($name, $value): void { + trigger_error("Writing to \$session['$name'] is deprecated, use \$session->set('$name', \$value) instead", E_USER_DEPRECATED); $this->__set($name, $value); } @@ -156,6 +161,7 @@ public function offsetSet($name, $value): void */ public function offsetGet($name): mixed { + trigger_error("Reading from \$session['$name'] is deprecated, use \$session->get('$name') instead", E_USER_DEPRECATED); return $this->get($name); } @@ -166,6 +172,7 @@ public function offsetGet($name): mixed */ public function offsetExists($name): bool { + trigger_error("Using \$session['$name'] is deprecated, use \$session->get('$name') instead", E_USER_DEPRECATED); return $this->__isset($name); } @@ -176,6 +183,7 @@ public function offsetExists($name): bool */ public function offsetUnset($name): void { + trigger_error("Unset(\$session['$name']) is deprecated, use \$session->remove('$name') instead", E_USER_DEPRECATED); $this->remove($name); } diff --git a/src/Http/Url.php b/src/Http/Url.php index ec18a40a..b1de6db2 100644 --- a/src/Http/Url.php +++ b/src/Http/Url.php @@ -105,6 +105,7 @@ public function getScheme(): string /** @deprecated */ public function setUser(string $user): static { + trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED); $this->user = $user; return $this; } @@ -113,6 +114,7 @@ public function setUser(string $user): static /** @deprecated */ public function getUser(): string { + trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED); return $this->user; } @@ -120,6 +122,7 @@ public function getUser(): string /** @deprecated */ public function setPassword(string $password): static { + trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED); $this->password = $password; return $this; } @@ -128,6 +131,7 @@ public function setPassword(string $password): static /** @deprecated */ public function getPassword(): string { + trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED); return $this->password; } @@ -289,6 +293,7 @@ public function getHostUrl(): string /** @deprecated use UrlScript::getBasePath() instead */ public function getBasePath(): string { + trigger_error(__METHOD__ . '() is deprecated, use UrlScript object', E_USER_DEPRECATED); $pos = strrpos($this->path, '/'); return $pos === false ? '' : substr($this->path, 0, $pos + 1); } @@ -297,6 +302,7 @@ public function getBasePath(): string /** @deprecated use UrlScript::getBaseUrl() instead */ public function getBaseUrl(): string { + trigger_error(__METHOD__ . '() is deprecated, use UrlScript object', E_USER_DEPRECATED); return $this->getHostUrl() . $this->getBasePath(); } @@ -304,6 +310,7 @@ public function getBaseUrl(): string /** @deprecated use UrlScript::getRelativeUrl() instead */ public function getRelativeUrl(): string { + trigger_error(__METHOD__ . '() is deprecated, use UrlScript object', E_USER_DEPRECATED); return substr($this->getAbsoluteUrl(), strlen($this->getBaseUrl())); } diff --git a/src/Http/UrlImmutable.php b/src/Http/UrlImmutable.php index 0affad2e..7c12bf94 100644 --- a/src/Http/UrlImmutable.php +++ b/src/Http/UrlImmutable.php @@ -83,6 +83,7 @@ public function getScheme(): string /** @deprecated */ public function withUser(string $user): static { + trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED); $dolly = clone $this; $dolly->user = $user; $dolly->authority = null; @@ -93,6 +94,7 @@ public function withUser(string $user): static /** @deprecated */ public function getUser(): string { + trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED); return $this->user; } @@ -100,6 +102,7 @@ public function getUser(): string /** @deprecated */ public function withPassword(string $password): static { + trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED); $dolly = clone $this; $dolly->password = $password; $dolly->authority = null; @@ -110,6 +113,7 @@ public function withPassword(string $password): static /** @deprecated */ public function getPassword(): string { + trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED); return $this->password; } @@ -117,6 +121,7 @@ public function getPassword(): string /** @deprecated */ public function withoutUserInfo(): static { + trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED); $dolly = clone $this; $dolly->user = $dolly->password = ''; $dolly->authority = null; diff --git a/tests/Http/FileUpload.basic.phpt b/tests/Http/FileUpload.basic.phpt index ec9157e4..416d5701 100644 --- a/tests/Http/FileUpload.basic.phpt +++ b/tests/Http/FileUpload.basic.phpt @@ -22,7 +22,7 @@ test('basic upload properties', function () { 'size' => 209, ]); - Assert::same('readme.txt', $upload->getName()); + Assert::same('readme.txt', @$upload->getName()); // deprecated Assert::same('readme.txt', $upload->getUntrustedName()); Assert::same('readme.txt', $upload->getSanitizedName()); Assert::same('path/to/readme.txt', $upload->getUntrustedFullPath()); @@ -47,7 +47,7 @@ test('sanitizing name with image detection', function () { 'size' => 209, ]); - Assert::same('../.image.png', $upload->getName()); + Assert::same('../.image.png', $upload->getUntrustedName()); Assert::same('image.png', $upload->getSanitizedName()); Assert::same('../.image.png', $upload->getUntrustedFullPath()); Assert::same('image/png', $upload->getContentType()); diff --git a/tests/Http/Request.invalidEncoding.phpt b/tests/Http/Request.invalidEncoding.phpt index 8d05275d..f7deeb4f 100644 --- a/tests/Http/Request.invalidEncoding.phpt +++ b/tests/Http/Request.invalidEncoding.phpt @@ -118,5 +118,5 @@ test('invalid encoding sanitization by default', function () { Assert::null($request->getFile(INVALID)); Assert::null($request->getFile(CONTROL_CHARACTERS)); Assert::type(Nette\Http\FileUpload::class, $request->files['file1']); - Assert::same('', $request->files['file1']->name); + Assert::same('', $request->files['file1']->getUntrustedName()); }); diff --git a/tests/Http/Request.request.phpt b/tests/Http/Request.request.phpt index a86b5d73..b818b79c 100644 --- a/tests/Http/Request.request.phpt +++ b/tests/Http/Request.request.phpt @@ -35,8 +35,8 @@ test('URL parsing with custom filters', function () { Assert::same('/file.php', $request->getUrl()->scriptPath); Assert::same('https', $request->getUrl()->scheme); - Assert::same('', $request->getUrl()->user); - Assert::same('', $request->getUrl()->password); + Assert::same('', @$request->getUrl()->user); // deprecated + Assert::same('', @$request->getUrl()->password); // deprecated Assert::same('nette.org', $request->getUrl()->host); Assert::same(8080, $request->getUrl()->port); Assert::same('/file.php', $request->getUrl()->path); @@ -61,8 +61,8 @@ test('URL components with special characters', function () { $request = $factory->fromGlobals(); Assert::same('https', $request->getUrl()->scheme); - Assert::same('', $request->getUrl()->user); - Assert::same('', $request->getUrl()->password); + Assert::same('', @$request->getUrl()->user); // deprecated + Assert::same('', @$request->getUrl()->password); // deprecated Assert::same('nette.org', $request->getUrl()->host); Assert::same(8080, $request->getUrl()->port); Assert::same('/file.php', $request->getUrl()->path); diff --git a/tests/Http/RequestFactory.authorization.phpt b/tests/Http/RequestFactory.authorization.phpt index 39316615..71788e27 100644 --- a/tests/Http/RequestFactory.authorization.phpt +++ b/tests/Http/RequestFactory.authorization.phpt @@ -26,8 +26,8 @@ test('basic authentication via PHP_AUTH_* variables', function () { ); Assert::same(['user', 'password'], $request->getBasicCredentials()); - Assert::same('', $request->getUrl()->getUser()); - Assert::same('', $request->getUrl()->getPassword()); + Assert::same('', @$request->getUrl()->getUser()); // deprecated + Assert::same('', @$request->getUrl()->getPassword()); // deprecated }); diff --git a/tests/Http/Url.fileScheme.phpt b/tests/Http/Url.fileScheme.phpt index abc1e2ba..8dd971df 100644 --- a/tests/Http/Url.fileScheme.phpt +++ b/tests/Http/Url.fileScheme.phpt @@ -16,8 +16,8 @@ test('file URL parsing with explicit host', function () { $url = new Url('file://localhost/D:/dokumentace/rfc3986.txt'); Assert::same('file://localhost/D:/dokumentace/rfc3986.txt', (string) $url); Assert::same('file', $url->scheme); - Assert::same('', $url->user); - Assert::same('', $url->password); + Assert::same('', @$url->user); // deprecated + Assert::same('', @$url->password); // deprecated Assert::same('localhost', $url->host); Assert::null($url->port); Assert::same('/D:/dokumentace/rfc3986.txt', $url->path); @@ -30,8 +30,8 @@ test('file URL parsing without host (local path)', function () { $url = new Url('file:///D:/dokumentace/rfc3986.txt'); Assert::same('file:D:/dokumentace/rfc3986.txt', (string) $url); Assert::same('file', $url->scheme); - Assert::same('', $url->user); - Assert::same('', $url->password); + Assert::same('', @$url->user); // deprecated + Assert::same('', @$url->password); // deprecated Assert::same('', $url->host); Assert::null($url->port); Assert::same('D:/dokumentace/rfc3986.txt', $url->path); diff --git a/tests/Http/Url.ftpScheme.phpt b/tests/Http/Url.ftpScheme.phpt index 68ed1af8..f9ef2932 100644 --- a/tests/Http/Url.ftpScheme.phpt +++ b/tests/Http/Url.ftpScheme.phpt @@ -15,8 +15,8 @@ require __DIR__ . '/../bootstrap.php'; $url = new Url('ftp://ftp.is.co.za/rfc/rfc3986.txt'); Assert::same('ftp', $url->scheme); -Assert::same('', $url->user); -Assert::same('', $url->password); +Assert::same('', @$url->user); // deprecated +Assert::same('', @$url->password); // deprecated Assert::same('ftp.is.co.za', $url->host); Assert::same(21, $url->port); Assert::same('/rfc/rfc3986.txt', $url->path); diff --git a/tests/Http/Url.httpScheme.phpt b/tests/Http/Url.httpScheme.phpt index 1ee32b68..b376f32f 100644 --- a/tests/Http/Url.httpScheme.phpt +++ b/tests/Http/Url.httpScheme.phpt @@ -17,8 +17,8 @@ $url = new Url('http://username%3A:password%3A@hostn%61me:60/p%61th/script.php?% Assert::same('http://username%3A:password%3A@hostname:60/p%61th/script.php?arg=value#anchor', (string) $url); Assert::same('"http:\/\/username%3A:password%3A@hostname:60\/p%61th\/script.php?arg=value#anchor"', json_encode($url)); Assert::same('http', $url->scheme); -Assert::same('username:', $url->user); -Assert::same('password:', $url->password); +Assert::same('username:', @$url->user); // deprecated +Assert::same('password:', @$url->password); // deprecated Assert::same('hostname', $url->host); Assert::same(60, $url->port); Assert::same(80, $url->getDefaultPort()); diff --git a/tests/Http/UrlImmutable.Url.phpt b/tests/Http/UrlImmutable.Url.phpt index 84850722..95baf886 100644 --- a/tests/Http/UrlImmutable.Url.phpt +++ b/tests/Http/UrlImmutable.Url.phpt @@ -17,8 +17,8 @@ $url = new UrlImmutable(new Url('http://username%3A:password%3A@hostn%61me:60/p% Assert::same('http://username%3A:password%3A@hostname:60/p%61th/script.php?arg=value#anchor', (string) $url); Assert::same('"http:\/\/username%3A:password%3A@hostname:60\/p%61th\/script.php?arg=value#anchor"', json_encode($url)); Assert::same('http', $url->scheme); -Assert::same('username:', $url->user); -Assert::same('password:', $url->password); +Assert::same('username:', @$url->user); // deprecated +Assert::same('password:', @$url->password); // deprecated Assert::same('hostname', $url->host); Assert::same(60, $url->port); Assert::same('hostname', $url->getDomain()); diff --git a/tests/Http/UrlImmutable.manipulation.phpt b/tests/Http/UrlImmutable.manipulation.phpt index 4e36a7e7..6affbccd 100644 --- a/tests/Http/UrlImmutable.manipulation.phpt +++ b/tests/Http/UrlImmutable.manipulation.phpt @@ -14,10 +14,10 @@ test('immutable URL component modifications', function () { $url = $url->withScheme(''); Assert::same('//username%3A:password%3A@hostname:60/p%61th/script.php?arg=value#anchor', $url->absoluteUrl); - $url = $url->withUser('name'); + $url = @$url->withUser('name'); // deprecated Assert::same('//name:password%3A@hostname:60/p%61th/script.php?arg=value#anchor', $url->absoluteUrl); - $url = $url->withPassword('secret'); + $url = @$url->withPassword('secret'); // deprecated Assert::same('//name:secret@hostname:60/p%61th/script.php?arg=value#anchor', $url->absoluteUrl); $url = $url->withHost('localhost'); @@ -29,7 +29,7 @@ test('immutable URL component modifications', function () { $url = $url->withFragment('hello'); Assert::same('//name:secret@localhost:123/p%61th/script.php?arg=value#hello', $url->absoluteUrl); - $url = $url->withoutUserInfo(); + $url = @$url->withoutUserInfo(); // deprecated Assert::same('//localhost:123/p%61th/script.php?arg=value#hello', $url->absoluteUrl); }); diff --git a/tests/Http/UrlImmutable.usage.phpt b/tests/Http/UrlImmutable.usage.phpt index fcd1017a..d675dd3f 100644 --- a/tests/Http/UrlImmutable.usage.phpt +++ b/tests/Http/UrlImmutable.usage.phpt @@ -17,8 +17,8 @@ $url = new UrlImmutable('http://username%3A:password%3A@hostn%61me:60/p%61th/scr Assert::same('http://username%3A:password%3A@hostname:60/p%61th/script.php?arg=value#anchor', (string) $url); Assert::same('"http:\/\/username%3A:password%3A@hostname:60\/p%61th\/script.php?arg=value#anchor"', json_encode($url)); Assert::same('http', $url->scheme); -Assert::same('username:', $url->user); -Assert::same('password:', $url->password); +Assert::same('username:', @$url->user); // deprecated +Assert::same('password:', @$url->password); // deprecated Assert::same('hostname', $url->host); Assert::same(60, $url->port); Assert::same('hostname', $url->getDomain()); From f88f4a57641409fc9efba2f8cc5167f2dd5a81d3 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 4 Nov 2024 14:32:46 +0100 Subject: [PATCH 08/13] Request::getRemoteHost() does not perform DNS resolving [Closes #218] --- src/Http/Request.php | 4 ---- tests/Http/RequestFactory.proxy.forwarded.phpt | 8 ++++---- tests/Http/RequestFactory.proxy.x-forwarded.phpt | 10 +++++----- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/Http/Request.php b/src/Http/Request.php index 5720a160..00451fd4 100644 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -255,10 +255,6 @@ public function getRemoteAddress(): ?string */ public function getRemoteHost(): ?string { - if ($this->remoteHost === null && $this->remoteAddress !== null) { - $this->remoteHost = gethostbyaddr($this->remoteAddress); - } - return $this->remoteHost; } diff --git a/tests/Http/RequestFactory.proxy.forwarded.phpt b/tests/Http/RequestFactory.proxy.forwarded.phpt index 30f9df86..d00545ad 100644 --- a/tests/Http/RequestFactory.proxy.forwarded.phpt +++ b/tests/Http/RequestFactory.proxy.forwarded.phpt @@ -25,7 +25,7 @@ test('forwarded header handling with proxy', function () { $factory->setProxy('127.0.0.1/8'); Assert::same('23.75.45.200', $factory->fromGlobals()->getRemoteAddress()); - Assert::same('a23-75-45-200.deploy.static.akamaitechnologies.com', $factory->fromGlobals()->getRemoteHost()); + Assert::null($factory->fromGlobals()->getRemoteHost()); $url = $factory->fromGlobals()->getUrl(); Assert::same('http', $url->getScheme()); @@ -43,7 +43,7 @@ test('forwarded header with port numbers', function () { $factory->setProxy('127.0.0.3'); Assert::same('23.75.45.200', $factory->fromGlobals()->getRemoteAddress()); - Assert::same('a23-75-45-200.deploy.static.akamaitechnologies.com', $factory->fromGlobals()->getRemoteHost()); + Assert::null($factory->fromGlobals()->getRemoteHost()); $url = $factory->fromGlobals()->getUrl(); Assert::same(8080, $url->getPort()); @@ -62,7 +62,7 @@ test('IPv6 addresses in Forwarded header', function () { $factory->setProxy('127.0.0.3'); Assert::same('2001:db8:cafe::17', $factory->fromGlobals()->getRemoteAddress()); - Assert::same('2001:db8:cafe::17', $factory->fromGlobals()->getRemoteHost()); + Assert::null($factory->fromGlobals()->getRemoteHost()); $url = $factory->fromGlobals()->getUrl(); Assert::same('[2001:db8:cafe::18]', $url->getHost()); @@ -79,7 +79,7 @@ test('IPv6 addresses and ports in Forwarded header', function () { $factory->setProxy('127.0.0.3'); Assert::same('2001:db8:cafe::17', $factory->fromGlobals()->getRemoteAddress()); - Assert::same('2001:db8:cafe::17', $factory->fromGlobals()->getRemoteHost()); + Assert::null($factory->fromGlobals()->getRemoteHost()); $url = $factory->fromGlobals()->getUrl(); Assert::same(47832, $url->getPort()); diff --git a/tests/Http/RequestFactory.proxy.x-forwarded.phpt b/tests/Http/RequestFactory.proxy.x-forwarded.phpt index 58dca049..15e8c9b4 100644 --- a/tests/Http/RequestFactory.proxy.x-forwarded.phpt +++ b/tests/Http/RequestFactory.proxy.x-forwarded.phpt @@ -27,7 +27,7 @@ test('X-Forwarded headers handling with proxy', function () { $factory->setProxy('127.0.0.1/8'); Assert::same('23.75.45.200', $factory->fromGlobals()->getRemoteAddress()); - Assert::same('a23-75-45-200.deploy.static.akamaitechnologies.com', $factory->fromGlobals()->getRemoteHost()); + Assert::null($factory->fromGlobals()->getRemoteHost()); $url = $factory->fromGlobals()->getUrl(); Assert::same('otherhost', $url->getHost()); @@ -45,7 +45,7 @@ test('X-Forwarded-Host with port', function () { $factory = new RequestFactory; $factory->setProxy('127.0.0.3'); Assert::same('23.75.45.200', $factory->fromGlobals()->getRemoteAddress()); - Assert::same('a23-75-45-200.deploy.static.akamaitechnologies.com', $factory->fromGlobals()->getRemoteHost()); + Assert::null($factory->fromGlobals()->getRemoteHost()); $url = $factory->fromGlobals()->getUrl(); Assert::same('otherhost', $url->getHost()); @@ -81,7 +81,7 @@ test('multiple proxies in X-Forwarded headers', function () { $factory = new RequestFactory; $factory->setProxy('10.0.0.0/24'); Assert::same('172.16.0.1', $factory->fromGlobals()->getRemoteAddress()); - Assert::same('172.16.0.1', $factory->fromGlobals()->getRemoteHost()); + Assert::null($factory->fromGlobals()->getRemoteHost()); $url = $factory->fromGlobals()->getUrl(); Assert::same('real', $url->getHost()); @@ -89,7 +89,7 @@ test('multiple proxies in X-Forwarded headers', function () { $factory->setProxy(['10.0.0.1', '10.0.0.2']); Assert::same('172.16.0.1', $factory->fromGlobals()->getRemoteAddress()); - Assert::same('172.16.0.1', $factory->fromGlobals()->getRemoteHost()); + Assert::null($factory->fromGlobals()->getRemoteHost()); $url = $factory->fromGlobals()->getUrl(); Assert::same('real', $url->getHost()); @@ -107,7 +107,7 @@ test('X-Forwarded-Host with multiple entries and port', function () { $factory = new RequestFactory; $factory->setProxy(['10.0.0.1', '10.0.0.2']); Assert::same('172.16.0.1', $factory->fromGlobals()->getRemoteAddress()); - Assert::same('172.16.0.1', $factory->fromGlobals()->getRemoteHost()); + Assert::null($factory->fromGlobals()->getRemoteHost()); $url = $factory->fromGlobals()->getUrl(); Assert::same('real', $url->getHost()); From 91d8aa05b564cb4bf3a94d089ca6c624c116d8f8 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 29 Jan 2023 04:28:57 +0100 Subject: [PATCH 09/13] Request::getDecodedBody() WIP --- src/Http/Request.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Http/Request.php b/src/Http/Request.php index 00451fd4..af3ad2a7 100644 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -268,6 +268,20 @@ public function getRawBody(): ?string } + /** + * Returns decoded content of HTTP request body. + */ + public function getDecodedBody(): mixed + { + $type = $this->getHeader('Content-Type'); + return match ($type) { + 'application/json' => json_decode($this->getRawBody()), + 'application/x-www-form-urlencoded' => $_POST, + default => throw new \Exception("Unsupported content type: $type"), + }; + } + + /** * Returns basic HTTP authentication credentials. * @return array{string, string}|null From 442898553ff696353698be628593f8f9d2511b45 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 29 Apr 2024 13:05:51 +0200 Subject: [PATCH 10/13] SessionSection: removed $warnOnUndefined (BC break) --- src/Http/SessionSection.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Http/SessionSection.php b/src/Http/SessionSection.php index df730e8e..3f75d6d1 100644 --- a/src/Http/SessionSection.php +++ b/src/Http/SessionSection.php @@ -18,9 +18,6 @@ */ class SessionSection implements \IteratorAggregate, \ArrayAccess { - public bool $warnOnUndefined = false; - - /** * Do not call directly. Use Session::getSection(). */ @@ -113,10 +110,6 @@ public function &__get(string $name): mixed trigger_error("Reading from \$session->$name is deprecated, use \$session->get('$name') instead", E_USER_DEPRECATED); $this->session->autoStart(true); $data = &$this->getData(); - if ($this->warnOnUndefined && !array_key_exists($name, $data ?? [])) { - trigger_error("The variable '$name' does not exist in session section"); - } - return $data[$name]; } From a02f3d131f8a5dbd573244a6813ed316cde8d6ad Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 27 Nov 2022 21:36:23 +0100 Subject: [PATCH 11/13] IRequest, IResponse: added typehints, unification (BC break) --- src/Http/IRequest.php | 12 ++++-------- src/Http/IResponse.php | 30 +++++++++++++++--------------- src/Http/Response.php | 8 ++++---- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/Http/IRequest.php b/src/Http/IRequest.php index 9c3fb8f7..434682c1 100644 --- a/src/Http/IRequest.php +++ b/src/Http/IRequest.php @@ -58,22 +58,19 @@ function getUrl(): UrlScript; /** * Returns variable provided to the script via URL query ($_GET). * If no key is passed, returns the entire array. - * @return mixed */ - function getQuery(?string $key = null); + function getQuery(?string $key = null): mixed; /** * Returns variable provided to the script via POST method ($_POST). * If no key is passed, returns the entire array. - * @return mixed */ - function getPost(?string $key = null); + function getPost(?string $key = null): mixed; /** * Returns uploaded file. - * @return FileUpload|array|null */ - function getFile(string $key); + function getFile(string $key): ?FileUpload; /** * Returns uploaded files. @@ -82,9 +79,8 @@ function getFiles(): array; /** * Returns variable provided to the script via HTTP cookies. - * @return mixed */ - function getCookie(string $key); + function getCookie(string $key): mixed; /** * Returns variables provided to the script via HTTP cookies. diff --git a/src/Http/IResponse.php b/src/Http/IResponse.php index b71dfe29..f3e64844 100644 --- a/src/Http/IResponse.php +++ b/src/Http/IResponse.php @@ -337,9 +337,8 @@ interface IResponse /** * Sets HTTP response code. - * @return static */ - function setCode(int $code, ?string $reason = null); + function setCode(int $code, ?string $reason = null): static; /** * Returns HTTP response code. @@ -348,21 +347,18 @@ function getCode(): int; /** * Sends a HTTP header and replaces a previous one. - * @return static */ - function setHeader(string $name, string $value); + function setHeader(string $name, string $value): static; /** * Adds HTTP header. - * @return static */ - function addHeader(string $name, string $value); + function addHeader(string $name, string $value): static; /** * Sends a Content-type HTTP header. - * @return static */ - function setContentType(string $type, ?string $charset = null); + function setContentType(string $type, ?string $charset = null): static; /** * Redirects to a new URL. @@ -371,9 +367,8 @@ function redirect(string $url, int $code = self::S302_Found): void; /** * Sets the time (like '20 minutes') before a page cached on a browser expires, null means "must-revalidate". - * @return static */ - function setExpiration(?string $expire); + function setExpiration(?string $expire): static; /** * Checks if headers have been sent. @@ -392,7 +387,6 @@ function getHeaders(): array; /** * Sends a cookie. - * @return static */ function setCookie( string $name, @@ -400,12 +394,18 @@ function setCookie( string|int|\DateTimeInterface|null $expire, ?string $path = null, ?string $domain = null, - ?bool $secure = null, - ?bool $httpOnly = null, - ); + bool $secure = false, + bool $httpOnly = true, + string $sameSite = self::SameSiteLax, + ): static; /** * Deletes a cookie. */ - function deleteCookie(string $name, ?string $path = null, ?string $domain = null, ?bool $secure = null); + function deleteCookie( + string $name, + ?string $path = null, + ?string $domain = null, + bool $secure = false, + ); } diff --git a/src/Http/Response.php b/src/Http/Response.php index 631da9b3..07e16734 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -235,8 +235,8 @@ public function setCookie( ?string $path = null, ?string $domain = null, ?bool $secure = null, - ?bool $httpOnly = null, - ?string $sameSite = null, + bool $httpOnly = true, + string $sameSite = self::SameSiteLax, ): static { self::checkHeaders(); @@ -245,8 +245,8 @@ public function setCookie( 'path' => $path ?? ($domain ? '/' : $this->cookiePath), 'domain' => $domain ?? ($path ? '' : $this->cookieDomain), 'secure' => $secure ?? $this->cookieSecure, - 'httponly' => $httpOnly ?? true, - 'samesite' => $sameSite ?? self::SameSiteLax, + 'httponly' => $httpOnly, + 'samesite' => $sameSite, ]); return $this; } From 2ca8d0118c5d6a76137cdcbe7a7443d5229d7146 Mon Sep 17 00:00:00 2001 From: Jakub Vrana Date: Wed, 10 Sep 2025 06:51:07 +0200 Subject: [PATCH 12/13] IRequest, Request: improved return type of getQuery() --- src/Http/IRequest.php | 2 ++ src/Http/Request.php | 1 + 2 files changed, 3 insertions(+) diff --git a/src/Http/IRequest.php b/src/Http/IRequest.php index 434682c1..a3e6197e 100644 --- a/src/Http/IRequest.php +++ b/src/Http/IRequest.php @@ -58,12 +58,14 @@ function getUrl(): UrlScript; /** * Returns variable provided to the script via URL query ($_GET). * If no key is passed, returns the entire array. + * @return ($key is null ? array : mixed) */ function getQuery(?string $key = null): mixed; /** * Returns variable provided to the script via POST method ($_POST). * If no key is passed, returns the entire array. + * @return ($key is null ? array : mixed) */ function getPost(?string $key = null): mixed; diff --git a/src/Http/Request.php b/src/Http/Request.php index af3ad2a7..75d6a7ad 100644 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -82,6 +82,7 @@ public function getUrl(): UrlScript /** * Returns variable provided to the script via URL query ($_GET). * If no key is passed, returns the entire array. + * @return ($key is null ? array : mixed) */ public function getQuery(?string $key = null): mixed { From 002027986626dc6065219829d5c3d35e7d3bfdc4 Mon Sep 17 00:00:00 2001 From: Jakub Vrana Date: Wed, 10 Sep 2025 06:54:23 +0200 Subject: [PATCH 13/13] Url, UrlImmutable: fixed type of $query --- src/Http/Url.php | 2 +- src/Http/UrlImmutable.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Http/Url.php b/src/Http/Url.php index b1de6db2..5939c94b 100644 --- a/src/Http/Url.php +++ b/src/Http/Url.php @@ -33,7 +33,7 @@ * @property string $host * @property int $port * @property string $path - * @property string $query + * @property array $query * @property string $fragment * @property-read string $absoluteUrl * @property-read string $authority diff --git a/src/Http/UrlImmutable.php b/src/Http/UrlImmutable.php index 7c12bf94..2c642cd0 100644 --- a/src/Http/UrlImmutable.php +++ b/src/Http/UrlImmutable.php @@ -33,7 +33,7 @@ * @property-read string $host * @property-read int $port * @property-read string $path - * @property-read string $query + * @property-read array $query * @property-read string $fragment * @property-read string $absoluteUrl * @property-read string $authority