diff --git a/classes/Controller/BaseController.php b/classes/Controller/BaseController.php index 164686e..3279708 100644 --- a/classes/Controller/BaseController.php +++ b/classes/Controller/BaseController.php @@ -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']; + } } diff --git a/classes/Controller/DownloadController.php b/classes/Controller/DownloadController.php index 50a1110..dece054 100644 --- a/classes/Controller/DownloadController.php +++ b/classes/Controller/DownloadController.php @@ -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')); } } diff --git a/classes/Controller/FrontController.php b/classes/Controller/FrontController.php index 21cd8a9..15e1428 100644 --- a/classes/Controller/FrontController.php +++ b/classes/Controller/FrontController.php @@ -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 stdClass; use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; @@ -241,24 +242,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); } } diff --git a/classes/Controller/JsonController.php b/classes/Controller/JsonController.php index 9f916bc..fddef42 100644 --- a/classes/Controller/JsonController.php +++ b/classes/Controller/JsonController.php @@ -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); } } diff --git a/composer.json b/composer.json index 72e6468..110bb13 100644 --- a/composer.json +++ b/composer.json @@ -25,6 +25,8 @@ "aura/session": "^2.1", "barracudanetworks/archivestream-php": "^1.0", "consolidation/log": "^2.0", + "cweagans/composer-patches": "^1.7", + "j0k3r/httplug-ssrf-plugin": "^2.0", "jawira/case-converter": "^3.4", "jean85/pretty-package-versions": "^1.3", "mathmarques/smarty-view": "^1.2", @@ -97,7 +99,12 @@ }, "installer-types": [ "library" - ] + ], + "patches": { + "ytdl-org/youtube-dl": { + "Disable redirects in generic extractor": "patches/youtube-dl-redirect.diff" + } + } }, "scripts": { "lint": "grumphp run --ansi", diff --git a/composer.lock b/composer.lock index 29a4a78..9ebb02c 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "f0b1941ee7bf6b47d0e64b985820f67f", + "content-hash": "974394449b698311047a0560ca06f431", "packages": [ { "name": "aura/session", @@ -116,6 +116,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", @@ -395,6 +461,54 @@ }, "time": "2020-05-27T17:06:13+00:00" }, + { + "name": "cweagans/composer-patches", + "version": "1.7.2", + "source": { + "type": "git", + "url": "https://github.com/cweagans/composer-patches.git", + "reference": "e9969cfc0796e6dea9b4e52f77f18e1065212871" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweagans/composer-patches/zipball/e9969cfc0796e6dea9b4e52f77f18e1065212871", + "reference": "e9969cfc0796e6dea9b4e52f77f18e1065212871", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.3.0" + }, + "require-dev": { + "composer/composer": "~1.0 || ~2.0", + "phpunit/phpunit": "~4.6" + }, + "type": "composer-plugin", + "extra": { + "class": "cweagans\\Composer\\Patches" + }, + "autoload": { + "psr-4": { + "cweagans\\Composer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Cameron Eagans", + "email": "me@cweagans.net" + } + ], + "description": "Provides a way to patch Composer packages.", + "support": { + "issues": "https://github.com/cweagans/composer-patches/issues", + "source": "https://github.com/cweagans/composer-patches/tree/1.7.2" + }, + "time": "2022-01-25T19:21:20+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "6.5.5", @@ -493,12 +607,12 @@ } }, "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, "files": [ "src/functions_include.php" - ] + ], + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -596,6 +710,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.6", @@ -1007,6 +1192,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.1", @@ -1113,6 +1688,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", @@ -1759,6 +2441,75 @@ ], "time": "2021-12-15T11:06:13+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" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v5.2.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-27T12:56:27+00:00" + }, { "name": "symfony/polyfill-ctype", "version": "v1.23.0", @@ -1790,12 +2541,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2579,12 +3330,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "Symfony\\Component\\String\\": "" - }, "files": [ "Resources/functions.php" ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, "exclude-from-classmap": [ "/Tests/" ] @@ -2950,13 +3701,13 @@ } }, "autoload": { - "psr-4": { - "Amp\\": "lib" - }, "files": [ "lib/functions.php", "lib/Internal/functions.php" - ] + ], + "psr-4": { + "Amp\\": "lib" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5318,12 +6069,12 @@ } }, "autoload": { - "psr-4": { - "Opis\\Closure\\": "src/" - }, "files": [ "functions.php" - ] + ], + "psr-4": { + "Opis\\Closure\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -8361,75 +9112,6 @@ ], "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" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.2.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-01-27T12:56:27+00:00" - }, { "name": "symfony/var-dumper", "version": "v5.4.2", diff --git a/patches/youtube-dl-redirect.diff b/patches/youtube-dl-redirect.diff new file mode 100644 index 0000000..d3f5530 --- /dev/null +++ b/patches/youtube-dl-redirect.diff @@ -0,0 +1,12 @@ +diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py +index f99d887ca..749ed6ecf 100644 +--- a/youtube_dl/extractor/generic.py ++++ b/youtube_dl/extractor/generic.py +@@ -2252,6 +2252,7 @@ class GenericIE(InfoExtractor): + + def report_following_redirect(self, new_url): + """Report information extraction.""" ++ raise UnsupportedError('Redirects are not allowed') + self._downloader.to_screen('[redirect] Following redirect to %s' % new_url) + + def _extract_rss(self, url, video_id, doc): diff --git a/tests/FrontControllerTest.php b/tests/FrontControllerTest.php index 65a3d61..4b77ab6 100644 --- a/tests/FrontControllerTest.php +++ b/tests/FrontControllerTest.php @@ -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', []); } /**