Updated implementation for package update servers
authorAlexander Ebert <ebert@woltlab.com>
Sun, 21 Dec 2014 18:08:26 +0000 (19:08 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Sun, 21 Dec 2014 18:08:26 +0000 (19:08 +0100)
wcfsetup/install/files/lib/data/package/update/server/PackageUpdateServer.class.php
wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php
wcfsetup/setup/db/install.sql

index f6ec7196bc1586cde6a0e927a9cf435765104c77..9542942612703655479b0bc5e0f82974c0f959d4 100644 (file)
@@ -3,6 +3,8 @@ namespace wcf\data\package\update\server;
 use wcf\data\DatabaseObject;
 use wcf\system\Regex;
 use wcf\system\WCF;
+use wcf\util\FileUtil;
+use wcf\system\io\RemoteFile;
 
 /**
  * Represents a package update server.
@@ -135,4 +137,26 @@ class PackageUpdateServer extends DatabaseObject {
                $host = parse_url($this->serverURL, PHP_URL_HOST);
                return str_replace($host, '<strong>'.$host.'</strong>', $this->serverURL);
        }
+       
+       /**
+        * Returns the list URL for package servers.
+        * 
+        * @return      string
+        */
+       public function getListURL() {
+               if ($this->apiVersion == '2.0') {
+                       return $this->serverURL;
+               }
+               
+               $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;
+       }
 }
index 8b6268217346d356b6bb1f5e20d773b082a6a024..31bd9afc455c0963b253f43a911facce6593cd56 100644 (file)
@@ -78,21 +78,18 @@ class PackageUpdateDispatcher extends SingletonFactory {
         * @param       \wcf\data\package\update\server\PackageUpdateServer     $updateServer
         */
        protected function getPackageUpdateXML(PackageUpdateServer $updateServer) {
-               $authData = $updateServer->getAuthData();
                $settings = array();
-               if ($authData) $settings['auth'] = $authData;
-               
-               $postData = array(
-                       'apiVersion' => PackageUpdate::API_VERSION,
-                       'lastUpdateTime' => $updateServer->lastUpdateTime
-               );
+               if ($updateServer->apiVersion == '2.0') {
+                       $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)) {
+               /*if (PACKAGE_SERVER_AUTH_CODE && Regex::compile('^https?://[a-z]+.woltlab.com/')->match($updateServer->serverURL)) {
                        $postData['authCode'] = PACKAGE_SERVER_AUTH_CODE;
-               }
+               }*/
                
-               $request = new HTTPRequest($updateServer->serverURL, $settings, $postData);
+               $request = new HTTPRequest($updateServer->getListURL(), $settings);
                
                try {
                        $request->execute();
@@ -109,43 +106,66 @@ class PackageUpdateDispatcher extends SingletonFactory {
                }
                
                // parse given package update xml
-               $allNewPackages = $this->parsePackageUpdateXML($reply['body']);
-               unset($request, $reply);
+               $allNewPackages = $this->parsePackageUpdateXML($updateServer, $reply['body']);
                
-               // purge package list
-               $sql = "DELETE FROM     wcf".WCF_N."_package_update
-                       WHERE           packageUpdateServerID = ?";
-               $statement = WCF::getDB()->prepareStatement($sql);
-               $statement->execute(array($updateServer->packageUpdateServerID));
+               $data = array(
+                       'lastUpdateTime' => TIME_NOW,
+                       'status' => 'online',
+                       'errorMessage' => ''
+               );
+               
+               // check if server indicates support for a newer API
+               if ($updateServer->apiVersion == '2.0' && !empty($reply['httpHeaders']['wcf-update-server-api'])) {
+                       $apiVersions = explode(' ', reset($reply['httpHeaders']['wcf-update-server-api']));
+                       if (in_array('2.1', $apiVersions)) {
+                               $data['apiVersion'] = '2.1';
+                       }
+               }
                
-               // save packages
-               if (!empty($allNewPackages)) {
-                       $this->savePackageUpdates($allNewPackages, $updateServer->packageUpdateServerID);
+               unset($request, $reply);
+               
+               if ($allNewPackages !== false) {
+                       // purge package list
+                       $sql = "DELETE FROM     wcf".WCF_N."_package_update
+                               WHERE           packageUpdateServerID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array($updateServer->packageUpdateServerID));
+                       
+                       // save packages
+                       if (!empty($allNewPackages)) {
+                               $this->savePackageUpdates($allNewPackages, $updateServer->packageUpdateServerID);
+                       }
+                       unset($allNewPackages);
                }
-               unset($allNewPackages);
                
                // update server status
                $updateServerEditor = new PackageUpdateServerEditor($updateServer);
-               $updateServerEditor->update(array(
-                       'lastUpdateTime' => TIME_NOW,
-                       'status' => 'online',
-                       'errorMessage' => ''
-               ));
+               $updateServerEditor->update($data);
        }
        
        /**
-        * Parses a stream containing info from a packages_update.xml.
+        * Parses a stream containing info from a packages_update.xml, returns false if package list
+        * has not changed since last update.
         * 
-        * @param       string          $content
-        * @return      array           $allNewPackages
+        * @param       \wcf\data\package\update\server\PackageUpdateServer     $updateServer
+        * @param       string                                                  $content
+        * @return      array                                                   $allNewPackages
         */
-       protected function parsePackageUpdateXML($content) {
+       protected function parsePackageUpdateXML(PackageUpdateServer $updateServer, $content) {
                // load xml document
                $xml = new XML();
                $xml->loadXML('packageUpdateServer.xml', $content);
                $xpath = $xml->xpath();
                
                // loop through <package> tags inside the <section> 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) {
index 5684f29ca30a3e93b50a3c30315f7320434c7bf7..e951c2f20771d09a5ca6c01dd53d0ef4d75dfad6 100644 (file)
@@ -759,7 +759,8 @@ CREATE TABLE wcf1_package_update_server (
        isDisabled TINYINT(1) NOT NULL DEFAULT 0,
        lastUpdateTime INT(10) NOT NULL DEFAULT 0,
        status ENUM('online', 'offline') NOT NULL DEFAULT 'online',
-       errorMessage TEXT
+       errorMessage TEXT,
+       apiVersion ENUM('2.0', '2.1') NOT NULL DEFAULT '2.0'
 );
 
 DROP TABLE IF EXISTS wcf1_package_update_version;