Skip to content

Commit

Permalink
Merge pull request phpbb#6715 from marc1706/ticket/17385
Browse files Browse the repository at this point in the history
[ticket/17385] Backport file_downloader with guzzle for versioncheck with redirect support
  • Loading branch information
marc1706 authored Sep 29, 2024
2 parents 6db142b + 9ace4dc commit 13b267c
Show file tree
Hide file tree
Showing 3 changed files with 320 additions and 60 deletions.
137 changes: 81 additions & 56 deletions phpBB/phpbb/file_downloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,99 +13,124 @@

namespace phpbb;

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use phpbb\exception\runtime_exception;

class file_downloader
{
const OK = 200;
const NOT_FOUND = 404;
const REQUEST_TIMEOUT = 408;

/** @var string Error string */
protected $error_string = '';

/** @var int Error number */
protected $error_number = 0;

/**
* Create new guzzle client
*
* @param string $host
* @param int $port
* @param int $timeout
*
* @return Client
*/
protected function create_client(string $host, int $port = 443, int $timeout = 6): Client
{
// Only set URL scheme if not specified in URL
$url_parts = parse_url($host);
if (!isset($url_parts['scheme']))
{
$host = (($port === 443) ? 'https://' : 'http://') . $host;
}

// Initialize Guzzle client
return new Client([
'base_uri' => $host,
'timeout' => $timeout,
]);
}

/**
* Retrieve contents from remotely stored file
*
* @param string $host File host
* @param string $directory Directory file is in
* @param string $filename Filename of file to retrieve
* @param int $port Port to connect to; default: 80
* @param int $timeout Connection timeout in seconds; default: 6
* @param string $host File host
* @param string $directory Directory file is in
* @param string $filename Filename of file to retrieve
* @param int $port Port to connect to; default: 443
* @param int $timeout Connection timeout in seconds; default: 6
*
* @return mixed File data as string if file can be read and there is no
* timeout, false if there were errors or the connection timed out
* @return false|string File data as string if file can be read and there is no
* timeout, false if there were errors or the connection timed out
*
* @throws \phpbb\exception\runtime_exception If data can't be retrieved and no error
* message is returned
* @throws runtime_exception If data can't be retrieved and no error
* message is returned
*/
public function get($host, $directory, $filename, $port = 80, $timeout = 6)
public function get(string $host, string $directory, string $filename, int $port = 443, int $timeout = 6)
{
// Initialize Guzzle client
$client = $this->create_client($host, $port, $timeout);

// Set default values for error variables
$this->error_number = 0;
$this->error_string = '';

if (function_exists('fsockopen') &&
$socket = @fsockopen(($port == 443 ? 'ssl://' : '') . $host, $port, $this->error_number, $this->error_string, $timeout)
)
try
{
@fputs($socket, "GET $directory/$filename HTTP/1.0\r\n");
@fputs($socket, "HOST: $host\r\n");
@fputs($socket, "Connection: close\r\n\r\n");

$timer_stop = time() + $timeout;
stream_set_timeout($socket, $timeout);
$response = $client->request('GET', "$directory/$filename");

$file_info = '';
$get_info = false;

while (!@feof($socket))
// Check if the response status code is 200 (OK)
if ($response->getStatusCode() == self::OK)
{
if ($get_info)
{
$file_info .= @fread($socket, 1024);
}
else
{
$line = @fgets($socket, 1024);
if ($line == "\r\n")
{
$get_info = true;
}
else if (stripos($line, '404 not found') !== false)
{
throw new \phpbb\exception\runtime_exception('FILE_NOT_FOUND', array($filename));
}
}

$stream_meta_data = stream_get_meta_data($socket);

if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop)
{
throw new \phpbb\exception\runtime_exception('FSOCK_TIMEOUT');
}
return $response->getBody()->getContents();
}
else
{
$this->error_number = $response->getStatusCode();
throw new runtime_exception('FILE_NOT_FOUND', [$filename]);
}
@fclose($socket);
}
else
catch (RequestException $exception)
{
if ($this->error_string)
if ($exception->hasResponse())
{
$this->error_string = utf8_convert_message($this->error_string);
return false;
$this->error_number = $exception->getResponse()->getStatusCode();

if ($this->error_number == self::NOT_FOUND)
{
throw new runtime_exception('FILE_NOT_FOUND', [$filename]);
}
}
else
{
throw new \phpbb\exception\runtime_exception('FSOCK_DISABLED');
$this->error_number = self::REQUEST_TIMEOUT;
throw new runtime_exception('FSOCK_TIMEOUT');
}
}

return $file_info;
$this->error_string = utf8_convert_message($exception->getMessage());
return false;
}
catch (runtime_exception $exception)
{
// Rethrow runtime_exceptions, only handle unknown cases below
throw $exception;
}
catch (\Throwable $exception)
{
$this->error_string = utf8_convert_message($exception->getMessage());
throw new runtime_exception('FSOCK_DISABLED');
}
}

/**
* Get error string
*
* @return string Error string
*/
public function get_error_string()
public function get_error_string(): string
{
return $this->error_string;
}
Expand All @@ -115,7 +140,7 @@ public function get_error_string()
*
* @return int Error number
*/
public function get_error_number()
public function get_error_number(): int
{
return $this->error_number;
}
Expand Down
4 changes: 4 additions & 0 deletions tests/version/fixture/30x.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
3.0.14
https://www.phpbb.com/community/viewtopic.php?f=14&t=2313941
3.3.12
https://www.phpbb.com/community/viewtopic.php?t=2653732
Loading

0 comments on commit 13b267c

Please sign in to comment.