/** * Validates if the package has suitable install or update instructions * * @param string $requiredVersion * @param integer $validationMode */ protected function validateInstructions($requiredVersion, $validationMode) { $package = $this->getPackage(); // delivered package does not provide the minimum required version if (Package::compareVersion($requiredVersion, $this->archive->getPackageInfo('version'), '>')) { throw new PackageValidationException(PackageValidationException::INSUFFICIENT_VERSION, array('packageName' => $package->packageName, 'packageVersion' => $package->packageVersion, 'deliveredPackageVersion' => $this->archive->getPackageInfo('version'))); } // package is not installed yet if ($package === null) { $instructions = $this->archive->getInstallInstructions(); if (empty($instructions)) { throw new PackageValidationException(PackageValidationException::NO_INSTALL_PATH, array('packageName' => $this->archive->getPackageInfo('name'))); } if ($validationMode == PackageValidationManager::VALIDATION_RECURSIVE) { $this->validatePackageInstallationPlugins('install', $instructions); } } else { // package is already installed, check update path if (!$this->archive->isValidUpdate($package)) { throw new PackageValidationException(PackageValidationException::NO_UPDATE_PATH, array('packageName' => $package->packageName, 'packageVersion' => $package->packageVersion, 'deliveredPackageVersion' => $this->archive->getPackageInfo('version'))); } if ($validationMode === PackageValidationManager::VALIDATION_RECURSIVE) { $this->validatePackageInstallationPlugins('update', $this->archive->getUpdateInstructions()); } } }
/** * @see \wcf\form\IForm::validate() */ public function validate() { parent::validate(); if (empty($this->source['name'])) { throw new UserInputException('source'); } if (empty($this->source['tmp_name'])) { throw new UserInputException('source', 'uploadFailed'); } try { // check if the uploaded file is a package $archive = new PackageArchive($this->source['tmp_name']); $archive->openArchive(); // check if the package is an application if ($archive->getPackageInfo('isApplication')) { throw new SystemException("Package is application"); } // check if the package includes a style $containsStyle = false; $installInstructions = $archive->getInstallInstructions(); foreach ($installInstructions as $instruction) { if ($instruction['pip'] == 'style') { $containsStyle = true; break; } } if (!$containsStyle) { throw new SystemException("Package contains no style"); } $filename = FileUtil::getTemporaryFilename('package_', preg_replace('!^.*(?=\\.(?:tar\\.gz|tgz|tar)$)!i', '', basename($this->source['name']))); if (!@move_uploaded_file($this->source['tmp_name'], $filename)) { throw new SystemException("Cannot move uploaded file"); } WCF::getSession()->register('stylePackageImportLocation', $filename); HeaderUtil::redirect(LinkHandler::getInstance()->getLink('PackageStartInstall', array('action' => 'install'))); exit; } catch (SystemException $e) { // ignore errors } try { $this->style = StyleEditor::import($this->source['tmp_name']); } catch (\Exception $e) { @unlink($this->source['tmp_name']); throw new UserInputException('source', 'importFailed'); } }
/** * Tries to download a package from available update servers. * * @param string $package package identifier * @param array $packageUpdateVersions package update versions * @param boolean $validateInstallInstructions * @return string tmp filename of a downloaded package */ protected function downloadPackage($package, $packageUpdateVersions, $validateInstallInstructions = false) { // get download from cache if ($filename = $this->getCachedDownload($package, $packageUpdateVersions[0]['package'])) { return $filename; } // download file foreach ($packageUpdateVersions as $packageUpdateVersion) { // get auth data $authData = $this->getAuthData($packageUpdateVersion); if ($packageUpdateVersion['filename']) { $request = new HTTPRequest($packageUpdateVersion['filename'], !empty($authData) ? array('auth' => $authData) : array(), array('apiVersion' => PackageUpdate::API_VERSION)); } else { // create request $request = new HTTPRequest($this->packageUpdateServers[$packageUpdateVersion['packageUpdateServerID']]->getDownloadURL(), !empty($authData) ? array('auth' => $authData) : array(), array('apiVersion' => PackageUpdate::API_VERSION, 'packageName' => $packageUpdateVersion['package'], 'packageVersion' => $packageUpdateVersion['packageVersion'])); } try { $request->execute(); } catch (HTTPUnauthorizedException $e) { throw new PackageUpdateUnauthorizedException($request, $this->packageUpdateServers[$packageUpdateVersion['packageUpdateServerID']], $packageUpdateVersion); } $response = $request->getReply(); // check response if ($response['statusCode'] != 200) { throw new SystemException(WCF::getLanguage()->getDynamicVariable('wcf.acp.package.error.downloadFailed', array('__downloadPackage' => $package)) . ' (' . $response['body'] . ')'); } // write content to tmp file $filename = FileUtil::getTemporaryFilename('package_'); $file = new File($filename); $file->write($response['body']); $file->close(); unset($response['body']); // test package $archive = new PackageArchive($filename); $archive->openArchive(); // check install instructions if ($validateInstallInstructions) { $installInstructions = $archive->getInstallInstructions(); if (empty($installInstructions)) { throw new SystemException("Package '" . $archive->getLocalizedPackageInfo('packageName') . "' (" . $archive->getPackageInfo('name') . ") does not contain valid installation instructions."); } } $archive->getTar()->close(); // cache download in session PackageUpdateDispatcher::getInstance()->cacheDownload($package, $packageUpdateVersion['packageVersion'], $filename); return $filename; } return false; }