Server : LiteSpeed System : Linux server 3.10.0-1160.90.1.el7.x86_64 #1 SMP Thu May 4 15:21:22 UTC 2023 x86_64 User : alsaif ( 1057) PHP Version : 7.4.33 Disable Function : show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/alsaif/public_html/administrator/components/com_falang/liveupdate/classes/ |
<?php
/**
* @package LiveUpdate
* @copyright Copyright (c)2010-2016 Nicholas K. Dionysopoulos / AkeebaBackup.com
* @license GNU GPLv3 or later <https://www.gnu.org/licenses/gpl.html>
*/
defined('_JEXEC') or die();
/**
* Fetches the update information from the server or the cache, depending on
* whether the cache is fresh or not.
*/
class LiveUpdateFetch extends JObject
{
/** @var int How many hours to cache the update results? */
private $cacheTTL = 24;
/** @var LiveUpdateStorage The live update cache storage handler */
private $storage = null;
/**
* One-stop-shop function which fetches update information and tells you
* if there are updates available or not, or if updates are not supported.
*
* Return values:
* 0 = no updates
* 1 = updates available
* -1 = updates not supported
* -2 = fetching updates crashes the server
*
* @param boolean Should I forcibly reload the updates?
*
* @return integer See description
*/
public function hasUpdates($force = false)
{
$updateInfo = $this->getUpdateInformation($force);
if ($updateInfo->stuck)
{
return -2;
}
if (!$updateInfo->supported)
{
return -1;
}
$config = LiveUpdateConfig::getInstance();
$extInfo = $config->getExtensionInformation();
// Filter by stability level
$minStability = $config->getMinimumStability();
$stability = strtolower($updateInfo->stability);
switch ($minStability)
{
case 'alpha':
default:
// Reports any stability level as an available update
break;
case 'beta':
// Do not report alphas as available updates
if (in_array($stability, array('alpha')))
{
return 0;
}
break;
case 'rc':
// Do not report alphas and betas as available updates
if (in_array($stability, array('alpha', 'beta')))
{
return 0;
}
break;
case 'stable':
// Do not report alphas, betas and rcs as available updates
if (in_array($stability, array('alpha', 'beta', 'rc')))
{
return 0;
}
break;
}
if (empty($updateInfo->version) && empty($updateInfo->date))
{
return 0;
}
// Use the version strategy to determine the availability of an update
switch ($config->getVersionStrategy())
{
case 'newest':
JLoader::import('joomla.utilities.date');
if (empty($extInfo))
{
$mine = new JDate('2000-01-01 00:00:00');
}
else
{
try
{
$mine = new JDate($extInfo['date']);
}
catch (Exception $e)
{
$mine = new JDate('2000-01-01 00:00:00');
}
}
$theirs = new JDate($updateInfo->date);
return ($theirs->toUnix() > $mine->toUnix()) ? 1 : 0;
break;
case 'vcompare':
$mine = $extInfo['version'];
if (empty($mine))
{
$mine = '0.0.0';
}
$theirs = $updateInfo->version;
if (empty($theirs))
{
$theirs = '0.0.0';
}
return (version_compare($theirs, $mine, 'gt')) ? 1 : 0;
break;
case 'different':
$mine = $extInfo['version'];
if (empty($mine))
{
$mine = '0.0.0';
}
$theirs = $updateInfo->version;
if (empty($theirs))
{
$theirs = '0.0.0';
}
return ($theirs != $mine) ? 1 : 0;
break;
}
}
/**
* Get the latest version (update) information, either from the cache or
* from the update server.
*
* @param boolean $force Set to true to force fetching fresh data from the server
*
* @return stdClass The update information, in object format
*/
public function getUpdateInformation($force = false)
{
// Get the Live Update configuration
$config = LiveUpdateConfig::getInstance();
// Get an instance of the storage class
$storageOptions = $config->getStorageAdapterPreferences();
require_once dirname(__FILE__) . '/storage/storage.php';
$this->storage = LiveUpdateStorage::getInstance($storageOptions['adapter'], $storageOptions['config']);
// If we are requested to forcibly reload the information, clear old data first
if ($force)
{
$this->storage->set('lastcheck', null);
$this->storage->set('updatedata', null);
$this->storage->save();
}
// Fetch information from the cache
$lastCheck = $this->storage->get('lastcheck', 0);
$cachedData = $this->storage->get('updatedata', null);
if (!is_object($cachedData))
{
$cachedData = null;
}
if (empty($cachedData))
{
$lastCheck = 0;
}
// Check if the cache is at most $cacheTTL hours old
$now = time();
$maxDifference = $this->cacheTTL * 3600;
$difference = abs($now - $lastCheck);
if (!($force) && ($difference <= $maxDifference))
{
// The cache is fresh enough; return cached data
return $cachedData;
}
else
{
// The cache is stale; fetch new data, cache it and return it to the caller
$data = $this->getUpdateData($force);
$this->storage->set('lastcheck', $now);
$this->storage->set('updatedata', $data);
$this->storage->save();
return $data;
}
}
/**
* Retrieves the update data from the server, unless previous runs indicate
* that the download process gets stuck and ends up in a WSOD.
*
* @param bool $force Set to true to force fetching new data no matter if the process is marked as stuck
*
* @return stdClass
*/
private function getUpdateData($force = false)
{
$ret = array(
'supported' => false,
'stuck' => true,
'version' => '',
'date' => '',
'stability' => '',
'downloadURL' => '',
'infoURL' => '',
'releasenotes' => ''
);
// If the process is marked as "stuck", we won't bother fetching data again; well,
// unless you really force me to, by setting $force = true.
if (($this->storage->get('stuck', 0) != 0) && !$force)
{
return (object)$ret;
}
$ret['stuck'] = false;
require_once dirname(__FILE__) . '/download.php';
// First we mark Live Updates as getting stuck. This way, if fetching the update
// fails with a server error, reloading the page will not result to a White Screen
// of Death again. Hey, Joomla! core team, are you listening? Some hosts PRETEND to
// support cURL or URL fopen() wrappers but using them throws an immediate WSOD.
$this->storage->set('stuck', 1);
$this->storage->save();
$config = LiveUpdateConfig::getInstance();
$extInfo = $config->getExtensionInformation();
$url = $extInfo['updateurl'];
$rawData = LiveUpdateDownloadHelper::downloadAndReturn($url);
// Now that we have some data returned, let's unmark the process as being stuck ;)
$this->storage->set('stuck', 0);
$this->storage->save();
// If we didn't get anything, assume Live Update is not supported (communication error)
if (empty($rawData) || ($rawData == false))
{
return (object)$ret;
}
// TODO Detect the content type of the returned update stream. For now, I will pretend it's an INI file.
$data = $this->parseINI($rawData);
$ret['supported'] = true;
return (object)array_merge($ret, $data);
}
/**
* Fetches update information from the server using cURL
*
* @return string The raw server data
*/
private function fetchCURL()
{
$config = LiveUpdateConfig::getInstance();
$extInfo = $config->getExtensionInformation();
$url = $extInfo['updateurl'];
$process = curl_init($url);
$config = new LiveUpdateConfig();
$config->applyCACert($process);
curl_setopt($process, CURLOPT_HEADER, 0);
// Pretend we are Firefox, so that webservers play nice with us
curl_setopt($process, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.14) Gecko/20110105 Firefox/3.6.14');
curl_setopt($process, CURLOPT_ENCODING, 'gzip');
curl_setopt($process, CURLOPT_TIMEOUT, 10);
curl_setopt($process, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);
// The @ sign allows the next line to fail if open_basedir is set or if safe mode is enabled
@curl_setopt($process, CURLOPT_FOLLOWLOCATION, 1);
@curl_setopt($process, CURLOPT_MAXREDIRS, 20);
$inidata = curl_exec($process);
curl_close($process);
return $inidata;
}
/**
* Fetches update information from the server using file_get_contents, which internally
* uses URL fopen() wrappers.
*
* @return string The raw server data
*/
private function fetchFOPEN()
{
$config = LiveUpdateConfig::getInstance();
$extInfo = $config->getExtensionInformation();
$url = $extInfo['updateurl'];
return @file_get_contents($url);
}
/**
* Parses the raw INI data into an array of update information
*
* @param string $rawData The raw INI data
*
* @return array The parsed data
*/
private function parseINI($rawData)
{
$ret = array(
'version' => '',
'date' => '',
'stability' => '',
'downloadURL' => '',
'infoURL' => '',
'releasenotes' => ''
);
// Get the magic string
$magicPos = strpos($rawData, '; Live Update provision file');
if ($magicPos === false)
{
// That's not an INI file :(
return $ret;
}
if ($magicPos !== 0)
{
$rawData = substr($rawData, $magicPos);
}
require_once dirname(__FILE__) . '/inihelper.php';
$iniData = LiveUpdateINIHelper::parse_ini_file($rawData, false, true);
// Get the supported platforms
$supportedPlatform = false;
$versionParts = explode('.', JVERSION);
$currentPlatform = $versionParts[0] . '.' . $versionParts[1];
if (array_key_exists('platforms', $iniData))
{
$rawPlatforms = explode(',', $iniData['platforms']);
foreach ($rawPlatforms as $platform)
{
$platform = trim($platform);
if (substr($platform, 0, 7) != 'joomla/')
{
continue;
}
$platform = substr($platform, 7);
if ($currentPlatform == $platform)
{
$supportedPlatform = true;
}
}
}
else
{
// Lies, damn lies
$supportedPlatform = true;
}
if (!$supportedPlatform)
{
return $ret;
}
$ret['version'] = array_key_exists('version', $iniData) ? $iniData['version'] : '';
$ret['date'] = array_key_exists('date', $iniData) ? $iniData['date'] : '';
if (!array_key_exists('link', $iniData))
{
$iniData['link'] = '';
}
$ret['downloadURL'] = $iniData['link'];
if (array_key_exists('stability', $iniData))
{
$stability = $iniData['stability'];
}
else
{
// Stability not defined; guesswork mode enabled
$version = $ret['version'];
if (preg_match('#^[0-9\.]*a[0-9\.]*#', $version) == 1)
{
$stability = 'alpha';
}
elseif (preg_match('#^[0-9\.]*b[0-9\.]*#', $version) == 1)
{
$stability = 'beta';
}
elseif (preg_match('#^[0-9\.]*rc[0-9\.]*#', $version) == 1)
{
$stability = 'rc';
}
elseif (preg_match('#^[0-9\.]*$#', $version) == 1)
{
$stability = 'stable';
}
else
{
$stability = 'svn';
}
}
$ret['stability'] = $stability;
if (array_key_exists('releasenotes', $iniData))
{
$ret['releasenotes'] = $iniData['releasenotes'];
}
if (array_key_exists('infourl', $iniData))
{
$ret['infoURL'] = $iniData['infourl'];
}
return $ret;
}
}