Prevent SSRF requests

By validating the provided URL before passing it to youtube-dl
This commit is contained in:
Pierre Rudloff 2022-02-27 10:54:56 +01:00
parent 2afbfb4bf2
commit 3a4f09dda0
7 changed files with 814 additions and 161 deletions

View file

@ -11,6 +11,9 @@ use Alltube\Library\Downloader;
use Alltube\Library\Video;
use Alltube\LocaleManager;
use Aura\Session\Segment;
use Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Exception\InvalidURLException;
use Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Options;
use Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Url;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Slim\Http\Request;
@ -127,10 +130,11 @@ abstract class BaseController
* @param Request $request PSR-7 request
*
* @return string|null Password
* @throws InvalidURLException
*/
protected function getPassword(Request $request): ?string
{
$url = $request->getQueryParam('url');
$url = $this->getVideoPageUrl($request);
$password = $request->getParam('password');
if (isset($password)) {
@ -157,4 +161,19 @@ abstract class BaseController
return $controller->displayError($request, $response, $message);
}
/**
* @param Request $request
* @return string
* @throws InvalidURLException
*/
protected function getVideoPageUrl(Request $request): string
{
$url = $request->getQueryParam('url') ?: $request->getQueryParam('v');
// Prevent SSRF attacks.
$parts = Url::validateUrl($url, new Options());
return $parts['url'];
}
}

View file

@ -19,6 +19,7 @@ use Alltube\Library\Exception\YoutubedlException;
use Alltube\Stream\ConvertedPlaylistArchiveStream;
use Alltube\Stream\PlaylistArchiveStream;
use Alltube\Stream\YoutubeStream;
use Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Exception\InvalidURLException;
use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Http\StatusCode;
@ -37,56 +38,53 @@ class DownloadController extends BaseController
*
* @return Response HTTP response
* @throws AlltubeLibraryException
* @throws InvalidURLException
*/
public function download(Request $request, Response $response): Response
{
$url = $request->getQueryParam('url');
$url = $this->getVideoPageUrl($request);
if (isset($url)) {
$this->video = $this->downloader->getVideo($url, $this->getFormat($request), $this->getPassword($request));
$this->video = $this->downloader->getVideo($url, $this->getFormat($request), $this->getPassword($request));
try {
if ($this->config->convert && $request->getQueryParam('audio')) {
// Audio convert.
return $this->getAudioResponse($request, $response);
} elseif ($this->config->convertAdvanced && !is_null($request->getQueryParam('customConvert'))) {
// Advance convert.
return $this->getConvertedResponse($request, $response);
}
try {
if ($this->config->convert && $request->getQueryParam('audio')) {
// Audio convert.
return $this->getAudioResponse($request, $response);
} elseif ($this->config->convertAdvanced && !is_null($request->getQueryParam('customConvert'))) {
// Advance convert.
return $this->getConvertedResponse($request, $response);
}
// Regular download.
return $this->getDownloadResponse($request, $response);
} catch (PasswordException $e) {
$frontController = new FrontController($this->container);
// Regular download.
return $this->getDownloadResponse($request, $response);
} catch (PasswordException $e) {
$frontController = new FrontController($this->container);
return $frontController->password($request, $response);
} catch (WrongPasswordException $e) {
return $this->displayError($request, $response, $this->localeManager->t('Wrong password'));
} catch (PlaylistConversionException $e) {
return $frontController->password($request, $response);
} catch (WrongPasswordException $e) {
return $this->displayError($request, $response, $this->localeManager->t('Wrong password'));
} catch (PlaylistConversionException $e) {
return $this->displayError(
$request,
$response,
$this->localeManager->t('Conversion of playlists is not supported.')
);
} catch (InvalidProtocolConversionException $e) {
if (in_array($this->video->protocol, ['m3u8', 'm3u8_native'])) {
return $this->displayError(
$request,
$response,
$this->localeManager->t('Conversion of playlists is not supported.')
$this->localeManager->t('Conversion of M3U8 files is not supported.')
);
} catch (InvalidProtocolConversionException $e) {
if (in_array($this->video->protocol, ['m3u8', 'm3u8_native'])) {
return $this->displayError(
$request,
$response,
$this->localeManager->t('Conversion of M3U8 files is not supported.')
);
} elseif ($this->video->protocol == 'http_dash_segments') {
return $this->displayError(
$request,
$response,
$this->localeManager->t('Conversion of DASH segments is not supported.')
);
} else {
throw $e;
}
} elseif ($this->video->protocol == 'http_dash_segments') {
return $this->displayError(
$request,
$response,
$this->localeManager->t('Conversion of DASH segments is not supported.')
);
} else {
throw $e;
}
} else {
return $response->withRedirect($this->router->pathFor('index'));
}
}

View file

@ -12,6 +12,7 @@ use Alltube\Library\Exception\WrongPasswordException;
use Alltube\Locale;
use Alltube\Middleware\CspMiddleware;
use Exception;
use Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Exception\InvalidURLException;
use Slim\Http\StatusCode;
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
use Throwable;
@ -198,24 +199,21 @@ class FrontController extends BaseController
*
* @return Response HTTP response
* @throws AlltubeLibraryException
* @throws InvalidURLException
*/
public function info(Request $request, Response $response): Response
{
$url = $request->getQueryParam('url') ?: $request->getQueryParam('v');
$url = $this->getVideoPageUrl($request);
if (isset($url) && !empty($url)) {
$this->video = $this->downloader->getVideo($url, $this->getFormat($request), $this->getPassword($request));
$this->video = $this->downloader->getVideo($url, $this->getFormat($request), $this->getPassword($request));
if ($this->config->convert && $request->getQueryParam('audio')) {
// We skip the info page and get directly to the download.
return $response->withRedirect(
$this->router->pathFor('download', [], $request->getQueryParams())
);
} else {
return $this->getInfoResponse($request, $response);
}
if ($this->config->convert && $request->getQueryParam('audio')) {
// We skip the info page and get directly to the download.
return $response->withRedirect(
$this->router->pathFor('download', [], $request->getQueryParams())
);
} else {
return $response->withRedirect($this->router->pathFor('index'));
return $this->getInfoResponse($request, $response);
}
}

View file

@ -7,6 +7,8 @@
namespace Alltube\Controller;
use Alltube\Library\Exception\AlltubeLibraryException;
use Exception;
use Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Exception\InvalidURLException;
use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Http\StatusCode;
@ -23,13 +25,12 @@ class JsonController extends BaseController
* @param Response $response PSR-7 response
*
* @return Response HTTP response
* @throws AlltubeLibraryException
*/
public function json(Request $request, Response $response): Response
{
$url = $request->getQueryParam('url');
try {
$url = $this->getVideoPageUrl($request);
if (isset($url)) {
$this->video = $this->downloader->getVideo(
$url,
$this->getFormat($request),
@ -37,8 +38,8 @@ class JsonController extends BaseController
);
return $response->withJson($this->video->getJson());
} else {
return $response->withJson(['error' => 'You need to provide the url parameter'])
} catch (InvalidURLException $e) {
return $response->withJson(['error' => $e->getMessage()])
->withStatus(StatusCode::HTTP_BAD_REQUEST);
}
}

View file

@ -25,6 +25,7 @@
"aura/session": "^2.1",
"barracudanetworks/archivestream-php": "^1.0",
"consolidation/log": "^2.0",
"j0k3r/httplug-ssrf-plugin": "^2.0",
"jawira/case-converter": "^3.4",
"jean85/pretty-package-versions": "^1.3",
"mathmarques/smarty-view": "^1.1",

842
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "93cbba477de92eb8ec3d913b8cd83c82",
"content-hash": "06423e8f32df697ae32be27a2c7a97b2",
"packages": [
{
"name": "aura/session",
@ -108,6 +108,72 @@
],
"time": "2018-08-10T13:58:33+00:00"
},
{
"name": "clue/stream-filter",
"version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/clue/stream-filter.git",
"reference": "d6169430c7731d8509da7aecd0af756a5747b78e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/clue/stream-filter/zipball/d6169430c7731d8509da7aecd0af756a5747b78e",
"reference": "d6169430c7731d8509da7aecd0af756a5747b78e",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36"
},
"type": "library",
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"Clue\\StreamFilter\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Christian Lück",
"email": "christian@clue.engineering"
}
],
"description": "A simple and modern approach to stream filtering in PHP",
"homepage": "https://github.com/clue/php-stream-filter",
"keywords": [
"bucket brigade",
"callback",
"filter",
"php_user_filter",
"stream",
"stream_filter_append",
"stream_filter_register"
],
"support": {
"issues": "https://github.com/clue/stream-filter/issues",
"source": "https://github.com/clue/stream-filter/tree/v1.6.0"
},
"funding": [
{
"url": "https://clue.engineering/support",
"type": "custom"
},
{
"url": "https://github.com/clue",
"type": "github"
}
],
"time": "2022-02-21T13:15:14+00:00"
},
{
"name": "composer/installers",
"version": "v1.9.0",
@ -540,6 +606,77 @@
],
"time": "2019-07-01T23:21:34+00:00"
},
{
"name": "j0k3r/httplug-ssrf-plugin",
"version": "v2.0.2",
"source": {
"type": "git",
"url": "https://github.com/j0k3r/httplug-ssrf-plugin.git",
"reference": "b60e8068054bdb15fdf1e62cd314d941c62a3b72"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/j0k3r/httplug-ssrf-plugin/zipball/b60e8068054bdb15fdf1e62cd314d941c62a3b72",
"reference": "b60e8068054bdb15fdf1e62cd314d941c62a3b72",
"shasum": ""
},
"require": {
"php": ">=7.2.9",
"php-http/client-common": "^2.0",
"php-http/discovery": "^1.5",
"php-http/message": "^1.7",
"php-http/message-factory": "^1.0.2"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.14",
"guzzlehttp/psr7": "^1.0",
"php-http/guzzle6-adapter": "^2.0",
"php-http/mock-client": "^1.0",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"symfony/phpunit-bridge": "~5.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Graby\\HttpClient\\Plugin\\ServerSideRequestForgeryProtection\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jeremy Benoist",
"email": "jeremy.benoist@gmail.com"
},
{
"name": "aaa2000",
"email": "adev2000@gmail.com"
},
{
"name": "Jack W",
"email": "jack@fin1te.net",
"role": "Developer (SafeCurl original version)"
}
],
"description": "Server-Side Request Forgery (SSRF) protection plugin for HTTPlug",
"homepage": "https://github.com/j0k3r/httplug-ssrf-plugin",
"keywords": [
"http",
"httplug",
"plugin",
"security",
"ssrf"
],
"support": {
"issues": "https://github.com/j0k3r/httplug-ssrf-plugin/issues",
"source": "https://github.com/j0k3r/httplug-ssrf-plugin/tree/master"
},
"time": "2020-06-26T06:05:06+00:00"
},
{
"name": "jawira/case-converter",
"version": "v3.4.1",
@ -916,6 +1053,396 @@
],
"time": "2020-09-02T14:53:15+00:00"
},
{
"name": "php-http/client-common",
"version": "2.5.0",
"source": {
"type": "git",
"url": "https://github.com/php-http/client-common.git",
"reference": "d135751167d57e27c74de674d6a30cef2dc8e054"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/client-common/zipball/d135751167d57e27c74de674d6a30cef2dc8e054",
"reference": "d135751167d57e27c74de674d6a30cef2dc8e054",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0",
"php-http/httplug": "^2.0",
"php-http/message": "^1.6",
"php-http/message-factory": "^1.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0",
"symfony/options-resolver": "~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0 || ^6.0",
"symfony/polyfill-php80": "^1.17"
},
"require-dev": {
"doctrine/instantiator": "^1.1",
"guzzlehttp/psr7": "^1.4",
"nyholm/psr7": "^1.2",
"phpspec/phpspec": "^5.1 || ^6.3 || ^7.1",
"phpspec/prophecy": "^1.10.2",
"phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3"
},
"suggest": {
"ext-json": "To detect JSON responses with the ContentTypePlugin",
"ext-libxml": "To detect XML responses with the ContentTypePlugin",
"php-http/cache-plugin": "PSR-6 Cache plugin",
"php-http/logger-plugin": "PSR-3 Logger plugin",
"php-http/stopwatch-plugin": "Symfony Stopwatch plugin"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3.x-dev"
}
},
"autoload": {
"psr-4": {
"Http\\Client\\Common\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com"
}
],
"description": "Common HTTP Client implementations and tools for HTTPlug",
"homepage": "http://httplug.io",
"keywords": [
"client",
"common",
"http",
"httplug"
],
"support": {
"issues": "https://github.com/php-http/client-common/issues",
"source": "https://github.com/php-http/client-common/tree/2.5.0"
},
"time": "2021-11-26T15:01:24+00:00"
},
{
"name": "php-http/discovery",
"version": "1.14.1",
"source": {
"type": "git",
"url": "https://github.com/php-http/discovery.git",
"reference": "de90ab2b41d7d61609f504e031339776bc8c7223"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/discovery/zipball/de90ab2b41d7d61609f504e031339776bc8c7223",
"reference": "de90ab2b41d7d61609f504e031339776bc8c7223",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"conflict": {
"nyholm/psr7": "<1.0"
},
"require-dev": {
"graham-campbell/phpspec-skip-example-extension": "^5.0",
"php-http/httplug": "^1.0 || ^2.0",
"php-http/message-factory": "^1.0",
"phpspec/phpspec": "^5.1 || ^6.1",
"puli/composer-plugin": "1.0.0-beta10"
},
"suggest": {
"php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
}
},
"autoload": {
"psr-4": {
"Http\\Discovery\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com"
}
],
"description": "Finds installed HTTPlug implementations and PSR-7 message factories",
"homepage": "http://php-http.org",
"keywords": [
"adapter",
"client",
"discovery",
"factory",
"http",
"message",
"psr7"
],
"support": {
"issues": "https://github.com/php-http/discovery/issues",
"source": "https://github.com/php-http/discovery/tree/1.14.1"
},
"time": "2021-09-18T07:57:46+00:00"
},
{
"name": "php-http/httplug",
"version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/php-http/httplug.git",
"reference": "f640739f80dfa1152533976e3c112477f69274eb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/httplug/zipball/f640739f80dfa1152533976e3c112477f69274eb",
"reference": "f640739f80dfa1152533976e3c112477f69274eb",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0",
"php-http/promise": "^1.1",
"psr/http-client": "^1.0",
"psr/http-message": "^1.0"
},
"require-dev": {
"friends-of-phpspec/phpspec-code-coverage": "^4.1",
"phpspec/phpspec": "^5.1 || ^6.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"autoload": {
"psr-4": {
"Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Eric GELOEN",
"email": "geloen.eric@gmail.com"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://sagikazarmark.hu"
}
],
"description": "HTTPlug, the HTTP client abstraction for PHP",
"homepage": "http://httplug.io",
"keywords": [
"client",
"http"
],
"support": {
"issues": "https://github.com/php-http/httplug/issues",
"source": "https://github.com/php-http/httplug/tree/2.3.0"
},
"time": "2022-02-21T09:52:22+00:00"
},
{
"name": "php-http/message",
"version": "1.13.0",
"source": {
"type": "git",
"url": "https://github.com/php-http/message.git",
"reference": "7886e647a30a966a1a8d1dad1845b71ca8678361"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/message/zipball/7886e647a30a966a1a8d1dad1845b71ca8678361",
"reference": "7886e647a30a966a1a8d1dad1845b71ca8678361",
"shasum": ""
},
"require": {
"clue/stream-filter": "^1.5",
"php": "^7.1 || ^8.0",
"php-http/message-factory": "^1.0.2",
"psr/http-message": "^1.0"
},
"provide": {
"php-http/message-factory-implementation": "1.0"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.6",
"ext-zlib": "*",
"guzzlehttp/psr7": "^1.0",
"laminas/laminas-diactoros": "^2.0",
"phpspec/phpspec": "^5.1 || ^6.3 || ^7.1",
"slim/slim": "^3.0"
},
"suggest": {
"ext-zlib": "Used with compressor/decompressor streams",
"guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories",
"laminas/laminas-diactoros": "Used with Diactoros Factories",
"slim/slim": "Used with Slim Framework PSR-7 implementation"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10-dev"
}
},
"autoload": {
"files": [
"src/filters.php"
],
"psr-4": {
"Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com"
}
],
"description": "HTTP Message related tools",
"homepage": "http://php-http.org",
"keywords": [
"http",
"message",
"psr-7"
],
"support": {
"issues": "https://github.com/php-http/message/issues",
"source": "https://github.com/php-http/message/tree/1.13.0"
},
"time": "2022-02-11T13:41:14+00:00"
},
{
"name": "php-http/message-factory",
"version": "v1.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-http/message-factory.git",
"reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1",
"reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1",
"shasum": ""
},
"require": {
"php": ">=5.4",
"psr/http-message": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com"
}
],
"description": "Factory interfaces for PSR-7 HTTP Message",
"homepage": "http://php-http.org",
"keywords": [
"factory",
"http",
"message",
"stream",
"uri"
],
"support": {
"issues": "https://github.com/php-http/message-factory/issues",
"source": "https://github.com/php-http/message-factory/tree/master"
},
"time": "2015-12-19T14:08:53+00:00"
},
{
"name": "php-http/promise",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-http/promise.git",
"reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/promise/zipball/4c4c1f9b7289a2ec57cde7f1e9762a5789506f88",
"reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"friends-of-phpspec/phpspec-code-coverage": "^4.3.2",
"phpspec/phpspec": "^5.1.2 || ^6.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
},
"autoload": {
"psr-4": {
"Http\\Promise\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Joel Wurtz",
"email": "joel.wurtz@gmail.com"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com"
}
],
"description": "Promise used for asynchronous HTTP requests",
"homepage": "http://httplug.io",
"keywords": [
"promise"
],
"support": {
"issues": "https://github.com/php-http/promise/issues",
"source": "https://github.com/php-http/promise/tree/1.1.0"
},
"time": "2020-07-07T09:29:14+00:00"
},
{
"name": "pimple/pimple",
"version": "v3.3.0",
@ -1015,6 +1542,113 @@
],
"time": "2017-02-14T16:28:37+00:00"
},
{
"name": "psr/http-client",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client/tree/master"
},
"time": "2020-06-29T06:28:15+00:00"
},
{
"name": "psr/http-factory",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-factory.git",
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
"shasum": ""
},
"require": {
"php": ">=7.0.0",
"psr/http-message": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for PSR-7 HTTP message factories",
"keywords": [
"factory",
"http",
"message",
"psr",
"psr-17",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-factory/tree/master"
},
"time": "2019-04-30T12:38:16+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
@ -1487,6 +2121,56 @@
],
"time": "2021-01-28T22:06:19+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665",
"reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"time": "2020-09-07T11:33:47+00:00"
},
{
"name": "symfony/finder",
"version": "v5.0.8",
@ -1536,6 +2220,58 @@
"homepage": "https://symfony.com",
"time": "2020-03-27T16:56:45+00:00"
},
{
"name": "symfony/options-resolver",
"version": "v5.2.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
"reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce",
"reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-php73": "~1.0",
"symfony/polyfill-php80": "^1.15"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\OptionsResolver\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an improved replacement for the array_replace PHP function",
"homepage": "https://symfony.com",
"keywords": [
"config",
"configuration",
"options"
],
"time": "2021-01-27T12:56:27+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.22.0",
@ -6576,56 +7312,6 @@
"homepage": "https://symfony.com",
"time": "2021-01-27T12:56:27+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665",
"reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"time": "2020-09-07T11:33:47+00:00"
},
{
"name": "symfony/dotenv",
"version": "v5.2.3",
@ -6909,58 +7595,6 @@
"homepage": "https://symfony.com",
"time": "2021-01-27T10:01:46+00:00"
},
{
"name": "symfony/options-resolver",
"version": "v5.2.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
"reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce",
"reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-php73": "~1.0",
"symfony/polyfill-php80": "^1.15"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\OptionsResolver\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an improved replacement for the array_replace PHP function",
"homepage": "https://symfony.com",
"keywords": [
"config",
"configuration",
"options"
],
"time": "2021-01-27T12:56:27+00:00"
},
{
"name": "symfony/var-dumper",
"version": "v5.0.8",
@ -7139,5 +7773,5 @@
"platform-overrides": {
"php": "7.3.11"
},
"plugin-api-version": "2.2.0"
"plugin-api-version": "2.0.0"
}

View file

@ -11,6 +11,7 @@ use Alltube\Exception\ConfigException;
use Alltube\Exception\DependencyException;
use Alltube\Library\Exception\AlltubeLibraryException;
use Exception;
use Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Exception\InvalidURLException;
use Slim\Http\Environment;
use Slim\Http\Request;
use SmartyException;
@ -113,7 +114,8 @@ class FrontControllerTest extends ControllerTest
*/
public function testInfoWithoutUrl()
{
$this->assertRequestIsRedirect('info');
$this->expectException(InvalidURLException::class);
$this->getRequestResult('info', []);
}
/**