Line 32 | Line 32 |
---|
* @var string File name */ protected $file = 'versions.json';
|
* @var string File name */ protected $file = 'versions.json';
|
| /** * @var bool Use SSL or not */ protected $use_ssl = false;
|
/** * @var string Current version installed
| /** * @var string Current version installed
|
Line 49 | Line 54 |
---|
/** @var \phpbb\config\config */ protected $config;
|
/** @var \phpbb\config\config */ protected $config;
|
| /** @var \phpbb\file_downloader */ protected $file_downloader;
|
/** @var \phpbb\user */ protected $user;
|
/** @var \phpbb\user */ protected $user;
|
| protected $version_schema = array( 'stable' => array( 'current' => 'version', 'download' => 'url', 'announcement' => 'url', 'eol' => 'url', 'security' => 'bool', ), 'unstable' => array( 'current' => 'version', 'download' => 'url', 'announcement' => 'url', 'eol' => 'url', 'security' => 'bool', ), );
|
/** * Constructor * * @param \phpbb\cache\service $cache * @param \phpbb\config\config $config
|
/** * Constructor * * @param \phpbb\cache\service $cache * @param \phpbb\config\config $config
|
| * @param \phpbb\file_downloader $file_downloader
|
* @param \phpbb\user $user */
|
* @param \phpbb\user $user */
|
public function __construct(\phpbb\cache\service $cache, \phpbb\config\config $config, \phpbb\user $user)
| public function __construct(\phpbb\cache\service $cache, \phpbb\config\config $config, \phpbb\file_downloader $file_downloader, \phpbb\user $user)
|
{ $this->cache = $cache; $this->config = $config;
|
{ $this->cache = $cache; $this->config = $config;
|
| $this->file_downloader = $file_downloader;
|
$this->user = $user;
if (defined('PHPBB_QA'))
| $this->user = $user;
if (defined('PHPBB_QA'))
|
Line 80 | Line 107 |
---|
* @param string $host Host (e.g. version.phpbb.com) * @param string $path Path to file (e.g. /phpbb) * @param string $file File name (Default: versions.json)
|
* @param string $host Host (e.g. version.phpbb.com) * @param string $path Path to file (e.g. /phpbb) * @param string $file File name (Default: versions.json)
|
| * @param bool $use_ssl Use SSL or not (Default: false)
|
* @return version_helper */
|
* @return version_helper */
|
public function set_file_location($host, $path, $file = 'versions.json')
| public function set_file_location($host, $path, $file = 'versions.json', $use_ssl = false)
|
{ $this->host = $host; $this->path = $path; $this->file = $file;
|
{ $this->host = $host; $this->path = $path; $this->file = $file;
|
| $this->use_ssl = $use_ssl;
|
return $this; }
| return $this; }
|
Line 172 | Line 201 |
---|
$self = $this; $current_version = $this->current_version;
|
$self = $this; $current_version = $this->current_version;
|
// Filter out any versions less than to the current version
| // Filter out any versions less than the current version
|
$versions = array_filter($versions, function($data) use ($self, $current_version) { return $self->compare($data['current'], $current_version, '>='); });
| $versions = array_filter($versions, function($data) use ($self, $current_version) { return $self->compare($data['current'], $current_version, '>='); });
|
Line 186 | Line 215 |
---|
return $value; });
|
return $value; });
|
| }
/** * Gets the latest update for the current branch the user is on * Will suggest versions from newer branches when EoL has been reached * and/or version from newer branch is needed for having all known security * issues fixed. * * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update. * @return array Version info or empty array if there are no updates * @throws \RuntimeException */ public function get_update_on_branch($force_update = false, $force_cache = false) { $versions = $this->get_versions_matching_stability($force_update, $force_cache);
$self = $this; $current_version = $this->current_version;
// Filter out any versions less than the current version $versions = array_filter($versions, function($data) use ($self, $current_version) { return $self->compare($data['current'], $current_version, '>='); });
// Get the lowest version from the previous list. $update_info = array_reduce($versions, function($value, $data) use ($self, $current_version) { if ($value === null && $self->compare($data['current'], $current_version, '>=')) { if (!$data['eol'] && (!$data['security'] || $self->compare($data['security'], $data['current'], '<='))) { return ($self->compare($data['current'], $current_version, '>')) ? $data : array(); } else { return null; } }
return $value; });
return $update_info === null ? array() : $update_info; }
/** * Gets the latest extension update for the current phpBB branch the user is on * Will suggest versions from newer branches when EoL has been reached * and/or version from newer branch is needed for having all known security * issues fixed. * * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update. * @return array Version info or empty array if there are no updates * @throws \RuntimeException */ public function get_ext_update_on_branch($force_update = false, $force_cache = false) { $versions = $this->get_versions_matching_stability($force_update, $force_cache);
$self = $this; $current_version = $this->current_version;
// Get current phpBB branch from version, e.g.: 3.2 preg_match('/^(\d+\.\d+).*$/', $this->config['version'], $matches); $current_branch = $matches[1];
// Filter out any versions less than the current version $versions = array_filter($versions, function($data) use ($self, $current_version) { return $self->compare($data['current'], $current_version, '>='); });
// Filter out any phpbb branches less than the current version $branches = array_filter(array_keys($versions), function($branch) use ($self, $current_branch) { return $self->compare($branch, $current_branch, '>='); }); if (!empty($branches)) { $versions = array_intersect_key($versions, array_flip($branches)); } else { // If branches are empty, it means the current phpBB branch is newer than any branch the // extension was validated against. Reverse sort the versions array so we get the newest // validated release available. krsort($versions); }
// Get the first available version from the previous list. $update_info = array_reduce($versions, function($value, $data) use ($self, $current_version) { if ($value === null && $self->compare($data['current'], $current_version, '>=')) { if (!$data['eol'] && (!$data['security'] || $self->compare($data['security'], $data['current'], '<='))) { return $self->compare($data['current'], $current_version, '>') ? $data : array(); } else { return null; } }
return $value; });
return $update_info === null ? array() : $update_info;
|
}
/**
| }
/**
|
Line 193 | Line 328 |
---|
* * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update.
|
* * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update.
|
* @return string
| * @return array
|
* @throws \RuntimeException */ public function get_suggested_updates($force_update = false, $force_cache = false)
| * @throws \RuntimeException */ public function get_suggested_updates($force_update = false, $force_cache = false)
|
Line 214 | Line 349 |
---|
* * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update.
|
* * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update.
|
* @return string Version info
| * @return array Version info
|
* @throws \RuntimeException */ public function get_versions_matching_stability($force_update = false, $force_cache = false)
| * @throws \RuntimeException */ public function get_versions_matching_stability($force_update = false, $force_cache = false)
|
Line 234 | Line 369 |
---|
* * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update.
|
* * @param bool $force_update Ignores cached data. Defaults to false. * @param bool $force_cache Force the use of the cache. Override $force_update.
|
* @return string Version info, includes stable and unstable data
| * @return array Version info, includes stable and unstable data
|
* @throws \RuntimeException */ public function get_versions($force_update = false, $force_cache = false) {
|
* @throws \RuntimeException */ public function get_versions($force_update = false, $force_cache = false) {
|
$cache_file = '_versioncheck_' . $this->host . $this->path . $this->file;
| $cache_file = '_versioncheck_' . $this->host . $this->path . $this->file . $this->use_ssl;
|
$info = $this->cache->get($cache_file);
| $info = $this->cache->get($cache_file);
|
Line 249 | Line 384 |
---|
} else if ($info === false || $force_update) {
|
} else if ($info === false || $force_update) {
|
$errstr = $errno = ''; $info = get_remote_file($this->host, $this->path, $this->file, $errstr, $errno);
| try { $info = $this->file_downloader->get($this->host, $this->path, $this->file, $this->use_ssl ? 443 : 80); } catch (\phpbb\exception\runtime_exception $exception) { $prepare_parameters = array_merge(array($exception->getMessage()), $exception->get_parameters()); throw new \RuntimeException(call_user_func_array(array($this->user, 'lang'), $prepare_parameters)); } $error_string = $this->file_downloader->get_error_string();
|
|
|
if (!empty($errstr))
| if (!empty($error_string))
|
{
|
{
|
throw new \RuntimeException($errstr);
| throw new \RuntimeException($error_string);
|
}
$info = json_decode($info, true);
|
}
$info = json_decode($info, true);
|
| // Sanitize any data we retrieve from a server if (!empty($info)) { $json_sanitizer = function (&$value, $key) { $type_cast_helper = new \phpbb\request\type_cast_helper(); $type_cast_helper->set_var($value, $value, gettype($value), true); }; array_walk_recursive($info, $json_sanitizer); }
|
if (empty($info['stable']) && empty($info['unstable'])) {
| if (empty($info['stable']) && empty($info['unstable'])) {
|
Line 266 | Line 418 |
---|
throw new \RuntimeException($this->user->lang('VERSIONCHECK_FAIL')); }
|
throw new \RuntimeException($this->user->lang('VERSIONCHECK_FAIL')); }
|
// Replace & with & on announcement links foreach ($info as $stability => $branches)
| $info['stable'] = (empty($info['stable'])) ? array() : $info['stable']; $info['unstable'] = (empty($info['unstable'])) ? $info['stable'] : $info['unstable'];
$info = $this->validate_versions($info);
$this->cache->put($cache_file, $info, 86400); // 24 hours }
return $info; }
/** * Validate versions info input * * @param array $versions_info Decoded json data array. Will be modified * and cleaned by this method * * @return array Versions info array */ public function validate_versions($versions_info)
|
{
|
{
|
foreach ($branches as $branch => $branch_data)
| $array_diff = array_diff_key($versions_info, array($this->version_schema));
// Remove excessive data if (count($array_diff) > 0)
|
{
|
{
|
$info[$stability][$branch]['announcement'] = str_replace('&', '&', $branch_data['announcement']);
| $old_versions_info = $versions_info; $versions_info = array( 'stable' => !empty($old_versions_info['stable']) ? $old_versions_info['stable'] : array(), 'unstable' => !empty($old_versions_info['unstable']) ? $old_versions_info['unstable'] : array(), ); unset($old_versions_info);
|
}
|
}
|
| foreach ($versions_info as $stability_type => &$versions_data) { foreach ($versions_data as $branch => &$version_data) { if (!preg_match('/^[0-9a-z\-\.]+$/i', $branch)) { unset($versions_data[$branch]); continue;
|
}
|
}
|
$info['stable'] = (empty($info['stable'])) ? array() : $info['stable']; $info['unstable'] = (empty($info['unstable'])) ? $info['stable'] : $info['unstable'];
| $stability_diff = array_diff_key($version_data, $this->version_schema[$stability_type]);
|
|
|
$this->cache->put($cache_file, $info, 86400); // 24 hours
| if (count($stability_diff) > 0) { $old_version_data = $version_data; $version_data = array(); foreach ($this->version_schema[$stability_type] as $key => $value) { if (isset($old_version_data[$key])) { $version_data[$key] = $old_version_data[$key]; } } unset($old_version_data);
|
}
|
}
|
return $info;
| foreach ($version_data as $key => &$value) { if (!isset($this->version_schema[$stability_type][$key])) { unset($version_data[$key]); throw new \RuntimeException($this->user->lang('VERSIONCHECK_INVALID_ENTRY')); }
switch ($this->version_schema[$stability_type][$key]) { case 'bool': $value = (bool) $value; break;
case 'url': if (!empty($value) && !preg_match('#^' . get_preg_expression('url') . '$#iu', $value) && !preg_match('#^' . get_preg_expression('www_url') . '$#iu', $value)) { throw new \RuntimeException($this->user->lang('VERSIONCHECK_INVALID_URL')); } break;
case 'version': if (!empty($value) && !preg_match(get_preg_expression('semantic_version'), $value)) { throw new \RuntimeException($this->user->lang('VERSIONCHECK_INVALID_VERSION')); } break;
default: // Shouldn't be possible to trigger this throw new \RuntimeException($this->user->lang('VERSIONCHECK_INVALID_ENTRY')); } } } }
return $versions_info;
|
} }
| } }
|