From 47789f8f8db9b6b29222cb2b7f0fdd5f3f7eb878 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Tue, 5 Dec 2017 16:06:57 +0100 Subject: [PATCH] Check that PlaylistArchiveStream::stream_read returns a string --- classes/VideoDownload.php | 44 ++++- composer.json | 6 +- composer.lock | 281 +++++++++++++++++++++++++++- tests/PlaylistArchiveStreamTest.php | 6 +- tests/bootstrap.php | 7 + 5 files changed, 330 insertions(+), 14 deletions(-) diff --git a/classes/VideoDownload.php b/classes/VideoDownload.php index eb8b071..7e847e1 100644 --- a/classes/VideoDownload.php +++ b/classes/VideoDownload.php @@ -297,7 +297,7 @@ class VideoDownload * @param string $format Format to use for the video * @param string $password Video password * - * @return resource|false popen stream + * @return resource popen stream */ public function getAudioStream($url, $format, $password = null) { @@ -311,12 +311,18 @@ class VideoDownload $chain = new Chain($process); $chain->add('|', $this->getAvconvMp3Process('-')); - return popen($chain->getProcess()->getCommandLine(), 'r'); + $stream = popen($chain->getProcess()->getCommandLine(), 'r'); } else { $avconvProc = $this->getAvconvMp3Process($video->url); - return popen($avconvProc->getCommandLine(), 'r'); + $stream = popen($avconvProc->getCommandLine(), 'r'); } + + if (!is_resource($stream)) { + throw new \Exception('Could not open popen stream.'); + } + + return $stream; } /** @@ -324,7 +330,7 @@ class VideoDownload * * @param \stdClass $video Video object returned by getJSON * - * @return resource|false popen stream + * @return resource popen stream */ public function getM3uStream(\stdClass $video) { @@ -345,7 +351,12 @@ class VideoDownload ] ); - return popen($procBuilder->getProcess()->getCommandLine(), 'r'); + $stream = popen($procBuilder->getProcess()->getCommandLine(), 'r'); + if (!is_resource($stream)) { + throw new \Exception('Could not open popen stream.'); + } + + return $stream; } /** @@ -353,7 +364,7 @@ class VideoDownload * * @param array $urls URLs of the video ($urls[0]) and audio ($urls[1]) files * - * @return resource|false popen stream + * @return resource popen stream */ public function getRemuxStream(array $urls) { @@ -371,7 +382,12 @@ class VideoDownload ] ); - return popen($procBuilder->getProcess()->getCommandLine(), 'r'); + $stream = popen($procBuilder->getProcess()->getCommandLine(), 'r'); + if (!is_resource($stream)) { + throw new \Exception('Could not open popen stream.'); + } + + return $stream; } /** @@ -379,11 +395,16 @@ class VideoDownload * * @param \stdClass $video Video object returned by getJSON * - * @return resource|false popen stream + * @return resource popen stream */ public function getRtmpStream(\stdClass $video) { - return popen($this->getRtmpProcess($video)->getCommandLine(), 'r'); + $stream = popen($this->getRtmpProcess($video)->getCommandLine(), 'r'); + if (!is_resource($stream)) { + throw new \Exception('Could not open popen stream.'); + } + + return $stream; } /** @@ -392,7 +413,7 @@ class VideoDownload * @param object $video Video object returned by youtube-dl * @param string $format Requested format * - * @return resource|false + * @return resource */ public function getPlaylistArchiveStream(\stdClass $video, $format) { @@ -401,6 +422,9 @@ class VideoDownload $playlistItems[] = urlencode($entry->url); } $stream = fopen('playlist://'.implode(';', $playlistItems).'/'.$format, 'r'); + if (!is_resource($stream)) { + throw new \Exception('Could not fopen popen stream.'); + } return $stream; } diff --git a/composer.json b/composer.json index d47e8ba..1ab082c 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,8 @@ "ffmpeg/ffmpeg": "dev-release", "rg3/youtube-dl": "2017.11.06", "rudloff/rtmpdump-bin": "~2.3.0", - "heroku/heroku-buildpack-php": "*" + "heroku/heroku-buildpack-php": "*", + "php-mock/php-mock-mockery": "~1.1.0" }, "extra": { "paas": { @@ -78,7 +79,8 @@ "autoload": { "psr-4": { "Alltube\\": "classes/", - "Alltube\\Controller\\": "controllers/" + "Alltube\\Controller\\": "controllers/", + "Alltube\\Test\\": "tests/" } }, "scripts": { diff --git a/composer.lock b/composer.lock index 41f9d19..f9fe3ba 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "571ff0ac0262ea0ad5b992fa2d0705cd", + "content-hash": "195cbc39a8ad0fbd9ed135f6c81944a9", "packages": [ { "name": "aura/session", @@ -1065,6 +1065,51 @@ ], "type": "library" }, + { + "name": "hamcrest/hamcrest-php", + "version": "v1.2.2", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c", + "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "1.3.3", + "satooshi/php-coveralls": "dev-master" + }, + "type": "library", + "autoload": { + "classmap": [ + "hamcrest" + ], + "files": [ + "hamcrest/Hamcrest.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "time": "2015-05-11T14:41:42+00:00" + }, { "name": "heroku/heroku-buildpack-php", "version": "v127", @@ -1109,6 +1154,71 @@ ], "time": "2017-11-30T16:10:52+00:00" }, + { + "name": "mockery/mockery", + "version": "0.9.9", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "6fdb61243844dc924071d3404bb23994ea0b6856" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/6fdb61243844dc924071d3404bb23994ea0b6856", + "reference": "6fdb61243844dc924071d3404bb23994ea0b6856", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "~1.1", + "lib-pcre": ">=7.0", + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.9.x-dev" + } + }, + "autoload": { + "psr-0": { + "Mockery": "library/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "http://davedevelopment.co.uk" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", + "homepage": "http://github.com/padraic/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "time": "2017-02-28T12:52:32+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.7.0", @@ -1256,6 +1366,175 @@ "description": "Library for handling version information and constraints", "time": "2017-03-05T17:38:23+00:00" }, + { + "name": "php-mock/php-mock", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-mock/php-mock.git", + "reference": "bfa2d17d64dbf129073a7ba2051a96ce52749570" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-mock/php-mock/zipball/bfa2d17d64dbf129073a7ba2051a96ce52749570", + "reference": "bfa2d17d64dbf129073a7ba2051a96ce52749570", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpunit/php-text-template": "^1" + }, + "replace": { + "malkusch/php-mock": "*" + }, + "require-dev": { + "phpunit/phpunit": "^4|^5" + }, + "suggest": { + "php-mock/php-mock-mockery": "Allows using PHPMockery for Mockery integration", + "php-mock/php-mock-phpunit": "Allows integration into PHPUnit testcase with the trait PHPMock." + }, + "type": "library", + "autoload": { + "psr-4": { + "phpmock\\": [ + "classes/", + "tests/unit/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "WTFPL" + ], + "authors": [ + { + "name": "Markus Malkusch", + "email": "markus@malkusch.de", + "homepage": "http://markus.malkusch.de", + "role": "Developer" + } + ], + "description": "PHP-Mock can mock built-in PHP functions (e.g. time()). PHP-Mock relies on PHP's namespace fallback policy. No further extension is needed.", + "homepage": "https://github.com/php-mock/php-mock", + "keywords": [ + "BDD", + "TDD", + "function", + "mock", + "stub", + "test", + "test double" + ], + "time": "2015-11-11T22:37:09+00:00" + }, + { + "name": "php-mock/php-mock-integration", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-mock/php-mock-integration.git", + "reference": "e83fb65dd20cd3cf250d554cbd4682b96b684f4b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-mock/php-mock-integration/zipball/e83fb65dd20cd3cf250d554cbd4682b96b684f4b", + "reference": "e83fb65dd20cd3cf250d554cbd4682b96b684f4b", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "php-mock/php-mock": "^1", + "phpunit/php-text-template": "^1" + }, + "require-dev": { + "phpunit/phpunit": "^4|^5" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpmock\\integration\\": "classes/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "WTFPL" + ], + "authors": [ + { + "name": "Markus Malkusch", + "email": "markus@malkusch.de", + "homepage": "http://markus.malkusch.de", + "role": "Developer" + } + ], + "description": "Integration package for PHP-Mock", + "homepage": "https://github.com/php-mock/php-mock-integration", + "keywords": [ + "BDD", + "TDD", + "function", + "mock", + "stub", + "test", + "test double" + ], + "time": "2015-10-26T21:21:42+00:00" + }, + { + "name": "php-mock/php-mock-mockery", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-mock/php-mock-mockery.git", + "reference": "bc1fe0608cd47c939aba5eac1cb50de1cda9cbc3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-mock/php-mock-mockery/zipball/bc1fe0608cd47c939aba5eac1cb50de1cda9cbc3", + "reference": "bc1fe0608cd47c939aba5eac1cb50de1cda9cbc3", + "shasum": "" + }, + "require": { + "mockery/mockery": "^0.9", + "php": ">=5.5", + "php-mock/php-mock-integration": "^1" + }, + "require-dev": { + "phpunit/phpunit": "^4|^5" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpmock\\mockery\\": "classes/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "WTFPL" + ], + "authors": [ + { + "name": "Markus Malkusch", + "email": "markus@malkusch.de", + "homepage": "http://markus.malkusch.de", + "role": "Developer" + } + ], + "description": "Mock built-in PHP functions (e.g. time()) with Mockery. This package relies on PHP's namespace fallback policy. No further extension is needed.", + "homepage": "https://github.com/php-mock/php-mock-mockery", + "keywords": [ + "BDD", + "TDD", + "function", + "mock", + "mockery", + "stub", + "test", + "test double" + ], + "time": "2015-11-11T22:48:58+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "1.0.1", diff --git a/tests/PlaylistArchiveStreamTest.php b/tests/PlaylistArchiveStreamTest.php index 35ac628..fde76c6 100644 --- a/tests/PlaylistArchiveStreamTest.php +++ b/tests/PlaylistArchiveStreamTest.php @@ -95,7 +95,11 @@ class PlaylistArchiveStreamTest extends TestCase { $this->stream->stream_open('playlist://BaW_jenozKc;BaW_jenozKc/worst'); while (!$this->stream->stream_eof()) { - $this->assertLessThanOrEqual(8192, strlen($this->stream->stream_read(8192))); + $result = $this->stream->stream_read(8192); + $this->assertInternalType('string', $result); + if (is_string($result)) { + $this->assertLessThanOrEqual(8192, strlen($result)); + } } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 44bb21f..320d6d1 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -3,6 +3,7 @@ * File used to bootstrap tests. */ use Alltube\PlaylistArchiveStream; +use phpmock\mockery\PHPMockery; /** * Composer autoload. @@ -14,3 +15,9 @@ session_cache_limiter(''); session_start(); stream_wrapper_register('playlist', PlaylistArchiveStream::class); + +/** + * @see https://bugs.php.net/bug.php?id=68541 + */ +PHPMockery::define('Alltube', 'popen'); +PHPMockery::define('Alltube', 'fopen');