/**
  * @see wcf\page\IPage::assignVariables()
  */
 public function readParameters()
 {
     parent::readParameters();
     if (!count($_POST)) {
         // refresh package database
         PackageUpdateDispatcher::refreshPackageDatabase();
     }
     // get updatable packages
     $this->availableUpdates = PackageUpdateDispatcher::getAvailableUpdates();
 }
 /**
  * @see wcf\form\IForm::validate()
  */
 public function validate()
 {
     parent::validate();
     if (!count($this->updates)) {
         throw new UserInputException('updates');
     }
     // build update stack
     $this->packageUpdate = PackageUpdateDispatcher::prepareInstallation($this->updates, array(), isset($_POST['send']));
     try {
         $this->packageUpdate->buildPackageInstallationStack();
         $this->excludedPackages = $this->packageUpdate->getExcludedPackages();
         if (count($this->excludedPackages)) {
             throw new UserInputException('excludedPackages');
         }
     } catch (SystemException $e) {
         // show detailed error message
         throw new UserInputException('updates', $e);
     }
 }
 /**
  * @see	\wcf\system\cache\builder\AbstractCacheBuilder::rebuild()
  */
 public function rebuild(array $parameters)
 {
     $updates = PackageUpdateDispatcher::getInstance()->getAvailableUpdates();
     return array('updates' => count($updates));
 }
 /**
  * Validates parameters to perform a system update.
  */
 public function validatePrepareUpdate()
 {
     WCF::getSession()->checkPermissions(array('admin.system.package.canUpdatePackage'));
     if (!isset($this->parameters['packages']) || !is_array($this->parameters['packages'])) {
         throw new UserInputException('packages');
     }
     // validate packages for their existance
     $availableUpdates = PackageUpdateDispatcher::getInstance()->getAvailableUpdates();
     foreach ($this->parameters['packages'] as $packageName => $versionNumber) {
         $isValid = false;
         foreach ($availableUpdates as $package) {
             if ($package['package'] == $packageName) {
                 // validate version
                 if (isset($package['versions'][$versionNumber])) {
                     $isValid = true;
                     break;
                 }
             }
         }
         if (!$isValid) {
             throw new UserInputException('packages');
         }
     }
     if (isset($this->parameters['authData'])) {
         if (!is_array($this->parameters['authData'])) {
             throw new UserInputException('authData');
         }
         $this->readInteger('packageUpdateServerID', false, 'authData');
         $this->readString('password', false, 'authData');
         $this->readString('username', false, 'authData');
         $this->readBoolean('saveCredentials', true, 'authData');
     }
 }
 /**
  * @see	\wcf\system\ICronjob::execute()
  */
 public function execute(Cronjob $cronjob)
 {
     PackageUpdateDispatcher::getInstance()->refreshPackageDatabase();
 }
 /**
  * Updates an existing package.
  * 
  * @param	integer		$packageID
  * @param	string		$version
  */
 protected function updatePackage($packageID, $version)
 {
     // get package info
     $package = PackageCache::getInstance()->getPackage($packageID);
     // get current package version
     $packageVersion = $package->packageVersion;
     if (isset($this->virtualPackageVersions[$packageID])) {
         $packageVersion = $this->virtualPackageVersions[$packageID];
         // check virtual package version
         if (Package::compareVersion($packageVersion, $version, '>=')) {
             // virtual package version is greater than requested version
             // skip package update
             return;
         }
     }
     // get highest version of the required major release
     if (preg_match('/(\\d+\\.\\d+\\.)/', $version, $match)) {
         $packageVersions = array();
         $sql = "SELECT\tDISTINCT packageVersion\n\t\t\t\tFROM\twcf" . WCF_N . "_package_update_version\n\t\t\t\tWHERE\tpackageUpdateID IN (\n\t\t\t\t\t\tSELECT\tpackageUpdateID\n\t\t\t\t\t\tFROM\twcf" . WCF_N . "_package_update\n\t\t\t\t\t\tWHERE\tpackage = ?\n\t\t\t\t\t)\n\t\t\t\t\tAND packageVersion LIKE ?";
         $statement = WCF::getDB()->prepareStatement($sql);
         $statement->execute(array($package->package, $match[1] . '%'));
         while ($row = $statement->fetchArray()) {
             $packageVersions[] = $row['packageVersion'];
         }
         if (count($packageVersions) > 1) {
             // sort by version number
             usort($packageVersions, array('wcf\\data\\package\\Package', 'compareVersion'));
             // get highest version
             $version = array_pop($packageVersions);
         }
     }
     // get all fromversion
     $fromversions = array();
     $sql = "SELECT\t\tpuv.packageVersion, puf.fromversion\n\t\t\tFROM\t\twcf" . WCF_N . "_package_update_fromversion puf\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update_version puv\n\t\t\tON\t\t(puv.packageUpdateVersionID = puf.packageUpdateVersionID)\n\t\t\tWHERE\t\tpuf.packageUpdateVersionID IN (\n\t\t\t\t\t\tSELECT\tpackageUpdateVersionID\n\t\t\t\t\t\tFROM\twcf" . WCF_N . "_package_update_version\n\t\t\t\t\t\tWHERE\tpackageUpdateID IN (\n\t\t\t\t\t\t\tSELECT\tpackageUpdateID\n\t\t\t\t\t\t\tFROM\twcf" . WCF_N . "_package_update\n\t\t\t\t\t\t\tWHERE\tpackage = ?\n\t\t\t\t\t\t)\n\t\t\t\t\t)";
     $statement = WCF::getDB()->prepareStatement($sql);
     $statement->execute(array($package->package));
     while ($row = $statement->fetchArray()) {
         if (!isset($fromversions[$row['packageVersion']])) {
             $fromversions[$row['packageVersion']] = array();
         }
         $fromversions[$row['packageVersion']][$row['fromversion']] = $row['fromversion'];
     }
     // sort by version number
     uksort($fromversions, array('wcf\\data\\package\\Package', 'compareVersion'));
     // find shortest update thread
     $updateThread = $this->findShortestUpdateThread($package->package, $fromversions, $packageVersion, $version);
     // process update thread
     foreach ($updateThread as $fromversion => $toVersion) {
         $packageUpdateVersions = PackageUpdateDispatcher::getInstance()->getPackageUpdateVersions($package->package, $toVersion);
         // resolve requirements
         $this->resolveRequirements($packageUpdateVersions[0]['packageUpdateVersionID']);
         // download package
         $download = $this->downloadPackage($package->package, $packageUpdateVersions);
         // add to stack
         $this->packageInstallationStack[] = array('packageName' => $package->getName(), 'fromversion' => $fromversion, 'toVersion' => $toVersion, 'package' => $package->package, 'packageID' => $packageID, 'archive' => $download, 'action' => 'update');
         // update virtual versions
         $this->virtualPackageVersions[$packageID] = $toVersion;
     }
 }
Exemple #7
0
 /**
  * Checks for updates.
  * 
  * @return	string
  */
 public function checkForUpdates()
 {
     if (WCF::getSession()->getPermission('admin.system.package.canUpdatePackage') && VERBOSITY >= -1 && !self::getArgvParser()->disableUpdateCheck) {
         $updates = PackageUpdateDispatcher::getInstance()->getAvailableUpdates();
         if (!empty($updates)) {
             $return = self::getReader()->println(count($updates) . ' update' . (count($updates) > 1 ? 's are' : ' is') . ' available');
             if (VERBOSITY >= 1) {
                 $table = array(array(WCF::getLanguage()->get('wcf.acp.package.name'), WCF::getLanguage()->get('wcf.acp.package.version'), WCF::getLanguage()->get('wcf.acp.package.newVersion')));
                 foreach ($updates as $update) {
                     $row = array(WCF::getLanguage()->get($update['packageName']), $update['packageVersion'], $update['version']['packageVersion']);
                     $table[] = $row;
                 }
                 self::getReader()->println(CLIUtil::generateTable($table));
             }
         }
     }
 }
 /**
  * @see wcf\form\IForm::validate()
  */
 public function validate()
 {
     parent::validate();
     // refresh package database
     PackageUpdateDispatcher::refreshPackageDatabase($this->packageUpdateServerIDs);
     // build conditions
     $conditions = new PreparedStatementConditionBuilder();
     // update servers
     if (count($this->packageUpdateServerIDs)) {
         $conditions->add("packageUpdateServerID IN (?)", array($this->packageUpdateServerIDs));
     }
     // name
     if (!empty($this->packageName)) {
         $condition = "packageName LIKE ?";
         $parameters = array('%' . $this->packageName . '%');
         if ($this->searchDescription) {
             $condition .= " OR packageDescription LIKE ?";
             $parameters[] = '%' . $this->packageName . '%';
         }
         $conditions->add('(' . $condition . ')', $parameters);
     }
     // author
     if (!empty($this->author)) {
         $conditions->add("author LIKE ?", array($this->author));
     }
     // ignore already installed uniques
     if ($this->ignoreUniques == 1) {
         $conditions->add("package NOT IN (SELECT package FROM wcf" . WCF_N . "_package WHERE isUnique = 1)");
     }
     // package type
     if (($this->plugin == 0 || $this->isApplication == 0 || $this->other == 0) && ($this->plugin == 1 || $this->isApplication == 1 || $this->other == 1)) {
         if ($this->isApplication == 1) {
             $condition = 'isApplication = 1';
             if ($this->plugin == 1) {
                 $condition .= " OR plugin IN (SELECT package FROM wcf" . WCF_N . "_package)";
             } else {
                 if ($this->other == 1) {
                     $condition .= " OR plugin = ''";
                 }
             }
             $conditions->add('(' . $condition . ')');
         } else {
             if ($this->plugin == 1) {
                 $condition = "plugin IN (SELECT package FROM wcf" . WCF_N . "_package)";
                 if ($this->other == 1) {
                     $condition .= " OR isApplication = 0";
                 }
                 $conditions->add('(' . $condition . ')');
             } else {
                 if ($this->other) {
                     $conditions->add("(isApplication = 0 AND plugin = '')");
                 }
             }
         }
     }
     // search package database
     $packages = array();
     $packageUpdateIDs = array();
     $sql = "SELECT\tpackage, packageUpdateID\n\t\t\tFROM\twcf" . WCF_N . "_package_update\n\t\t\t" . $conditions;
     $statement = WCF::getDB()->prepareStatement($sql, 1000);
     $statement->execute($conditions->getParameters());
     while ($row = $statement->fetchArray()) {
         $packageUpdateIDs[] = $row['packageUpdateID'];
         if (!isset($packages[$row['package']])) {
             $packages[$row['package']] = array();
         }
         $packages[$row['package']][$row['packageUpdateID']] = array();
     }
     if (empty($packageUpdateIDs)) {
         throw new UserInputException('packageName');
     }
     // remove duplicates
     $condition = '';
     $statementParameters = array();
     foreach ($packageUpdateIDs as $packageUpdateID) {
         if (!empty($condition)) {
             $condition .= ',';
         }
         $condition .= '?';
         $statementParameters[] = $packageUpdateID;
     }
     $sql = "SELECT\t\tpuv.packageVersion, pu.package, pu.packageUpdateID\n\t\t\tFROM\t\twcf" . WCF_N . "_package_update_version puv\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_package_update pu\n\t\t\tON\t\t(pu.packageUpdateID = puv.packageUpdateID)\n\t\t\tWHERE\t\tpuv.packageUpdateID IN (" . $condition . ")";
     $statement = WCF::getDB()->prepareStatement($sql);
     $statement->execute($statementParameters);
     while ($row = $statement->fetchArray()) {
         $packages[$row['package']][$row['packageUpdateID']][] = $row['packageVersion'];
     }
     foreach ($packages as $identifier => $packageUpdates) {
         if (count($packageUpdates) > 1) {
             foreach ($packageUpdates as $packageUpdateID => $versions) {
                 usort($versions, array('wcf\\data\\package\\Package', 'compareVersion'));
                 $packageUpdates[$packageUpdateID] = array_pop($versions);
             }
             uasort($packageUpdates, array('wcf\\data\\package\\Package', 'compareVersion'));
         }
         $keys = array_keys($packageUpdates);
         if (!empty($this->packageUpdateIDs)) {
             $this->packageUpdateIDs .= ',';
         }
         $this->packageUpdateIDs .= array_pop($keys);
     }
 }
 /**
  * @see	\wcf\page\IPage::readData()
  */
 public function readData()
 {
     parent::readData();
     $this->availableUpdates = PackageUpdateDispatcher::getInstance()->getAvailableUpdates(true, true);
 }
	/**
	 * Tries to download a package from available update servers.
	 * 
	 * @param	string		$package		package identifier
	 * @param	array		$packageUpdateVersions	package update versions
	 * @return	string		tmp filename of a downloaded package
	 */
	protected function downloadPackage($package, $packageUpdateVersions) {
		// get download from cache
		if ($filename = $this->getCachedDownload($package, $packageUpdateVersions[0]['package'])) {
			return $filename;
		}
		
		// download file
		$authorizationRequiredException = array();
		$systemExceptions = array();
		foreach ($packageUpdateVersions as $packageUpdateVersion) {
			try {
				// get auth data
				$authData = $this->getAuthData($packageUpdateVersion);
				
				// send request
				// TODO: Use HTTPRequest
				if (!empty($packageUpdateVersion['file'])) {
					$response = PackageUpdateDispatcher::getInstance()->sendRequest($packageUpdateVersion['file'], array(), $authData);
				}
				else {
					$response = PackageUpdateDispatcher::getInstance()->sendRequest($packageUpdateVersion['server'], array('packageName' => $packageUpdateVersion['package'], 'packageVersion' => $packageUpdateVersion['packageVersion']), $authData);
				}
				
				// check response
				// check http code
				if ($response['httpStatusCode'] == 401) {
					throw new PackageUpdateAuthorizationRequiredException($packageUpdateVersion['packageUpdateServerID'], (!empty($packageUpdateVersion['file']) ? $packageUpdateVersion['file'] : $packageUpdateVersion['server']), $response);
				}
				
				if ($response['httpStatusCode'] != 200) {
					throw new SystemException(WCF::getLanguage()->get('wcf.acp.packageUpdate.error.downloadFailed', array('$package' => $package)) . ' ('.$response['httpStatusLine'].')');
				}
				
				// write content to tmp file
				$filename = FileUtil::getTemporaryFilename('package_');
				$file = new File($filename);
				$file->write($response['content']);
				$file->close();
				unset($response['content']);
				
				// test package
				$archive = new PackageArchive($filename);
				$archive->openArchive();
				$archive->getTar()->close();
				
				// cache download in session
				PackageUpdateDispatcher::getInstance()->cacheDownload($package, $packageUpdateVersion['packageVersion'], $filename);
				
				return $filename;
			}
			catch (PackageUpdateAuthorizationRequiredException $e) {
				$authorizationRequiredException[] = $e;
			}
			catch (SystemException $e) {
				$systemExceptions[] = $e;
			}
		}
		
		if (!empty($authorizationRequiredException)) {
			throw array_shift($authorizationRequiredException);
		}
		
		if (!empty($systemExceptions)) {
			throw array_shift($systemExceptions);
		}
		
		return false;
	}