From 5ccce215a17e7ed546143bb1094608ad6b8e9332 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Thu, 6 Dec 2012 18:10:31 +0100 Subject: [PATCH] Disallowing uninstallation of required packages Fixes # --- .../{packageView.tpl => package.tpl} | 4 +- .../acp/templates/packageListDetailed.tpl | 2 +- .../files/lib/data/package/Package.class.php | 80 +++++++++++++++++-- 3 files changed, 76 insertions(+), 10 deletions(-) rename wcfsetup/install/files/acp/templates/{packageView.tpl => package.tpl} (97%) diff --git a/wcfsetup/install/files/acp/templates/packageView.tpl b/wcfsetup/install/files/acp/templates/package.tpl similarity index 97% rename from wcfsetup/install/files/acp/templates/packageView.tpl rename to wcfsetup/install/files/acp/templates/package.tpl index 677da369a2..42d731a5dc 100644 --- a/wcfsetup/install/files/acp/templates/packageView.tpl +++ b/wcfsetup/install/files/acp/templates/package.tpl @@ -134,7 +134,7 @@ {else} {/if} - {if $__wcf->session->getPermission('admin.system.package.canUninstallPackage') && $requiredPackage->package != 'com.woltlab.wcf' && $requiredPackage->packageID != PACKAGE_ID} + {if $requiredPackage->canUninstall()} {else} @@ -194,7 +194,7 @@ {else} {/if} - {if $__wcf->session->getPermission('admin.system.package.canUninstallPackage') && $dependentPackage->package != 'com.woltlab.wcf' && $dependentPackage->packageID != PACKAGE_ID} + {if $dependentPackage->canUninstall()} {else} diff --git a/wcfsetup/install/files/acp/templates/packageListDetailed.tpl b/wcfsetup/install/files/acp/templates/packageListDetailed.tpl index 220836b3c6..cc5ab073ad 100644 --- a/wcfsetup/install/files/acp/templates/packageListDetailed.tpl +++ b/wcfsetup/install/files/acp/templates/packageListDetailed.tpl @@ -62,7 +62,7 @@ {else} {/if} - {if $__wcf->session->getPermission('admin.system.package.canUninstallPackage') && $package->package != 'com.woltlab.wcf' && $package->packageID != PACKAGE_ID} + {if $package->canUninstall()} {else} diff --git a/wcfsetup/install/files/lib/data/package/Package.class.php b/wcfsetup/install/files/lib/data/package/Package.class.php index f970b4853e..44993a77cb 100644 --- a/wcfsetup/install/files/lib/data/package/Package.class.php +++ b/wcfsetup/install/files/lib/data/package/Package.class.php @@ -31,6 +31,12 @@ class Package extends DatabaseObject { */ protected static $databaseTableIndexName = 'packageID'; + /** + * package requirement map + * @var array + */ + protected static $requirementMap = null; + /** * list of packages that this package requires * @var array @@ -61,14 +67,9 @@ class Package extends DatabaseObject { * @return boolean */ public function isRequired() { - $sql = "SELECT COUNT(*) AS count - FROM wcf".WCF_N."_package_requirement - WHERE requirement = ?"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute(array($this->packageID)); - $row = $statement->fetchArray(); + self::loadRequirementMap(); - return $row['count']; + return (isset(self::$requirementMap[$this->packageID])); } /** @@ -168,6 +169,71 @@ class Package extends DatabaseObject { return $this->requiredPackages; } + /** + * Returns true, if current user can uninstall this package. + * + * @return boolean + */ + public function canUninstall() { + if (!WCF::getSession()->getPermission('admin.system.package.canUninstallPackage')) { + return false; + } + + // disallow uninstallation of current package or WCF + if ($this->package == 'com.woltlab.wcf' || $this->packageID == PACKAGE_ID) { + return false; + } + + // check if package is required by current application + if (self::isRequiredBy($this->packageID, PACKAGE_ID)) { + return false; + } + + return true; + } + + /** + * Returns true, if package $packageID is required by package $targetPackageID. + * + * @param integer $packageID + * @param integer $targetPackageID + * @return boolean + */ + public static function isRequiredBy($packageID, $targetPackageID) { + self::loadRequirementMap(); + + if (isset(self::$requirementMap[$packageID])) { + foreach (self::$requirementMap[$packageID] as $requiredBy) { + if ($requiredBy == $targetPackageID) { + return true; + } + } + } + + return false; + } + + /** + * Loads package requirement map. + */ + protected static function loadRequirementMap() { + if (self::$requirementMap === null) { + $sql = "SELECT packageID, requirement + FROM wcf".WCF_N."_package_requirement_map"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute(); + + self::$requirementMap = array(); + while ($row = $statement->fetchArray()) { + if (!isset(self::$requirementMap[$row['requirement']])) { + self::$requirementMap[$row['requirement']] = array(); + } + + self::$requirementMap[$row['requirement']][] = $row['packageID']; + } + } + } + /** * Checks if a package name is valid. * -- 2.20.1