Skip to content

Commit

Permalink
[SECURITY] Use a fluid template for the ConfirmationFinisher message
Browse files Browse the repository at this point in the history
The ConfirmationFinisher message is now rendered within a fluid template
to allow styling of the message.
Furthermore, the FormRuntime (and thus all form element values) and the
finisherVariableProvider are available in the template.
Custom variables can be added globally within the form setup or at
form level in the form definition.
By using a fluid template and the associated html escaping, the display
of the ConfirmationFinisher message is protected against XSS / html
injection attacks.

Resolves: #84902
Releases: master, 9.5, 8.7
Security-Commit: e73ae7cae8ccc3450d850f554ab50bc09b57e716
Security-Bulletin: TYPO3-CORE-SA-2019-007
Change-Id: Id8aa02d92f6b89a3008e8c91cf8ab318a05e7489
Reviewed-on: https://review.typo3.org/59532
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
  • Loading branch information
waldhacker1 authored and ohader committed Jan 22, 2019
1 parent d578fd3 commit a0c4348
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 5 deletions.
@@ -0,0 +1,80 @@
.. include:: ../../Includes.txt

===================================================
Feature: #83405 - add ConfirmationFinisher template
===================================================

See :issue:`83405`

Description
===========

The ConfirmationFinisher message is now rendered within a fluid template to allow styling of the message.
Furthermore, the FormRuntime (and thus all form element values) and the finisherVariableProvider are available in the template [1].
Custom variables can be added globally within the form setup or at form level in the form definition [2].
By using a fluid template and the associated html escaping, the display of the ConfirmationFinisher message is protected against XSS / html injection attacks.
The ext: form supplied fluid template does not include any HTML wrapping to remain compatible with existing installations, but it is possible to implement your own template [3].

[1] Template variables
----------------------

* :html:`{form}` - Object for access to submitted form element values (https://docs.typo3.org/typo3cms/extensions/form/Concepts/FrontendRendering/Index.html#accessing-form-values)
* :html:`{finisherVariableProvider}` - Object with data from previous finishers (https://docs.typo3.org/typo3cms/extensions/form/Concepts/FrontendRendering/Index.html#share-data-between-finishers)
* :html:`{message}` - The confirmation message

[2] custom template variables
-----------------------------

global within the form setup:

.. code-block:: yaml
TYPO3:
CMS:
Form:
prototypes:
standard:
finishersDefinition:
Confirmation:
options:
variables:
foo: bar
per form within the form definition:

.. code-block:: yaml
finishers:
-
identifier: Confirmation
options:
message: 'Thx'
variables:
foo: bar
[3] custom Template
-------------------

form setup:

.. code-block:: yaml
TYPO3:
CMS:
Form:
prototypes:
standard:
finishersDefinition:
Confirmation:
options:
templateRootPaths:
20: 'EXT:my_site_package/Resources/Private/Templates/Form/Finishers/Confirmation/'
Impact
======

Integrators can use a ConfirmationFinisher message within a fluid template.
Integrators can use additional information such as form element values within the template.
The ConfirmationFinisher message is protected against XSS / html injection attacks.

.. index:: Frontend, ext:form, NotScanned
Expand Up @@ -5,8 +5,6 @@
/*
* This file is part of the TYPO3 CMS project.
*
* It originated from the Neos.Form package (www.neos.io)
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
Expand All @@ -19,15 +17,19 @@

use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException;
use TYPO3\CMS\Form\Domain\Runtime\FormRuntime;
use TYPO3\CMS\Form\ViewHelpers\RenderRenderableViewHelper;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;

/**
* A simple finisher that outputs a given text
* A finisher that outputs a given text
*
* Options:
*
* - message: A hard-coded message to be rendered
* - contentElementUid: A content element uid to be rendered
*
* Usage:
* //...
Expand Down Expand Up @@ -113,6 +115,45 @@ protected function executeInternal()
$message = $this->parseOption('message');
}

return $message;
$standaloneView = $this->initializeStandaloneView(
$this->finisherContext->getFormRuntime()
);

$standaloneView->assign('message', $message);

return $standaloneView->render();
}

/**
* @param FormRuntime $formRuntime
* @return StandaloneView
* @throws FinisherException
*/
protected function initializeStandaloneView(FormRuntime $formRuntime): StandaloneView
{
$standaloneView = $this->objectManager->get(StandaloneView::class);

if (!isset($this->options['templateName'])) {
throw new FinisherException(
'The option "templateName" must be set for the ConfirmationFinisher.',
1521573955
);
}

$standaloneView->setTemplate($this->options['templateName']);
$standaloneView->getTemplatePaths()->fillFromConfigurationArray($this->options);

if (isset($this->options['variables']) && is_array($this->options['variables'])) {
$standaloneView->assignMultiple($this->options['variables']);
}

$standaloneView->assign('form', $formRuntime);
$standaloneView->assign('finisherVariableProvider', $this->finisherContext->getFinisherVariableProvider());

$standaloneView->getRenderingContext()
->getViewHelperVariableContainer()
->addOrUpdate(RenderRenderableViewHelper::class, 'formRuntime', $formRuntime);

return $standaloneView;
}
}
6 changes: 5 additions & 1 deletion typo3/sysext/form/Configuration/Yaml/BaseSetup.yaml
Expand Up @@ -296,10 +296,14 @@ TYPO3:

Confirmation:
implementationClassName: 'TYPO3\CMS\Form\Domain\Finishers\ConfirmationFinisher'
#options:
options:
#message: ''
#contentElementUid: 0
#typoscriptObjectPath: 'lib.tx_form.contentElementRendering'
#variables:
templateName: 'Confirmation'
templateRootPaths:
10: 'EXT:form/Resources/Private/Frontend/Templates/Finishers/Confirmation/'

EmailToSender:
__inheritances:
Expand Down
Expand Up @@ -3529,6 +3529,10 @@ Full default configuration
closure: ''
Confirmation:
implementationClassName: TYPO3\CMS\Form\Domain\Finishers\ConfirmationFinisher
options:
templateName: 'Confirmation'
templateRootPaths:
10: 'EXT:form/Resources/Private/Frontend/Templates/Finishers/Confirmation/'
formEditor:
iconIdentifier: t3-form-icon-finisher
label: formEditor.elements.Form.finisher.Confirmation.editor.header.label
Expand Down
Expand Up @@ -74,6 +74,133 @@ options.message
The text which is shown if the finisher is invoked.


.. _typo3.cms.form.prototypes.<prototypeIdentifier>.finishersdefinition.confirmation.options.contentelementuid:

options.contentElementUid
-------------------------

:aspect:`Option path`
TYPO3.CMS.Form.prototypes.<prototypeIdentifier>.finishersDefinition.Confirmation.options.contentElementUid

:aspect:`Data type`
integer

:aspect:`Needed by`
Frontend

:aspect:`Mandatory`
No

:aspect:`Default value`
undefined

:aspect:`Description`
The option "contentElementUid" can be used to render a content element.
If contentElementUid is set, the option "message" will be ignored.


.. _typo3.cms.form.prototypes.<prototypeIdentifier>.finishersdefinition.confirmation.options.typoscriptobjectpath:

options.typoscriptObjectPath
----------------------------

:aspect:`Option path`
TYPO3.CMS.Form.prototypes.<prototypeIdentifier>.finishersDefinition.Confirmation.options.typoscriptObjectPath

:aspect:`Data type`
string

:aspect:`Needed by`
Frontend

:aspect:`Mandatory`
No

:aspect:`Default value`
'lib.tx_form.contentElementRendering'

:aspect:`Description`
The option "typoscriptObjectPath" can be used to render the content element (options.contentElementUid) through a typoscript lib.


.. _typo3.cms.form.prototypes.<prototypeIdentifier>.finishersdefinition.confirmation.options.variables:

options.variables
-----------------

:aspect:`Option path`
TYPO3.CMS.Form.prototypes.<prototypeIdentifier>.finishersDefinition.Confirmation.options.variables

:aspect:`Data type`
array

:aspect:`Needed by`
Frontend

:aspect:`Mandatory`
No

:aspect:`Default value`
undefined

:aspect:`Description`
Variables which should be available within the template.


.. _typo3.cms.form.prototypes.<prototypeIdentifier>.finishersdefinition.confirmation.options.templatename:

options.templateName
--------------------

:aspect:`Option path`
TYPO3.CMS.Form.prototypes.<prototypeIdentifier>.finishersDefinition.Confirmation.options.templateName

:aspect:`Data type`
string

:aspect:`Needed by`
Frontend

:aspect:`Mandatory`
Yes

:aspect:`Default value`
'Confirmation'

:aspect:`Description`
Define a custom template name which should be used.


.. _typo3.cms.form.prototypes.<prototypeIdentifier>.finishersdefinition.confirmation.options.templaterootpaths:

options.templateRootPaths
-------------------------

:aspect:`Option path`
TYPO3.CMS.Form.prototypes.<prototypeIdentifier>.finishersDefinition.Confirmation.options.templateRootPaths

:aspect:`Data type`
array

:aspect:`Needed by`
Frontend

:aspect:`Mandatory`
Yes

:aspect:`Default value`
.. code-block:: yaml
:linenos:
Confirmation:
options:
templateRootPaths:
10: 'EXT:form/Resources/Private/Frontend/Templates/Finishers/Confirmation/'
:aspect:`Description`
Used to define several paths for templates, which will be tried in reversed order (the paths are searched from bottom to top).


.. _typo3.cms.form.prototypes.<prototypeIdentifier>.finishersdefinition.confirmation.options.translation.translationfile:

options.translation.translationFile
Expand Down
@@ -0,0 +1,3 @@
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" xmlns:formvh="http://typo3.org/ns/TYPO3/CMS/Form/ViewHelpers" data-namespace-typo3-fluid="true">
{message}
</html>

0 comments on commit a0c4348

Please sign in to comment.