diff --git a/composer.json b/composer.json index 31c2aa8b3c51..a03250c4b427 100644 --- a/composer.json +++ b/composer.json @@ -37,6 +37,7 @@ "league/flysystem": "^3.25.1", "league/flysystem-local": "^3.25.1", "league/uri": "^7.5.1", + "league/uri-polyfill": "^7.7.0", "monolog/monolog": "^3.0", "nesbot/carbon": "^3.8.4", "nunomaduro/termwind": "^2.0", diff --git a/config/mail.php b/config/mail.php index a8d18503e6e9..5e168f14653c 100644 --- a/config/mail.php +++ b/config/mail.php @@ -1,5 +1,7 @@ env('MAIL_USERNAME'), 'password' => env('MAIL_PASSWORD'), 'timeout' => null, - 'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url((string) env('APP_URL', 'http://localhost'), PHP_URL_HOST)), + 'local_domain' => env('MAIL_EHLO_DOMAIN', (new Uri((string) env('APP_URL', 'http://localhost')))->getHost()), ], 'ses' => [ diff --git a/src/Illuminate/Filesystem/FilesystemAdapter.php b/src/Illuminate/Filesystem/FilesystemAdapter.php index 588f8c66f973..b8d319975497 100644 --- a/src/Illuminate/Filesystem/FilesystemAdapter.php +++ b/src/Illuminate/Filesystem/FilesystemAdapter.php @@ -38,6 +38,7 @@ use RuntimeException; use Symfony\Component\HttpFoundation\StreamedResponse; use Throwable; +use Uri\Rfc3986\Uri; /** * @mixin \League\Flysystem\FilesystemOperator @@ -858,12 +859,12 @@ protected function concatPathToUrl($url, $path) */ protected function replaceBaseUrl($uri, $url) { - $parsed = parse_url($url); + $parsed = new Uri($url); return $uri - ->withScheme($parsed['scheme']) - ->withHost($parsed['host']) - ->withPort($parsed['port'] ?? null); + ->withScheme($parsed->getScheme()) + ->withHost($parsed->getHost()) + ->withPort($parsed->getPort()); } /** diff --git a/src/Illuminate/Filesystem/FilesystemServiceProvider.php b/src/Illuminate/Filesystem/FilesystemServiceProvider.php index 5fe6b9e531be..d9d80c9ae1b3 100644 --- a/src/Illuminate/Filesystem/FilesystemServiceProvider.php +++ b/src/Illuminate/Filesystem/FilesystemServiceProvider.php @@ -6,6 +6,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; use Illuminate\Support\ServiceProvider; +use Uri\Rfc3986\Uri; class FilesystemServiceProvider extends ServiceProvider { @@ -90,7 +91,7 @@ protected function serveFiles() $this->app->booted(function ($app) use ($disk, $config) { $uri = isset($config['url']) - ? rtrim(parse_url($config['url'])['path'], '/') + ? rtrim((new Uri($config['url']))->getPath(), '/') : '/storage'; $isProduction = $app->isProduction(); diff --git a/src/Illuminate/Filesystem/composer.json b/src/Illuminate/Filesystem/composer.json index 13deb8c174fb..98a0cbf41e2e 100644 --- a/src/Illuminate/Filesystem/composer.json +++ b/src/Illuminate/Filesystem/composer.json @@ -19,6 +19,7 @@ "illuminate/contracts": "^13.0", "illuminate/macroable": "^13.0", "illuminate/support": "^13.0", + "league/uri-polyfill": "^7.7.0", "symfony/finder": "^7.4.0|^8.0.0" }, "autoload": { diff --git a/src/Illuminate/Foundation/Bootstrap/SetRequestForConsole.php b/src/Illuminate/Foundation/Bootstrap/SetRequestForConsole.php index 613fa857ed04..fdf1beb88d22 100644 --- a/src/Illuminate/Foundation/Bootstrap/SetRequestForConsole.php +++ b/src/Illuminate/Foundation/Bootstrap/SetRequestForConsole.php @@ -4,6 +4,7 @@ use Illuminate\Contracts\Foundation\Application; use Illuminate\Http\Request; +use Uri\Rfc3986\Uri; class SetRequestForConsole { @@ -17,14 +18,14 @@ public function bootstrap(Application $app) { $uri = $app->make('config')->get('app.url', 'http://localhost'); - $components = parse_url($uri); + $components = new Uri($uri); $server = $_SERVER; - if (isset($components['path'])) { + if ($path = $components->getPath()) { $server = array_merge($server, [ - 'SCRIPT_FILENAME' => $components['path'], - 'SCRIPT_NAME' => $components['path'], + 'SCRIPT_FILENAME' => $path, + 'SCRIPT_NAME' => $path, ]); } diff --git a/src/Illuminate/Foundation/Console/stubs/maintenance-mode.stub b/src/Illuminate/Foundation/Console/stubs/maintenance-mode.stub index a90b8cde8aec..854806ac1f6e 100644 --- a/src/Illuminate/Foundation/Console/stubs/maintenance-mode.stub +++ b/src/Illuminate/Foundation/Console/stubs/maintenance-mode.stub @@ -1,5 +1,7 @@ getPath(); $uri = rawurldecode($uri !== '/' ? trim($uri, '/') : $uri); diff --git a/src/Illuminate/Foundation/Providers/FoundationServiceProvider.php b/src/Illuminate/Foundation/Providers/FoundationServiceProvider.php index 625e3f608bf3..2a47b2b040fe 100644 --- a/src/Illuminate/Foundation/Providers/FoundationServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/FoundationServiceProvider.php @@ -35,6 +35,7 @@ use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; use Symfony\Component\VarDumper\Caster\StubCaster; use Symfony\Component\VarDumper\Cloner\AbstractCloner; +use Uri\Rfc3986\Uri as Rfc3986Uri; class FoundationServiceProvider extends AggregateServiceProvider { @@ -133,7 +134,7 @@ public function registerDumper() 'html' == $format => HtmlDumper::register($basePath, $compiledViewPath), 'cli' == $format => CliDumper::register($basePath, $compiledViewPath), 'server' == $format => null, - $format && 'tcp' == parse_url($format, PHP_URL_SCHEME) => null, + $format && 'tcp' == Rfc3986Uri::parse($format)?->getScheme() => null, default => in_array(PHP_SAPI, ['cli', 'phpdbg']) ? CliDumper::register($basePath, $compiledViewPath) : HtmlDumper::register($basePath, $compiledViewPath), }; } diff --git a/src/Illuminate/Foundation/resources/server.php b/src/Illuminate/Foundation/resources/server.php index b1a9387a6740..df5fe056abaf 100644 --- a/src/Illuminate/Foundation/resources/server.php +++ b/src/Illuminate/Foundation/resources/server.php @@ -3,7 +3,9 @@ $publicPath = getcwd(); $uri = urldecode( - parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) ?? '' + (class_exists(\Uri\Rfc3986\Uri::class) + ? \Uri\Rfc3986\Uri::parse($_SERVER['REQUEST_URI'])?->getPath() + : parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)) ?? '' ); // This file allows us to emulate Apache's "mod_rewrite" functionality from the diff --git a/src/Illuminate/Http/Middleware/TrustHosts.php b/src/Illuminate/Http/Middleware/TrustHosts.php index b0bb3b5c06a8..241f431da093 100644 --- a/src/Illuminate/Http/Middleware/TrustHosts.php +++ b/src/Illuminate/Http/Middleware/TrustHosts.php @@ -4,6 +4,7 @@ use Illuminate\Contracts\Foundation\Application; use Illuminate\Http\Request; +use Uri\Rfc3986\Uri; class TrustHosts { @@ -109,7 +110,7 @@ protected function shouldSpecifyTrustedHosts() */ protected function allSubdomainsOfApplicationUrl() { - if ($host = parse_url($this->app['config']->get('app.url'), PHP_URL_HOST)) { + if ($host = Uri::parse($this->app['config']->get('app.url'))?->getHost()) { return '^(.+\.)?'.preg_quote($host).'$'; } } diff --git a/src/Illuminate/Http/composer.json b/src/Illuminate/Http/composer.json index 1826793934af..5041d6427301 100755 --- a/src/Illuminate/Http/composer.json +++ b/src/Illuminate/Http/composer.json @@ -23,6 +23,7 @@ "illuminate/macroable": "^13.0", "illuminate/session": "^13.0", "illuminate/support": "^13.0", + "league/uri-polyfill": "^7.7.0", "symfony/http-foundation": "^7.4.0|^8.0.0", "symfony/http-kernel": "^7.4.0|^8.0.0", "symfony/polyfill-php85": "^1.33", diff --git a/src/Illuminate/Routing/RouteUrlGenerator.php b/src/Illuminate/Routing/RouteUrlGenerator.php index 245c4c01156d..16e1fcf11c3e 100644 --- a/src/Illuminate/Routing/RouteUrlGenerator.php +++ b/src/Illuminate/Routing/RouteUrlGenerator.php @@ -7,6 +7,7 @@ use Illuminate\Routing\Exceptions\UrlGenerationException; use Illuminate\Support\Arr; use Illuminate\Support\Collection; +use Uri\Rfc3986\Uri; class RouteUrlGenerator { @@ -381,7 +382,7 @@ protected function addQueryString($uri, array $parameters) // If the URI has a fragment we will move it to the end of this URI since it will // need to come after any query string that may be added to the URL else it is // not going to be available. We will remove it then append it back on here. - if (! is_null($fragment = parse_url($uri, PHP_URL_FRAGMENT))) { + if (! is_null($fragment = Uri::parse($uri)?->getFragment())) { $uri = preg_replace('/#.*/', '', $uri); } diff --git a/src/Illuminate/Support/composer.json b/src/Illuminate/Support/composer.json index d12b580c4373..eaba954e6dd9 100644 --- a/src/Illuminate/Support/composer.json +++ b/src/Illuminate/Support/composer.json @@ -24,6 +24,7 @@ "illuminate/contracts": "^13.0", "illuminate/macroable": "^13.0", "illuminate/reflection": "^13.0", + "league/uri-polyfill": "^7.7.0", "nesbot/carbon": "^3.8.4", "symfony/polyfill-php83": "^1.33", "symfony/polyfill-php85": "^1.33", diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index 854fcc831443..a5bd279c9376 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -28,6 +28,7 @@ use InvalidArgumentException; use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\UploadedFile; +use Uri\Rfc3986\Uri; use ValueError; trait ValidatesAttributes @@ -123,7 +124,7 @@ public function validateActiveUrl($attribute, $value) return false; } - if ($url = parse_url($value, PHP_URL_HOST)) { + if ($url = Uri::parse($value)?->getHost()) { try { $records = $this->getDnsRecords($url.'.', DNS_A | DNS_AAAA); diff --git a/src/Illuminate/Validation/composer.json b/src/Illuminate/Validation/composer.json index bf7587e040a9..19e389537e8b 100755 --- a/src/Illuminate/Validation/composer.json +++ b/src/Illuminate/Validation/composer.json @@ -25,6 +25,7 @@ "illuminate/macroable": "^13.0", "illuminate/support": "^13.0", "illuminate/translation": "^13.0", + "league/uri-polyfill": "^7.7.0", "symfony/http-foundation": "^7.4.0|^8.0.0", "symfony/mime": "^7.4.0|^8.0.0" }, diff --git a/tests/Http/HttpRedirectResponseTest.php b/tests/Http/HttpRedirectResponseTest.php index ee69f19ba8f4..c04c3147d86a 100755 --- a/tests/Http/HttpRedirectResponseTest.php +++ b/tests/Http/HttpRedirectResponseTest.php @@ -12,6 +12,7 @@ use Mockery as m; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Cookie; +use Uri\Rfc3986\Uri; class HttpRedirectResponseTest extends TestCase { @@ -57,13 +58,13 @@ public function testFragmentIdentifierOnRedirect() $response = new RedirectResponse('foo.bar'); $response->withFragment('foo'); - $this->assertSame('foo', parse_url($response->getTargetUrl(), PHP_URL_FRAGMENT)); + $this->assertSame('foo', (new Uri($response->getTargetUrl()))->getFragment()); $response->withFragment('#bar'); - $this->assertSame('bar', parse_url($response->getTargetUrl(), PHP_URL_FRAGMENT)); + $this->assertSame('bar', (new Uri($response->getTargetUrl()))->getFragment()); $response->withoutFragment(); - $this->assertNull(parse_url($response->getTargetUrl(), PHP_URL_FRAGMENT)); + $this->assertNull((new Uri($response->getTargetUrl()))->getFragment()); } public function testInputOnRedirect()