From 4976fa3dbf42aa9b0634c529ae55c15a7e784b26 Mon Sep 17 00:00:00 2001 From: Jake Jackson Date: Mon, 20 Jul 2020 16:01:00 +1000 Subject: [PATCH] Replace league/url with league/uri & league/uri-components league/url has been abandoned since 2015-09-23 and this PR replaces it with its successor: league/uri and its components package. The package change requires the minimum PHP version to be set to 7.2. PHPUnit was also updated to the last version that supports PHP7.2. I know there was concern about requiring new extensions (https://github.com/spatie/url-signer/issues/1) by making the switch, however these are not hard dependencies. If you don't use the `league/uri` i18n URI processing feature (`ext-intl`) or don't want to create a data URI from a filepath (`ext-fileinfo`) then there is no issues (an exception is thrown should you use one of these features and don't have the required extension). --- .travis.yml | 3 +- composer.json | 7 ++-- src/BaseUrlSigner.php | 79 ++++++++++++++++++++++++------------------- 3 files changed, 51 insertions(+), 38 deletions(-) diff --git a/.travis.yml b/.travis.yml index 836ea7a..a294525 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,9 @@ language: php php: - - 7.1 - 7.2 + - 7.3 + - 7.4 before_script: - travis_retry composer install --no-interaction --prefer-source diff --git a/composer.json b/composer.json index 5a3edec..c4dc573 100644 --- a/composer.json +++ b/composer.json @@ -19,11 +19,12 @@ } ], "require": { - "php": "^7.1", - "league/url": "^3.3" + "php": "^7.2", + "league/uri": "^6.0", + "league/uri-components": "^2.2" }, "require-dev": { - "phpunit/phpunit": "^6.5" + "phpunit/phpunit": "^8.0" }, "autoload": { "psr-4": { diff --git a/src/BaseUrlSigner.php b/src/BaseUrlSigner.php index 261c389..b264d7b 100644 --- a/src/BaseUrlSigner.php +++ b/src/BaseUrlSigner.php @@ -3,8 +3,9 @@ namespace Spatie\UrlSigner; use DateTime; -use League\Url\Components\QueryInterface; -use League\Url\UrlImmutable; +use League\Uri\Http; +use League\Uri\QueryString; +use Psr\Http\Message\UriInterface; use Spatie\UrlSigner\Exceptions\InvalidExpiration; use Spatie\UrlSigner\Exceptions\InvalidSignatureKey; @@ -55,12 +56,13 @@ public function __construct($signatureKey, $expiresParameter = 'expires', $signa * @param string $url * @param \DateTime|int $expiration * - * @return string * @throws InvalidExpiration + * + * @return string */ public function sign($url, $expiration) { - $url = UrlImmutable::createFromUrl($url); + $url = Http::createFromString($url); $expiration = $this->getExpirationTimestamp($expiration); $signature = $this->createSignature((string) $url, $expiration); @@ -71,24 +73,20 @@ public function sign($url, $expiration) /** * Add expiration and signature query parameters to an url. * - * @param \League\Url\UrlImmutable $url - * @param string $expiration - * @param string $signature + * @param UriInterface $url + * @param string $expiration + * @param string $signature * * @return \League\Url\UrlImmutable */ - protected function signUrl(UrlImmutable $url, $expiration, $signature) + protected function signUrl(UriInterface $url, $expiration, $signature) { - $query = $url->getQuery(); - - $query->modify([ - $this->expiresParameter => $expiration, - $this->signatureParameter => $signature, - ]); + $query = QueryString::extract($url->getQuery()); - $urlSigner = $url->setQuery($query); + $query[$this->expiresParameter] = $expiration; + $query[$this->signatureParameter] = $signature; - return $urlSigner; + return $url->withQuery($this->buildQueryStringFromArray($query)); } /** @@ -100,9 +98,9 @@ protected function signUrl(UrlImmutable $url, $expiration, $signature) */ public function validate($url) { - $url = UrlImmutable::createFromUrl($url); + $url = Http::createFromString($url); - $query = $url->getQuery(); + $query = QueryString::extract($url->getQuery()); if ($this->isMissingAQueryParameter($query)) { return false; @@ -124,11 +122,11 @@ public function validate($url) /** * Check if a query is missing a necessary parameter. * - * @param \League\Url\Components\QueryInterface $query + * @param array $query * * @return bool */ - protected function isMissingAQueryParameter(QueryInterface $query) + protected function isMissingAQueryParameter(array $query) { if (!isset($query[$this->expiresParameter])) { return true; @@ -156,22 +154,18 @@ protected function isFuture($timestamp) /** * Retrieve the intended URL by stripping off the UrlSigner specific parameters. * - * @param \League\Url\UrlImmutable $url + * @param UriInterface $url * - * @return \League\Url\UrlImmutable + * @return UriInterface */ - protected function getIntendedUrl(UrlImmutable $url) + protected function getIntendedUrl(UriInterface $url) { - $intendedQuery = $url->getQuery(); - - $intendedQuery->modify([ - $this->expiresParameter => null, - $this->signatureParameter => null, - ]); + $intendedQuery = QueryString::extract($url->getQuery()); - $intendedUrl = $url->setQuery($intendedQuery); + unset($intendedQuery[$this->expiresParameter]); + unset($intendedQuery[$this->signatureParameter]); - return $intendedUrl; + return $url->withQuery($this->buildQueryStringFromArray($intendedQuery)); } /** @@ -205,13 +199,13 @@ protected function getExpirationTimestamp($expiration) /** * Determine if the url has a forged signature. * - * @param \League\Url\UrlImmutable $url + * @param UriInterface $url * * @return bool */ - protected function hasValidSignature(UrlImmutable $url) + protected function hasValidSignature(UriInterface $url) { - $query = $url->getQuery(); + $query = QueryString::extract($url->getQuery()); $expiration = $query[$this->expiresParameter]; $providedSignature = $query[$this->signatureParameter]; @@ -222,4 +216,21 @@ protected function hasValidSignature(UrlImmutable $url) return hash_equals($validSignature, $providedSignature); } + + /** + * Turn a key => value associate array into a query string. + * + * @param array $query + * + * @return string|null + */ + protected function buildQueryStringFromArray(array $query) + { + $buildQuery = []; + foreach ($query as $key => $value) { + $buildQuery[] = [$key, $value]; + } + + return QueryString::build($buildQuery); + } }