/iCagenda/admin/liveupdate/classes/updatefetch.php
PHP | 357 lines | 222 code | 55 blank | 80 comment | 46 complexity | 7e552c91fe3b4a70ca1260b60ed874a7 MD5 | raw file
- <?php
- /**
- *------------------------------------------------------------------------------
- * iCagenda v3 by Jooml!C - Events Management Extension for Joomla! 2.5 / 3.x
- *------------------------------------------------------------------------------
- *
- * @package LiveUpdate 2.1.5 - 2.2.1
- * @copyright Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com
- * @license GNU LGPLv3 or later <http://www.gnu.org/copyleft/lesser.html>
- *
- * @version 3.1.7 2013-08-28
- * @since 1.2.6
- */
- 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
- {
- private $cacheTTL = 24;
- 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 int 0 = no updates, 1 = updates available, -1 = updates not supported, -2 = fetching updates crashes the server
- */
- 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 $force bool 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'] : '';
- $config = LiveUpdateConfig::getInstance();
- $auth = $config->getAuthorization();
- if(!array_key_exists('link', $iniData)) $iniData['link'] = '';
- $glue = strpos($iniData['link'],'?') === false ? '?' : '&';
- $ret['downloadURL'] = $iniData['link'] . (empty($auth) ? '' : $glue.$auth);
- 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;
- }
- }