[BUGFIX] Fix broken Fluid templates 50/62450/2
authorPatrick Broens <patrick@patrickbroens.nl>
Thu, 28 Nov 2019 14:09:18 +0000 (15:09 +0100)
committerSusanne Moog <look@susi.dev>
Fri, 29 Nov 2019 21:24:59 +0000 (22:24 +0100)
In some versions of PHP there is a PCRE bug, which will be triggered when
using an unquoted array syntax in Fluid templates, leading to an error
and possibly not able to display the rendered template.

This is solved by using the quoted array syntax where it is not used yet.

Resolves: #87970
Releases: master, 9.5
Change-Id: I36f4ee86765fae24f7daa0e7e59ff9fc6741144f
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/62450
Reviewed-by: Rens Admiraal <rens@simplyadmire.com>
Reviewed-by: Alexander Schnitzler <review.typo3.org@alexanderschnitzler.de>
Reviewed-by: Claus Due <claus@phpmind.net>
Reviewed-by: Benni Mack <benni@typo3.org>
Reviewed-by: Susanne Moog <look@susi.dev>
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Benni Mack <benni@typo3.org>
Tested-by: Susanne Moog <look@susi.dev>
15 files changed:
typo3/sysext/backend/Resources/Private/Partials/ContextSensitiveHelp/TableOfContents.html
typo3/sysext/backend/Resources/Private/Templates/ContextSensitiveHelp/Index.html
typo3/sysext/backend/Resources/Private/Templates/SiteConfiguration/Edit.html
typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/UserToolbarItemDropDown.html
typo3/sysext/beuser/Resources/Private/Templates/Permission/Index.html
typo3/sysext/extensionmanager/Resources/Private/Partials/List/UnresolvedDependencies.html
typo3/sysext/extensionmanager/Resources/Private/Templates/List/Index.html
typo3/sysext/felogin/Resources/Private/Email/Templates/PasswordRecovery.html
typo3/sysext/filelist/Resources/Private/Templates/FileList/Search.html
typo3/sysext/fluid/Resources/Private/Templates/ViewHelpers/Be/Widget/Paginate/Index.html
typo3/sysext/redirects/Resources/Private/Partials/Pagination.html
typo3/sysext/redirects/Resources/Private/Templates/Management/Overview.html
typo3/sysext/reports/Resources/Private/Templates/Report/Index.html
typo3/sysext/scheduler/Resources/Private/Partials/Backend/SchedulerModule/TaskList.html
typo3/sysext/tstemplate/Resources/Private/Templates/PageZero.html

index fbfb5f1..5f05066 100644 (file)
@@ -25,7 +25,7 @@
                                     <a href="#{module}">{module}</a>
                                 </f:then>
                                 <f:else>
-                                    <a href="{be:moduleLink(route:'help_cshmanual',arguments:{action:'detail', table:module,field:'*'})}">
+                                    <a href="{be:moduleLink(route:'help_cshmanual',arguments:'{action:\'detail\', table:module,field:\'*\'}')}">
                                         {title}
                                     </a>
                                 </f:else>
index 16c180d..0ac2d33 100644 (file)
@@ -8,7 +8,7 @@
 <f:section name="content">
     <f:render partial="ContextSensitiveHelp/TableOfContents" arguments="{toc:toc,all:0}" />
 
-    <a href="{be:moduleLink(route:'help_cshmanual',arguments:{action:'all'})}">
+    <a href="{be:moduleLink(route:'help_cshmanual',arguments:'{action:\'all\'}')}">
         <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_view_help.xlf:full_manual" />
     </a>
 </f:section>
index 28feb0d..be3c877 100644 (file)
@@ -1,6 +1,6 @@
 <f:be.pageRenderer includeRequireJsModules="{0: 'TYPO3/CMS/Backend/SiteInlineActions'}" />
 <form
-    action="{f:be.uri(route:'site_configuration', parameters:{action: 'save'})}"
+    action="{f:be.uri(route:'site_configuration', parameters:'{action: \'save\'}')}"
     method="post"
     enctype="multipart/form-data"
     name="editform"
index dd98b99..a595d31 100644 (file)
@@ -33,7 +33,7 @@
                     <be:avatar backendUser="{user.uid}" size="32" />
                 </div>
                 <div class="dropdown-table-column dropdown-table-title">
-                    <a href="{user.switchUserLink}" title="{f:translate(key: 'usermodule.su.tooltip', arguments: {0: user.username})}">
+                    <a href="{user.switchUserLink}" title="{f:translate(key: 'usermodule.su.tooltip', arguments: '{0: user.username}')}">
                         <f:if condition="{user.realName}">
                             <f:then>
                                 {user.realName}
index 194907c..4ecd067 100644 (file)
@@ -37,7 +37,7 @@
                                 <td align="left" class="nowrap">
                                     <f:link.action
                                         action="edit"
-                                        arguments="{id: '{f:if(condition: data.row._ORIG_uid, then: data.row._ORIG_uid, else: data.row.uid)}', depth: depth, returnUrl: '{f:uri.action(action: \'index\', arguments: {id: currentId, depth: depth})}'}"
+                                        arguments="{id: '{f:if(condition: data.row._ORIG_uid, then: data.row._ORIG_uid, else: data.row.uid)}', depth: depth, returnUrl: '{f:uri.action(action: \'index\', arguments: \'{id: currentId, depth: depth}\')}'}"
                                         title="{f:translate(key: 'LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:ch_permissions')}"
                                     >
                                         <f:format.raw>{data.depthData}{data.HTML}</f:format.raw>
@@ -51,7 +51,7 @@
                                     </f:comment>
                                     <f:link.action
                                         action="edit"
-                                        arguments="{id: '{f:if(condition: data.row._ORIG_uid, then: data.row._ORIG_uid, else: data.row.uid)}', depth: depth, returnUrl: '{f:uri.action(action: \'index\', arguments: {id: currentId, depth: depth})}'}"
+                                        arguments="{id: '{f:if(condition: data.row._ORIG_uid, then: data.row._ORIG_uid, else: data.row.uid)}', depth: depth, returnUrl: '{f:uri.action(action: \'index\', arguments: \'{id: currentId, depth: depth}\')}'}"
                                         class="btn btn-default"
                                         title="{f:translate(key: 'LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:ch_permissions')}"
                                     >
index 27286b1..d7903fb 100644 (file)
@@ -10,7 +10,7 @@
     <f:for each="{unresolvedDependencies}" key="key" as="messages">
         <f:if condition="{key} != {extension.extensionKey}">
             <li>
-                <strong>{f:translate(key: 'dependencyCheck.requiredExtension', arguments: {key: key}) -> f:format.htmlspecialchars()}</strong>
+                <strong>{f:translate(key: 'dependencyCheck.requiredExtension', arguments: '{key: key}') -> f:format.htmlspecialchars()}</strong>
                 <ul>
                     <f:for each="{messages}" as="message">
                         <li>{message.message -> f:format.htmlspecialchars()}</li>
index eb96c6a..318cd3c 100644 (file)
@@ -52,7 +52,7 @@
                                         additionalAttributes="{data-action:'update-extension'}"
                                         format="json" controller="Download"
                                         arguments="{extension:extension.key, integerVersionStart: extension.terObject.integerVersion, integerVersionStop: extension.updateToVersion.integerVersion}"
-                                        title="{f:translate(key:'extensionList.updateToVersion', arguments:{0:extension.updateToVersion.version})}"
+                                        title="{f:translate(key:'extensionList.updateToVersion', arguments:'{0:extension.updateToVersion.version}')}"
                                     >
                                         <core:icon identifier="actions-system-extension-update" />
                                     </f:link.action>
index 8130bd3..16e6186 100644 (file)
@@ -7,7 +7,7 @@
     {f:translate(
     key: 'forgot_validate_reset_password_html',
     extensionName: 'felogin',
-    arguments: { 0: receiverName, 1: recoveryLink, 2: validUntil }
+    arguments: '{ 0: receiverName, 1: recoveryLink, 2: validUntil }'
     ) -> f:format.html()}
 </f:spaceless>
 </html>
index e9bb153..272cc6e 100644 (file)
@@ -42,7 +42,7 @@
                         <td class="col-title col-responsive nowrap">
                             <f:if condition="{file.isMetadataEditable}">
                                 <f:then>
-                                    <a href="{be:uri.editRecord( uid:file.metadataUid, table:'sys_file_metadata', returnUrl:'{f:uri.action( action:\'search\', arguments:{ searchWord:\'{searchWord->f:format.htmlentities()}\' } ) -> f:format.raw()}' )}"
+                                    <a href="{be:uri.editRecord( uid:file.metadataUid, table:'sys_file_metadata', returnUrl:'{f:uri.action( action:\'search\', arguments:\'{ searchWord:\\'{searchWord->f:format.htmlentities()}\\' }\' ) -> f:format.raw()}' )}"
                                         class="filelist-file-title"
                                         title="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.editMetadata' )}"
                                     >
@@ -62,7 +62,7 @@
                             <div class="btn-group">
                                 <f:if condition="{file.isEditable}">
                                     <f:then>
-                                        <a href="{fl:uri.editFileContent( file:file.resource, returnUrl:'{f:uri.action( action:\'search\', arguments:{ searchWord:\'{searchWord->f:format.htmlentities()}\' } ) -> f:format.raw()}' )}"
+                                        <a href="{fl:uri.editFileContent( file:file.resource, returnUrl:'{f:uri.action( action:\'search\', arguments:\'{ searchWord:\\'{searchWord->f:format.htmlentities()}\\' }\' ) -> f:format.raw()}' )}"
                                             class="btn btn-default filelist-file-edit"
                                             title="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.editcontent' )}"
                                         >
@@ -76,7 +76,7 @@
 
                                 <f:if condition="{file.IsMetadataEditable}">
                                     <f:then>
-                                        <a href="{be:uri.editRecord(uid:file.metadataUid, table:'sys_file_metadata', returnUrl:'{f:uri.action( action:\'search\', arguments:{ searchWord:\'{searchWord->f:format.htmlentities()}\' } ) -> f:format.raw()}' )}"
+                                        <a href="{be:uri.editRecord(uid:file.metadataUid, table:'sys_file_metadata', returnUrl:'{f:uri.action( action:\'search\', arguments:\'{ searchWord:\\'{searchWord->f:format.htmlentities()}\\' }\' ) -> f:format.raw()}' )}"
                                             class="btn btn-default filelist-file-edit"
                                             title="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.editMetadata' )}"
                                         >
 
                                 <f:if condition="{file.isReplaceable}">
                                     <f:then>
-                                        <a href="{fl:uri.replaceFile( file:file.resource, returnUrl:'{f:uri.action( action:\'search\', arguments:{ searchWord:\'{searchWord->f:format.htmlentities()}\' } ) -> f:format.raw()}' )}"
+                                        <a href="{fl:uri.replaceFile( file:file.resource, returnUrl:'{f:uri.action( action:\'search\', arguments:\'{ searchWord:\\'{searchWord->f:format.htmlentities()}\\' }\' ) -> f:format.raw()}' )}"
                                             class="btn btn-default filelist-file-replace"
                                             title="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.replace' )}"
                                         >
 
                                 <f:if condition="{file.isRenamable}">
                                     <f:then>
-                                        <a href="{fl:uri.renameFile( file:file.resource, returnUrl:'{f:uri.action( action:\'search\', arguments:{ searchWord:\'{searchWord->f:format.htmlentities()}\' } ) -> f:format.raw()}' )}"
+                                        <a href="{fl:uri.renameFile( file:file.resource, returnUrl:'{f:uri.action( action:\'search\', arguments:\'{ searchWord:\\'{searchWord->f:format.htmlentities()}\\' }\' ) -> f:format.raw()}' )}"
                                             class="btn btn-default filelist-file-rename"
                                             title="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.rename' )}"
                                         >
                                         <a href="{fl:uri.copyCutFile( file:file.resource, copyOrCut: 'copy' )}"
                                             class="btn btn-default filelist-file-copy"
                                             title="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.copy' )}"
-                                            data-redirect-url="{f:uri.action( action:'search', arguments:{ searchWord:'{searchWord->f:format.htmlentities()}' } )}"
+                                            data-redirect-url="{f:uri.action( action:'search', arguments:'{ searchWord:\'{searchWord->f:format.htmlentities()}\' }' )}"
                                         >
                                             <f:if condition="{file.selected} == 'copy'">
                                                 <f:then><core:icon identifier="actions-edit-copy-release" /></f:then>
                                             title="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.delete' )}"
                                             data-identifier="{file.identifier}"
                                             data-title="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.delete' )}"
-                                            data-content="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:mess.delete', arguments: {0:file.name} )}"
+                                            data-content="{f:translate( key:'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:mess.delete', arguments: '{0:file.name}' )}"
                                             data-check="{f:if(condition:settings.jsConfirmationDelete, then:'1', else:'0')}"
                                             data-delete-url="{deleteUrl}"
                                             data-delete-type="delete_file"
-                                            data-redirect-url="{f:uri.action( action:'search', arguments:{ searchWord:'{searchWord->f:format.htmlentities()}' } )}"
+                                            data-redirect-url="{f:uri.action( action:'search', arguments:'{ searchWord:\'{searchWord->f:format.htmlentities()}\' }' )}"
                                         >
                                             <core:icon identifier="actions-edit-delete" />
                                         </a>
index d27ecb2..318dcb5 100644 (file)
             <f:if condition="{pagination.hasLessPages}">
                 <f:then>
                     <li>
-                        <a href="{f:widget.uri(arguments:{currentPage: 1})}" title="{f:translate(key:'widget.pagination.first')}">
+                        <a href="{f:widget.uri(arguments:'{currentPage: 1}')}" title="{f:translate(key:'widget.pagination.first')}">
                             <core:icon identifier="actions-view-paging-first" />
                         </a>
                     </li>
                     <li>
-                        <a href="{f:widget.uri(arguments:{currentPage: pagination.previousPage})}" title="{f:translate(key:'widget.pagination.previous')}">
+                        <a href="{f:widget.uri(arguments:'{currentPage: pagination.previousPage}')}" title="{f:translate(key:'widget.pagination.previous')}">
                             <core:icon identifier="actions-view-paging-previous" />
                         </a>
                     </li>
@@ -74,7 +74,7 @@
                     <f:translate key="widget.pagination.page" />
 
                     <form onsubmit="return goToPage(this);" style="display:inline;">
-                        <f:form.textfield additionalAttributes="{min: '1', data-number-of-pages: '{pagination.numberOfPages}', data-url: '{f:widget.uri(arguments:{currentPage: 987654321})}'}" name="paginator-target-page" class="form-control input-sm paginator-input" size="5" value="{pagination.current}" type="number" />
+                        <f:form.textfield additionalAttributes="{min: '1', data-number-of-pages: '{pagination.numberOfPages}', data-url: '{f:widget.uri(arguments:\'{currentPage: 987654321}\')}'}" name="paginator-target-page" class="form-control input-sm paginator-input" size="5" value="{pagination.current}" type="number" />
                     </form>
 
                     / {pagination.numberOfPages}
             <f:if condition="{pagination.hasMorePages}">
                 <f:then>
                     <li>
-                        <a href="{f:widget.uri(arguments:{currentPage: pagination.nextPage})}" title="{f:translate(key:'widget.pagination.next')}">
+                        <a href="{f:widget.uri(arguments:'{currentPage: pagination.nextPage}')}" title="{f:translate(key:'widget.pagination.next')}">
                             <core:icon identifier="actions-view-paging-next" />
                         </a>
                     </li>
                     <li>
-                        <a href="{f:widget.uri(arguments:{currentPage: pagination.numberOfPages})}" title="{f:translate(key:'widget.pagination.last')}">
+                        <a href="{f:widget.uri(arguments:'{currentPage: pagination.numberOfPages}')}" title="{f:translate(key:'widget.pagination.last')}">
                             <core:icon identifier="actions-view-paging-last" />
                         </a>
                     </li>
                 </f:else>
             </f:if>
             <li>
-                <a href="{f:widget.uri(arguments:{currentPage: pagination.current})}" title="{f:translate(key:'widget.pagination.refresh')}">
+                <a href="{f:widget.uri(arguments:'{currentPage: pagination.current}')}" title="{f:translate(key:'widget.pagination.refresh')}">
                     <core:icon identifier="actions-refresh" />
                 </a>
             </li>
index 1e2625c..1e91364 100644 (file)
         <f:if condition="{pagination.hasLessPages}">
             <f:then>
                 <li>
-                    <a href="{f:be.uri(route:'site_redirects', parameters: {action: 'overview', demand: demand.parameters, page: 1})}" title="{f:translate(extensionName: 'fluid', key:'widget.pagination.first')}">
+                    <a href="{f:be.uri(route:'site_redirects', parameters: '{action: \'overview\', demand: demand.parameters, page: 1}')}" title="{f:translate(extensionName: 'fluid', key:'widget.pagination.first')}">
                         <core:icon identifier="actions-view-paging-first" />
                     </a>
                 </li>
                 <li>
-                    <a href="{f:be.uri(route:'site_redirects', parameters: {action: 'overview', demand: demand.parameters, page: pagination.previousPage})}" title="{f:translate(extensionName: 'fluid', key:'widget.pagination.previous')}">
+                    <a href="{f:be.uri(route:'site_redirects', parameters: '{action: \'overview\', demand: demand.parameters, page: pagination.previousPage}')}" title="{f:translate(extensionName: 'fluid', key:'widget.pagination.previous')}">
                         <core:icon identifier="actions-view-paging-previous" />
                     </a>
                 </li>
         <f:if condition="{pagination.hasMorePages}">
             <f:then>
                 <li>
-                    <a href="{f:be.uri(route:'site_redirects', parameters: {action: 'overview', demand: demand.parameters, page: pagination.nextPage})}" title="{f:translate(extensionName: 'fluid', key:'widget.pagination.next')}">
+                    <a href="{f:be.uri(route:'site_redirects', parameters: '{action: \'overview\', demand: demand.parameters, page: pagination.nextPage}')}" title="{f:translate(extensionName: 'fluid', key:'widget.pagination.next')}">
                         <core:icon identifier="actions-view-paging-next" />
                     </a>
                 </li>
                 <li>
-                    <a href="{f:be.uri(route:'site_redirects', parameters: {action: 'overview', demand: demand.parameters, page: pagination.numberOfPages})}" title="{f:translate(extensionName: 'fluid', key:'widget.pagination.last')}">
+                    <a href="{f:be.uri(route:'site_redirects', parameters: '{action: \'overview\', demand: demand.parameters, page: pagination.numberOfPages}')}" title="{f:translate(extensionName: 'fluid', key:'widget.pagination.last')}">
                         <core:icon identifier="actions-view-paging-last" />
                     </a>
                 </li>
@@ -97,7 +97,7 @@
             </f:else>
         </f:if>
         <li>
-            <a href="{f:be.uri(route:'site_redirects', parameters: {action: 'overview', demand: demand.parameters, page: demand.page})}" title="{f:translate(extensionName: 'fluid', key:'widget.pagination.refresh')}">
+            <a href="{f:be.uri(route:'site_redirects', parameters: '{action: \'overview\', demand: demand.parameters, page: demand.page}')}" title="{f:translate(extensionName: 'fluid', key:'widget.pagination.refresh')}">
                 <core:icon identifier="actions-refresh" />
             </a>
         </li>
index 9a47b82..0ce3d89 100644 (file)
@@ -21,7 +21,7 @@
                     <f:render section="filter" arguments="{_all}" />
                     <f:be.infobox state="-2" title="{f:translate(key: 'LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:redirect_not_found_with_filter.title')}">
                         <p><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:redirect_not_found_with_filter.message"/></p>
-                        <a class="btn btn-default" href="{f:be.uri(route:'site_redirects', parameters: {action: 'overview'})}">
+                        <a class="btn btn-default" href="{f:be.uri(route:'site_redirects', parameters: '{action: \'overview\'}')}">
                             <f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:redirect_no_filter"/>
                         </a>
                         <be:link.newRecord class="btn btn-primary" table="sys_redirect">
 </f:section>
 
 <f:section name="filter">
-    <form action="{f:be.uri(route:'site_redirects', parameters: {action: 'overview'})}"
+    <form action="{f:be.uri(route:'site_redirects', parameters: '{action: \'overview\'}')}"
         method="post"
         enctype="multipart/form-data"
         name="demand"
index f944575..aa88af8 100644 (file)
@@ -14,7 +14,7 @@
         <f:for each="{reports}" as="reportOverview" key="extensionKey">
             <f:for each="{reportOverview}" key="reportName" as="report">
                 <dt>
-                    <a href="{be:moduleLink(route:'system_reports',arguments:{action:'detail', extension:extensionKey, report:reportName})}">
+                    <a href="{be:moduleLink(route:'system_reports',arguments:'{action:\'detail\', extension:extensionKey, report:reportName}')}">
                         <r:icon icon="{report.icon}" title="{f:translate(key:report.title)}" />
                         <f:translate key="{report.title}" />
                     </a>
index 826f148..9cde22a 100644 (file)
@@ -1,6 +1,6 @@
 <html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
     <f:if condition="{missingClasses}">
-        <f:be.infobox title="{f:translate(key:'msg.invalidTaskClass.infobox.title', arguments: {0: '{missingClasses ->f:count()}'})}" state="2">
+        <f:be.infobox title="{f:translate(key:'msg.invalidTaskClass.infobox.title', arguments: '{0: \'{missingClasses ->f:count()}\'}')}" state="2">
             <f:format.raw><f:translate key="msg.invalidTaskClass.infobox.message" /></f:format.raw>
         </f:be.infobox>
     </f:if>
index fb50cc4..fd20ae7 100644 (file)
@@ -30,7 +30,7 @@
                 <f:then>
                     <f:if condition="{page._templates}">
                         <f:then>
-                            <a href="{f:be.uri(route:'web_ts', parameters:{id: page.uid})}"
+                            <a href="{f:be.uri(route:'web_ts', parameters:'{id: page.uid}')}"
                                 title="ID: {page.uid}">
                                 <core:IconForRecord table="pages" row="{page}" />
                                 {page.title -> f:format.crop(maxCharacters: maxCharacters)}