Fixed bug #12230: Function tslib_cObj::crop() is not fully multibyte safe (Thanks...
[Packages/TYPO3.CMS.git] / typo3 / sysext / cms / tslib / class.tslib_content.php
index 0e6f2c4..68535ab 100644 (file)
@@ -1,34 +1,34 @@
 <?php
 /***************************************************************
- Copyright notice
-*
-*  (c) 1999-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
- 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.
- A copy is found in the textfile GPL.txt and important notices to the license
- from the author is found in LICENSE.txt distributed with these scripts.
-*
-*
- 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!
-***************************************************************/
+ * Copyright notice
+ *
+ * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
+ * 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.
+ * A copy is found in the textfile GPL.txt and important notices to the license
+ * from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ * 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!
+ ***************************************************************/
 /**
  * Contains classes for Content Rendering based on TypoScript Template configuration
  *
  * $Id$
- * Revised for TYPO3 3.6 June/2003 by Kasper Skaarhoj
+ * Revised for TYPO3 3.6 June/2003 by Kasper Skårhøj
  * XHTML compliant
  *
  * class tslib_cObj                    :               All main TypoScript features, rendering of content objects (cObjects). This class is the backbone of TypoScript Template rendering.
  * class tslib_tableOffset             :               Makes a table-offset (TS)
  * class tslib_frameset                        :               Generates framesets (TS)
  *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  */
 /**
  * [CLASS/FUNCTION INDEX of SCRIPT]
  *
  *
  *
- *  256: class tslib_cObj
- *  353:     function start($data,$table='')
- *  387:     function setParent($data,$currentRecord)
+ * 256: class tslib_cObj
+ * 353:     function start($data,$table='')
+ * 387:     function setParent($data,$currentRecord)
  *
- *              SECTION: CONTENT_OBJ:
- *  412:     function getCurrentVal()
- *  423:     function setCurrentVal($value)
- *  436:     function cObjGet($setup,$addKey='')
- *  460:     function cObjGetSingle($name,$conf,$TSkey='__')
+ * SECTION: CONTENT_OBJ:
+ * 412:     function getCurrentVal()
+ * 423:     function setCurrentVal($value)
+ * 436:     function cObjGet($setup,$addKey='')
+ * 460:     function cObjGetSingle($name,$conf,$TSkey='__')
  *
- *              SECTION: Functions rendering content objects (cObjects)
- *  629:     function HTML($conf)
- *  640:     function TEXT($conf)
- *  651:     function CLEARGIF($conf)
- *  670:     function COBJ_ARRAY($conf,$ext='')
- *  706:     function USER($conf,$ext='')
- *  733:     function FILE($conf)
- *  749:     function IMAGE($conf)
- *  768:     function IMG_RESOURCE($conf)
- *  780:     function IMGTEXT($conf)
+ * SECTION: Functions rendering content objects (cObjects)
+ * 629:     function HTML($conf)
+ * 640:     function TEXT($conf)
+ * 651:     function CLEARGIF($conf)
+ * 670:     function COBJ_ARRAY($conf,$ext='')
+ * 706:     function USER($conf,$ext='')
+ * 733:     function FILE($conf)
+ * 749:     function IMAGE($conf)
+ * 768:     function IMG_RESOURCE($conf)
+ * 780:     function IMGTEXT($conf)
  * 1203:     function CONTENT($conf)
  * 1290:     function RECORDS($conf)
  * 1370:     function HMENU($conf)
@@ -78,7 +78,7 @@
  * 2354:     function TEMPLATE($conf)
  * 2505:     function MULTIMEDIA($conf)
  *
- *              SECTION: Various helper functions for content objects:
+ * SECTION: Various helper functions for content objects:
  * 2592:     function getSlidePids($pidList, $pidConf)
  * 2623:     function getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal)
  * 2641:     function cImage($file,$conf)
  * 2765:     function fileResource($fName, $addParams='alt="" title=""')
  * 2788:     function lastChanged($tstamp)
  * 2805:     function linkWrap($content,$wrap)
- * 2824:     function getAltParam($conf, $longDesc=true)
+ * 2824:     function getAltParam($conf, $longDesc=TRUE)
  * 2859:     function cleanFormName($name)
  * 2875:     function getATagParams($conf, $addGlobal=1)
  *
- *              SECTION: HTML template processing functions
+ * SECTION: HTML template processing functions
  * 2922:     function getSubpart($content, $marker)
  * 2938:     function substituteSubpart($content,$marker,$subpartContent,$recursive=1)
  * 2951:     function substituteMarker($content,$marker,$markContent)
  * 3081:     function substituteMarkerInObject(&$tree, $markContentArray)
  * 3104:     function fillInMarkerArray($markContentArray, $row, $fieldList='', $nl2br=TRUE, $prefix='FIELD_', $HSC=FALSE)
  *
- *              SECTION: "stdWrap" + sub functions
+ * SECTION: "stdWrap" + sub functions
  * 3167:     function stdWrap($content,$conf)
  * 3364:     function numRows($conf)
  * 3388:     function listNum($content,$listNum,$char)
  * 4574:     function mailto_makelinks($data,$conf)
  * 4617:     function getImgResource($file,$fileArray)
  *
- *              SECTION: Data retrieval etc.
+ * SECTION: Data retrieval etc.
  * 4810:     function getFieldVal($field)
  * 4830:     function getData($string,$fieldArray)
  * 4975:     function rootLineValue($key,$field,$slideBack=0,$altRootLine='')
  * 5033:     function getKey($key,$arr)
  * 5056:     function TCAlookup($inputValue,$conf)
  *
- *              SECTION: Link functions (typolink)
+ * SECTION: Link functions (typolink)
  * 5116:     function typoLink($linktxt, $conf)
  * 5481:     function typoLink_URL($conf)
  * 5499:     function getTypoLink($label,$params,$urlParameters=array(),$target='')
  * 5619:     function getMailTo($mailAddress,$linktxt,$initP='?')
  * 5658:     function getQueryArguments($conf,$overruleQueryArgs=array(),$forceArgs=FALSE)
  *
- *              SECTION: Miscellaneous functions, stand alone
+ * SECTION: Miscellaneous functions, stand alone
  * 5754:     function wrap($content,$wrap,$char='|')
  * 5770:     function noTrimWrap($content,$wrap)
  * 5784:     function wrapSpace($content, $wrap)
  * 6159:     function linebreaks($string,$chars,$maxLines=0)
  * 6190:     function getUpdateJS($dataArray, $formName, $arrPrefix, $fieldList)
  *
- *              SECTION: Database functions, making of queries
+ * SECTION: Database functions, making of queries
  * 6260:     function DBgetDelete($table, $uid, $doExec=FALSE)
  * 6292:     function DBgetUpdate($table, $uid, $dataArr, $fieldList, $doExec=FALSE)
  * 6334:     function DBgetInsert($table, $pid, $dataArr, $fieldList, $doExec=FALSE)
  * 6878:     function checkPidArray($listArr)
  * 6902:     function checkPid($uid)
  *
- *              SECTION: Frontend editing functions
+ * SECTION: Frontend editing functions
  * 6959:     function editPanel($content, $conf, $currentRecord='', $dataArr=array())
  * 7146:     function editIcons($content,$params, $conf=array(), $currentRecord='', $dataArr=array(),$addUrlParamStr='')
  * 7228:     function editPanelLinkWrap($string,$formName,$cmd,$currentRecord='',$confirm='',$nPid='')
  *
  */
 
-       // Object TypoScript library included:
-if(t3lib_extMgm::isLoaded('obts')) {
-       require_once(t3lib_extMgm::extPath('obts').'_tsobject/_tso.php');
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 
 
 /**
@@ -244,13 +225,170 @@ if(t3lib_extMgm::isLoaded('obts')) {
  * The class "tslib_cObj" is normally instantiated and referred to as "cObj".
  * When you call your own PHP-code typically through a USER or USER_INT cObject then it is this class that instantiates the object and calls the main method. Before it does so it will set (if you are using classes) a reference to itself in the internal variable "cObj" of the object. Thus you can access all functions and data from this class by $this->cObj->... from within you classes written to be USER or USER_INT content objects.
  *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  * @package TYPO3
  * @subpackage tslib
- * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&cHash=4ad9d7acb4
  */
 class tslib_cObj {
-       var $align = Array ('center', 'right', 'left');
+
+       var $align = array(
+               'center',
+               'right',
+               'left'
+       );
+
+       /**
+        * stdWrap functions in their correct order
+        *
+        * @see stdWrap()
+        */
+       var $stdWrapOrder = array(
+               'stdWrapPreProcess' => 'hook', // this is a placeholder for the first Hook
+               'setContentToCurrent' => 'boolean',
+               'setContentToCurrent.' => 'array',
+               'setCurrent' => 'string',
+               'setCurrent.' => 'array',
+               'lang.' => 'array',
+               'data' => 'getText',
+               'data.' => 'array',
+               'field' => 'fieldName',
+               'field.' => 'array',
+               'current' => 'boolean',
+               'current.' => 'array',
+               'cObject' => 'cObject',
+               'cObject.' => 'array',
+               'numRows.' => 'array',
+               'filelist' => 'dir',
+               'filelist.' => 'array',
+               'preUserFunc' => 'functionName',
+               'stdWrapOverride' => 'hook', // this is a placeholder for the second Hook
+               'override' => 'string',
+               'override.' => 'array',
+               'preIfEmptyListNum' => 'listNum',
+               'preIfEmptyListNum.' => 'array',
+               'ifEmpty' => 'string',
+               'ifEmpty.' => 'array',
+               'ifBlank' => 'string',
+               'ifBlank.' => 'array',
+               'listNum' => 'listNum',
+               'listNum.' => 'array',
+               'trim' => 'boolean',
+               'trim.' => 'array',
+               'stdWrap' => 'stdWrap',
+               'stdWrap.' => 'array',
+               'stdWrapProcess' => 'hook', // this is a placeholder for the third Hook
+               'required' => 'boolean',
+               'required.' => 'array',
+               'if.' => 'array',
+               'fieldRequired' => 'fieldName',
+               'fieldRequired.' => 'array',
+               'csConv' => 'string',
+               'csConv.' => 'array',
+               'parseFunc' => 'objectpath',
+               'parseFunc.' => 'array',
+               'HTMLparser' => 'boolean',
+               'HTMLparser.' => 'array',
+               'split.' => 'array',
+               'prioriCalc' => 'boolean',
+               'prioriCalc.' => 'array',
+               'char' => 'integer',
+               'char.' => 'array',
+               'intval' => 'boolean',
+               'intval.' => 'array',
+               'numberFormat.' => 'array',
+               'date' => 'dateconf',
+               'date.' => 'array',
+               'strftime' => 'strftimeconf',
+               'strftime.' => 'array',
+               'age' => 'boolean',
+               'age.' => 'array',
+               'case' => 'case',
+               'case.' => 'array',
+               'bytes' => 'boolean',
+               'bytes.' => 'array',
+               'substring' => 'parameters',
+               'substring.' => 'array',
+               'removeBadHTML' => 'boolean',
+               'removeBadHTML.' => 'array',
+               'cropHTML' => 'crop',
+               'cropHTML.' => 'array',
+               'stripHtml' => 'boolean',
+               'stripHtml.' => 'array',
+               'crop' => 'crop',
+               'crop.' => 'array',
+               'rawUrlEncode' => 'boolean',
+               'rawUrlEncode.' => 'array',
+               'htmlSpecialChars' => 'boolean',
+               'htmlSpecialChars.' => 'array',
+               'doubleBrTag' => 'string',
+               'doubleBrTag.' => 'array',
+               'br' => 'boolean',
+               'br.' => 'array',
+               'brTag' => 'string',
+               'brTag.' => 'array',
+               'encapsLines.' => 'array',
+               'keywords' => 'boolean',
+               'keywords.' => 'array',
+               'innerWrap' => 'wrap',
+               'innerWrap.' => 'array',
+               'innerWrap2' => 'wrap',
+               'innerWrap2.' => 'array',
+               'fontTag' => 'wrap',
+               'fontTag.' => 'array',
+               'addParams.' => 'array',
+               'textStyle.' => 'array',
+               'tableStyle.' => 'array',
+               'filelink.' => 'array',
+               'preCObject' => 'cObject',
+               'preCObject.' => 'array',
+               'postCObject' => 'cObject',
+               'postCObject.' => 'array',
+               'wrapAlign' => 'align',
+               'wrapAlign.' => 'array',
+               'typolink.' => 'array',
+               'TCAselectItem.' => 'array',
+               'space' => 'space',
+               'space.' => 'array',
+               'spaceBefore' => 'int',
+               'spaceBefore.' => 'array',
+               'spaceAfter' => 'int',
+               'spaceAfter.' => 'array',
+               'wrap' => 'wrap',
+               'wrap.' => 'array',
+               'noTrimWrap' => 'wrap',
+               'noTrimWrap.' => 'array',
+               'wrap2' => 'wrap',
+               'wrap2.' => 'array',
+               'dataWrap' => 'dataWrap',
+               'dataWrap.' => 'array',
+               'prepend' => 'cObject',
+               'prepend.' => 'array',
+               'append' => 'cObject',
+               'append.' => 'array',
+               'wrap3' => 'wrap',
+               'wrap3.' => 'array',
+               'outerWrap' => 'wrap',
+               'outerWrap.' => 'array',
+               'insertData' => 'boolean',
+               'insertData.' => 'array',
+               'offsetWrap' => 'space',
+               'offsetWrap.' => 'array',
+               'postUserFunc' => 'functionName',
+               'postUserFuncInt' => 'functionName',
+               'prefixComment' => 'string',
+               'prefixComment.' => 'array',
+               'editIcons' => 'string',
+               'editIcons.' => 'array',
+               'editPanel' => 'boolean',
+               'editPanel.' => 'array',
+               'stdWrapPostProcess' => 'hook', // this is a placeholder for the last Hook
+               'debug' => 'boolean',
+               'debug.' => 'array',
+               'debugFunc' => 'boolean',
+               'debugFunc.' => 'array',
+               'debugData' => 'boolean',
+               'debugData.' => 'array'
+       );
 
        /**
         * Holds ImageMagick parameters and extensions used for compression
@@ -262,31 +400,75 @@ class tslib_cObj {
         * 1x = GIFs
         * 2x = JPGs
         */
-       var $image_compression = Array(
-               10 => Array('params'=>'', 'ext'=>'gif'),
-               11 => Array('params'=>'-colors 128', 'ext'=>'gif'),
-               12 => Array('params'=>'-colors 64', 'ext'=>'gif'),
-               13 => Array('params'=>'-colors 32', 'ext'=>'gif'),
-               14 => Array('params'=>'-colors 16', 'ext'=>'gif'),
-               15 => Array('params'=>'-colors 8', 'ext'=>'gif'),
-
-               30 => Array('params'=>'-colors 256', 'ext'=>'png'),
-               31 => Array('params'=>'-colors 128', 'ext'=>'png'),
-               32 => Array('params'=>'-colors 64', 'ext'=>'png'),
-               33 => Array('params'=>'-colors 32', 'ext'=>'png'),
-               34 => Array('params'=>'-colors 16', 'ext'=>'png'),
-               35 => Array('params'=>'-colors 8', 'ext'=>'png'),
-               39 => Array('params'=>'', 'ext'=>'png'),
-
-               20 => Array('params'=>'-quality 100', 'ext'=>'jpg'),
-               21 => Array('params'=>'-quality 90', 'ext'=>'jpg'),
-               22 => Array('params'=>'-quality 80', 'ext'=>'jpg'),
-               23 => Array('params'=>'-quality 70', 'ext'=>'jpg'),
-               24 => Array('params'=>'-quality 60', 'ext'=>'jpg'),
-               25 => Array('params'=>'-quality 50', 'ext'=>'jpg'),
-               26 => Array('params'=>'-quality 40', 'ext'=>'jpg'),
-               27 => Array('params'=>'-quality 30', 'ext'=>'jpg'),
-               28 => Array('params'=>'-quality 20', 'ext'=>'jpg')
+       var $image_compression = array(
+               10 => array(
+                       'params' => '', 'ext' => 'gif'
+               ),
+               11 => array(
+                       'params' => '-colors 128', 'ext' => 'gif'
+               ),
+               12 => array(
+                       'params' => '-colors 64', 'ext' => 'gif'
+               ),
+               13 => array(
+                       'params' => '-colors 32', 'ext' => 'gif'
+               ),
+               14 => array(
+                       'params' => '-colors 16', 'ext' => 'gif'
+               ),
+               15 => array(
+                       'params' => '-colors 8', 'ext' => 'gif'
+               ),
+
+               20 => array(
+                       'params' => '-quality 100', 'ext' => 'jpg'
+               ),
+               21 => array(
+                       'params' => '-quality 90', 'ext' => 'jpg'
+               ),
+               22 => array(
+                       'params' => '-quality 80', 'ext' => 'jpg'
+               ),
+               23 => array(
+                       'params' => '-quality 70', 'ext' => 'jpg'
+               ),
+               24 => array(
+                       'params' => '-quality 60', 'ext' => 'jpg'
+               ),
+               25 => array(
+                       'params' => '-quality 50', 'ext' => 'jpg'
+               ),
+               26 => array(
+                       'params' => '-quality 40', 'ext' => 'jpg'
+               ),
+               27 => array(
+                       'params' => '-quality 30', 'ext' => 'jpg'
+               ),
+               28 => array(
+                       'params' => '-quality 20', 'ext' => 'jpg'
+               ),
+
+               30 => array(
+                       'params' => '-colors 256', 'ext' => 'png'
+               ),
+               31 => array(
+                       'params' => '-colors 128', 'ext' => 'png'
+               ),
+               32 => array(
+                       'params' => '-colors 64', 'ext' => 'png'
+               ),
+               33 => array(
+                       'params' => '-colors 32', 'ext' => 'png'
+               ),
+               34 => array(
+                       'params' => '-colors 16', 'ext' => 'png'
+               ),
+               35 => array(
+                       'params' => '-colors 8', 'ext' => 'png'
+               ),
+               39 => array(
+                       'params' => '', 'ext' => 'png'
+               ),
        );
 
        /**
@@ -294,7 +476,7 @@ class tslib_cObj {
         *
         * @see IMGTEXT()
         */
-       var $image_effects = Array(
+       var $image_effects = array(
                1 => '-rotate 90',
                2 => '-rotate 270',
                3 => '-rotate 180',
@@ -313,42 +495,49 @@ class tslib_cObj {
         * The function stdWrap has TypoScript properties that fetch field-data from this array.
         * @see init()
         */
-       var $data = Array();
-       var $oldData = Array();                         // Used for backup...
-       var $alternativeData ='';                       // If this is set with an array before stdWrap, it's used instead of $this->data in the data-property in stdWrap
-       var $parameters = Array();                      // Used by the parseFunc function and is loaded with tag-parameters when parsing tags.
+       var $data = array();
+       protected $table = '';
+       var $oldData = array(); // Used for backup...
+       var $alternativeData = ''; // If this is set with an array before stdWrap, it's used instead of $this->data in the data-property in stdWrap
+       var $parameters = array(); // Used by the parseFunc function and is loaded with tag-parameters when parsing tags.
        var $currentValKey = 'currentValue_kidjls9dksoje';
-       var $currentRecord = '';                        // This is set to the [table]:[uid] of the record delivered in the $data-array, if the cObjects CONTENT or RECORD is in operation. Note that $GLOBALS['TSFE']->currentRecord is set to an equal value but always indicating the latest record rendered.
-       var $currentRecordTotal = 0;            // Set in cObj->RECORDS and cObj->CONTENT to the current number of records selected in a query.
-       var $currentRecordNumber = 0;           // Incremented in cObj->RECORDS and cObj->CONTENT before each record rendering.
-       var $parentRecordNumber = 0;            // Incremented in parent cObj->RECORDS and cObj->CONTENT before each record rendering.
-       var $parentRecord = array();            // If the tslib_cObj was started from CONTENT, RECORD or SEARCHRESULT cObject's this array has two keys, 'data' and 'currentRecord' which indicates the record and data for the parent cObj.
-       var $regObj;            // This may be set as a reference to the calling object of eg. cObjGetSingle. Anyway, just use it as you like. It's used in productsLib.inc for example.
-
-       // internal
-       var $INT_include=0;             // Is set to 1 if the instance of this cObj is executed from a PHP_SCRIPT_INT -include script (see pagegen, bottom of document)
-       var $checkPid_cache = Array();          // This is used by checkPid, that checks if pages are accessible. The $checkPid_cache['page_uid'] is set true or false upon this check featuring a caching function for the next request.
+       var $currentRecord = ''; // This is set to the [table]:[uid] of the record delivered in the $data-array, if the cObjects CONTENT or RECORD is in operation. Note that $GLOBALS['TSFE']->currentRecord is set to an equal value but always indicating the latest record rendered.
+       var $currentRecordTotal = 0; // Set in cObj->RECORDS and cObj->CONTENT to the current number of records selected in a query.
+       var $currentRecordNumber = 0; // Incremented in cObj->RECORDS and cObj->CONTENT before each record rendering.
+       var $parentRecordNumber = 0; // Incremented in parent cObj->RECORDS and cObj->CONTENT before each record rendering.
+       var $parentRecord = array(); // If the tslib_cObj was started from CONTENT, RECORD or SEARCHRESULT cObject's this array has two keys, 'data' and 'currentRecord' which indicates the record and data for the parent cObj.
+       var $regObj; // This may be set as a reference to the calling object of eg. cObjGetSingle. Anyway, just use it as you like. It's used in productsLib.inc for example.
+
+
+               // internal
+       var $INT_include = 0; // Is set to 1 if the instance of this cObj is executed from a PHP_SCRIPT_INT -include script (see pagegen, bottom of document)
+       var $checkPid_cache = array(); // This is used by checkPid, that checks if pages are accessible. The $checkPid_cache['page_uid'] is set TRUE or FALSE upon this check featuring a caching function for the next request.
        var $checkPid_badDoktypeList = '255';
-       var $lastTypoLinkUrl='';        // This will be set by typoLink() to the url of the most recent link created.
-       var $lastTypoLinkTarget='';     // DO. link target.
+       var $lastTypoLinkUrl = ''; // This will be set by typoLink() to the url of the most recent link created.
+       var $lastTypoLinkTarget = ''; // DO. link target.
        var $lastTypoLinkLD = array();
-       var $substMarkerCache=array();  // Caching substituteMarkerArrayCached function
-       var $recordRegister=array();    // Array that registers rendered content elements (or any table) to make sure they are not rendered recursively!
-       var $cObjHookObjectsArr = array();              // Containig hooks for userdefined cObjects
-       protected $stdWrapHookObjects = array();                // Containing hook objects for stdWrap
-       protected $getImgResourceHookObjects;                   // Containing hook objects for getImgResource
+       var $substMarkerCache = array(); // Caching substituteMarkerArrayCached function
+       var $recordRegister = array(); // array that registers rendered content elements (or any table) to make sure they are not rendered recursively!
+       var $cObjHookObjectsArr = array(); // Containig hooks for userdefined cObjects
+       protected $stdWrapHookObjects = array(); // Containing hook objects for stdWrap
+       protected $getImgResourceHookObjects; // Containing hook objects for getImgResource
 
        /**
-        * Set to true by doConvertToUserIntObject() if USER object wants to become USER_INT
+        * @var array with members of tslib_content_abstract
         */
-       protected $doConvertToUserIntObject = false;
+       protected $contentObjects = array();
 
        /**
-        * Indicates current object type. Can hold one of OBJECTTYPE_ constants or false.
+        * Set to TRUE by doConvertToUserIntObject() if USER object wants to become USER_INT
+        */
+       public $doConvertToUserIntObject = FALSE;
+
+       /**
+        * Indicates current object type. Can hold one of OBJECTTYPE_ constants or FALSE.
         * The value is set and reset inside USER() function. Any time outside of
-        * USER() it is false.
+        * USER() it is FALSE.
         */
-       protected $userObjectType = false;
+       protected $userObjectType = FALSE;
 
        /**
         * Indicates that object type is USER.
@@ -373,29 +562,63 @@ class tslib_cObj {
         * @param       string          $table  the table that the data record is from.
         * @return      void
         */
-       function start($data,$table='') {
+       function start($data, $table = '') {
                global $TYPO3_CONF_VARS;
                $this->data = $data;
-               $this->currentRecord = $table ? $table.':'.$this->data['uid'] : '';
-               $this->parameters = Array();
-               if (is_array ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'])) {
+               $this->table = $table;
+               $this->currentRecord = $table ? $table . ':' . $this->data['uid'] : '';
+               $this->parameters = array();
+               if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'])) {
                        foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'] as $classArr) {
                                $this->cObjHookObjectsArr[$classArr[0]] = t3lib_div::getUserObj($classArr[1]);
                        }
                }
 
                $this->stdWrapHookObjects = array();
-               if(is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'])) {
-                       foreach($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'] as $classData) {
+               if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'])) {
+                       foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'] as $classData) {
                                $hookObject = t3lib_div::getUserObj($classData);
 
-                               if(!($hookObject instanceof tslib_content_stdWrapHook)) {
-                                       throw new UnexpectedValueException('$hookObject must implement interface tslib_content_stdWrapHook', 1195043965);
+                               if (!($hookObject instanceof tslib_content_stdWrapHook)) {
+                                       throw new UnexpectedValueException(
+                                               $classData . ' must implement interface tslib_content_stdWrapHook',
+                                               1195043965
+                                       );
                                }
 
                                $this->stdWrapHookObjects[] = $hookObject;
                        }
                }
+
+               if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'])) {
+                       foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'] as $classData) {
+                               $postInitializationProcessor = t3lib_div::getUserObj($classData);
+
+                               if (!($postInitializationProcessor instanceof tslib_content_PostInitHook)) {
+                                       throw new UnexpectedValueException(
+                                               $classData . ' must implement interface tslib_content_PostInitHook',
+                                               1274563549
+                                       );
+                               }
+
+                               $postInitializationProcessor->postProcessContentObjectInitialization($this);
+                       }
+               }
+       }
+
+       /**
+        * Clone helper.
+        *
+        * Resets the references to the TypoScript Content Object implementation
+        * objects of tslib_content_*. Otherwise they would still point to the
+        * original tslib_cObj instance's tslib_content_* instances, they in return
+        * would back-reference to the original tslib_cObj instance instead of the
+        * newly cloned tslib_cObj instance.
+        *
+        * @see http://bugs.typo3.org/view.php?id=16568
+        */
+       public function __clone() {
+               $this->contentObjects = array();
        }
 
        /**
@@ -408,12 +631,15 @@ class tslib_cObj {
                if (!isset($this->getImgResourceHookObjects)) {
                        $this->getImgResourceHookObjects = array();
 
-                       if(is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'])) {
-                               foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'] as $classData) {
+                       if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'])) {
+                               foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'] as $classData) {
                                        $hookObject = t3lib_div::getUserObj($classData);
 
-                                       if(!($hookObject instanceof tslib_cObj_getImgResourceHook)) {
-                                               throw new UnexpectedValueException('$hookObject must implement interface tslib_cObj_getImgResourceHook', 1218636383);
+                                       if (!($hookObject instanceof tslib_cObj_getImgResourceHook)) {
+                                               throw new UnexpectedValueException(
+                                                       '$hookObject must implement interface tslib_cObj_getImgResourceHook',
+                                                       1218636383
+                                               );
                                        }
 
                                        $this->getImgResourceHookObjects[] = $hookObject;
@@ -433,17 +659,15 @@ class tslib_cObj {
         * @return      void
         * @access private
         */
-       function setParent($data,$currentRecord)        {
-               $this->parentRecord=array('data'=>$data, 'currentRecord'=>$currentRecord);
+       function setParent($data, $currentRecord) {
+               $this->parentRecord = array(
+                       'data' => $data,
+                       'currentRecord' => $currentRecord
+               );
        }
 
 
 
-
-
-
-
-
        /***********************************************
         *
         * CONTENT_OBJ:
@@ -458,7 +682,7 @@ class tslib_cObj {
         *
         * @return      mixed           The "current" value
         */
-       function getCurrentVal()        {
+       function getCurrentVal() {
                return $this->data[$this->currentValKey];
        }
 
@@ -469,7 +693,7 @@ class tslib_cObj {
         * @return      void
         * @see getCurrentVal()
         */
-       function setCurrentVal($value)  {
+       function setCurrentVal($value) {
                $this->data[$this->currentValKey] = $value;
        }
 
@@ -477,20 +701,20 @@ class tslib_cObj {
         * Rendering of a "numerical array" of cObjects from TypoScript
         * Will call ->cObjGetSingle() for each cObject found and accumulate the output.
         *
-        * @param       array           $setup: Array with cObjects as values.
+        * @param       array           $setup: array with cObjects as values.
         * @param       string          $addKey: A prefix for the debugging information
         * @return      string          Rendered output from the cObjects in the array.
         * @see cObjGetSingle()
         */
-       function cObjGet($setup,$addKey='')     {
-               if (is_array($setup))   {
-                       $sKeyArray=t3lib_TStemplate::sortedKeyList($setup);
-                       $content ='';
-                       foreach($sKeyArray as $theKey)  {
-                               $theValue=$setup[$theKey];
-                               if (intval($theKey) && !strstr($theKey,'.'))    {
-                                       $conf=$setup[$theKey.'.'];
-                                       $content.=$this->cObjGetSingle($theValue,$conf,$addKey.$theKey);        // Get the contentObject
+       function cObjGet($setup, $addKey = '') {
+               if (is_array($setup)) {
+                       $sKeyArray = t3lib_TStemplate::sortedKeyList($setup);
+                       $content = '';
+                       foreach ($sKeyArray as $theKey) {
+                               $theValue = $setup[$theKey];
+                               if (intval($theKey) && !strstr($theKey, '.')) {
+                                       $conf = $setup[$theKey . '.'];
+                                       $content .= $this->cObjGetSingle($theValue, $conf, $addKey . $theKey); // Get the contentObject
                                }
                        }
                        return $content;
@@ -504,170 +728,133 @@ class tslib_cObj {
         * @param       array           The array with TypoScript properties for the content object
         * @param       string          A string label used for the internal debugging tracking.
         * @return      string          cObject output
-        * @example http://typo3.org/doc.0.html?&encryptionKey=&tx_extrepmgm_pi1[extUid]=267&tx_extrepmgm_pi1[tocEl]=153&cHash=7e74f4d331
         */
-       function cObjGetSingle($name,$conf,$TSkey='__') {
+       function cObjGetSingle($name, $conf, $TSkey = '__') {
                global $TYPO3_CONF_VARS;
 
-               $content='';
+               $content = '';
                        // Checking that the function is not called eternally. This is done by interrupting at a depth of 100
                $GLOBALS['TSFE']->cObjectDepthCounter--;
-               if ($GLOBALS['TSFE']->cObjectDepthCounter>0)    {
+               if ($GLOBALS['TSFE']->cObjectDepthCounter > 0) {
                        $name = trim($name);
-                       if ($GLOBALS['TT']->LR) $GLOBALS['TT']->push($TSkey, $name);
+                       if ($GLOBALS['TT']->LR)
+                               $GLOBALS['TT']->push($TSkey, $name);
 
                                // Checking if the COBJ is a reference to another object. (eg. name of 'blabla.blabla = < styles.something')
-                       if (substr($name,0,1)=='<')     {
-                               $key = trim(substr($name,1));
+                       if (substr($name, 0, 1) == '<') {
+                               $key = trim(substr($name, 1));
                                $cF = t3lib_div::makeInstance('t3lib_TSparser');
                                        // $name and $conf is loaded with the referenced values.
-                               $old_conf=$conf;
-                               list($name, $conf) = $cF->getVal($key,$GLOBALS['TSFE']->tmpl->setup);
-                               if (is_array($old_conf) && count($old_conf))    {
-                                       $conf = $this->joinTSarrays($conf,$old_conf);
+                               $old_conf = $conf;
+                               list ($name, $conf) = $cF->getVal($key, $GLOBALS['TSFE']->tmpl->setup);
+                               if (is_array($old_conf) && count($old_conf)) {
+                                       $conf = $this->joinTSarrays($conf, $old_conf);
                                }
                                        // Getting the cObject
                                $GLOBALS['TT']->incStackPointer();
-                                       $content.=$this->cObjGetSingle($name,$conf,$key);
+                               $content .= $this->cObjGetSingle($name, $conf, $key);
                                $GLOBALS['TT']->decStackPointer();
                        } else {
 
-                               $hooked = false;
+                               $hooked = FALSE;
                                        // Application defined cObjects
-                               foreach ($this->cObjHookObjectsArr as $cObjName => $hookObj)    {
-                                       if (($name===$cObjName) && method_exists($hookObj, 'cObjGetSingleExt')) {
-                                               $content.= $hookObj->cObjGetSingleExt($name, $conf, $TSkey, $this);
-                                               $hooked = true;
+                               foreach ($this->cObjHookObjectsArr as $cObjName => $hookObj) {
+                                       if (($name === $cObjName) && method_exists($hookObj, 'cObjGetSingleExt')) {
+                                               $content .= $hookObj->cObjGetSingleExt($name, $conf, $TSkey, $this);
+                                               $hooked = TRUE;
                                        }
                                }
-                               if (!$hooked && isset($GLOBALS['OBTS']['tso_list'][$name]) && t3lib_extMgm::isLoaded('obts')) {
-                                       $content.= obts_dtutil::renderDatatypeContent($name, $GLOBALS['OBTS']['tso_list'][$name], $conf, $this);
-                               } elseif (!$hooked) {
-                                               // Traditional Content Object branching:
-                                       switch($name)   {
-                                               case 'COBJ_ARRAY':
-                                               case 'COA':
-                                                       $content.=$this->COBJ_ARRAY($conf);
-                                               break;
-                                               case 'COA_INT':
-                                                       $content.=$this->COBJ_ARRAY($conf,'INT');
-                                               break;
-                                               case 'HTML':
-                                                       $content.=$this->HTML($conf);
-                                               break;
-                                               case 'TEXT':
-                                                       $content.=$this->TEXT($conf);
-                                               break;
-                                               case 'CLEARGIF':
-                                                       $content.=$this->CLEARGIF($conf);
-                                               break;
-                                               case 'FILE':
-                                                       $content.=$this->FILE($conf);
-                                               break;
-                                               case 'IMAGE':
-                                                       $content.=$this->IMAGE($conf);
-                                               break;
-                                               case 'IMG_RESOURCE':
-                                                       $content.=$this->IMG_RESOURCE($conf);
-                                               break;
-                                               case 'IMGTEXT':
-                                                       $content.=$this->IMGTEXT($conf);
-                                               break;
-                                               case 'CONTENT':
-                                                       $content.=$this->CONTENT($conf);
-                                               break;
-                                               case 'RECORDS':
-                                                       $content.=$this->RECORDS($conf);
-                                               break;
-                                               case 'HMENU':
-                                                       $content.=$this->HMENU($conf);
-                                               break;
-                                               case 'CTABLE':
-                                                       $content.=$this->CTABLE($conf);
-                                               break;
-                                               case 'OTABLE':
-                                                       $content.=$this->OTABLE($conf);
-                                               break;
-                                               case 'COLUMNS':
-                                                       $content.=$this->COLUMNS($conf);
-                                               break;
-                                               case 'HRULER':
-                                                       $content.=$this->HRULER($conf);
-                                               break;
-                                               case 'CASE':
-                                                       $content.=$this->CASEFUNC($conf);
-                                               break;
-                                               case 'LOAD_REGISTER':
-                                               case 'RESTORE_REGISTER':
-                                                       $this->LOAD_REGISTER($conf,$name);
-                                               break;
-                                               case 'FORM':
-                                                       $content.=$this->FORM($conf);
-                                               break;
-                                               case 'SEARCHRESULT':
-                                                       $content.=$this->SEARCHRESULT($conf);
-                                               break;
-                                               case 'PHP_SCRIPT':
-                                                       $content.=$this->PHP_SCRIPT($conf);
-                                               break;
-                                               case 'PHP_SCRIPT_EXT':
-                                                       $content.=$this->PHP_SCRIPT($conf,'EXT');
-                                               break;
-                                               case 'PHP_SCRIPT_INT':
-                                                       $content.=$this->PHP_SCRIPT($conf,'INT');
-                                               break;
-                                               case 'USER':
-                                                       $content.=$this->USER($conf);
-                                               break;
-                                               case 'USER_INT':
-                                                       $content.=$this->USER($conf,'INT');
-                                               break;
-                                               case 'TEMPLATE':
-                                                       $content.=$this->TEMPLATE($conf);
-                                               break;
-                                               case 'EDITPANEL':
-                                                       if ($GLOBALS['TSFE']->beUserLogin)      {$content.=$this->editPanel($content, $conf);}
-                                               break;
-                                               case 'MULTIMEDIA':
-                                                       $content.=$this->MULTIMEDIA($conf);
-                                               break;
-                                               case 'MEDIA':
-                                                       $content.=$this->MEDIA($conf);
-                                               break;
-                                               case 'SWFOBJECT':
-                                                       $content.=$this->SWFOBJECT($conf);
-                                               break;
-                                               case 'QTOBJECT':
-                                                       $content.=$this->QTOBJECT($conf);
-                                               break;
-                                               default:
+                               if (!$hooked) {
+                                       $contentObject = $this->getContentObject($name);
+                                       if ($contentObject) {
+                                               $content .= $contentObject->render($conf);
+                                       } else {
                                                                // call hook functions for extra processing
-                                                       if($name && is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault']))    {
-                                                               foreach($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'] as $classData)    {
+                                                       if ($name && is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'])) {
+                                                               foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'] as $classData) {
                                                                        $hookObject = t3lib_div::getUserObj($classData);
 
-                                                                       if(!($hookObject instanceof tslib_content_cObjGetSingleHook)) {
-                                                                               throw new UnexpectedValueException('$hookObject must implement interface tslib_content_cObjGetSingleHook', 1195043731);
+                                                                       if (!($hookObject instanceof tslib_content_cObjGetSingleHook)) {
+                                                                               throw new UnexpectedValueException(
+                                                                                       '$hookObject must implement interface tslib_content_cObjGetSingleHook',
+                                                                                       1195043731
+                                                                               );
                                                                        }
                                                                        /* @var $hookObject tslib_content_cObjGetSingleHook */
                                                                        $content .= $hookObject->getSingleContentObject($name, (array) $conf, $TSkey, $this);
                                                                }
-                                                       }
-                                               break;
+                                               } else {
+                                                               // log error in AdminPanel
+                                                       $warning = sprintf('Content Object "%s" does not exist', $name);
+                                                       $GLOBALS['TT']->setTSlogMessage($warning, 2);
+                                               }
                                        }
                                }
                        }
-                       if ($GLOBALS['TT']->LR) $GLOBALS['TT']->pull($content);
+                       if ($GLOBALS['TT']->LR)
+                               $GLOBALS['TT']->pull($content);
                }
                        // Increasing on exit...
                $GLOBALS['TSFE']->cObjectDepthCounter++;
                return $content;
        }
 
+       /**
+        * Returns a new content object of type $name.
+        *
+        * @param string $name
+        * @return tslib_content_abstract
+        */
+       public function getContentObject($name) {
+               $classMapping = array(
+                       'HTML' => 'Html',
+                       'TEXT' => 'Text',
+                       'CASE' => 'Case',
+                       'CLEARGIF' => 'ClearGif',
+                       'COBJ_ARRAY' => 'ContentObjectArray',
+                       'COA' => 'ContentObjectArray',
+                       'COA_INT' => 'ContentObjectArrayInternal',
+                       'USER' => 'User',
+                       'USER_INT' => 'UserInternal',
+                       'FILE' => 'File',
+                       'IMAGE' => 'Image',
+                       'IMG_RESOURCE' => 'ImageResource',
+                       'IMGTEXT' => 'ImageText',
+                       'CONTENT' => 'Content',
+                       'RECORDS' => 'Records',
+                       'HMENU' => 'HierarchicalMenu',
+                       'CTABLE' => 'ContentTable',
+                       'OTABLE' => 'OffsetTable',
+                       'COLUMNS' => 'Columns',
+                       'HRULER' => 'HorizontalRuler',
+                       'CASEFUNC' => 'Case',
+                       'LOAD_REGISTER' => 'LoadRegister',
+                       'RESTORE_REGISTER' => 'RestoreRegister',
+                       'FORM' => 'Form',
+                       'SEARCHRESULT' => 'SearchResult',
+                       'PHP_SCRIPT' => 'PhpScript',
+                       'PHP_SCRIPT_INT' => 'PhpScriptInternal',
+                       'PHP_SCRIPT_EXT' => 'PhpScriptExternal',
+                       'TEMPLATE' => 'Template',
+                       'FLUIDTEMPLATE' => 'FluidTemplate',
+                       'MULTIMEDIA' => 'Multimedia',
+                       'MEDIA' => 'Media',
+                       'SWFOBJECT' => 'ShockwaveFlashObject',
+                       'QTOBJECT' => 'QuicktimeObject',
+                       'SVG' => 'ScalableVectorGraphics',
+                       'EDITPANEL' => 'EditPanel',
+               );
+               $name = $classMapping[$name];
 
-
-
-
+               if (!array_key_exists($name, $this->contentObjects)) {
+                       try {
+                               $this->contentObjects[$name] = t3lib_div::makeInstance('tslib_content_' . $name, $this);
+                       } catch (ReflectionException $e) {
+                               $this->contentObjects[$name] = NULL;
+                       }
+               }
+               return $this->contentObjects[$name];
+       }
 
 
        /********************************************
@@ -679,3225 +866,2387 @@ class tslib_cObj {
        /**
         * Rendering the cObject, HTML
         *
-        * @param       array           Array of TypoScript properties
+        * @param       array           array of TypoScript properties
         * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=349&cHash=d3fd0c70b4
         */
-       function HTML($conf)    {
-               return $this->stdWrap($conf['value'],$conf['value.']);
+       function HTML($conf) {
+               return $this->getContentObject('HTML')->render($conf);
        }
 
        /**
         * Rendering the cObject, TEXT
         *
-        * @param       array           Array of TypoScript properties
+        * @param       array           array of TypoScript properties
         * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=350&cHash=b49de28f83
         */
-       function TEXT($conf)    {
-               return $this->stdWrap($conf['value'],$conf);
+       function TEXT($conf) {
+               return $this->getContentObject('TEXT')->render($conf);
        }
 
        /**
         * Rendering the cObject, CLEARGIF
         *
-        * @param       array           Array of TypoScript properties
+        * @param       array           array of TypoScript properties
         * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=355&cHash=70c0f19915
         */
-       function CLEARGIF($conf)        {
-               $w = $this->stdWrap($conf['width'],$conf['width.']);
-               $h = $this->stdWrap($conf['height'],$conf['height.']);
-               $w = $w ? $w : 1;
-               $h = $h ? $h : 1;
-               $wrap = $conf['wrap'] ? $conf['wrap'] : '|<br />';
-               $theValue = $this->wrap('<img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$w.'" height="'.$h.'"'.$this->getBorderAttr(' border="0"').' alt="" title="" />', $wrap);
-
-               return $this->stdWrap($theValue,$conf['stdWrap.']);
+       function CLEARGIF($conf) {
+               return $this->getContentObject('CLEARGIF')->render($conf);
        }
 
        /**
         * Rendering the cObject, COBJ_ARRAY / COA and COBJ_ARRAY_INT
         *
-        * @param       array           Array of TypoScript properties
+        * @param       array           array of TypoScript properties
         * @param       string          If "INT" then the cObject is a "COBJ_ARRAY_INT" (non-cached), otherwise just "COBJ_ARRAY" (cached)
         * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=351&cHash=a09db0329c
         */
-       function COBJ_ARRAY($conf,$ext='')      {
-
-               if (is_array($conf)) {
-                       $content = '';
-                       switch($ext) {
-                               case 'INT':
-                                       $substKey = $ext . '_SCRIPT.' . $GLOBALS['TSFE']->uniqueHash();
-                                       $content .= '<!--'.$substKey.'-->';
-                                       $GLOBALS['TSFE']->config[$ext . 'incScript'][$substKey] = array (
-                                               'file' => $conf['includeLibs'],
-                                               'conf' => $conf,
-                                               'cObj' => serialize($this),
-                                               'type' => 'COA'
-                                       );
-                               break;
-                               default:
-                                       if ($this->checkIf($conf['if.'])) {
-                                               $this->includeLibs($conf);
-                                               $content = $this->cObjGet($conf);
-                                               if ($conf['wrap']) {
-                                                       $content = $this->wrap($content, $conf['wrap']);
-                                               }
-                                               if ($conf['stdWrap.']) {
-                                                       $content = $this->stdWrap($content, $conf['stdWrap.']);
-                                               }
-                                       }
-                               break;
-                       }
-                       return $content;
+       function COBJ_ARRAY($conf, $ext = '') {
+               if ($ext === 'INT') {
+                       return $this->getContentObject('COA_INT')->render($conf);
                } else {
-                       $GLOBALS['TT']->setTSlogMessage('No elements in this content object array (COBJ_ARRAY, COA, COA_INT).', 2);
+                       return $this->getContentObject('COA')->render($conf);
                }
        }
 
        /**
         * Rendering the cObject, USER and USER_INT
         *
-        * @param       array           Array of TypoScript properties
+        * @param       array           array of TypoScript properties
         * @param       string          If "INT" then the cObject is a "USER_INT" (non-cached), otherwise just "USER" (cached)
         * @return      string          Output
-        * @link        http://typo3.org/documentation/document-library/references/doc_core_tsref/4.1.0/view/8/22/
         */
        function USER($conf, $ext = '') {
-               $content = '';
-               switch ($ext) {
-                       case 'INT':
-                               $this->userObjectType = self::OBJECTTYPE_USER_INT;
-                               $substKey = $ext . '_SCRIPT.' . $GLOBALS['TSFE']->uniqueHash();
-                               $content.='<!--' . $substKey . '-->';
-                               $GLOBALS['TSFE']->config[$ext . 'incScript'][$substKey] = array(
-                                       'file' => $conf['includeLibs'],
-                                       'conf' => $conf,
-                                       'cObj' => serialize($this),
-                                       'type' => 'FUNC'
-                               );
-                               break;
-                       default:
-                               if ($this->userObjectType === false) {
-                                       // Come here only if we are not called from $TSFE->INTincScript_process()!
-                                       $this->userObjectType = self::OBJECTTYPE_USER;
-                               }
-                               $this->includeLibs($conf);
-                               $tempContent = $this->callUserFunction($conf['userFunc'], $conf, '');
-                               if ($this->doConvertToUserIntObject) {
-                                       $this->doConvertToUserIntObject = false;
-                                       $content = $this->USER($conf, 'INT');
-                               } else {
-                                       $content .= $tempContent;
-                               }
-                               break;
+               if ($ext === 'INT') {
+                       return $this->getContentObject('USER_INT')->render($conf);
+               } else {
+                       return $this->getContentObject('USER')->render($conf);
                }
-               $this->userObjectType = false;
-               return $content;
        }
 
        /**
         * Retrieves a type of object called as USER or USER_INT. Object can detect their
         * type by using this call. It returns OBJECTTYPE_USER_INT or OBJECTTYPE_USER depending on the
-        * current object execution. In all other cases it will return false to indicate
+        * current object execution. In all other cases it will return FALSE to indicate
         * a call out of context.
         *
-        * @return      mixed   One of OBJECTTYPE_ class constants or false
+        * @return      mixed   One of OBJECTTYPE_ class constants or FALSE
         */
        public function getUserObjectType() {
                return $this->userObjectType;
        }
 
        /**
+        * Sets the user object type
+        *
+        * @param mixed $userObjectType
+        * @return void
+        */
+       public function setUserObjectType($userObjectType) {
+               $this->userObjectType = $userObjectType;
+       }
+
+       /**
         * Requests the current USER object to be converted to USER_INT.
         *
         * @return      void
         */
        public function convertToUserIntObject() {
                if ($this->userObjectType !== self::OBJECTTYPE_USER) {
-                       $GLOBALS['TT']->setTSlogMessage('tslib_cObj::convertToUserIntObject() ' .
-                               'is called in the wrong context or for the wrong object type', 2);
-               }
-               else {
-                       $this->doConvertToUserIntObject = true;
+                       $GLOBALS['TT']->setTSlogMessage('tslib_cObj::convertToUserIntObject() ' . 'is called in the wrong context or for the wrong object type', 2);
+               } else {
+                       $this->doConvertToUserIntObject = TRUE;
                }
        }
 
        /**
         * Rendering the cObject, FILE
         *
-        * @param       array           Array of TypoScript properties
+        * @param       array           array of TypoScript properties
         * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=352&cHash=379c60f8bc
         */
-       function FILE($conf)    {
-               $theValue = $this->fileResource($this->stdWrap($conf['file'],$conf['file.']), trim($this->getAltParam($conf, false)));
-               if ($conf['linkWrap'])  {
-                       $theValue = $this->linkWrap($theValue,$conf['linkWrap']);
-               }
-               return $this->wrap($theValue,$conf['wrap']);
+       function FILE($conf) {
+               return $this->getContentObject('FILE')->render($conf);
        }
 
        /**
         * Rendering the cObject, IMAGE
         *
-        * @param       array           Array of TypoScript properties
+        * @param       array           array of TypoScript properties
         * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=353&cHash=440681ea56
         * @see cImage()
         */
-       function IMAGE($conf)   {
-               $content='';
-               if ($this->checkIf($conf['if.']))       {
-                       $theValue = $this->cImage($conf['file'],$conf);
-                       if ($conf['stdWrap.'])  {
-                               $theValue = $this->stdWrap($theValue,$conf['stdWrap.']);
-                       }
-                       return $theValue;
-               }
+       function IMAGE($conf) {
+               return $this->getContentObject('IMAGE')->render($conf);
        }
 
        /**
         * Rendering the cObject, IMG_RESOURCE
         *
-        * @param       array           Array of TypoScript properties
+        * @param       array           array of TypoScript properties
         * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=354&cHash=46f9299706
         * @see getImgResource()
         */
-       function IMG_RESOURCE($conf)    {
-               $GLOBALS['TSFE']->lastImgResourceInfo = $this->getImgResource($conf['file'],$conf['file.']);
-               return $this->stdWrap($GLOBALS['TSFE']->lastImgResourceInfo[3],$conf['stdWrap.']);
+       function IMG_RESOURCE($conf) {
+               return $this->getContentObject('IMG_RESOURCE')->render($conf);
        }
 
        /**
         * Rendering the cObject, IMGTEXT
         *
-        * @param       array           Array of TypoScript properties
+        * @param       array           array of TypoScript properties
         * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=363&cHash=cf2969bce1
         */
        function IMGTEXT($conf) {
-               $content='';
-               if (is_array($conf['text.']))   {
-                       $content.= $this->stdWrap($this->cObjGet($conf['text.'],'text.'),$conf['text.']);       // this gets the surrounding content
-               }
-               $imgList=trim($this->stdWrap($conf['imgList'],$conf['imgList.']));      // gets images
-               if ($imgList)   {
-                       $imgs = t3lib_div::trimExplode(',',$imgList);
-                       $imgStart = intval($this->stdWrap($conf['imgStart'],$conf['imgStart.']));
+               return $this->getContentObject('IMGTEXT')->render($conf);
+       }
 
-                       $imgCount= count($imgs)-$imgStart;
+       /**
+        * Rendering the cObject, CONTENT
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       function CONTENT($conf) {
+               return $this->getContentObject('CONTENT')->render($conf);
+       }
 
-                       $imgMax = intval($this->stdWrap($conf['imgMax'],$conf['imgMax.']));
-                       if ($imgMax)    {
-                               $imgCount = t3lib_div::intInRange($imgCount,0,$imgMax); // reduces the number of images.
-                       }
+       /**
+        * Rendering the cObject, RECORDS
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       function RECORDS($conf) {
+               return $this->getContentObject('RECORDS')->render($conf);
+       }
 
-                       $imgPath = $this->stdWrap($conf['imgPath'],$conf['imgPath.']);
+       /**
+        * Rendering the cObject, HMENU
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       function HMENU($conf) {
+               return $this->getContentObject('HMENU')->render($conf);
+       }
 
-                               // initialisation
-                       $caption='';
-                       $captionArray = array();
-                       if (!$conf['captionSplit'] && !$conf['imageTextSplit'] && is_array($conf['caption.']))  {
-                               $caption = $this->stdWrap($this->cObjGet($conf['caption.'], 'caption.'),$conf['caption.']);     // global caption, no splitting
-                       }
-                       if ($conf['captionSplit'] && $conf['captionSplit.']['cObject']) {
-                               $legacyCaptionSplit = 1;
-                               $capSplit = $this->stdWrap($conf['captionSplit.']['token'], $conf['captionSplit.']['token.']);
-                               if (!$capSplit) {$capSplit=LF;}
-                               $captionArray = explode($capSplit, $this->cObjGetSingle($conf['captionSplit.']['cObject'], $conf['captionSplit.']['cObject.'], 'captionSplit.cObject'));
-                               foreach ($captionArray as $ca_key => $ca_val) {
-                                       $captionArray[$ca_key] = $this->stdWrap(trim($captionArray[$ca_key]), $conf['captionSplit.']['stdWrap.']);
-                               }
-                       }
+       /**
+        * Rendering the cObject, CTABLE
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       function CTABLE($conf) {
+               return $this->getContentObject('CTABLE')->render($conf);
+       }
 
-                       $tablecode='';
-                       $position=$this->stdWrap($conf['textPos'],$conf['textPos.']);
+       /**
+        * Rendering the cObject, OTABLE
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       function OTABLE($conf) {
+               return $this->getContentObject('OTABLE')->render($conf);
+       }
 
-                       $tmppos = $position&7;
-                       $contentPosition = $position&24;
-                       $align = $this->align[$tmppos];
-                       $cap = ($caption)?1:0;
-                       $txtMarg = intval($this->stdWrap($conf['textMargin'],$conf['textMargin.']));
-                       if (!$conf['textMargin_outOfText'] && $contentPosition<16)      {
-                               $txtMarg=0;
-                       }
+       /**
+        * Rendering the cObject, COLUMNS
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       function COLUMNS($conf) {
+               return $this->getContentObject('COLUMNS')->render($conf);
+       }
 
-                       $cols = intval($this->stdWrap($conf['cols'],$conf['cols.']));
-                       $rows = intval($this->stdWrap($conf['rows'],$conf['rows.']));
-                       $colspacing = intval($this->stdWrap($conf['colSpace'],$conf['colSpace.']));
-                       $rowspacing = intval($this->stdWrap($conf['rowSpace'],$conf['rowSpace.']));
+       /**
+        * Rendering the cObject, HRULER
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       function HRULER($conf) {
+               return $this->getContentObject('HRULER')->render($conf);
+       }
 
-                       $border = intval($this->stdWrap($conf['border'],$conf['border.'])) ? 1:0;
-                       $borderColor = $this->stdWrap($conf['borderCol'],$conf['borderCol.']);
-                       $borderThickness = intval($this->stdWrap($conf['borderThick'],$conf['borderThick.']));
+       /**
+        * Rendering the cObject, CASE
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       function CASEFUNC($conf) {
+               return $this->getContentObject('CASE')->render($conf);
+       }
 
-                       $borderColor=$borderColor?$borderColor:'black';
-                       $borderThickness=$borderThickness?$borderThickness:1;
+       /**
+        * Rendering the cObject, LOAD_REGISTER and RESTORE_REGISTER
+        * NOTICE: This cObject does NOT return any content since it just sets internal data based on the TypoScript properties.
+        *
+        * @param       array           array of TypoScript properties
+        * @param       string          If "RESTORE_REGISTER" then the cObject rendered is "RESTORE_REGISTER", otherwise "LOAD_REGISTER"
+        * @return      string          Empty string (the cObject only sets internal data!)
+        */
+       function LOAD_REGISTER($conf, $name) {
+               if ($name === 'RESTORE_REGISTER') {
+                       return $this->getContentObject('RESTORE_REGISTER')->render($conf);
+               } else {
+                       return $this->getContentObject('LOAD_REGISTER')->render($conf);
+               }
+       }
 
-                       $caption_align = $this->stdWrap($conf['captionAlign'],$conf['captionAlign.']);
-                       if (!$caption_align) {
-                               $caption_align = $align;
-                       }
-                               // generate cols
-                       $colCount = ($cols > 1) ? $cols : 1;
-                       if ($colCount > $imgCount)      {$colCount = $imgCount;}
-                       $rowCount = ($colCount > 1) ? ceil($imgCount / $colCount) : $imgCount;
-                               // generate rows
-                       if ($rows>1)  {
-                               $rowCount = $rows;
-                               if ($rowCount > $imgCount)      {$rowCount = $imgCount;}
-                               $colCount = ($rowCount>1) ? ceil($imgCount / $rowCount) : $imgCount;
-                       }
+       /**
+        * Rendering the cObject, FORM
+        *
+        * @param       array           array of TypoScript properties
+        * @param       array           Alternative formdata overriding whatever comes from TypoScript
+        * @return      string          Output
+        */
+       function FORM($conf, $formData = '') {
+               return $this->getContentObject('FORM')->render($conf);
+       }
 
-                               // max Width
-                       $colRelations = trim($this->stdWrap($conf['colRelations'],$conf['colRelations.']));
-                       $maxW = intval($this->stdWrap($conf['maxW'],$conf['maxW.']));
+       /**
+        * Rendering the cObject, SEARCHRESULT
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       function SEARCHRESULT($conf) {
+               return $this->getContentObject('SEARCHRESULT')->render($conf);
+       }
 
-                       $maxWInText = intval($this->stdWrap($conf['maxWInText'],$conf['maxWInText.']));
-                       if (!$maxWInText)       {       // If maxWInText is not set, it's calculated to the 50 % of the max...
-                               $maxWInText = round($maxW/2);
-                       }
+       /**
+        * Rendering the cObject, PHP_SCRIPT, PHP_SCRIPT_INT and PHP_SCRIPT_EXT
+        *
+        * @param       array           array of TypoScript properties
+        * @param       string          If "INT", then rendering "PHP_SCRIPT_INT"; If "EXT", then rendering "PHP_SCRIPT_EXT"; Default is rendering "PHP_SCRIPT" (cached)
+        * @return      string          Output
+        */
+       function PHP_SCRIPT($conf, $ext = '') {
+               if ($ext === 'INT' || $ext === 'EXT') {
+                       $conf['scriptSuffix'] = $ext;
+                       return $this->getContentObject('PHP_SCRIPT_INT')->render($conf);
+               } else {
+                       return $this->getContentObject('PHP_SCRIPT')->render($conf);
+               }
+       }
 
-                       if ($maxWInText && $contentPosition>=16)        {       // inText
-                               $maxW = $maxWInText;
-                       }
+       /**
+        * Rendering the cObject, TEMPLATE
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        * @see substituteMarkerArrayCached()
+        */
+       function TEMPLATE($conf) {
+               return $this->getContentObject('TEMPLATE')->render($conf);
+       }
 
-                       if ($maxW && $colCount > 0) {   // If there is a max width and if colCount is greater than  column
-/*                             debug($border*$borderThickness*2);
-                               debug($maxW);
-                               debug($colspacing);
-                               debug(($maxW-$colspacing*($colCount-1)-$colCount*$border*$borderThickness*2));
-                               */
-                               $maxW = ceil(($maxW-$colspacing*($colCount-1)-$colCount*$border*$borderThickness*2)/$colCount);
-                       }
-                               // create the relation between rows
-                       $colMaxW = Array();
-                       if ($colRelations)      {
-                               $rel_parts = explode(':',$colRelations);
-                               $rel_total = 0;
-                               for ($a=0;$a<$colCount;$a++)    {
-                                       $rel_parts[$a] = intval($rel_parts[$a]);
-                                       $rel_total+= $rel_parts[$a];
-                               }
-                               if ($rel_total) {
-                                       for ($a=0;$a<$colCount;$a++)    {
-                                               $colMaxW[$a] = round(($maxW*$colCount)/$rel_total*$rel_parts[$a]);
-                                       }
-                                       if (min($colMaxW)<=0 || max($rel_parts)/min($rel_parts)>10)     {               // The difference in size between the largest and smalles must be within a factor of ten.
-                                               $colMaxW = Array();
-                                       }
-                               }
-                       }
-                       $image_compression = intval($this->stdWrap($conf['image_compression'],$conf['image_compression.']));
-                       $image_effects = intval($this->stdWrap($conf['image_effects'],$conf['image_effects.']));
-                       $image_frames = intval($this->stdWrap($conf['image_frames.']['key'],$conf['image_frames.']['key.']));
-
-                               // fetches pictures
-                       $splitArr=array();
-                       $splitArr['imgObjNum']=$conf['imgObjNum'];
-                       $splitArr = $GLOBALS['TSFE']->tmpl->splitConfArray($splitArr,$imgCount);
-
-                               // EqualHeight
-                       $equalHeight = intval($this->stdWrap($conf['equalH'],$conf['equalH.']));
-                       if ($equalHeight)       {       // Initiate gifbuilder object in order to get dimensions AND calculate the imageWidth's
-                               $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
-                               $gifCreator->init();
-                               $relations = Array();
-                               $relations_cols = Array();
-                               $totalMaxW = $maxW*$colCount;
-                               for($a=0;$a<$imgCount;$a++)     {
-                                       $imgKey = $a+$imgStart;
-                                       $imgInfo = $gifCreator->getImageDimensions($imgPath.$imgs[$imgKey]);
-                                       $relations[$a] = $imgInfo[1] / $equalHeight;    // relationship between the original height and the wished height
-                                       if ($relations[$a])     {       // if relations is zero, then the addition of this value is omitted as the image is not expected to display because of some error.
-                                               $relations_cols[floor($a/$colCount)] += $imgInfo[0]/$relations[$a];     // counts the total width of the row with the new height taken into consideration.
-                                       }
-                               }
-                       }
+       /**
+        * Rendering the cObject, FLUIDTEMPLATE
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          the HTML output
+        * @author      Steffen Ritter  <info@steffen-ritter.net>
+        * @author      Benjamin Mack   <benni@typo3.org>
+        */
+       protected function FLUIDTEMPLATE(array $conf) {
+               return $this->getContentObject('FLUIDTEMPLATE')->render($conf);
+       }
 
-                       $imageRowsFinalWidths = Array();        // contains the width of every image row
-                       $imageRowsMaxHeights = Array();
-                       $imgsTag=array();
-                       $origImages=array();
-                       for($a=0;$a<$imgCount;$a++)     {
-                               $GLOBALS['TSFE']->register['IMAGE_NUM'] = $a;
-                               $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $a;
-
-                               $imgKey = $a+$imgStart;
-                               $totalImagePath = $imgPath.$imgs[$imgKey];
-                               $this->data[$this->currentValKey] = $totalImagePath;
-                               $imgObjNum = intval($splitArr[$a]['imgObjNum']);
-                               $imgConf = $conf[$imgObjNum.'.'];
-
-                               if ($equalHeight)       {
-                                       $scale = 1;
-                                       if ($totalMaxW) {
-                                               $rowTotalMaxW = $relations_cols[floor($a/$colCount)];
-                                               if ($rowTotalMaxW > $totalMaxW) {
-                                                       $scale = $rowTotalMaxW / $totalMaxW;
-                                               }
-                                       }
-                                               // transfer info to the imageObject. Please note, that
-                                       $imgConf['file.']['height'] = round($equalHeight/$scale);
-
-                                       unset($imgConf['file.']['width']);
-                                       unset($imgConf['file.']['maxW']);
-                                       unset($imgConf['file.']['maxH']);
-                                       unset($imgConf['file.']['minW']);
-                                       unset($imgConf['file.']['minH']);
-                                       unset($imgConf['file.']['width.']);
-                                       unset($imgConf['file.']['maxW.']);
-                                       unset($imgConf['file.']['maxH.']);
-                                       unset($imgConf['file.']['minW.']);
-                                       unset($imgConf['file.']['minH.']);
-                                       $maxW = 0;      // setting this to zero, so that it doesn't disturb
-                               }
+               /**
+        * Rendering the cObject, MULTIMEDIA
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       function MULTIMEDIA($conf) {
+               return $this->getContentObject('MULTIMEDIA')->render($conf);
+       }
 
-                               if ($maxW) {
-                                       if (count($colMaxW))    {
-                                               $imgConf['file.']['maxW'] = $colMaxW[($a%$colCount)];
-                                       } else {
-                                               $imgConf['file.']['maxW'] = $maxW;
-                                       }
-                               }
-
-                                       // Image Object supplied:
-                               if (is_array($imgConf)) {
-                                       if ($this->image_effects[$image_effects])       {
-                                               $imgConf['file.']['params'].= ' '.$this->image_effects[$image_effects];
-                                       }
-                                       if ($image_frames)      {
-                                               if (is_array($conf['image_frames.'][$image_frames.'.']))        {
-                                                       $imgConf['file.']['m.'] = $conf['image_frames.'][$image_frames.'.'];
-                                               }
-                                       }
-                                       if ($image_compression && $imgConf['file']!='GIFBUILDER')       {
-                                               if ($image_compression==1)      {
-                                                       $tempImport = $imgConf['file.']['import'];
-                                                       $tempImport_dot = $imgConf['file.']['import.'];
-                                                       unset($imgConf['file.']);
-                                                       $imgConf['file.']['import'] = $tempImport;
-                                                       $imgConf['file.']['import.'] = $tempImport_dot;
-                                               } elseif (isset($this->image_compression[$image_compression])) {
-                                                       $imgConf['file.']['params'].= ' '.$this->image_compression[$image_compression]['params'];
-                                                       $imgConf['file.']['ext'] = $this->image_compression[$image_compression]['ext'];
-                                                       unset($imgConf['file.']['ext.']);
-                                               }
-                                       }
-
-                                               // "alt", "title" and "longdesc" attributes:
-                                       if (!strlen($imgConf['altText']) && !is_array($imgConf['altText.'])) {
-                                               $imgConf['altText'] = $conf['altText'];
-                                               $imgConf['altText.'] = $conf['altText.'];
-                                       }
-                                       if (!strlen($imgConf['titleText']) && !is_array($imgConf['titleText.'])) {
-                                               $imgConf['titleText'] = $conf['titleText'];
-                                               $imgConf['titleText.'] = $conf['titleText.'];
-                                       }
-                                       if (!strlen($imgConf['longdescURL']) && !is_array($imgConf['longdescURL.'])) {
-                                               $imgConf['longdescURL'] = $conf['longdescURL'];
-                                               $imgConf['longdescURL.'] = $conf['longdescURL.'];
-                                       }
-                               } else {
-                                       $imgConf = array(
-                                               'altText' => $conf['altText'],
-                                               'titleText' => $conf['titleText'],
-                                               'longdescURL' => $conf['longdescURL'],
-                                               'file' => $totalImagePath
-                                       );
-                               }
-
-                               $imgsTag[$imgKey] = $this->IMAGE($imgConf);
-
-                                       // Store the original filepath
-                               $origImages[$imgKey]=$GLOBALS['TSFE']->lastImageInfo;
+       /**
+        * Rendering the cObject, MEDIA
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       public function MEDIA($conf) {
+               return $this->getContentObject('MEDIA')->render($conf);
+       }
 
-                               $imageRowsFinalWidths[floor($a/$colCount)] += $GLOBALS['TSFE']->lastImageInfo[0];
-                               if ($GLOBALS['TSFE']->lastImageInfo[1]>$imageRowsMaxHeights[floor($a/$colCount)])       {
-                                       $imageRowsMaxHeights[floor($a/$colCount)] = $GLOBALS['TSFE']->lastImageInfo[1];
-                               }
-                       }
-                               // calculating the tableWidth:
-                               // TableWidth problems: It creates problems if the pictures are NOT as wide as the tableWidth.
-                       $tableWidth = max($imageRowsFinalWidths)+ $colspacing*($colCount-1) + $colCount*$border*$borderThickness*2;
+       /**
+        * Rendering the cObject, SWFOBJECT
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       public function SWFOBJECT($conf) {
+               return $this->getContentObject('SWFOBJECT')->render($conf);
+       }
 
-                               // make table for pictures
-                       $index=$imgStart;
+       /**
+        * Rendering the cObject, QTOBJECT
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       public function QTOBJECT($conf) {
+               return $this->getContentObject('QTOBJECT')->render($conf);
+       }
 
-                       $noRows = $this->stdWrap($conf['noRows'],$conf['noRows.']);
-                       $noCols = $this->stdWrap($conf['noCols'],$conf['noCols.']);
-                       if ($noRows) {$noCols=0;}       // noRows overrides noCols. They cannot exist at the same time.
-                       if ($equalHeight) {
-                               $noCols=1;
-                               $noRows=0;
-                       }
+       /**
+        * Rendering the cObject, SVG
+        *
+        * @param       array           array of TypoScript properties
+        * @return      string          Output
+        */
+       public function SVG($conf) {
+               return $this->getContentObject('SVG')->render($conf);
+       }
 
-                       $rowCount_temp=1;
-                       $colCount_temp=$colCount;
-                       if ($noRows)    {
-                               $rowCount_temp = $rowCount;
-                               $rowCount=1;
-                       }
-                       if ($noCols)    {
-                               $colCount=1;
-                       }
-                               // col- and rowspans calculated
-                       $colspan = (($colspacing) ? $colCount*2-1 : $colCount);
-                       $rowspan = (($rowspacing) ? $rowCount*2-1 : $rowCount) + $cap;
+       /************************************
+        *
+        * Various helper functions for content objects:
+        *
+        ************************************/
 
 
-                               // Edit icons:
-                       $editIconsHTML = $conf['editIcons']&&$GLOBALS['TSFE']->beUserLogin ? $this->editIcons('',$conf['editIcons'],$conf['editIcons.']) : '';
+       /**
+        * Converts a given config in Flexform to a conf-array
+        * @param       string          Flexform data
+        * @param       array           array to write the data into, by reference
+        * @param       boolean         is set if called recursive. Don't call function with this parameter, it's used inside the function only
+        * @access      public
+        *
+        */
+       public function readFlexformIntoConf($flexData, &$conf, $recursive = FALSE) {
+               if ($recursive === FALSE) {
+                       $flexData = t3lib_div::xml2array($flexData, 'T3');
+               }
 
-                               // strech out table:
-                       $tablecode='';
-                       $flag=0;
-                       if ($conf['noStretchAndMarginCells']!=1)        {
-                               $tablecode.='<tr>';
-                               if ($txtMarg && $align=='right')        {       // If right aligned, the textborder is added on the right side
-                                       $tablecode.='<td rowspan="'.($rowspan+1).'" valign="top"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$txtMarg.'" height="1" alt="" title="" />'.($editIconsHTML?'<br />'.$editIconsHTML:'').'</td>';
-                                       $editIconsHTML='';
-                                       $flag=1;
-                               }
-                               $tablecode.='<td colspan="'.$colspan.'"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$tableWidth.'" height="1" alt="" /></td>';
-                               if ($txtMarg && $align=='left') {       // If left aligned, the textborder is added on the left side
-                                       $tablecode.='<td rowspan="'.($rowspan+1).'" valign="top"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$txtMarg.'" height="1" alt="" title="" />'.($editIconsHTML?'<br />'.$editIconsHTML:'').'</td>';
-                                       $editIconsHTML='';
-                                       $flag=1;
-                               }
-                               if ($flag) $tableWidth+=$txtMarg+1;
-       //                      $tableWidth=0;
-                               $tablecode.='</tr>';
+               if (is_array($flexData)) {
+                       if (isset($flexData['data']['sDEF']['lDEF'])) {
+                               $flexData = $flexData['data']['sDEF']['lDEF'];
                        }
 
-                               // draw table
-                       for ($c=0;$c<$rowCount;$c++) {  // Looping through rows. If 'noRows' is set, this is '1 time', but $rowCount_temp will hold the actual number of rows!
-                               if ($c && $rowspacing)  {               // If this is NOT the first time in the loop AND if space is required, a row-spacer is added. In case of "noRows" rowspacing is done further down.
-                                       $tablecode.='<tr><td colspan="'.$colspan.'"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="1" height="'.$rowspacing.'"'.$this->getBorderAttr(' border="0"').' alt="" title="" /></td></tr>';
-                               }
-                               $tablecode.='<tr>';     // starting row
-                               for ($b=0; $b<$colCount_temp; $b++)     {       // Looping through the columns
-                                       if ($b && $colspacing)  {               // If this is NOT the first iteration AND if column space is required. In case of "noCols", the space is done without a separate cell.
-                                               if (!$noCols)   {
-                                                       $tablecode.='<td><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$colspacing.'" height="1"'.$this->getBorderAttr(' border="0"').' alt="" title="" /></td>';
+                       foreach ($flexData as $key => $value) {
+                               if (is_array($value['el']) && count($value['el']) > 0) {
+                                       foreach ($value['el'] as $ekey => $element) {
+                                               if (isset($element['vDEF'])) {
+                                                       $conf[$ekey] = $element['vDEF'];
                                                } else {
-                                                       $colSpacer='<img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.($border?$colspacing-6:$colspacing).'" height="'.($imageRowsMaxHeights[$c]+($border?$borderThickness*2:0)).'"'.$this->getBorderAttr(' border="0"').' align="'.($border?'left':'top').'" alt="" title="" />';
-                                                       $colSpacer='<td valign="top">'.$colSpacer.'</td>';      // added 160301, needed for the new "noCols"-table...
-                                                       $tablecode.=$colSpacer;
-                                               }
-                                       }
-                                       if (!$noCols || ($noCols && !$b))       {
-                                               $tablecode.='<td valign="top">';        // starting the cell. If "noCols" this cell will hold all images in the row, otherwise only a single image.
-                                               if ($noCols)    {$tablecode.='<table width="'.$imageRowsFinalWidths[$c].'" border="0" cellpadding="0" cellspacing="0"><tr>';}           // In case of "noCols" we must set the table-tag that surrounds the images in the row.
-                                       }
-                                       for ($a=0;$a<$rowCount_temp;$a++)       {       // Looping through the rows IF "noRows" is set. "noRows"  means that the rows of images is not rendered by physical table rows but images are all in one column and spaced apart with clear-gifs. This loop is only one time if "noRows" is not set.
-                                               $GLOBALS['TSFE']->register['IMAGE_NUM'] = $imgIndex;    // register previous imgIndex
-                                               $imgIndex = $index+$a*$colCount_temp;
-                                               $GLOBALS['TSFE']->register['IMAGE_NUM_CURRENT'] = $imgIndex;
-                                               if ($imgsTag[$imgIndex])        {
-                                                       if ($rowspacing && $noRows && $a) {             // Puts distance between the images IF "noRows" is set and this is the first iteration of the loop
-                                                               $tablecode.= '<img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="1" height="'.$rowspacing.'" alt="" title="" /><br />';
-                                                       }
-                                                       if ($legacyCaptionSplit)        {
-                                                               $thisCaption = $captionArray[$imgIndex];
-                                                       } else if ($conf['captionSplit'] || $conf['imageTextSplit'])    {
-                                                               $thisCaption = $this->stdWrap($this->cObjGet($conf['caption.'], 'caption.'), $conf['caption.']);
+                                                       if (is_array($element)) {
+                                                               $this->readFlexformIntoConf($element, $conf[$key][key($element)][$ekey], TRUE);
+                                                       } else {
+                                                               $this->readFlexformIntoConf($element, $conf[$key][$ekey], TRUE);
                                                        }
-                                                       $imageHTML = $imgsTag[$imgIndex].'<br />';
-                                                       $Talign = (!trim($thisCaption) && !$noRows) ? ' align="left"' : '';  // this is necessary if the tablerows are supposed to space properly together! "noRows" is excluded because else the images "layer" together.
-                                                       if ($border)    {$imageHTML='<table border="0" cellpadding="'.$borderThickness.'" cellspacing="0" bgcolor="'.$borderColor.'"'.$Talign.'><tr><td>'.$imageHTML.'</td></tr></table>';}
-                                                       $imageHTML.=$editIconsHTML;
-                                                       $editIconsHTML='';
-                                                       $imageHTML.=$thisCaption;       // Adds caption.
-                                                       if ($noCols)    {$imageHTML='<td valign="top">'.$imageHTML.'</td>';}            // If noCols, put in table cell.
-                                                       $tablecode.=$imageHTML;
                                                }
                                        }
-                                       $index++;
-                                       if (!$noCols || ($noCols && $b+1==$colCount_temp))      {
-                                               if ($noCols)    {$tablecode.='</tr></table>';}  // In case of "noCols" we must finish the table that surrounds the images in the row.
-                                               $tablecode.='</td>';    // Ending the cell. In case of "noCols" the cell holds all pictures!
-                                       }
-                               }
-                               $tablecode.='</tr>';    // ending row
-                       }
-                       if ($c) {
-                               switch ($contentPosition)       {
-                                       case '0':       // above
-                                       case '8':       // below
-                                               switch ($align)        {        // These settings are needed for Firefox
-                                                       case 'center':
-                                                               $table_align = 'margin-left: auto; margin-right: auto';
-                                                       break;
-                                                       case 'right':
-                                                               $table_align = 'margin-left: auto; margin-right: 0px';
-                                                       break;
-                                                       default:        // Most of all: left
-                                                               $table_align = 'margin-left: 0px; margin-right: auto';
-                                               }
-                                               $table_align = 'style="'.$table_align.'"';
-                                       break;
-                                       case '16':      // in text
-                                               $table_align = 'align="'.$align.'"';
-                                       break;
-                                       default:
-                                               $table_align = '';
-                               }
-
-                                       // Table-tag is inserted
-                               $tablecode = '<table'.($tableWidth?' width="'.$tableWidth.'"':'').' border="0" cellspacing="0" cellpadding="0" '.$table_align.' class="imgtext-table">'.$tablecode;
-                               if ($editIconsHTML)     {       // IF this value is not long since reset.
-                                       $tablecode.='<tr><td colspan="'.$colspan.'">'.$editIconsHTML.'</td></tr>';
-                                       $editIconsHTML='';
+                               } else {
+                                       $this->readFlexformIntoConf($value['el'], $conf[$key], TRUE);
                                }
-                               if ($cap)       {
-                                       $tablecode.='<tr><td colspan="'.$colspan.'" align="'.$caption_align.'">'.$caption.'</td></tr>';
+                               if ($value['vDEF']) {
+                                       $conf[$key] = $value['vDEF'];
                                }
-                               $tablecode.='</table>';
-                               if ($conf['tableStdWrap.'])     {$tablecode=$this->stdWrap($tablecode,$conf['tableStdWrap.']);}
-                       }
-
-                       $spaceBelowAbove = intval($this->stdWrap($conf['spaceBelowAbove'],$conf['spaceBelowAbove.']));
-                       switch ($contentPosition)       {
-                               case '0':       // above
-                                       $output= '<div style="text-align:'.$align.';">'.$tablecode.'</div>'.$this->wrapSpace($content, $spaceBelowAbove.'|0');
-                               break;
-                               case '8':       // below
-                                       $output= $this->wrapSpace($content, '0|'.$spaceBelowAbove).'<div style="text-align:'.$align.';">'.$tablecode.'</div>';
-                               break;
-                               case '16':      // in text
-                                       $output= $tablecode.$content;
-                               break;
-                               case '24':      // in text, no wrap
-                                       $theResult = '';
-                                       $theResult.= '<table border="0" cellspacing="0" cellpadding="0" class="imgtext-nowrap"><tr>';
-                                       if ($align=='right')    {
-                                               $theResult.= '<td valign="top">'.$content.'</td><td valign="top">'.$tablecode.'</td>';
-                                       } else {
-                                               $theResult.= '<td valign="top">'.$tablecode.'</td><td valign="top">'.$content.'</td>';
-                                       }
-                                       $theResult.= '</tr></table>';
-                                       $output= $theResult;
-                               break;
                        }
-               } else {
-                       $output= $content;
                }
+       }
 
-               if ($conf['stdWrap.']) {
-                       $output = $this->stdWrap($output, $conf['stdWrap.']);
-               }
 
-               return $output;
+       /**
+        * Returns all parents of the given PID (Page UID) list
+        *
+        * @param       string          A list of page Content-Element PIDs (Page UIDs) / stdWrap
+        * @param       array           stdWrap array for the list
+        * @return      string          A list of PIDs
+        * @access private
+        */
+       function getSlidePids($pidList, $pidConf) {
+               $pidList = isset($pidConf)
+                       ? trim($this->stdWrap($pidList, $pidConf))
+                       : trim($pidList);
+               if (!strcmp($pidList, '')) {
+                       $pidList = 'this';
+               }
+               if (trim($pidList)) {
+                       $listArr = t3lib_div::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $pidList));
+                       $listArr = $this->checkPidArray($listArr);
+               }
+               $pidList = array();
+               if (is_array($listArr) && count($listArr)) {
+                       foreach ($listArr as $uid) {
+                               $page = $GLOBALS['TSFE']->sys_page->getPage($uid);
+                               if (!$page['is_siteroot']) {
+                                       $pidList[] = $page['pid'];
+                               }
+                       }
+               }
+               return implode(',', $pidList);
        }
 
        /**
-        * Rendering the cObject, CONTENT
+        * Returns a default value for a form field in the FORM cObject.
+        * Page CANNOT be cached because that would include the inserted value for the current user.
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=356&cHash=9f3b5c6ba2
+        * @param       boolean         If noValueInsert OR if the no_cache flag for this page is NOT set, the original default value is returned.
+        * @param       string          $fieldName: The POST var name to get default value for
+        * @param       string          $defaultVal: The current default value
+        * @return      string          The default value, either from INPUT var or the current default, based on whether caching is enabled or not.
+        * @access private
         */
-       function CONTENT($conf) {
-               $theValue='';
-
-               $originalRec = $GLOBALS['TSFE']->currentRecord;
-               if ($originalRec)       {               // If the currentRecord is set, we register, that this record has invoked this function. It's should not be allowed to do this again then!!
-                       $GLOBALS['TSFE']->recordRegister[$originalRec]++;
+       function getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal) {
+               if (!$GLOBALS['TSFE']->no_cache || (!isset($_POST[$fieldName]) && !isset($_GET[$fieldName])) || $noValueInsert) {
+                       return $defaultVal;
+               } else {
+                       return t3lib_div::_GP($fieldName);
                }
+       }
 
-               $conf['table'] = trim($this->stdWrap($conf['table'], $conf['table.']));
-               if ($conf['table']=='pages' || substr($conf['table'],0,3)=='tt_' || substr($conf['table'],0,3)=='fe_' || substr($conf['table'],0,3)=='tx_' || substr($conf['table'],0,4)=='ttx_' || substr($conf['table'],0,5)=='user_' || substr($conf['table'],0,7)=='static_')       {
-
-                       $renderObjName = $conf['renderObj'] ? $conf['renderObj'] : '<'.$conf['table'];
-                       $renderObjKey = $conf['renderObj'] ? 'renderObj' : '';
-                       $renderObjConf = $conf['renderObj.'];
-
-                       $slide = intval($conf['slide'])?intval($conf['slide']):0;
-                       $slideCollect = intval($conf['slide.']['collect'])?intval($conf['slide.']['collect']):0;
-                       $slideCollectReverse = intval($conf['slide.']['collectReverse'])?true:false;
-                       $slideCollectFuzzy = $slideCollect?(intval($conf['slide.']['collectFuzzy'])?true:false):true;
-                       $again = false;
+       /**
+        * Returns a <img> tag with the image file defined by $file and processed according to the properties in the TypoScript array.
+        * Mostly this function is a sub-function to the IMAGE function which renders the IMAGE cObject in TypoScript.
+        * This function is called by "$this->cImage($conf['file'],$conf);" from IMAGE().
+        *
+        * @param       string          File TypoScript resource
+        * @param       array           TypoScript configuration properties
+        * @return      string          <img> tag, (possibly wrapped in links and other HTML) if any image found.
+        * @access private
+        * @see IMAGE()
+        */
+       function cImage($file, $conf) {
+               $info = $this->getImgResource($file, $conf['file.']);
+               $GLOBALS['TSFE']->lastImageInfo = $info;
+               if (is_array($info)) {
+                       $info[3] = t3lib_div::png_to_gif_by_imagemagick($info[3]);
+                       $GLOBALS['TSFE']->imagesOnPage[] = $info[3]; // This array is used to collect the image-refs on the page...
 
-                       do {
-                               $res = $this->exec_getQuery($conf['table'],$conf['select.']);
-                               if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
-                                       $GLOBALS['TT']->setTSlogMessage($error,3);
-                               } else {
-                                       $this->currentRecordTotal = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
-                                       $GLOBALS['TT']->setTSlogMessage('NUMROWS: '.$GLOBALS['TYPO3_DB']->sql_num_rows($res));
-                                       $cObj =t3lib_div::makeInstance('tslib_cObj');
-                                       $cObj->setParent($this->data,$this->currentRecord);
-                                       $this->currentRecordNumber=0;
-                                       $cobjValue = '';
-                                       while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
-
-                                                       // Versioning preview:
-                                               $GLOBALS['TSFE']->sys_page->versionOL($conf['table'],$row,TRUE);
-
-                                                       // Language overlay:
-                                               if (is_array($row) && $GLOBALS['TSFE']->sys_language_contentOL) {
-                                                       $row = $GLOBALS['TSFE']->sys_page->getRecordOverlay($conf['table'],$row,$GLOBALS['TSFE']->sys_language_content,$GLOBALS['TSFE']->sys_language_contentOL);
-                                               }
 
-                                               if (is_array($row)) { // Might be unset in the sys_language_contentOL
-                                                       if (!$GLOBALS['TSFE']->recordRegister[$conf['table'].':'.$row['uid']]) {
-                                                               $this->currentRecordNumber++;
-                                                               $cObj->parentRecordNumber = $this->currentRecordNumber;
-                                                               $GLOBALS['TSFE']->currentRecord = $conf['table'].':'.$row['uid'];
-                                                               $this->lastChanged($row['tstamp']);
-                                                               $cObj->start($row,$conf['table']);
-                                                               $tmpValue = $cObj->cObjGetSingle($renderObjName, $renderObjConf, $renderObjKey);
-                                                               $cobjValue .= $tmpValue;
-                                                       }
-                                               }
-                                       }
-                                       $GLOBALS['TYPO3_DB']->sql_free_result($res);
-                               }
-                               if ($slideCollectReverse) {
-                                       $theValue = $cobjValue.$theValue;
-                               } else {
-                                       $theValue .= $cobjValue;
-                               }
-                               if ($slideCollect>0) {
-                                       $slideCollect--;
-                               }
-                               if ($slide) {
-                                       if ($slide>0) {
-                                               $slide--;
-                                       }
-                                       $conf['select.']['pidInList'] = $this->getSlidePids($conf['select.']['pidInList'], $conf['select.']['pidInList.']);
-                                       $again = strlen($conf['select.']['pidInList'])?true:false;
+                               // Backwards compatibility if altText is not set and alttext is set
+                               // @deprecated since TYPO3 4.3, will be removed in TYPO3 4.6
+                       if (strlen($conf['alttext']) || is_array($conf['alttext.'])) {
+                               $GLOBALS['TSFE']->logDeprecatedTyposcript(
+                                       'IMAGE.alttext',
+                                       'use IMAGE.altText instead - src: ' . $info[3] . ' - original image: ' . $info['origFile']
+                               );
+                               if (!strlen($conf['altText']) && !is_array($conf['altText.'])) {
+                                       $conf['altText'] = $conf['alttext'];
+                                       $conf['altText.'] = $conf['alttext.'];
                                }
-                       } while ($again&&(($slide&&!strlen($tmpValue)&&$slideCollectFuzzy)||($slide&&$slideCollect)));
-               }
+                       }
 
-               $theValue = $this->wrap($theValue,$conf['wrap']);
-               if ($conf['stdWrap.']) $theValue = $this->stdWrap($theValue,$conf['stdWrap.']);
+                       $altParam = $this->getAltParam($conf);
+                       if($conf['params'] && !isset($conf['params.'])) {
+                               $params = ' ' . $conf['params'];
+                       } else {
+                               $params = isset($conf['params.'])
+                                       ? ' ' . $this->stdWrap($conf['params'], $conf['params.'])
+                                       : '';
+                       }
+                       $theValue = '<img src="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix .
+                               t3lib_div::rawUrlEncodeFP($info[3])) . '" width="' . $info[0] . '" height="' . $info[1] . '"' .
+                               $this->getBorderAttr(' border="' . intval($conf['border']) . '"') .
+                               $params .
+                               ($altParam) . ' />';
+                       $linkWrap = isset($conf['linkWrap.'])
+                               ? $this->stdWrap($conf['linkWrap'], $conf['linkWrap.'])
+                               : $conf['linkWrap'];
+                       if ($linkWrap) {
+                               $theValue = $this->linkWrap($theValue, $linkWrap);
+                       } elseif ($conf['imageLinkWrap']) {
+                               $theValue = $this->imageLinkWrap($theValue, $info['origFile'], $conf['imageLinkWrap.']);
+                       }
+                       $wrap = isset($conf['wrap.'])
+                               ? $this->stdWrap($conf['wrap'], $conf['wrap.'])
+                               : $conf['wrap'];
+                       if($wrap) {
+                               $theValue = $this->wrap($theValue, $conf['wrap']);
+                       }
+                       return $theValue;
+               }
+       }
 
-               $GLOBALS['TSFE']->currentRecord = $originalRec; // Restore
-               return $theValue;
+       /**
+        * Returns the 'border' attribute for an <img> tag only if the doctype is not xhtml_strict, xhtml_11, xhtml_2 or html5
+        * or if the config parameter 'disableImgBorderAttr' is not set.
+        *
+        * @param       string          the border attribute
+        * @return      string          the border attribute
+        */
+       function getBorderAttr($borderAttr) {
+               if (! t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype) &&
+                               $GLOBALS['TSFE']->config['config']['doctype'] != 'html5' &&
+                               ! $GLOBALS['TSFE']->config['config']['disableImgBorderAttr']) {
+                       return $borderAttr;
+               }
        }
 
        /**
-        * Rendering the cObject, RECORDS
+        * Wraps the input string in link-tags that opens the image in a new window.
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=357&cHash=303e959472
+        * @param       string          String to wrap, probably an <img> tag
+        * @param       string          The original image file
+        * @param       array           TypoScript properties for the "imageLinkWrap" function
+        * @return      string          The input string, $string, wrapped as configured.
+        * @see cImage()
         */
-       function RECORDS($conf) {
-               $theValue='';
+       function imageLinkWrap($string, $imageFile, $conf) {
+               $a1 = '';
+               $a2 = '';
+               $content = $string;
+               $enable = isset($conf['enable.'])
+                       ? $this->stdWrap($conf['enable'], $conf['enable.'])
+                       : $conf['enable'];
+               if ($enable) {
+                       $content = $this->typolink($string, $conf['typolink.']);
+                       if(isset($conf['file.'])) {
+                               $imageFile = $this->stdWrap($imageFile, $conf['file.']);
+                       }
 
-               $originalRec = $GLOBALS['TSFE']->currentRecord;
-               if ($originalRec)       {               // If the currentRecord is set, we register, that this record has invoked this function. It's should not be allowed to do this again then!!
-                       $GLOBALS['TSFE']->recordRegister[$originalRec]++;
-               }
+                               // imageFileLink:
+                       if ($content == $string && @is_file($imageFile)) {
+                               $parameterNames = array('width', 'height', 'effects', 'alternativeTempPath', 'bodyTag', 'title', 'wrap');
+                               $parameters = array();
 
-               $conf['source'] = $this->stdWrap($conf['source'],$conf['source.']);
-               if ($conf['tables'] && $conf['source']) {
-                       $allowedTables = $conf['tables'];
-                       if (is_array($conf['conf.']))   {
-                               foreach ($conf['conf.'] as $k => $v) {
-                                       if (substr($k,-1)!='.')         $allowedTables.=','.$k;
+                               $sample = isset($conf['sample.'])
+                                       ? $this->stdWrap($conf['sample'], $conf['sample.'])
+                                       : $conf['sample'];
+                               if ($sample) {
+                                       $parameters['sample'] = 1;
                                }
-                       }
 
-                       $loadDB = t3lib_div::makeInstance('FE_loadDBGroup');
-                       $loadDB->start($conf['source'], $allowedTables);
-                       foreach ($loadDB->tableArray as $table => $v) {
-                               if (is_array($GLOBALS['TCA'][$table]))  {
-                                       $loadDB->additionalWhere[$table]=$this->enableFields($table);
+                               foreach ($parameterNames as $parameterName) {
+                                       if(isset($conf[$parameterName.'.'])) {
+                                               $conf[$parameterName] = $this->stdWrap($conf[$parameterName], $conf[$parameterName.'.']);
+                                       }
+                                       if (isset($conf[$parameterName]) && $conf[$parameterName]) {
+                                               $parameters[$parameterName] = $conf[$parameterName];
+                                       }
                                }
-                       }
-                       $loadDB->getFromDB();
 
-                       reset($loadDB->itemArray);
-                       $data = $loadDB->results;
+                               $parametersEncoded = base64_encode(serialize($parameters));
+
+                               $md5_value = t3lib_div::hmac(
+                                       implode(
+                                               '|',
+                                               array($imageFile, $parametersEncoded)
+                                       )
+                               );
 
-                       $cObj =t3lib_div::makeInstance('tslib_cObj');
-                       $cObj->setParent($this->data,$this->currentRecord);
-                       $this->currentRecordNumber=0;
-                       $this->currentRecordTotal = count($loadDB->itemArray);
-                       foreach ($loadDB->itemArray as $val) {
-                               $row = $data[$val['table']][$val['id']];
+                               $params = '&md5=' . $md5_value;
+                               foreach (str_split($parametersEncoded, 64) as $index => $chunk) {
+                                       $params .= '&parameters[' . $index . ']=' . rawurlencode($chunk);
+                               }
 
-                                       // Versioning preview:
-                               $GLOBALS['TSFE']->sys_page->versionOL($val['table'],$row);
+                               $url = $GLOBALS['TSFE']->absRefPrefix . 'index.php?eID=tx_cms_showpic&file=' . rawurlencode($imageFile) . $params;
 
-                                       // Language overlay:
-                               if (is_array($row) && $GLOBALS['TSFE']->sys_language_contentOL) {
-                                       $row = $GLOBALS['TSFE']->sys_page->getRecordOverlay($val['table'],$row,$GLOBALS['TSFE']->sys_language_content,$GLOBALS['TSFE']->sys_language_contentOL);
+                               $directImageLink = isset($conf['directImageLink.'])
+                                       ? $this->stdWrap($conf['directImageLink'], $conf['directImageLink.'])
+                                       : $conf['directImageLink'];
+                               if ($directImageLink) {
+                                       $imgResourceConf = array(
+                                               'file' => $imageFile,
+                                               'file.' => $conf
+                                       );
+                                       $url = $this->IMG_RESOURCE($imgResourceConf);
+                                       if (!$url) {
+                                                       // if no imagemagick / gm is available
+                                               $url = $imageFile;
+                                       }
                                }
 
-                               if (is_array($row))     {       // Might be unset in the content overlay things...
-                                       if (!$conf['dontCheckPid'])     {
-                                               $row = $this->checkPid($row['pid']) ? $row : '';
+                                       // Create TARGET-attribute only if the right doctype is used
+                               if (!t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype)) {
+                                       $target = isset($conf['target.'])
+                                               ? $this-stdWrap($conf['target'], $conf['target.'])
+                                               : $conf['target'];
+                                       if(!$target) {
+                                               $target = sprintf(' target="%s"', $target);
+                                       } else {
+                                               $target = ' target="thePicture"';
                                        }
-                                       if ($row && !$GLOBALS['TSFE']->recordRegister[$val['table'].':'.$val['id']])    {
-                                               $renderObjName = $conf['conf.'][$val['table']] ? $conf['conf.'][$val['table']] : '<'.$val['table'];
-                                               $renderObjKey = $conf['conf.'][$val['table']] ? 'conf.'.$val['table'] : '';
-                                               $renderObjConf = $conf['conf.'][$val['table'].'.'];
-                                               $this->currentRecordNumber++;
-                                               $cObj->parentRecordNumber=$this->currentRecordNumber;
-                                               $GLOBALS['TSFE']->currentRecord = $val['table'].':'.$val['id'];
-                                               $this->lastChanged($row['tstamp']);
-                                               $cObj->start($row,$val['table']);
-                                               $tmpValue = $cObj->cObjGetSingle($renderObjName, $renderObjConf, $renderObjKey);
-                                               $theValue .= $tmpValue;
-                                       }# else debug($GLOBALS['TSFE']->recordRegister,'RECORDS');
+                               } else {
+                                       $target = '';
                                }
-                       }
-               }
-               if ($conf['wrap'])      $theValue = $this->wrap($theValue,$conf['wrap']);
-               if ($conf['stdWrap.'])  $theValue = $this->stdWrap($theValue,$conf['stdWrap.']);
+                               $conf['JSwindow'] = isset($conf['JSwindow.'])
+                                       ? $this->stdWrap($conf['JSwindow'], $conf['JSwindow.'])
+                                       : $conf['JSwindow'];
+                               if ($conf['JSwindow']) {
+                                       if ($conf['JSwindow.']['altUrl'] || $conf['JSwindow.']['altUrl.']) {
+                                               $altUrl = isset($conf['JSwindow.']['altUrl.'])
+                                                       ? $this->stdWrap($conf['JSwindow.']['altUrl'], $conf['JSwindow.']['altUrl.'])
+                                                       : $conf['JSwindow.']['altUrl'];
+                                               if ($altUrl) {
+                                                       $url = $altUrl .
+                                                               ($conf['JSwindow.']['altUrl_noDefaultParams'] ? '' : '?file=' .
+                                                               rawurlencode($imageFile) . $params);
+                                               }
+                                       }
+                                       $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
+                                       $gifCreator->init();
+                                       $gifCreator->mayScaleUp = 0;
 
-               $GLOBALS['TSFE']->currentRecord = $originalRec; // Restore
-               return $theValue;
-       }
+                                       $dims = $gifCreator->getImageScale($gifCreator->getImageDimensions($imageFile), $conf['width'], $conf['height'], '');
+                                       $JSwindowExpand = isset($conf['JSwindow.']['expand.'])
+                                               ? $this->stdWrap($conf['JSwindow.']['expand'], $conf['JSwindow.']['expand.'])
+                                               : $conf['JSwindow.']['expand'];
+                                       $offset = t3lib_div::intExplode(',', $JSwindowExpand . ',');
+
+                                       $newWindow = isset($conf['JSwindow.']['newWindow.'])
+                                               ? $this->stdWrap($conf['JSwindow.']['newWindow'], $conf['JSwindow.']['newWindow.'])
+                                               : $conf['JSwindow.']['newWindow'];
+                                       $a1 = '<a href="' . htmlspecialchars($url) . '" onclick="' .
+                                               htmlspecialchars('openPic(\'' . $GLOBALS['TSFE']->baseUrlWrap($url) . '\',\'' .
+                                               ($newWindow ? md5($url) : 'thePicture') . '\',\'width=' .
+                                               ($dims[0] + $offset[0]) . ',height=' . ($dims[1] + $offset[1]) .
+                                               ',status=0,menubar=0\'); return false;') . '"' .
+                                               $target . $GLOBALS['TSFE']->ATagParams . '>';
+                                       $a2 = '</a>';
+                                       $GLOBALS['TSFE']->setJS('openPic');
+                               } else {
+                                       $conf['linkParams.']['parameter'] = $url;
+                                       $string = $this->typoLink($string, $conf['linkParams.']);
+                               }
 
-       /**
-        * Rendering the cObject, HMENU
-        *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=358&cHash=5400c1c06a
-        */
-       function HMENU($conf)   {
-               $content='';
-               if ($this->checkIf($conf['if.']))       {
-                       $cls = strtolower($conf[1]);
-                       if (t3lib_div::inList($GLOBALS['TSFE']->tmpl->menuclasses,$cls))        {
-                               if ($conf['special.']['value.'])        {
-                                       $conf['special.']['value']  = $this->stdWrap($conf['special.']['value'], $conf['special.']['value.']);
+                               if(isset($conf['stdWrap.'])) {
+                                       $string = $this->stdWrap($string, $conf['stdWrap.']);
                                }
-                               $GLOBALS['TSFE']->register['count_HMENU']++;
-                               $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']=0;
-                               $GLOBALS['TSFE']->applicationData['GMENU_LAYERS']['WMid']=array();
-                               $GLOBALS['TSFE']->applicationData['GMENU_LAYERS']['WMparentId']=array();
 
-                               $menu = t3lib_div::makeInstance('tslib_'.$cls);
-                               $menu->parent_cObj = $this;
-                               $menu->start($GLOBALS['TSFE']->tmpl, $GLOBALS['TSFE']->sys_page, '', $conf, 1);
-                               $menu->makeMenu();
-                               $content.=$menu->writeMenu();
+                               $content = $a1 . $string . $a2;
                        }
-                       if ($conf['wrap'])              $content=$this->wrap($content, $conf['wrap']);
-                       if ($conf['stdWrap.'])  $content = $this->stdWrap($content, $conf['stdWrap.']);
                }
+
                return $content;
        }
 
        /**
-        * Rendering the cObject, CTABLE
+        * Returns content of a file. If it's an image the content of the file is not returned but rather an image tag is.
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=359&cHash=2e0065b4e7
+        * @param       string          The filename, being a TypoScript resource data type
+        * @param       string          Additional parameters (attributes). Default is empty alt and title tags.
+        * @return      string          If jpg,gif,jpeg,png: returns image_tag with picture in. If html,txt: returns content string
+        * @see FILE()
         */
-       function CTABLE ($conf) {
-               $controlTable = t3lib_div::makeInstance('tslib_controlTable');
-                       if ($conf['tableParams'])       {
-                       $controlTable->tableParams = $conf['tableParams'];
-               }
-                       // loads the pagecontent
-               $controlTable->contentW = $conf['cWidth'];
-                       // loads the menues if any
-               if (is_array($conf['c.']))      {
-                       $controlTable->content = $this->cObjGet($conf['c.'],'c.');
-                       $controlTable->contentTDparams = isset($conf['c.']['TDParams']) ? $conf['c.']['TDParams'] : 'valign="top"';
-               }
-               if (is_array($conf['lm.']))     {
-                       $controlTable->lm = $this->cObjGet($conf['lm.'],'lm.');
-                       $controlTable->lmTDparams = isset($conf['lm.']['TDParams']) ? $conf['lm.']['TDParams'] : 'valign="top"';
-               }
-               if (is_array($conf['tm.']))     {
-                       $controlTable->tm = $this->cObjGet($conf['tm.'],'tm.');
-                       $controlTable->tmTDparams = isset($conf['tm.']['TDParams']) ? $conf['tm.']['TDParams'] : 'valign="top"';
-               }
-               if (is_array($conf['rm.']))     {
-                       $controlTable->rm = $this->cObjGet($conf['rm.'],'rm.');
-                       $controlTable->rmTDparams = isset($conf['rm.']['TDParams']) ? $conf['rm.']['TDParams'] : 'valign="top"';
-               }
-               if (is_array($conf['bm.']))     {
-                       $controlTable->bm = $this->cObjGet($conf['bm.'],'bm.');
-                       $controlTable->bmTDparams = isset($conf['bm.']['TDParams']) ? $conf['bm.']['TDParams'] : 'valign="top"';
+       function fileResource($fName, $addParams = 'alt="" title=""') {
+               $incFile = $GLOBALS['TSFE']->tmpl->getFileName($fName);
+               if ($incFile) {
+                       $fileinfo = t3lib_div::split_fileref($incFile);
+                       if (t3lib_div::inList('jpg,gif,jpeg,png', $fileinfo['fileext'])) {
+                               $imgFile = $incFile;
+                               $imgInfo = @getImageSize($imgFile);
+                               return '<img src="' . $GLOBALS['TSFE']->absRefPrefix . $imgFile .
+                                       '" width="' . $imgInfo[0] . '" height="' . $imgInfo[1] . '"' .
+                                       $this->getBorderAttr(' border="0"') . ' ' . $addParams . ' />';
+                       } elseif (filesize($incFile) < 1024 * 1024) {
+                               return $GLOBALS['TSFE']->tmpl->fileContent($incFile);
+                       }
                }
-               return $controlTable->start($conf['offset'],$conf['cMargins']);
        }
 
        /**
-        * Rendering the cObject, OTABLE
+        * Sets the SYS_LASTCHANGED timestamp if input timestamp is larger than current value.
+        * The SYS_LASTCHANGED timestamp can be used by various caching/indexing applications to determine if the page has new content.
+        * Therefore you should call this function with the last-changed timestamp of any element you display.
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=360&cHash=02c9552d38
+        * @param       integer         Unix timestamp (number of seconds since 1970)
+        * @return      void
+        * @see tslib_fe::setSysLastChanged()
         */
-       function OTABLE ($conf) {
-               $controlTable = t3lib_div::makeInstance('tslib_tableOffset');
-               if ($conf['tableParams'])       {
-                       $controlTable->tableParams = $conf['tableParams'];
+       function lastChanged($tstamp) {
+               $tstamp = intval($tstamp);
+               if ($tstamp > intval($GLOBALS['TSFE']->register['SYS_LASTCHANGED'])) {
+                       $GLOBALS['TSFE']->register['SYS_LASTCHANGED'] = $tstamp;
                }
-               return $controlTable->start($this->cObjGet($conf),$conf['offset']);
        }
 
        /**
-        * Rendering the cObject, COLUMNS
+        * Wraps the input string by the $wrap value and implements the "linkWrap" data type as well.
+        * The "linkWrap" data type means that this function will find any integer encapsulated in {} (curly braces) in the first wrap part and substitute it with the corresponding page uid from the rootline where the found integer is pointing to the key in the rootline. See link below.
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=361&cHash=7e4e228cad
-        */
-       function COLUMNS ($conf)        {
-               $content='';
-               if (is_array($conf) && $this->checkIf($conf['if.']))    {
-                       $tdRowCount=0;
-                       $tableParams = $conf['tableParams'] ? ' '.$conf['tableParams'] : ' border="0" cellspacing="0" cellpadding="0"';
-                       $TDparams = $conf['TDparams'] ? ' '.$conf['TDparams']:' valign="top"';
-                       $rows = t3lib_div::intInRange($conf['rows'],2,20);
-                       $totalWidth = intval($conf['totalWidth']);
-                       $columnWidth=0;
-
-                       $totalGapWidth=0;
-                       $gapData = Array(
-                               'gapWidth' => $this->stdWrap($conf['gapWidth'],$conf['gapWidth.']),
-                               'gapBgCol' => $this->stdWrap($conf['gapBgCol'],$conf['gapBgCol.']),
-                               'gapLineThickness' => $this->stdWrap($conf['gapLineThickness'],$conf['gapLineThickness.']),
-                               'gapLineCol' => $this->stdWrap($conf['gapLineCol'],$conf['gapLineCol.'])
-                       );
-                       $gapData = $GLOBALS['TSFE']->tmpl->splitConfArray($gapData,$rows-1);
-                       foreach ($gapData as $val) {
-                               $totalGapWidth+=intval($val['gapWidth']);
-                       }
-
-                       if ($totalWidth)        {
-                               $columnWidth = ceil(($totalWidth-$totalGapWidth)/$rows);
-                               $TDparams.=' width="'.$columnWidth.'"';
-                               $tableParams.=' width="'.$totalWidth.'"';
-                       } else {
-                               $TDparams.=' width="'.floor(100/$rows).'%"';
-                               $tableParams.=' width="100%"';
-                       }
-
-                       for ($a=1;$a<=$rows;$a++)       {
-                               $tdRowCount++;
-                               $content.='<td'.$TDparams.'>';
-                               $content.=$this->cObjGetSingle($conf[$a],$conf[$a.'.'], $a);
-                               $content.='</td>';
-                               if ($a < $rows) {
-                                       $gapConf = $gapData[($a-1)];
-                                       $gapWidth = intval($gapConf['gapWidth']);
-                                       if ($gapWidth)  {
-                                               $tdPar = $gapConf['gapBgCol'] ? ' bgcolor="'.$gapConf['gapBgCol'].'"' : '';
-                                               $gapLine = intval($gapConf['gapLineThickness']);
-                                               if ($gapLine)   {
-                                                       $gapSurround = t3lib_div::intInRange(($gapWidth-$gapLine)/2, 1, 1000);
-                                                               // right gap
-                                                       $content.='<td'.$tdPar.'><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$gapSurround.'" height="1" alt="" title="" /></td>';
-                                                       $tdRowCount++;
-                                                               // line:
-                                                       $GtdPar = $gapConf['gapLineCol'] ? ' bgcolor="'.$gapConf['gapLineCol'].'"' : ' bgcolor="black"';
-                                                       $content.='<td'.$GtdPar.'><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$gapLine.'" height="1" alt="" title="" /></td>';
-                                                       $tdRowCount++;
-                                                               // left gap
-                                                       $content.='<td'.$tdPar.'><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$gapSurround.'" height="1" alt="" title="" /></td>';
-                                                       $tdRowCount++;
-                                               } else {
-                                                       $content.='<td'.$tdPar.'><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$gapWidth.'" height="1" alt="" title="" /></td>';
-                                                       $tdRowCount++;
-                                               }
-                                       }
-                               }
-                       }
-                       $content = '<tr>'.$content.'</tr>';
-                       $content = '<table'.$tableParams.'>'.$content.'</table>';
-                       $content.= $this->cObjGetSingle($conf['after'],$conf['after.'], 'after');
-                       if ($conf['stdWrap.'])  {
-                               $content = $this->stdWrap($content,$conf['stdWrap.']);
+        * @param       string          Input string
+        * @param       string          A string where the first two parts separated by "|" (vertical line) will be wrapped around the input string
+        * @return      string          Wrapped output string
+        * @see wrap(), cImage(), FILE()
+        */
+       function linkWrap($content, $wrap) {
+               $wrapArr = explode('|', $wrap);
+               if (preg_match('/\{([0-9]*)\}/', $wrapArr[0], $reg)) {
+                       if ($uid = $GLOBALS['TSFE']->tmpl->rootLine[$reg[1]]['uid']) {
+                               $wrapArr[0] = str_replace($reg[0], $uid, $wrapArr[0]);
                        }
                }
-               return $content;
+               return trim($wrapArr[0]) . $content . trim($wrapArr[1]);
        }
 
        /**
-        * Rendering the cObject, HRULER
+        * An abstraction method which creates an alt or title parameter for an HTML img, applet, area or input element and the FILE content element.
+        * From the $conf array it implements the properties "altText", "titleText" and "longdescURL"
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=362&cHash=2a462aa084
-        */
-       function HRULER ($conf) {
-               $lineThickness = t3lib_div::intInRange($this->stdWrap($conf['lineThickness'],$conf['lineThickness.']),1,50);
-               $lineColor = $conf['lineColor'] ? $conf['lineColor'] : 'black';
-               $spaceBefore = intval($conf['spaceLeft']);
-               $spaceAfter = intval($conf['spaceRight']);
-               $tableWidth = $conf['tableWidth'] ? $conf['tableWidth'] : '99%';
-               $content='';
-
-               $content.='<table border="0" cellspacing="0" cellpadding="0" width="'.htmlspecialchars($tableWidth).'" summary=""><tr>';
-               if ($spaceBefore)       {$content.='<td width="1"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$spaceBefore.'" height="1" alt="" title="" /></td>'; }
-               $content.='<td bgcolor="'.$lineColor.'"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="1" height="'.$lineThickness.'" alt="" title="" /></td>';
-               if ($spaceAfter)        {$content.='<td width="1"><img src="'.$GLOBALS['TSFE']->absRefPrefix.'clear.gif" width="'.$spaceAfter.'" height="1" alt="" title="" /></td>'; }
-               $content.='</tr></table>';
+        * @param       array           TypoScript configuration properties
+        * @param       boolean         If set, the longdesc attribute will be generated - must only be used for img elements!
+        * @return      string          Parameter string containing alt and title parameters (if any)
+        * @see IMGTEXT(), FILE(), FORM(), cImage(), filelink()
+        */
+       function getAltParam($conf, $longDesc = TRUE) {
+               $altText = isset($conf['altText.'])
+                       ? trim($this->stdWrap($conf['altText'], $conf['altText.']))
+                       : trim($conf['altText']);
+               $titleText = isset($conf['titleText.'])
+                       ? trim($this->stdWrap($conf['titleText'], $conf['titleText.']))
+                       : trim($conf['titleText']);
+               $longDesc = isset($conf['longdescURL.'])
+                       ? trim($this->stdWrap($conf['longdescURL'], $conf['longdescURL.']))
+                       : trim($conf['longdescURL']);
 
-               $content = $this->stdWrap($content, $conf['stdWrap.']);
-               return $content;
+                       // "alt":
+               $altParam = ' alt="' . htmlspecialchars($altText) . '"';
+
+                       // "title":
+               $emptyTitleHandling = 'useAlt';
+               $emptyTitleHandling = isset($conf['emptyTitleHandling.'])
+                       ? $this->stdWrap($conf['emptyTitleHandling'], $conf['emptyTitleHandling.'])
+                       : $conf['emptyTitleHandling'];
+                               // choices: 'keepEmpty' | 'useAlt' | 'removeAttr'
+               if ($titleText || $emptyTitleHandling == 'keepEmpty') {
+                       $altParam .= ' title="' . htmlspecialchars($titleText) . '"';
+               } elseif (!$titleText && $emptyTitleHandling == 'useAlt') {
+                       $altParam .= ' title="' . htmlspecialchars($altText) . '"';
+               }
+
+                       // "longDesc" URL
+               if ($longDesc) {
+                       $altParam .= ' longdesc="' . htmlspecialchars(strip_tags($longDesc)) . '"';
+               }
+
+               return $altParam;
        }
 
        /**
-        * Rendering the cObject, CASE
+        * Removes forbidden characters and spaces from name/id attributes in the form tag and formfields
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=364&cHash=cffedd09e3
+        * @param       string          Input string
+        * @return      string          the cleaned string
+        * @see FORM()
         */
-       function CASEFUNC ($conf){
-               $content='';
-               if ($this->checkIf($conf['if.']))       {
-                       if ($conf['setCurrent'] || $conf['setCurrent.']){$this->data[$this->currentValKey] = $this->stdWrap($conf['setCurrent'], $conf['setCurrent.']);}
-                       $key = $this->stdWrap($conf['key'],$conf['key.']);
-                       $key = strlen($conf[$key]) ? $key : 'default';
-                       $name = $conf[$key];
-                       $theValue = $this->cObjGetSingle($name,$conf[$key.'.'], $key);
-                       if ($conf['stdWrap.'])  {
-                               $theValue = $this->stdWrap($theValue,$conf['stdWrap.']);
-                       }
-                       return $theValue;
-               }
+       function cleanFormName($name) {
+                       // turn data[x][y] into data:x:y:
+               $name = preg_replace('/\[|\]\[?/', ':', trim($name));
+                       // remove illegal chars like _
+               return preg_replace('#[^:a-zA-Z0-9]#', '', $name);
        }
 
        /**
-        * Rendering the cObject, LOAD_REGISTER and RESTORE_REGISTER
-        * NOTICE: This cObject does NOT return any content since it just sets internal data based on the TypoScript properties.
+        * An abstraction method to add parameters to an A tag.
+        * Uses the ATagParams property.
         *
-        * @param       array           Array of TypoScript properties
-        * @param       string          If "RESTORE_REGISTER" then the cObject rendered is "RESTORE_REGISTER", otherwise "LOAD_REGISTER"
-        * @return      string          Empty string (the cObject only sets internal data!)
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=365&cHash=4935524e2e
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=366&cHash=4f9485e8cc
+        * @param       array           TypoScript configuration properties
+        * @param       boolean         If set, will add the global config.ATagParams to the link
+        * @return      string          String containing the parameters to the A tag (if non empty, with a leading space)
+        * @see IMGTEXT(), filelink(), makelinks(), typolink()
         */
-       function LOAD_REGISTER($conf,$name)     {
-               if ($name=='RESTORE_REGISTER')  {
-                       $GLOBALS['TSFE']->register = array_pop($GLOBALS['TSFE']->registerStack);
-               } else {
-                       array_push($GLOBALS['TSFE']->registerStack,$GLOBALS['TSFE']->register);
-                       if (is_array($conf))    {
-                               foreach ($conf as $theKey => $theValue) {
-                                       if (!strstr($theKey,'.') || !isset($conf[substr($theKey,0,-1)]))        {               // Only if 1) the property is set but not the value itself, 2) the value and/or any property
-                                               if (strstr($theKey,'.'))        {
-                                                       $theKey = substr($theKey,0,-1);
-                                               }
-                                               $GLOBALS['TSFE']->register[$theKey] = $this->stdWrap($conf[$theKey],$conf[$theKey.'.']);
-                                       }
-                               }
-                       }
+       function getATagParams($conf, $addGlobal = 1) {
+               $aTagParams = '';
+               if ($conf['ATagParams.']) {
+                       $aTagParams = ' ' . $this->stdWrap($conf['ATagParams'], $conf['ATagParams.']);
+               } elseif ($conf['ATagParams']) {
+                       $aTagParams = ' ' . $conf['ATagParams'];
+               }
+               if ($addGlobal) {
+                       $aTagParams = ' ' . trim($GLOBALS['TSFE']->ATagParams . $aTagParams);
                }
-               return '';
+               return $aTagParams;
        }
 
        /**
-        * Rendering the cObject, FORM
-        *
-        * Note on $formData:
-        * In the optional $formData array each entry represents a line in the ordinary setup.
-        * In those entries each entry (0,1,2...) represents a space normally divided by the '|' line.
-        *
-        * $formData [] = array('Name:', 'name=input, 25 ', 'Default value....');
-        * $formData [] = array('Email:', 'email=input, 25 ', 'Default value for email....');
-        *
-        * - corresponds to the $conf['data'] value being :
-        * Name:|name=input, 25 |Default value....||Email:|email=input, 25 |Default value for email....
-        *
-        * If $formData is an array the value of $conf['data'] is ignored.
+        * All extension links should ask this function for additional properties to their tags.
+        * Designed to add for instance an "onclick" property for site tracking systems.
         *
-        * @param       array           Array of TypoScript properties
-        * @param       array           Alternative formdata overriding whatever comes from TypoScript
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=367&cHash=bbc518d930
+        * @param       string  URL of the website
+        * @return  string      the additional tag properties
         */
-       function FORM($conf,$formData='') {
-               $content='';
-               if (is_array($formData)) {
-                       $dataArr = $formData;
-               } else {
-                       $data = $this->stdWrap($conf['data'],$conf['data.']);
-                               // Clearing dataArr
-                       $dataArr = array();
-                               // Getting the original config
-                       if (trim($data))        {
-                               $data = str_replace(LF,'||',$data);
-                               $dataArr = explode('||',$data);
-                       }
-                               // Adding the new dataArray config form:
-                       if (is_array($conf['dataArray.'])) {    // dataArray is supplied
-                               $sKeyArray = t3lib_TStemplate::sortedKeyList($conf['dataArray.'], TRUE);
-                               foreach ($sKeyArray as $theKey) {
-                                       $dAA = $conf['dataArray.'][$theKey.'.'];
-                                       if (is_array($dAA))     {
-                                               $temp = array();
-                                               list($temp[0]) = explode('|',$dAA['label.'] ? $this->stdWrap($dAA['label'],$dAA['label.']) : $dAA['label']);
-                                               list($temp[1]) = explode('|',$dAA['type']);
-                                               if ($dAA['required']) {
-                                                       $temp[1] = '*'.$temp[1];
-                                               }
-                                               list($temp[2]) = explode('|',$dAA['value.'] ? $this->stdWrap($dAA['value'],$dAA['value.']) : $dAA['value']);
-                                                       // If value Array is set, then implode those values.
-                                               if (is_array($dAA['valueArray.'])) {
-                                                       $temp_accum = array();
-                                                       foreach ($dAA['valueArray.'] as $dAKey_vA => $dAA_vA) {
-                                                               if (is_array($dAA_vA) && !strcmp(intval($dAKey_vA).'.',$dAKey_vA))      {
-                                                                       $temp_vA=array();
-                                                                       list($temp_vA[0])= explode('=',$dAA_vA['label.'] ? $this->stdWrap($dAA_vA['label'],$dAA_vA['label.']) : $dAA_vA['label']);
-                                                                       if ($dAA_vA['selected'])        {$temp_vA[0]='*'.$temp_vA[0];}
-                                                                       list($temp_vA[1])= explode(',',$dAA_vA['value']);
-                                                               }
-                                                               $temp_accum[] = implode('=',$temp_vA);
-                                                       }
-                                                       $temp[2] = implode(',',$temp_accum);
-                                               }
-                                               list($temp[3]) = explode('|',$dAA['specialEval.'] ? $this->stdWrap($dAA['specialEval'],$dAA['specialEval.']) : $dAA['specialEval']);
-
-                                                       // adding the form entry to the dataArray
-                                               $dataArr[] = implode('|',$temp);
-                                       }
-                               }
-                       }
-               }
-
-               $attachmentCounter = '';
-               $hiddenfields = '';
-               $fieldlist = Array();
-               $propertyOverride = Array();
-               $fieldname_hashArray = Array();
-               $cc = 0;
+       function extLinkATagParams($URL, $TYPE) {
+               $out = '';
 
-               $xhtmlStrict = t3lib_div::inList('xhtml_strict,xhtml_11,xhtml_2',$GLOBALS['TSFE']->xhtmlDoctype);
-                       // Formname
-               if ($conf['formName']) {
-                       $formname = $this->cleanFormName($conf['formName']);
-               } else {
-                       $formname = $GLOBALS['TSFE']->uniqueHash();
-                       $formname = 'a'.$formname;      // form name has to start with a letter to reach XHTML compliance
-               }
+               if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']) {
+                       $extLinkATagParamsHandler = t3lib_div::getUserObj(
+                               $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']
+                       );
 
-               if (isset($conf['fieldPrefix'])) {
-                       if ($conf['fieldPrefix']) {
-                               $prefix = $this->cleanFormName($conf['fieldPrefix']);
-                       } else {
-                               $prefix = '';
+                       if (method_exists($extLinkATagParamsHandler, 'main')) {
+                               $out .= trim($extLinkATagParamsHandler->main($URL, $TYPE, $this));
                        }
-               } else {
-                       $prefix = $formname;
                }
 
-               foreach ($dataArr as $val)      {
-
-                       $cc++;
-                       $confData=Array();
-                       if (is_array($formData)) {
-                               $parts = $val;
-                               $val = 1;    // true...
-                       } else {
-                               $val = trim($val);
-                               $parts = explode('|',$val);
-                       }
-                       if ($val && strcspn($val,'#/')) {
-                                       // label:
-                               $confData['label'] = trim($parts[0]);
-                                       // field:
-                               $fParts = explode(',',$parts[1]);
-                               $fParts[0]=trim($fParts[0]);
-                               if (substr($fParts[0],0,1)=='*')        {
-                                       $confData['required']=1;
-                                       $fParts[0] = substr($fParts[0],1);
-                               }
-                               $typeParts = explode('=',$fParts[0]);
-                               $confData['type'] = trim(strtolower(end($typeParts)));
-                               if (count($typeParts)==1)       {
-                                       $confData['fieldname'] = $this->cleanFormName($parts[0]);
-                                       if (strtolower(preg_replace('/[^[:alnum:]]/','',$confData['fieldname']))=='email')      {$confData['fieldname']='email';}
-                                               // Duplicate fieldnames resolved
-                                       if (isset($fieldname_hashArray[md5($confData['fieldname'])]))   {
-                                               $confData['fieldname'].='_'.$cc;
-                                       }
-                                       $fieldname_hashArray[md5($confData['fieldname'])]=$confData['fieldname'];
-                                               // Attachment names...
-                                       if ($confData['type']=='file')  {
-                                               $confData['fieldname']='attachment'.$attachmentCounter;
-                                               $attachmentCounter=intval($attachmentCounter)+1;
-                                       }
-                               } else {
-                                       $confData['fieldname'] = str_replace(' ','_',trim($typeParts[0]));
-                               }
-                               $fieldCode='';
-
-                               if ($conf['wrapFieldName'])     {
-                                       $confData['fieldname'] = $this->wrap($confData['fieldname'],$conf['wrapFieldName']);
-                               }
-
-                                       // Set field name as current:
-                               $this->setCurrentVal($confData['fieldname']);
-
-                                       // Additional parameters
-                               if (trim($confData['type']))    {
-                                       $addParams=trim($conf['params']);
-                                       if (is_array($conf['params.']) && isset($conf['params.'][$confData['type']]))   {
-                                               $addParams=trim($conf['params.'][$confData['type']]);
-                                       }
-                                       if (strcmp('',$addParams))      { $addParams=' '.$addParams; }
-                               } else $addParams='';
-
-                               if ($conf['dontMd5FieldNames']) {
-                                       $fName = $confData['fieldname'];
-                               } else {
-                                       $fName = md5($confData['fieldname']);
-                               }
-
-                                       // Accessibility: Set id = fieldname attribute:
-                               if ($conf['accessibility'] || $xhtmlStrict)     {
-                                       $elementIdAttribute = ' id="'.$prefix.$fName.'"';
-                               } else {
-                                       $elementIdAttribute = '';
-                               }
-
-                                       // Create form field based on configuration/type:
-                               switch ($confData['type'])      {
-                                       case 'textarea':
-                                               $cols=trim($fParts[1]) ? intval($fParts[1]) : 20;
-                                               $compWidth = doubleval($conf['compensateFieldWidth'] ? $conf['compensateFieldWidth'] : $GLOBALS['TSFE']->compensateFieldWidth);
-                                               $compWidth = $compWidth ? $compWidth : 1;
-                                               $cols = t3lib_div::intInRange($cols*$compWidth, 1, 120);
-
-                                               $rows=trim($fParts[2]) ? t3lib_div::intInRange($fParts[2],1,30) : 5;
-                                               $wrap=trim($fParts[3]);
-                                               if ($conf['noWrapAttr'] || $wrap === 'disabled')        {
-                                                       $wrap='';
-                                               } else {
-                                                       $wrap = $wrap ? ' wrap="'.$wrap.'"' : ' wrap="virtual"';
-                                               }
-                                               $default = $this->getFieldDefaultValue($conf['noValueInsert'], $confData['fieldname'], str_replace('\n',LF,trim($parts[2])));
-                                               $fieldCode=sprintf('<textarea name="%s"%s cols="%s" rows="%s"%s%s>%s</textarea>',
-                                                       $confData['fieldname'], $elementIdAttribute, $cols, $rows, $wrap, $addParams, t3lib_div::formatForTextarea($default));
-                                       break;
-                                       case 'input':
-                                       case 'password':
-                                               $size=trim($fParts[1]) ? intval($fParts[1]) : 20;
-                                               $compWidth = doubleval($conf['compensateFieldWidth'] ? $conf['compensateFieldWidth'] : $GLOBALS['TSFE']->compensateFieldWidth);
-                                               $compWidth = $compWidth ? $compWidth : 1;
-                                               $size = t3lib_div::intInRange($size*$compWidth, 1, 120);
-                                               $default = $this->getFieldDefaultValue($conf['noValueInsert'], $confData['fieldname'], trim($parts[2]));
-
-                                               if ($confData['type']=='password')      {
-                                                       $default='';
-                                               }
-
-                                               $max=trim($fParts[2]) ? ' maxlength="'.t3lib_div::intInRange($fParts[2],1,1000).'"' : "";
-                                               $theType = $confData['type']=='input' ? 'text' : 'password';
-
-                                               $fieldCode=sprintf('<input type="%s" name="%s"%s size="%s"%s value="%s"%s />',
-                                                       $theType, $confData['fieldname'], $elementIdAttribute, $size, $max, htmlspecialchars($default), $addParams);
-
-                                       break;
-                                       case 'file':
-                                               $size=trim($fParts[1]) ? t3lib_div::intInRange($fParts[1],1,60) : 20;
-                                               $fieldCode=sprintf('<input type="file" name="%s"%s size="%s"%s />',
-                                                       $confData['fieldname'], $elementIdAttribute, $size, $addParams);
-                                       break;
-                                       case 'check':
-                                                       // alternative default value:
-                                               $default = $this->getFieldDefaultValue($conf['noValueInsert'], $confData['fieldname'], trim($parts[2]));
-                                               $checked = $default ? ' checked="checked"' : '';
-                                               $fieldCode=sprintf('<input type="checkbox" value="%s" name="%s"%s%s%s />',
-                                                       1, $confData['fieldname'], $elementIdAttribute, $checked, $addParams);
-                                       break;
-                                       case 'select':
-                                               $option='';
-                                               $valueParts = explode(',',$parts[2]);
-                                                       // size
-                                               if (strtolower(trim($fParts[1]))=='auto')       {$fParts[1]=count($valueParts);}                // Auto size set here. Max 20
-                                               $size=trim($fParts[1]) ? t3lib_div::intInRange($fParts[1],1,20) : 1;
-                                                       // multiple
-                                               $multiple = strtolower(trim($fParts[2]))=='m' ? ' multiple="multiple"' : '';
-
-                                               $items=array();         // Where the items will be
-                                               $defaults=array(); //RTF
-                                               $pCount = count($valueParts);
-                                               for($a=0;$a<$pCount;$a++)       {
-                                                       $valueParts[$a]=trim($valueParts[$a]);
-                                                       if (substr($valueParts[$a],0,1)=='*')   {       // Finding default value
-                                                               $sel='selected';
-                                                               $valueParts[$a] = substr($valueParts[$a],1);
-                                                       } else $sel='';
-                                                               // Get value/label
-                                                       $subParts=explode('=',$valueParts[$a]);
-                                                       $subParts[1] = (isset($subParts[1])?trim($subParts[1]):trim($subParts[0]));             // Sets the value
-                                                       $items[] = $subParts;   // Adds the value/label pair to the items-array
-                                                       if ($sel) {$defaults[]=$subParts[1];}   // Sets the default value if value/label pair is marked as default.
-                                               }
-                                                       // alternative default value:
-                                               $default = $this->getFieldDefaultValue($conf['noValueInsert'], $confData['fieldname'], $defaults);
-                                               if (!is_array($default)) {
-                                                       $defaults=array();
-                                                       $defaults[] = $default;
-                                               } else $defaults=$default;
-                                                       // Create the select-box:
-                                               $iCount = count($items);
-                                               for($a=0;$a<$iCount;$a++)       {
-                                                       $option.='<option value="'.$items[$a][1].'"'.(in_array($items[$a][1],$defaults)?' selected="selected"':'').'>'.trim($items[$a][0]).'</option>'; //RTF
-                                               }
-
-                                               if ($multiple)  $confData['fieldname'].='[]';   // The fieldname must be prepended '[]' if multiple select. And the reason why it's prepended is, because the required-field list later must also have [] prepended.
-                                               $fieldCode=sprintf('<select name="%s"%s size="%s"%s%s>%s</select>',
-                                                       $confData['fieldname'], $elementIdAttribute, $size, $multiple, $addParams, $option); //RTF
-                                       break;
-                                       case 'radio':
-                                               $option='';
-
-                                               $valueParts = explode(',',$parts[2]);
-                                               $items=array();         // Where the items will be
-                                               $default='';
-                                               $pCount = count($valueParts);
-                                               for($a=0;$a<$pCount;$a++)       {
-                                                       $valueParts[$a]=trim($valueParts[$a]);
-                                                       if (substr($valueParts[$a],0,1)=='*')   {
-                                                               $sel='checked';
-                                                               $valueParts[$a] = substr($valueParts[$a],1);
-                                                       } else $sel='';
-                                                               // Get value/label
-                                                       $subParts=explode('=',$valueParts[$a]);
-                                                       $subParts[1] = (isset($subParts[1])?trim($subParts[1]):trim($subParts[0]));             // Sets the value
-                                                       $items[] = $subParts;   // Adds the value/label pair to the items-array
-                                                       if ($sel) {$default=$subParts[1];}      // Sets the default value if value/label pair is marked as default.
-                                               }
-                                                       // alternative default value:
-                                               $default = $this->getFieldDefaultValue($conf['noValueInsert'], $confData['fieldname'], $default);
-                                                       // Create the select-box:
-                                               $iCount = count($items);
-                                               for($a=0;$a<$iCount;$a++)       {
-                                                       $radioId = $prefix.$fName.$this->cleanFormName($items[$a][0]);
-                                                       if ($conf['accessibility'])     {
-                                                               $radioLabelIdAttribute = ' id="'.$radioId.'"';
-                                                       } else {
-                                                               $radioLabelIdAttribute = '';
-                                                       }
-                                                       $option .= '<input type="radio" name="'.$confData['fieldname'].'"'.$radioLabelIdAttribute.' value="'.$items[$a][1].'"'.(!strcmp($items[$a][1],$default)?' checked="checked"':'').$addParams.' />';
-                                                       if ($conf['accessibility'])     {
-                                                               $option .= '<label for="'.$radioId.'">' . $this->stdWrap(trim($items[$a][0]), $conf['radioWrap.']) . '</label>';
-                                                       } else {
-                                                               $option .= $this->stdWrap(trim($items[$a][0]), $conf['radioWrap.']);
-                                                       }
-                                               }
-
-                                               if ($conf['accessibility'])     {
-                                                       $accessibilityWrap = $conf['radioWrap.']['accessibilityWrap'];
-
-                                                       $search = array(
-                                                               '###RADIO_FIELD_ID###',
-                                                               '###RADIO_GROUP_LABEL###'
-                                                       );
-                                                       $replace = array(
-                                                               $elementIdAttribute,
-                                                               $confData['label']
-                                                       );
-                                                       $accessibilityWrap = str_replace($search, $replace, $accessibilityWrap);
-
-                                                       $option = $this->wrap($option, $accessibilityWrap);
-                                               }
-
-                                               $fieldCode = $option;
-                                       break;
-                                       case 'hidden':
-                                               $value = trim($parts[2]);
-                                               if (strlen($value) && t3lib_div::inList('recipient_copy,recipient',$confData['fieldname']) && $GLOBALS['TYPO3_CONF_VARS']['FE']['secureFormmail'])      {
-                                                       break;
-                                               }
-                                               if (strlen($value) && t3lib_div::inList('recipient_copy,recipient',$confData['fieldname']))     {
-                                                       $value = $GLOBALS['TSFE']->codeString($value);
-                                               }
-                                               $hiddenfields.= sprintf('<input type="hidden" name="%s"%s value="%s" />',
-                                                       $confData['fieldname'], $elementIdAttribute, htmlspecialchars($value));
-                                       break;
-                                       case 'property':
-                                               if (t3lib_div::inList('type,locationData,goodMess,badMess,emailMess',$confData['fieldname']))   {
-                                                       $value=trim($parts[2]);
-                                                       $propertyOverride[$confData['fieldname']] = $value;
-                                                       $conf[$confData['fieldname']] = $value;
-                                               }
-                                       break;
-                                       case 'submit':
-                                               $value=trim($parts[2]);
-                                               if ($conf['image.'])    {
-                                                       $this->data[$this->currentValKey] = $value;
-                                                       $image = $this->IMG_RESOURCE($conf['image.']);
-                                                       $params = $conf['image.']['params'] ? ' '.$conf['image.']['params'] : '';
-                                                       $params.= $this->getAltParam($conf['image.'], false);
-                                                       $params.= $addParams;
-                                               } else {
-                                                       $image = '';
-                                               }
-                                               if ($image)     {
-                                                       $fieldCode=sprintf('<input type="image" name="%s"%s src="%s"%s />',
-                                                               $confData['fieldname'], $elementIdAttribute, $image, $params);
-                                               } else  {
-                                                       $fieldCode=sprintf('<input type="submit" name="%s"%s value="%s"%s />',
-                                                               $confData['fieldname'], $elementIdAttribute, t3lib_div::deHSCentities(htmlspecialchars($value)), $addParams);
-                                               }
-                                       break;
-                                       case 'reset':
-                                               $value=trim($parts[2]);
-                                               $fieldCode=sprintf('<input type="reset" name="%s"%s value="%s"%s />',
-                                                       $confData['fieldname'], $elementIdAttribute, t3lib_div::deHSCentities(htmlspecialchars($value)), $addParams);
-                                       break;
-                                       case 'label':
-                                               $fieldCode = nl2br(htmlspecialchars(trim($parts[2])));
-                                       break;
-                                       default:
-                                               $confData['type'] = 'comment';
-                                               $fieldCode = trim($parts[2]).'&nbsp;';
-                                       break;
-                               }
-                               if ($fieldCode) {
-
-                                               // Checking for special evaluation modes:
-                                       if (t3lib_div::inList('textarea,input,password',$confData['type']) && strlen(trim($parts[3])))  {
-                                               $modeParameters = t3lib_div::trimExplode(':',$parts[3]);
-                                       } else {
-                                               $modeParameters = array();
-                                       }
-
-                                               // Adding evaluation based on settings:
-                                       switch ((string)$modeParameters[0])     {
-                                               case 'EREG':
-                                                       $fieldlist[] = '_EREG';
-                                                       $fieldlist[] = $modeParameters[1];
-                                                       $fieldlist[] = $modeParameters[2];
-                                                       $fieldlist[] = $confData['fieldname'];
-                                                       $fieldlist[] = $confData['label'];
-                                                       $confData['required'] = 1;      // Setting this so "required" layout is used.
-                                               break;
-                                               case 'EMAIL':
-                                                       $fieldlist[] = '_EMAIL';
-                                                       $fieldlist[] = $confData['fieldname'];
-                                                       $fieldlist[] = $confData['label'];
-                                                       $confData['required'] = 1;      // Setting this so "required" layout is used.
-                                               break;
-                                               default:
-                                                       if ($confData['required'])      {
-                                                               $fieldlist[] = $confData['fieldname'];
-                                                               $fieldlist[] = $confData['label'];
-                                                       }
-                                               break;
-                                       }
-
-                                               // Field:
-                                       $fieldLabel = $confData['label'];
-                                       if ($conf['accessibility'] && trim($fieldLabel) && !preg_match('/^(label|hidden|comment)$/',$confData['type'])) {
-                                               $fieldLabel = '<label for="'.$prefix.$fName.'">'.$fieldLabel.'</label>';
-                                       }
-
-                                               // Getting template code:
-                                       $fieldCode = $this->stdWrap($fieldCode, $conf['fieldWrap.']);
-                                       $labelCode = $this->stdWrap($fieldLabel, $conf['labelWrap.']);
-                                       $commentCode = $this->stdWrap($confData['label'], $conf['commentWrap.']); // RTF
-                                       $result = $conf['layout'];
-                                       if ($conf['REQ'] && $confData['required'])      {
-                                               if (is_array($conf['REQ.']['fieldWrap.']))
-                                                       $fieldCode = $this->stdWrap($fieldCode, $conf['REQ.']['fieldWrap.']);
-                                               if (is_array($conf['REQ.']['labelWrap.']))
-                                                       $labelCode = $this->stdWrap($fieldLabel, $conf['REQ.']['labelWrap.']);
-                                               if ($conf['REQ.']['layout'])    {
-                                                       $result = $conf['REQ.']['layout'];
-                                               }
-                                       }
-                                       if ($confData['type']=='comment' && $conf['COMMENT.']['layout'])        {
-                                               $result = $conf['COMMENT.']['layout'];
-                                       }
-                                       if ($confData['type']=='check' && $conf['CHECK.']['layout'])    {
-                                               $result = $conf['CHECK.']['layout'];
-                                       }
-                                       if ($confData['type']=='radio' && $conf['RADIO.']['layout'])    {
-                                               $result = $conf['RADIO.']['layout'];
-                                       }
-                                       if ($confData['type']=='label' && $conf['LABEL.']['layout']) {
-                                               $result = $conf['LABEL.']['layout'];
-                                       }
-                                       $result = str_replace('###FIELD###',$fieldCode,$result);
-                                       $result = str_replace('###LABEL###',$labelCode,$result);
-                                       $result = str_replace('###COMMENT###',$commentCode,$result); //RTF
-                                       $content.= $result;
-                               }
-                       }
-               }
-               if ($conf['stdWrap.'])  { $content = $this->stdWrap($content, $conf['stdWrap.']); }
-
-
-                       // redirect (external: where to go afterwards. internal: where to submit to)
-               $theRedirect = $this->stdWrap($conf['redirect'], $conf['redirect.']);                   // redirect should be set to the page to redirect to after an external script has been used. If internal scripts is used, and if no 'type' is set that dictates otherwise, redirect is used as the url to jump to as long as it's an integer (page)
-               $page = $GLOBALS['TSFE']->page;
-               if (!$theRedirect)      {               // Internal: Just submit to current page
-                       $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $conf['target'], $conf['no_cache'],'index.php', '', $this->getClosestMPvalueForPage($page['uid']));
-               } elseif (t3lib_div::testInt($theRedirect))     {               // Internal: Submit to page with ID $theRedirect
-                       $page = $GLOBALS['TSFE']->sys_page->getPage_noCheck($theRedirect);
-                       $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $conf['target'], $conf['no_cache'],'index.php', '', $this->getClosestMPvalueForPage($page['uid']));
-               } else {        // External URL, redirect-hidden field is rendered!
-                       $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $conf['target'], $conf['no_cache'],'', '', $this->getClosestMPvalueForPage($page['uid']));
-                       $LD['totalURL'] = $theRedirect;
-                       $hiddenfields.= '<input type="hidden" name="redirect" value="'.htmlspecialchars($LD['totalURL']).'" />';                // 18-09-00 added
-               }
-
-                       // Formtype (where to submit to!):
-               $formtype = $propertyOverride['type'] ? $propertyOverride['type'] : $this->stdWrap($conf['type'], $conf['type.']);
-               if (t3lib_div::testInt($formtype))      {       // Submit to a specific page
-                       $page = $GLOBALS['TSFE']->sys_page->getPage_noCheck($formtype);
-                       $LD_A = $GLOBALS['TSFE']->tmpl->linkData($page, $conf['target'], $conf['no_cache'], '', '', $this->getClosestMPvalueForPage($page['uid']));
-                       $action = $LD_A['totalURL'];
-               } elseif ($formtype)    {       // Submit to external script
-                       $LD_A = $LD;
-                       $action = $formtype;
-               } elseif (t3lib_div::testInt($theRedirect))     {
-                       $LD_A = $LD;
-                       $action = $LD_A['totalURL'];
-               } else {                // Submit to "nothing" - which is current page
-                       $LD_A = $GLOBALS['TSFE']->tmpl->linkData($GLOBALS['TSFE']->page, $conf['target'], $conf['no_cache'], '', '', $this->getClosestMPvalueForPage($page['uid']));
-                       $action = $LD_A['totalURL'];
-               }
-
-                       // Recipient:
-               $theEmail = $this->stdWrap($conf['recipient'], $conf['recipient.']);
-               if ($theEmail && !$GLOBALS['TYPO3_CONF_VARS']['FE']['secureFormmail'])  {
-                       $theEmail = $GLOBALS['TSFE']->codeString($theEmail);
-                       $hiddenfields.= '<input type="hidden" name="recipient" value="'.htmlspecialchars($theEmail).'" />';
-               }
-
-                       // location data:
-               if ($conf['locationData'])      {
-                       if ($conf['locationData']=='HTTP_POST_VARS' && isset($_POST['locationData']))   {
-                               $locationData = t3lib_div::_POST('locationData');
-                       } else {
-                               $locationData = $GLOBALS['TSFE']->id.':'.$this->currentRecord;  // locationData is [hte page id]:[tablename]:[uid of record]. Indicates on which page the record (from tablename with uid) is shown. Used to check access.
-                       }
-                       $hiddenfields.='<input type="hidden" name="locationData" value="'.htmlspecialchars($locationData).'" />';
-               }
+               return trim($out) ? ' ' . trim($out) : '';
+       }
 
-                       // hidden fields:
-               if (is_array($conf['hiddenFields.']))   {
-                       foreach ($conf['hiddenFields.'] as $hF_key => $hF_conf) {
-                               if (substr($hF_key,-1)!='.')    {
-                                       $hF_value = $this->cObjGetSingle($hF_conf,$conf['hiddenFields.'][$hF_key.'.'],'hiddenfields');
-                                       if (strlen($hF_value) && t3lib_div::inList('recipient_copy,recipient',$hF_key)) {
-                                               if ($GLOBALS['TYPO3_CONF_VARS']['FE']['secureFormmail'])        {
-                                                       continue;
-                                               }
-                                               $hF_value = $GLOBALS['TSFE']->codeString($hF_value);
-                                       }
-                                       $hiddenfields.= '<input type="hidden" name="'.$hF_key.'" value="'.htmlspecialchars($hF_value).'" />';
-                               }
-                       }
-               }
 
-                       // Wrap all hidden fields in a div tag (see http://bugs.typo3.org/view.php?id=678)
-               $hiddenfields = '<div style="display:none;">'.$hiddenfields.'</div>';
 
-               if ($conf['REQ'])       {
-                       $validateForm = ' onsubmit="return validateForm(\'' .
-                               $formname . '\',\'' . implode(',',$fieldlist) . '\',' .
-                               t3lib_div::quoteJSvalue($conf['goodMess']) . ',' .
-                               t3lib_div::quoteJSvalue($conf['badMess']) . ',' .
-                               t3lib_div::quoteJSvalue($conf['emailMess']) . ')"';
-                       $GLOBALS['TSFE']->additionalHeaderData['JSFormValidate'] =
-                               '<script type="text/javascript" src="' .
-                               t3lib_div::createVersionNumberedFilename($GLOBALS['TSFE']->absRefPrefix .
-                                       't3lib/jsfunc.validateform.js') .
-                               '"</script>';
-               } else {
-                       $validateForm = '';
-               }
-
-                       // Create form tag:
-               $theTarget = ($theRedirect?$LD['target']:$LD_A['target']);
-               $content = array(
-                       '<form'.
-                               ' action="'.htmlspecialchars($action).'"'.
-                               ' id="'.$formname.'"'.($xhtmlStrict ? '' : ' name="'.$formname.'"').
-                               ' enctype="'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'].'"'.
-                               ' method="'.($conf['method']?$conf['method']:'post').'"'.
-                               ($theTarget ? ' target="'.$theTarget.'"' : '').
-                               $validateForm.
-                               '>',
-                       $hiddenfields.$content,
-                       '</form>'
-               );
+       /***********************************************
+        *
+        * HTML template processing functions
+        *
+        ***********************************************/
 
-               if ($conf['arrayReturnMode'])   {
-                       $content['validateForm']=$validateForm;
-                       $content['formname']=$formname;
-                       return $content;
-               } else {
-                       return implode('',$content);
-               }
+       /**
+        * Returns a subpart from the input content stream.
+        * A subpart is a part of the input stream which is encapsulated in a
+        * string matching the input string, $marker. If this string is found
+        * inside of HTML comment tags the start/end points of the content block
+        * returned will be that right outside that comment block.
+        * Example: The contennt string is
+        * "Hello <!--###sub1### begin--> World. How are <!--###sub1### end--> you?"
+        * If $marker is "###sub1###" then the content returned is
+        * " World. How are ". The input content string could just as well have
+        * been "Hello ###sub1### World. How are ###sub1### you?" and the result
+        * would be the same
+        * Wrapper for t3lib_parsehtml::getSubpart which behaves identical
+        *
+        * @param       string          The content stream, typically HTML template content.
+        * @param       string          The marker string, typically on the form "###[the marker string]###"
+        * @return      string          The subpart found, if found.
+        * @see substituteSubpart(), t3lib_parsehtml::getSubpart()
+        */
+       public function getSubpart($content, $marker) {
+               return t3lib_parsehtml::getSubpart($content, $marker);
        }
 
        /**
-        * Rendering the cObject, SEARCHRESULT
+        * Substitute subpart in input template stream.
+        * This function substitutes a subpart in $content with the content of
+        * $subpartContent.
+        * Wrapper for t3lib_parsehtml::substituteSubpart which behaves identical
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=368&cHash=d00731cd7b
-        */
-       function SEARCHRESULT($conf)    {
-               if (t3lib_div::_GP('sword') && t3lib_div::_GP('scols')) {
-                       $search = t3lib_div::makeInstance('tslib_search');
-                       $search->register_and_explode_search_string(t3lib_div::_GP('sword'));
-                       $search->register_tables_and_columns(t3lib_div::_GP('scols'),$conf['allowedCols']);
-                               // depth
-                       $depth=100;
-                               // the startId is found
-                       $theStartId=0;
-                       if (t3lib_div::testInt(t3lib_div::_GP('stype')))        {
-                               $temp_theStartId=t3lib_div::_GP('stype');
-                               $rootLine = $GLOBALS['TSFE']->sys_page->getRootLine($temp_theStartId);
-                                       // The page MUST have a rootline with the Level0-page of the current site inside!!
-                               foreach ($rootLine as $val) {
-                                       if($val['uid']==$GLOBALS['TSFE']->tmpl->rootLine[0]['uid'])     {
-                                               $theStartId = $temp_theStartId;
-                                       }
-                               }
-                       } else if (t3lib_div::_GP('stype'))     {
-                               if (substr(t3lib_div::_GP('stype'),0,1)=='L')   {
-                                       $pointer = intval(substr(t3lib_div::_GP('stype'),1));
-                                       $theRootLine = $GLOBALS['TSFE']->tmpl->rootLine;
-                                               // location Data:
-                                       $locDat_arr = explode(':',t3lib_div::_POST('locationData'));
-                                       $pId = intval($locDat_arr[0]);
-                                       if ($pId)       {
-                                               $altRootLine = $GLOBALS['TSFE']->sys_page->getRootLine($pId);
-                                               ksort($altRootLine);
-                                               if (count($altRootLine))        {
-                                                               // check if the rootline has the real Level0 in it!!
-                                                       $hitRoot=0;
-                                                       $theNewRoot=array();
-                                                       foreach ($altRootLine as $val) {
-                                                               if($hitRoot || $val['uid']==$GLOBALS['TSFE']->tmpl->rootLine[0]['uid']) {
-                                                                       $hitRoot=1;
-                                                                       $theNewRoot[]=$val;
-                                                               }
-                                                       }
-                                                       if ($hitRoot)   {
-                                                               $theRootLine = $theNewRoot;             // Override the real rootline if any thing
-                                                       }
-                                               }
-                                       }
-                                       $key = $this->getKey($pointer,$theRootLine);
-                                       $theStartId = $theRootLine[$key]['uid'];
-                               }
-                       }
-                       if (!$theStartId)       {
-                                       // If not set, we use current page
-                               $theStartId = $GLOBALS['TSFE']->id;
-                       }
-                               // generate page-tree
-                       $search->pageIdList.= $this->getTreeList(-1*$theStartId,$depth);
-
-                       $endClause = 'pages.uid IN ('.$search->pageIdList.')
-                               AND pages.doktype in ('.$GLOBALS['TYPO3_CONF_VARS']['FE']['content_doktypes'].($conf['addExtUrlsAndShortCuts']?',3,4':'').')
-                               AND pages.no_search=0'.
-                               $this->enableFields($search->fTable).
-                               $this->enableFields('pages');
-
-                       if ($conf['languageField.'][$search->fTable])   {
-                               $endClause.= ' AND '.$search->fTable.'.'.$conf['languageField.'][$search->fTable].' = '.intval($GLOBALS['TSFE']->sys_language_uid);     // (using sys_language_uid which is the ACTUAL language of the page. sys_language_content is only for selecting DISPLAY content!)
-                       }
-
-                               // build query
-                       $search->build_search_query($endClause);
-
-                               // count...
-                       if (t3lib_div::testInt(t3lib_div::_GP('scount')))       {
-                               $search->res_count = t3lib_div::_GP('scount');
-                       } else {
-                               $search->count_query();
-                       }
-
-                               // range
-                       $spointer = intval(t3lib_div::_GP('spointer'));
-                       if (isset($conf['range']))      {
-                               $theRange = intval($conf['range']);
-                       } else {
-                               $theRange = 20;
-                       }
-
-                               // Order By:
-                       if (!$conf['noOrderBy'])        {
-                               $search->queryParts['ORDERBY'] = 'pages.lastUpdated, pages.tstamp';
-                       }
-
-                       $search->queryParts['LIMIT'] = $spointer.','.$theRange;
-
-                               // search...
-                       $search->execute_query();
-                       if ($GLOBALS['TYPO3_DB']->sql_num_rows($search->result))        {
-                               $GLOBALS['TSFE']->register['SWORD_PARAMS'] = $search->get_searchwords();
-
-                               $total = $search->res_count;
-                               $rangeLow = t3lib_div::intInRange($spointer+1,1,$total);
-                               $rangeHigh = t3lib_div::intInRange($spointer+$theRange,1,$total);
-                                       // prev/next url:
-                               $LD = $GLOBALS['TSFE']->tmpl->linkData($GLOBALS['TSFE']->page,$conf['target'],1,'', '', $this->getClosestMPvalueForPage($GLOBALS['TSFE']->page['uid']));
-                               $targetPart = $LD['target'] ? ' target="'.htmlspecialchars($LD['target']).'"' : '';
-                               $urlParams = $this->URLqMark($LD['totalURL'],
-                                               '&sword='.rawurlencode(t3lib_div::_GP('sword')).
-                                               '&scols='.rawurlencode(t3lib_div::_GP('scols')).
-                                               '&stype='.rawurlencode(t3lib_div::_GP('stype')).
-                                               '&scount='.$total);
-                                       // substitution:
-                               $result= $this->cObjGetSingle($conf['layout'],$conf['layout.'], 'layout');
-                               $result = str_replace('###RANGELOW###',$rangeLow,$result);
-                               $result = str_replace('###RANGEHIGH###',$rangeHigh,$result);
-                               $result = str_replace('###TOTAL###',$total,$result);
-
-                               if ($rangeHigh<$total)  {
-                                       $next = $this->cObjGetSingle($conf['next'], $conf['next.'], 'next');
-                                       $next = '<a href="'.htmlspecialchars($urlParams.'&spointer='.($spointer+$theRange)).'"'.$targetPart.$GLOBALS['TSFE']->ATagParams.'>'.$next.'</a>';
-                               } else $next='';
-                               $result = str_replace('###NEXT###',$next,$result);
-
-                               if ($rangeLow>1)        {
-                                       $prev = $this->cObjGetSingle($conf['prev'], $conf['prev.'], 'prev');
-                                       $prev = '<a href="'.htmlspecialchars($urlParams.'&spointer='.($spointer-$theRange)).'"'.$targetPart.$GLOBALS['TSFE']->ATagParams.'>'.$prev.'</a>';
-                               } else $prev='';
-                               $result = str_replace('###PREV###',$prev,$result);
-
-                                       // searching result
-                               $theValue = $this->cObjGetSingle($conf['resultObj'], $conf['resultObj.'],'resultObj');
-                               $cObj = t3lib_div::makeInstance('tslib_cObj');
-                               $cObj->setParent($this->data,$this->currentRecord);
-                               $renderCode='';
-                               while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($search->result))   {
-                                               // versionOL() here? This is search result displays, is that possible to preview anyway? Or are records selected here already future versions?
-                                       $cObj->start($row);
-                                       $renderCode.=$cObj->cObjGetSingle($conf['renderObj'], $conf['renderObj.'],'renderObj');
-                               }
-                               $theValue.=$this->wrap($renderCode,$conf['renderWrap']);
-                               $theValue = str_replace('###RESULT###',$theValue,$result);
-                       } else {
-                               $theValue = $this->cObjGetSingle($conf['noResultObj'], $conf['noResultObj.'],'noResultObj');
-                       }
-
-                       $GLOBALS['TT']->setTSlogMessage('Search in fields:   '.$search->listOfSearchFields);
-
-                               // wrapping
-                       $content=$theValue;
-                       if ($conf['wrap']) {
-                               $content=$this->wrap($content, $conf['wrap']);
-                       }
-                       if ($conf['stdWrap.']) {
-                               $content=$this->stdWrap($content, $conf['stdWrap.']);
-                       }
-                               // returning
-                       $GLOBALS['TSFE']->set_no_cache();
-                       return $content;
-               }
+        * @param       string          The content stream, typically HTML template content.
+        * @param       string          The marker string, typically on the form "###[the marker string]###"
+        * @param       mixed           The content to insert instead of the subpart found. If a string, then just plain substitution happens (includes removing the HTML comments of the subpart if found). If $subpartContent happens to be an array, it's [0] and [1] elements are wrapped around the EXISTING content of the subpart (fetched by getSubpart()) thereby not removing the original content.
+        * @param       boolean         If $recursive is set, the function calls itself with the content set to the remaining part of the content after the second marker. This means that proceding subparts are ALSO substituted!
+        * @return      string          The processed HTML content string.
+        * @see getSubpart(), t3lib_parsehtml::substituteSubpart()
+        */
+       public function substituteSubpart($content, $marker, $subpartContent, $recursive = 1) {
+               return t3lib_parsehtml::substituteSubpart($content, $marker, $subpartContent, $recursive);
        }
 
        /**
-        * Rendering the cObject, PHP_SCRIPT, PHP_SCRIPT_INT and PHP_SCRIPT_EXT
+        * Substitues multiple subparts at once
         *
-        * @param       array           Array of TypoScript properties
-        * @param       string          If "INT", then rendering "PHP_SCRIPT_INT"; If "EXT", then rendering "PHP_SCRIPT_EXT"; Default is rendering "PHP_SCRIPT" (cached)
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=370&cHash=aa107f2ad8
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=371&cHash=53f71d025e
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=372&cHash=91fe391e1c
-        */
-       function PHP_SCRIPT($conf,$ext='')      {
-               $incFile = $GLOBALS['TSFE']->tmpl->getFileName($conf['file']);
-               $content='';
-               if ($incFile && $GLOBALS['TSFE']->checkFileInclude($incFile))   {
-                       switch($ext)    {
-                               case 'INT':
-                               case 'EXT':
-                                       $substKey = $ext.'_SCRIPT.'.$GLOBALS['TSFE']->uniqueHash();
-                                       $content.='<!--'.$substKey.'-->';
-                                       $GLOBALS['TSFE']->config[$ext.'incScript'][$substKey] = array(
-                                               'file'=>$incFile,
-                                               'conf'=>$conf,
-                                               'type'=>'SCRIPT'
-                                       );
-                                       if ($ext=='INT')        {
-                                               $GLOBALS['TSFE']->config[$ext.'incScript'][$substKey]['cObj'] = serialize($this);
-                                       } else {
-                                               $GLOBALS['TSFE']->config[$ext.'incScript'][$substKey]['data'] = $this->data;
-                                       }
-                               break;
-                               default:
-                                               // Added 31-12-00: Make backup...
-                                       $this->oldData = $this->data;
-                                               // Include file..
-                                       include('./'.$incFile);
-                                               // Added 31-12-00: restore...
-                                       if ($RESTORE_OLD_DATA)  {
-                                               $this->data = $this->oldData;
-                                       }
-                               break;
-                       }
-               }
-               return $content;
+        * @param       string          The content stream, typically HTML template content.
+        * @param       array           The array of key/value pairs being subpart/content values used in the substitution. For each element in this array the function will substitute a subpart in the content stream with the content.
+        * @return      string          The processed HTML content string.
+        */
+       public function substituteSubpartArray($content, array $subpartsContent) {
+               return t3lib_parsehtml::substituteSubpartArray($content, $subpartsContent);
        }
 
        /**
-        * Rendering the cObject, TEMPLATE
+        * Substitutes a marker string in the input content
+        * (by a simple str_replace())
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=373&cHash=109a171b1e
-        * @see substituteMarkerArrayCached()
+        * @param       string          The content stream, typically HTML template content.
+        * @param       string          The marker string, typically on the form "###[the marker string]###"
+        * @param       mixed           The content to insert instead of the marker string found.
+        * @return      string          The processed HTML content string.
+        * @see substituteSubpart()
         */
-       function TEMPLATE($conf)        {
-               $subparts = Array();
-               $marks = Array();
-               $wraps = Array();
-               $content='';
+       public function substituteMarker($content, $marker, $markContent) {
+               return t3lib_parsehtml::substituteMarker($content, $marker, $markContent);
+       }
 
-               list($PRE,$POST) = explode('|',$conf['markerWrap'] ? $conf['markerWrap'] : '### | ###');
-               $POST = trim($POST);
-               $PRE  = trim($PRE);
+       /**
+        * Multi substitution function with caching.
+        *
+        * This function should be a one-stop substitution function for working
+        * with HTML-template. It does not substitute by str_replace but by
+        * splitting. This secures that the value inserted does not themselves
+        * contain markers or subparts.
+        *
+        * Note that the "caching" won't cache the content of the substition,
+        * but only the splitting of the template in various parts. So if you
+        * want only one cache-entry per template, make sure you always pass the
+        * exact same set of marker/subpart keys. Else you will be flooding the
+        * users cache table.
+        *
+        * This function takes three kinds of substitutions in one:
+        * $markContentArray is a regular marker-array where the 'keys' are
+        * substituted in $content with their values
+        *
+        * $subpartContentArray works exactly like markContentArray only is whole
+        * subparts substituted and not only a single marker.
+        *
+        * $wrappedSubpartContentArray is an array of arrays with 0/1 keys where
+        * the subparts pointed to by the main key is wrapped with the 0/1 value
+        * alternating.
+        *
+        * @param       string          The content stream, typically HTML template content.
+        * @param       array           Regular marker-array where the 'keys' are substituted in $content with their values
+        * @param       array           Exactly like markContentArray only is whole subparts substituted and not only a single marker.
+        * @param       array           An array of arrays with 0/1 keys where the subparts pointed to by the main key is wrapped with the 0/1 value alternating.
+        * @return      string          The output content stream
+        * @see substituteSubpart(), substituteMarker(), substituteMarkerInObject(), TEMPLATE()
+        */
+       public function substituteMarkerArrayCached($content, array $markContentArray = NULL, array $subpartContentArray = NULL, array $wrappedSubpartContentArray = NULL) {
+               $GLOBALS['TT']->push('substituteMarkerArrayCached');
 
-                       // Getting the content
-               $content = $this->cObjGetSingle($conf['template'],$conf['template.'],'template');
-               if ($conf['workOnSubpart'])     {
-                       $content = $this->getSubpart($content, $PRE.$conf['workOnSubpart'].$POST);
+                       // If not arrays then set them
+               if (is_null($markContentArray))
+                       $markContentArray = array(); // Plain markers
+               if (is_null($subpartContentArray))
+                       $subpartContentArray = array(); // Subparts being directly substituted
+               if (is_null($wrappedSubpartContentArray))
+                       $wrappedSubpartContentArray = array(); // Subparts being wrapped
+                       // Finding keys and check hash:
+               $sPkeys = array_keys($subpartContentArray);
+               $wPkeys = array_keys($wrappedSubpartContentArray);
+               $aKeys = array_merge(array_keys($markContentArray), $sPkeys, $wPkeys);
+               if (!count($aKeys)) {
+                       $GLOBALS['TT']->pull();
+                       return $content;
                }
+               asort($aKeys);
+               $storeKey = md5('substituteMarkerArrayCached_storeKey:' . serialize(array(
+                       $content, $aKeys
+               )));
+               if ($this->substMarkerCache[$storeKey]) {
+                       $storeArr = $this->substMarkerCache[$storeKey];
+                       $GLOBALS['TT']->setTSlogMessage('Cached', 0);
+               } else {
+                       $storeArrDat = $GLOBALS['TSFE']->sys_page->getHash($storeKey);
+                       if (!isset($storeArrDat)) {
+                                       // Initialize storeArr
+                               $storeArr = array();
 
-                       // Fixing all relative paths found:
-               if ($conf['relPathPrefix'])     {
-                       $htmlParser = t3lib_div::makeInstance('t3lib_parsehtml');
-                       $content = $htmlParser->prefixResourcePath($conf['relPathPrefix'],$content,$conf['relPathPrefix.']);
-               }
-
-               if ($content)   {
-                       if ($conf['nonCachedSubst'])    {               // NON-CACHED:
-                                       // Getting marks
-                               if (is_array($conf['marks.']))  {
-                                       foreach ($conf['marks.'] as $theKey => $theValue) {
-                                               if (!strstr($theKey,'.'))       {
-                                                       $content = str_replace(
-                                                               $PRE.$theKey.$POST,
-                                                               $this->cObjGetSingle($theValue,$conf['marks.'][$theKey.'.'],'marks.'.$theKey),
-                                                               $content);
-                                               }
-                                       }
+                                       // Finding subparts and substituting them with the subpart as a marker
+                               foreach ($sPkeys as $sPK) {
+                                       $content = $this->substituteSubpart($content, $sPK, $sPK);
                                }
 
-                                       // Getting subparts.
-                               if (is_array($conf['subparts.']))       {
-                                       foreach ($conf['subparts.'] as $theKey => $theValue) {
-                                               if (!strstr($theKey,'.'))       {
-                                                       $subpart = $this->getSubpart($content, $PRE.$theKey.$POST);
-                                                       if ($subpart)   {
-                                                               $this->setCurrentVal($subpart);
-                                                               $content = $this->substituteSubpart(
-                                                                       $content,
-                                                                       $PRE.$theKey.$POST,
-                                                                       $this->cObjGetSingle($theValue,$conf['subparts.'][$theKey.'.'],'subparts.'.$theKey),
-                                                                       1
-                                                               );
-                                                       }
-                                               }
-                                       }
-                               }
-                                       // Getting subpart wraps
-                               if (is_array($conf['wraps.']))  {
-                                       foreach ($conf['wraps.'] as $theKey => $theValue) {
-                                               if (!strstr($theKey,'.'))       {
-                                                       $subpart = $this->getSubpart($content, $PRE.$theKey.$POST);
-                                                       if ($subpart)   {
-                                                               $this->setCurrentVal($subpart);
-                                                               $content = $this->substituteSubpart(
-                                                                       $content,
-                                                                       $PRE.$theKey.$POST,
-                                                                       explode('|',$this->cObjGetSingle($theValue,$conf['wraps.'][$theKey.'.'],'wraps.'.$theKey)),
-                                                                       1
-                                                               );
-                                                       }
-                                               }
-                                       }
-                               }
-                       } else {        // CACHED
-                                       // Getting subparts.
-                               if (is_array($conf['subparts.']))       {
-                                       foreach ($conf['subparts.'] as $theKey => $theValue) {
-                                               if (!strstr($theKey,'.'))       {
-                                                       $subpart = $this->getSubpart($content, $PRE.$theKey.$POST);
-                                                       if ($subpart)   {
-                                                               $GLOBALS['TSFE']->register['SUBPART_'.$theKey] = $subpart;
-                                                               $subparts[$theKey]['name'] = $theValue;
-                                                               $subparts[$theKey]['conf'] = $conf['subparts.'][$theKey.'.'];
-                                                       }
-                                               }
-                                       }
-                               }
-                                       // Getting marks
-                               if (is_array($conf['marks.']))  {
-                                       foreach ($conf['marks.'] as $theKey => $theValue) {
-                                               if (!strstr($theKey,'.'))       {
-                                                       $marks[$theKey]['name'] = $theValue;
-                                                       $marks[$theKey]['conf'] = $conf['marks.'][$theKey.'.'];
-                                               }
-                                       }
-                               }
-                                       // Getting subpart wraps
-                               if (is_array($conf['wraps.']))  {
-                                       foreach ($conf['wraps.'] as $theKey => $theValue) {
-                                               if (!strstr($theKey,'.'))       {
-                                                       $wraps[$theKey]['name'] = $theValue;
-                                                       $wraps[$theKey]['conf'] = $conf['wraps.'][$theKey.'.'];
-                                               }
-                                       }
-                               }
-                                       // Getting subparts
-                               $subpartArray =array();
-                               foreach ($subparts as $theKey => $theValue) {
-                                               // Set current with the content of the subpart...
-                                       $this->data[$this->currentValKey] = $GLOBALS['TSFE']->register['SUBPART_'.$theKey];
-                                               // Get subpart cObject and substitute it!
-                                       $subpartArray[$PRE.$theKey.$POST] = $this->cObjGetSingle($theValue['name'],$theValue['conf'],'subparts.'.$theKey);
+                                       // Finding subparts and wrapping them with markers
+                               foreach ($wPkeys as $wPK) {
+                                       $content = $this->substituteSubpart($content, $wPK, array(
+                                               $wPK, $wPK
+                                       ));
                                }
-                               $this->data[$this->currentValKey] = ''; // Reset current to empty
 
-                                       // Getting marks
-                               $markerArray =array();
-                               foreach ($marks as $theKey => $theValue) {
-                                       $markerArray[$PRE.$theKey.$POST] = $this->cObjGetSingle($theValue['name'],$theValue['conf'],'marks.'.$theKey);
-                               }
-                                       // Getting wraps
-                               $subpartWraps =array();
-                               foreach ($wraps as $theKey => $theValue) {
-                                       $subpartWraps[$PRE.$theKey.$POST] = explode('|',$this->cObjGetSingle($theValue['name'],$theValue['conf'],'wraps.'.$theKey));
+                                       // traverse keys and quote them for reg ex.
+                               foreach ($aKeys as $tK => $tV) {
+                                       $aKeys[$tK] = preg_quote($tV, '/');
                                }
+                               $regex = '/' . implode('|', $aKeys) . '/';
+                                       // Doing regex's
+                               $storeArr['c'] = preg_split($regex, $content);
+                               preg_match_all($regex, $content, $keyList);
+                               $storeArr['k'] = $keyList[0];
+                                       // Setting cache:
+                               $this->substMarkerCache[$storeKey] = $storeArr;
 
-                                       // Substitution
-                               if ($conf['substMarksSeparately'])      {
-                                       $content = $this->substituteMarkerArrayCached($content,array(),$subpartArray,$subpartWraps);
-                                       $content = $this->substituteMarkerArray($content, $markerArray);
-                               } else {
-                                       $content = $this->substituteMarkerArrayCached($content,$markerArray,$subpartArray,$subpartWraps);
-                               }
+                                       // Storing the cached data:
+                               $GLOBALS['TSFE']->sys_page->storeHash($storeKey, serialize($storeArr), 'substMarkArrayCached');
+
+                               $GLOBALS['TT']->setTSlogMessage('Parsing', 0);
+                       } else {
+                                       // Unserializing
+                               $storeArr = unserialize($storeArrDat);
+                                       // Setting cache:
+                               $this->substMarkerCache[$storeKey] = $storeArr;
+                               $GLOBALS['TT']->setTSlogMessage('Cached from DB', 0);
                        }
                }
+
+                       // Substitution/Merging:
+                       // Merging content types together, resetting
+               $valueArr = array_merge($markContentArray, $subpartContentArray, $wrappedSubpartContentArray);
+
+               $wSCA_reg = array();
+               $content = '';
+                       // traversing the keyList array and merging the static and dynamic content
+               foreach ($storeArr['k'] as $n => $keyN) {
+                       $content .= $storeArr['c'][$n];
+                       if (!is_array($valueArr[$keyN])) {
+                               $content .= $valueArr[$keyN];
+                       } else {
+                               $content .= $valueArr[$keyN][(intval($wSCA_reg[$keyN]) % 2)];
+                               $wSCA_reg[$keyN]++;
+                       }
+               }
+               $content .= $storeArr['c'][count($storeArr['k'])];
+
+               $GLOBALS['TT']->pull();
                return $content;
        }
 
        /**
-        * Rendering the cObject, MULTIMEDIA
+        * Traverses the input $markContentArray array and for each key the marker
+        * by the same name (possibly wrapped and in upper case) will be
+        * substituted with the keys value in the array.
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
-        * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=374&cHash=efd88ab4a9
+        * This is very useful if you have a data-record to substitute in some
+        * content. In particular when you use the $wrap and $uppercase values to
+        * pre-process the markers. Eg. a key name like "myfield" could effectively
+        * be represented by the marker "###MYFIELD###" if the wrap value
+        * was "###|###" and the $uppercase boolean TRUE.
+        *
+        * @param       string          The content stream, typically HTML template content.
+        * @param       array           The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content stream with the content.
+        * @param       string          A wrap value - [part 1] | [part 2] - for the markers before substitution
+        * @param       boolean         If set, all marker string substitution is done with upper-case markers.
+        * @param       boolean         If set, all unused marker are deleted.
+        * @return      string          The processed output stream
+        * @see substituteMarker(), substituteMarkerInObject(), TEMPLATE()
         */
-       function MULTIMEDIA($conf)      {
-               $content='';
-               $filename=$this->stdWrap($conf['file'],$conf['file.']);
-               $incFile = $GLOBALS['TSFE']->tmpl->getFileName($filename);
-               if ($incFile)   {
-                       $fileinfo = t3lib_div::split_fileref($incFile);
-                       if (t3lib_div::inList('txt,html,htm',$fileinfo['fileext']))     {
-                               $content = $GLOBALS['TSFE']->tmpl->fileContent($incFile);
-                       } else {
-                                       // default params...
-                               $parArray=array();
-                                       // src is added
-                               $parArray['src']='src="'.$GLOBALS['TSFE']->absRefPrefix.$incFile.'"';
-                               if (t3lib_div::inList('au,wav,mp3',$fileinfo['fileext']))       {
-                               }
-                               if (t3lib_div::inList('avi,mov,mpg,asf,wmv',$fileinfo['fileext']))      {
-                                       $parArray['width'] = 'width="' . ($conf['width'] ? $conf['width'] : 200) . '"';
-                                       $parArray['height'] = 'height="' . ($conf['height'] ? $conf['height'] : 200) . '"';
-                               }
-                               if (t3lib_div::inList('swf,swa,dcr',$fileinfo['fileext']))      {
-                                       $parArray['quality'] = 'quality="high"';
-                               }
-                               if (t3lib_div::inList('class',$fileinfo['fileext']))    {
-                                       $parArray['width'] = 'width="' . ($conf['width'] ? $conf['width'] : 200) . '"';
-                                       $parArray['height'] = 'height="' . ($conf['height'] ? $conf['height'] : 200) . '"';
-                               }
+       public function substituteMarkerArray($content, array $markContentArray, $wrap = '', $uppercase = FALSE, $deleteUnused = FALSE) {
+               return t3lib_parsehtml::substituteMarkerArray($content, $markContentArray, $wrap, $uppercase, $deleteUnused);
+       }
 
-                                       // fetching params
-                               $lines = explode(LF, $this->stdWrap($conf['params'],$conf['params.']));
-                               foreach ($lines as $l) {
-                                       $parts = explode('=', $l);
-                                       $parameter = strtolower(trim($parts[0]));
-                                       $value = trim($parts[1]);
-                                       if ((string)$value!='') {
-                                               $parArray[$parameter] = $parameter.'="'.htmlspecialchars($value).'"';
-                                       } else {
-                                               unset($parArray[$parameter]);
-                                       }
-                               }
-                               if ($fileinfo['fileext']=='class')      {
-                                       unset($parArray['src']);
-                                       $parArray['code'] = 'code="'.htmlspecialchars($fileinfo['file']).'"';
-                                       $parArray['codebase'] = 'codebase="'.htmlspecialchars($fileinfo['path']).'"';
-                                       $content='<applet '.implode(' ',$parArray).'></applet>';
-                               } else {
-                                       $content='<embed '.implode(' ',$parArray).'></embed>';
-                               }
+       /**
+        * Substitute marker array in an array of values
+        *
+        * @param       mixed           If string, then it just calls substituteMarkerArray. If array(and even multi-dim) then for each key/value pair the marker array will be substituted (by calling this function recursively)
+        * @param       array           The array of key/value pairs being marker/content values used in the substitution. For each element in this array the function will substitute a marker in the content string/array values.
+        * @return      mixed           The processed input variable.
+        * @see substituteMarker()
+        */
+       public function substituteMarkerInObject(&$tree, array $markContentArray) {
+               if (is_array($tree)) {
+                       foreach ($tree as $key => $value) {
+                               $this->substituteMarkerInObject($tree[$key], $markContentArray);
                        }
+               } else {
+                       $tree = $this->substituteMarkerArray($tree, $markContentArray);
                }
 
-               if ($conf['stdWrap.']) {
-                       $content=$this->stdWrap($content, $conf['stdWrap.']);
-               }
-
-               return $content;
+               return $tree;
        }
 
        /**
-        * Rendering the cObject, SWFOBJECT
+        * Adds elements to the input $markContentArray based on the values from
+        * the fields from $fieldList found in $row
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
+        * @param       array           array with key/values being marker-strings/substitution values.
+        * @param       array           An array with keys found in the $fieldList (typically a record) which values should be moved to the $markContentArray
+        * @param       string          A list of fields from the $row array to add to the $markContentArray array. If empty all fields from $row will be added (unless they are integers)
+        * @param       boolean         If set, all values added to $markContentArray will be nl2br()'ed
+        * @param       string          Prefix string to the fieldname before it is added as a key in the $markContentArray. Notice that the keys added to the $markContentArray always start and end with "###"
+        * @param       boolean         If set, all values are passed through htmlspecialchars() - RECOMMENDED to avoid most obvious XSS and maintain XHTML compliance.
+        * @return      array           The modified $markContentArray
         */
-       public function MEDIA($conf) {
-               $content = '';
-               $flexParams = $this->stdWrap($conf['flexParams'], $conf['flexParams.']);
-               if (substr($flexParams, 0, 1) === '<') {
-                       // it is a content element
-                       $this->readFlexformIntoConf($flexParams, $conf['parameter.']);
-                       $url = $conf['parameter.']['mmFile'];
-                       $url = $this->stdWrap($url, $conf['file.']);
-               } else {
-                       // it is a TS object
-                       $url = $this->stdWrap($conf['file'], $conf['file.']);
-               }
-
-               $mode = is_file(PATH_site . $url) ? 'file' : 'url';
-               if ($mode === 'file') {
-                       $filename = $GLOBALS['TSFE']->tmpl->getFileName($url);
-                       $fileinfo = t3lib_div::split_fileref($filename);
-                       $conf['file'] = $filename;
+       public function fillInMarkerArray(array $markContentArray, array $row, $fieldList = '', $nl2br = TRUE, $prefix = 'FIELD_', $HSC = FALSE) {
+               if ($fieldList) {
+                       $fArr = t3lib_div::trimExplode(',', $fieldList, 1);
+                       foreach ($fArr as $field) {
+                               $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($row[$field]) : $row[$field];
+                       }
                } else {
-                       $conf['file'] = $this->typoLink_URL(array('parameter' => $url));
-               }
+                       if (is_array($row)) {
+                               foreach ($row as $field => $value) {
+                                       if (!t3lib_div::testInt($field)) {
+                                               if ($HSC) {
+                                                       $value = htmlspecialchars($value);
+                                               }
 
-               $renderType = $conf['renderType'];
-               if (isset($conf['parameter.']['mmRenderType'])) {
-                       $renderType = $conf['parameter.']['mmRenderType'];
-               }
-               if ($renderType === 'auto') {
-                               // default renderType is swf
-                       $renderType = 'swf';
-                       $handler = array_keys($conf['fileExtHandler.']);
-                       if (in_array($fileinfo['fileext'], $handler)) {
-                               $renderType = strtolower($conf['fileExtHandler.'][$fileinfo['fileext']]);
+                                               $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($value) : $value;
+                                       }
+                               }
                        }
                }
 
-               $forcePlayer = isset($conf['parameter.']['mmFile']) ? intval($conf['parameter.']['mmforcePlayer']) :  $conf['forcePlayer'];
-               $conf['forcePlayer'] = $forcePlayer;
+               return $markContentArray;
+       }
 
-               $conf['type'] = isset($conf['parameter.']['mmType']) ? $conf['parameter.']['mmType'] : $conf['type'];
-               $mime = $renderType . 'object';
-               $typeConf = $conf['mimeConf.'][$mime . '.'][$conf['type'] . '.'] ? $conf['mimeConf.'][$mime . '.'][$conf['type'] . '.'] : array();
-               $conf['predefined'] = array();
+       /***********************************************
+        *
+        * "stdWrap" + sub functions
+        *
+        ***********************************************/
 
-               $width = intval($conf['parameter.']['mmWidth']);
-               $height = intval($conf['parameter.']['mmHeight']);
-               if ($width) {
-                       $conf['width'] = $width;
-               } else {
-                       $conf['width'] = intval($conf['width']) ? $conf['width'] : $typeConf['defaultWidth'];
-               }
-               if ($height) {
-                       $conf['height'] = $height;
-               } else {
-                       $conf['height'] = intval($conf['height']) ? $conf['height'] : $typeConf['defaultHeight'];
-               }
-
-               if (is_array($conf['parameter.']['mmMediaOptions'])) {
-                       $params = array();
-                       foreach ($conf['parameter.']['mmMediaOptions'] as $key => $value) {
-                               if ($key == 'mmMediaCustomParameterContainer') {
-                                       foreach ($value as $val) {
-                                               //custom parameter entry
-                                               $rawTS = $val['mmParamCustomEntry'];
-                                               //read and merge
-                                               $tmp = t3lib_div::trimExplode(LF, $rawTS);
-                                               if (count($tmp)) {
-                                                       foreach ($tmp as $tsLine) {
-                                                               if (substr($tsLine, 0, 1) != '#' && $pos = strpos($tsLine, '.')) {
-                                                                       $parts[0] = substr($tsLine, 0, $pos);
-                                                                       $parts[1] = substr($tsLine, $pos + 1);
-                                                                       $valueParts = t3lib_div::trimExplode('=', $parts[1], true);
-
-                                                                       switch (strtolower($parts[0])) {
-                                                                               case 'flashvars':
-                                                                                       $conf['flashvars.'][$valueParts[0]] = $valueParts[1];
-                                                                               break;
-                                                                               case 'params':
-                                                                                       $conf['params.'][$valueParts[0]] = $valueParts[1];
-                                                                               break;
-                                                                               case 'attributes':
-                                                                                       $conf['attributes.'][$valueParts[0]] = $valueParts[1];
-                                                                               break;
-                                                                       }
-                                                               }
-                                                       }
+       /**
+        * The "stdWrap" function. This is the implementation of what is known as "stdWrap properties" in TypoScript.
+        * Basically "stdWrap" performs some processing of a value based on properties in the input $conf array(holding the TypoScript "stdWrap properties")
+        * See the link below for a complete list of properties and what they do. The order of the table with properties found in TSref (the link) follows the actual order of implementation in this function.
+        *
+        * If $this->alternativeData is an array it's used instead of the $this->data array in ->getData
+        *
+        * @param       string          Input value undergoing processing in this function. Possibly substituted by other values fetched from another source.
+        * @param       array           TypoScript "stdWrap properties".
+        * @return      string          The processed input value
+        */
+       public function stdWrap($content = '', $conf = array()) {
+               if (count($this->stdWrapHookObjects)) {
+                       foreach ($this->stdWrapHookObjects as $hookObject) {
+                               if (is_callable(array($hookObject, 'stdWrapPreProcess'))) {
+                                       $conf['stdWrapPreProcess'] = 1;
+                               }
+                               ;
+                               if (is_callable(array($hookObject, 'stdWrapOverride'))) {
+                                       $conf['stdWrapOverride'] = 1;
+                               }
+                               ;
+                               if (is_callable(array($hookObject, 'stdWrapProcess'))) {
+                                       $conf['stdWrapProcess'] = 1;
+                               }
+                               ;
+                               if (is_callable(array($hookObject, 'stdWrapPostProcess'))) {
+                                       $conf['stdWrapPostProcess'] = 1;
+                               }
+                               ;
+                       }
+               }
+               if (is_array($conf) && count($conf)) {
+                       // check, which of the available stdWrap functions is needed for the current conf Array
+                       // and keep only those but still in the same order
+                       $sortedConf = array_intersect_key($this->stdWrapOrder, $conf);
+                       // functions types that should not make use of nested stdWrap function calls to avoid conflicts with internal TypoScript used by these functions
+                       $stdWrapDisabledFunctionTypes = 'cObject,functionName,stdWrap';
+                       // additional Array to check whether a function has already been executed
+                       $isExecuted = array();
+                       // additional switch to make sure 'required', 'if' and 'fieldRequired'
+                       // will still stop rendering immediately in case they return false
+
+                       $this->stdWrapRecursionLevel++;
+                       $this->stopRendering[$this->stdWrapRecursionLevel] = false;
+
+                       // execute each funtion in the predefined order
+                       foreach ($sortedConf as $stdWrapName => $functionType) {
+                               // eliminate the second key of a pair 'key'|'key.' to make sure functions get called only once and check if rendering has been stopped
+                               if (!$isExecuted[$stdWrapName] &&
+                                               !$this->stopRendering[$this->stdWrapRecursionLevel]) {
+                                       $functionName = rtrim($stdWrapName, '.');
+                                       $functionProperties = $functionName . '.';
+                                       // if there is any code one the next level, check if it contains "official" stdWrap functions
+                                       // if yes, execute them first - will make each function stdWrap aware
+                                       // so additional stdWrap calls within the functions can be removed, since the result will be the same
+                                       // exception: the recursive stdWrap function and cObject will still be using their own stdWrap call, since it modifies the content and not a property
+                                       if (count($conf[$functionProperties]) &&
+                                                       !t3lib_div::inList($stdWrapDisabledFunctionTypes, $functionType)) {
+                                               if (array_intersect_key($this->stdWrapOrder, $conf[$functionProperties])) {
+                                                       $conf[$functionName] = $this->stdWrap($conf[$functionName], $conf[$functionProperties]);
                                                }
                                        }
-                               } elseif ($key == 'mmMediaOptionsContainer') {
-                                       foreach ($value as $val) {
-                                               if (isset($val['mmParamSet'])) {
-                                                       $pName = $val['mmParamName'];
-                                                       $pSet = $val['mmParamSet'];
-                                                       $pValue = $pSet == 2 ? $val['mmParamValue'] : ($pSet == 0 ? 'false' : 'true');
-                                                       $conf['predefined'][$pName] = $pValue;
-                                               }
+                                       // get just that part of $conf that is needed for the particular function
+                                       $singleConf = array(
+                                               $functionName => $conf[$functionName],
+                                               $functionProperties => $conf[$functionProperties]
+                                       );
+
+                                       // in this special case 'spaceBefore' and 'spaceAfter' need additional stuff from 'space.''
+                                       if ($functionName == 'spaceBefore' || $functionName == 'spaceAfter') {
+                                               $singleConf['space.'] = $conf['space.'];
+                                       }
+
+                                       // hand over the whole $conf array to the stdWrapHookObjects
+                                       if ($functionType === 'hook') {
+                                               $singleConf = $conf;
+                                       }
+                                       // check if key is still containing something, since it might have been changed by next level stdWrap before
+                                       if ((isset($conf[$functionName]) || $conf[$functionProperties]) &&
+                                                       !($functionType == 'boolean' && $conf[$functionName] === '0')) {
+                                               //add both keys - with and without the dot - to the set of executed functions
+                                               $isExecuted[$functionName] = true;
+                                               $isExecuted[$functionProperties] = true;
+                                               // call the function with the prefix stdWrap_ to make sure nobody can execute functions just by adding their name to the TS Array
+                                               $functionName = 'stdWrap_' . $functionName;
+                                               $content = $this->$functionName(
+                                                       $content,
+                                                       $singleConf
+                                               );
                                        }
                                }
                        }
-               }
 
-                       // render MEDIA
-               if ($mode == 'url' && !$forcePlayer) {
-                               // url is called direct, not with player
-                       if ($url == '' && !$conf['allowEmptyUrl']) {
-                               return '<p style="background-color: yellow;">' . $GLOBALS['TSFE']->sL('LLL:EXT:cms/locallang_ttc.xml:media.noFile', true) . '</p>';
-                       }
-                       $conf = array_merge($conf['mimeConf.']['swfobject.'], $conf);
-                       $conf[$conf['type'] . '.']['player'] = strpos($url, '://') === false ? 'http://' . $url : $url;
-                       $conf['installUrl'] = 'null';
-                       $conf['flashvars'] = array_merge((array) $conf['flashvars'], $conf['predefined']);
-               }
+                       unset($this->stopRendering[$this->stdWrapRecursionLevel]);
+                       $this->stdWrapRecursionLevel--;
 
-               switch ($renderType) {
-                       case 'swf':
-                               $conf[$conf['type'] . '.'] = array_merge($conf['mimeConf.']['swfobject.'][$conf['type'] . '.'], $typeConf);
-                               $conf = array_merge($conf['mimeConf.']['swfobject.'], $conf);
-                               unset($conf['mimeConf.']);
-                               $conf['flashvars.'] = array_merge((array) $conf['flashvars.'], $conf['predefined']);
-                               $content = $this->SWFOBJECT($conf);
-                       break;
-                       case 'qt':
-                               $conf[$conf['type'] . '.'] = array_merge($conf['mimeConf.']['swfobject.'][$conf['type'] . '.'], $typeConf);
-                               $conf = array_merge($conf['mimeConf.']['qtobject.'], $conf);
-                               unset($conf['mimeConf.']);
-                               $conf['params.'] = array_merge((array) $conf['params.'], $conf['predefined']);
-                               $content = $this->QTOBJECT($conf);
-                       break;
-                       case 'media':
-                               $paramsArray = array_merge((array) $typeConf['default.']['params.'], (array) $conf['params.'], $conf['predefined']);
-                               $conf['params']= '';
-                               foreach ($paramsArray as $key => $value) {
-                                       $conf['params'] .= $key . '=' . $value . LF;
-                               }
-                               $content = $this->MULTIMEDIA($conf);
-                       break;
-                       default:
-                               if (is_array ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['customMediaRender'])) {
-                                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['customMediaRender'] as $classRef) {
-                                               $hookObj = t3lib_div::getUserObj($classRef);
-                                               $conf['file'] = $url;
-                                               $conf['mode'] = $mode;
-                                               $content = $hookObj->customMediaRender($renderType, $conf, $this);
-                                       }
-                               }
                }
-
                return $content;
        }
 
-
        /**
-        * Rendering the cObject, SWFOBJECT
+        * stdWrap pre process hook
+        * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
+        * this hook will execute functions before any other stdWrap function can modify anything
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
+        * @param       string          Input value undergoing processing in these functions.
+        * @param       array           All stdWrap properties, not just the ones for a particular function.
+        * @return      string          The processed input value
         */
-       public function SWFOBJECT($conf) {
-               $content = '';
-               $flashvars = $params = $attributes = '';
-               $prefix = '';
-               if ($GLOBALS['TSFE']->baseUrl) {
-                       $prefix = $GLOBALS['TSFE']->baseUrl;
-               }
-               if ($GLOBALS['TSFE']->absRefPrefix) {
-                       $prefix = $GLOBALS['TSFE']->absRefPrefix;
-               };
-
-               $typeConf = $conf[$conf['type'] . '.'];
-
-                       //add SWFobject js-file
-               $GLOBALS['TSFE']->getPageRenderer()->addJsFile(TYPO3_mainDir . 'contrib/flashmedia/swfobject/swfobject.js');
-
-               $player = $this->stdWrap($conf[$conf['type'] . '.']['player'], $conf[$conf['type'] . '.']['player.']);
-               $installUrl = $conf['installUrl'] ? $conf['installUrl'] : $prefix . TYPO3_mainDir . 'contrib/flashmedia/swfobject/expressInstall.swf';
-               $filename = $this->stdWrap($conf['file'], $conf['file.']);
-               if ($filename && $conf['forcePlayer']) {
-                       if (strpos($filename, '://') !== FALSE) {
-                               $conf['flashvars.']['file'] = $filename;
-                       } else {
-                               if ($prefix) {
-                                       $conf['flashvars.']['file'] = $prefix . $filename;
-                               } else {
-                                       $conf['flashvars.']['file'] = str_repeat('../', substr_count($player, '/')) . $filename;
-                               }
-
-                       }
-               } else {
-                       $player = $filename;
-               }
-                       // Write calculated values in conf for the hook
-               $conf['player'] = $player;
-               $conf['installUrl'] = $installUrl;
-               $conf['filename'] = $filename;
-               $conf['prefix'] = $prefix;
-
-                       // merge with default parameters
-               $conf['flashvars.'] = array_merge((array) $typeConf['default.']['flashvars.'], (array) $conf['flashvars.']);
-               $conf['params.'] = array_merge((array) $typeConf['default.']['params.'], (array) $conf['params.']);
-               $conf['attributes.'] = array_merge((array) $typeConf['default.']['attributes.'], (array) $conf['attributes.']);
-               $conf['embedParams'] = 'flashvars, params, attributes';
-
-                       // Hook for manipulating the conf array, it's needed for some players like flowplayer
-               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['swfParamTransform'])) {
-                       foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['swfParamTransform'] as $classRef) {
-                               t3lib_div::callUserFunction($classRef, $conf, $this);
-                       }
+       public function stdWrap_stdWrapPreProcess($content = '', $conf = array()) {
+               foreach ($this->stdWrapHookObjects as $hookObject) {
+                       $content = $hookObject->stdWrapPreProcess($content, $conf, $this);
                }
-               if (is_array($conf['flashvars.'])) {
-                       t3lib_div::remapArrayKeys($conf['flashvars.'], $typeConf['mapping.']['flashvars.']);
-               }
-               $flashvars = 'var flashvars = ' . (count($conf['flashvars.']) ? json_encode($conf['flashvars.']) : '{}') . ';';
-
-               if (is_array($conf['params.'])) {
-                       t3lib_div::remapArrayKeys($conf['params.'], $typeConf['mapping.']['params.']);
-               }
-               $params = 'var params = ' . (count($conf['params.']) ? json_encode($conf['params.']) : '{}') . ';';
-
-               if (is_array($conf['attributes.'])) {
-                       t3lib_div::remapArrayKeys($conf['attributes.'], $typeConf['attributes.']['params.']);
-               }
-               $attributes = 'var attributes = ' . (count($conf['attributes.']) ? json_encode($conf['attributes.']) : '{}') . ';';
-
-               $flashVersion = $this->stdWrap($conf['flashVersion'], $conf['flashVersion.']);
-               if (!$flashVersion) {
-                       $flashVersion = '9';
-               }
-
-               $replaceElementIdString = uniqid('mmswf');
-               $GLOBALS['TSFE']->register['MMSWFID'] = $replaceElementIdString;
-
-               $alternativeContent = $this->stdWrap($conf['alternativeContent'], $conf['alternativeContent.']);
-
-               $layout = $this->stdWrap($conf['layout'], $conf['layout.']);
-               $layout = str_replace('###ID###', $replaceElementIdString, $layout);
-               $layout = str_replace('###SWFOBJECT###', '<div id="' . $replaceElementIdString . '">' . $alternativeContent . '</div>', $layout);
-
-               $width = $this->stdWrap($conf['width'], $conf['width.']);
-               $height = $this->stdWrap($conf['height'], $conf['height.']);
-
-               $width = $width ? $width : $conf[$conf['type'] . '.']['defaultWidth'];
-               $height = $height ? $height : $conf[$conf['type'] . '.']['defaultHeight'];
-
-
-               $embed = 'swfobject.embedSWF("' . $conf['player'] . '", "' . $replaceElementIdString . '", "' . $width . '", "' . $height . '",
-                               "' . $flashVersion . '", "' . $installUrl . '", ' . $conf['embedParams'] . ');';
-
-               $content = $layout . '
-                       <script type="text/javascript">
-                               ' . $flashvars . '
-                               ' . $params . '
-                               ' . $attributes . '
-                               ' . $embed . '
-                       </script>';
-
                return $content;
        }
 
        /**
-        * Rendering the cObject, QTOBJECT
+        * setContentToCurrent
+        * actually it just does the contrary: Sets the value of 'current' based on current content
         *
-        * @param       array           Array of TypoScript properties
-        * @return      string          Output
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for setContentToCurrent.
+        * @return      string          The processed input value
         */
-       public function QTOBJECT($conf) {
-               $content = '';
-               $params = '';
-               $prefix = '';
-               if ($GLOBALS['TSFE']->baseUrl) {
-                       $prefix = $GLOBALS['TSFE']->baseUrl;
-               }
-               if ($GLOBALS['TSFE']->absRefPrefix) {
-                       $prefix = $GLOBALS['TSFE']->absRefPrefix;
-               }
-
-               $filename = $this->stdWrap($conf['file'],$conf['file.']);
-
-               $typeConf = $conf[$conf['type'] . '.'];
-
-                       //add QTobject js-file
-               $GLOBALS['TSFE']->getPageRenderer()->addJsFile(TYPO3_mainDir . 'contrib/flashmedia/qtobject/qtobject.js');
-               $replaceElementIdString = uniqid('mmqt');
-               $GLOBALS['TSFE']->register['MMQTID'] = $replaceElementIdString;
-               $qtObject = 'QTObject' . $replaceElementIdString;
+       public function stdWrap_setContentToCurrent($content = '', $conf = array()) {
+               $this->data[$this->currentValKey] = $content;
+               return $content;
+       }
 
-                       // merge with default parameters
-               $conf['params.'] = array_merge((array) $typeConf['default.']['params.'], (array) $conf['params.']);
+       /**
+        * setCurrent
+        * Sets the value of 'current' based on the outcome of stdWrap operations
+        *
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for setCurrent.
+        * @return      string          The processed input value
+        */
+       public function stdWrap_setCurrent($content = '', $conf = array()) {
+               $this->data[$this->currentValKey] = $conf['setCurrent'];
+               return $content;
+       }
 
-               if (is_array($conf['params.'])) {
-                       t3lib_div::remapArrayKeys($conf['params.'], $typeConf['mapping.']['params.']);
-                       foreach ($conf['params.'] as $key => $value) {
-                               $params .= $qtObject . '.addParam("' .$key . '", "' . $value . '");' . LF;
-                       }
+       /**
+        * lang
+        * Translates content based on the language currently used by the FE
+        *
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for lang.
+        * @return      string          The processed input value
+        */
+       public function stdWrap_lang($content = '', $conf = array()) {
+               if (isset($conf['lang.']) && $GLOBALS['TSFE']->config['config']['language'] && isset($conf['lang.'][$GLOBALS['TSFE']->config['config']['language']])) {
+                       $content = $conf['lang.'][$GLOBALS['TSFE']->config['config']['language']];
                }
-               $params = ($params ? substr($params, 0, -2) : '') . LF . $qtObject . '.write("' . $replaceElementIdString . '");';
-
-               $alternativeContent = $this->stdWrap($conf['alternativeContent'], $conf['alternativeContent.']);
-               $layout = $this->stdWrap($conf['layout'], $conf['layout.']);
-               $layout = str_replace('###ID###', $replaceElementIdString, $layout);
-               $layout = str_replace('###QTOBJECT###', '<div id="' . $replaceElementIdString . '">' . $alternativeContent . '</div>', $layout);
-
-               $width = $this->stdWrap($conf['width'], $conf['width.']);
-               $height = $this->stdWrap($conf['height'], $conf['height.']);
-               $width = $width ? $width : $conf[$conf['type'] . '.']['defaultWidth'];
-               $height = $height ? $height : $conf[$conf['type'] . '.']['defaultHeight'];
-
-               $embed = 'var ' . $qtObject . ' = new QTObject("' . $prefix . $filename . '", "' . $replaceElementIdString . '", "' . $width . '", "' . $height . '");';
-
-               $content = $layout . '
-                       <script type="text/javascript">
-                               ' . $embed . '
-                               ' . $params . '
-                       </script>';
-
                return $content;
        }
 
-
-
-
-
-
-
-
-
-       /************************************
+       /**
+        * data
+        * Gets content from different sources based on getText functions, makes use of alternativeData, when set
         *
-        * Various helper functions for content objects:
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for data.
+        * @return      string          The processed input value
+        */
+       public function stdWrap_data($content = '', $conf = array()) {
+               $content = $this->getData($conf['data'], is_array($this->alternativeData) ? $this->alternativeData : $this->data);
+               $this->alternativeData = ''; // This must be unset directly after
+               return $content;
+       }
+
+       /**
+        * field
+        * Gets content from a DB field
         *
-        ************************************/
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for field.
+        * @return      string          The processed input value
+        */
+       public function stdWrap_field($content = '', $conf = array()) {
+               $content = $this->getFieldVal($conf['field']);
+               return $content;
+       }
 
+       /**
+        * current
+        * Gets content that has been perviously set as 'current'
+        * Can be set via setContentToCurrent or setCurrent or will be set automatically i.e. inside the split function
+        *
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for current.
+        * @return      string          The processed input value
+        */
+       public function stdWrap_current($content = '', $conf = array()) {
+               $content = $this->data[$this->currentValKey];
+               return $content;
+       }
 
        /**
-        * Converts a given config in Flexform to a conf-Array
-        * @param       string          Flexform data
-        * @param       array           Array to write the data into, by reference
-        * @param       boolean         is set if called recursive. Don't call function with this parameter, it's used inside the function only
-        * @access      public
+        * cObject
+        * Will replace the content with the value of a any official TypoScript cObject
+        * like TEXT, COA, HMENU
         *
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for cObject.
+        * @return      string          The processed input value
         */
-       public function readFlexformIntoConf($flexData, &$conf, $recursive=FALSE) {
-               if ($recursive === FALSE) {
-                       $flexData = t3lib_div::xml2array($flexData, 'T3');
-               }
+       public function stdWrap_cObject($content = '', $conf = array()) {
+               $content = $this->cObjGetSingle($conf['cObject'], $conf['cObject.'], '/stdWrap/.cObject');
+               return $content;
+       }
 
-               if (is_array($flexData)) {
-                       if (isset($flexData['data']['sDEF']['lDEF'])) {
-                               $flexData = $flexData['data']['sDEF']['lDEF'];
-                       }
+       /**
+        * numRows
+        * Counts the number of returned records of a DB operation
+        * makes use of select internally
+        *
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for numRows.
+        * @return      string          The processed input value
+        */
+       public function stdWrap_numRows($content = '', $conf = array()) {
+               $content = $this->numRows($conf['numRows.']);
+               return $content;
+       }
 
-                       foreach ($flexData as $key => $value) {
-                               if (is_array($value['el']) && count($value['el']) > 0) {
-                                       foreach ($value['el'] as $ekey => $element) {
-                                               if (isset($element['vDEF'])) {
-                                                       $conf[$ekey] =  $element['vDEF'];
-                                               } else {
-                                                       if(is_array($element)) {
-                                                               $this->readFlexformIntoConf($element, $conf[$key][key($element)][$ekey], TRUE);
-                                                       } else {
-                                                               $this->readFlexformIntoConf($element, $conf[$key][$ekey], TRUE);
-                                                       }
-                                               }
-                                       }
-                               } else {
-                                       $this->readFlexformIntoConf($value['el'], $conf[$key], TRUE);
-                               }
-                               if ($value['vDEF']) {
-                                       $conf[$key] = $value['vDEF'];
-                               }
-                       }
-               }
+       /**
+        * filelist
+        * Will create a list of files based on some additional parameters
+        *
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for filelist.
+        * @return      string          The processed input value
+        */
+       public function stdWrap_filelist($content = '', $conf = array()) {
+               $content = $this->filelist($conf['filelist']);
+               return $content;
        }
 
+       /**
+        * preUserFunc
+        * Will execute a user public function before the content will be modified by any other stdWrap function
+        *
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for preUserFunc.
+        * @return      string          The processed input value
+        */
+       public function stdWrap_preUserFunc($content = '', $conf = array()) {
+               $content = $this->callUserFunction($conf['preUserFunc'], $conf['preUserFunc.'], $content);
+               return $content;
+       }
 
        /**
-        * Returns all parents of the given PID (Page UID) list
+        * stdWrap override hook
+        * can be used by extensions authors to modify the behaviour of stdWrap functions to their needs
+        * this hook will execute functions on existing content but still before the content gets modified or replaced
         *
-        * @param       string          A list of page Content-Element PIDs (Page UIDs) / stdWrap
-        * @param       array           stdWrap array for the list
-        * @return      string          A list of PIDs
-        * @access private
+        * @param       string          Input value undergoing processing in these functions.
+        * @param       array           All stdWrap properties, not just the ones for a particular function.
+        * @return      string          The processed input value
         */
-       function getSlidePids($pidList, $pidConf)       {
-               $pidList = trim($this->stdWrap($pidList,$pidConf));
-               if (!strcmp($pidList,''))       {
-                       $pidList = 'this';
+       public function stdWrap_stdWrapOverride($content = '', $conf = array()) {
+               foreach ($this->stdWrapHookObjects as $hookObject) {
+                       $content = $hookObject->stdWrapOverride($content, $conf, $this);
                }
-               if (trim($pidList))     {
-                       $listArr = t3lib_div::intExplode(',',str_replace('this',$GLOBALS['TSFE']->contentPid,$pidList));
-                       $listArr = $this->checkPidArray($listArr);
-               }
-               $pidList = array();
-               if (is_array($listArr)&&count($listArr))        {
-                       foreach ($listArr as $uid)      {
-                               $page = $GLOBALS['TSFE']->sys_page->getPage($uid);
-                               if (!$page['is_siteroot'])      {
-                                       $pidList[] = $page['pid'];
-                               }
-                       }
-               }
-               return implode(',', $pidList);
+               return $content;
        }
 
        /**
-        * Returns a default value for a form field in the FORM cObject.
-        * Page CANNOT be cached because that would include the inserted value for the current user.
+        * override
+        * Will override the current value of content with its own value'
         *
-        * @param       boolean         If noValueInsert OR if the no_cache flag for this page is NOT set, the original default value is returned.
-        * @param       string          $fieldName: The POST var name to get default value for
-        * @param       string          $defaultVal: The current default value
-        * @return      string          The default value, either from INPUT var or the current default, based on whether caching is enabled or not.
-        * @access private
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for override.
+        * @return      string          The processed input value
         */
-       function getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal) {
-               if (!$GLOBALS['TSFE']->no_cache || (!isset($_POST[$fieldName]) && !isset($_GET[$fieldName])) || $noValueInsert) {
-                       return $defaultVal;
-               } else {
-                       return t3lib_div::_GP($fieldName);
+       public function stdWrap_override($content = '', $conf = array()) {
+               if (trim($conf['override'])) {
+                       $content = $conf['override'];
                }
+               return $content;
        }
 
        /**
-        * Returns a <img> tag with the image file defined by $file and processed according to the properties in the TypoScript array.
-        * Mostly this function is a sub-function to the IMAGE function which renders the IMAGE cObject in TypoScript. This function is called by "$this->cImage($conf['file'],$conf);" from IMAGE().
+        * preIfEmptyListNum
+        * Gets a value off a CSV list before the following ifEmpty check
+        * Makes sure that the result of ifEmpty will be true in case the CSV does not contain a value at the position given by preIfEmptyListNum
         *
-        * @param       string          File TypoScript resource
-        * @param       array           TypoScript configuration properties
-        * @return      string          <img> tag, (possibly wrapped in links and other HTML) if any image found.
-        * @access private
-        * @see IMAGE()
+        * @param       string          Input value undergoing processing in this function.
+        * @param       array           stdWrap properties for preIfEmptyListNum.
+        * @return      string          The processed input value
         */
-       function cImage($file,$conf) {
-               $info = $this->getImgResource($file,$conf['file.']);
-               $GLOBALS['TSFE']->lastImageInfo=$info;
-               if (is_array($info))    {
-                       $info[3] = t3lib_div::png_to_gif_by_imagemagick($info[3]);
-                       $GLOBALS['TSFE']->imagesOnPage[]=$info[3];              // This array is used to collect the image-refs on the page...
+       public function stdWrap_preIfEmptyListNum($content = '', $conf = array()) {
+               $content = $this->listNum($content, $conf['preIfEmptyListNum'], $conf['preIfEmptyListNum.']['splitChar']);
+               return $content;
+       }
 
-                       if (!strlen($conf['altText']) && !is_array($conf['altText.']))  {       // Backwards compatible:
-                               if ($conf['altText'] || $conf['altText.']) {
-                                       $GLOBALS['TSFE']->logDe