[!!!][SECURITY] Add CSRF protection to mod.php 36/27636/8
authorHelmut Hummel <helmut.hummel@typo3.org>
Fri, 14 Feb 2014 22:56:38 +0000 (23:56 +0100)
committerHelmut Hummel <helmut.hummel@typo3.org>
Wed, 26 Feb 2014 15:36:20 +0000 (16:36 +0100)
Add a token check in mod.php and token generation
to BackendUtility::getModuleUrl()

Adapt code to use BackendUtility::getModuleUrl()
in every place where links are hardcoded.

Releases: 6.2
Resolves: #55509
Change-Id: I952c40fc1004a0a8d77c929927d37e1d93dcfef4
Reviewed-on: https://review.typo3.org/27636
Reviewed-by: Wouter Wolters
Tested-by: Wouter Wolters
Reviewed-by: Markus Klein
Tested-by: Markus Klein
Reviewed-by: Helmut Hummel
Tested-by: Helmut Hummel
22 files changed:
typo3/mod.php
typo3/sysext/backend/Classes/Controller/BackendController.php
typo3/sysext/backend/Classes/Module/ModuleLoader.php
typo3/sysext/backend/Classes/Search/LiveSearch/LiveSearch.php
typo3/sysext/backend/Classes/Utility/BackendUtility.php
typo3/sysext/backend/Classes/View/ModuleMenuView.php
typo3/sysext/backend/Resources/Public/JavaScript/notifications.js
typo3/sysext/beuser/Classes/Controller/BackendUserController.php
typo3/sysext/cshmanual/Classes/Controller/HelpModuleController.php
typo3/sysext/dbal/Classes/Controller/ModuleController.php
typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php
typo3/sysext/extbase/Classes/Utility/ExtensionUtility.php
typo3/sysext/extbase/Tests/Unit/Mvc/Web/Routing/UriBuilderTest.php
typo3/sysext/impexp/Classes/Task/ImportExportTask.php
typo3/sysext/install/Classes/Report/InstallStatusReport.php
typo3/sysext/openid/Classes/OpenidModuleSetup.php
typo3/sysext/openid/ext_tables.php
typo3/sysext/openid/wizard/conf.php
typo3/sysext/reports/Classes/Report/Status/SecurityStatus.php
typo3/sysext/sys_action/Classes/ActionTask.php
typo3/sysext/sys_action/Classes/ActionToolbarMenu.php
typo3/sysext/taskcenter/Classes/Controller/TaskModuleController.php

index 99da32d..e43aa85 100644 (file)
 unset($MCONF);
 require __DIR__ . '/init.php';
 // Find module path:
-$temp_M = (string) \TYPO3\CMS\Core\Utility\GeneralUtility::_GET('M');
+$moduleName = (string)\TYPO3\CMS\Core\Utility\GeneralUtility::_GET('M');
 $isDispatched = FALSE;
-if ($temp_path = $TBE_MODULES['_PATHS'][$temp_M]) {
-       $MCONF['_'] = 'mod.php?M=' . rawurlencode($temp_M);
+$formprotection = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get();
+if (!$formprotection->validateToken(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('moduleToken'), 'moduleCall', $moduleName)) {
+       throw new \UnexpectedValueException('Invalid form/module token detected. Access Denied!', 1392409507);
+}
+if ($temp_path = $TBE_MODULES['_PATHS'][$moduleName]) {
+       $MCONF['_'] = \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl($moduleName);
        require $temp_path . 'conf.php';
        $BACK_PATH = '';
        require $temp_path . 'index.php';
@@ -44,7 +48,7 @@ if ($temp_path = $TBE_MODULES['_PATHS'][$temp_M]) {
        if (is_array($TBE_MODULES['_dispatcher'])) {
                foreach ($TBE_MODULES['_dispatcher'] as $dispatcherClassName) {
                        $dispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager')->get($dispatcherClassName);
-                       if ($dispatcher->callModule($temp_M) === TRUE) {
+                       if ($dispatcher->callModule($moduleName) === TRUE) {
                                $isDispatched = TRUE;
                                break;
                        }
@@ -52,6 +56,6 @@ if ($temp_path = $TBE_MODULES['_PATHS'][$temp_M]) {
        }
 }
 if ($isDispatched === FALSE) {
-       throw new UnexpectedValueException('No module "' . htmlspecialchars($temp_M) . '" could be found.', 1294585070);
+       throw new UnexpectedValueException('No module "' . htmlspecialchars($moduleName) . '" could be found.', 1294585070);
 }
 \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->shutdown();
index f59963c..7f35cb9 100644 (file)
@@ -214,7 +214,7 @@ class BackendController {
                        if (typeof console === "undefined") {
                                console = TYPO3.Backend.DebugConsole;
                        }
-                       TYPO3.ContextHelpWindow.init();';
+                       TYPO3.ContextHelpWindow.init(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('help_cshmanual')) . ');';
                $this->pageRenderer->addExtOnReadyCode($extOnReadyCode);
                // Set document title:
                $title = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . ' [TYPO3 CMS ' . TYPO3_version . ']' : 'TYPO3 CMS ' . TYPO3_version;
index ca4a428..497b06b 100644 (file)
@@ -27,6 +27,7 @@ namespace TYPO3\CMS\Backend\Module;
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
 
+use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -306,9 +307,9 @@ class ModuleLoader {
                                // Default script setup
                                if ($setupInformation['configuration']['script'] === '_DISPATCH') {
                                        if ($setupInformation['configuration']['extbase']) {
-                                               $finalModuleConfiguration['script'] = 'mod.php?M=Tx_' . rawurlencode($name);
+                                               $finalModuleConfiguration['script'] = BackendUtility::getModuleUrl('Tx_' . $name);
                                        } else {
-                                               $finalModuleConfiguration['script'] = 'mod.php?M=' . rawurlencode($name);
+                                               $finalModuleConfiguration['script'] = BackendUtility::getModuleUrl($name);
                                        }
                                } elseif ($setupInformation['configuration']['script'] && file_exists($setupInformation['path'] . '/' . $setupInformation['configuration']['script'])) {
                                        $finalModuleConfiguration['script'] = $this->getRelativePath(PATH_typo3, $fullpath . '/' . $setupInformation['configuration']['script']);
index 8f98743..aad194a 100644 (file)
@@ -259,8 +259,8 @@ class LiveSearch {
                // "Edit" link: ( Only if permissions to edit the page-record of the content of the parent page ($this->id)
                // @todo Is there an existing function to generate this link?
                if ($permsEdit) {
-                       $returnUrl = rawurlencode('mod.php?M=web_list&id=' . $row['pid']);
-                       $editLink = 'alt_doc.php?' . '&edit[' . $tableName . '][' . $row['uid'] . ']=edit&returnUrl=' . $returnUrl;
+                       $returnUrl = BackendUtility::getModuleUrl('web_list', array('id' => $row['pid']));
+                       $editLink = 'alt_doc.php?' . '&edit[' . $tableName . '][' . $row['uid'] . ']=edit&returnUrl=' . rawurlencode($returnUrl);
                }
                return $editLink;
        }
index 79e2748..dc03289 100644 (file)
@@ -2735,17 +2735,19 @@ class BackendUtility {
                if (!is_array($mainParams)) {
                        $mainParams = array('id' => $mainParams);
                }
-               $mainParams = GeneralUtility::implodeArrayForUrl('', $mainParams);
+
                if (!$script) {
-                       $script = basename(PATH_thisScript);
-                       $mainParams .= GeneralUtility::_GET('M') ? '&M=' . rawurlencode(GeneralUtility::_GET('M')) : '';
+                       $scriptUrl = self::getModuleUrl(GeneralUtility::_GET('M'), $mainParams) . $addparams;
+               } else {
+                       $mainParams = GeneralUtility::implodeArrayForUrl('', $mainParams);
+                       $scriptUrl = $script . '?' . $mainParams . $addparams;
                }
                $options = array();
                foreach ($menuItems as $value => $label) {
                        $options[] = '<option value="' . htmlspecialchars($value) . '"' . ((string)$currentValue === (string)$value ? ' selected="selected"' : '') . '>' . GeneralUtility::deHSCentities(htmlspecialchars($label)) . '</option>';
                }
                if (count($options)) {
-                       $onChange = 'jumpToUrl(\'' . $script . '?' . $mainParams . $addparams . '&' . $elementName . '=\'+this.options[this.selectedIndex].value,this);';
+                       $onChange = 'jumpToUrl(' . GeneralUtility::quoteJSvalue($scriptUrl . '&' . $elementName . '=') . '+this.options[this.selectedIndex].value,this);';
                        return '
 
                                <!-- Function Menu of module -->
@@ -3007,8 +3009,9 @@ class BackendUtility {
                }
                $allUrlParameters = array();
                $allUrlParameters['M'] = $moduleName;
+               $allUrlParameters['moduleToken'] = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get()->generateToken('moduleCall', $moduleName);
                $allUrlParameters = array_merge($allUrlParameters, $urlParameters);
-               $url = 'mod.php?' . GeneralUtility::implodeArrayForUrl('', $allUrlParameters, '', TRUE);
+               $url = 'mod.php?' . ltrim(GeneralUtility::implodeArrayForUrl('', $allUrlParameters, '', TRUE, TRUE), '&');
                if ($returnAbsoluteUrl) {
                        return GeneralUtility::getIndpEnv('TYPO3_REQUEST_DIR') . $url;
                } else {
index fc8060c..f088949 100644 (file)
@@ -27,6 +27,7 @@ namespace TYPO3\CMS\Backend\View;
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
 
+use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -235,7 +236,11 @@ class ModuleMenuView {
                                );
                        } elseif (is_array($moduleData['sub'])) {
                                foreach ($moduleData['sub'] as $submoduleName => $submoduleData) {
-                                       $submoduleLink = GeneralUtility::resolveBackPath($submoduleData['script']);
+                                       if (isset($submoduleData['script'])) {
+                                               $submoduleLink = GeneralUtility::resolveBackPath($submoduleData['script']);
+                                       } else {
+                                               $submoduleLink = BackendUtility::getModuleUrl($submoduleData['name']);
+                                       }
                                        $submoduleKey = $moduleName . '_' . $submoduleName . '_tab';
                                        $submoduleIcon = $this->getModuleIcon($submoduleKey);
                                        $submoduleDescription = $GLOBALS['LANG']->moduleLabels['labels'][$submoduleKey . 'label'];
index 83a1033..947c87b 100644 (file)
@@ -271,45 +271,55 @@ TYPO3.Dialog = function() {
  */
 TYPO3.ContextHelpWindow = function() {
        /**
-       * Path to typo3 directory
-       *
-       * @type {String}
-       * @private
+        * Path to typo3 directory
+        *
+        * @type {String}
+        * @private
        */
        var typo3Path = '';
 
        /**
-       * Context for open a window
-       * "window" - open a new window
-       * "inline" - open a TYPO3.Window (not currently implementy)
-       *
-       * @type {String}
-       * @private
+        * Context for open a window
+        * "window" - open a new window
+        * "inline" - open a TYPO3.Window (not currently implementy)
+        *
+        * @type {String}
+        * @private
        */
        var openContext;
 
        /**
-       * Width for the window
-       *
-       * @type {Number}
-       * @private
+        * Width for the window
+        *
+        * @type {Number}
+        * @private
        */
        var width;
+
        /**
-       * Height of the window
-       *
-       * @type {Number}
-       * @private
+        * Height of the window
+        *
+        * @type {Number}
+        * @private
        */
        var height;
 
+       /**
+        * Token for help module
+        *
+        * @type {String}
+        * @private
+        */
+       var helpModuleUrl;
+
        return {
                /**
                 * init class vars
                 *
                 * @return void
                 */
-               init: function() {
+               init: function(helpModuleUrl) {
+                       this.helpModuleUrl = helpModuleUrl;
                        this.typo3Path = top.TYPO3.configuration.PATH_typo3;
                        this.openContext = 'window';
                        this.width = top.TYPO3.configuration.ContextHelpWindows.width;
@@ -325,7 +335,7 @@ TYPO3.ContextHelpWindow = function() {
                open: function(helpIdentifier) {
                        if (this.openContext === 'window') {
                                var cshWindow = window.open(
-                                       this.typo3Path + 'mod.php?M=help_cshmanual&tfID=' + helpIdentifier,
+                                       this.typo3Path + this.helpModuleUrl + '&tfID=' + helpIdentifier,
                                        'ContextHelpWindow',
                                        'height=' + this.height + ',width=' + this.width + ',status=0,menubar=0,scrollbars=1'
                                );
index d467f0a..eb2355d 100755 (executable)
@@ -25,6 +25,7 @@ namespace TYPO3\CMS\Beuser\Controller;
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
+use TYPO3\CMS\Backend\Utility\BackendUtility;
 
 /**
  * Backend module user administration controller
@@ -121,7 +122,7 @@ class BackendUserController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionCont
                }
                $compareUserList = $this->moduleData->getCompareUserList();
                $this->view->assign('demand', $demand);
-               $this->view->assign('returnUrl', 'mod.php?M=system_BeuserTxBeuser');
+               $this->view->assign('returnUrl', rawurlencode(BackendUtility::getModuleUrl('system_BeuserTxBeuser')));
                $this->view->assign('dateFormat', $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy']);
                $this->view->assign('timeFormat', $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm']);
                $this->view->assign('backendUsers', $this->backendUserRepository->findDemanded($demand));
index 4c58f6d..2009947 100644 (file)
@@ -108,12 +108,20 @@ class HelpModuleController {
        public $glossaryWords;
 
        /**
+        * URL to help module
+        *
+        * @var string
+        */
+       protected $moduleUrl;
+
+       /**
         * Initialize the class for various input etc.
         *
         * @return void
         * @todo Define visibility
         */
        public function init() {
+               $this->moduleUrl = BackendUtility::getModuleUrl('help_cshmanual');
                // Setting GPvars:
                $this->tfID = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('tfID');
                // Sanitizes the tfID using whitelisting.
@@ -272,7 +280,7 @@ class HelpModuleController {
                if (!$this->renderALL) {
                        $output .= '
                                <br/>
-                               <p class="c-nav"><a href="mod.php?M=help_cshmanual&renderALL=1">' . $GLOBALS['LANG']->getLL('full_manual', TRUE) . '</a></p>';
+                               <p class="c-nav"><a href="' . htmlspecialchars($this->moduleUrl) . '&amp;renderALL=1">' . $GLOBALS['LANG']->getLL('full_manual', TRUE) . '</a></p>';
                }
                if ($this->renderALL) {
                        $output .= '
@@ -316,7 +324,7 @@ class HelpModuleController {
                        }
                } else {
                        // Only TOC:
-                       $tocArray[$tocCat][$table] = '<p><a href="mod.php?M=help_cshmanual&tfID=' . rawurlencode(($table . '.*')) . '">' . $this->getTableFieldLabel($table) . '</a></p>';
+                       $tocArray[$tocCat][$table] = '<p><a href="' . htmlspecialchars($this->moduleUrl) . '&amp;tfID=' . rawurlencode(($table . '.*')) . '">' . $this->getTableFieldLabel($table) . '</a></p>';
                }
                // Unset CSH key:
                unset($CSHkeys[$table]);
@@ -400,7 +408,7 @@ class HelpModuleController {
                $output = $this->substituteGlossaryWords($output);
                // TOC link:
                if (!$this->renderALL) {
-                       $tocLink = '<p class="c-nav"><a href="mod.php?M=help_cshmanual">' . $GLOBALS['LANG']->getLL('goToToc', TRUE) . '</a></p>';
+                       $tocLink = '<p class="c-nav"><a href="' . htmlspecialchars($this->moduleUrl) . '">' . $GLOBALS['LANG']->getLL('goToToc', TRUE) . '</a></p>';
                        $output = $tocLink . '
                                <br/>' . $output . '
                                <br />' . $tocLink;
@@ -427,8 +435,8 @@ class HelpModuleController {
                // Link to Full table description and TOC:
                $getLLKey = $this->limitAccess ? 'fullDescription' : 'fullDescription_module';
                $output .= '<br />
-                       <p class="c-nav"><a href="mod.php?M=help_cshmanual&tfID=' . rawurlencode(($key . '.*')) . '">' . $GLOBALS['LANG']->getLL($getLLKey, TRUE) . '</a></p>
-                       <p class="c-nav"><a href="mod.php?M=help_cshmanual">' . $GLOBALS['LANG']->getLL('goToToc', TRUE) . '</a></p>';
+                       <p class="c-nav"><a href="' . htmlspecialchars($this->moduleUrl) . '&amp;tfID=' . rawurlencode(($key . '.*')) . '">' . $GLOBALS['LANG']->getLL($getLLKey, TRUE) . '</a></p>
+                       <p class="c-nav"><a href="' . htmlspecialchars($this->moduleUrl) . '">' . $GLOBALS['LANG']->getLL('goToToc', TRUE) . '</a></p>';
                return $output;
        }
 
@@ -468,7 +476,7 @@ class HelpModuleController {
                                                // Checking read access:
                                                if (isset($GLOBALS['TCA_DESCR'][$iP[0]])) {
                                                        // Make see-also link:
-                                                       $href = $this->renderALL || $anchorTable && $iP[0] == $anchorTable ? '#' . implode('.', $iP) : 'mod.php?M=help_cshmanual&tfID=' . rawurlencode(implode('.', $iP)) . '&back=' . $this->tfID;
+                                                       $href = $this->renderALL || $anchorTable && $iP[0] == $anchorTable ? '#' . implode('.', $iP) : htmlspecialchars($this->moduleUrl) . '&amp;tfID=' . rawurlencode(implode('.', $iP)) . '&amp;back=' . $this->tfID;
                                                        $label = $this->getTableFieldLabel($iP[0], $iP[1], ' / ');
                                                        $lines[] = '<a href="' . htmlspecialchars($href) . '">' . htmlspecialchars($label) . '</a>';
                                                }
@@ -566,7 +574,7 @@ class HelpModuleController {
                        // Make seeAlso references.
                        $seeAlsoRes = $this->make_seeAlso($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['seeAlso'], $anchors ? $key : '');
                        // Making item:
-                       $out = '<a name="' . $key . '.' . $field . '"></a>' . $this->headerLine($this->getTableFieldLabel($key, $field), 1) . $this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['description']) . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['details'] ? $this->headerLine(($GLOBALS['LANG']->getLL('details') . ':')) . $this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['details']) : '') . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['syntax'] ? $this->headerLine(($GLOBALS['LANG']->getLL('syntax') . ':')) . $this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['syntax']) : '') . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['image'] ? $this->printImage($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['image'], $GLOBALS['TCA_DESCR'][$key]['columns'][$field]['image_descr']) : '') . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['seeAlso'] && $seeAlsoRes ? $this->headerLine(($GLOBALS['LANG']->getLL('seeAlso') . ':')) . '<p>' . $seeAlsoRes . '</p>' : '') . ($this->back ? '<br /><p><a href="' . htmlspecialchars(('mod.php?M=help_cshmanual&tfID=' . rawurlencode($this->back))) . '" class="typo3-goBack">' . htmlspecialchars($GLOBALS['LANG']->getLL('goBack')) . '</a></p>' : '') . '<br />';
+                       $out = '<a name="' . $key . '.' . $field . '"></a>' . $this->headerLine($this->getTableFieldLabel($key, $field), 1) . $this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['description']) . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['details'] ? $this->headerLine(($GLOBALS['LANG']->getLL('details') . ':')) . $this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['details']) : '') . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['syntax'] ? $this->headerLine(($GLOBALS['LANG']->getLL('syntax') . ':')) . $this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['syntax']) : '') . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['image'] ? $this->printImage($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['image'], $GLOBALS['TCA_DESCR'][$key]['columns'][$field]['image_descr']) : '') . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['seeAlso'] && $seeAlsoRes ? $this->headerLine(($GLOBALS['LANG']->getLL('seeAlso') . ':')) . '<p>' . $seeAlsoRes . '</p>' : '') . ($this->back ? '<br /><p><a href="' . htmlspecialchars($this->moduleUrl . '&amp;tfID=' . rawurlencode($this->back)) . '" class="typo3-goBack">' . htmlspecialchars($GLOBALS['LANG']->getLL('goBack')) . '</a></p>' : '') . '<br />';
                }
                return $out;
        }
@@ -616,8 +624,6 @@ class HelpModuleController {
         * @todo Define visibility
         */
        public function getTableFieldLabel($key, $field = '', $mergeToken = ': ') {
-               $tableName = '';
-               $fieldName = '';
                // Get table / field parts:
                list($tableName, $fieldName) = $this->getTableFieldNames($key, $field);
                // Create label:
@@ -638,7 +644,7 @@ class HelpModuleController {
         */
        public function createGlossaryIndex() {
                // Create hash string and try to retrieve glossary array:
-               $hash = md5('typo3/mod.php?M=help_cshmanual:glossary');
+               $hash = md5('help_cshmanual:glossary');
                $cachedData = BackendUtility::getHash($hash);
                // Generate glossary words if not found:
                if (is_array($cachedData)) {
@@ -710,7 +716,7 @@ class HelpModuleController {
                                // quoteMeta used so special chars (which should not occur though) in words will not break the regex. Seemed to work (- kasper)
                                $parts = preg_split('/( |[\\(])(' . quoteMeta($wordSet['title']) . ')([\\.\\!\\)\\?\\:\\,]+| )/i', ' ' . $code . ' ', 2, PREG_SPLIT_DELIM_CAPTURE);
                                if (count($parts) == 5) {
-                                       $parts[2] = '<a class="glossary-term" href="' . htmlspecialchars(('mod.php?M=help_cshmanual&tfID=' . rawurlencode($wordSet['key']) . '&back=' . $this->tfID)) . '" title="' . rawurlencode(htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs(rawurldecode($wordSet['description']), 80))) . '">' . htmlspecialchars($parts[2]) . '</a>';
+                                       $parts[2] = '<a class="glossary-term" href="' . htmlspecialchars($this->moduleUrl . '&amp;tfID=' . rawurlencode($wordSet['key']) . '&amp;back=' . $this->tfID) . '" title="' . rawurlencode(htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs(rawurldecode($wordSet['description']), 80))) . '">' . htmlspecialchars($parts[2]) . '</a>';
                                        $code = substr(implode('', $parts), 1, -1);
                                        // Disable entry so it doesn't get used next time:
                                        unset($this->substWords[$wordKey]);
index c4bbd3a..99cf58c 100644 (file)
@@ -62,7 +62,7 @@ class ModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClass {
         * @return      void
         */
        public function main() {
-               $this->thisScript = 'mod.php?M=' . $this->MCONF['name'];
+               $this->thisScript = BackendUtility::getModuleUrl($this->MCONF['name']);
                // Clean up settings:
                $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('SET'), $this->MCONF['name']);
                // Draw the header
index 007a4ec..995598c 100644 (file)
@@ -13,6 +13,8 @@ namespace TYPO3\CMS\Extbase\Mvc\Web\Routing;
  * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General      *
  * Public License for more details.                                       *
  *                                                                        */
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+
 /**
  * An URI Builder
  *
@@ -609,7 +611,9 @@ class UriBuilder {
                \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($arguments, $this->arguments);
                $arguments = $this->convertDomainObjectsToIdentityArrays($arguments);
                $this->lastArguments = $arguments;
-               $uri = 'mod.php?' . http_build_query($arguments, NULL, '&');
+               $moduleName = $arguments['M'];
+               unset($arguments['M'], $arguments['moduleToken']);
+               $uri = BackendUtility::getModuleUrl($moduleName, $arguments);
                if ($this->section !== '') {
                        $uri .= '#' . $this->section;
                }
index aa4bdfb..7727c3f 100644 (file)
@@ -222,7 +222,6 @@ tt_content.' . $pluginSignature . ' {
                        $moduleSignature .= '_' . $subModuleName;
                }
                $moduleConfiguration['name'] = $moduleSignature;
-               $moduleConfiguration['script'] = 'mod.php?M=' . rawurlencode($moduleSignature);
                if (NULL !== $vendorName) {
                        $moduleConfiguration['vendorName'] = $vendorName;
                }
index 66b2f22..aa0ed9f 100644 (file)
@@ -27,6 +27,7 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\Mvc\Web\Routing;
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
+
 /**
  * Uri Builder Test Class
  */
@@ -69,6 +70,10 @@ class UriBuilderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                $this->uriBuilder->_set('configurationManager', $this->mockConfigurationManager);
                $this->uriBuilder->_set('extensionService', $this->mockExtensionService);
                $this->uriBuilder->_set('environmentService', $this->objectManager->get('TYPO3\\CMS\\Extbase\\Service\\EnvironmentService'));
+               // Mocking backend user is required for backend URI generation as BackendUtility::getModuleUrl() is called
+               $backendUserMock = $this->getMock('TYPO3\\CMS\\Core\\Authentication\\BackendUserAuthentication');
+               $backendUserMock->expects($this->any())->method('check')->will($this->returnValue(TRUE));
+               $GLOBALS['BE_USER'] = $backendUserMock;
        }
 
        /**
@@ -177,7 +182,7 @@ class UriBuilderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                $_POST['foo2'] = 'bar2';
                $this->uriBuilder->setAddQueryString(TRUE);
                $this->uriBuilder->setAddQueryStringMethod('GET,POST');
-               $expectedResult = 'mod.php?M=moduleKey&id=pageId&foo=bar&foo2=bar2';
+               $expectedResult = 'mod.php?M=moduleKey&moduleToken=dummyToken&id=pageId&foo=bar&foo2=bar2';
                $actualResult = $this->uriBuilder->buildBackendUri();
                $this->assertEquals($expectedResult, $actualResult);
        }
@@ -191,7 +196,7 @@ class UriBuilderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                $_POST['foo2'] = 'bar2';
                $this->uriBuilder->setAddQueryString(TRUE);
                $this->uriBuilder->setAddQueryStringMethod(NULL);
-               $expectedResult = 'mod.php?M=moduleKey&id=pageId&foo=bar';
+               $expectedResult = 'mod.php?M=moduleKey&moduleToken=dummyToken&id=pageId&foo=bar';
                $actualResult = $this->uriBuilder->buildBackendUri();
                $this->assertEquals($expectedResult, $actualResult);
        }
@@ -214,7 +219,7 @@ class UriBuilderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                                        'M',
                                        'id'
                                ),
-                               'mod.php?foo=bar&foo2=bar2'
+                               'mod.php?moduleToken=dummyToken&foo=bar&foo2=bar2'
                        ),
                        'Arguments to be excluded in the end' => array(
                                array(
@@ -229,7 +234,7 @@ class UriBuilderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                                        'M',
                                        'id'
                                ),
-                               'mod.php?foo=bar&foo2=bar2'
+                               'mod.php?moduleToken=dummyToken&foo=bar&foo2=bar2'
                        ),
                        'Arguments in nested array to be excluded' => array(
                                array(
@@ -246,7 +251,7 @@ class UriBuilderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                                        'id',
                                        'tx_foo[bar]'
                                ),
-                               'mod.php?M=moduleKey&foo2=bar2'
+                               'mod.php?M=moduleKey&moduleToken=dummyToken&foo2=bar2'
                        ),
                        'Arguments in multidimensional array to be excluded' => array(
                                array(
@@ -265,7 +270,7 @@ class UriBuilderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                                        'id',
                                        'tx_foo[bar][baz]'
                                ),
-                               'mod.php?M=moduleKey&foo2=bar2'
+                               'mod.php?M=moduleKey&moduleToken=dummyToken&foo2=bar2'
                        ),
                );
        }
@@ -289,7 +294,7 @@ class UriBuilderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
         */
        public function buildBackendUriKeepsModuleQueryParametersIfAddQueryStringIsNotSet() {
                \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset(array('M' => 'moduleKey', 'id' => 'pageId', 'foo' => 'bar'));
-               $expectedResult = 'mod.php?M=moduleKey&id=pageId';
+               $expectedResult = 'mod.php?M=moduleKey&moduleToken=dummyToken&id=pageId';
                $actualResult = $this->uriBuilder->buildBackendUri();
                $this->assertEquals($expectedResult, $actualResult);
        }
@@ -300,7 +305,7 @@ class UriBuilderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
        public function buildBackendUriMergesAndOverrulesQueryParametersWithArguments() {
                \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset(array('M' => 'moduleKey', 'id' => 'pageId', 'foo' => 'bar'));
                $this->uriBuilder->setArguments(array('M' => 'overwrittenModuleKey', 'somePrefix' => array('bar' => 'baz')));
-               $expectedResult = 'mod.php?M=overwrittenModuleKey&id=pageId&somePrefix%5Bbar%5D=baz';
+               $expectedResult = 'mod.php?M=overwrittenModuleKey&moduleToken=dummyToken&id=pageId&somePrefix%5Bbar%5D=baz';
                $actualResult = $this->uriBuilder->buildBackendUri();
                $this->assertEquals($expectedResult, $actualResult);
        }
@@ -313,7 +318,7 @@ class UriBuilderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                $mockDomainObject = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity', array('dummy'));
                $mockDomainObject->_set('uid', '123');
                $this->uriBuilder->setArguments(array('somePrefix' => array('someDomainObject' => $mockDomainObject)));
-               $expectedResult = 'mod.php?M=moduleKey&somePrefix%5BsomeDomainObject%5D=123';
+               $expectedResult = 'mod.php?M=moduleKey&moduleToken=dummyToken&somePrefix%5BsomeDomainObject%5D=123';
                $actualResult = $this->uriBuilder->buildBackendUri();
                $this->assertEquals($expectedResult, $actualResult);
        }
@@ -324,7 +329,7 @@ class UriBuilderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
        public function buildBackendUriRespectsSection() {
                \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset(array('M' => 'moduleKey'));
                $this->uriBuilder->setSection('someSection');
-               $expectedResult = 'mod.php?M=moduleKey#someSection';
+               $expectedResult = 'mod.php?M=moduleKey&moduleToken=dummyToken#someSection';
                $actualResult = $this->uriBuilder->buildBackendUri();
                $this->assertEquals($expectedResult, $actualResult);
        }
@@ -336,7 +341,7 @@ class UriBuilderTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
                \TYPO3\CMS\Core\Utility\GeneralUtility::_GETset(array('M' => 'moduleKey'));
                $this->mockRequest->expects($this->any())->method('getBaseUri')->will($this->returnValue('http://baseuri/' . TYPO3_mainDir));
                $this->uriBuilder->setCreateAbsoluteUri(TRUE);
-               $expectedResult = 'http://baseuri/' . TYPO3_mainDir . 'mod.php?M=moduleKey';
+               $expectedResult = 'http://baseuri/' . TYPO3_mainDir . 'mod.php?M=moduleKey&moduleToken=dummyToken';
                $actualResult = $this->uriBuilder->buildBackendUri();
                $this->assertSame($expectedResult, $actualResult);
        }
index 55e398e..3ec8b54 100644 (file)
@@ -24,6 +24,7 @@ namespace TYPO3\CMS\Impexp\Task;
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
+use TYPO3\CMS\Backend\Utility\BackendUtility;
 
 /**
  * This class provides a textarea to save personal notes
@@ -134,7 +135,7 @@ class ImportExportTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
                                                'icon' => $icon,
                                                'title' => $title,
                                                'descriptionHtml' => implode('<br />', $description),
-                                               'link' => 'mod.php?M=user_task&SET[function]=impexp.tx_impexp_task&display=' . $presetCfg['uid']
+                                               'link' => BackendUtility::getModuleUrl('user_task') . '&SET[function]=impexp.tx_impexp_task&display=' . $presetCfg['uid']
                                        );
                                }
                                // Render preset list
index 051f596..0755745 100644 (file)
@@ -23,6 +23,7 @@ namespace TYPO3\CMS\Install\Report;
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
+use TYPO3\CMS\Backend\Utility\BackendUtility;
 
 /**
  * Provides an installation status report
@@ -135,7 +136,7 @@ class InstallStatusReport implements \TYPO3\CMS\Reports\StatusProviderInterface
                if (!\TYPO3\CMS\Core\Utility\GeneralUtility::compat_version(TYPO3_branch)) {
                        $value = $GLOBALS['LANG']->getLL('status_updateIncomplete');
                        $severity = \TYPO3\CMS\Reports\Status::WARNING;
-                       $url = 'mod.php?M=system_InstallInstall';
+                       $url = BackendUtility::getModuleUrl('system_InstallInstall');
                        $message = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.install_update'), '<a href="' . $url . '">', '</a>');
                }
                return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Reports\\Status', $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_remainingUpdates'), $value, $message, $severity);
index caa77a7..e44723b 100644 (file)
@@ -23,6 +23,9 @@ namespace TYPO3\CMS\Openid;
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
 /**
  * This class is the OpenID return script for the TYPO3 Backend (used in the user-settings module).
  *
@@ -62,9 +65,7 @@ class OpenidModuleSetup {
                        ' type="text" name="data[be_users][tx_openid_openid]"' .
                        ' value="' . htmlspecialchars($openid) . '" />' .
                        '&nbsp;&nbsp;<a href="#" onclick="' .
-                       'vHWin=window.open(\'../typo3/mod.php\?' .
-                       'M=openid_wizard&' .
-                       'P[itemName]=data%5Bbe_users%5D%5Btx_openid_openid%5D\'' .
+                       'vHWin=window.open(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('wizard_openid') . '&P[itemName]=data%5Bbe_users%5D%5Btx_openid_openid%5D') .
                        ',null,\'width=600,height=400,status=0,menubar=0,scrollbars=0\');' .
                        'vHWin.focus();return false;' .
                        '">' .
index 1c3006f..fdc17e2 100644 (file)
@@ -18,7 +18,9 @@ $tempColumns = array(
                                '0' => Array(
                                        'type' => 'popup',
                                        'title' => 'Add OpenID',
-                                       'script' => 'mod.php?M=openid_wizard',
+                                       'module' => array(
+                                               'name' => 'wizard_openid'
+                                       ),
                                        'icon' => 'EXT:openid/ext_icon.gif',
                                        'JSopenParams' => ',width=600,height=400,status=0,menubar=0,scrollbars=0',
                                )
@@ -51,7 +53,7 @@ $GLOBALS['TYPO3_USER_SETTINGS']['columns']['tx_openid_openid'] = array(
 if (TYPO3_MODE === 'BE') {
        // Register wizard
        \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModulePath(
-               'openid_wizard',
+               'wizard_openid',
                \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY) . 'wizard/'
        );
 }
index 483b160..73bc630 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 //required for mod.php
-$MCONF['name'] = 'openid_wizard';
+$MCONF['name'] = 'wizard_openid';
 $MCONF['script'] = '_DISPATCH';
 $MCONF['access'] = '';
 ?>
index 7313fc9..0794c9c 100644 (file)
@@ -24,6 +24,7 @@ namespace TYPO3\CMS\Reports\Report\Status;
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
 
+use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -79,7 +80,7 @@ class SecurityStatus implements \TYPO3\CMS\Reports\StatusProviderInterface {
                        if (!$secure) {
                                $value = $GLOBALS['LANG']->getLL('status_insecure');
                                $severity = \TYPO3\CMS\Reports\Status::ERROR;
-                               $editUserAccountUrl = 'alt_doc.php?returnUrl=' . urlencode('mod.php?M=system_ReportsTxreportsm1') . '&edit[be_users][' . $row['uid'] . ']=edit';
+                               $editUserAccountUrl = 'alt_doc.php?returnUrl=' . rawurlencode(BackendUtility::getModuleUrl('system_ReportsTxreportsm1')) . '&edit[be_users][' . $row['uid'] . ']=edit';
                                $message = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.backend_admin'), '<a href="' . $editUserAccountUrl . '">', '</a>');
                        }
                }
@@ -194,7 +195,7 @@ class SecurityStatus implements \TYPO3\CMS\Reports\StatusProviderInterface {
                if (!$validPassword) {
                        $value = $GLOBALS['LANG']->getLL('status_insecure');
                        $severity = \TYPO3\CMS\Reports\Status::ERROR;
-                       $changeInstallToolPasswordUrl = 'mod.php?M=system_InstallInstall';
+                       $changeInstallToolPasswordUrl = BackendUtility::getModuleUrl('system_InstallInstall');
                        $message = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.installtool_default_password'), '<a href="' . $changeInstallToolPasswordUrl . '">', '</a>');
                }
                return GeneralUtility::makeInstance('TYPO3\\CMS\\Reports\\Status', $GLOBALS['LANG']->getLL('status_installToolPassword'), $value, $message, $severity);
index a644ff2..1f6cb4c 100644 (file)
@@ -55,9 +55,17 @@ class ActionTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
        protected $hookObjects = array();
 
        /**
+        * URL to task module
+        *
+        * @var string
+        */
+       protected $moduleUrl;
+
+       /**
         * Constructor
         */
        public function __construct(\TYPO3\CMS\Taskcenter\Controller\TaskModuleController $taskObject) {
+               $this->moduleUrl = BackendUtility::getModuleUrl('user_task');
                $this->taskObject = $taskObject;
                $GLOBALS['LANG']->includeLLFile('EXT:sys_action/locallang.xlf');
                if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['sys_action']['tx_sysaction_task'])) {
@@ -176,7 +184,7 @@ class ActionTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
                                'title' => $actionRow['title'],
                                'description' => $actionRow['description'],
                                'descriptionHtml' => nl2br(htmlspecialchars($actionRow['description'])) . $editActionLink,
-                               'link' => 'mod.php?M=user_task&SET[function]=sys_action.tx_sysaction_task&show=' . $actionRow['uid'],
+                               'link' => $this->moduleUrl . '&SET[function]=sys_action.tx_sysaction_task&show=' . $actionRow['uid'],
                                'icon' => 'EXT:sys_action/sys_action.gif'
                        );
                }
@@ -202,7 +210,7 @@ class ActionTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
                }
                // Admin users can create a new action
                if ($GLOBALS['BE_USER']->isAdmin()) {
-                       $returnUrl = rawurlencode('mod.php?M=user_task');
+                       $returnUrl = rawurlencode($this->moduleUrl);
                        $link = GeneralUtility::getIndpEnv('TYPO3_REQUEST_DIR') . $GLOBALS['BACK_PATH'] . 'alt_doc.php?returnUrl=' . $returnUrl . '&edit[sys_action][0]=new';
                        $content .= '<br />
                                                <a href="' . $link . '" title="' . $GLOBALS['LANG']->getLL('new-sys_action') . '">' . '<img class="icon"' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/new_record.gif') . ' title="' . $GLOBALS['LANG']->getLL('new-sys_action') . '" alt="" /> ' . $GLOBALS['LANG']->getLL('new-sys_action') . '</a>';
@@ -337,7 +345,7 @@ class ActionTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
                        'tstamp' => $GLOBALS['ACCESS_TIME']
                ));
                // redirect to the original task
-               $redirectUrl = 'mod.php?M=user_task&show=' . $actionId;
+               $redirectUrl = $this->moduleUrl . '&show=' . $actionId;
                \TYPO3\CMS\Core\Utility\HttpUtility::redirect($redirectUrl);
        }
 
@@ -401,7 +409,7 @@ class ActionTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
                        $username .= ' (' . $realName . ')';
                }
                // Link to update the user record
-               $href = 'mod.php?M=user_task&SET[function]=sys_action.tx_sysaction_task&show=' . (int)$sysActionUid . '&be_users_uid=' . (int)$userId;
+               $href = $this->moduleUrl . '&SET[function]=sys_action.tx_sysaction_task&show=' . (int)$sysActionUid . '&be_users_uid=' . (int)$userId;
                $link = '<a href="' . htmlspecialchars($href) . '">' . htmlspecialchars($username) . '</a>';
                // Link to delete the user record
                $onClick = ' onClick="return confirm(' . GeneralUtility::quoteJSvalue($GLOBALS['LANG']->getLL('lDelete_warning')) . ');"';
@@ -634,7 +642,7 @@ class ActionTask implements \TYPO3\CMS\Taskcenter\TaskInterface {
         * @return void Redirect to form to create a record
         */
        protected function viewNewRecord($record) {
-               $returnUrl = rawurlencode('mod.php?M=user_task');
+               $returnUrl = rawurlencode($this->moduleUrl);
                $link = GeneralUtility::getIndpEnv('TYPO3_REQUEST_DIR') . $GLOBALS['BACK_PATH'] . 'alt_doc.php?returnUrl=' . $returnUrl . '&edit[' . $record['t3_tables'] . '][' . (int)$record['t3_listPid'] . ']=new';
                \TYPO3\CMS\Core\Utility\HttpUtility::redirect($link);
        }
index b355bed..833ab6f 100644 (file)
@@ -23,6 +23,7 @@ namespace TYPO3\CMS\SysAction;
  *
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
+use TYPO3\CMS\Backend\Utility\BackendUtility;
 
 /**
  * Adds action links to the backend's toolbar
@@ -117,7 +118,7 @@ class ActionToolbarMenu implements \TYPO3\CMS\Backend\Toolbar\ToolbarItemHookInt
                        while ($actionRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($queryResource)) {
                                $actions[] = array(
                                        $actionRow['title'],
-                                       'mod.php?M=user_task&SET[mode]=tasks&SET[function]=sys_action.TYPO3\\CMS\\SysAction\\ActionTask&show=' . $actionRow['uid'],
+                                       BackendUtility::getModuleUrl('user_task') . '&SET[mode]=tasks&SET[function]=sys_action.TYPO3\\CMS\\SysAction\\ActionTask&show=' . $actionRow['uid'],
                                        \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord('sys_action', $actionRow)
                                );
                        }
index dd3196c..edc07ce 100644 (file)
@@ -24,6 +24,7 @@ namespace TYPO3\CMS\Taskcenter\Controller;
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
 
+use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -288,7 +289,7 @@ class TaskModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClass {
                                        if (!$this->checkAccess($extKey, $taskClass)) {
                                                continue;
                                        }
-                                       $link = 'mod.php?M=user_task&SET[function]=' . $extKey . '.' . $taskClass;
+                                       $link = BackendUtility::getModuleUrl('user_task') . '&SET[function]=' . $extKey . '.' . $taskClass;
                                        $taskTitle = $GLOBALS['LANG']->sL($task['title']);
                                        $taskDescriptionHtml = '';
                                        // Check for custom icon