[BUGFIX] Correct record title escaping 79/48779/6
authorNicole Cordes <typo3@cordes.co>
Sat, 2 Jul 2016 17:26:08 +0000 (19:26 +0200)
committerMarkus Klein <markus.klein@typo3.org>
Mon, 25 Jul 2016 11:02:12 +0000 (13:02 +0200)
This patch removes default record title escaping in resolved DataProvider
data and adds proper escaping where html output is generated.

Resolves: #76399
Resolves: #76668
Resolves: #76900
Releases: master, 7.6
Change-Id: I03cf41c5200e920088116d1a67a2e342e46142d3
Reviewed-on: https://review.typo3.org/48779
Tested-by: Bamboo TYPO3com <info@typo3.com>
Tested-by: Susanne Moog <typo3@susannemoog.de>
Reviewed-by: Andreas Fernandez <typo3@scripting-base.de>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Michael Oehlhof <typo3@oehlhof.de>
Reviewed-by: Frederic Gaus <frederic.gaus@flagbit.de>
Tested-by: Frederic Gaus <frederic.gaus@flagbit.de>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
typo3/sysext/backend/Classes/Form/Container/InlineRecordContainer.php
typo3/sysext/backend/Classes/Form/Element/SelectCheckBoxElement.php
typo3/sysext/backend/Classes/Form/Element/SelectMultipleSideBySideElement.php
typo3/sysext/backend/Classes/Form/Element/SelectSingleElement.php
typo3/sysext/backend/Classes/Form/FormDataProvider/AbstractItemProvider.php
typo3/sysext/backend/Classes/Form/FormDataProvider/TcaRecordTitle.php
typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaRecordTitleTest.php

index cd75f7f..492487c 100644 (file)
@@ -305,7 +305,9 @@ class InlineRecordContainer extends AbstractContainer
         $objectId = $domObjectId . '-' . $foreignTable . '-' . $rec['uid'];
 
         $recordTitle = $data['recordTitle'];
-        if (empty($recordTitle)) {
+        if (!empty($recordTitle)) {
+            $recordTitle = BackendUtility::getRecordTitlePrep($recordTitle);
+        } else {
             $recordTitle = '<em>[' . htmlspecialchars($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.no_title')) . ']</em>';
         }
 
index 71b332a..3a7b672 100644 (file)
@@ -63,7 +63,7 @@ class SelectCheckBoxElement extends AbstractFormElement
                         $currentGroup++;
                         $groups[$currentGroup]['header'] = array(
                             'icon' => $selIcon,
-                            'title' => htmlspecialchars($p[0])
+                            'title' => $p[0]
                         );
                     } else {
                         // Check if some help text is available
@@ -103,7 +103,7 @@ class SelectCheckBoxElement extends AbstractFormElement
                             'disabled' => false,
                             'class' => '',
                             'icon' => FormEngineUtility::getIconHtml(!empty($p[2]) ? $p[2] : 'empty-empty'),
-                            'title' => htmlspecialchars($p[0], ENT_COMPAT, 'UTF-8', false),
+                            'title' => $p[0],
                             'help' => $help
                         );
                         $c++;
@@ -121,7 +121,7 @@ class SelectCheckBoxElement extends AbstractFormElement
                     $html[] = '<div class="panel-heading">';
                     $html[] = '<a data-toggle="collapse" href="#' . $groupId . '" aria-expanded="false" aria-controls="' . $groupId . '">';
                     $html[] = $group['header']['icon'];
-                    $html[] = $group['header']['title'];
+                    $html[] = htmlspecialchars($group['header']['title']);
                     $html[] = '</a>';
                     $html[] = '</div>';
                 }
@@ -145,7 +145,7 @@ class SelectCheckBoxElement extends AbstractFormElement
                         $tableRows[] =        '<label class="label-block" for="' . $item['id'] . '">' . $item['icon'] . '</label>';
                         $tableRows[] =    '</td>';
                         $tableRows[] =    '<td class="col-title">';
-                        $tableRows[] =        '<label class="label-block" for="' . $item['id'] . '">' . $item['title'] . '</label>';
+                        $tableRows[] =        '<label class="label-block" for="' . $item['id'] . '">' . htmlspecialchars($item['title'], ENT_COMPAT, 'UTF-8', false) . '</label>';
                         $tableRows[] =    '</td>';
                         $tableRows[] =    '<td class="text-right">' . $item['help'] . '</td>';
                         $tableRows[] = '</tr>';
index 0f24b84..61c89a8 100644 (file)
@@ -104,7 +104,7 @@ class SelectMultipleSideBySideElement extends AbstractFormElement
                     $disabledAttr = ' disabled="disabled"';
                     $classAttr = ' class="hidden"';
                 }
-                $opt[] = '<option value="' . htmlspecialchars($p[1]) . '" title="' . $p[0] . '"' . $classAttr . $disabledAttr . '>' . $p[0] . '</option>';
+                $opt[] = '<option value="' . htmlspecialchars($p[1]) . '" title="' . htmlspecialchars($p[0]) . '"' . $classAttr . $disabledAttr . '>' . htmlspecialchars($p[0]) . '</option>';
             }
             // Put together the selector box:
             $selector_itemListStyle = isset($config['itemListStyle'])
index 5ae43dc..0db1980 100644 (file)
@@ -106,7 +106,6 @@ class SelectSingleElement extends AbstractFormElement
                 );
             } else {
                 // IS ITEM
-                $title = htmlspecialchars($item['0'], ENT_COMPAT, 'UTF-8', false);
                 $icon = !empty($item[2]) ? FormEngineUtility::getIconHtml($item[2], $title, $title) : '';
                 $selected = $selectedValue === (string)$item[1];
 
@@ -115,7 +114,7 @@ class SelectSingleElement extends AbstractFormElement
                 }
 
                 $selectItemGroups[$selectItemGroupCount]['items'][] = array(
-                    'title' => $title,
+                    'title' => $item[0],
                     'value' => $item[1],
                     'icon' => $icon,
                     'selected' => $selected,
@@ -125,7 +124,7 @@ class SelectSingleElement extends AbstractFormElement
                 // ICON
                 if ($icon) {
                     $selectIcons[] = array(
-                        'title' => $title,
+                        'title' => $item[0],
                         'icon' => $icon,
                         'index' => $selectItemCounter,
                     );
@@ -155,7 +154,7 @@ class SelectSingleElement extends AbstractFormElement
                 foreach ($selectItemGroup['items'] as $item) {
                     $options .= '<option value="' . htmlspecialchars($item['value']) . '" data-icon="' .
                         htmlspecialchars($item['icon']) . '"'
-                        . ($item['selected'] ? ' selected="selected"' : '') . '>' . $item['title'] . '</option>';
+                        . ($item['selected'] ? ' selected="selected"' : '') . '>' . htmlspecialchars($item['title'], ENT_COMPAT, 'UTF-8', false) . '</option>';
                 }
                 $hasIcons = !empty($item['icon']);
             }
@@ -216,7 +215,7 @@ class SelectSingleElement extends AbstractFormElement
                 $html[] =            '<td>';
 
                 if (is_array($selectIcon)) {
-                    $html[] = '<a href="#" title="' . $selectIcon['title'] . '" data-select-index="' . $selectIcon['index'] . '">';
+                    $html[] = '<a href="#" title="' . htmlspecialchars($selectIcon['title'], ENT_COMPAT, 'UTF-8', false) . '" data-select-index="' . htmlspecialchars($selectIcon['index']) . '">';
                     $html[] = $selectIcon['icon'];
                     $html[] = '</a>';
                 }
index 3da5caa..e02820c 100644 (file)
@@ -483,7 +483,7 @@ abstract class AbstractItemProvider
                 }
                 // Add the item
                 $items[] = [
-                    $labelPrefix . htmlspecialchars(BackendUtility::getRecordTitle($foreignTable, $foreignRow)),
+                    $labelPrefix . BackendUtility::getRecordTitle($foreignTable, $foreignRow),
                     $foreignRow['uid'],
                     $icon
                 ];
index f53df8f..ca9d44a 100644 (file)
@@ -69,10 +69,7 @@ class TcaRecordTitle implements FormDataProviderInterface
             $fieldName = $result['isOnSymmetricSide']
                 ? $result['inlineParentConfig']['symmetric_label']
                 : $result['inlineParentConfig']['foreign_label'];
-            // @todo: this is a mixup here. problem is the prep method cuts the string, but also hsc's the thing.
-            // @todo: this is uncool for the userfuncs, so it is applied only here. however, the OuterWrapContainer
-            // @todo: also prep()'s the title created by the else patch below ... find a better separation and clean this up!
-            $result['recordTitle'] = BackendUtility::getRecordTitlePrep($this->getRecordTitleForField($fieldName, $result));
+            $result['recordTitle'] = $this->getRecordTitleForField($fieldName, $result);
         } elseif (isset($result['processedTca']['ctrl']['label_userFunc'])) {
             // userFunc takes precedence over everything else
             $parameters = [
@@ -127,7 +124,7 @@ class TcaRecordTitle implements FormDataProviderInterface
             }
         }
 
-        $result['recordTitle'] = htmlspecialchars(implode(', ', $titles));
+        $result['recordTitle'] = implode(', ', $titles);
         return $result;
     }
 
index 0caec2b..16d2888 100644 (file)
@@ -272,13 +272,6 @@ class TcaRecordTitleTest extends UnitTestCase
                 'aValue',
                 'aValue',
             ],
-            'html is escaped' => [
-                [
-                    'type' => 'input',
-                ],
-                '<foo>',
-                '&lt;foo&gt;',
-            ],
             'date input' => [
                 [
                     'type' => 'input',