Reject duplicated elements in `<packageinformation>`
authorTim Düsterhus <duesterhus@woltlab.com>
Wed, 13 Sep 2023 12:21:42 +0000 (14:21 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Wed, 13 Sep 2023 12:34:02 +0000 (14:34 +0200)
wcfsetup/install/files/lib/system/package/PackageArchive.class.php
wcfsetup/install/files/lib/system/package/validation/PackageValidationException.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 4a774272a9f5b83a8557292e87d7a105dbb0753f..1cdbd6459538605b5fed2790eaeb229b3184b7e0 100644 (file)
@@ -174,16 +174,12 @@ class PackageArchive
 
         $this->packageInfo['name'] = $packageName;
 
-        // set default values
-        $this->packageInfo['isApplication'] = 0;
-        $this->packageInfo['packageURL'] = '';
-
-        // get package information
         $packageInformation = $xpath->query('./ns:packageinformation', $package)->item(0);
         if ($packageInformation !== null) {
             $elements = $xpath->query('child::*', $packageInformation);
-            /** @var \DOMElement $element */
             foreach ($elements as $element) {
+                \assert($element instanceof \DOMElement);
+
                 switch ($element->tagName) {
                     case 'packagename':
                     case 'packagedescription':
@@ -209,20 +205,56 @@ class PackageArchive
                         break;
 
                     case 'isapplication':
+                        if (isset($this->packageInfo['isApplication'])) {
+                            throw new PackageValidationException(
+                                PackageValidationException::DUPLICATE_PACKAGE_INFORMATION,
+                                [
+                                    'tag' => $element->tagName,
+                                ]
+                            );
+                        }
+
                         $this->packageInfo['isApplication'] = \intval($element->nodeValue);
                         break;
 
                     case 'applicationdirectory':
+                        if (isset($this->packageInfo['applicationdirectory'])) {
+                            throw new PackageValidationException(
+                                PackageValidationException::DUPLICATE_PACKAGE_INFORMATION,
+                                [
+                                    'tag' => $element->tagName,
+                                ]
+                            );
+                        }
+
                         if (\preg_match('~^[a-z0-9\-\_]+$~', $element->nodeValue)) {
                             $this->packageInfo['applicationDirectory'] = $element->nodeValue;
                         }
                         break;
 
                     case 'packageurl':
+                        if (isset($this->packageInfo['packageURL'])) {
+                            throw new PackageValidationException(
+                                PackageValidationException::DUPLICATE_PACKAGE_INFORMATION,
+                                [
+                                    'tag' => $element->tagName,
+                                ]
+                            );
+                        }
+
                         $this->packageInfo['packageURL'] = $element->nodeValue;
                         break;
 
                     case 'version':
+                        if (isset($this->packageInfo['version'])) {
+                            throw new PackageValidationException(
+                                PackageValidationException::DUPLICATE_PACKAGE_INFORMATION,
+                                [
+                                    'tag' => $element->tagName,
+                                ]
+                            );
+                        }
+
                         if (!Package::isValidVersion($element->nodeValue)) {
                             throw new PackageValidationException(
                                 PackageValidationException::INVALID_PACKAGE_VERSION,
@@ -234,6 +266,15 @@ class PackageArchive
                         break;
 
                     case 'date':
+                        if (isset($this->packageInfo['date'])) {
+                            throw new PackageValidationException(
+                                PackageValidationException::DUPLICATE_PACKAGE_INFORMATION,
+                                [
+                                    'tag' => $element->tagName,
+                                ]
+                            );
+                        }
+
                         DateUtil::validateDate($element->nodeValue);
 
                         $this->packageInfo['date'] = @\strtotime($element->nodeValue);
@@ -250,6 +291,10 @@ class PackageArchive
             }
         }
 
+        // set default values
+        $this->packageInfo['isApplication'] ??= 0;
+        $this->packageInfo['packageURL'] ??= '';
+
         // get author information
         $authorInformation = $xpath->query('./ns:authorinformation', $package)->item(0);
         if ($authorInformation !== null) {
index 12452f6f09fd08115ab48922d9b7409374215604..2091ed2aada9772d12dc6e7bdd3a83cd29e173f6 100644 (file)
@@ -201,6 +201,13 @@ class PackageValidationException extends SystemException
      */
     const MISSING_DISPLAY_NAME = 27;
 
+    /**
+     * an duplicate tag is given in the <packageinformation>
+     * @var int
+     * @since 6.0
+     */
+    const DUPLICATE_PACKAGE_INFORMATION = 28;
+
     /**
      * Creates a new PackageArchiveValidationException.
      *
index 8eab51b01454ea2b308a4126c3f7ee2581b1b02f..d3b7c82bbd79a6059f8fbf4663fe89aab7c7110c 100644 (file)
@@ -1947,6 +1947,7 @@ Die Datenbestände werden sorgfältig gepflegt, aber es ist nicht ausgeschlossen
                <item name="wcf.acp.package.validation.errorCode.25"><![CDATA[Die &lt;authorinformation&gt; enthalten das unbekannte Element „{$tag}“.]]></item>
                <item name="wcf.acp.package.validation.errorCode.26"><![CDATA[Es wurden keine (gültigen) &lt;authorinformation&gt; hinterlegt.]]></item>
                <item name="wcf.acp.package.validation.errorCode.27"><![CDATA[Es wurde kein (gültiger) &lt;packagename&gt; hinterlegt.]]></item>
+               <item name="wcf.acp.package.validation.errorCode.28"><![CDATA[Die &lt;packageinformation&gt; enthalten das doppelte Element „{$tag}“.]]></item>
                <item name="wcf.acp.package.validation.failed"><![CDATA[Das hochgeladene Paket kann nicht installiert werden, bitte {if LANGUAGE_USE_INFORMAL_VARIANT}beachte{else}beachten Sie{/if} das unten stehende Prüfungsergebnis.]]></item>
                <item name="wcf.acp.package.evaluation.expired"><![CDATA[Die Testphase von <strong>{$packageName}</strong> ist abgelaufen. Bitte aktualisiere{if !LANGUAGE_USE_INFORMAL_VARIANT}n Sie{/if} auf die aktuelle Version, um diese Software weiterhin legal betreiben zu können.{if $pluginStoreFileID || $isWoltLab}<br>{if LANGUAGE_USE_INFORMAL_VARIANT}Du kannst{else}Sie können{/if} die aktuelle Version sicher und bequem <strong>{if $pluginStoreFileID}<a href="https://pluginstore.woltlab.com/file/{$pluginStoreFileID}/">im WoltLab Plugin-Store</a>{else}<a href="https://www.woltlab.com/de/kaufen/">auf WoltLab.com</a>{/if}</strong> erwerben.{/if}]]></item>
                <item name="wcf.acp.package.evaluation.pending"><![CDATA[Bei den folgenden installierten Apps handelt es sich um Testversionen, die am <strong>{$evaluationEndDate|plainTime}</strong> ({@$evaluationEndDate|dateDiff:TIME_NOW:true}) ablaufen. Mit Ablauf der Frist deaktiviert sich die App automatisch, es ist dann notwendig diese auf die endgültige Version zu aktualisieren, um den legalen Betrieb fortzusetzen.
index 54b516e5f666e31d57a4407d8ef0d5749b281ec3..72f0721f2b7858514c63fae048f77dd5dda1561e 100644 (file)
@@ -1930,6 +1930,7 @@ The database is carefully maintained, but there will be always be a margin of er
                <item name="wcf.acp.package.validation.errorCode.25"><![CDATA[The &lt;authorinformation&gt; contain the unknown child element “{$tag}”.]]></item>
                <item name="wcf.acp.package.validation.errorCode.26"><![CDATA[No (valid) &lt;authorinformation&gt; have been given.]]></item>
                <item name="wcf.acp.package.validation.errorCode.27"><![CDATA[No (valid) &lt;packagename&gt; have been given.]]></item>
+               <item name="wcf.acp.package.validation.errorCode.28"><![CDATA[The &lt;packageinformation&gt; contain the duplicate child element “{$tag}”.]]></item>
                <item name="wcf.acp.package.validation.failed"><![CDATA[The package cannot be installed, please review the validation results below.]]></item>
                <item name="wcf.acp.package.evaluation.expired"><![CDATA[The evaluation period of <strong>{$packageName}</strong> has expired. For a legal use of this software, please update to the latest available version.{if $pluginStoreFileID || $isWoltLab}<br>The latest version can be purchased quickly and securely <strong>{if $pluginStoreFileID}<a href="https://pluginstore.woltlab.com/file/{$pluginStoreFileID}/">in the WoltLab Plugin-Store</a>{else}<a href="https://www.woltlab.com/en/purchase/">on WoltLab.com</a>{/if}</strong>.{/if}]]></item>
                <item name="wcf.acp.package.evaluation.pending"><![CDATA[The evaluation period of the apps listed below will expire on <strong>{$evaluationEndDate|plainTime}</strong> ({@$evaluationEndDate|dateDiff:TIME_NOW:true}). The apps will automatically disable themselves after this date and become unusable, you'll need to install the latest versions of the apps to active them again.