Added support for auth code
authorAlexander Ebert <ebert@woltlab.com>
Mon, 8 Aug 2016 11:01:33 +0000 (13:01 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 8 Aug 2016 11:02:12 +0000 (13:02 +0200)
com.woltlab.wcf/option.xml
wcfsetup/install/files/acp/js/WCF.ACP.js
wcfsetup/install/files/lib/system/package/PackageUpdateDispatcher.class.php

index eafc8535604402079d622ec4ddb369d1ffa37c80..a04d6633a4f35aae3c73c238e25977020a714581 100644 (file)
@@ -555,7 +555,6 @@ private:wcf.acp.option.exception_privacy.private</selectoptions>
                        <option name="package_server_auth_code">
                                <categoryname>general.system.packageServer</categoryname>
                                <optiontype>text</optiontype>
-                               <hidden>1</hidden>
                        </option>
                        <!-- /general.system.packageServer -->
                        
index c1a8b12697ff8619c4b9c22d12e41ebec44e3346..710769e457081d05107a4b8545a636b5db17b814 100644 (file)
@@ -1384,7 +1384,7 @@ WCF.ACP.Package.Update.Search = Class.extend({
                }
                else {
                        var $button = $('<li><a class="button"><span class="icon icon16 fa-refresh"></span> <span>' + WCF.Language.get('wcf.acp.package.searchForUpdates') + '</span></a></li>');
-                       $button.click($.proxy(this._click, this)).prependTo($('.contentNavigation:eq(0) > nav:not(.pagination) > ul'));
+                       $button.click(this._click.bind(this)).prependTo($('.contentHeaderNavigation > ul'));
                }
        },
        
index d7c8997db8120b35aa66422556ce73a48d98834b..ccaa775a047463bc77e94a495b56f445972a7a4d 100644 (file)
@@ -13,6 +13,7 @@ use wcf\system\io\RemoteFile;
 use wcf\system\SingletonFactory;
 use wcf\system\WCF;
 use wcf\util\HTTPRequest;
+use wcf\util\JSON;
 use wcf\util\XML;
 
 /**
@@ -24,6 +25,12 @@ use wcf\util\XML;
  * @package    WoltLabSuite\Core\System\Package
  */
 class PackageUpdateDispatcher extends SingletonFactory {
+       protected $hasAuthCode = false;
+       protected $purchasedVersions = [
+               'woltlab' => [],
+               'pluginstore' => []
+       ];
+       
        /**
         * Refreshes the package database.
         * 
@@ -37,20 +44,29 @@ class PackageUpdateDispatcher extends SingletonFactory {
                // loop servers
                $updateServers = [];
                $foundWoltLabServer = false;
+               $requirePurchasedVersions = false;
                foreach ($tmp as $updateServer) {
                        if ($ignoreCache || $updateServer->lastUpdateTime < TIME_NOW - 600) {
-                               // try to queue a woltlab.com update server first to probe for SSL support
-                               if (!$foundWoltLabServer && preg_match('~^https?://(?:update|store)\.woltlab\.com~', $updateServer->serverURL)) {
-                                       array_unshift($updateServers, $updateServer);
-                                       $foundWoltLabServer = true;
+                               if (preg_match('~^https?://(?:update|store)\.woltlab\.com~', $updateServer->serverURL)) {
+                                       $requirePurchasedVersions = true;
                                        
-                                       continue;
+                                       // move a woltlab.com update server to the front of the queue to probe for SSL support
+                                       if (!$foundWoltLabServer) {
+                                               array_unshift($updateServers, $updateServer);
+                                               $foundWoltLabServer = true;
+                                               
+                                               continue;
+                                       }
                                }
                                
                                $updateServers[] = $updateServer;
                        }
                }
                
+               if ($requirePurchasedVersions && PACKAGE_SERVER_AUTH_CODE) {
+                       $this->getPurchasedVersions();
+               }
+               
                // loop servers
                $refreshedPackageLists = false;
                foreach ($updateServers as $updateServer) {
@@ -83,6 +99,33 @@ class PackageUpdateDispatcher extends SingletonFactory {
                }
        }
        
+       protected function getPurchasedVersions() {
+               if (!RemoteFile::supportsSSL()) {
+                       return;
+               }
+               
+               $request = new HTTPRequest(
+                       'https://api.woltlab.com/1.0/customer/license/list.json',
+                       ['timeout' => 5],
+                       ['authCode' => PACKAGE_SERVER_AUTH_CODE]
+               );
+               
+               try {
+                       $request->execute();
+                       $reply = JSON::decode($request->getReply()['body']);
+                       if ($reply['status'] == 200) {
+                               $this->hasAuthCode = true;
+                               $this->purchasedVersions = [
+                                       'woltlab' => (isset($reply['woltlab']) ? $reply['woltlab'] : []),
+                                       'pluginstore' => (isset($reply['pluginstore']) ? $reply['pluginstore'] : [])
+                               ];
+                       }
+               }
+               catch (SystemException $e) {
+                       // ignore
+               }
+       }
+       
        /**
         * Fetches the package_update.xml from an update server.
         * 
@@ -136,7 +179,7 @@ class PackageUpdateDispatcher extends SingletonFactory {
                // parse given package update xml
                $allNewPackages = false;
                if ($updateServer->apiVersion == '2.0' || $reply['statusCode'] != 304) {
-                       $allNewPackages = $this->parsePackageUpdateXML($reply['body']);
+                       $allNewPackages = $this->parsePackageUpdateXML($updateServer, $reply['body']);
                }
                
                $data = [
@@ -194,11 +237,12 @@ class PackageUpdateDispatcher extends SingletonFactory {
        /**
         * Parses a stream containing info from a packages_update.xml.
         * 
-        * @param       string          $content
-        * @return      array
-        * @throws      SystemException
+        * @param       PackageUpdateServer     $updateServer
+        * @param       string                  $content
+        * @return      array
+        * @throws      SystemException
         */
-       protected function parsePackageUpdateXML($content) {
+       protected function parsePackageUpdateXML(PackageUpdateServer $updateServer, $content) {
                // load xml document
                $xml = new XML();
                $xml->loadXML('packageUpdateServer.xml', $content);
@@ -206,25 +250,27 @@ class PackageUpdateDispatcher extends SingletonFactory {
                
                $allNewPackages = [];
                $packages = $xpath->query('/ns:section/ns:package');
+               /** @var \DOMElement $package */
                foreach ($packages as $package) {
                        if (!Package::isValidPackageName($package->getAttribute('name'))) {
                                throw new SystemException("'".$package->getAttribute('name')."' is not a valid package name.");
                        }
                        
-                       $allNewPackages[$package->getAttribute('name')] = $this->parsePackageUpdateXMLBlock($xpath, $package);
+                       $allNewPackages[$package->getAttribute('name')] = $this->parsePackageUpdateXMLBlock($updateServer, $xpath, $package);
                }
                
                return $allNewPackages;
        }
        
        /**
-        * Parses the xml stucture from a packages_update.xml.
+        * Parses the xml structure from a packages_update.xml.
         * 
-        * @param       \DOMXPath       $xpath
-        * @param       \DOMNode        $package
-        * @return      array
+        * @param       PackageUpdateServer     $updateServer
+        * @param       \DOMXPath               $xpath
+        * @param       \DOMElement             $package
+        * @return      array
         */
-       protected function parsePackageUpdateXMLBlock(\DOMXPath $xpath, \DOMNode $package) {
+       protected function parsePackageUpdateXMLBlock(PackageUpdateServer $updateServer, \DOMXPath $xpath, \DOMElement $package) {
                // define default values
                $packageInfo = [
                        'author' => '',
@@ -266,15 +312,42 @@ class PackageUpdateDispatcher extends SingletonFactory {
                        }
                }
                
+               $key = '';
+               if ($this->hasAuthCode) {
+                       if (preg_match('~^https?://update\.woltlab\.com~', $updateServer->serverURL)) {
+                               $key = 'woltlab';
+                       }
+                       else if (preg_match('~^https?://store\.woltlab\.com~', $updateServer->serverURL)) {
+                               $key = 'pluginstore';
+                       }
+               }
+               
                // parse versions
                $elements = $xpath->query('./ns:versions/ns:version', $package);
+               /** @var \DOMElement $element */
                foreach ($elements as $element) {
                        $versionNo = $element->getAttribute('name');
-                       $packageInfo['versions'][$versionNo] = [
-                               'isAccessible' => $element->getAttribute('accessible') == 'true' ? true : false
-                       ];
+                       
+                       $isAccessible = ($element->getAttribute('accessible') == 'true') ? 1 : 0;
+                       if ($key && $element->getAttribute('requireAuth') == 'true') {
+                               $packageName = $package->getAttribute('name');
+                               if (isset($this->purchasedVersions[$key][$packageName])) {
+                                       if ($this->purchasedVersions[$key][$packageName] == '*') {
+                                               $isAccessible = 1;
+                                       }
+                                       else {
+                                               $isAccessible = (Package::compareVersion($versionNo, $this->purchasedVersions[$key][$packageName] . '99', '<=') ? 1 : 0);
+                                       }
+                               }
+                               else {
+                                       $isAccessible = 0;
+                               }
+                       }
+                       
+                       $packageInfo['versions'][$versionNo] = ['isAccessible' => $isAccessible];
                        
                        $children = $xpath->query('child::*', $element);
+                       /** @var \DOMElement $child */
                        foreach ($children as $child) {
                                switch ($child->tagName) {
                                        case 'fromversions':
@@ -318,6 +391,7 @@ class PackageUpdateDispatcher extends SingletonFactory {
                                        
                                        case 'excludedpackages':
                                                $excludedpackages = $xpath->query('child::*', $child);
+                                               /** @var \DOMElement $excludedPackage */
                                                foreach ($excludedpackages as $excludedPackage) {
                                                        $exclusion = $excludedPackage->nodeValue;
                                                        $version = $excludedPackage->getAttribute('version');