diff --git a/administrator/components/com_installer/models/update.php b/administrator/components/com_installer/models/update.php index e1bbde987e7ee..de722577c75d3 100644 --- a/administrator/components/com_installer/models/update.php +++ b/administrator/components/com_installer/models/update.php @@ -405,7 +405,8 @@ private function install($update) return false; } - $url = $update->downloadurl->_data; + $url = $update->downloadurl->_data; + $sources = $update->get('downloadSources', array()); if ($extra_query = $update->get('extra_query')) { @@ -413,7 +414,21 @@ private function install($update) $url .= $extra_query; } - $p_file = JInstallerHelper::downloadPackage($url); + $mirror = 0; + + while (!($p_file = JInstallerHelper::downloadPackage($url)) && isset($sources[$mirror])) + { + $name = $sources[$mirror]; + $url = $name->url; + + if ($extra_query) + { + $url .= (strpos($url, '?') === false) ? '?' : '&'; + $url .= $extra_query; + } + + $mirror++; + } // Was the package downloaded? if (!$p_file) diff --git a/administrator/components/com_joomlaupdate/models/default.php b/administrator/components/com_joomlaupdate/models/default.php index 106c9804e7aed..91634a88fa9cf 100644 --- a/administrator/components/com_joomlaupdate/models/default.php +++ b/administrator/components/com_joomlaupdate/models/default.php @@ -251,6 +251,7 @@ public function download() { $updateInfo = $this->getUpdateInformation(); $packageURL = $updateInfo['object']->downloadurl->_data; + $sources = $updateInfo['object']->get('downloadSources', array()); $headers = get_headers($packageURL, 1); // Follow the Location headers until the actual download URL is known @@ -279,7 +280,16 @@ public function download() if (!$exists) { // Not there, let's fetch it. - return $this->downloadPackage($packageURL, $target); + $mirror = 0; + + while (!($download = $this->downloadPackage($packageURL, $target)) && isset($sources[$mirror])) + { + $name = $sources[$mirror]; + $packageURL = $name->url; + $mirror++; + } + + return $download; } else { @@ -288,7 +298,16 @@ public function download() if (empty($filesize)) { - return $this->downloadPackage($packageURL, $target); + $mirror = 0; + + while (!($download = $this->downloadPackage($packageURL, $target)) && isset($sources[$mirror])) + { + $name = $sources[$mirror]; + $packageURL = $name->url; + $mirror++; + } + + return $download; } // Yes, it's there, skip downloading. @@ -335,7 +354,15 @@ protected function downloadPackage($url, $target) JFile::delete($target); // Download the package - $result = $http->get($url); + try + { + $result = $http->get($url); + } + catch (RuntimeException $e) + { + return false; + } + if (!$result || ($result->code != 200 && $result->code != 310)) { diff --git a/libraries/src/Updater/DownloadSource.php b/libraries/src/Updater/DownloadSource.php new file mode 100644 index 0000000000000..f352073c9d915 --- /dev/null +++ b/libraries/src/Updater/DownloadSource.php @@ -0,0 +1,59 @@ +` element + * + * @since __DEPLOY_VERSION__ + */ +class DownloadSource +{ + /** + * Defines a ZIP download package + * + * @const string + * @since __DEPLOY_VERSION__ + */ + const FORMAT_ZIP = 'zip'; + + /** + * Defines a full package download type + * + * @const string + * @since __DEPLOY_VERSION__ + */ + const TYPE_FULL = 'full'; + + /** + * The download type + * + * @var string + * @since __DEPLOY_VERSION__ + */ + public $type = self::TYPE_FULL; + + /** + * The download file's format + * + * @var string + * @since __DEPLOY_VERSION__ + */ + public $format = self::FORMAT_ZIP; + + /** + * The URL to retrieve the package from + * + * @var string + * @since __DEPLOY_VERSION__ + */ + public $url; +} diff --git a/libraries/src/Updater/Update.php b/libraries/src/Updater/Update.php index dced0de77cf75..6eb1eba809a3a 100644 --- a/libraries/src/Updater/Update.php +++ b/libraries/src/Updater/Update.php @@ -97,6 +97,14 @@ class Update extends \JObject */ protected $downloads; + /** + * Update manifest `` elements + * + * @var DownloadSource[] + * @since __DEPLOY_VERSION__ + */ + protected $downloadSources = array(); + /** * Update manifest `` element * @@ -262,6 +270,20 @@ public function _startElement($parser, $name, $attrs = array()) $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; @@ -437,6 +459,15 @@ public function _characterData($parser, $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;