Merge pull request #9130 from glaubinix/t/max-file-size
Downloader: add a max_file_size option to prevent too big files to be downloadedpull/9146/head
commit
9ea9d20b21
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Composer\Downloader;
|
||||||
|
|
||||||
|
class MaxFileSizeExceededException extends TransportException
|
||||||
|
{
|
||||||
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
namespace Composer\Util\Http;
|
namespace Composer\Util\Http;
|
||||||
|
|
||||||
use Composer\Config;
|
use Composer\Config;
|
||||||
|
use Composer\Downloader\MaxFileSizeExceededException;
|
||||||
use Composer\IO\IOInterface;
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Downloader\TransportException;
|
use Composer\Downloader\TransportException;
|
||||||
use Composer\CaBundle\CaBundle;
|
use Composer\CaBundle\CaBundle;
|
||||||
|
@ -365,6 +366,18 @@ class CurlDownloader
|
||||||
$previousProgress = $this->jobs[$i]['progress'];
|
$previousProgress = $this->jobs[$i]['progress'];
|
||||||
$this->jobs[$i]['progress'] = $progress;
|
$this->jobs[$i]['progress'] = $progress;
|
||||||
|
|
||||||
|
if (isset($this->jobs[$i]['options']['max_file_size'])) {
|
||||||
|
// Compare max_file_size with the content-length header this value will be -1 until the header is parsed
|
||||||
|
if ($this->jobs[$i]['options']['max_file_size'] < $progress['download_content_length']) {
|
||||||
|
throw new MaxFileSizeExceededException('Maximum allowed download size reached. Content-length header indicates ' . $progress['download_content_length'] . ' bytes. Allowed ' . $this->jobs[$i]['options']['max_file_size'] . ' bytes');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare max_file_size with the download size in bytes
|
||||||
|
if ($this->jobs[$i]['options']['max_file_size'] < $progress['size_download']) {
|
||||||
|
throw new MaxFileSizeExceededException('Maximum allowed download size reached. Downloaded ' . $progress['size_download'] . ' of allowed ' . $this->jobs[$i]['options']['max_file_size'] . ' bytes');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
//$this->onProgress($curlHandle, $this->jobs[$i]['callback'], $progress, $previousProgress);
|
//$this->onProgress($curlHandle, $this->jobs[$i]['callback'], $progress, $previousProgress);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
namespace Composer\Util;
|
namespace Composer\Util;
|
||||||
|
|
||||||
use Composer\Config;
|
use Composer\Config;
|
||||||
|
use Composer\Downloader\MaxFileSizeExceededException;
|
||||||
use Composer\IO\IOInterface;
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Downloader\TransportException;
|
use Composer\Downloader\TransportException;
|
||||||
use Composer\CaBundle\CaBundle;
|
use Composer\CaBundle\CaBundle;
|
||||||
|
@ -244,6 +245,11 @@ class RemoteFilesystem
|
||||||
$degradedPackagist = true;
|
$degradedPackagist = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$maxFileSize = null;
|
||||||
|
if (isset($options['max_file_size'])) {
|
||||||
|
$maxFileSize = $options['max_file_size'];
|
||||||
|
}
|
||||||
|
|
||||||
$ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
|
$ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
|
||||||
|
|
||||||
$actualContextOptions = stream_context_get_options($ctx);
|
$actualContextOptions = stream_context_get_options($ctx);
|
||||||
|
@ -273,7 +279,7 @@ class RemoteFilesystem
|
||||||
});
|
});
|
||||||
$http_response_header = array();
|
$http_response_header = array();
|
||||||
try {
|
try {
|
||||||
$result = $this->getRemoteContents($originUrl, $fileUrl, $ctx, $http_response_header);
|
$result = $this->getRemoteContents($originUrl, $fileUrl, $ctx, $http_response_header, $maxFileSize);
|
||||||
|
|
||||||
if (!empty($http_response_header[0])) {
|
if (!empty($http_response_header[0])) {
|
||||||
$statusCode = $this->findStatusCode($http_response_header);
|
$statusCode = $this->findStatusCode($http_response_header);
|
||||||
|
@ -535,20 +541,31 @@ class RemoteFilesystem
|
||||||
* @param string $originUrl The origin URL
|
* @param string $originUrl The origin URL
|
||||||
* @param string $fileUrl The file URL
|
* @param string $fileUrl The file URL
|
||||||
* @param resource $context The stream context
|
* @param resource $context The stream context
|
||||||
|
* @param int $maxFileSize The maximum allowed file size
|
||||||
*
|
*
|
||||||
* @return string|false The response contents or false on failure
|
* @return string|false The response contents or false on failure
|
||||||
*/
|
*/
|
||||||
protected function getRemoteContents($originUrl, $fileUrl, $context, array &$responseHeaders = null)
|
protected function getRemoteContents($originUrl, $fileUrl, $context, array &$responseHeaders = null, $maxFileSize = null)
|
||||||
{
|
{
|
||||||
$result = false;
|
$result = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$e = null;
|
$e = null;
|
||||||
|
if ($maxFileSize !== null) {
|
||||||
|
$result = file_get_contents($fileUrl, false, $context, 0, $maxFileSize);
|
||||||
|
} else {
|
||||||
|
// passing `null` to file_get_contents will convert `null` to `0` and return 0 bytes
|
||||||
$result = file_get_contents($fileUrl, false, $context);
|
$result = file_get_contents($fileUrl, false, $context);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($maxFileSize !== null && Platform::strlen($result) >= $maxFileSize) {
|
||||||
|
throw new MaxFileSizeExceededException('Maximum allowed download size reached. Downloaded ' . Platform::strlen($result) . ' of allowed ' . $maxFileSize . ' bytes');
|
||||||
|
}
|
||||||
|
|
||||||
$responseHeaders = isset($http_response_header) ? $http_response_header : array();
|
$responseHeaders = isset($http_response_header) ? $http_response_header : array();
|
||||||
|
|
||||||
if (null !== $e) {
|
if (null !== $e) {
|
||||||
|
|
Loading…
Reference in New Issue