You've already forked joomla_test
first commit
This commit is contained in:
264
libraries/joomla/updater/adapters/collection.php
Normal file
264
libraries/joomla/updater/adapters/collection.php
Normal file
@ -0,0 +1,264 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Updater
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.updater.updateadapter');
|
||||
|
||||
/**
|
||||
* Collection Update Adapter Class
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Updater
|
||||
* @since 11.1
|
||||
*/
|
||||
class JUpdaterCollection extends JUpdateAdapter
|
||||
{
|
||||
/**
|
||||
* Root of the tree
|
||||
*
|
||||
* @var object
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $base;
|
||||
|
||||
/**
|
||||
* Tree of objects
|
||||
*
|
||||
* @var array
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $parent = array(0);
|
||||
|
||||
/**
|
||||
* Used to control if an item has a child or not
|
||||
*
|
||||
* @var boolean
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $pop_parent = 0;
|
||||
|
||||
/**
|
||||
* @var array A list of discovered update sites
|
||||
*/
|
||||
protected $update_sites;
|
||||
|
||||
/**
|
||||
* A list of discovered updates
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $updates;
|
||||
|
||||
/**
|
||||
* Gets the reference to the current direct parent
|
||||
*
|
||||
* @return object
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _getStackLocation()
|
||||
{
|
||||
return implode('->', $this->stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent tag
|
||||
*
|
||||
* @return string parent
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
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 11.1
|
||||
*/
|
||||
public function _startElement($parser, $name, $attrs = array())
|
||||
{
|
||||
array_push($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 = JTable::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 = JApplicationHelper::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 JVersion;
|
||||
|
||||
// Lower case and remove the exclamation mark
|
||||
$product = strtolower(JFilterInput::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 ourself as a default
|
||||
// validate that we can install the extension
|
||||
if ($product == $values['targetplatform'] && preg_match('/' . $values['targetplatformversion'] . '/', $ver->RELEASE))
|
||||
{
|
||||
$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 11.1
|
||||
*/
|
||||
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 11.1
|
||||
*/
|
||||
public function findUpdate($options)
|
||||
{
|
||||
$url = $options['location'];
|
||||
$this->updateSiteId = $options['update_site_id'];
|
||||
if (substr($url, -4) != '.xml')
|
||||
{
|
||||
if (substr($url, -1) != '/')
|
||||
{
|
||||
$url .= '/';
|
||||
}
|
||||
$url .= 'update.xml';
|
||||
}
|
||||
|
||||
$this->base = new stdClass;
|
||||
$this->update_sites = array();
|
||||
$this->updates = array();
|
||||
$db = $this->parent->getDBO();
|
||||
|
||||
$http = JHttpFactory::getHttp();
|
||||
$response = $http->get($url);
|
||||
if (200 != $response->code)
|
||||
{
|
||||
$query = $db->getQuery(true)
|
||||
->update('#__update_sites')
|
||||
->set('enabled = 0')
|
||||
->where('update_site_id = ' . $this->updateSiteId);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
JLog::add("Error parsing url: " . $url, JLog::WARNING, 'updater');
|
||||
$app = JFactory::getApplication();
|
||||
$app->enqueueMessage(JText::sprintf('JLIB_UPDATER_ERROR_COLLECTION_OPEN_URL', $url), 'warning');
|
||||
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))
|
||||
{
|
||||
JLog::add("Error parsing url: " . $url, JLog::WARNING, 'updater');
|
||||
$app = JFactory::getApplication();
|
||||
$app->enqueueMessage(JText::sprintf('JLIB_UPDATER_ERROR_COLLECTION_PARSE_URL', $url), 'warning');
|
||||
return false;
|
||||
}
|
||||
// TODO: Decrement the bad counter if non-zero
|
||||
return array('update_sites' => $this->update_sites, 'updates' => $this->updates);
|
||||
}
|
||||
}
|
232
libraries/joomla/updater/adapters/extension.php
Normal file
232
libraries/joomla/updater/adapters/extension.php
Normal file
@ -0,0 +1,232 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Updater
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.updater.updateadapter');
|
||||
/**
|
||||
* Extension class for updater
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Updater
|
||||
* @since 11.1
|
||||
* */
|
||||
class JUpdaterExtension extends JUpdateAdapter
|
||||
{
|
||||
/**
|
||||
* 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 11.1
|
||||
*/
|
||||
protected function _startElement($parser, $name, $attrs = array())
|
||||
{
|
||||
array_push($this->stack, $name);
|
||||
$tag = $this->_getStackLocation();
|
||||
|
||||
// Reset the data
|
||||
if (isset($this->$tag))
|
||||
{
|
||||
$this->$tag->_data = "";
|
||||
}
|
||||
|
||||
switch ($name)
|
||||
{
|
||||
case 'UPDATE':
|
||||
$this->current_update = JTable::getInstance('update');
|
||||
$this->current_update->update_site_id = $this->updateSiteId;
|
||||
$this->current_update->detailsurl = $this->_url;
|
||||
$this->current_update->folder = "";
|
||||
$this->current_update->client_id = 1;
|
||||
break;
|
||||
|
||||
// Don't do anything
|
||||
case 'UPDATES':
|
||||
break;
|
||||
default:
|
||||
if (in_array($name, $this->updatecols))
|
||||
{
|
||||
$name = strtolower($name);
|
||||
$this->current_update->$name = '';
|
||||
}
|
||||
if ($name == 'TARGETPLATFORM')
|
||||
{
|
||||
$this->current_update->targetplatform = $attrs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Character Parser Function
|
||||
*
|
||||
* @param object $parser Parser object.
|
||||
* @param object $name The name of the element.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _endElement($parser, $name)
|
||||
{
|
||||
array_pop($this->stack);
|
||||
|
||||
// @todo remove code: echo 'Closing: '. $name .'<br />';
|
||||
switch ($name)
|
||||
{
|
||||
case 'UPDATE':
|
||||
$ver = new JVersion;
|
||||
|
||||
// Lower case and remove the exclamation mark
|
||||
$product = strtolower(JFilterInput::getInstance()->clean($ver->PRODUCT, 'cmd'));
|
||||
|
||||
// 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)
|
||||
if ($product == $this->current_update->targetplatform['NAME']
|
||||
&& preg_match('/' . $this->currentUpdate->targetplatform->version . '/', $ver->RELEASE)
|
||||
&& ((!isset($this->currentUpdate->targetplatform->min_dev_level)) || $ver->DEV_LEVEL >= $this->currentUpdate->targetplatform->min_dev_level)
|
||||
&& ((!isset($this->currentUpdate->targetplatform->max_dev_level)) || $ver->DEV_LEVEL <= $this->currentUpdate->targetplatform->max_dev_level))
|
||||
{
|
||||
// Target platform isn't a valid field in the update table so unset it to prevent J! from trying to store it
|
||||
unset($this->current_update->targetplatform);
|
||||
if (isset($this->latest))
|
||||
{
|
||||
if (version_compare($this->current_update->version, $this->latest->version, '>') == 1)
|
||||
{
|
||||
$this->latest = $this->current_update;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->latest = $this->current_update;
|
||||
}
|
||||
}
|
||||
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 11.1
|
||||
*/
|
||||
protected function _characterData($parser, $data)
|
||||
{
|
||||
$tag = $this->_getLastTag();
|
||||
/**
|
||||
* @todo remove code
|
||||
* if(!isset($this->$tag->_data)) $this->$tag->_data = '';
|
||||
* $this->$tag->_data .= $data;
|
||||
*/
|
||||
if (in_array($tag, $this->updatecols))
|
||||
{
|
||||
$tag = strtolower($tag);
|
||||
$this->current_update->$tag .= $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an update.
|
||||
*
|
||||
* @param array $options Update options.
|
||||
*
|
||||
* @return array Array containing the array of update sites and array of updates
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function findUpdate($options)
|
||||
{
|
||||
$url = $options['location'];
|
||||
$this->_url = &$url;
|
||||
$this->updateSiteId = $options['update_site_id'];
|
||||
if (substr($url, -4) != '.xml')
|
||||
{
|
||||
if (substr($url, -1) != '/')
|
||||
{
|
||||
$url .= '/';
|
||||
}
|
||||
$url .= 'extension.xml';
|
||||
}
|
||||
|
||||
$db = $this->parent->getDBO();
|
||||
|
||||
$http = JHttpFactory::getHttp();
|
||||
$response = $http->get($url);
|
||||
if (!empty($response->code) && 200 != $response->code)
|
||||
{
|
||||
$query = $db->getQuery(true)
|
||||
->update('#__update_sites')
|
||||
->set('enabled = 0')
|
||||
->where('update_site_id = ' . $this->updateSiteId);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
JLog::add("Error opening url: " . $url, JLog::WARNING, 'updater');
|
||||
$app = JFactory::getApplication();
|
||||
$app->enqueueMessage(JText::sprintf('JLIB_UPDATER_ERROR_EXTENSION_OPEN_URL', $url), 'warning');
|
||||
return false;
|
||||
}
|
||||
|
||||
$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))
|
||||
{
|
||||
JLog::add("Error parsing url: " . $url, JLog::WARNING, 'updater');
|
||||
$app = JFactory::getApplication();
|
||||
$app->enqueueMessage(JText::sprintf('JLIB_UPDATER_ERROR_EXTENSION_PARSE_URL', $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 depreceated. See http://docs.joomla.org/Design_of_JUpdate
|
||||
JLog::add(
|
||||
'Using numeric values for <client> in the updater xml is deprecated. Use \'administrator\' or \'site\' instead.',
|
||||
JLog::WARNING, 'deprecated'
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$byName = true;
|
||||
}
|
||||
$this->latest->client_id = JApplicationHelper::getClientInfo($this->latest->client, $byName)->id;
|
||||
unset($this->latest->client);
|
||||
}
|
||||
$updates = array($this->latest);
|
||||
}
|
||||
else
|
||||
{
|
||||
$updates = array();
|
||||
}
|
||||
return array('update_sites' => array(), 'updates' => $updates);
|
||||
}
|
||||
}
|
1
libraries/joomla/updater/adapters/index.html
Normal file
1
libraries/joomla/updater/adapters/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
1
libraries/joomla/updater/index.html
Normal file
1
libraries/joomla/updater/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
342
libraries/joomla/updater/update.php
Normal file
342
libraries/joomla/updater/update.php
Normal file
@ -0,0 +1,342 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Updater
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Update class.
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Updater
|
||||
* @since 11.1
|
||||
*/
|
||||
class JUpdate extends JObject
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $element;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $version;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $infourl;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $group;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $downloads;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $tags;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $maintainer;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $maintainerurl;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $category;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $relationships;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $targetplatform;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $xmlParser;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $stack = array('base');
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $stateStore = array();
|
||||
|
||||
/**
|
||||
* @var stdClass
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $currentUpdate;
|
||||
|
||||
/**
|
||||
* @var stdClass
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $latest;
|
||||
|
||||
/**
|
||||
* Gets the reference to the current direct parent
|
||||
*
|
||||
* @return object
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _getStackLocation()
|
||||
{
|
||||
return implode('->', $this->stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last position in stack count
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
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 11.1
|
||||
*/
|
||||
public function _startElement($parser, $name, $attrs = array())
|
||||
{
|
||||
array_push($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;
|
||||
|
||||
// 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 11.1
|
||||
*/
|
||||
public function _endElement($parser, $name)
|
||||
{
|
||||
array_pop($this->stack);
|
||||
switch ($name)
|
||||
{
|
||||
// Closing update, find the latest version and check
|
||||
case 'UPDATE':
|
||||
$ver = new JVersion;
|
||||
$product = strtolower(JFilterInput::getInstance()->clean($ver->PRODUCT, 'cmd'));
|
||||
|
||||
// Check for optional min_dev_level and max_dev_level attributes to further specify targetplatform (e.g., 3.0.1)
|
||||
if (isset($this->currentUpdate->targetplatform->name)
|
||||
&& $product == $this->currentUpdate->targetplatform->name
|
||||
&& preg_match('/' . $this->currentUpdate->targetplatform->version . '/', $ver->RELEASE)
|
||||
&& ((!isset($this->currentUpdate->targetplatform->min_dev_level)) || $ver->DEV_LEVEL >= $this->currentUpdate->targetplatform->min_dev_level)
|
||||
&& ((!isset($this->currentUpdate->targetplatform->max_dev_level)) || $ver->DEV_LEVEL <= $this->currentUpdate->targetplatform->max_dev_level))
|
||||
{
|
||||
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 11.1
|
||||
*/
|
||||
public function _characterData($parser, $data)
|
||||
{
|
||||
$tag = $this->_getLastTag();
|
||||
|
||||
// @todo remove code: if(!isset($this->$tag->_data)) $this->$tag->_data = '';
|
||||
// @todo remove code: $this->$tag->_data .= $data;
|
||||
|
||||
// Throw the data for this item together
|
||||
$tag = strtolower($tag);
|
||||
if (isset($this->currentUpdate->$tag))
|
||||
{
|
||||
$this->currentUpdate->$tag->_data .= $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an XML file from a URL.
|
||||
*
|
||||
* @param string $url The URL.
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function loadFromXML($url)
|
||||
{
|
||||
$http = JHttpFactory::getHttp();
|
||||
$response = $http->get($url);
|
||||
if (200 != $response->code)
|
||||
{
|
||||
// TODO: Add a 'mark bad' setting here somehow
|
||||
JLog::add(JText::sprintf('JLIB_UPDATER_ERROR_EXTENSION_OPEN_URL', $url), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
$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))
|
||||
{
|
||||
die(
|
||||
sprintf(
|
||||
"XML error: %s at line %d", xml_error_string(xml_get_error_code($this->xmlParser)),
|
||||
xml_get_current_line_number($this->xmlParser)
|
||||
)
|
||||
);
|
||||
}
|
||||
xml_parser_free($this->xmlParser);
|
||||
return true;
|
||||
}
|
||||
}
|
74
libraries/joomla/updater/updateadapter.php
Normal file
74
libraries/joomla/updater/updateadapter.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Updater
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.base.adapterinstance');
|
||||
|
||||
/**
|
||||
* UpdateAdapter class.
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Updater
|
||||
* @since 11.1
|
||||
*/
|
||||
class JUpdateAdapter extends JAdapterInstance
|
||||
{
|
||||
/**
|
||||
* @var resource
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $xmlParser;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $stack = array('base');
|
||||
|
||||
/**
|
||||
* ID of update site
|
||||
*
|
||||
* @var string
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $updateSiteId = 0;
|
||||
|
||||
/**
|
||||
* Columns in the extensions table to be updated
|
||||
*
|
||||
* @var array
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $updatecols = array('NAME', 'ELEMENT', 'TYPE', 'FOLDER', 'CLIENT', 'VERSION', 'DESCRIPTION', 'INFOURL');
|
||||
|
||||
/**
|
||||
* Gets the reference to the current direct parent
|
||||
*
|
||||
* @return object
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _getStackLocation()
|
||||
{
|
||||
return implode('->', $this->stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the reference to the last tag
|
||||
*
|
||||
* @return object
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _getLastTag()
|
||||
{
|
||||
return $this->stack[count($this->stack) - 1];
|
||||
}
|
||||
}
|
209
libraries/joomla/updater/updater.php
Normal file
209
libraries/joomla/updater/updater.php
Normal file
@ -0,0 +1,209 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Updater
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.filesystem.file');
|
||||
jimport('joomla.filesystem.folder');
|
||||
jimport('joomla.filesystem.path');
|
||||
jimport('joomla.base.adapter');
|
||||
jimport('joomla.utilities.arrayhelper');
|
||||
|
||||
/**
|
||||
* Updater Class
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Updater
|
||||
* @since 11.1
|
||||
*/
|
||||
class JUpdater extends JAdapter
|
||||
{
|
||||
/**
|
||||
* @var JUpdater JUpdater instance container.
|
||||
* @since 11.3
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Adapter base path, class prefix
|
||||
parent::__construct(__DIR__, 'JUpdater');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the global Installer object, only creating it
|
||||
* if it doesn't already exist.
|
||||
*
|
||||
* @return object An installer object
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (!isset(self::$instance))
|
||||
{
|
||||
self::$instance = new JUpdater;
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an update for an extension
|
||||
*
|
||||
* @param integer $eid Extension Identifier; if zero use all sites
|
||||
* @param integer $cacheTimeout How many seconds to cache update information; if zero, force reload the update information
|
||||
*
|
||||
* @return boolean True if there are updates
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function findUpdates($eid = 0, $cacheTimeout = 0)
|
||||
{
|
||||
|
||||
$db = $this->getDBO();
|
||||
$retval = false;
|
||||
|
||||
// Push it into an array
|
||||
if (!is_array($eid))
|
||||
{
|
||||
$query = 'SELECT DISTINCT update_site_id, type, location, last_check_timestamp FROM #__update_sites WHERE enabled = 1';
|
||||
}
|
||||
else
|
||||
{
|
||||
$query = 'SELECT DISTINCT update_site_id, type, location, last_check_timestamp FROM #__update_sites' .
|
||||
' WHERE update_site_id IN' .
|
||||
' (SELECT update_site_id FROM #__update_sites_extensions WHERE extension_id IN (' . implode(',', $eid) . '))';
|
||||
}
|
||||
$db->setQuery($query);
|
||||
$results = $db->loadAssocList();
|
||||
$result_count = count($results);
|
||||
$now = time();
|
||||
for ($i = 0; $i < $result_count; $i++)
|
||||
{
|
||||
$result = &$results[$i];
|
||||
$this->setAdapter($result['type']);
|
||||
if (!isset($this->_adapters[$result['type']]))
|
||||
{
|
||||
// Ignore update sites requiring adapters we don't have installed
|
||||
continue;
|
||||
}
|
||||
if ($cacheTimeout > 0)
|
||||
{
|
||||
if (isset($result['last_check_timestamp']) && ($now - $result['last_check_timestamp'] <= $cacheTimeout))
|
||||
{
|
||||
// Ignore update sites whose information we have fetched within
|
||||
// the cache time limit
|
||||
$retval = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$update_result = $this->_adapters[$result['type']]->findUpdate($result);
|
||||
if (is_array($update_result))
|
||||
{
|
||||
if (array_key_exists('update_sites', $update_result) && count($update_result['update_sites']))
|
||||
{
|
||||
$results = JArrayHelper::arrayUnique(array_merge($results, $update_result['update_sites']));
|
||||
$result_count = count($results);
|
||||
}
|
||||
if (array_key_exists('updates', $update_result) && count($update_result['updates']))
|
||||
{
|
||||
for ($k = 0, $count = count($update_result['updates']); $k < $count; $k++)
|
||||
{
|
||||
$current_update = &$update_result['updates'][$k];
|
||||
$update = JTable::getInstance('update');
|
||||
$extension = JTable::getInstance('extension');
|
||||
$uid = $update
|
||||
->find(
|
||||
array(
|
||||
'element' => strtolower($current_update->get('element')), 'type' => strtolower($current_update->get('type')),
|
||||
'client_id' => strtolower($current_update->get('client_id')),
|
||||
'folder' => strtolower($current_update->get('folder'))
|
||||
)
|
||||
);
|
||||
|
||||
$eid = $extension
|
||||
->find(
|
||||
array(
|
||||
'element' => strtolower($current_update->get('element')), 'type' => strtolower($current_update->get('type')),
|
||||
'client_id' => strtolower($current_update->get('client_id')),
|
||||
'folder' => strtolower($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'], '>') == 1)
|
||||
{
|
||||
$current_update->extension_id = $eid;
|
||||
$current_update->store();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// A potentially new extension to be installed
|
||||
$current_update->store();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$update->load($uid);
|
||||
|
||||
// If there is an update, check that the version is newer then replaces
|
||||
if (version_compare($current_update->version, $update->version, '>') == 1)
|
||||
{
|
||||
$current_update->store();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, update the last update check timestamp
|
||||
$query = $db->getQuery(true)
|
||||
->update($db->quoteName('#__update_sites'))
|
||||
->set($db->quoteName('last_check_timestamp') . ' = ' . $db->quote($now))
|
||||
->where($db->quoteName('update_site_id') . ' = ' . $db->quote($result['update_site_id']));
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
}
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an update for an extension
|
||||
*
|
||||
* @param integer $id Id of the extension
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function update($id)
|
||||
{
|
||||
$updaterow = JTable::getInstance('update');
|
||||
$updaterow->load($id);
|
||||
$update = new JUpdate;
|
||||
if ($update->loadFromXML($updaterow->detailsurl))
|
||||
{
|
||||
return $update->install();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user