diff --git a/.travis.yml b/.travis.yml index 9f514fb..dfeb0ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,22 @@ language: php +php: + - 5.6 + - 7 install: - - composer install --no-dev + - composer install before_install: - - composer selfupdate + - npm install -g npm@3 after_success: - bash <(curl -s https://codecov.io/bash) +before_deploy: + - npm install + - ./node_modules/.bin/grunt doc +deploy: + provider: surge + project: ./docs/ + domain: alltube.surge.sh + skip_cleanup: true +env: + global: + - SURGE_LOGIN=contact@rudloff.pro + - secure: Icw8UqAilq0+neZsdXn7pny5OrDin1tTN0H3HGPFDBawHWBEffettRsURljnBlm0IcAE8HPvl0DlaGFMedM3ZlYjvp7OqMqe84p7dY22JMvirV4MsMz546FKEYI+g3txawAMDFPCorE+fgkDrL1eUoozGVJxc5c4w4nBVm84QvjxRvCvEKbfevd4giaie1Xuo927lKAwTaVFZryYNotPyJVB2pBBndxfl2EJczJ4DXQc3VczFXkTmuE/QLa2tQVJm5vnVPwOi1xmvgh6g1ChEOw0zAks1Mf5+UvxtVV7qTicVAWK0fVVBL9mHPpNzSNb4pPqHPWQjhAPdCW+WPn6+DhqS5BHeSfQit/OtLMpUWO1IceVDRwU3jkXmMgnKwz1t9yDh6VBZRvGPkXfU3cjQ9SFpmnnu/4JLgwA/zSU2Pzl7/+gsHQBazkXh8HYAbOjF2w1IBXOpZ8Yv7D5axRIDduS/TUQ6oNK3KYmRMBcg8ZzVzIdz+55NchaDtihcp5akaHhKxR7GMPrfi66b+wARSw3OsYmCGLNFF8zj/6zo3/zB02+oVMlXXySOAKKi0A2OvH9xV4W4Jl0TGua/27XOWr9c5btrZrykk3PXfKe5YgT46Q8CtK8yN97bDKbwbAp6gNEyMFFatdHKlEndZYsVDQ16htd0b/303SZfXYMvO0= diff --git a/Dockerfile b/Dockerfile index 5dbf4fd..92426ba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,16 @@ FROM php:5.6-apache RUN apt-get update -RUN apt-get install -y libicu-dev xz-utils git zlib1g-dev python npm nodejs-legacy +RUN curl -sL https://deb.nodesource.com/setup_6.x | bash - +RUN apt-get install -y libicu-dev xz-utils git zlib1g-dev python nodejs RUN docker-php-ext-install mbstring RUN docker-php-ext-install intl RUN docker-php-ext-install zip RUN npm install -g bower grunt-cli RUN a2enmod rewrite +RUN curl -sS https://getcomposer.org/installer | php COPY php.ini /usr/local/etc/php/ COPY . /var/www/html/ -RUN curl -sS https://getcomposer.org/installer | php -RUN php composer.phar install +RUN php composer.phar install --prefer-dist RUN npm install RUN bower --allow-root install RUN grunt diff --git a/FAQ.md b/FAQ.md index 1bfb336..2a79dbf 100644 --- a/FAQ.md +++ b/FAQ.md @@ -55,3 +55,11 @@ There are two known workarounds: * You can run Alltube locally on your computer. * You can use the experimental `feature/stream` branch which streams the video through the server in order to bypass IP restrictions. Please note that this can use a lot of resources on the server (which is why we won't enable it on alltubedownload.net). + +## CSS and JavaScript files are missing + +You probably don't have the minified files (in the `dist` folder). +You need to either: + +* Use a [release package](https://github.com/Rudloff/alltube/releases) +* Run `npm install` (see detailed instructions in the [README](README.md#from-git)) diff --git a/Gruntfile.js b/Gruntfile.js index 6e13bd6..dcc42ff 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -68,7 +68,7 @@ module.exports = function (grunt) { options: { archive: 'alltube-<%= githash.main.tag %>.zip' }, - src: ['*.php', '!config.yml', 'dist/**', '.htaccess', 'img/**', 'LICENSE', 'README.md', 'robots.txt', 'sitemap.xml', 'templates/**', 'templates_c/', 'vendor/**', 'classes/**', 'controllers/**', 'bower_components/**', '!vendor/ffmpeg/**', '!vendor/bin/ffmpeg'] + src: ['*.php', '!config.yml', 'dist/**', '.htaccess', 'img/**', 'LICENSE', 'README.md', 'robots.txt', 'sitemap.xml', 'templates/**', 'templates_c/', 'vendor/**', 'classes/**', 'controllers/**', 'bower_components/**', '!vendor/ffmpeg/**', '!vendor/bin/ffmpeg', '!vendor/phpunit/**', '!vendor/squizlabs/**'] } }, phpdocumentor: { diff --git a/README.md b/README.md index 63fea97..f35d40b 100644 --- a/README.md +++ b/README.md @@ -110,12 +110,6 @@ server { } ``` -## License - -This software is available under the [GNU General Public License](http://www.gnu.org/licenses/gpl.html). - -Please __use a different name and logo__ if you run it on a public server. - ## Other dependencies You need [avconv](https://libav.org/avconv.html), [rtmpdump](http://rtmpdump.mplayerhq.hu/) and [curl](https://curl.haxx.se/) in order to enable conversions. @@ -129,6 +123,45 @@ sudo apt-get install libav-tools rtmpdump curl You also probably need to edit the `avconv` variable in `config.yml` so that it points to your ffmpeg/avconv binary (`/usr/bin/avconv` on Debian/Ubuntu). +## Use as library + +Alltube can also be used as a library to extract a video URL from a webpage. + +You can install it with: + +```bash +composer require rudloff/alltube +``` + +You can then use it in your PHP code: + +```php +use Alltube\Config; +use Alltube\VideoDownload; + +require_once __DIR__.'/vendor/autoload.php'; + +$downloader = new VideoDownload( + new Config( + [ + 'youtubedl' => '/usr/local/bin/youtube-dl', + ] + ) +); + +$downloader->getURL('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +``` + +The library documentation is available on [alltube.surge.sh](https://alltube.surge.sh/classes/Alltube.VideoDownload.html). + +You can also have a look at this [example project](https://github.com/Rudloff/alltube-example-project). + ## FAQ Please read the [FAQ](FAQ.md) before reporting any issue. + +## License + +This software is available under the [GNU General Public License](http://www.gnu.org/licenses/gpl.html). + +Please __use a different name and logo__ if you run it on a public server. diff --git a/classes/Config.php b/classes/Config.php index 674717b..c57c848 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -2,6 +2,7 @@ /** * Config class. */ + namespace Alltube; use Symfony\Component\Yaml\Yaml; @@ -84,28 +85,37 @@ class Config /** * Config constructor. * - * @param string $yamlfile YAML config file path + * Available options: + * * youtubedl: youtube-dl binary path + * * python: Python binary path + * * avconv: avconv or ffmpeg binary path + * * rtmpdump: rtmpdump binary path + * * curl: curl binary path + * * params: Array of youtube-dl parameters + * * curl_params: Array of curl parameters + * * convert: Enable conversion? + * + * @param array $options Options */ - private function __construct($yamlfile) + public function __construct(array $options) { - $this->file = $yamlfile; - if (is_file($yamlfile)) { - $yaml = Yaml::parse(file_get_contents($yamlfile)); - if (isset($yaml) && is_array($yaml)) { - foreach ($yaml as $param => $value) { - if (isset($this->$param) && isset($value)) { - $this->$param = $value; - } + if (isset($options) && is_array($options)) { + foreach ($options as $option => $value) { + if (isset($this->$option) && isset($value)) { + $this->$option = $value; } } } if (getenv('CONVERT')) { $this->convert = (bool) getenv('CONVERT'); } + if (getenv('PYTHON')) { + $this->python = getenv('PYTHON'); + } } /** - * Get singleton instance. + * Get Config singleton instance from YAML config file. * * @param string $yamlfile YAML config file name * @@ -113,9 +123,21 @@ class Config */ public static function getInstance($yamlfile = 'config.yml') { - $yamlfile = __DIR__.'/../'.$yamlfile; + $yamlPath = __DIR__.'/../'.$yamlfile; if (is_null(self::$instance) || self::$instance->file != $yamlfile) { - self::$instance = new self($yamlfile); + if (is_file($yamlfile)) { + $options = Yaml::parse(file_get_contents($yamlPath)); + } elseif ($yamlfile == 'config.yml') { + /* + Allow for the default file to be missing in order to + not surprise users that did not create a config file + */ + $options = []; + } else { + throw new \Exception("Can't find config file at ".$yamlPath); + } + self::$instance = new self($options); + self::$instance->file = $yamlfile; } return self::$instance; diff --git a/classes/PasswordException.php b/classes/PasswordException.php new file mode 100644 index 0000000..6ede500 --- /dev/null +++ b/classes/PasswordException.php @@ -0,0 +1,13 @@ +config = Config::getInstance(); + if (isset($config)) { + $this->config = $config; + } else { + $this->config = Config::getInstance(); + } $this->procBuilder = new ProcessBuilder(); + if (!is_file($this->config->youtubedl)) { + throw new \Exception("Can't find youtube-dl at ".$this->config->youtubedl); + } elseif (!is_file($this->config->python)) { + throw new \Exception("Can't find Python at ".$this->config->python); + } $this->procBuilder->setPrefix( array_merge( [$this->config->python, $this->config->youtubedl], @@ -48,27 +58,20 @@ class VideoDownload * */ public function listExtractors() { - $this->procBuilder->setArguments( - [ - '--list-extractors', - ] - ); - $process = $this->procBuilder->getProcess(); - $process->run(); - - return explode(PHP_EOL, trim($process->getOutput())); + return explode(PHP_EOL, trim($this->getProp(null, null, 'list-extractors'))); } /** * 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( [ @@ -79,10 +82,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(); } @@ -91,55 +105,59 @@ 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)); } /** * Get filename of audio 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 converted audio file * */ - public function getAudioFilename($url, $format = null) + public function getAudioFilename($url, $format = null, $password = null) { return html_entity_decode( pathinfo( - $this->getFilename($url, $format), + $this->getFilename($url, $format, $password), PATHINFO_FILENAME ).'.mp3', ENT_COMPAT, @@ -147,21 +165,106 @@ class VideoDownload ); } + /** + * Add options to a process builder running rtmp. + * + * @param ProcessBuilder $builder Process builder + * @param object $video Video object returned by youtube-dl + * + * @return ProcessBuilder + */ + private function addOptionsToRtmpProcess(ProcessBuilder $builder, $video) + { + foreach ([ + 'url' => 'rtmp', + 'webpage_url' => 'pageUrl', + 'player_url' => 'swfVfy', + 'flash_version' => 'flashVer', + 'play_path' => 'playpath', + 'app' => 'app', + ] as $property => $option) { + if (isset($video->{$property})) { + $builder->add('--'.$option); + $builder->add($video->{$property}); + } + } + + return $builder; + } + + /** + * Get a process that runs rtmp in order to download a video. + * + * @param object $video Video object returned by youtube-dl + * + * @return \Symfony\Component\Process\Process Process + */ + private function getRtmpProcess($video) + { + if (!shell_exec('which '.$this->config->rtmpdump)) { + throw(new \Exception('Can\'t find rtmpdump')); + } + $builder = new ProcessBuilder( + [ + $this->config->rtmpdump, + '-q', + ] + ); + $builder = $this->addOptionsToRtmpProcess($builder, $video); + if (isset($video->rtmp_conn)) { + foreach ($video->rtmp_conn as $conn) { + $builder->add('--conn'); + $builder->add($conn); + } + } + + return $builder->getProcess(); + } + + /** + * Get a process that runs curl in order to download a video. + * + * @param object $video Video object returned by youtube-dl + * + * @return \Symfony\Component\Process\Process Process + */ + private function getCurlProcess($video) + { + if (!shell_exec('which '.$this->config->curl)) { + throw(new \Exception('Can\'t find curl')); + } + $builder = ProcessBuilder::create( + array_merge( + [ + $this->config->curl, + '--silent', + '--location', + '--user-agent', $video->http_headers->{'User-Agent'}, + $video->url, + ], + $this->config->curl_params + ) + ); + + return $builder->getProcess(); + } + /** * Get audio stream of converted 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 resource popen stream */ - public function getAudioStream($url, $format) + public function getAudioStream($url, $format, $password = null) { if (!shell_exec('which '.$this->config->avconv)) { throw(new \Exception('Can\'t find avconv or ffmpeg')); } - $video = $this->getJSON($url, $format); + $video = $this->getJSON($url, $format, $password); //Vimeo needs a correct user-agent ini_set( @@ -180,62 +283,12 @@ class VideoDownload ); if (parse_url($video->url, PHP_URL_SCHEME) == 'rtmp') { - if (!shell_exec('which '.$this->config->rtmpdump)) { - throw(new \Exception('Can\'t find rtmpdump')); - } - $builder = new ProcessBuilder( - [ - $this->config->rtmpdump, - '-q', - '-r', - $video->url, - '--pageUrl', $video->webpage_url, - ] - ); - if (isset($video->player_url)) { - $builder->add('--swfVfy'); - $builder->add($video->player_url); - } - if (isset($video->flash_version)) { - $builder->add('--flashVer'); - $builder->add($video->flash_version); - } - if (isset($video->play_path)) { - $builder->add('--playpath'); - $builder->add($video->play_path); - } - if (isset($video->rtmp_conn)) { - foreach ($video->rtmp_conn as $conn) { - $builder->add('--conn'); - $builder->add($conn); - } - } - if (isset($video->app)) { - $builder->add('--app'); - $builder->add($video->app); - } - $chain = new Chain($builder->getProcess()); - $chain->add('|', $avconvProc); + $process = $this->getRtmpProcess($video); } else { - if (!shell_exec('which '.$this->config->curl)) { - throw(new \Exception('Can\'t find curl')); - } - $chain = new Chain( - ProcessBuilder::create( - array_merge( - [ - $this->config->curl, - '--silent', - '--location', - '--user-agent', $video->http_headers->{'User-Agent'}, - $video->url, - ], - $this->config->curl_params - ) - ) - ); - $chain->add('|', $avconvProc); + $process = $this->getCurlProcess($video); } + $chain = new Chain($process); + $chain->add('|', $avconvProc); return popen($chain->getProcess()->getCommandLine(), 'r'); } diff --git a/composer.json b/composer.json index d8bb080..630a948 100644 --- a/composer.json +++ b/composer.json @@ -6,21 +6,23 @@ "type": "project", "require": { "smarty/smarty": "~3.1.29", - "rg3/youtube-dl": "~2016.09.08", - "slim/slim": "~3.5.0", + "slim/slim": "~3.6.0", "mathmarques/smarty-view": "~1.1.0", - "symfony/yaml": "~3.1.0", - "symfony/process": "~3.1.0", + "symfony/yaml": "~3.2.0", + "symfony/process": "~3.2.0", "ptachoire/process-builder-chain": "~1.2.0", - "ffmpeg/ffmpeg": "dev-release", "rudloff/smarty-plugin-noscheme": "~0.1.0", "guzzlehttp/guzzle": "~6.2.0", - "rudloff/rtmpdump-bin": "~2.3" + "rudloff/rtmpdump-bin": "~2.3", + "aura/session": "~2.1.0" }, "require-dev": { - "symfony/var-dumper": "~3.1.0", + "symfony/var-dumper": "~3.2.0", "squizlabs/php_codesniffer": "~2.7.0", - "phpunit/phpunit": "~5.5.2" + "phpunit/phpunit": "~5.7.2", + "ffmpeg/ffmpeg": "dev-release", + "rg3/youtube-dl": "~2016.12.20", + "rudloff/rtmpdump-bin": "~2.3" }, "extra": { "paas": { @@ -34,11 +36,10 @@ "type": "package", "package": { "name": "rg3/youtube-dl", - "version": "2016.09.08", - "source": { - "url": "https://github.com/rg3/youtube-dl.git", - "type": "git", - "reference": "2016.09.08" + "version": "2016.12.20", + "dist": { + "type": "zip", + "url": "https://github.com/rg3/youtube-dl/archive/2016.12.20.zip" } } }, @@ -79,5 +80,8 @@ }, "config": { "secure-http": false + }, + "scripts": { + "compile": "composer install --dev" } } diff --git a/composer.lock b/composer.lock index fbba819..1a08f5b 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "619ed10d49b90725061dfd851d994432", - "content-hash": "dac044b232222cd1af6f62f3ad24d231", + "hash": "a4497d475262ef7fa88f43d6bd18b3db", + "content-hash": "f553e8eeebb1466397549b8304eccece", "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", @@ -34,20 +96,6 @@ "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", "time": "2014-12-30 15:22:37" }, - { - "name": "ffmpeg/ffmpeg", - "version": "dev-release", - "dist": { - "type": "xz", - "url": "http://johnvansickle.com/ffmpeg/releases/ffmpeg-release-64bit-static.tar.xz", - "reference": null, - "shasum": null - }, - "bin": [ - "ffmpeg" - ], - "type": "library" - }, { "name": "guzzlehttp/guzzle", "version": "6.2.2", @@ -112,28 +160,28 @@ }, { "name": "guzzlehttp/promises", - "version": "1.2.0", + "version": "v1.3.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", - "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", "shasum": "" }, "require": { "php": ">=5.5.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -159,7 +207,7 @@ "keywords": [ "promise" ], - "time": "2016-05-18 16:56:05" + "time": "2016-12-20 10:07:11" }, { "name": "guzzlehttp/psr7", @@ -570,16 +618,6 @@ "description": "Add ability to chain symfony processes", "time": "2016-04-10 08:33:20" }, - { - "name": "rg3/youtube-dl", - "version": "2016.09.08", - "source": { - "type": "git", - "url": "https://github.com/rg3/youtube-dl.git", - "reference": "2016.09.08" - }, - "type": "library" - }, { "name": "rudloff/rtmpdump-bin", "version": "2.3", @@ -651,16 +689,16 @@ }, { "name": "slim/slim", - "version": "3.5.0", + "version": "3.6.0", "source": { "type": "git", "url": "https://github.com/slimphp/Slim.git", - "reference": "184352bc1913d7ba552ab4131d62f4730ddb0893" + "reference": "a685fe91a9435e1432e8eeb7cf516e2f5cee7f64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slimphp/Slim/zipball/184352bc1913d7ba552ab4131d62f4730ddb0893", - "reference": "184352bc1913d7ba552ab4131d62f4730ddb0893", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/a685fe91a9435e1432e8eeb7cf516e2f5cee7f64", + "reference": "a685fe91a9435e1432e8eeb7cf516e2f5cee7f64", "shasum": "" }, "require": { @@ -717,20 +755,20 @@ "micro", "router" ], - "time": "2016-07-26 15:12:13" + "time": "2016-11-20 20:48:49" }, { "name": "smarty/smarty", - "version": "v3.1.30", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/smarty-php/smarty.git", - "reference": "ed2b7f1146cfda13df1eea8a5f707a1b771b6e7e" + "reference": "c7d42e4a327c402897dd587871434888fde1e7a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/smarty-php/smarty/zipball/ed2b7f1146cfda13df1eea8a5f707a1b771b6e7e", - "reference": "ed2b7f1146cfda13df1eea8a5f707a1b771b6e7e", + "url": "https://api.github.com/repos/smarty-php/smarty/zipball/c7d42e4a327c402897dd587871434888fde1e7a9", + "reference": "c7d42e4a327c402897dd587871434888fde1e7a9", "shasum": "" }, "require": { @@ -743,10 +781,8 @@ } }, "autoload": { - "classmap": [ - "libs/Smarty.class.php", - "libs/SmartyBC.class.php", - "libs/sysplugins/" + "files": [ + "libs/bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -772,20 +808,20 @@ "keywords": [ "templating" ], - "time": "2016-08-07 18:46:49" + "time": "2016-12-14 21:57:25" }, { "name": "symfony/process", - "version": "v3.1.5", + "version": "v3.2.1", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "66de154ae86b1a07001da9fbffd620206e4faf94" + "reference": "02ea84847aad71be7e32056408bb19f3a616cdd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/66de154ae86b1a07001da9fbffd620206e4faf94", - "reference": "66de154ae86b1a07001da9fbffd620206e4faf94", + "url": "https://api.github.com/repos/symfony/process/zipball/02ea84847aad71be7e32056408bb19f3a616cdd3", + "reference": "02ea84847aad71be7e32056408bb19f3a616cdd3", "shasum": "" }, "require": { @@ -794,7 +830,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -821,29 +857,35 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-09-29 14:13:09" + "time": "2016-11-24 10:40:28" }, { "name": "symfony/yaml", - "version": "v3.1.5", + "version": "v3.2.1", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "368b9738d4033c8b93454cb0dbd45d305135a6d3" + "reference": "a7095af4b97a0955f85c8989106c249fa649011f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/368b9738d4033c8b93454cb0dbd45d305135a6d3", - "reference": "368b9738d4033c8b93454cb0dbd45d305135a6d3", + "url": "https://api.github.com/repos/symfony/yaml/zipball/a7095af4b97a0955f85c8989106c249fa649011f", + "reference": "a7095af4b97a0955f85c8989106c249fa649011f", "shasum": "" }, "require": { "php": ">=5.5.9" }, + "require-dev": { + "symfony/console": "~2.8|~3.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -870,7 +912,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-09-25 08:27:07" + "time": "2016-12-10 10:07:06" } ], "packages-dev": [ @@ -928,18 +970,32 @@ ], "time": "2015-06-14 21:17:01" }, + { + "name": "ffmpeg/ffmpeg", + "version": "dev-release", + "dist": { + "type": "xz", + "url": "http://johnvansickle.com/ffmpeg/releases/ffmpeg-release-64bit-static.tar.xz", + "reference": null, + "shasum": null + }, + "bin": [ + "ffmpeg" + ], + "type": "library" + }, { "name": "myclabs/deep-copy", - "version": "1.5.4", + "version": "1.5.5", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f" + "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/ea74994a3dc7f8d2f65a06009348f2d63c81e61f", - "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/399c1f9781e222f6eb6cc238796f5200d1b7f108", + "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108", "shasum": "" }, "require": { @@ -968,7 +1024,7 @@ "object", "object graph" ], - "time": "2016-09-16 13:37:59" + "time": "2016-10-31 17:19:45" }, { "name": "phpdocumentor/reflection-common", @@ -1071,16 +1127,16 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "0.2", + "version": "0.2.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", - "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", "shasum": "" }, "require": { @@ -1114,20 +1170,20 @@ "email": "me@mikevanriel.com" } ], - "time": "2016-06-10 07:14:17" + "time": "2016-11-25 06:54:22" }, { "name": "phpspec/prophecy", - "version": "v1.6.1", + "version": "v1.6.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "58a8137754bc24b25740d4281399a4a3596058e0" + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", - "reference": "58a8137754bc24b25740d4281399a4a3596058e0", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", "shasum": "" }, "require": { @@ -1135,10 +1191,11 @@ "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0" + "sebastian/recursion-context": "^1.0|^2.0" }, "require-dev": { - "phpspec/phpspec": "^2.0" + "phpspec/phpspec": "^2.0", + "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", "extra": { @@ -1176,20 +1233,20 @@ "spy", "stub" ], - "time": "2016-06-07 08:13:47" + "time": "2016-11-21 14:58:47" }, { "name": "phpunit/php-code-coverage", - "version": "4.0.1", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3" + "reference": "c14196e64a78570034afd0b7a9f3757ba71c2a0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5f3f7e736d6319d5f1fc402aff8b026da26709a3", - "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c14196e64a78570034afd0b7a9f3757ba71c2a0a", + "reference": "c14196e64a78570034afd0b7a9f3757ba71c2a0a", "shasum": "" }, "require": { @@ -1239,20 +1296,20 @@ "testing", "xunit" ], - "time": "2016-07-26 14:39:29" + "time": "2016-12-20 15:22:42" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", "shasum": "" }, "require": { @@ -1286,7 +1343,7 @@ "filesystem", "iterator" ], - "time": "2015-06-21 13:08:43" + "time": "2016-10-03 07:40:28" }, { "name": "phpunit/php-text-template", @@ -1375,16 +1432,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.8", + "version": "1.4.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", "shasum": "" }, "require": { @@ -1420,20 +1477,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-09-15 10:49:45" + "time": "2016-11-15 14:06:22" }, { "name": "phpunit/phpunit", - "version": "5.5.7", + "version": "5.7.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3f67cee782c9abfaee5e32fd2f57cdd54bc257ba" + "reference": "af91da3f2671006ff5d0628023de3b7ac4d1ef09" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3f67cee782c9abfaee5e32fd2f57cdd54bc257ba", - "reference": "3f67cee782c9abfaee5e32fd2f57cdd54bc257ba", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/af91da3f2671006ff5d0628023de3b7ac4d1ef09", + "reference": "af91da3f2671006ff5d0628023de3b7ac4d1ef09", "shasum": "" }, "require": { @@ -1444,18 +1501,18 @@ "ext-xml": "*", "myclabs/deep-copy": "~1.3", "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "^4.0.1", + "phpspec/prophecy": "^1.6.2", + "phpunit/php-code-coverage": "^4.0.3", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "~1.1", + "sebastian/comparator": "~1.2.2", "sebastian/diff": "~1.2", - "sebastian/environment": "^1.3 || ^2.0", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/object-enumerator": "~1.0", + "sebastian/environment": "^1.3.4 || ^2.0", + "sebastian/exporter": "~2.0", + "sebastian/global-state": "^1.0 || ^2.0", + "sebastian/object-enumerator": "~2.0", "sebastian/resource-operations": "~1.0", "sebastian/version": "~1.0|~2.0", "symfony/yaml": "~2.1|~3.0" @@ -1467,7 +1524,6 @@ "ext-pdo": "*" }, "suggest": { - "ext-tidy": "*", "ext-xdebug": "*", "phpunit/php-invoker": "~1.1" }, @@ -1477,7 +1533,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.5.x-dev" + "dev-master": "5.7.x-dev" } }, "autoload": { @@ -1503,27 +1559,27 @@ "testing", "xunit" ], - "time": "2016-10-03 13:04:15" + "time": "2016-12-13 16:19:44" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.4.0", + "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2" + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/238d7a2723bce689c79eeac9c7d5e1d623bb9dc2", - "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.6 || ^7.0", "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2" + "sebastian/exporter": "^1.2 || ^2.0" }, "conflict": { "phpunit/phpunit": "<5.4.0" @@ -1562,7 +1618,18 @@ "mock", "xunit" ], - "time": "2016-10-09 07:01:45" + "time": "2016-12-08 20:27:08" + }, + { + "name": "rg3/youtube-dl", + "version": "2016.12.20", + "dist": { + "type": "zip", + "url": "https://github.com/rg3/youtube-dl/archive/2016.12.20.zip", + "reference": null, + "shasum": null + }, + "type": "library" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -1611,22 +1678,22 @@ }, { "name": "sebastian/comparator", - "version": "1.2.0", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" + "sebastian/exporter": "~1.2 || ~2.0" }, "require-dev": { "phpunit/phpunit": "~4.4" @@ -1671,7 +1738,7 @@ "compare", "equality" ], - "time": "2015-07-26 15:48:44" + "time": "2016-11-19 09:18:40" }, { "name": "sebastian/diff", @@ -1727,28 +1794,28 @@ }, { "name": "sebastian/environment", - "version": "1.3.8", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" + "phpunit/phpunit": "^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1773,25 +1840,25 @@ "environment", "hhvm" ], - "time": "2016-08-18 05:49:44" + "time": "2016-11-26 07:53:53" }, { "name": "sebastian/exporter", - "version": "1.2.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", "shasum": "" }, "require": { "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" + "sebastian/recursion-context": "~2.0" }, "require-dev": { "ext-mbstring": "*", @@ -1800,7 +1867,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1840,7 +1907,7 @@ "export", "exporter" ], - "time": "2016-06-17 09:04:28" + "time": "2016-11-19 08:54:04" }, { "name": "sebastian/global-state", @@ -1895,21 +1962,21 @@ }, { "name": "sebastian/object-enumerator", - "version": "1.0.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" + "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", + "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", "shasum": "" }, "require": { "php": ">=5.6", - "sebastian/recursion-context": "~1.0" + "sebastian/recursion-context": "~2.0" }, "require-dev": { "phpunit/phpunit": "~5" @@ -1917,7 +1984,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1937,20 +2004,20 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2016-01-28 13:25:10" + "time": "2016-11-19 07:35:10" }, { "name": "sebastian/recursion-context", - "version": "1.0.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", "shasum": "" }, "require": { @@ -1962,7 +2029,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1990,7 +2057,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11 19:50:13" + "time": "2016-11-19 07:33:16" }, { "name": "sebastian/resource-operations", @@ -2036,16 +2103,16 @@ }, { "name": "sebastian/version", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5" + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", - "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", "shasum": "" }, "require": { @@ -2075,20 +2142,20 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-02-04 12:56:52" + "time": "2016-10-03 07:35:21" }, { "name": "squizlabs/php_codesniffer", - "version": "2.7.0", + "version": "2.7.1", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed" + "reference": "9b324f3a1132459a7274a0ace2e1b766ba80930f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", - "reference": "571e27b6348e5b3a637b2abc82ac0d01e6d7bbed", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/9b324f3a1132459a7274a0ace2e1b766ba80930f", + "reference": "9b324f3a1132459a7274a0ace2e1b766ba80930f", "shasum": "" }, "require": { @@ -2153,20 +2220,20 @@ "phpcs", "standards" ], - "time": "2016-09-01 23:53:02" + "time": "2016-11-30 04:02:31" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.2.0", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "dff51f72b0706335131b00a7f49606168c582594" + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", - "reference": "dff51f72b0706335131b00a7f49606168c582594", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", "shasum": "" }, "require": { @@ -2178,7 +2245,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -2212,20 +2279,20 @@ "portable", "shim" ], - "time": "2016-05-18 14:26:46" + "time": "2016-11-14 01:06:16" }, { "name": "symfony/var-dumper", - "version": "v3.1.5", + "version": "v3.2.1", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "70bfe927b86ba9999aeebd829715b0bb2cd39a10" + "reference": "f722532b0966e9b6fc631e682143c07b2cf583a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/70bfe927b86ba9999aeebd829715b0bb2cd39a10", - "reference": "70bfe927b86ba9999aeebd829715b0bb2cd39a10", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/f722532b0966e9b6fc631e682143c07b2cf583a0", + "reference": "f722532b0966e9b6fc631e682143c07b2cf583a0", "shasum": "" }, "require": { @@ -2241,7 +2308,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2275,24 +2342,24 @@ "debug", "dump" ], - "time": "2016-09-29 14:13:09" + "time": "2016-12-11 14:34:22" }, { "name": "webmozart/assert", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "bb2d123231c095735130cc8f6d31385a44c7b308" + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308", - "reference": "bb2d123231c095735130cc8f6d31385a44c7b308", + "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", "shasum": "" }, "require": { - "php": "^5.3.3|^7.0" + "php": "^5.3.3 || ^7.0" }, "require-dev": { "phpunit/phpunit": "^4.6", @@ -2301,7 +2368,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -2325,7 +2392,7 @@ "check", "validate" ], - "time": "2016-08-09 15:02:57" + "time": "2016-11-23 20:04:58" } ], "aliases": [], diff --git a/controllers/FrontController.php b/controllers/FrontController.php index 79a9128..91a82f7 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -2,9 +2,11 @@ /** * FrontController class. */ + namespace Alltube\Controller; use Alltube\Config; +use Alltube\PasswordException; use Alltube\VideoDownload; use Interop\Container\ContainerInterface; use Slim\Container; @@ -38,6 +40,20 @@ class FrontController */ private $container; + /** + * Session segment used to store session variables. + * + * @var \Aura\Session\Segment + */ + private $sessionSegment; + + /** + * Smarty view. + * + * @var \Slim\Views\Smarty + */ + private $view; + /** * FrontController constructor. * @@ -48,6 +64,10 @@ class FrontController $this->config = Config::getInstance(); $this->download = new VideoDownload(); $this->container = $container; + $this->view = $this->container->get('view'); + $session_factory = new \Aura\Session\SessionFactory(); + $session = $session_factory->newInstance($_COOKIE); + $this->sessionSegment = $session->getSegment('Alltube\Controller\FrontController'); } /** @@ -60,17 +80,15 @@ class FrontController */ public function index(Request $request, Response $response) { - if ($this->container instanceof Container) { - $this->container->view->render( - $response, - 'index.tpl', - [ - 'convert' => $this->config->convert, - 'class' => 'index', - 'description' => 'Easily download videos from Youtube, Dailymotion, Vimeo and other websites.', - ] - ); - } + $this->view->render( + $response, + 'index.tpl', + [ + 'convert' => $this->config->convert, + 'class' => 'index', + 'description' => 'Easily download videos from Youtube, Dailymotion, Vimeo and other websites.', + ] + ); } /** @@ -83,19 +101,38 @@ class FrontController */ public function extractors(Request $request, Response $response) { - if ($this->container instanceof Container) { - $this->container->view->render( - $response, - 'extractors.tpl', - [ - 'extractors' => $this->download->listExtractors(), - 'class' => 'extractors', - 'title' => 'Supported websites', - 'description' => 'List of all supported websites from which Alltube Download '. - 'can extract video or audio files', - ] - ); - } + $this->view->render( + $response, + 'extractors.tpl', + [ + 'extractors' => $this->download->listExtractors(), + 'class' => 'extractors', + 'title' => 'Supported websites', + 'description' => 'List of all supported websites from which Alltube Download '. + 'can extract video or audio files', + ] + ); + } + + /** + * 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) + { + $this->view->render( + $response, + 'password.tpl', + [ + 'class' => 'password', + 'title' => 'Password prompt', + 'description' => 'You need a password in order to download this video with Alltube Download', + ] + ); } /** @@ -109,40 +146,47 @@ 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 { return $this->getStream($params['url'], 'mp3[protocol^=http]', $response, $request); + } catch (PasswordException $e) { + return $this->password($request, $response); } catch (\Exception $e) { $response = $response->withHeader( 'Content-Disposition', 'attachment; filename="'. - $this->download->getAudioFilename($params['url'], 'bestaudio/best').'"' + $this->download->getAudioFilename($params['url'], 'bestaudio/best', $password).'"' ); $response = $response->withHeader('Content-Type', 'audio/mpeg'); - if ($request->isGet()) { - $process = $this->download->getAudioStream($params['url'], 'bestaudio/best'); + if ($request->isGet() || $request->isPost()) { + $process = $this->download->getAudioStream($params['url'], 'bestaudio/best', $password); $response = $response->withBody(new Stream($process)); } return $response; } } else { - $video = $this->download->getJSON($params['url']); - if ($this->container instanceof Container) { - $this->container->view->render( - $response, - 'video.tpl', - [ - 'video' => $video, - 'class' => 'video', - 'title' => $video->title, - 'description' => 'Download "'.$video->title.'" from '.$video->extractor_key, - ] - ); + try { + $video = $this->download->getJSON($params['url'], null, $password); + } catch (PasswordException $e) { + return $this->password($request, $response); } + $this->view->render( + $response, + 'video.tpl', + [ + 'video' => $video, + 'class' => 'video', + 'title' => $video->title, + 'description' => 'Download "'.$video->title.'" from '.$video->extractor_key, + ] + ); } } else { return $response->withRedirect($this->container->get('router')->pathFor('index')); @@ -160,17 +204,15 @@ class FrontController */ public function error(Request $request, Response $response, \Exception $exception) { - if ($this->container instanceof Container) { - $this->container->view->render( - $response, - 'error.tpl', - [ - 'errors' => $exception->getMessage(), - 'class' => 'video', - 'title' => 'Error', - ] - ); - } + $this->view->render( + $response, + 'error.tpl', + [ + 'errors' => $exception->getMessage(), + 'class' => 'video', + 'title' => 'Error', + ] + ); return $response->withStatus(500); } @@ -207,6 +249,10 @@ class FrontController if (isset($params['url'])) { try { return $this->getStream($params['url'], $params['format'], $response, $request); + } catch (PasswordException $e) { + return $response->withRedirect( + $this->container->get('router')->pathFor('video').'?url='.urlencode($params['url']) + ); } catch (\Exception $e) { $response->getBody()->write($e->getMessage()); diff --git a/css/style.css b/css/style.css index 1c5c8e7..31ae741 100644 --- a/css/style.css +++ b/css/style.css @@ -1,6 +1,7 @@ body { text-align:center; + background-color: #EBEBEB; background-image:url('../img/fond.jpg'); font-family: 'Open Sans', sans-serif; font-weight:400; diff --git a/index.php b/index.php index f9fdd7d..6db8190 100644 --- a/index.php +++ b/index.php @@ -3,7 +3,7 @@ require_once __DIR__.'/vendor/autoload.php'; use Alltube\Controller\FrontController; -if (strpos($_SERVER['REQUEST_URI'], '/index.php') !== false) { +if (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '/index.php') !== false) { header('Location: '.str_ireplace('/index.php', '/', $_SERVER['REQUEST_URI'])); die; } @@ -19,7 +19,6 @@ $container['view'] = function ($c) { $view->registerPlugin('modifier', 'noscheme', 'Smarty_Modifier_noscheme'); - return $view; }; @@ -35,7 +34,7 @@ $app->get( '/extractors', [$controller, 'extractors'] )->setName('extractors'); -$app->get( +$app->any( '/video', [$controller, 'video'] )->setName('video'); diff --git a/manifest.json b/manifest.json index 0c4b662..25aae7f 100644 --- a/manifest.json +++ b/manifest.json @@ -33,5 +33,6 @@ "lang": "en", "start_url": "./", "theme_color": "#4F4F4F", + "background_color": "#EBEBEB", "orientation": "portrait" } diff --git a/package.json b/package.json index dfbfd4a..7d9d123 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,12 @@ { "name": "alltube", "description": "HTML GUI for youtube-dl", - "version": "0.5.2", + "version": "0.7.0", "author": "Pierre Rudloff", "bugs": "https://github.com/Rudloff/alltube/issues", "dependencies": { - "bower": "~1.7.1", + "bower": "~1.8.0", "grunt": "~1.0.1", - "grunt-cli": "~1.2.0", "grunt-contrib-cssmin": "~1.0.0", "grunt-contrib-uglify": "~2.0.0" }, @@ -39,6 +38,6 @@ "url": "https://github.com/Rudloff/alltube.git" }, "scripts": { - "postinstall": "node node_modules/bower/bin/bower install && node node_modules/grunt-cli/bin/grunt" + "postinstall": "node node_modules/.bin/bower install && node node_modules/.bin/grunt" } } diff --git a/phpdoc.xml b/phpdoc.xml new file mode 100644 index 0000000..27bf4a6 --- /dev/null +++ b/phpdoc.xml @@ -0,0 +1,4 @@ + + + Alltube Download library documentation + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/templates/password.tpl b/templates/password.tpl new file mode 100644 index 0000000..ab8e302 --- /dev/null +++ b/templates/password.tpl @@ -0,0 +1,13 @@ +{include file='inc/head.tpl'} +
+
+ {include file="inc/logo.tpl"} +

This video is protected

+

You need a password in order to download this video.

+
+ +

+ +
+
+{include file='inc/footer.tpl'} diff --git a/templates/video.tpl b/templates/video.tpl index e3790b1..6f11251 100644 --- a/templates/video.tpl +++ b/templates/video.tpl @@ -28,11 +28,7 @@