Spade
Mini Shell
| Directory:~$ /home/lmsyaran/public_html/joomla4/ |
| [Home] [System Details] [Kill Me] |
PK���[�n�;;Adapter/CollectionAdapter.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Updater\Adapter;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Application\ApplicationHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Updater\UpdateAdapter;
use Joomla\CMS\Version;
/**
* Collection Update Adapter Class
*
* @since 1.7.0
*/
class CollectionAdapter extends UpdateAdapter
{
/**
* Root of the tree
*
* @var object
* @since 1.7.0
*/
protected $base;
/**
* Tree of objects
*
* @var array
* @since 1.7.0
*/
protected $parent = array(0);
/**
* Used to control if an item has a child or not
*
* @var boolean
* @since 1.7.0
*/
protected $pop_parent = 0;
/**
* A list of discovered update sites
*
* @var array
*/
protected $update_sites = array();
/**
* A list of discovered updates
*
* @var array
*/
protected $updates = array();
/**
* Gets the reference to the current direct parent
*
* @return object
*
* @since 1.7.0
*/
protected function _getStackLocation()
{
return implode('->', $this->stack);
}
/**
* Get the parent tag
*
* @return string parent
*
* @since 1.7.0
*/
protected function _getParent()
{
return end($this->parent);
}
/**
* Opening an XML element
*
* @param object $parser Parser object
* @param string $name Name of element that is opened
* @param array $attrs Array of attributes for the element
*
* @return void
*
* @since 1.7.0
*/
public function _startElement($parser, $name, $attrs = array())
{
$this->stack[] = $name;
$tag = $this->_getStackLocation();
// Reset the data
if (isset($this->$tag))
{
$this->$tag->_data = '';
}
switch ($name)
{
case 'CATEGORY':
if (isset($attrs['REF']))
{
$this->update_sites[] = array('type' =>
'collection', 'location' => $attrs['REF'],
'update_site_id' => $this->updateSiteId);
}
else
{
// This item will have children, so prepare to attach them
$this->pop_parent = 1;
}
break;
case 'EXTENSION':
$update = Table::getInstance('update');
$update->set('update_site_id', $this->updateSiteId);
foreach ($this->updatecols as $col)
{
// Reset the values if it doesn't exist
if (!array_key_exists($col, $attrs))
{
$attrs[$col] = '';
if ($col == 'CLIENT')
{
$attrs[$col] = 'site';
}
}
}
$client = ApplicationHelper::getClientInfo($attrs['CLIENT'],
1);
if (isset($client->id))
{
$attrs['CLIENT_ID'] = $client->id;
}
// Lower case all of the fields
foreach ($attrs as $key => $attr)
{
$values[strtolower($key)] = $attr;
}
// Only add the update if it is on the same platform and release as we
are
$ver = new Version;
// Lower case and remove the exclamation mark
$product =
strtolower(InputFilter::getInstance()->clean($ver::PRODUCT,
'cmd'));
/*
* Set defaults, the extension file should clarify in case but it may
be only available in one version
* This allows an update site to specify a targetplatform
* targetplatformversion can be a regexp, so 1.[56] would be valid for
an extension that supports 1.5 and 1.6
* Note: Whilst the version is a regexp here, the targetplatform is not
(new extension per platform)
* Additionally, the version is a regexp here and it may also be in an
extension file if the extension is
* compatible against multiple versions of the same platform (e.g. a
library)
*/
if (!isset($values['targetplatform']))
{
$values['targetplatform'] = $product;
}
// Set this to ourself as a default
if (!isset($values['targetplatformversion']))
{
$values['targetplatformversion'] = $ver::RELEASE;
}
// Set this to ourselves as a default
// validate that we can install the extension
if ($product == $values['targetplatform'] &&
preg_match('/^' . $values['targetplatformversion'] .
'/', JVERSION))
{
$update->bind($values);
$this->updates[] = $update;
}
break;
}
}
/**
* Closing an XML element
* Note: This is a protected function though has to be exposed externally
as a callback
*
* @param object $parser Parser object
* @param string $name Name of the element closing
*
* @return void
*
* @since 1.7.0
*/
protected function _endElement($parser, $name)
{
array_pop($this->stack);
switch ($name)
{
case 'CATEGORY':
if ($this->pop_parent)
{
$this->pop_parent = 0;
array_pop($this->parent);
}
break;
}
}
// Note: we don't care about char data in collection because there
should be none
/**
* Finds an update
*
* @param array $options Options to use: update_site_id: the unique ID
of the update site to look at
*
* @return array Update_sites and updates discovered
*
* @since 1.7.0
*/
public function findUpdate($options)
{
$response = $this->getUpdateSiteResponse($options);
if ($response === false)
{
return false;
}
$this->xmlParser = xml_parser_create('');
xml_set_object($this->xmlParser, $this);
xml_set_element_handler($this->xmlParser, '_startElement',
'_endElement');
if (!xml_parse($this->xmlParser, $response->body))
{
// If the URL is missing the .xml extension, try appending it and retry
loading the update
if (!$this->appendExtension && (substr($this->_url, -4) !=
'.xml'))
{
$options['append_extension'] = true;
return $this->findUpdate($options);
}
Log::add('Error parsing url: ' . $this->_url, Log::WARNING,
'updater');
$app = Factory::getApplication();
$app->enqueueMessage(\JText::sprintf('JLIB_UPDATER_ERROR_COLLECTION_PARSE_URL',
$this->_url), 'warning');
return false;
}
// TODO: Decrement the bad counter if non-zero
return array('update_sites' => $this->update_sites,
'updates' => $this->updates);
}
}
PK���[l]��+�+Adapter/ExtensionAdapter.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Updater\Adapter;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Application\ApplicationHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Updater\UpdateAdapter;
use Joomla\CMS\Updater\Updater;
use Joomla\CMS\Version;
/**
* Extension class for updater
*
* @since 1.7.0
*/
class ExtensionAdapter extends UpdateAdapter
{
/**
* Start element parser callback.
*
* @param object $parser The parser object.
* @param string $name The name of the element.
* @param array $attrs The attributes of the element.
*
* @return void
*
* @since 1.7.0
*/
protected function _startElement($parser, $name, $attrs = array())
{
$this->stack[] = $name;
$tag = $this->_getStackLocation();
// Reset the data
if (isset($this->$tag))
{
$this->$tag->_data = '';
}
switch ($name)
{
case 'UPDATE':
$this->currentUpdate = Table::getInstance('update');
$this->currentUpdate->update_site_id = $this->updateSiteId;
$this->currentUpdate->detailsurl = $this->_url;
$this->currentUpdate->folder = '';
$this->currentUpdate->client_id = 1;
break;
// Don't do anything
case 'UPDATES':
break;
default:
if (in_array($name, $this->updatecols))
{
$name = strtolower($name);
$this->currentUpdate->$name = '';
}
if ($name == 'TARGETPLATFORM')
{
$this->currentUpdate->targetplatform = $attrs;
}
if ($name == 'PHP_MINIMUM')
{
$this->currentUpdate->php_minimum = '';
}
if ($name == 'SUPPORTED_DATABASES')
{
$this->currentUpdate->supported_databases = $attrs;
}
break;
}
}
/**
* Character Parser Function
*
* @param object $parser Parser object.
* @param object $name The name of the element.
*
* @return void
*
* @since 1.7.0
*/
protected function _endElement($parser, $name)
{
array_pop($this->stack);
// @todo remove code: echo 'Closing: '. $name .'<br
/>';
switch ($name)
{
case 'UPDATE':
// Lower case and remove the exclamation mark
$product =
strtolower(InputFilter::getInstance()->clean(Version::PRODUCT,
'cmd'));
// Support for the min_dev_level and max_dev_level attributes is
deprecated, a regexp should be used instead
if (isset($this->currentUpdate->targetplatform->min_dev_level)
|| isset($this->currentUpdate->targetplatform->max_dev_level))
{
Log::add(
'Support for the min_dev_level and max_dev_level attributes of
an update\'s <targetplatform> tag is deprecated and'
. ' will be removed in 4.0. The full version should be specified
in the version attribute and may optionally be a regexp.',
Log::WARNING,
'deprecated'
);
}
/*
* Check that the product matches and that the version matches
(optionally a regexp)
*
* Check for optional min_dev_level and max_dev_level attributes to
further specify targetplatform (e.g., 3.0.1)
*/
$patchMinimumSupported =
!isset($this->currentUpdate->targetplatform->min_dev_level)
|| Version::PATCH_VERSION >=
$this->currentUpdate->targetplatform->min_dev_level;
$patchMaximumSupported =
!isset($this->currentUpdate->targetplatform->max_dev_level)
|| Version::PATCH_VERSION <=
$this->currentUpdate->targetplatform->max_dev_level;
if ($product ==
$this->currentUpdate->targetplatform['NAME']
&& preg_match('/^' .
$this->currentUpdate->targetplatform['VERSION'] .
'/', JVERSION)
&& $patchMinimumSupported
&& $patchMaximumSupported)
{
// Check if PHP version supported via <php_minimum> tag, assume
true if tag isn't present
if (!isset($this->currentUpdate->php_minimum) ||
version_compare(PHP_VERSION, $this->currentUpdate->php_minimum,
'>='))
{
$phpMatch = true;
}
else
{
// Notify the user of the potential update
$msg = \JText::sprintf(
'JLIB_INSTALLER_AVAILABLE_UPDATE_PHP_VERSION',
$this->currentUpdate->name,
$this->currentUpdate->version,
$this->currentUpdate->php_minimum,
PHP_VERSION
);
Factory::getApplication()->enqueueMessage($msg,
'warning');
$phpMatch = false;
}
$dbMatch = false;
// Check if DB & version is supported via
<supported_databases> tag, assume supported if tag isn't present
if (isset($this->currentUpdate->supported_databases))
{
$db = Factory::getDbo();
$dbType = strtoupper($db->getServerType());
$dbVersion = $db->getVersion();
$supportedDbs = $this->currentUpdate->supported_databases;
// MySQL and MariaDB use the same database driver but not the same
version numbers
if ($dbType === 'mysql')
{
// Check whether we have a MariaDB version string and extract the
proper version from it
if (stripos($dbVersion, 'mariadb') !== false)
{
// MariaDB: Strip off any leading '5.5.5-', if present
$dbVersion = preg_replace('/^5\.5\.5-/', '',
$dbVersion);
$dbType = 'mariadb';
}
}
// Do we have an entry for the database?
if (array_key_exists($dbType, $supportedDbs))
{
$minumumVersion = $supportedDbs[$dbType];
$dbMatch = version_compare($dbVersion, $minumumVersion,
'>=');
if (!$dbMatch)
{
// Notify the user of the potential update
$dbMsg = \JText::sprintf(
'JLIB_INSTALLER_AVAILABLE_UPDATE_DB_MINIMUM',
$this->currentUpdate->name,
$this->currentUpdate->version,
\JText::_($db->name),
$dbVersion,
$minumumVersion
);
Factory::getApplication()->enqueueMessage($dbMsg,
'warning');
}
}
else
{
// Notify the user of the potential update
$dbMsg = \JText::sprintf(
'JLIB_INSTALLER_AVAILABLE_UPDATE_DB_TYPE',
$this->currentUpdate->name,
$this->currentUpdate->version,
\JText::_($db->name)
);
Factory::getApplication()->enqueueMessage($dbMsg,
'warning');
}
}
else
{
// Set to true if the <supported_databases> tag is not set
$dbMatch = true;
}
// Check minimum stability
$stabilityMatch = true;
if (isset($this->currentUpdate->stability) &&
($this->currentUpdate->stability < $this->minimum_stability))
{
$stabilityMatch = false;
}
// Some properties aren't valid fields in the update table so
unset them to prevent J! from trying to store them
unset($this->currentUpdate->targetplatform);
if (isset($this->currentUpdate->php_minimum))
{
unset($this->currentUpdate->php_minimum);
}
if (isset($this->currentUpdate->supported_databases))
{
unset($this->currentUpdate->supported_databases);
}
if (isset($this->currentUpdate->stability))
{
unset($this->currentUpdate->stability);
}
// If the PHP version and minimum stability checks pass, consider this
version as a possible update
if ($phpMatch && $stabilityMatch && $dbMatch)
{
if (isset($this->latest))
{
// We already have a possible update. Check the version.
if (version_compare($this->currentUpdate->version,
$this->latest->version, '>') == 1)
{
$this->latest = $this->currentUpdate;
}
}
else
{
// We don't have any possible updates yet, assume this is an
available update.
$this->latest = $this->currentUpdate;
}
}
}
break;
case 'UPDATES':
// :D
break;
}
}
/**
* Character Parser Function
*
* @param object $parser Parser object.
* @param object $data The data.
*
* @return void
*
* @note This is public because its called externally.
* @since 1.7.0
*/
protected function _characterData($parser, $data)
{
$tag = $this->_getLastTag();
if (in_array($tag, $this->updatecols))
{
$tag = strtolower($tag);
$this->currentUpdate->$tag .= $data;
}
if ($tag == 'PHP_MINIMUM')
{
$this->currentUpdate->php_minimum = $data;
}
if ($tag == 'TAG')
{
$this->currentUpdate->stability =
$this->stabilityTagToInteger((string) $data);
}
}
/**
* Finds an update.
*
* @param array $options Update options.
*
* @return array Array containing the array of update sites and array of
updates
*
* @since 1.7.0
*/
public function findUpdate($options)
{
$response = $this->getUpdateSiteResponse($options);
if ($response === false)
{
return false;
}
if (array_key_exists('minimum_stability', $options))
{
$this->minimum_stability = $options['minimum_stability'];
}
$this->xmlParser = xml_parser_create('');
xml_set_object($this->xmlParser, $this);
xml_set_element_handler($this->xmlParser, '_startElement',
'_endElement');
xml_set_character_data_handler($this->xmlParser,
'_characterData');
if (!xml_parse($this->xmlParser, $response->body))
{
// If the URL is missing the .xml extension, try appending it and retry
loading the update
if (!$this->appendExtension && (substr($this->_url, -4) !=
'.xml'))
{
$options['append_extension'] = true;
return $this->findUpdate($options);
}
Log::add('Error parsing url: ' . $this->_url, Log::WARNING,
'updater');
$app = Factory::getApplication();
$app->enqueueMessage(\JText::sprintf('JLIB_UPDATER_ERROR_EXTENSION_PARSE_URL',
$this->_url), 'warning');
return false;
}
xml_parser_free($this->xmlParser);
if (isset($this->latest))
{
if (isset($this->latest->client) &&
strlen($this->latest->client))
{
if (is_numeric($this->latest->client))
{
$byName = false;
// <client> has to be 'administrator' or
'site', numeric values are deprecated. See
https://docs.joomla.org/Special:MyLanguage/Design_of_JUpdate
Log::add(
'Using numeric values for <client> in the updater xml is
deprecated. Use \'administrator\' or \'site\'
instead.',
Log::WARNING, 'deprecated'
);
}
else
{
$byName = true;
}
$this->latest->client_id =
ApplicationHelper::getClientInfo($this->latest->client,
$byName)->id;
unset($this->latest->client);
}
$updates = array($this->latest);
}
else
{
$updates = array();
}
return array('update_sites' => array(), 'updates'
=> $updates);
}
/**
* Converts a tag to numeric stability representation. If the tag
doesn't represent a known stability level (one of
* dev, alpha, beta, rc, stable) it is ignored.
*
* @param string $tag The tag string, e.g. dev, alpha, beta, rc,
stable
*
* @return integer
*
* @since 3.4
*/
protected function stabilityTagToInteger($tag)
{
$constant = '\\Joomla\\CMS\\Updater\\Updater::STABILITY_' .
strtoupper($tag);
if (defined($constant))
{
return constant($constant);
}
return Updater::STABILITY_STABLE;
}
}
PK���[i�c��DownloadSource.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Updater;
defined('JPATH_PLATFORM') or die;
/**
* Data object representing a download source given as part of an
update's `<downloads>` element
*
* @since 3.8.3
*/
class DownloadSource
{
/**
* Defines a BZIP2 download package
*
* @var string
* @since 3.8.4
*/
const FORMAT_TAR_BZIP = 'bz2';
/**
* Defines a TGZ download package
*
* @var string
* @since 3.8.4
*/
const FORMAT_TAR_GZ = 'gz';
/**
* Defines a ZIP download package
*
* @var string
* @since 3.8.3
*/
const FORMAT_ZIP = 'zip';
/**
* Defines a full package download type
*
* @var string
* @since 3.8.3
*/
const TYPE_FULL = 'full';
/**
* Defines a patch package download type
*
* @var string
* @since 3.8.4
*/
const TYPE_PATCH = 'patch';
/**
* Defines an upgrade package download type
*
* @var string
* @since 3.8.4
*/
const TYPE_UPGRADE = 'upgrade';
/**
* The download type
*
* @var string
* @since 3.8.3
*/
public $type = self::TYPE_FULL;
/**
* The download file's format
*
* @var string
* @since 3.8.3
*/
public $format = self::FORMAT_ZIP;
/**
* The URL to retrieve the package from
*
* @var string
* @since 3.8.3
*/
public $url;
}
PK���[b�q.33
Update.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Updater;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Http\HttpFactory;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Version;
use Joomla\Registry\Registry;
/**
* Update class. It is used by Updater::update() to install an update. Use
Updater::findUpdates() to find updates for
* an extension.
*
* @since 1.7.0
*/
class Update extends \JObject
{
/**
* Update manifest `<name>` element
*
* @var string
* @since 1.7.0
*/
protected $name;
/**
* Update manifest `<description>` element
*
* @var string
* @since 1.7.0
*/
protected $description;
/**
* Update manifest `<element>` element
*
* @var string
* @since 1.7.0
*/
protected $element;
/**
* Update manifest `<type>` element
*
* @var string
* @since 1.7.0
*/
protected $type;
/**
* Update manifest `<version>` element
*
* @var string
* @since 1.7.0
*/
protected $version;
/**
* Update manifest `<infourl>` element
*
* @var string
* @since 1.7.0
*/
protected $infourl;
/**
* Update manifest `<client>` element
*
* @var string
* @since 1.7.0
*/
protected $client;
/**
* Update manifest `<group>` element
*
* @var string
* @since 1.7.0
*/
protected $group;
/**
* Update manifest `<downloads>` element
*
* @var string
* @since 1.7.0
*/
protected $downloads;
/**
* Update manifest `<downloadsource>` elements
*
* @var DownloadSource[]
* @since 3.8.3
*/
protected $downloadSources = array();
/**
* Update manifest `<tags>` element
*
* @var string
* @since 1.7.0
*/
protected $tags;
/**
* Update manifest `<maintainer>` element
*
* @var string
* @since 1.7.0
*/
protected $maintainer;
/**
* Update manifest `<maintainerurl>` element
*
* @var string
* @since 1.7.0
*/
protected $maintainerurl;
/**
* Update manifest `<category>` element
*
* @var string
* @since 1.7.0
*/
protected $category;
/**
* Update manifest `<relationships>` element
*
* @var string
* @since 1.7.0
*/
protected $relationships;
/**
* Update manifest `<targetplatform>` element
*
* @var string
* @since 1.7.0
*/
protected $targetplatform;
/**
* Extra query for download URLs
*
* @var string
* @since 3.2.0
*/
protected $extra_query;
/**
* Resource handle for the XML Parser
*
* @var resource
* @since 3.0.0
*/
protected $xmlParser;
/**
* Element call stack
*
* @var array
* @since 3.0.0
*/
protected $stack = array('base');
/**
* Unused state array
*
* @var array
* @since 3.0.0
*/
protected $stateStore = array();
/**
* Object containing the current update data
*
* @var \stdClass
* @since 3.0.0
*/
protected $currentUpdate;
/**
* Object containing the latest update data
*
* @var \stdClass
* @since 3.0.0
*/
protected $latest;
/**
* The minimum stability required for updates to be taken into account.
The possible values are:
* 0 dev Development snapshots, nightly builds, pre-release versions and
so on
* 1 alpha Alpha versions (work in progress, things are likely to be
broken)
* 2 beta Beta versions (major functionality in place, show-stopper bugs
are likely to be present)
* 3 rc Release Candidate versions (almost stable, minor bugs might be
present)
* 4 stable Stable versions (production quality code)
*
* @var int
* @since 14.1
*
* @see Updater
*/
protected $minimum_stability = Updater::STABILITY_STABLE;
/**
* Gets the reference to the current direct parent
*
* @return object
*
* @since 1.7.0
*/
protected function _getStackLocation()
{
return implode('->', $this->stack);
}
/**
* Get the last position in stack count
*
* @return string
*
* @since 1.7.0
*/
protected function _getLastTag()
{
return $this->stack[count($this->stack) - 1];
}
/**
* XML Start Element callback
*
* @param object $parser Parser object
* @param string $name Name of the tag found
* @param array $attrs Attributes of the tag
*
* @return void
*
* @note This is public because it is called externally
* @since 1.7.0
*/
public function _startElement($parser, $name, $attrs = array())
{
$this->stack[] = $name;
$tag = $this->_getStackLocation();
// Reset the data
if (isset($this->$tag))
{
$this->$tag->_data = '';
}
switch ($name)
{
// This is a new update; create a current update
case 'UPDATE':
$this->currentUpdate = new \stdClass;
break;
// Handle the array of download sources
case 'DOWNLOADSOURCE':
$source = new DownloadSource;
foreach ($attrs as $key => $data)
{
$key = strtolower($key);
$source->$key = $data;
}
$this->downloadSources[] = $source;
break;
// Don't do anything
case 'UPDATES':
break;
// For everything else there's...the default!
default:
$name = strtolower($name);
if (!isset($this->currentUpdate->$name))
{
$this->currentUpdate->$name = new \stdClass;
}
$this->currentUpdate->$name->_data = '';
foreach ($attrs as $key => $data)
{
$key = strtolower($key);
$this->currentUpdate->$name->$key = $data;
}
break;
}
}
/**
* Callback for closing the element
*
* @param object $parser Parser object
* @param string $name Name of element that was closed
*
* @return void
*
* @note This is public because it is called externally
* @since 1.7.0
*/
public function _endElement($parser, $name)
{
array_pop($this->stack);
switch ($name)
{
// Closing update, find the latest version and check
case 'UPDATE':
$product =
strtolower(InputFilter::getInstance()->clean(Version::PRODUCT,
'cmd'));
// Support for the min_dev_level and max_dev_level attributes is
deprecated, a regexp should be used instead
if (isset($this->currentUpdate->targetplatform->min_dev_level)
|| isset($this->currentUpdate->targetplatform->max_dev_level))
{
Log::add(
'Support for the min_dev_level and max_dev_level attributes of
an update\'s <targetplatform> tag is deprecated and'
. ' will be removed in 4.0. The full version should be specified
in the version attribute and may optionally be a regexp.',
Log::WARNING,
'deprecated'
);
}
/*
* Check that the product matches and that the version matches
(optionally a regexp)
*
* Check for optional min_dev_level and max_dev_level attributes to
further specify targetplatform (e.g., 3.0.1)
*/
$patchVersion = $this->get('jversion.dev_level',
Version::PATCH_VERSION);
$patchMinimumSupported =
!isset($this->currentUpdate->targetplatform->min_dev_level)
|| $patchVersion >=
$this->currentUpdate->targetplatform->min_dev_level;
$patchMaximumSupported =
!isset($this->currentUpdate->targetplatform->max_dev_level)
|| $patchVersion <=
$this->currentUpdate->targetplatform->max_dev_level;
if (isset($this->currentUpdate->targetplatform->name)
&& $product ==
$this->currentUpdate->targetplatform->name
&& preg_match('/^' .
$this->currentUpdate->targetplatform->version . '/',
$this->get('jversion.full', JVERSION))
&& $patchMinimumSupported
&& $patchMaximumSupported)
{
$phpMatch = false;
// Check if PHP version supported via <php_minimum> tag, assume
true if tag isn't present
if (!isset($this->currentUpdate->php_minimum) ||
version_compare(PHP_VERSION,
$this->currentUpdate->php_minimum->_data, '>='))
{
$phpMatch = true;
}
$dbMatch = false;
// Check if DB & version is supported via
<supported_databases> tag, assume supported if tag isn't present
if (isset($this->currentUpdate->supported_databases))
{
$db = Factory::getDbo();
$dbType = strtolower($db->getServerType());
$dbVersion = $db->getVersion();
$supportedDbs = $this->currentUpdate->supported_databases;
// MySQL and MariaDB use the same database driver but not the same
version numbers
if ($dbType === 'mysql')
{
// Check whether we have a MariaDB version string and extract the
proper version from it
if (stripos($dbVersion, 'mariadb') !== false)
{
// MariaDB: Strip off any leading '5.5.5-', if present
$dbVersion = preg_replace('/^5\.5\.5-/', '',
$dbVersion);
$dbType = 'mariadb';
}
}
// Do we have an entry for the database?
if (isset($supportedDbs->$dbType))
{
$minumumVersion = $supportedDbs->$dbType;
$dbMatch = version_compare($dbVersion, $minumumVersion,
'>=');
}
}
else
{
// Set to true if the <supported_databases> tag is not set
$dbMatch = true;
}
// Check minimum stability
$stabilityMatch = true;
if (isset($this->currentUpdate->stability) &&
($this->currentUpdate->stability < $this->minimum_stability))
{
$stabilityMatch = false;
}
if ($phpMatch && $stabilityMatch && $dbMatch)
{
if (isset($this->latest))
{
if (version_compare($this->currentUpdate->version->_data,
$this->latest->version->_data, '>') == 1)
{
$this->latest = $this->currentUpdate;
}
}
else
{
$this->latest = $this->currentUpdate;
}
}
}
break;
case 'UPDATES':
// If the latest item is set then we transfer it to where we want to
if (isset($this->latest))
{
foreach (get_object_vars($this->latest) as $key => $val)
{
$this->$key = $val;
}
unset($this->latest);
unset($this->currentUpdate);
}
elseif (isset($this->currentUpdate))
{
// The update might be for an older version of j!
unset($this->currentUpdate);
}
break;
}
}
/**
* Character Parser Function
*
* @param object $parser Parser object.
* @param object $data The data.
*
* @return void
*
* @note This is public because its called externally.
* @since 1.7.0
*/
public function _characterData($parser, $data)
{
$tag = $this->_getLastTag();
// Throw the data for this item together
$tag = strtolower($tag);
if ($tag == 'tag')
{
$this->currentUpdate->stability =
$this->stabilityTagToInteger((string) $data);
return;
}
if ($tag == 'downloadsource')
{
// Grab the last source so we can append the URL
$source = end($this->downloadSources);
$source->url = $data;
return;
}
if (isset($this->currentUpdate->$tag))
{
$this->currentUpdate->$tag->_data .= $data;
}
}
/**
* Loads an XML file from a URL.
*
* @param string $url The URL.
* @param int $minimumStability The minimum stability required for
updating the extension {@see Updater}
*
* @return boolean True on success
*
* @since 1.7.0
*/
public function loadFromXml($url, $minimumStability =
Updater::STABILITY_STABLE)
{
$version = new Version;
$httpOption = new Registry;
$httpOption->set('userAgent',
$version->getUserAgent('Joomla', true, false));
try
{
$http = HttpFactory::getHttp($httpOption);
$response = $http->get($url);
}
catch (\RuntimeException $e)
{
$response = null;
}
if ($response === null || $response->code !== 200)
{
// TODO: Add a 'mark bad' setting here somehow
Log::add(\JText::sprintf('JLIB_UPDATER_ERROR_EXTENSION_OPEN_URL',
$url), Log::WARNING, 'jerror');
return false;
}
$this->minimum_stability = $minimumStability;
$this->xmlParser = xml_parser_create('');
xml_set_object($this->xmlParser, $this);
xml_set_element_handler($this->xmlParser, '_startElement',
'_endElement');
xml_set_character_data_handler($this->xmlParser,
'_characterData');
if (!xml_parse($this->xmlParser, $response->body))
{
Log::add(
sprintf(
'XML error: %s at line %d',
xml_error_string(xml_get_error_code($this->xmlParser)),
xml_get_current_line_number($this->xmlParser)
),
Log::WARNING, 'updater'
);
return false;
}
xml_parser_free($this->xmlParser);
return true;
}
/**
* Converts a tag to numeric stability representation. If the tag
doesn't represent a known stability level (one of
* dev, alpha, beta, rc, stable) it is ignored.
*
* @param string $tag The tag string, e.g. dev, alpha, beta, rc,
stable
*
* @return integer
*
* @since 3.4
*/
protected function stabilityTagToInteger($tag)
{
$constant = '\\Joomla\\CMS\\Updater\\Updater::STABILITY_' .
strtoupper($tag);
if (defined($constant))
{
return constant($constant);
}
return Updater::STABILITY_STABLE;
}
}
PK���[�[�w##UpdateAdapter.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Updater;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Http\HttpFactory;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Version;
use Joomla\Registry\Registry;
\JLoader::import('joomla.base.adapterinstance');
/**
* UpdateAdapter class.
*
* @since 1.7.0
*/
abstract class UpdateAdapter extends \JAdapterInstance
{
/**
* Resource handle for the XML Parser
*
* @var resource
* @since 3.0.0
*/
protected $xmlParser;
/**
* Element call stack
*
* @var array
* @since 3.0.0
*/
protected $stack = array('base');
/**
* ID of update site
*
* @var string
* @since 3.0.0
*/
protected $updateSiteId = 0;
/**
* Columns in the extensions table to be updated
*
* @var array
* @since 3.0.0
*/
protected $updatecols = array('NAME', 'ELEMENT',
'TYPE', 'FOLDER', 'CLIENT',
'VERSION', 'DESCRIPTION', 'INFOURL',
'EXTRA_QUERY');
/**
* Should we try appending a .xml extension to the update site's URL?
*
* @var bool
*/
protected $appendExtension = false;
/**
* The name of the update site (used in logging)
*
* @var string
*/
protected $updateSiteName = '';
/**
* The update site URL from which we will get the update information
*
* @var string
*/
protected $_url = '';
/**
* The minimum stability required for updates to be taken into account.
The possible values are:
* 0 dev Development snapshots, nightly builds, pre-release versions and
so on
* 1 alpha Alpha versions (work in progress, things are likely to be
broken)
* 2 beta Beta versions (major functionality in place, show-stopper bugs
are likely to be present)
* 3 rc Release Candidate versions (almost stable, minor bugs might be
present)
* 4 stable Stable versions (production quality code)
*
* @var int
* @since 14.1
*
* @see Updater
*/
protected $minimum_stability = Updater::STABILITY_STABLE;
/**
* Gets the reference to the current direct parent
*
* @return object
*
* @since 1.7.0
*/
protected function _getStackLocation()
{
return implode('->', $this->stack);
}
/**
* Gets the reference to the last tag
*
* @return object
*
* @since 1.7.0
*/
protected function _getLastTag()
{
return $this->stack[count($this->stack) - 1];
}
/**
* Finds an update
*
* @param array $options Options to use: update_site_id: the unique ID
of the update site to look at
*
* @return array Update_sites and updates discovered
*
* @since 1.7.0
*/
abstract public function findUpdate($options);
/**
* Toggles the enabled status of an update site. Update sites are disabled
before getting the update information
* from their URL and enabled afterwards. If the URL fetch fails with a
PHP fatal error (e.g. timeout) the faulty
* update site will remain disabled the next time we attempt to load the
update information.
*
* @param int $updateSiteId The numeric ID of the update site to
enable/disable
* @param bool $enabled Enable the site when true, disable it
when false
*
* @return void
*/
protected function toggleUpdateSite($updateSiteId, $enabled = true)
{
$updateSiteId = (int) $updateSiteId;
$enabled = (bool) $enabled;
if (empty($updateSiteId))
{
return;
}
$db = $this->parent->getDbo();
$query = $db->getQuery(true)
->update($db->qn('#__update_sites'))
->set($db->qn('enabled') . ' = ' .
$db->q($enabled ? 1 : 0))
->where($db->qn('update_site_id') . ' = ' .
$db->q($updateSiteId));
$db->setQuery($query);
try
{
$db->execute();
}
catch (\RuntimeException $e)
{
// Do nothing
}
}
/**
* Get the name of an update site. This is used in logging.
*
* @param int $updateSiteId The numeric ID of the update site
*
* @return string The name of the update site or an empty string if
it's not found
*/
protected function getUpdateSiteName($updateSiteId)
{
$updateSiteId = (int) $updateSiteId;
if (empty($updateSiteId))
{
return '';
}
$db = $this->parent->getDbo();
$query = $db->getQuery(true)
->select($db->qn('name'))
->from($db->qn('#__update_sites'))
->where($db->qn('update_site_id') . ' = ' .
$db->q($updateSiteId));
$db->setQuery($query);
$name = '';
try
{
$name = $db->loadResult();
}
catch (\RuntimeException $e)
{
// Do nothing
}
return $name;
}
/**
* Try to get the raw HTTP response from the update site, hopefully
containing the update XML.
*
* @param array $options The update options, see findUpdate() in
children classes
*
* @return boolean|\JHttpResponse False if we can't connect to the
site, JHttpResponse otherwise
*
* @throws \Exception
*/
protected function getUpdateSiteResponse($options = array())
{
$url = trim($options['location']);
$this->_url = &$url;
$this->updateSiteId = $options['update_site_id'];
if (!isset($options['update_site_name']))
{
$options['update_site_name'] =
$this->getUpdateSiteName($this->updateSiteId);
}
$this->updateSiteName = $options['update_site_name'];
$this->appendExtension = false;
if (array_key_exists('append_extension', $options))
{
$this->appendExtension = $options['append_extension'];
}
if ($this->appendExtension && (substr($url, -4) !=
'.xml'))
{
if (substr($url, -1) != '/')
{
$url .= '/';
}
$url .= 'extension.xml';
}
// Disable the update site. If the get() below fails with a fatal error
(e.g. timeout) the faulty update
// site will remain disabled
$this->toggleUpdateSite($this->updateSiteId, false);
$startTime = microtime(true);
$version = new Version;
$httpOption = new Registry;
$httpOption->set('userAgent',
$version->getUserAgent('Joomla', true, false));
// JHttp transport throws an exception when there's no response.
try
{
$http = HttpFactory::getHttp($httpOption);
$response = $http->get($url, array(), 20);
}
catch (\RuntimeException $e)
{
$response = null;
}
// Enable the update site. Since the get() returned the update site
should remain enabled
$this->toggleUpdateSite($this->updateSiteId, true);
// Log the time it took to load this update site's information
$endTime = microtime(true);
$timeToLoad = sprintf('%0.2f', $endTime - $startTime);
Log::add(
"Loading information from update site #{$this->updateSiteId}
with name " .
"\"$this->updateSiteName\" and URL $url took
$timeToLoad seconds", Log::INFO, 'updater'
);
if ($response === null || $response->code !== 200)
{
// If the URL is missing the .xml extension, try appending it and retry
loading the update
if (!$this->appendExtension && (substr($url, -4) !=
'.xml'))
{
$options['append_extension'] = true;
return $this->getUpdateSiteResponse($options);
}
// Log the exact update site name and URL which could not be loaded
Log::add('Error opening url: ' . $url . ' for update
site: ' . $this->updateSiteName, Log::WARNING,
'updater');
$app = Factory::getApplication();
$app->enqueueMessage(\JText::sprintf('JLIB_UPDATER_ERROR_OPEN_UPDATE_SITE',
$this->updateSiteId, $this->updateSiteName, $url),
'warning');
return false;
}
return $response;
}
}
PK���[���.�.Updater.phpnu�[���<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Updater;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Table\Table;
\JLoader::import('joomla.filesystem.file');
\JLoader::import('joomla.filesystem.folder');
\JLoader::import('joomla.filesystem.path');
\JLoader::import('joomla.base.adapter');
/**
* Updater Class
*
* @since 1.7.0
*/
class Updater extends \JAdapter
{
/**
* Development snapshots, nightly builds, pre-release versions and so on
*
* @var integer
* @since 3.4
*/
const STABILITY_DEV = 0;
/**
* Alpha versions (work in progress, things are likely to be broken)
*
* @var integer
* @since 3.4
*/
const STABILITY_ALPHA = 1;
/**
* Beta versions (major functionality in place, show-stopper bugs are
likely to be present)
*
* @var integer
* @since 3.4
*/
const STABILITY_BETA = 2;
/**
* Release Candidate versions (almost stable, minor bugs might be present)
*
* @var integer
* @since 3.4
*/
const STABILITY_RC = 3;
/**
* Stable versions (production quality code)
*
* @var integer
* @since 3.4
*/
const STABILITY_STABLE = 4;
/**
* Updater instance container.
*
* @var Updater
* @since 1.7.3
*/
protected static $instance;
/**
* Constructor
*
* @param string $basepath Base Path of the adapters
* @param string $classprefix Class prefix of adapters
* @param string $adapterfolder Name of folder to append to base path
*
* @since 3.1
*/
public function __construct($basepath = __DIR__, $classprefix =
'\\Joomla\\CMS\\Updater\\Adapter', $adapterfolder =
'Adapter')
{
parent::__construct($basepath, $classprefix, $adapterfolder);
}
/**
* Returns a reference to the global Installer object, only creating it
* if it doesn't already exist.
*
* @return Updater An installer object
*
* @since 1.7.0
*/
public static function getInstance()
{
if (!isset(self::$instance))
{
self::$instance = new Updater;
}
return self::$instance;
}
/**
* Finds the update for an extension. Any discovered updates are stored in
the #__updates table.
*
* @param int|array $eid Extension Identifier or list of
Extension Identifiers; if zero use all
* sites
* @param integer $cacheTimeout How many seconds to cache update
information; if zero, force reload the
* update information
* @param integer $minimumStability Minimum stability for the
updates; 0=dev, 1=alpha, 2=beta, 3=rc,
* 4=stable
* @param boolean $includeCurrent Should I include the current
version in the results?
*
* @return boolean True if there are updates
*
* @since 1.7.0
*/
public function findUpdates($eid = 0, $cacheTimeout = 0, $minimumStability
= self::STABILITY_STABLE, $includeCurrent = false)
{
$retval = false;
$results = $this->getUpdateSites($eid);
if (empty($results))
{
return $retval;
}
$now = time();
$earliestTime = $now - $cacheTimeout;
$sitesWithUpdates = array();
if ($cacheTimeout > 0)
{
$sitesWithUpdates = $this->getSitesWithUpdates($earliestTime);
}
foreach ($results as $result)
{
/**
* If we have already checked for updates within the cache timeout
period we will report updates available
* only if there are update records matching this update site. Then we
skip processing of the update site
* since it's already processed within the cache timeout period.
*/
if (($cacheTimeout > 0)
&& isset($result['last_check_timestamp'])
&& ($result['last_check_timestamp'] >=
$earliestTime))
{
$retval = $retval || in_array($result['update_site_id'],
$sitesWithUpdates);
continue;
}
// Make sure there is no update left over in the database.
$db = $this->getDbo();
$query = $db->getQuery(true)
->delete($db->quoteName('#__updates'))
->where($db->quoteName('update_site_id') . ' =
' . $db->quote($result['update_site_id']));
$db->setQuery($query);
$db->execute();
$updateObjects = $this->getUpdateObjectsForSite($result,
$minimumStability, $includeCurrent);
if (!empty($updateObjects))
{
$retval = true;
/** @var \JTableUpdate $update */
foreach ($updateObjects as $update)
{
$update->check();
$update->store();
}
}
// Finally, update the last update check timestamp
$this->updateLastCheckTimestamp($result['update_site_id']);
}
return $retval;
}
/**
* Finds an update for an extension
*
* @param integer $id Id of the extension
*
* @return mixed
*
* @since 3.6.0
*
* @deprecated 4.0 No replacement.
*/
public function update($id)
{
$updaterow = Table::getInstance('update');
$updaterow->load($id);
$update = new Update;
if ($update->loadFromXml($updaterow->detailsurl))
{
return $update->install();
}
return false;
}
/**
* Returns the update site records for an extension with ID $eid. If $eid
is zero all enabled update sites records
* will be returned.
*
* @param int $eid The extension ID to fetch.
*
* @return array
*
* @since 3.6.0
*/
private function getUpdateSites($eid = 0)
{
$db = $this->getDbo();
$query = $db->getQuery(true);
$query->select('DISTINCT a.update_site_id, a.type, a.location,
a.last_check_timestamp, a.extra_query')
->from($db->quoteName('#__update_sites', 'a'))
->where('a.enabled = 1');
if ($eid)
{
$query->join('INNER', '#__update_sites_extensions AS b
ON a.update_site_id = b.update_site_id');
if (is_array($eid))
{
$query->where('b.extension_id IN (' .
implode(',', $eid) . ')');
}
elseif ((int) $eid)
{
$query->where('b.extension_id = ' . $eid);
}
}
$db->setQuery($query);
$result = $db->loadAssocList();
if (!is_array($result))
{
return array();
}
return $result;
}
/**
* Loads the contents of an update site record $updateSite and returns the
update objects
*
* @param array $updateSite The update site record to process
* @param int $minimumStability Minimum stability for the returned
update records
* @param bool $includeCurrent Should I also include the current
version?
*
* @return array The update records. Empty array if no updates are
found.
*
* @since 3.6.0
*/
private function getUpdateObjectsForSite($updateSite, $minimumStability =
self::STABILITY_STABLE, $includeCurrent = false)
{
$retVal = array();
$this->setAdapter($updateSite['type']);
if (!isset($this->_adapters[$updateSite['type']]))
{
// Ignore update sites requiring adapters we don't have installed
return $retVal;
}
$updateSite['minimum_stability'] = $minimumStability;
// Get the update information from the remote update XML document
/** @var UpdateAdapter $adapter */
$adapter = $this->_adapters[ $updateSite['type']];
$update_result = $adapter->findUpdate($updateSite);
// Version comparison operator.
$operator = $includeCurrent ? 'ge' : 'gt';
if (is_array($update_result))
{
// If we have additional update sites in the remote (collection) update
XML document, parse them
if (array_key_exists('update_sites', $update_result)
&& count($update_result['update_sites']))
{
$thisUrl = trim($updateSite['location']);
$thisId = (int) $updateSite['update_site_id'];
foreach ($update_result['update_sites'] as $extraUpdateSite)
{
$extraUrl = trim($extraUpdateSite['location']);
$extraId = (int) $extraUpdateSite['update_site_id'];
// Do not try to fetch the same update site twice
if (($thisId == $extraId) || ($thisUrl == $extraUrl))
{
continue;
}
$extraUpdates = $this->getUpdateObjectsForSite($extraUpdateSite,
$minimumStability);
if (count($extraUpdates))
{
$retVal = array_merge($retVal, $extraUpdates);
}
}
}
if (array_key_exists('updates', $update_result) &&
count($update_result['updates']))
{
/** @var \JTableUpdate $current_update */
foreach ($update_result['updates'] as $current_update)
{
$current_update->extra_query =
$updateSite['extra_query'];
/** @var \JTableUpdate $update */
$update = Table::getInstance('update');
/** @var \JTableExtension $extension */
$extension = Table::getInstance('extension');
$uid = $update
->find(
array(
'element' =>
$current_update->get('element'),
'type' =>
$current_update->get('type'),
'client_id' =>
$current_update->get('client_id'),
'folder' =>
$current_update->get('folder'),
)
);
$eid = $extension
->find(
array(
'element' =>
$current_update->get('element'),
'type' =>
$current_update->get('type'),
'client_id' =>
$current_update->get('client_id'),
'folder' =>
$current_update->get('folder'),
)
);
if (!$uid)
{
// Set the extension id
if ($eid)
{
// We have an installed extension, check the update is actually
newer
$extension->load($eid);
$data = json_decode($extension->manifest_cache, true);
if (version_compare($current_update->version,
$data['version'], $operator) == 1)
{
$current_update->extension_id = $eid;
$retVal[] = $current_update;
}
}
else
{
// A potentially new extension to be installed
$retVal[] = $current_update;
}
}
else
{
$update->load($uid);
// We already have an update in the database lets check whether it
has an extension_id
if ((int) $update->extension_id === 0 && $eid)
{
// The current update does not have an extension_id but we found one
let's use them
$current_update->extension_id = $eid;
}
// If there is an update, check that the version is newer then
replaces
if (version_compare($current_update->version, $update->version,
$operator) == 1)
{
$retVal[] = $current_update;
}
}
}
}
}
return $retVal;
}
/**
* Returns the IDs of the update sites with cached updates
*
* @param int $timestamp Optional. If set, only update sites checked
before $timestamp will be taken into
* account.
*
* @return array The IDs of the update sites with cached updates
*
* @since 3.6.0
*/
private function getSitesWithUpdates($timestamp = 0)
{
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select('DISTINCT update_site_id')
->from('#__updates');
if ($timestamp)
{
$subQuery = $db->getQuery(true)
->select('update_site_id')
->from('#__update_sites')
->where($db->qn('last_check_timestamp') . ' IS
NULL', 'OR')
->where($db->qn('last_check_timestamp') . ' <=
' . $db->q($timestamp), 'OR');
$query->where($db->qn('update_site_id') . ' IN
(' . $subQuery . ')');
}
$retVal = $db->setQuery($query)->loadColumn(0);
if (empty($retVal))
{
return array();
}
return $retVal;
}
/**
* Update the last check timestamp of an update site
*
* @param int $updateSiteId The update site ID to mark as just checked
*
* @return void
*
* @since 3.6.0
*/
private function updateLastCheckTimestamp($updateSiteId)
{
$timestamp = time();
$db = Factory::getDbo();
$query = $db->getQuery(true)
->update($db->quoteName('#__update_sites'))
->set($db->quoteName('last_check_timestamp') . ' =
' . $db->quote($timestamp))
->where($db->quoteName('update_site_id') . ' =
' . $db->quote($updateSiteId));
$db->setQuery($query);
$db->execute();
}
}
PK���[�n�;;Adapter/CollectionAdapter.phpnu�[���PK���[l]��+�+�Adapter/ExtensionAdapter.phpnu�[���PK���[i�c���DDownloadSource.phpnu�[���PK���[b�q.33
�JUpdate.phpnu�[���PK���[�[�w##�}UpdateAdapter.phpnu�[���PK���[���.�.Z�Updater.phpnu�[���PK�h�