Add support for password protected videos
This commit is contained in:
parent
621ccfb491
commit
e34b01f2c4
9 changed files with 196 additions and 29 deletions
13
classes/PasswordException.php
Normal file
13
classes/PasswordException.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
/**
|
||||
* PasswordException class
|
||||
*/
|
||||
namespace Alltube;
|
||||
|
||||
/**
|
||||
* Exception thrown when a video requires a password
|
||||
*/
|
||||
class PasswordException extends \Exception
|
||||
{
|
||||
|
||||
}
|
|
@ -71,13 +71,14 @@ class VideoDownload
|
|||
/**
|
||||
* Get a property from youtube-dl.
|
||||
*
|
||||
* @param string $url URL to parse
|
||||
* @param string $format Format
|
||||
* @param string $prop Property
|
||||
* @param string $url URL to parse
|
||||
* @param string $format Format
|
||||
* @param string $prop Property
|
||||
* @param string $password Video password
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getProp($url, $format = null, $prop = 'dump-json')
|
||||
private function getProp($url, $format = null, $prop = 'dump-json', $password = null)
|
||||
{
|
||||
$this->procBuilder->setArguments(
|
||||
[
|
||||
|
@ -88,10 +89,21 @@ class VideoDownload
|
|||
if (isset($format)) {
|
||||
$this->procBuilder->add('-f '.$format);
|
||||
}
|
||||
if (isset($password)) {
|
||||
$this->procBuilder->add('--video-password');
|
||||
$this->procBuilder->add($password);
|
||||
}
|
||||
$process = $this->procBuilder->getProcess();
|
||||
$process->run();
|
||||
if (!$process->isSuccessful()) {
|
||||
throw new \Exception($process->getErrorOutput());
|
||||
$errorOutput = trim($process->getErrorOutput());
|
||||
if ($errorOutput == 'ERROR: This video is protected by a password, use the --video-password option') {
|
||||
throw new PasswordException($errorOutput);
|
||||
} elseif (substr($errorOutput, 0, 21) == 'ERROR: Wrong password') {
|
||||
throw new \Exception('Wrong password');
|
||||
} else {
|
||||
throw new \Exception($errorOutput);
|
||||
}
|
||||
} else {
|
||||
return $process->getOutput();
|
||||
}
|
||||
|
@ -100,40 +112,43 @@ class VideoDownload
|
|||
/**
|
||||
* Get all information about a video.
|
||||
*
|
||||
* @param string $url URL of page
|
||||
* @param string $format Format to use for the video
|
||||
* @param string $url URL of page
|
||||
* @param string $format Format to use for the video
|
||||
* @param string $password Video password
|
||||
*
|
||||
* @return object Decoded JSON
|
||||
* */
|
||||
public function getJSON($url, $format = null)
|
||||
public function getJSON($url, $format = null, $password = null)
|
||||
{
|
||||
return json_decode($this->getProp($url, $format, 'dump-json'));
|
||||
return json_decode($this->getProp($url, $format, 'dump-json', $password));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get URL of video from URL of page.
|
||||
*
|
||||
* @param string $url URL of page
|
||||
* @param string $format Format to use for the video
|
||||
* @param string $url URL of page
|
||||
* @param string $format Format to use for the video
|
||||
* @param string $password Video password
|
||||
*
|
||||
* @return string URL of video
|
||||
* */
|
||||
public function getURL($url, $format = null)
|
||||
public function getURL($url, $format = null, $password = null)
|
||||
{
|
||||
return $this->getProp($url, $format, 'get-url');
|
||||
return $this->getProp($url, $format, 'get-url', $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filename of video file from URL of page.
|
||||
*
|
||||
* @param string $url URL of page
|
||||
* @param string $format Format to use for the video
|
||||
* @param string $url URL of page
|
||||
* @param string $format Format to use for the video
|
||||
* @param string $password Video password
|
||||
*
|
||||
* @return string Filename of extracted video
|
||||
* */
|
||||
public function getFilename($url, $format = null)
|
||||
public function getFilename($url, $format = null, $password = null)
|
||||
{
|
||||
return trim($this->getProp($url, $format, 'get-filename'));
|
||||
return trim($this->getProp($url, $format, 'get-filename', $password));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
"symfony/yaml": "~3.1.0",
|
||||
"symfony/process": "~3.1.0",
|
||||
"ptachoire/process-builder-chain": "~1.2.0",
|
||||
"rudloff/smarty-plugin-noscheme": "~0.1.0"
|
||||
"rudloff/smarty-plugin-noscheme": "~0.1.0",
|
||||
"aura/session": "~2.1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/var-dumper": "~3.1.0",
|
||||
|
|
66
composer.lock
generated
66
composer.lock
generated
|
@ -4,9 +4,71 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "2814570fa83cedc8e079c1d236a787d2",
|
||||
"content-hash": "91057608d6f29b8de8a9761bb419f19c",
|
||||
"hash": "7feb22c9a83e389562253bd1e7389080",
|
||||
"content-hash": "0ca3a07c96a159c3a44ae007b56a9fbf",
|
||||
"packages": [
|
||||
{
|
||||
"name": "aura/session",
|
||||
"version": "2.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/auraphp/Aura.Session.git",
|
||||
"reference": "7d2f7d41ad693970b5b6b83facca0961d3378883"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/auraphp/Aura.Session/zipball/7d2f7d41ad693970b5b6b83facca0961d3378883",
|
||||
"reference": "7d2f7d41ad693970b5b6b83facca0961d3378883",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"aura/di": "~2.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mcrypt": "Mcrypt generates the next best secure CSRF tokens.",
|
||||
"ext-openssl": "OpenSSL generates the best secure CSRF tokens.",
|
||||
"ircmaxell/random-lib": "A Library For Generating Secure Random Numbers",
|
||||
"paragonie/random_compat": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"aura": {
|
||||
"type": "library",
|
||||
"config": {
|
||||
"common": "Aura\\Session\\_Config\\Common"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Aura\\Session\\": "src/",
|
||||
"Aura\\Session\\_Config\\": "config/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-2-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Aura.Session Contributors",
|
||||
"homepage": "https://github.com/auraphp/Aura.Session/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides session management functionality, including lazy session starting, session segments, next-request-only (\"flash\") values, and CSRF tools.",
|
||||
"homepage": "https://github.com/auraphp/Aura.Session",
|
||||
"keywords": [
|
||||
"csrf",
|
||||
"flash",
|
||||
"flash message",
|
||||
"session",
|
||||
"sessions"
|
||||
],
|
||||
"time": "2016-10-03 20:28:32"
|
||||
},
|
||||
{
|
||||
"name": "container-interop/container-interop",
|
||||
"version": "1.1.0",
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Alltube\Controller;
|
|||
|
||||
use Alltube\Config;
|
||||
use Alltube\VideoDownload;
|
||||
use Alltube\PasswordException;
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Slim\Container;
|
||||
use Slim\Http\Request;
|
||||
|
@ -48,6 +49,9 @@ class FrontController
|
|||
$this->config = Config::getInstance();
|
||||
$this->download = new VideoDownload();
|
||||
$this->container = $container;
|
||||
$session_factory = new \Aura\Session\SessionFactory;
|
||||
$session = $session_factory->newInstance($_COOKIE);
|
||||
$this->sessionSegment = $session->getSegment('Alltube\Controller\FrontController');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,6 +102,28 @@ class FrontController
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a password prompt
|
||||
* @param Request $request PSR-7 request
|
||||
* @param Response $response PSR-7 response
|
||||
*
|
||||
* @return Response HTTP response
|
||||
*/
|
||||
public function password(Request $request, Response $response)
|
||||
{
|
||||
if ($this->container instanceof Container) {
|
||||
$this->container->view->render(
|
||||
$response,
|
||||
'password.tpl',
|
||||
[
|
||||
'class' => 'password',
|
||||
'title' => 'Password prompt',
|
||||
'description' => 'You need a password in order to download this video with Alltube Download',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dislay information about the video.
|
||||
*
|
||||
|
@ -109,8 +135,11 @@ class FrontController
|
|||
public function video(Request $request, Response $response)
|
||||
{
|
||||
$params = $request->getQueryParams();
|
||||
$this->config = Config::getInstance();
|
||||
if (isset($params['url'])) {
|
||||
$password = $request->getParam('password');
|
||||
if (isset($password)) {
|
||||
$this->sessionSegment->setFlash($params['url'], $password);
|
||||
}
|
||||
if (isset($params['audio'])) {
|
||||
try {
|
||||
$url = $this->download->getURL($params['url'], 'mp3[protocol^=http]');
|
||||
|
@ -132,7 +161,11 @@ class FrontController
|
|||
return $response;
|
||||
}
|
||||
} else {
|
||||
$video = $this->download->getJSON($params['url']);
|
||||
try {
|
||||
$video = $this->download->getJSON($params['url'], null, $password);
|
||||
} catch (PasswordException $e) {
|
||||
return $this->password($request, $response);
|
||||
}
|
||||
if ($this->container instanceof Container) {
|
||||
$this->container->view->render(
|
||||
$response,
|
||||
|
@ -190,9 +223,11 @@ class FrontController
|
|||
$params = $request->getQueryParams();
|
||||
if (isset($params['url'])) {
|
||||
try {
|
||||
$url = $this->download->getURL($params['url'], $params['format']);
|
||||
$url = $this->download->getURL($params['url'], $request->getParam('format'), $this->sessionSegment->getFlash($params['url']));
|
||||
|
||||
return $response->withRedirect($url);
|
||||
} catch (PasswordException $e) {
|
||||
return $response->withRedirect($this->container->get('router')->pathFor('video').'?url='.urlencode($params['url']));
|
||||
} catch (\Exception $e) {
|
||||
$response->getBody()->write($e->getMessage());
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ $app->get(
|
|||
'/extractors',
|
||||
[$controller, 'extractors']
|
||||
)->setName('extractors');
|
||||
$app->get(
|
||||
$app->any(
|
||||
'/video',
|
||||
[$controller, 'video']
|
||||
)->setName('video');
|
||||
|
|
13
templates/password.tpl
Normal file
13
templates/password.tpl
Normal file
|
@ -0,0 +1,13 @@
|
|||
{include file='inc/head.tpl'}
|
||||
<div class="wrapper">
|
||||
<div class="main">
|
||||
{include file="inc/logo.tpl"}
|
||||
<h2>This video is protected</h2>
|
||||
<p>You need a password in order to download this video.</p>
|
||||
<form action="" method="POST">
|
||||
<input class="URLinput" type="password" name="password" title="Video password" />
|
||||
<br/><br/>
|
||||
<input class="downloadBtn" type="submit" value="Download" />
|
||||
</form>
|
||||
</div>
|
||||
{include file='inc/footer.tpl'}
|
|
@ -28,11 +28,7 @@
|
|||
<optgroup label="Generic formats">
|
||||
<option value="best[protocol^=http]">
|
||||
{strip}
|
||||
Best ({$video->ext}
|
||||
{if isset($video->filesize)}
|
||||
{$video->filesize}
|
||||
{/if}
|
||||
)
|
||||
Best ({$video->ext})
|
||||
{/strip}
|
||||
</option>
|
||||
<option value="worst[protocol^=http]">
|
||||
|
|
|
@ -89,6 +89,38 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
|
|||
$this->assertContains($domain, $videoURL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getURL function with a protected video
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetURLWithPassword()
|
||||
{
|
||||
$this->assertContains('vimeocdn.com', $this->download->getURL('http://vimeo.com/68375962', null, 'youtube-dl'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getURL function with a protected video and no password.
|
||||
*
|
||||
* @return void
|
||||
* @expectedException \Alltube\PasswordException
|
||||
*/
|
||||
public function testGetURLWithMissingPassword()
|
||||
{
|
||||
$this->download->getURL('http://vimeo.com/68375962');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getURL function with a protected video and a wrong password.
|
||||
*
|
||||
* @return void
|
||||
* @expectedException Exception
|
||||
*/
|
||||
public function testGetURLWithWrongPassword()
|
||||
{
|
||||
$this->download->getURL('http://vimeo.com/68375962', null, 'foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getURL function errors.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue