[TASK] Streamline escaping for ViewHelpers of all sysexts 44/47644/12
authorBenni Mack <benni@typo3.org>
Wed, 13 Apr 2016 13:52:08 +0000 (15:52 +0200)
committerHelmut Hummel <helmut.hummel@typo3.org>
Wed, 20 Apr 2016 15:51:19 +0000 (17:51 +0200)
The Core does not strictly use $escapeChildren and
$escapeOutput as properly introduced by Fluid Standalone in 8.0.

This results in some weird HTML output when using the inline syntax
currently.

Since $escapeOutput and $escapeChildren is active by default,
some ViewHelpers even do HSC on their own (= twice) even if not
needed.

Resolves: #75575
Releases: master
Change-Id: I3bbebe75c0368519d3506360c68df92d30a3b80a
Reviewed-on: https://review.typo3.org/47644
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Helmut Hummel <helmut.hummel@typo3.org>
Reviewed-by: Nicole Cordes <typo3@cordes.co>
Tested-by: Nicole Cordes <typo3@cordes.co>
44 files changed:
typo3/sysext/belog/Classes/ViewHelpers/ErrorIconViewHelper.php
typo3/sysext/belog/Classes/ViewHelpers/FormatDetailsViewHelper.php
typo3/sysext/belog/Classes/ViewHelpers/HistoryEntryViewHelper.php
typo3/sysext/belog/Classes/ViewHelpers/UsernameViewHelper.php
typo3/sysext/belog/Classes/ViewHelpers/WorkspaceTitleViewHelper.php
typo3/sysext/beuser/Classes/ViewHelpers/Display/PagesViewHelper.php
typo3/sysext/beuser/Classes/ViewHelpers/Display/SysFileMountsViewHelper.php
typo3/sysext/beuser/Classes/ViewHelpers/Display/SysLanguageViewHelper.php
typo3/sysext/beuser/Classes/ViewHelpers/IssueCommandViewHelper.php
typo3/sysext/beuser/Classes/ViewHelpers/PermissionsViewHelper.php
typo3/sysext/beuser/Classes/ViewHelpers/RemoveUserViewHelper.php
typo3/sysext/beuser/Classes/ViewHelpers/SpriteIconForRecordViewHelper.php
typo3/sysext/beuser/Classes/ViewHelpers/SwitchUserViewHelper.php
typo3/sysext/core/Documentation/Changelog/master/Deprecation-75575-TranslateViewHelperHtmlEscapeArgumentMarkedAsDeprecated.rst [new file with mode: 0644]
typo3/sysext/documentation/Classes/ViewHelpers/FormatsViewHelper.php
typo3/sysext/extensionmanager/Classes/ViewHelpers/Format/JsonEncodeViewHelper.php
typo3/sysext/extensionmanager/Classes/ViewHelpers/Typo3DependencyViewHelper.php
typo3/sysext/extensionmanager/Resources/Private/Templates/Download/InstallFromTer.json
typo3/sysext/fluid/Classes/ViewHelpers/BaseViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Be/Buttons/CshViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Be/Buttons/ShortcutViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Be/InfoboxViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Be/TableListViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Format/BytesViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Format/CaseViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Format/CurrencyViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Format/HtmlViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Format/HtmlentitiesDecodeViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Format/NumberViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Format/PaddingViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Format/UrlencodeViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/TranslateViewHelper.php
typo3/sysext/fluid/Tests/Unit/ViewHelpers/TranslateViewHelperTest.php
typo3/sysext/indexed_search/Classes/ViewHelpers/Format/DateTimeViewHelper.php
typo3/sysext/indexed_search/Classes/ViewHelpers/Format/FlagValueViewHelper.php
typo3/sysext/indexed_search/Classes/ViewHelpers/Format/GroupListViewHelper.php
typo3/sysext/indexed_search/Classes/ViewHelpers/PageBrowsingViewHelper.php
typo3/sysext/install/Classes/ViewHelpers/File/ImageDimensionViewHelper.php
typo3/sysext/install/Classes/ViewHelpers/File/RelativePathViewHelper.php
typo3/sysext/install/Classes/ViewHelpers/File/SizeViewHelper.php
typo3/sysext/install/Classes/ViewHelpers/Format/CropViewHelper.php
typo3/sysext/install/Classes/ViewHelpers/Format/ImageMagickCommandsViewHelper.php
typo3/sysext/reports/Classes/ViewHelpers/IconViewHelper.php
typo3/sysext/sys_note/Classes/ViewHelpers/DeleteLinkViewHelper.php

index 1e28b2d..e4b8bcc 100644 (file)
@@ -26,6 +26,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class ErrorIconViewHelper extends AbstractBackendViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Renders an error icon link as known from the TYPO3 backend.
      * Error codes 2 and three are mapped to "error" and 1 is mapped to "warning".
      *
index e5be085..6013495 100644 (file)
@@ -68,7 +68,7 @@ class FormatDetailsViewHelper extends AbstractViewHelper
         $detailString = vsprintf($detailString, $substitutes);
         // Remove possible pending other %s
         $detailString = str_replace('%s', '', $detailString);
-        return htmlspecialchars($detailString);
+        return $detailString;
     }
 
     /**
index 15de558..04db501 100644 (file)
@@ -32,6 +32,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class HistoryEntryViewHelper extends AbstractViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Get system history record
      *
      * @param int $uid Uid of the log entry
@@ -89,6 +96,6 @@ class HistoryEntryViewHelper extends AbstractViewHelper
                 )
             );
         $historyLink = '<a href="' . htmlspecialchars($historyHref) . '" title="' . htmlspecialchars($titleLable) . '">' . $historyIcon . '</a>';
-        return $historyLabel . '&nbsp;' . $historyLink;
+        return htmlspecialchars($historyLabel) . '&nbsp;' . $historyLink;
     }
 }
index 3671539..e192bd4 100644 (file)
@@ -59,7 +59,7 @@ class UsernameViewHelper extends AbstractViewHelper
         $uid = $arguments['uid'];
 
         if (isset(static::$usernameRuntimeCache[$uid])) {
-            return htmlspecialchars(static::$usernameRuntimeCache[$uid]);
+            return static::$usernameRuntimeCache[$uid];
         }
 
         $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
@@ -68,6 +68,6 @@ class UsernameViewHelper extends AbstractViewHelper
         $user = $backendUserRepository->findByUid($uid);
         // $user may be NULL if user was deleted from DB, set it to empty string to always return a string
         static::$usernameRuntimeCache[$uid] = ($user === null) ? '' : $user->getUserName();
-        return htmlspecialchars(static::$usernameRuntimeCache[$uid]);
+        return static::$usernameRuntimeCache[$uid];
     }
 }
index 820f49f..c90d9c7 100644 (file)
@@ -59,7 +59,7 @@ class WorkspaceTitleViewHelper extends AbstractViewHelper
         $uid = $arguments['uid'];
 
         if (isset(static::$workspaceTitleRuntimeCache[$uid])) {
-            return htmlspecialchars(static::$workspaceTitleRuntimeCache[$uid]);
+            return static::$workspaceTitleRuntimeCache[$uid];
         }
 
         if ($uid === 0) {
@@ -75,6 +75,6 @@ class WorkspaceTitleViewHelper extends AbstractViewHelper
             static::$workspaceTitleRuntimeCache[$uid] = ($workspace === null) ? '' : $workspace->getTitle();
         }
 
-        return htmlspecialchars(static::$workspaceTitleRuntimeCache[$uid]);
+        return static::$workspaceTitleRuntimeCache[$uid];
     }
 }
index a502cd4..db3e39d 100644 (file)
@@ -24,6 +24,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class PagesViewHelper extends AbstractViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Render unordered list for pages
      *
      * @param string $uids
index 076febc..e56dbbc 100644 (file)
@@ -24,6 +24,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class SysFileMountsViewHelper extends AbstractViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Render unordered list for sys_filemounts
      *
      * @param string $uids
index 95e4c35..befbbb1 100644 (file)
@@ -24,6 +24,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class SysLanguageViewHelper extends AbstractViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Render unordered list for sys_language
      *
      * @param string $uids
index 869ad2e..7dcb825 100644 (file)
@@ -68,6 +68,6 @@ class IssueCommandViewHelper extends AbstractViewHelper
             $parametersArray = GeneralUtility::explodeUrl2Array($arguments['parameters']);
             $urlParameters += $parametersArray;
         }
-        return htmlspecialchars(BackendUtility::getModuleUrl('tce_db', $urlParameters));
+        return BackendUtility::getModuleUrl('tce_db', $urlParameters);
     }
 }
index 5c533db..a22cd35 100644 (file)
@@ -27,6 +27,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class PermissionsViewHelper extends AbstractViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * @var array Cached labels for a single permission mask like "Delete page"
      */
     protected static $permissionLabels = array();
@@ -76,18 +83,18 @@ class PermissionsViewHelper extends AbstractViewHelper
                 $mode = 'add';
             }
 
-            $label = htmlspecialchars(static::$permissionLabels[$mask]);
+            $label = static::$permissionLabels[$mask];
             $icon .= '<span style="cursor:pointer"'
-                . ' title="' . $label . '"'
+                . ' title="' . htmlspecialchars($label) . '"'
                 . ' data-toggle="tooltip"'
-                . ' data-page="' . $arguments['pageId'] . '"'
-                . ' data-permissions="' . $arguments['permission'] . '"'
-                . ' data-who="' . $arguments['scope'] . '"'
-                . ' data-bits="' . $mask . '"'
-                . ' data-mode="' . $mode . '"'
-                . ' class="t3-icon change-permission fa ' . $permissionClass . '"></span>';
+                . ' data-page="' . htmlspecialchars($arguments['pageId']) . '"'
+                . ' data-permissions="' . htmlspecialchars($arguments['permission']) . '"'
+                . ' data-who="' . htmlspecialchars($arguments['scope']) . '"'
+                . ' data-bits="' . htmlspecialchars($mask) . '"'
+                . ' data-mode="' . htmlspecialchars($mode) . '"'
+                . ' class="t3-icon change-permission fa ' . htmlspecialchars($permissionClass) . '"></span>';
         }
 
-        return '<span id="' . $arguments['pageId'] . '_' . $arguments['scope'] . '">' . $icon . '</span>';
+        return '<span id="' . htmlspecialchars($arguments['pageId'] . '_' . $arguments['scope']) . '">' . $icon . '</span>';
     }
 }
index 585d6a8..a71bb40 100644 (file)
@@ -32,6 +32,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class RemoveUserViewHelper extends AbstractViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Render link with sprite icon to remove user
      *
      * @param \TYPO3\CMS\Beuser\Domain\Model\BackendUser $backendUser Target backendUser to switch active session to
index 26751e1..ff3d5a3 100644 (file)
@@ -28,6 +28,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class SpriteIconForRecordViewHelper extends AbstractBackendViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Displays spriteIcon for database table and object
      *
      * @param string $table
@@ -53,7 +60,7 @@ class SpriteIconForRecordViewHelper extends AbstractBackendViewHelper
      * @param RenderingContextInterface $renderingContext
      *
      * @return string
-     * @throws Exception
+     * @throws \Exception
      */
     public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
     {
index d254daf..80e1982 100644 (file)
@@ -29,6 +29,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class SwitchUserViewHelper extends AbstractViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Render link with sprite icon to change current backend user to target
      *
      * @param BackendUser $backendUser Target backendUser to switch active session to
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-75575-TranslateViewHelperHtmlEscapeArgumentMarkedAsDeprecated.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-75575-TranslateViewHelperHtmlEscapeArgumentMarkedAsDeprecated.rst
new file mode 100644 (file)
index 0000000..088d6e3
--- /dev/null
@@ -0,0 +1,30 @@
+==================================================================================
+Deprecation: #75575 - TranslateViewHelper htmlEscape argument marked as deprecated
+==================================================================================
+
+Description
+===========
+
+The htmlEscape argument of the TranslateViewHelper has been marked as deprecated.
+
+This ViewHelper now HTML escapes the translation by default. The argument value has no effect any more.
+
+
+Impact
+======
+
+Usages of ``<f:translate>`` view helper with argument set to ``false`` will have the label HTML escaped anyway.
+
+Usages of ``<f:translate>`` view helper with argument set to ``true`` will have the label HTML escaped like before unless the view helper is wrapped with a ``<f:format.raw>``
+
+
+Affected Installations
+======================
+
+Installations with usages of ``<f:translate>`` in a context where HTML escaping is not desired (e.g. JavaScript).
+
+
+Migration
+=========
+
+``<f:translate>`` needs to be wrapped by ``<f:format.raw>`` if the view helper result is needed in a different context than HTML
\ No newline at end of file
index 376002d..88a1329 100644 (file)
@@ -30,6 +30,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class FormatsViewHelper extends AbstractViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Renders all format download links.
      *
      * @param \TYPO3\CMS\Documentation\Domain\Model\DocumentTranslation $documentTranslation
@@ -80,7 +87,7 @@ class FormatsViewHelper extends AbstractViewHelper
             $extension = substr($uri, strrpos($uri, '.') + 1);
             if (strlen($extension) < 5) {
                 // This is direct link to a file
-                $output .= 'href="' . $uri . '" class="btn btn-default"';
+                $output .= 'href="' . htmlspecialchars($uri) . '" class="btn btn-default"';
                 $iconHtml = static::getIconForFileExtension($extension, $iconFactory);
             } else {
                 $output .= 'href="#" onclick="top.TYPO3.Backend.ContentContainer.setUrl(' . GeneralUtility::quoteJSvalue($uri) . ')" class="btn btn-default"';
index 0206163..f44bce6 100644 (file)
@@ -26,6 +26,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class JsonEncodeViewHelper extends AbstractViewHelper
 {
     /**
+     * Rendered children is expected to be an array or object, which cannot be passed through htmlspecialchars.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
      * Constructor
      *
      * @api
index 97cf341..45a62a9 100644 (file)
@@ -29,6 +29,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class Typo3DependencyViewHelper extends AbstractViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Finds and returns the suitable TYPO3 versions of an extension
      *
      * @param Extension $extension
index 2e161dd..eae0355 100644 (file)
@@ -1,5 +1,5 @@
 {namespace em=TYPO3\CMS\Extensionmanager\ViewHelpers}
-<em:format.jsonEncode additionalAttributes="{
+<f:format.raw><em:format.jsonEncode additionalAttributes="{
        result: result,
        extension: extension.extensionKey,
        installationTypeLanguageKey: installationTypeLanguageKey,
@@ -7,4 +7,4 @@
        errorTitle: '{f:translate(key: \'downloadExtension.dependencies.errorTitle\')}',
        errorMessage: '{f:render(partial: \'List/UnresolvedDependencies\', arguments: \'{_all}\')}',
        skipDependencyUri: '{f:uri.action(action: \'installExtensionWithoutSystemDependencyCheck\', format: \'json\', arguments: \'{extension: extension}\')}'
-}" />
\ No newline at end of file
+}" /></f:format.raw>
\ No newline at end of file
index e3cb5c5..a1fe48e 100644 (file)
@@ -37,6 +37,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class BaseViewHelper extends AbstractViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Render the "Base" tag by outputting $request->getBaseUri()
      *
      * Note: renders as <base></base>, because IE6 will else refuse to display
index 02a055f..b1292cd 100644 (file)
@@ -43,6 +43,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class CshViewHelper extends AbstractBackendViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Render context sensitive help (CSH) for the given table
      *
      * @param string $table Table name ('_MOD_'+module name). If not set, the current module name will be used
index cb3fc4d..b9feb14 100644 (file)
@@ -46,6 +46,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class ShortcutViewHelper extends AbstractBackendViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Renders a shortcut button as known from the TYPO3 backend
      *
      * @param array $getVars list of GET variables to store. By default the current id, module and all module arguments will be stored
index 48390cb..2cb7830 100644 (file)
@@ -56,6 +56,8 @@ class InfoboxViewHelper extends AbstractViewHelper
     const STATE_ERROR = 2;
 
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
      * @var bool
      */
     protected $escapeOutput = false;
index e40c0ee..9f70a7a 100644 (file)
@@ -43,6 +43,14 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  */
 class TableListViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Be\AbstractBackendViewHelper
 {
+
+    /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
     /**
      * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
      */
index 7197065..42197f2 100644 (file)
@@ -45,6 +45,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class BytesViewHelper extends AbstractViewHelper
 {
     /**
+     * Output is escaped already. We must not escape children, to avoid double encoding.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
      * @var array
      */
     protected static $units = array();
index 22d0231..59f0be8 100644 (file)
@@ -92,6 +92,13 @@ class CaseViewHelper extends AbstractViewHelper
     const CASE_CAPITAL_WORDS = 'capitalWords';
 
     /**
+     * Output is escaped already. We must not escape children, to avoid double encoding.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
      * @var NULL|CharsetConverter
      */
     protected static $charsetConverter = null;
index d5476d6..b2725cb 100644 (file)
@@ -49,6 +49,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class CurrencyViewHelper extends AbstractViewHelper
 {
     /**
+     * Output is escaped already. We must not escape children, to avoid double encoding.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
      * @param string $currencySign (optional) The currency sign, eg $ or €.
      * @param string $decimalSeparator (optional) The separator for the decimal point.
      * @param string $thousandsSeparator (optional) The thousands separator.
index 389ac54..88cf715 100644 (file)
@@ -60,7 +60,7 @@ class HtmlViewHelper extends AbstractViewHelper
     protected static $tsfeBackup;
 
     /**
-     * Disable escaping of child nodes' output
+     * Children must not be escaped, to be able to pass {bodytext} directly to it
      *
      * @var bool
      */
index 369e943..9d6dca8 100644 (file)
@@ -41,6 +41,15 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class HtmlentitiesDecodeViewHelper extends AbstractEncodingViewHelper
 {
     /**
+     * We accept value and children interchangeably, thus we must disable children escaping.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
+     * If we decode, we must not encode again after that.
+     *
      * @var bool
      */
     protected $escapeOutput = false;
index 9cac862..a8af48f 100644 (file)
@@ -43,6 +43,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class NumberViewHelper extends AbstractViewHelper
 {
     /**
+     * Output is escaped already. We must not escape children, to avoid double encoding.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
      * Format the numeric value as a number with grouped thousands, decimal point and
      * precision.
      *
index 7ff0f9a..b260019 100644 (file)
@@ -49,6 +49,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class PaddingViewHelper extends AbstractViewHelper
 {
     /**
+     * Output is escaped already. We must not escape children, to avoid double encoding.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
      * Pad a string to a certain length with another string
      *
      * @param int $padLength Length of the resulting string. If the value of pad_length is negative or less than the length of the input string, no padding takes place.
index 6033c31..f7e251f 100644 (file)
@@ -43,14 +43,7 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class UrlencodeViewHelper extends AbstractViewHelper
 {
     /**
-     * Prevent escaping for further processing
-     *
-     * @var bool
-     */
-    protected $escapeOutput = false;
-
-    /**
-     * Prevent double escaping on child node's output
+     * Output is escaped already. We must not escape children, to avoid double encoding.
      *
      * @var bool
      */
index f12df4a..eac000f 100644 (file)
@@ -13,6 +13,7 @@ namespace TYPO3\CMS\Fluid\ViewHelpers;
  *
  * The TYPO3 project - inspiring people to share!
  */
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
 use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
 use TYPO3\CMS\Fluid\Core\ViewHelper\Exception\InvalidVariableException;
@@ -72,6 +73,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class TranslateViewHelper extends AbstractViewHelper
 {
     /**
+     * Output is escaped already. We must not escape children, to avoid double encoding.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
      * Render translation
      *
      * @param string $key Translation Key
@@ -116,6 +124,10 @@ class TranslateViewHelper extends AbstractViewHelper
         $extensionName = $arguments['extensionName'];
         $arguments = $arguments['arguments'];
 
+        if ($htmlEscape !== null) {
+            GeneralUtility::deprecationLog('htmlEscape argument has been deprecated and has no functionality any more. Please wrap the view helper in <f:format.raw> if you want to disable HTML escaping, which is enabled by default now.');
+        }
+
         // Wrapper including a compatibility layer for TYPO3 Flow Translation
         if ($id === null) {
             $id = $key;
@@ -133,8 +145,6 @@ class TranslateViewHelper extends AbstractViewHelper
             if (!empty($arguments)) {
                 $value = vsprintf($value, $arguments);
             }
-        } elseif ($htmlEscape) {
-            $value = htmlspecialchars($value);
         }
         return $value;
     }
index 9a70342..67b21cf 100644 (file)
@@ -69,14 +69,4 @@ class TranslateViewHelperTest extends ViewHelperBaseTestcase
         $this->injectDependenciesIntoViewHelper($this->subject);
         $this->assertEquals('default', $this->subject->render(null, 'bar', 'default'));
     }
-
-    /**
-     * @test
-     */
-    public function resultIsNotHtmlEscapedIfSoRequested()
-    {
-        $this->subject = GeneralUtility::makeInstance(TranslateViewHelperFixtureForTranslatedString::class);
-        $this->injectDependenciesIntoViewHelper($this->subject);
-        $this->assertEquals('&lt;p&gt;hello world&lt;/p&gt;', $this->subject->render('foo', null, null, true));
-    }
 }
index 731724c..a179e3e 100644 (file)
@@ -24,6 +24,14 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class DateTimeViewHelper extends AbstractViewHelper
 {
     /**
+     * The rendered children are fed into data() function, which expects an integer.
+     * It reduces overhead and is safe to disable children escaping here.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
      * Render the given timestamp as date & time
      *
      * @return string
@@ -46,6 +54,6 @@ class DateTimeViewHelper extends AbstractViewHelper
      */
     public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
     {
-        return htmlspecialchars(BackendUtility::datetime($renderChildrenClosure()));
+        return BackendUtility::datetime($renderChildrenClosure());
     }
 }
index 0804e5f..d8bfcce 100644 (file)
@@ -54,8 +54,7 @@ class FlagValueViewHelper extends AbstractViewHelper
             $content = ($flags & 128 ? '<title>' : '')
                 . ($flags & 64 ? '<meta/keywords>' : '')
                 . ($flags & 32 ? '<meta/description>' : '');
-
-            return htmlspecialchars($content);
+            return $content;
         }
         return '';
     }
index fd6fc5c..b537d57 100644 (file)
@@ -55,6 +55,6 @@ class GroupListViewHelper extends AbstractViewHelper
             $str[] = $row['gr_list'] === '0,-1' ? 'NL' : $row['gr_list'];
         }
         arsort($str);
-        return htmlspecialchars(implode('|', $str));
+        return implode('|', $str);
     }
 }
index 910a5bc..5e81406 100644 (file)
@@ -30,6 +30,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class PageBrowsingViewHelper extends AbstractViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * @var string
      */
     protected static $prefixId = 'tx_indexedsearch';
@@ -140,6 +147,6 @@ class PageBrowsingViewHelper extends AbstractViewHelper
             $onclick .= 'document.getElementById(' . GeneralUtility::quoteJSvalue(self::$prefixId . '_freeIndexUid') . ').value=' . GeneralUtility::quoteJSvalue($freeIndexUid) . ';';
         }
         $onclick .= 'document.getElementById(' . GeneralUtility::quoteJSvalue(self::$prefixId) . ').submit();return false;';
-        return '<a href="#" onclick="' . htmlspecialchars($onclick) . '">' . $str . '</a>';
+        return '<a href="#" onclick="' . htmlspecialchars($onclick) . '">' . htmlspecialchars($str) . '</a>';
     }
 }
index 6a79ecc..05ac08f 100644 (file)
@@ -34,6 +34,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class ImageDimensionViewHelper extends AbstractViewHelper
 {
     /**
+     * Output is escaped already. We must not escape children, to avoid double encoding.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
      * Get width / height from image file
      *
      * @param string $dimension Either width or height
@@ -55,6 +62,7 @@ class ImageDimensionViewHelper extends AbstractViewHelper
      * @param array $arguments
      * @param \Closure $renderChildrenClosure
      * @param RenderingContextInterface $renderingContext
+     * @throws \TYPO3\CMS\Install\ViewHelpers\Exception
      *
      * @return string
      */
index b30343f..babbffb 100644 (file)
@@ -34,6 +34,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class RelativePathViewHelper extends AbstractViewHelper
 {
     /**
+     * Output is escaped already. We must not escape children, to avoid double encoding.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
      * Get relative path
      *
      * @return string Relative path
index 2e872f5..8a5cee0 100644 (file)
@@ -35,6 +35,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class SizeViewHelper extends AbstractViewHelper
 {
     /**
+     * Output is escaped already. We must not escape children, to avoid double encoding.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
      * Get size from file
      *
      * @param bool $format If true, file size will be formatted
@@ -56,6 +63,7 @@ class SizeViewHelper extends AbstractViewHelper
      * @param array $arguments
      * @param \Closure $renderChildrenClosure
      * @param RenderingContextInterface $renderingContext
+     * @throws \TYPO3\CMS\Install\ViewHelpers\Exception
      *
      * @return string
      */
index 7a3d28f..6bc4c22 100644 (file)
@@ -42,6 +42,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class CropViewHelper extends AbstractViewHelper
 {
     /**
+     * Output is escaped already. We must not escape children, to avoid double encoding.
+     *
+     * @var bool
+     */
+    protected $escapeChildren = false;
+
+    /**
      * Render the cropped text
      *
      * @param int $maxCharacters Place where to truncate the string
index be58c8e..3919702 100644 (file)
@@ -25,6 +25,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class ImageMagickCommandsViewHelper extends AbstractViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Display image magick commands
      *
      * @param array $commands Given commands
@@ -54,10 +61,10 @@ class ImageMagickCommandsViewHelper extends AbstractViewHelper
 
         $result = array();
         foreach ($commands as $commandGroup) {
-            $result[] = '<strong>Command:</strong>' . LF . $commandGroup[1];
+            $result[] = '<strong>Command:</strong>' . LF . htmlspecialchars($commandGroup[1]);
             // If 3 elements: last one is result
             if (count($commandGroup) === 3) {
-                $result[] = '<strong>Result:</strong>' . LF . $commandGroup[2];
+                $result[] = '<strong>Result:</strong>' . LF . htmlspecialchars($commandGroup[2]);
             }
         }
         return '<pre><code class="language-bash">' . implode(LF, $result) . '</code></pre>';
index bfdf6dc..2e467f5 100644 (file)
@@ -27,6 +27,13 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 class IconViewHelper extends AbstractBackendViewHelper
 {
     /**
+     * As this ViewHelper renders HTML, the output must not be escaped.
+     *
+     * @var bool
+     */
+    protected $escapeOutput = false;
+
+    /**
      * Renders the icon
      *
      * @param string $icon Icon to be used
index 630778c..a3ab49e 100644 (file)
@@ -56,7 +56,6 @@ class DeleteLinkViewHelper extends AbstractViewHelper
             'cmd[sys_note][' . $arguments['id'] . '][delete]' => 1,
             'redirect' => GeneralUtility::getIndpEnv('REQUEST_URI')
         ];
-        $url = BackendUtility::getModuleUrl('tce_db', $urlParameters);
-        return htmlspecialchars($url);
+        return BackendUtility::getModuleUrl('tce_db', $urlParameters);
     }
 }