From b1701dd06beee86acf86654bb224137101efae5f Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Tue, 23 Dec 2014 19:38:01 +0100 Subject: [PATCH] Overhauled package update server API --- .../server/PackageUpdateServer.class.php | 67 ++++++++++++++++--- .../PackageInstallationScheduler.class.php | 2 +- .../package/PackageUpdateDispatcher.class.php | 58 ++++++++++------ wcfsetup/install/files/style/redactor.less | 4 ++ wcfsetup/setup/db/install.sql | 3 +- 5 files changed, 101 insertions(+), 33 deletions(-) diff --git a/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServer.class.php b/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServer.class.php index 9542942612..024b7c3708 100644 --- a/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServer.class.php +++ b/wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServer.class.php @@ -1,10 +1,10 @@ metaData = $metaData; + } + + unset($data['metaData']); + } + + parent::handleData($data); + } + /** * Returns all active update package servers sorted by hostname. * @@ -139,7 +161,7 @@ class PackageUpdateServer extends DatabaseObject { } /** - * Returns the list URL for package servers. + * Returns the list endpoint for package servers. * * @return string */ @@ -149,14 +171,39 @@ class PackageUpdateServer extends DatabaseObject { } $serverURL = FileUtil::addTrailingSlash($this->serverURL) . 'list/' . WCF::getLanguage()->getFixedLanguageCode() . '.xml'; - $serverURL = preg_replace_callback('~^https?://~', function($matches) { - if (RemoteFile::supportsSSL()) { - return 'https://'; - } - - return 'http://'; - }, $serverURL); - return $serverURL; + $metaData = $this->getMetaData(); + if (!RemoteFile::supportsSSL() || !$metaData['ssl']) { + return preg_replace('~^https://~', 'http://', $serverURL); + } + + return preg_replace('~^http://~', 'https://', $serverURL); + } + + /** + * Returns the download endpoint for package servers. + * + * @return string + */ + public function getDownloadURL() { + if ($this->apiVersion == '2.0') { + return $this->serverURL; + } + + $metaData = $this->getMetaData(); + if (!RemoteFile::supportsSSL() || !$metaData['ssl']) { + return preg_replace('~^https://~', 'http://', $this->serverURL); + } + + return preg_replace('~^http://~', 'https://', $this->serverURL); + } + + /** + * Returns API meta data. + * + * @return array + */ + public function getMetaData() { + return $this->metaData; } } diff --git a/wcfsetup/install/files/lib/system/package/PackageInstallationScheduler.class.php b/wcfsetup/install/files/lib/system/package/PackageInstallationScheduler.class.php index c1dfef4147..623a874e46 100644 --- a/wcfsetup/install/files/lib/system/package/PackageInstallationScheduler.class.php +++ b/wcfsetup/install/files/lib/system/package/PackageInstallationScheduler.class.php @@ -230,7 +230,7 @@ class PackageInstallationScheduler { else { // create request $request = new HTTPRequest( - $this->packageUpdateServers[$packageUpdateVersion['packageUpdateServerID']]->serverURL, + $this->packageUpdateServers[$packageUpdateVersion['packageUpdateServerID']]->getDownloadURL(), (!empty($authData) ? array('auth' => $authData) : array()), array( 'apiVersion' => PackageUpdate::API_VERSION, diff --git a/wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php b/wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php index 31bd9afc45..880e81d74f 100644 --- a/wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php +++ b/wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php @@ -79,10 +79,8 @@ class PackageUpdateDispatcher extends SingletonFactory { */ protected function getPackageUpdateXML(PackageUpdateServer $updateServer) { $settings = array(); - if ($updateServer->apiVersion == '2.0') { - $authData = $updateServer->getAuthData(); - if ($authData) $settings['auth'] = $authData; - } + $authData = $updateServer->getAuthData(); + if ($authData) $settings['auth'] = $authData; // append auth code if set and update server resolves to woltlab.com /*if (PACKAGE_SERVER_AUTH_CODE && Regex::compile('^https?://[a-z]+.woltlab.com/')->match($updateServer->serverURL)) { @@ -91,9 +89,18 @@ class PackageUpdateDispatcher extends SingletonFactory { $request = new HTTPRequest($updateServer->getListURL(), $settings); + if ($updateServer->apiVersion == '2.1') { + $metaData = $updateServer->getMetaData(); + if (!empty($metaData['list'])) { + $request->addHeader('if-none-match', $metaData['list']['etag']); + $request->addHeader('if-modified-since', $metaData['list']['lastModified']); + } + } + try { $request->execute(); $reply = $request->getReply(); + //die("
".print_r($request, true));
 		}
 		catch (HTTPUnauthorizedException $e) {
 			throw new PackageUpdateUnauthorizedException($request, $updateServer);
@@ -104,9 +111,12 @@ class PackageUpdateDispatcher extends SingletonFactory {
 			$statusCode = (is_array($reply['statusCode'])) ? reset($reply['statusCode']) : $reply['statusCode'];
 			throw new SystemException(WCF::getLanguage()->get('wcf.acp.package.update.error.listNotFound') . ' ('.$statusCode.')');
 		}
-		
+		//echo "
" . $updateServer->getListURL() . ": " . ((is_array($reply['statusCode'])) ? reset($reply['statusCode']) : $reply['statusCode']) . "
"; // parse given package update xml - $allNewPackages = $this->parsePackageUpdateXML($updateServer, $reply['body']); + $allNewPackages = false; + if ($updateServer->apiVersion == '2.0' || $reply['statusCode'] != 304) { + $allNewPackages = $this->parsePackageUpdateXML($reply['body']); + } $data = array( 'lastUpdateTime' => TIME_NOW, @@ -122,6 +132,23 @@ class PackageUpdateDispatcher extends SingletonFactory { } } + $metaData = array(); + if ($updateServer->apiVersion == '2.1' || (isset($data['apiVersion']) && $data['apiVersion'] == '2.1')) { + if (empty($reply['httpHeaders']['etag']) || empty($reply['httpHeaders']['last-modified'])) { + throw new SystemException("Missing required HTTP headers 'etag' and/or 'last-modified'."); + } + else if (empty($reply['httpHeaders']['wcf-update-server-ssl'])) { + throw new SystemException("Missing required HTTP header 'wcf-update-server-ssl'."); + } + + $metaData['list'] = array( + 'etag' => reset($reply['httpHeaders']['etag']), + 'lastModified' => reset($reply['httpHeaders']['last-modified']) + ); + $metaData['ssl'] = (reset($reply['httpHeaders']['wcf-update-server-ssl']) == 'true') ? true : false; + } + $data['metaData'] = serialize($metaData); + unset($request, $reply); if ($allNewPackages !== false) { @@ -144,28 +171,17 @@ class PackageUpdateDispatcher extends SingletonFactory { } /** - * Parses a stream containing info from a packages_update.xml, returns false if package list - * has not changed since last update. + * Parses a stream containing info from a packages_update.xml. * - * @param \wcf\data\package\update\server\PackageUpdateServer $updateServer - * @param string $content - * @return array $allNewPackages + * @param string $content + * @return array $allNewPackages */ - protected function parsePackageUpdateXML(PackageUpdateServer $updateServer, $content) { + protected function parsePackageUpdateXML($content) { // load xml document $xml = new XML(); $xml->loadXML('packageUpdateServer.xml', $content); $xpath = $xml->xpath(); - // loop through tags inside the
tag. - $section = $xpath->query('/ns:section'); - if ($section->item(0)->hasAttribute('lastUpdateTime')) { - $lastUpdateTime = intval($section->item(0)->getAttribute('lastUpdateTime')); - if ($lastUpdateTime && $updateServer->lastUpdateTime > $lastUpdateTime) { - return false; - } - } - $allNewPackages = array(); $packages = $xpath->query('/ns:section/ns:package'); foreach ($packages as $package) { diff --git a/wcfsetup/install/files/style/redactor.less b/wcfsetup/install/files/style/redactor.less index 623e9c6ac3..8ebc2f9ac6 100644 --- a/wcfsetup/install/files/style/redactor.less +++ b/wcfsetup/install/files/style/redactor.less @@ -247,6 +247,10 @@ &.redactor-btn-image { background-position: center; background-repeat: no-repeat; + + &.redactor-button-disabled { + opacity: .5; + } } } } diff --git a/wcfsetup/setup/db/install.sql b/wcfsetup/setup/db/install.sql index e951c2f207..645a267f15 100644 --- a/wcfsetup/setup/db/install.sql +++ b/wcfsetup/setup/db/install.sql @@ -760,7 +760,8 @@ CREATE TABLE wcf1_package_update_server ( lastUpdateTime INT(10) NOT NULL DEFAULT 0, status ENUM('online', 'offline') NOT NULL DEFAULT 'online', errorMessage TEXT, - apiVersion ENUM('2.0', '2.1') NOT NULL DEFAULT '2.0' + apiVersion ENUM('2.0', '2.1') NOT NULL DEFAULT '2.0', + metaData TEXT ); DROP TABLE IF EXISTS wcf1_package_update_version; -- 2.20.1