/**
  * @see	\wcf\form\IForm::validate()
  */
 public function validate()
 {
     parent::validate();
     if (empty($this->server)) {
         throw new UserInputException('server');
     }
     if (!PackageUpdateServer::isValidServerURL($this->server)) {
         throw new UserInputException('server', 'notValid');
     }
 }
 /**
  * Returns a list of available updates for installed packages.
  * 
  * @param	boolean		$removeRequirements
  * @return 	array
  */
 public static function getAvailableUpdates($removeRequirements = true)
 {
     $updates = array();
     // get update server data
     $updateServers = PackageUpdateServer::getActiveUpdateServers();
     $packageUpdateServerIDs = array_keys($updateServers);
     if (empty($packageUpdateServerIDs)) {
         return $updates;
     }
     // get existing packages and their versions
     $existingPackages = array();
     $sql = "SELECT\tpackageID, package, instanceNo, packageDescription,\n\t\t\t\tpackageVersion, packageDate, author, authorURL, isApplication,\n\t\t\t\tCASE WHEN instanceName <> '' THEN instanceName ELSE packageName END AS packageName\n\t\t\tFROM\twcf" . WCF_N . "_package";
     $statement = WCF::getDB()->prepareStatement($sql);
     $statement->execute();
     while ($row = $statement->fetchArray()) {
         $existingPackages[$row['package']][] = $row;
     }
     if (empty($existingPackages)) {
         return $updates;
     }
     // get all update versions
     $conditions = new PreparedStatementConditionBuilder();
     $conditions->add("pu.packageUpdateServerID IN (?)", array($packageUpdateServerIDs));
     $conditions->add("package IN (SELECT DISTINCT package FROM wcf" . WCF_N . "_package)");
     $sql = "SELECT\t\tpu.packageUpdateID, pu.packageUpdateServerID, pu.package,\n\t\t\t\t\tpuv.packageUpdateVersionID, puv.updateType, puv.packageDate, puv.filename, puv.packageVersion\n\t\t\tFROM\t\twcf" . WCF_N . "_package_update pu\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update_version puv\n\t\t\tON\t\t(puv.packageUpdateID = pu.packageUpdateID)\n\t\t\t" . $conditions;
     $statement = WCF::getDB()->prepareStatement($sql);
     $statement->execute($conditions->getParameters());
     while ($row = $statement->fetchArray()) {
         // test version
         foreach ($existingPackages[$row['package']] as $existingVersion) {
             if (Package::compareVersion($existingVersion['packageVersion'], $row['packageVersion'], '<')) {
                 // package data
                 if (!isset($updates[$existingVersion['packageID']])) {
                     $existingVersion['versions'] = array();
                     $updates[$existingVersion['packageID']] = $existingVersion;
                 }
                 // version data
                 if (!isset($updates[$existingVersion['packageID']]['versions'][$row['packageVersion']])) {
                     $updates[$existingVersion['packageID']]['versions'][$row['packageVersion']] = array('updateType' => $row['updateType'], 'packageDate' => $row['packageDate'], 'packageVersion' => $row['packageVersion'], 'servers' => array());
                 }
                 // server data
                 $updates[$existingVersion['packageID']]['versions'][$row['packageVersion']]['servers'][] = array('packageUpdateID' => $row['packageUpdateID'], 'packageUpdateServerID' => $row['packageUpdateServerID'], 'packageUpdateVersionID' => $row['packageUpdateVersionID'], 'filename' => $row['filename']);
             }
         }
     }
     // sort package versions
     // and remove old versions
     foreach ($updates as $packageID => $data) {
         uksort($updates[$packageID]['versions'], array('Package', 'compareVersion'));
         $updates[$packageID]['version'] = end($updates[$packageID]['versions']);
     }
     // remove requirements of application packages
     if ($removeRequirements) {
         foreach ($existingPackages as $identifier => $instances) {
             foreach ($instances as $instance) {
                 if ($instance['isApplication'] && isset($updates[$instance['packageID']])) {
                     $updates = self::removeUpdateRequirements($updates, $updates[$instance['packageID']]['version']['servers'][0]['packageUpdateVersionID']);
                 }
             }
         }
     }
     return $updates;
 }
 /**
  * Creates a new package installation queue.
  * 
  * @param	string		$queueType
  * @return	array
  */
 protected function createQueue($queueType)
 {
     if (isset($this->parameters['authData'])) {
         PackageUpdateServer::storeAuthData($this->parameters['authData']['packageUpdateServerID'], $this->parameters['authData']['username'], $this->parameters['authData']['password'], $this->parameters['authData']['saveCredentials']);
     }
     $scheduler = new PackageInstallationScheduler($this->parameters['packages']);
     try {
         $scheduler->buildPackageInstallationStack($queueType == 'install');
     } catch (PackageUpdateUnauthorizedException $e) {
         return array('template' => $e->getRenderedTemplate());
     }
     // validate exclusions
     if ($queueType == 'update') {
         $excludedPackages = $scheduler->getExcludedPackages();
         if (!empty($excludedPackages)) {
             return array('excludedPackages' => true, 'template' => WCF::getTPL()->fetch('packageUpdateExcludedPackages', 'wcf', array('excludedPackages' => $excludedPackages)));
         }
     }
     $stack = $scheduler->getPackageInstallationStack();
     $queueID = null;
     if (!empty($stack)) {
         $parentQueueID = 0;
         $processNo = PackageInstallationQueue::getNewProcessNo();
         foreach ($stack as $package) {
             $queue = PackageInstallationQueueEditor::create(array('parentQueueID' => $parentQueueID, 'processNo' => $processNo, 'userID' => WCF::getUser()->userID, 'package' => $package['package'], 'packageName' => $package['packageName'], 'packageID' => $package['packageID'] ?: null, 'archive' => $package['archive'], 'action' => $package['action']));
             $parentQueueID = $queue->queueID;
             if ($queueID === null) {
                 $queueID = $queue->queueID;
             }
         }
     }
     return array('queueID' => $queueID);
 }
 /**
  * Gets stored auth data of given update server.
  * 
  * @param	array		$updateServer
  * @return	array		$authData
  */
 protected function getAuthData(array $data)
 {
     $updateServer = new PackageUpdateServer(null, $data);
     return $updateServer->getAuthData();
 }
 /**
  * Returns a list of available updates for installed packages.
  * 
  * @param	boolean		$removeRequirements
  * @param	boolean		$removeOlderMinorReleases
  * @return	array
  */
 public function getAvailableUpdates($removeRequirements = true, $removeOlderMinorReleases = false)
 {
     $updates = array();
     // get update server data
     $updateServers = PackageUpdateServer::getActiveUpdateServers();
     $packageUpdateServerIDs = array_keys($updateServers);
     if (empty($packageUpdateServerIDs)) {
         return $updates;
     }
     // get existing packages and their versions
     $existingPackages = array();
     $sql = "SELECT\tpackageID, package, packageDescription, packageName,\n\t\t\t\tpackageVersion, packageDate, author, authorURL, isApplication\n\t\t\tFROM\twcf" . WCF_N . "_package";
     $statement = WCF::getDB()->prepareStatement($sql);
     $statement->execute();
     while ($row = $statement->fetchArray()) {
         $existingPackages[$row['package']][] = $row;
     }
     if (empty($existingPackages)) {
         return $updates;
     }
     // get all update versions
     $conditions = new PreparedStatementConditionBuilder();
     $conditions->add("pu.packageUpdateServerID IN (?)", array($packageUpdateServerIDs));
     $conditions->add("package IN (SELECT DISTINCT package FROM wcf" . WCF_N . "_package)");
     $sql = "SELECT\t\tpu.packageUpdateID, pu.packageUpdateServerID, pu.package,\n\t\t\t\t\tpuv.packageUpdateVersionID, puv.isCritical, puv.packageDate, puv.filename, puv.packageVersion\n\t\t\tFROM\t\twcf" . WCF_N . "_package_update pu\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update_version puv\n\t\t\tON\t\t(puv.packageUpdateID = pu.packageUpdateID AND puv.isAccessible = 1)\n\t\t\t" . $conditions;
     $statement = WCF::getDB()->prepareStatement($sql);
     $statement->execute($conditions->getParameters());
     while ($row = $statement->fetchArray()) {
         // test version
         foreach ($existingPackages[$row['package']] as $existingVersion) {
             if (Package::compareVersion($existingVersion['packageVersion'], $row['packageVersion'], '<')) {
                 // package data
                 if (!isset($updates[$existingVersion['packageID']])) {
                     $existingVersion['versions'] = array();
                     $updates[$existingVersion['packageID']] = $existingVersion;
                 }
                 // version data
                 if (!isset($updates[$existingVersion['packageID']]['versions'][$row['packageVersion']])) {
                     $updates[$existingVersion['packageID']]['versions'][$row['packageVersion']] = array('isCritical' => $row['isCritical'], 'packageDate' => $row['packageDate'], 'packageVersion' => $row['packageVersion'], 'servers' => array());
                 }
                 // server data
                 $updates[$existingVersion['packageID']]['versions'][$row['packageVersion']]['servers'][] = array('packageUpdateID' => $row['packageUpdateID'], 'packageUpdateServerID' => $row['packageUpdateServerID'], 'packageUpdateVersionID' => $row['packageUpdateVersionID'], 'filename' => $row['filename']);
             }
         }
     }
     // sort package versions
     // and remove old versions
     foreach ($updates as $packageID => $data) {
         uksort($updates[$packageID]['versions'], array('wcf\\data\\package\\Package', 'compareVersion'));
         $updates[$packageID]['version'] = end($updates[$packageID]['versions']);
     }
     // remove requirements of application packages
     if ($removeRequirements) {
         foreach ($existingPackages as $identifier => $instances) {
             foreach ($instances as $instance) {
                 if ($instance['isApplication'] && isset($updates[$instance['packageID']])) {
                     $updates = $this->removeUpdateRequirements($updates, $updates[$instance['packageID']]['version']['servers'][0]['packageUpdateVersionID']);
                 }
             }
         }
     }
     // remove older minor releases from list, e.g. only display 1.0.2, even if 1.0.1 is available
     if ($removeOlderMinorReleases) {
         foreach ($updates as &$updateData) {
             $highestVersions = array();
             foreach ($updateData['versions'] as $versionNumber => $dummy) {
                 if (preg_match('~^(\\d+\\.\\d+)\\.~', $versionNumber, $matches)) {
                     $major = $matches[1];
                     if (isset($highestVersions[$major])) {
                         if (Package::compareVersion($highestVersions[$major], $versionNumber, '<')) {
                             // version is newer, discard current version
                             unset($updateData['versions'][$highestVersions[$major]]);
                             $highestVersions[$major] = $versionNumber;
                         } else {
                             // version is lower, discard
                             unset($updateData['versions'][$versionNumber]);
                         }
                     } else {
                         $highestVersions[$major] = $versionNumber;
                     }
                 }
             }
         }
         unset($updateData);
     }
     return $updates;
 }
 /**
  * @see wcf\page\IPage::readData()
  */
 public function readData()
 {
     parent::readData();
     $this->updateServers = PackageUpdateServer::getActiveUpdateServers();
 }
 /**
  * @see wcf\page\IPage::readData()
  */
 public function readData()
 {
     parent::readData();
     // extract realm
     if (preg_match('/realm="(.*?)"/i', $this->header, $match)) {
         $this->realm = $match[1];
     }
     // get existing auth data
     if ($this->packageUpdateServerID) {
         $updateServer = new PackageUpdateServer($this->packageUpdateServerID);
         $authData = $updateServer->getAuthData();
         if (isset($authData['loginUsername'])) {
             $this->loginUsername = $authData['loginUsername'];
         }
         if (isset($authData['loginPassword'])) {
             $this->loginPassword = $authData['loginPassword'];
         }
         if (isset($authData['loginUsername']) || isset($authData['loginPassword'])) {
             $this->errorField = 'loginPassword';
             $this->errorType = 'invalid';
         }
     }
     $this->buildPostParameters();
     $this->buildGetParameters();
 }