/** * @see wcf\page\IPage::assignVariables() */ public function readParameters() { parent::readParameters(); if (empty($_POST)) { // refresh package database PackageUpdateDispatcher::getInstance()->refreshPackageDatabase(); } // get updatable packages $this->availableUpdates = PackageUpdateDispatcher::getInstance()->getAvailableUpdates(); }
/** * @see wcf\form\IForm::validate() */ public function validate() { parent::validate(); if (empty($this->updates)) { throw new UserInputException('updates'); } // build update stack $this->packageUpdate = PackageUpdateDispatcher::getInstance()->prepareInstallation($this->updates, array(), isset($_POST['send'])); try { $this->packageUpdate->buildPackageInstallationStack(); $this->excludedPackages = $this->packageUpdate->getExcludedPackages(); if (!empty($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; } }
/** * 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\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; }