[BUGFIX][SECURITY] Arbitrary TypoScript execution on system extension form
authorOliver Hader <oliver@typo3.org>
Tue, 20 Sep 2011 15:53:24 +0000 (17:53 +0200)
committerOliver Hader <oliver@typo3.org>
Fri, 30 Sep 2011 18:00:56 +0000 (20:00 +0200)
The new system extension form can be used to render custom FORM elements as
well as regular cObjects like TEXT or COA. Since the form wizard can be used
by any editor in the backend and writes data to the field bodytext, this can
also be used to execute arbitrary TypoScript without further access checks.

This change introduces two defined and allowed content elements "header" and
"textblock" that can be defined by using the form wizard. If the TypoScript
that was generated by the mentioned wizard is rendered, regular cObjects are
disabled. If the FORM or FORM_INT cObject is used directly from a TypoScript
template, all possible cObjects can still be used.

Change-Id: I573764de7583b078456e71e95ea7903b433c29db
Resolves: #30095
Releases: 4.6
Reviewed-on: http://review.typo3.org/5128
Reviewed-by: Andreas Wolf
Reviewed-by: Frederic Gaus
Tested-by: Frederic Gaus
Reviewed-by: Oliver Hader
Tested-by: Oliver Hader
25 files changed:
typo3/sysext/form/Classes/Common.php
typo3/sysext/form/Classes/Controller/Form.php
typo3/sysext/form/Classes/Domain/Factory/JsonToTyposcript.php
typo3/sysext/form/Classes/Domain/Factory/Typoscript.php
typo3/sysext/form/Classes/Domain/Factory/TyposcriptToJson.php
typo3/sysext/form/Classes/Domain/Model/Element/Abstract.php
typo3/sysext/form/Classes/Domain/Model/Element/AbstractPlain.php [new file with mode: 0644]
typo3/sysext/form/Classes/Domain/Model/Element/Content.php
typo3/sysext/form/Classes/Domain/Model/Element/Header.php [new file with mode: 0644]
typo3/sysext/form/Classes/Domain/Model/Element/Textblock.php [new file with mode: 0644]
typo3/sysext/form/Classes/Domain/Model/JSON/Header.php
typo3/sysext/form/Classes/Domain/Model/JSON/Textblock.php [new file with mode: 0644]
typo3/sysext/form/Classes/View/Form/Element/Abstract.php
typo3/sysext/form/Classes/View/Form/Element/Header.php [new file with mode: 0644]
typo3/sysext/form/Classes/View/Form/Element/Textblock.php [new file with mode: 0644]
typo3/sysext/form/Classes/View/Wizard/Wizard.php
typo3/sysext/form/Resources/Private/Configuration/PageTSconfig/modWizards.ts
typo3/sysext/form/Resources/Private/Language/locallang_wizard.xlf
typo3/sysext/form/Resources/Public/CSS/Wizard/Wizard.css
typo3/sysext/form/Resources/Public/Images/edit-textblock.png [new file with mode: 0644]
typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Content/Header.js
typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Content/Textblock.js [new file with mode: 0644]
typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/Content.js
typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Various.js
typo3/sysext/form/ext_autoload.php

index d131077..67a5c15 100644 (file)
@@ -50,25 +50,27 @@ class tx_form_Common implements t3lib_Singleton {
        public function __construct() {
                $this->setFormObjects(
                        array(
-                                'BUTTON',
-                                'CHECKBOX',
-                                'CHECKBOXGROUP',
-                                'FIELDSET',
-                                'FILEUPLOAD',
-                                'FORM',
-                                'FORM_INT',
-                                'HIDDEN',
-                                'IMAGEBUTTON',
-                                'OPTGROUP',
-                                'OPTION',
-                                'PASSWORD',
-                                'RADIO',
-                                'RADIOGROUP',
-                                'RESET',
-                                'SELECT',
-                                'SUBMIT',
-                                'TEXTAREA',
-                                'TEXTLINE',
+                               'BUTTON',
+                               'CHECKBOX',
+                               'CHECKBOXGROUP',
+                               'FIELDSET',
+                               'FILEUPLOAD',
+                               'FORM',
+                               'FORM_INT',
+                               'HEADER',
+                               'HIDDEN',
+                               'IMAGEBUTTON',
+                               'OPTGROUP',
+                               'OPTION',
+                               'PASSWORD',
+                               'RADIO',
+                               'RADIOGROUP',
+                               'RESET',
+                               'SELECT',
+                               'SUBMIT',
+                               'TEXTAREA',
+                               'TEXTBLOCK',
+                               'TEXTLINE',
                        )
                );
        }
index 4f4a95c..8bea615 100644 (file)
@@ -91,38 +91,45 @@ class tx_form_Controller_Form {
         * It simply calls execute because this function name is not really descriptive
         * but is needed by the core of TYPO3
         *
-        * @param string $typoscriptObjectName Name of the object
-        * @param array $typoscript TS configuration for this cObject
-        * @param string $typoscriptKey A string label used for the internal debugging tracking.
+        * @param string $typoScriptObjectName Name of the object
+        * @param array $typoScript TS configuration for this cObject
+        * @param string $typoScriptKey A string label used for the internal debugging tracking.
         * @param tslib_cObj $contentObject reference
         * @return string HTML output
         */
        public function cObjGetSingleExt(
-               $typoscriptObjectName,
-               array $typoscript,
-               $typoscriptKey,
+               $typoScriptObjectName,
+               array $typoScript,
+               $typoScriptKey,
                tslib_cObj $contentObject
        ) {
                $content = '';
 
-               if ($typoscriptObjectName === 'FORM') {
+               if ($typoScriptObjectName === 'FORM') {
                        if ($contentObject->data['CType'] === 'mailform') {
                                $bodytext = $contentObject->data['bodytext'];
+
                                /** @var $typoScriptParser t3lib_tsparser */
                                $typoScriptParser = t3lib_div::makeInstance('t3lib_tsparser');
                                $typoScriptParser->parse($bodytext);
-                               $typoscript = t3lib_div::array_merge_recursive_overrule(
+                               $typoScript = t3lib_div::array_merge_recursive_overrule(
                                        (array) $typoScriptParser->setup,
-                                       (array) $typoscript
+                                       (array) $typoScript
                                );
+
+                               // Disables content elements since TypoScript is handled that could contain insecure settings:
+                               $typoScript[tx_form_Domain_Factory_Typoscript::PROPERTY_DisableContentElement] = TRUE;
                        }
-                       $newTyposcript = array(
+
+                       $newTypoScript = array(
                                '10' => 'FORM_INT',
-                               '10.' => $typoscript,
+                               '10.' => $typoScript,
                        );
-                       $content = $contentObject->COBJ_ARRAY($newTyposcript, 'INT');
-               } elseif ($typoscriptObjectName == 'FORM_INT') {
-                       $this->initialize($typoscript);
+
+                       $content = $contentObject->COBJ_ARRAY($newTypoScript, 'INT');
+
+               } elseif ($typoScriptObjectName === 'FORM_INT') {
+                       $this->initialize($typoScript);
                        $content = $this->execute();
                }
 
index c5c233f..70e4217 100644 (file)
@@ -110,6 +110,7 @@ class tx_form_Domain_Factory_JsonToTyposcript {
                                                case 'typo3-form-wizard-elements-basic-textline':
                                                case 'typo3-form-wizard-elements-predefined-email':
                                                case 'typo3-form-wizard-elements-content-header':
+                                               case 'typo3-form-wizard-elements-content-textblock':
                                                        $this->getDefaultElementSetup($element, $parent, $elementCounter, $childrenWithParentName);
                                                        break;
                                                case 'typo3-form-wizard-elements-basic-fieldset':
@@ -227,8 +228,11 @@ class tx_form_Domain_Factory_JsonToTyposcript {
                                }
                                break;
                        case 'content':
-                               $contentObjectType = 'TEXT';
-                               break;
+                               switch ($type) {
+                                       case 'header':
+                                       case 'textblock':
+                                               $contentObjectType = strtoupper($type);
+                               }
                        default:
                }
 
@@ -520,19 +524,10 @@ class tx_form_Domain_Factory_JsonToTyposcript {
                foreach ($various as $key => $value) {
                        switch ($key) {
                                case 'headingSize':
-                                       $parent[$elementCounter . '.']['wrap'] = str_replace(
-                                               '%headingSize%',
-                                               $value,
-                                               '<%headingSize%>|</%headingSize%>'
-                                       );
-                                       break;
-                               case 'heading':
-                                       $parent[$elementCounter . '.']['value'] = $value;
-                                       break;
+                               case 'content':
                                case 'name':
-                                       $parent[$elementCounter . '.']['name'] = $value;
+                                       $parent[$elementCounter . '.'][$key] = (string) $value;
                                        break;
-                               default:
                        }
                }
        }
index 64b5dcf..9bac977 100644 (file)
  * @subpackage form
  */
 class tx_form_Domain_Factory_Typoscript implements t3lib_Singleton {
+       const PROPERTY_DisableContentElement = 'disableContentElement';
+
        /**
         * @var tslib_cObj
         */
        protected $localContentObject;
 
+       /**
+        * @var boolean
+        */
+       protected $disableContentElement = FALSE;
+
        /**
         * Build model from Typoscript
         *
@@ -45,6 +52,10 @@ class tx_form_Domain_Factory_Typoscript implements t3lib_Singleton {
         * @return tx_form_Domain_Model_Form The form object containing the child elements
         */
        public function buildModelFromTyposcript(array $typoscript) {
+               if (isset($typoscript[self::PROPERTY_DisableContentElement])) {
+                       $this->setDisableContentElement($typoscript[self::PROPERTY_DisableContentElement]);
+               }
+
                $this->setLayoutHandler($typoscript);
 
                $form = $this->createElement('form', $typoscript);
@@ -52,6 +63,16 @@ class tx_form_Domain_Factory_Typoscript implements t3lib_Singleton {
                return $form;
        }
 
+       /**
+        * Disables the content element.
+        *
+        * @param boolean $disableContentElement
+        * @return void
+        */
+       public function setDisableContentElement($disableContentElement) {
+               $this->disableContentElement = (bool) $disableContentElement;
+       }
+
        /**
         * Rendering of a "numerical array" of Form objects from TypoScript
         * Creates new object for each element found
@@ -91,34 +112,33 @@ class tx_form_Domain_Factory_Typoscript implements t3lib_Singleton {
         * @return void
         */
        public function setElementType(tx_form_Domain_Model_Element_Abstract $parentElement, $class, array $arguments) {
-               if (substr($class, 0, 1) == '<') {
-                       $key = trim(substr($class, 1));
-                       /** @var $typoscriptParser t3lib_TSparser */
-                       $typoscriptParser = t3lib_div::makeInstance('t3lib_TSparser');
-                       $oldArguments = $arguments;
-                       list($class, $arguments) = $typoscriptParser->getVal($key, $GLOBALS['TSFE']->tmpl->setup);
-                       if (is_array($oldArguments) && count($oldArguments)) {
-                               $arguments = $this->getLocalConentObject()->joinTSarrays($arguments, $oldArguments);
-                       }
-                       $GLOBALS['TT']->incStackPointer();
-                       $contentObject = array(
-                               'cObj' => $class,
-                               'cObj.' => $arguments,
-                       );
-                       $this->addElement($parentElement, 'content', $contentObject);
-                       $GLOBALS['TT']->decStackPointer();
-               } elseif (in_array($class, tx_form_Common::getInstance()->getFormObjects())) {
-                       try {
-                               $this->addElement($parentElement, $class, $arguments);
-                       } catch (Exception $exception) {
-                               throw $exception;
+               if (in_array($class, tx_form_Common::getInstance()->getFormObjects())) {
+                       $this->addElement($parentElement, $class, $arguments);
+
+               } elseif ($this->disableContentElement === FALSE) {
+                       if (substr($class, 0, 1) == '<') {
+                               $key = trim(substr($class, 1));
+                               /** @var $typoscriptParser t3lib_TSparser */
+                               $typoscriptParser = t3lib_div::makeInstance('t3lib_TSparser');
+                               $oldArguments = $arguments;
+                               list($class, $arguments) = $typoscriptParser->getVal($key, $GLOBALS['TSFE']->tmpl->setup);
+                               if (is_array($oldArguments) && count($oldArguments)) {
+                                       $arguments = $this->getLocalConentObject()->joinTSarrays($arguments, $oldArguments);
+                               }
+                               $GLOBALS['TT']->incStackPointer();
+                               $contentObject = array(
+                                       'cObj' => $class,
+                                       'cObj.' => $arguments,
+                               );
+                               $this->addElement($parentElement, 'content', $contentObject);
+                               $GLOBALS['TT']->decStackPointer();
+                       } else {
+                               $contentObject = array(
+                                       'cObj' => $class,
+                                       'cObj.' => $arguments,
+                               );
+                               $this->addElement($parentElement, 'content', $contentObject);
                        }
-               } else {
-                       $contentObject = array(
-                               'cObj' => $class,
-                               'cObj.' => $arguments,
-                       );
-                       $this->addElement($parentElement, 'content', $contentObject);
                }
        }
 
@@ -155,11 +175,15 @@ class tx_form_Domain_Factory_Typoscript implements t3lib_Singleton {
                /** @var $object tx_form_Domain_Model_Element_Abstract */
                $object = t3lib_div::makeInstance($className);
 
-               if ($class === 'content') {
+               if ($object->getElementType() === tx_form_Domain_Model_Element_Abstract::ELEMENT_TYPE_CONTENT) {
                        $object->setData($arguments['cObj'], $arguments['cObj.']);
-               } else {
+               } elseif ($object->getElementType() === tx_form_Domain_Model_Element_Abstract::ELEMENT_TYPE_PLAIN) {
+                       $object->setProperties($arguments);
+               } elseif ($object->getElementType() === tx_form_Domain_Model_Element_Abstract::ELEMENT_TYPE_FORM) {
                        $object->setData($arguments['data']);
                        $this->reconstituteElement($object, $arguments);
+               } else {
+                       throw new Exception('Element type "' . $object->getElementType() . '" is not supported.');
                }
 
                return $object;
index 50c0e8b..a1d95c0 100644 (file)
@@ -117,9 +117,6 @@ class tx_form_Domain_Factory_TyposcriptToJson {
                                $class = 'NAME';
                        }
                        $this->addElement($parentElement, $class, $arguments);
-               } elseif (strstr($arguments['class'], 'content-header')) {
-                       $class = 'HEADER';
-                       $this->addElement($parentElement, $class, $arguments);
                }
        }
 
index 5b0b19d..83070dc 100644 (file)
@@ -30,6 +30,9 @@
  * @subpackage form
  */
 abstract class tx_form_Domain_Model_Element_Abstract {
+       const ELEMENT_TYPE_FORM = 'FORM';
+       const ELEMENT_TYPE_PLAIN = 'PLAIN';
+       const ELEMENT_TYPE_CONTENT = 'CONTENT';
 
        /**
         * Internal Id of the element
@@ -38,6 +41,11 @@ abstract class tx_form_Domain_Model_Element_Abstract {
         */
        protected $elementId;
 
+       /**
+        * @var string
+        */
+       protected $elementType = self::ELEMENT_TYPE_FORM;
+
        /**
         * The name of the element
         *
@@ -176,6 +184,15 @@ abstract class tx_form_Domain_Model_Element_Abstract {
                return $this->elementId;
        }
 
+       /**
+        * Gets the element type.
+        *
+        * @return string
+        */
+       public function getElementType() {
+               return $this->elementType;
+       }
+
        /**
         * Set the name for the element
         *
diff --git a/typo3/sysext/form/Classes/Domain/Model/Element/AbstractPlain.php b/typo3/sysext/form/Classes/Domain/Model/Element/AbstractPlain.php
new file mode 100644 (file)
index 0000000..3133d9a
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2011 Oliver Hader <oliver.hader@typo3.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * Hidden field model object
+ *
+ * @author Oliver Hader <oliver.hader@typo3.org>
+ * @package TYPO3
+ * @subpackage form
+ */
+class tx_form_Domain_Model_Element_AbstractPlain extends tx_form_Domain_Model_Element_Abstract {
+       /**
+        * @var string
+        */
+       protected $elementType = self::ELEMENT_TYPE_PLAIN;
+
+       /**
+        * Allowed attributes for this object
+        *
+        * @var array
+        */
+       protected $allowedAttributes = array();
+
+       /**
+        * Mandatory attributes for this object
+        *
+        * @var array
+        */
+       protected $mandatoryAttributes = array();
+
+       /**
+        * @var array
+        */
+       protected $properties = array();
+
+       /**
+        * Sets the properties.
+        *
+        * @param array $properties
+        * @return void
+        */
+       public function setProperties(array $properties) {
+               $this->properties = $properties;
+       }
+
+       /**
+        * Gets the data.
+        *
+        * @return string
+        */
+       public function getData() {
+               return $this->getContent();
+       }
+
+       /**
+        * Gets the content.
+        *
+        * @return string
+        */
+       protected function getContent() {
+               $content = '';
+
+               if (isset($this->properties['content'])) {
+                       $content = $this->properties['content'];
+               }
+
+               return $content;
+       }
+}
+?>
\ No newline at end of file
index 4d0d803..55516bb 100644 (file)
  * @subpackage form
  */
 class tx_form_Domain_Model_Element_Content extends tx_form_Domain_Model_Element_Abstract {
+       /**
+        * @var string
+        */
+       protected $elementType = self::ELEMENT_TYPE_CONTENT;
+
        /**
         * @var string
         */
diff --git a/typo3/sysext/form/Classes/Domain/Model/Element/Header.php b/typo3/sysext/form/Classes/Domain/Model/Element/Header.php
new file mode 100644 (file)
index 0000000..8622262
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2011 Oliver Hader <oliver.hader@typo3.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * Header model object
+ *
+ * @author Oliver Hader <oliver.hader@typo3.org>
+ * @package TYPO3
+ * @subpackage form
+ */
+class tx_form_Domain_Model_Element_Header extends tx_form_Domain_Model_Element_AbstractPlain {
+       /**
+        * Gets the data.
+        *
+        * @return string
+        */
+       public function getData() {
+               return $this->wrapContent(
+                       $this->getContent()
+               );
+       }
+
+       /**
+        * Wraps the content.
+        *
+        * @param string $content
+        * @return string
+        */
+       protected function wrapContent($content) {
+               if (isset($this->properties['headingSize']) && preg_match('#^h[1-5]$#', $this->properties['headingSize'])) {
+                       $content = '<' . $this->properties['headingSize'] . '>' . $content . '</' . $this->properties['headingSize'] . '>';
+               }
+
+               return $content;
+       }
+}
+?>
\ No newline at end of file
diff --git a/typo3/sysext/form/Classes/Domain/Model/Element/Textblock.php b/typo3/sysext/form/Classes/Domain/Model/Element/Textblock.php
new file mode 100644 (file)
index 0000000..9278e78
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2011 Oliver Hader <oliver.hader@typo3.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * Textblock model object
+ *
+ * @author Oliver Hader <oliver.hader@typo3.org>
+ * @package TYPO3
+ * @subpackage form
+ */
+class tx_form_Domain_Model_Element_Textblock extends tx_form_Domain_Model_Element_AbstractPlain {
+
+}
+?>
\ No newline at end of file
index 24a0378..08aa3be 100644 (file)
@@ -46,7 +46,7 @@ class tx_form_Domain_Model_JSON_Header extends tx_form_Domain_Model_JSON_Element
                'attributes' => array(),
                'various' => array(
                        'headingSize' => 'h1',
-                       'heading' => ''
+                       'content' => ''
                )
        );
 
@@ -85,14 +85,13 @@ class tx_form_Domain_Model_JSON_Header extends tx_form_Domain_Model_JSON_Element
         * @return void
         */
        protected function setVarious(array $parameters) {
-               if (isset($parameters['wrap'])) {
-                       preg_match('/<(h[1-5]{1}).*?>/', $parameters['wrap'], $matches);
-                       if (!empty($matches)) {
-                               $this->configuration['various']['headingSize'] = $matches[1];
+               if (isset($parameters['headingSize'])) {
+                       if (preg_match('#^h[1-5]$#', $parameters['headingSize'])) {
+                               $this->configuration['various']['headingSize'] = $parameters['headingSize'];
                        }
                }
-               if (isset($parameters['value'])) {
-                       $this->configuration['various']['heading'] = $parameters['value'];
+               if (isset($parameters['content'])) {
+                       $this->configuration['various']['content'] = $parameters['content'];
                }
        }
 }
diff --git a/typo3/sysext/form/Classes/Domain/Model/JSON/Textblock.php b/typo3/sysext/form/Classes/Domain/Model/JSON/Textblock.php
new file mode 100644 (file)
index 0000000..8a57433
--- /dev/null
@@ -0,0 +1,92 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2011 Oliver Hader <oliver.hader@typo3.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * JSON textblock
+ *
+ * @author Oliver Hader <oliver.hader@typo3.org>
+ * @package TYPO3
+ * @subpackage form
+ */
+class tx_form_Domain_Model_JSON_Textblock extends tx_form_Domain_Model_JSON_Element {
+       /**
+        * The ExtJS xtype of the element
+        *
+        * @var string
+        */
+       public $xtype = 'typo3-form-wizard-elements-content-textblock';
+
+       /**
+        * The configuration array for the xtype
+        *
+        * @var array
+        */
+       public $configuration = array(
+               'attributes' => array(),
+               'various' => array(
+                       'content' => ''
+               )
+       );
+
+       /**
+        * Allowed attributes for this object
+        *
+        * @var array
+        */
+       protected $allowedAttributes = array(
+               'class',
+               'dir',
+               'id',
+               'lang',
+               'style',
+               'title'
+       );
+
+       /**
+        * Set all the parameters for this object
+        *
+        * @param array $parameters Configuration array
+        * @return void
+        * @see tx_form_Domain_Model_Json_Element::setParameters()
+        */
+       public function setParameters(array $parameters) {
+               parent::setParameters($parameters);
+               $this->setVarious($parameters);
+       }
+
+       /**
+        * Set the various properties for the element
+        *
+        * For this element this is the headingsize and the value
+        *
+        * @param array $parameters Configuration array
+        * @return void
+        */
+       protected function setVarious(array $parameters) {
+               if (isset($parameters['content'])) {
+                       $this->configuration['various']['content'] = $parameters['content'];
+               }
+       }
+}
+?>
\ No newline at end of file
index 76a2e6c..6ae3ea3 100644 (file)
@@ -183,6 +183,8 @@ abstract class tx_form_View_Form_Element_Abstract {
                                                        $deleteNode = TRUE;
                                                        break;
                                                case 'content':
+                                               case 'header':
+                                               case 'textblock':
                                                        $replaceNode = $dom->createTextNode($this->getElementData(FALSE));
                                                        $node->parentNode->insertBefore($replaceNode, $node);
                                                        $deleteNode = TRUE;
diff --git a/typo3/sysext/form/Classes/View/Form/Element/Header.php b/typo3/sysext/form/Classes/View/Form/Element/Header.php
new file mode 100644 (file)
index 0000000..79ab40f
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2011 Oliver Hader <oliver.hader@typo3.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * View object for the text input element
+ *
+ * @author Oliver Hader <oliver.hader@typo3.org>
+ * @package TYPO3
+ * @subpackage form
+ */
+class tx_form_View_Form_Element_Header extends tx_form_View_Form_Element_Abstract {
+       /**
+        * Default layout of this object
+        *
+        * @var string
+        */
+       protected $layout = '
+               <header />
+       ';
+}
+?>
\ No newline at end of file
diff --git a/typo3/sysext/form/Classes/View/Form/Element/Textblock.php b/typo3/sysext/form/Classes/View/Form/Element/Textblock.php
new file mode 100644 (file)
index 0000000..a8f0e5c
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2011 Oliver Hader <oliver.hader@typo3.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * View object for the text input element
+ *
+ * @author Oliver Hader <oliver.hader@typo3.org>
+ * @package TYPO3
+ * @subpackage form
+ */
+class tx_form_View_Form_Element_Textblock extends tx_form_View_Form_Element_Abstract {
+       /**
+        * Default layout of this object
+        *
+        * @var string
+        */
+       protected $layout = '
+               <textblock />
+       ';
+}
+?>
\ No newline at end of file
index 881ae01..1642bc1 100644 (file)
@@ -172,6 +172,7 @@ class tx_form_View_Wizard_Wizard extends tx_form_View_Wizard_Abstract {
                        'Elements/Predefined/Name.js',
                        'Elements/Predefined/RadioGroup.js',
                        'Elements/Content/Header.js',
+                       'Elements/Content/Textblock.js',
                        'Viewport.js',
                        'Viewport/Left.js',
                        'Viewport/Right.js',
index 4414950..131eab1 100644 (file)
@@ -26,7 +26,7 @@ prefix = tx_form
                                                        showButtons = email, radiogroup, checkboxgroup, name
                                                }
                                                content {
-                                                       showButtons = header
+                                                       showButtons = header, textblock
                                                }
                                        }
                                }
@@ -269,6 +269,9 @@ prefix = tx_form
                        header {
                                showAccordions = various
                        }
+                       textblock {
+                               showAccordions = various
+                       }
                        name {
                                showAccordions = legend, various
                        }
index c7516d9..2590d0a 100644 (file)
                                <source>Header</source>
                                <target>Header</target>
                        </trans-unit>
+                       <trans-unit id="content_textblock" approved="yes">
+                               <source>Text block</source>
+                               <target>Text block</target>
+                       </trans-unit>
                        <trans-unit id="left_elements_predefined" approved="yes">
                                <source>Predefined form elements</source>
                                <target>Predefined form elements</target>
                                <source>Name</source>
                                <target>Name</target>
                        </trans-unit>
-                       <trans-unit id="various_properties_heading" approved="yes">
-                               <source>Heading</source>
-                               <target>Heading</target>
+                       <trans-unit id="various_properties_content" approved="yes">
+                               <source>Content</source>
+                               <target>Content</target>
                        </trans-unit>
                        <trans-unit id="various_properties_headingsize" approved="yes">
                                <source>Heading size</source>
                                <source>Full name</source>
                                <target>Full name</target>
                        </trans-unit>
-                       <trans-unit id="elements_heading" approved="yes">
-                               <source>Edit this heading</source>
-                               <target>Edit this heading</target>
+                       <trans-unit id="elements_header_content" approved="yes">
+                               <source>Edit this header</source>
+                               <target>Edit this header</target>
+                       </trans-unit>
+                       <trans-unit id="elements_textblock_content" approved="yes">
+                               <source>Edit this textblock</source>
+                               <target>Edit this textblock</target>
                        </trans-unit>
                        <trans-unit id="elements_option_1" approved="yes">
                                <source>Option 1</source>
index d48fb08..639e459 100644 (file)
@@ -217,6 +217,10 @@ div.overflow-hidden {
        background-image: url("../../Images/edit-heading.png");
 }
 
+.formwizard-left-elements-content-textblock {
+       background-image: url("../../Images/edit-textblock.png");
+}
+
 .x-form-field-wrap .x-form-submit-trigger {
        background-image: url("../../Images/submit-trigger.gif");
 }
diff --git a/typo3/sysext/form/Resources/Public/Images/edit-textblock.png b/typo3/sysext/form/Resources/Public/Images/edit-textblock.png
new file mode 100644 (file)
index 0000000..abe2650
Binary files /dev/null and b/typo3/sysext/form/Resources/Public/Images/edit-textblock.png differ
index 626bbd2..054f8f8 100644 (file)
@@ -23,7 +23,7 @@ TYPO3.Form.Wizard.Elements.Content.Header = Ext.extend(TYPO3.Form.Wizard.Element
                '<div class="overflow-hidden">',
                        '<tpl for="various">',
                                '<{headingSize} {[this.getAttributes(parent.attributes)]}>',
-                               '{heading}',
+                               '{content}',
                                '</{type}>',
                        '</tpl>',
                '</div>',
@@ -60,7 +60,7 @@ TYPO3.Form.Wizard.Elements.Content.Header = Ext.extend(TYPO3.Form.Wizard.Element
                                },
                                various: {
                                        headingSize: 'h1',
-                                       heading: TYPO3.l10n.localize('elements_heading')
+                                       content: TYPO3.l10n.localize('elements_header_content')
                                }
                        }
                });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Content/Textblock.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Content/Textblock.js
new file mode 100644 (file)
index 0000000..1e915f9
--- /dev/null
@@ -0,0 +1,70 @@
+Ext.namespace('TYPO3.Form.Wizard.Elements.Content');
+
+/**
+ * The content HEADER element
+ *
+ * @class TYPO3.Form.Wizard.Elements.Content.Header
+ * @extends TYPO3.Form.Wizard.Elements
+ */
+TYPO3.Form.Wizard.Elements.Content.Textblock = Ext.extend(TYPO3.Form.Wizard.Elements, {
+       /**
+        * @cfg {String} elementClass
+        * An extra CSS class that will be added to this component's Element
+        */
+       elementClass: 'textblock',
+
+       /**
+        * @cfg {Mixed} tpl
+        * An Ext.Template, Ext.XTemplate or an array of strings to form an
+        * Ext.XTemplate. Used in conjunction with the data and tplWriteMode
+        * configurations.
+        */
+       tpl: new Ext.XTemplate(
+               '<div class="overflow-hidden">',
+                       '<tpl for="various">',
+                               '<div {[this.getAttributes(parent.attributes)]}>',
+                               '{content}',
+                               '</{type}>',
+                       '</tpl>',
+               '</div>',
+               {
+                       compiled: true,
+                       getAttributes: function(attributes) {
+                               var attributesHtml = '';
+                               Ext.iterate(attributes, function(key, value) {
+                                       if (value) {
+                                               attributesHtml += key + '="' + value + '" ';
+                                       }
+                               }, this);
+                               return attributesHtml;
+                       }
+               }
+       ),
+
+       /**
+        * Constructor
+        *
+        * Add the configuration object to this component
+        * @param config
+        */
+       constructor: function(config) {
+               Ext.apply(this, {
+                       configuration: {
+                               attributes: {
+                                       class: 'content-textblock',
+                                       dir: '',
+                                       id: '',
+                                       lang: '',
+                                       style: '',
+                                       title: ''
+                               },
+                               various: {
+                                       content: TYPO3.l10n.localize('elements_textblock_content')
+                               }
+                       }
+               });
+               TYPO3.Form.Wizard.Elements.Content.Textblock.superclass.constructor.apply(this, arguments);
+       }
+});
+
+Ext.reg('typo3-form-wizard-elements-content-textblock', TYPO3.Form.Wizard.Elements.Content.Textblock);
\ No newline at end of file
index 917cf47..44d8b14 100644 (file)
@@ -50,6 +50,16 @@ TYPO3.Form.Wizard.Viewport.Left.Elements.Content = Ext.extend(TYPO3.Form.Wizard.
                                                scope: this
                                        });
                                        break;
+                               case 'textblock':
+                                       buttons.push({
+                                               text: TYPO3.l10n.localize('content_textblock'),
+                                               id: 'content-textblock',
+                                               clickEvent: 'dblclick',
+                                               handler: this.onDoubleClick,
+                                               iconCls: 'formwizard-left-elements-content-textblock',
+                                               scope: this
+                                       });
+                                       break;
                        }
                }, this);
 
index ddc790f..e031296 100644 (file)
@@ -63,10 +63,10 @@ TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Various = Ext.extend(Ext.FormPanel
                                                }
                                        });
                                        break;
-                               case 'heading':
+                               case 'content':
                                        formItems.push({
-                                               fieldLabel: TYPO3.l10n.localize('various_properties_heading'),
-                                               name: 'heading',
+                                               fieldLabel: TYPO3.l10n.localize('various_properties_content'),
+                                               name: 'content',
                                                allowBlank: false,
                                                listeners: {
                                                        'triggerclick': {
index 1e24eef..faecb74 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 // DO NOT CHANGE THIS FILE! It is automatically generated by extdeveval::buildAutoloadRegistry.
-// This file was generated on 2011-09-19 21:46
+// This file was generated on 2011-09-20 16:43
 
 $extensionPath = t3lib_extMgm::extPath('form');
 $extensionClassesPath = t3lib_extMgm::extPath('form') . 'Classes/';
@@ -50,6 +50,7 @@ return array(
        'tx_form_domain_model_attributes_type' => $extensionClassesPath . 'Domain/Model/Attributes/Type.php',
        'tx_form_domain_model_attributes_value' => $extensionClassesPath . 'Domain/Model/Attributes/Value.php',
        'tx_form_domain_model_element_abstract' => $extensionClassesPath . 'Domain/Model/Element/Abstract.php',
+       'tx_form_domain_model_element_abstractplain' => $extensionClassesPath . 'Domain/Model/Element/AbstractPlain.php',
        'tx_form_domain_model_element_button' => $extensionClassesPath . 'Domain/Model/Element/Button.php',
        'tx_form_domain_model_element_checkbox' => $extensionClassesPath . 'Domain/Model/Element/Checkbox.php',
        'tx_form_domain_model_element_checkboxgroup' => $extensionClassesPath . 'Domain/Model/Element/Checkboxgroup.php',
@@ -57,6 +58,7 @@ return array(
        'tx_form_domain_model_element_content' => $extensionClassesPath . 'Domain/Model/Element/Content.php',
        'tx_form_domain_model_element_fieldset' => $extensionClassesPath . 'Domain/Model/Element/Fieldset.php',
        'tx_form_domain_model_element_fileupload' => $extensionClassesPath . 'Domain/Model/Element/Fileupload.php',
+       'tx_form_domain_model_element_header' => $extensionClassesPath . 'Domain/Model/Element/Header.php',
        'tx_form_domain_model_element_hidden' => $extensionClassesPath . 'Domain/Model/Element/Hidden.php',
        'tx_form_domain_model_element_imagebutton' => $extensionClassesPath . 'Domain/Model/Element/Imagebutton.php',
        'tx_form_domain_model_element_optgroup' => $extensionClassesPath . 'Domain/Model/Element/Optgroup.php',
@@ -68,6 +70,7 @@ return array(
        'tx_form_domain_model_element_select' => $extensionClassesPath . 'Domain/Model/Element/Select.php',
        'tx_form_domain_model_element_submit' => $extensionClassesPath . 'Domain/Model/Element/Submit.php',
        'tx_form_domain_model_element_textarea' => $extensionClassesPath . 'Domain/Model/Element/Textarea.php',
+       'tx_form_domain_model_element_textblock' => $extensionClassesPath . 'Domain/Model/Element/Textblock.php',
        'tx_form_domain_model_element_textline' => $extensionClassesPath . 'Domain/Model/Element/Textline.php',
        'tx_form_domain_model_json_button' => $extensionClassesPath . 'Domain/Model/JSON/Button.php',
        'tx_form_domain_model_json_checkbox' => $extensionClassesPath . 'Domain/Model/JSON/Checkbox.php',
@@ -87,6 +90,7 @@ return array(
        'tx_form_domain_model_json_select' => $extensionClassesPath . 'Domain/Model/JSON/Select.php',
        'tx_form_domain_model_json_submit' => $extensionClassesPath . 'Domain/Model/JSON/Submit.php',
        'tx_form_domain_model_json_textarea' => $extensionClassesPath . 'Domain/Model/JSON/Textarea.php',
+       'tx_form_domain_model_json_textblock' => $extensionClassesPath . 'Domain/Model/JSON/Textblock.php',
        'tx_form_domain_model_json_textline' => $extensionClassesPath . 'Domain/Model/JSON/Textline.php',
        'tx_form_domain_repository_content' => $extensionClassesPath . 'Domain/Repository/Content.php',
        'tx_form_system_elementcounter' => $extensionClassesPath . 'System/Elementcounter/Elementcounter.php',
@@ -163,6 +167,7 @@ return array(
        'tx_form_view_form_element_content' => $extensionClassesPath . 'View/Form/Element/Content.php',
        'tx_form_view_form_element_fieldset' => $extensionClassesPath . 'View/Form/Element/Fieldset.php',
        'tx_form_view_form_element_fileupload' => $extensionClassesPath . 'View/Form/Element/Fileupload.php',
+       'tx_form_view_form_element_header' => $extensionClassesPath . 'View/Form/Element/Header.php',
        'tx_form_view_form_element_hidden' => $extensionClassesPath . 'View/Form/Element/Hidden.php',
        'tx_form_view_form_element_imagebutton' => $extensionClassesPath . 'View/Form/Element/Imagebutton.php',
        'tx_form_view_form_element_optgroup' => $extensionClassesPath . 'View/Form/Element/Optgroup.php',
@@ -174,6 +179,7 @@ return array(
        'tx_form_view_form_element_select' => $extensionClassesPath . 'View/Form/Element/Select.php',
        'tx_form_view_form_element_submit' => $extensionClassesPath . 'View/Form/Element/Submit.php',
        'tx_form_view_form_element_textarea' => $extensionClassesPath . 'View/Form/Element/Textarea.php',
+       'tx_form_view_form_element_textblock' => $extensionClassesPath . 'View/Form/Element/Textblock.php',
        'tx_form_view_form_element_textline' => $extensionClassesPath . 'View/Form/Element/Textline.php',
        'tx_form_view_mail' => $extensionClassesPath . 'View/Mail/Mail.php',
        'tx_form_view_mail_html' => $extensionClassesPath . 'View/Mail/Html/Html.php',