Fixes #5897 -- Properly parse URLs without schemes.

This commit is contained in:
Buster Neece 2022-12-04 12:54:18 -06:00
parent a8572d76b5
commit 296317daf8
No known key found for this signature in database
GPG Key ID: F1D2E64A0005E80E
4 changed files with 47 additions and 54 deletions

View File

@ -11,7 +11,6 @@ use App\OpenApi;
use App\Service\Avatar;
use App\Utilities\Urls;
use Doctrine\ORM\Mapping as ORM;
use GuzzleHttp\Psr7\Uri;
use InvalidArgumentException;
use OpenApi\Attributes as OA;
use Psr\Http\Message\UriInterface;
@ -95,16 +94,6 @@ class Settings implements Stringable
'System Base URL'
);
if ('' === $baseUri->getScheme()) {
$baseUri = $baseUri->withScheme('http');
}
if ('/' === $baseUri->getPath()) {
$baseUri = $baseUri->withPath('');
}
if (Uri::isDefaultPort($baseUri)) {
$baseUri = $baseUri->withPort(null);
}
$this->base_url = $this->truncateNullableString((string)$baseUri);
}
@ -388,6 +377,7 @@ class Settings implements Stringable
return Urls::tryParseUserUrl(
$this->homepage_redirect_url,
'Homepage Redirect URL',
false
);
}
@ -413,6 +403,7 @@ class Settings implements Stringable
return Urls::tryParseUserUrl(
$this->default_album_art_url,
'Default Album Art URL',
false
);
}

View File

@ -939,7 +939,8 @@ class Station implements Stringable, IdentifiableEntityInterface
{
return Urls::tryParseUserUrl(
$this->default_album_art_url,
'Station ' . $this->__toString() . ' Default Album Art URL'
'Station ' . $this->__toString() . ' Default Album Art URL',
false
);
}

View File

@ -4,53 +4,51 @@ declare(strict_types=1);
namespace App\Utilities;
use Exception;
use GuzzleHttp\Psr7\Exception\MalformedUriException;
use GuzzleHttp\Psr7\Uri;
use LogicException;
use Psr\Http\Message\UriInterface;
final class Urls
{
public static function getUri(?string $url): ?UriInterface
{
if (null !== $url) {
$url = trim($url);
if (!empty($url)) {
try {
return new Uri($url);
} catch (MalformedUriException) {
if (!str_starts_with($url, 'http')) {
/** @noinspection HttpUrlsUsage */
return self::getUri('http://' . $url);
}
}
}
public static function getUri(
?string $url,
bool $mustBeAbsolute = true
): UriInterface {
if (null === $url) {
throw new \RuntimeException('URL field is empty.');
}
return null;
$url = trim($url);
if (empty($url)) {
throw new \RuntimeException('URL field is empty.');
}
$uri = new Uri($url);
if ($mustBeAbsolute && '' === $uri->getHost() && '' === $uri->getScheme()) {
return self::getUri('https://' . $url);
}
if ('' === $uri->getScheme()) {
$uri = $uri->withScheme('http');
}
if ('/' === $uri->getPath()) {
$uri = $uri->withPath('');
}
if (Uri::isDefaultPort($uri)) {
$uri = $uri->withPort(null);
}
return $uri;
}
public static function parseUserUrl(
?string $url,
string $context
string $context,
bool $mustBeAbsolute = true
): UriInterface {
try {
if (empty($url)) {
throw new LogicException('No URL specified.');
}
$url = trim($url);
try {
return new Uri($url);
} catch (MalformedUriException $ex) {
if (!str_starts_with($url, 'http')) {
/** @noinspection HttpUrlsUsage */
return new Uri('http://' . $url);
}
throw $ex;
}
} catch (Exception $e) {
return self::getUri($url, $mustBeAbsolute);
} catch (\Throwable $e) {
throw new LogicException(
message: sprintf('Could not parse %s URL "%s": %s', $context, $url, $e->getMessage()),
previous: $e
@ -60,21 +58,19 @@ final class Urls
public static function tryParseUserUrl(
?string $url,
string $context
string $context,
bool $mustBeAbsolute = true
): ?UriInterface {
if (empty($url)) {
return null;
}
try {
return self::parseUserUrl($url, $context);
} catch (Exception $e) {
return self::getUri($url, $mustBeAbsolute);
} catch (\Throwable $e) {
Logger::getInstance()->error(
sprintf('Could not parse %s URL "%s": %s', $context, $url, $e->getMessage()),
sprintf('Could not parse %s URL "%s"', $context, $url),
[
'exception' => $e,
]
);
return null;
}
}

View File

@ -42,7 +42,12 @@ final class Mastodon extends AbstractSocialConnector
$instanceUri = Urls::parseUserUrl($instanceUrl, 'Mastodon Instance URL');
$visibility = $config['visibility'] ?? 'public';
$this->logger->debug('Posting to Mastodon...');
$this->logger->debug(
'Posting to Mastodon...',
[
'url' => (string)$instanceUri,
]
);
foreach ($this->getMessages($webhook, $np, $triggers) as $message) {
$response = $this->httpClient->request(