[BUGFIX] URL-encoded title in link wizard 40/23740/10
authorHelmut Hummel <helmut.hummel@typo3.org>
Wed, 11 Sep 2013 10:49:39 +0000 (12:49 +0200)
committerWouter Wolters <typo3@wouterwolters.nl>
Tue, 25 Feb 2014 19:50:31 +0000 (20:50 +0100)
The security fix introduced a bug that the title is encoded
every time the link wizard is opened, leading to multiple
encoded strings.

Solution is to not encode it centrally but encode it just
before using it in the JavaScript context.

Fixes: #41413
Releases: 4.5, 4.7, 6.0, 6.1, 6.2
Change-Id: I6b08db290d5457761edc4506105672d79840764d
Reviewed-on: https://review.typo3.org/23740
Reviewed-by: Markus Klein
Tested-by: Markus Klein
Reviewed-by: Oliver Klee
Reviewed-by: Wouter Wolters
Tested-by: Wouter Wolters
typo3/sysext/recordlist/Classes/Browser/ElementBrowser.php
typo3/sysext/rtehtmlarea/Classes/BrowseLinks.php

index ad3e9c0..3e75934 100644 (file)
@@ -386,30 +386,30 @@ class ElementBrowser {
                        $this->thisConfig = BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
                }
                // Initializing the target value (RTE)
-               $this->setTarget = $this->curUrlArray['target'] != '-' ? rawurlencode($this->curUrlArray['target']) : '';
+               $this->setTarget = ($this->curUrlArray['target'] != '-') ? $this->curUrlArray['target'] : '';
                if ($this->thisConfig['defaultLinkTarget'] && !isset($this->curUrlArray['target'])) {
                        $this->setTarget = $this->thisConfig['defaultLinkTarget'];
                }
                // Initializing the class value (RTE)
-               $this->setClass = $this->curUrlArray['class'] != '-' ? rawurlencode($this->curUrlArray['class']) : '';
+               $this->setClass = ($this->curUrlArray['class'] != '-') ? $this->curUrlArray['class'] : '';
                // Initializing the title value (RTE)
-               $this->setTitle = $this->curUrlArray['title'] != '-' ? rawurlencode($this->curUrlArray['title']) : '';
+               $this->setTitle = ($this->curUrlArray['title'] != '-') ? $this->curUrlArray['title'] : '';
                // Initializing the params value
-               $this->setParams = $this->curUrlArray['params'] != '-' ? rawurlencode($this->curUrlArray['params']) : '';
+               $this->setParams = ($this->curUrlArray['params'] != '-') ? $this->curUrlArray['params'] : '';
                // BEGIN accumulation of header JavaScript:
                $JScode = '
-                               // This JavaScript is primarily for RTE/Link. jumpToUrl is used in the other cases as well...
-                       var add_href="' . ($this->curUrlArray['href'] ? '&curUrl[href]=' . rawurlencode($this->curUrlArray['href']) : '') . '";
-                       var add_target="' . ($this->setTarget ? '&curUrl[target]=' . rawurlencode($this->setTarget) : '') . '";
-                       var add_class="' . ($this->setClass ? '&curUrl[class]=' . rawurlencode($this->setClass) : '') . '";
-                       var add_title="' . ($this->setTitle ? '&curUrl[title]=' . rawurlencode($this->setTitle) : '') . '";
-                       var add_params="' . ($this->bparams ? '&bparams=' . rawurlencode($this->bparams) : '') . '";
-
-                       var cur_href="' . ($this->curUrlArray['href'] ? rawurlencode($this->curUrlArray['href']) : '') . '";
-                       var cur_target="' . ($this->setTarget ?: '') . '";
-                       var cur_class = "' . ($this->setClass ?: '') . '";
-                       var cur_title="' . ($this->setTitle ?: '') . '";
-                       var cur_params="' . ($this->setParams ?: '') . '";
+                       // This JavaScript is primarily for RTE/Link. jumpToUrl is used in the other cases as well...
+                       var add_href=' . GeneralUtility::quoteJSvalue(($this->curUrlArray['href'] ? '&curUrl[href]=' . rawurlencode($this->curUrlArray['href']) : '')) . ';
+                       var add_target=' . GeneralUtility::quoteJSvalue(($this->setTarget ? '&curUrl[target]=' . rawurlencode($this->setTarget) : '')) . ';
+                       var add_class=' . GeneralUtility::quoteJSvalue(($this->setClass ? '&curUrl[class]=' . rawurlencode($this->setClass) : '')) . ';
+                       var add_title=' . GeneralUtility::quoteJSvalue(($this->setTitle ? '&curUrl[title]=' . rawurlencode($this->setTitle) : '')) . ';
+                       var add_params=' . GeneralUtility::quoteJSvalue(($this->bparams ? '&bparams=' . rawurlencode($this->bparams) : '')) . ';
+
+                       var cur_href=' . GeneralUtility::quoteJSvalue(($this->curUrlArray['href'] ? $this->curUrlArray['href'] : '')) . ';
+                       var cur_target=' . GeneralUtility::quoteJSvalue(($this->setTarget ? $this->setTarget : '')) . ';
+                       var cur_class=' . GeneralUtility::quoteJSvalue(($this->setClass ? $this->setClass : '')) . ';
+                       var cur_title=' . GeneralUtility::quoteJSvalue(($this->setTitle ? $this->setTitle : '')) . ';
+                       var cur_params=' . GeneralUtility::quoteJSvalue(($this->setParams ? $this->setParams : '')) . ';
 
                        function browse_links_setTarget(target) {       //
                                cur_target=target;
@@ -554,7 +554,8 @@ class ElementBrowser {
                                var add_act = URL.indexOf("act=")==-1 ? "&act=' . $this->act . '" : "";
                                var add_mode = URL.indexOf("mode=")==-1 ? "&mode=' . $this->mode . '" : "";
                                var theLocation = URL + add_act + add_mode + add_href + add_target + add_class + add_title + add_params'
-                                       . ($addPassOnParams ? '+"' . $addPassOnParams . '"' : '') . '+(typeof(anchor)=="string"?anchor:"");
+                                       . ($addPassOnParams ? '+"' . GeneralUtility::quoteJSvalue($addPassOnParams) . '"' : '')
+                                       . '+(typeof(anchor)=="string"?anchor:"");
                                window.location.href = theLocation;
                                return false;
                        }
@@ -973,13 +974,13 @@ class ElementBrowser {
                                                        // URL + onclick event:
                                                        $onClickEvent = '';
                                                        if (isset($v[$k2i . '.']['target'])) {
-                                                               $onClickEvent .= 'browse_links_setTarget(\'' . $v[($k2i . '.')]['target'] . '\');';
+                                                               $onClickEvent .= 'browse_links_setTarget(' . GeneralUtility::quoteJSvalue($v[($k2i . '.')]['target']) . ');';
                                                        }
                                                        $v[$k2i . '.']['url'] = str_replace('###_URL###', $this->siteURL, $v[$k2i . '.']['url']);
                                                        if (substr($v[$k2i . '.']['url'], 0, 7) === 'http://' || substr($v[$k2i . '.']['url'], 0, 7) === 'mailto:') {
-                                                               $onClickEvent .= 'cur_href=unescape(\'' . rawurlencode($v[($k2i . '.')]['url']) . '\');link_current();';
+                                                               $onClickEvent .= 'cur_href=' . GeneralUtility::quoteJSvalue($v[($k2i . '.')]['url']) . ';link_current();';
                                                        } else {
-                                                               $onClickEvent .= 'link_spec(unescape(\'' . $this->siteURL . rawurlencode($v[($k2i . '.')]['url']) . '\'));';
+                                                               $onClickEvent .= 'link_spec(' . GeneralUtility::quoteJSvalue($this->siteURL . $v[($k2i . '.')]['url']) . '));';
                                                        }
                                                        // Link:
                                                        $A = array('<a href="#" onclick="' . htmlspecialchars($onClickEvent) . 'return false;">', '</a>');
@@ -1530,8 +1531,8 @@ class ElementBrowser {
                                                                        'width="18" height="16"') . ' alt="" />'
                                                                . '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], ('gfx/ol/join'
                                                                        . ($skey + 3 > count($split) ? 'bottom' : '') . '.gif'), 'width="18" height="16"')
-                                                                       . ' alt="" />' . '<a href="#" onclick="return link_typo3Page(\'' . $expPageId
-                                                                       . '\',\'#' . rawurlencode($sval) . '\');">' . htmlspecialchars((' <A> ' . $sval))
+                                                                       . ' alt="" />' . '<a href="#" onclick="return link_typo3Page(' . GeneralUtility::quoteJSvalue($expPageId)
+                                                                       . ',' . GeneralUtility::quoteJSvalue('#' . $sval) . ';">' . htmlspecialchars((' <A> ' . $sval))
                                                                        . '</a><br />';
                                                }
                                        }
@@ -1924,9 +1925,9 @@ class ElementBrowser {
                $content .= $this->barheader(sprintf($GLOBALS['LANG']->getLL('folders') . ' (%s):', count($folders)));
                $titleLength = (int)$GLOBALS['BE_USER']->uc['titleLen'];
                // Create the header of current folder:
-               $aTag = '<a href="#" onclick="return insertElement(\'\',\'' . rawurlencode($baseFolderPath)
-                       . '\', \'folder\', \'' . rawurlencode($baseFolderPath) . '\', unescape(\'' . rawurlencode($baseFolderPath)
-                       . '\'), \'\', \'\',\'\',1);">';
+               $aTag = '<a href="#" onclick="return insertElement(\'\',' . GeneralUtility::quoteJSvalue($baseFolderPath)
+                       . ', \'folder\', ' . GeneralUtility::quoteJSvalue($baseFolderPath) . ', ' . GeneralUtility::quoteJSvalue($baseFolderPath)
+                       . ', \'\', \'\',\'\',1);">';
                // Add the foder icon
                $folderIcon = $aTag;
                $folderIcon .= '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/i/_icon_webfolders.gif',
@@ -1946,12 +1947,12 @@ class ElementBrowser {
                                . '" class="absmiddle" alt="" />';
                        // Create links for adding the folder:
                        if ($this->P['itemName'] != '' && $this->P['formName'] != '') {
-                               $aTag = '<a href="#" onclick="return set_folderpath(unescape(\'' . rawurlencode($folderPath)
-                                       . '\'));">';
+                               $aTag = '<a href="#" onclick="return set_folderpath(' . GeneralUtility::quoteJSvalue($folderPath)
+                                       . ');">';
                        } else {
-                               $aTag = '<a href="#" onclick="return insertElement(\'\',\'' . rawurlencode($folderPath)
-                                       . '\', \'folder\', \'' . rawurlencode($folderPath) . '\', unescape(\''
-                                       . rawurlencode($folderPath) . '\'), \'' . $pathInfo['extension'] . '\', \'\');">';
+                               $aTag = '<a href="#" onclick="return insertElement(\'\',' . GeneralUtility::quoteJSvalue($folderPath)
+                                       . ', \'folder\', ' . GeneralUtility::quoteJSvalue($folderPath) . ', '
+                                       . GeneralUtility::quoteJSvalue($folderPath) . ', \'' . $pathInfo['extension'] . '\', \'\');">';
                        }
                        if (strstr($folderPath, ',') || strstr($folderPath, '|')) {
                                // In case an invalid character is in the filepath, display error message:
@@ -2078,8 +2079,8 @@ class ElementBrowser {
                                        </tr>';
                                $lines[] = '
                                        <tr>
-                                               <td colspan="2"><img src="' . $iUrl . '" data-htmlarea-file-uid="' . $fileObject->getUid()
-                                       . '" width="' . $IW . '" height="' . $IH . '" border="1" alt="" /></td>
+                                               <td colspan="2"><img src="' . htmlspecialchars($iUrl) . '" data-htmlarea-file-uid="' . $fileObject->getUid()
+                                       . '" width="' . htmlspecialchars($IW) . '" height="' . htmlspecialchars($IH) . '" border="1" alt="" /></td>
                                        </tr>';
                                $lines[] = '
                                        <tr>
index b09665a..f90e5f8 100644 (file)
@@ -300,18 +300,18 @@ class BrowseLinks extends \TYPO3\CMS\Recordlist\Browser\ElementBrowser {
                $JScode .= '
                        var plugin = window.parent.RTEarea["' . $this->editorNo . '"].editor.getPlugin("TYPO3Link");
                        var HTMLArea = window.parent.HTMLArea;
-                       var add_href="' . ($this->curUrlArray['href'] ? '&curUrl[href]=' . rawurlencode($this->curUrlArray['href']) : '') . '";
-                       var add_target="' . ($this->setTarget ? '&curUrl[target]=' . rawurlencode($this->setTarget) : '') . '";
-                       var add_class="' . ($this->setClass ? '&curUrl[class]=' . rawurlencode($this->setClass) : '') . '";
-                       var add_title="' . ($this->setTitle ? '&curUrl[title]=' . rawurlencode($this->setTitle) : '') . '";
-                       var add_params="' . ($this->bparams ? '&bparams=' . rawurlencode($this->bparams) : '') . '";
-                       var additionalValues = ' . (count($this->additionalAttributes) ? json_encode($this->additionalAttributes) : '{}') . ';';
+                       var add_href=' . GeneralUtility::quoteJSvalue(($this->curUrlArray['href'] ? '&curUrl[href]=' . rawurlencode($this->curUrlArray['href']) : '')) . ';
+                       var add_target=' . GeneralUtility::quoteJSvalue(($this->setTarget ? '&curUrl[target]=' . rawurlencode($this->setTarget) : '')) . ';
+                       var add_class=' . GeneralUtility::quoteJSvalue(($this->setClass ? '&curUrl[class]=' . rawurlencode($this->setClass) : '')) . ';
+                       var add_title=' . GeneralUtility::quoteJSvalue(($this->setTitle ? '&curUrl[title]=' . rawurlencode($this->setTitle) : '')) . ';
+                       var add_params=' . GeneralUtility::quoteJSvalue(($this->bparams ? '&bparams=' . rawurlencode($this->bparams) : '')) . ';
+                       var additionalValues = ' . (count($this->additionalAttributes) ? json_encode($this->additionalAttributes, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) : '{}') . ';';
                // Attributes setting functions
                $JScode .= '
-                       var cur_href="' . ($this->curUrlArray['href'] ? ($this->curUrlInfo['query'] ? substr($this->curUrlArray['href'], 0, -strlen($this->curUrlInfo['query'])) : $this->curUrlArray['href']) : '') . '";
-                       var cur_target="' . ($this->setTarget ?: '') . '";
-                       var cur_class="' . ($this->setClass ?: '') . '";
-                       var cur_title="' . ($this->setTitle ?: '') . '";
+                       var cur_href="' . GeneralUtility::quoteJSvalue($this->curUrlArray['href'] ? ($this->curUrlInfo['query'] ? substr($this->curUrlArray['href'], 0, -strlen($this->curUrlInfo['query'])) : $this->curUrlArray['href']) : '') . '";
+                       var cur_target="' . GeneralUtility::quoteJSvalue($this->setTarget ?: '') . '";
+                       var cur_class="' . GeneralUtility::quoteJSvalue($this->setClass ?: '') . '";
+                       var cur_title="' . GeneralUtility::quoteJSvalue($this->setTitle ?: '') . '";
 
                        function browse_links_setTarget(value) {
                                cur_target=value;
@@ -410,6 +410,7 @@ class BrowseLinks extends \TYPO3\CMS\Recordlist\Browser\ElementBrowser {
                ';
                // Hook to overwrite or extend javascript functions
                if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['extendJScode']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['extendJScode'])) {
+                       $conf = array();
                        $_params = array(
                                'conf' => &$conf
                        );
@@ -628,9 +629,9 @@ class BrowseLinks extends \TYPO3\CMS\Recordlist\Browser\ElementBrowser {
                                                        }
                                                        $v[$k2i . '.']['url'] = str_replace('###_URL###', $this->siteURL, $v[$k2i . '.']['url']);
                                                        if (substr($v[$k2i . '.']['url'], 0, 7) == 'http://' || substr($v[$k2i . '.']['url'], 0, 7) == 'mailto:') {
-                                                               $onClickEvent .= 'cur_href=unescape(\'' . rawurlencode($v[($k2i . '.')]['url']) . '\');link_current();';
+                                                               $onClickEvent .= 'cur_href=' . GeneralUtility::quoteJSvalue($v[($k2i . '.')]['url']) . ';link_current();';
                                                        } else {
-                                                               $onClickEvent .= 'link_spec(unescape(\'' . $this->siteURL . rawurlencode($v[($k2i . '.')]['url']) . '\'));';
+                                                               $onClickEvent .= 'link_spec(' . GeneralUtility::quoteJSvalue($this->siteURL . $v[($k2i . '.')]['url']) . ');';
                                                        }
                                                        // Link:
                                                        $A = array('<a href="#" onclick="' . htmlspecialchars($onClickEvent) . 'return false;">', '</a>');
@@ -713,6 +714,7 @@ class BrowseLinks extends \TYPO3\CMS\Recordlist\Browser\ElementBrowser {
                $rel = $this->addRelField();
                // additional fields for links
                if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['addAttributeFields']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['addAttributeFields'])) {
+                       $conf = array();
                        $_params = array(
                                'conf' => &$conf
                        );