Fixed issue #2714: In RTE htmlArea, unable to do an internal link with several parameters
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_tstemplate.php
index 28461b4..6e3da80 100755 (executable)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 1999-2008 Kasper Skaarhoj (kasperYYYY@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
  *
  *
  *
  *
  *
  *
- *  107: class t3lib_TStemplate
- *  209:     function init()
- *  247:     function getCurrentPageData()
- *  264:     function matching($cc)
- *  288:     function start($theRootLine)
+ *  109: class t3lib_TStemplate
+ *  211:     function init()
+ *  249:     function getCurrentPageData()
+ *  266:     function matching($cc)
+ *  290:     function start($theRootLine)
  *
  *              SECTION: Fetching TypoScript code text for the Template Hierarchy
  *
  *              SECTION: Fetching TypoScript code text for the Template Hierarchy
- *  404:     function runThroughTemplates($theRootLine,$start_template_uid=0)
- *  451:     function processTemplate($row, $idList,$pid,$templateID='',$templateParent='')
- *  566:     function includeStaticTypoScriptSources($idList,$templateID,$pid,$row)
- *  627:     function addExtensionStatics($idList,$templateID,$pid,$row)
- *  660:     function prependStaticExtra($subrow)
+ *  406:     function runThroughTemplates($theRootLine,$start_template_uid=0)
+ *  459:     function processTemplate($row, $idList,$pid,$templateID='',$templateParent='')
+ *  580:     function includeStaticTypoScriptSources($idList,$templateID,$pid,$row)
+ *  642:     function addExtensionStatics($idList,$templateID,$pid,$row)
+ *  675:     function prependStaticExtra($subrow)
+ *  688:     function versionOL(&$row)
  *
  *              SECTION: Parsing TypoScript code text from Template Records into PHP array
  *
  *              SECTION: Parsing TypoScript code text from Template Records into PHP array
- *  696:     function generateConfig()
- *  862:     function procesIncludes()
- *  886:     function mergeConstantsFromPageTSconfig($constArray)
- *  915:     function flattenSetup($setupArray, $prefix, $resourceFlag)
- *  939:     function substituteConstants($all)
+ *  725:     function generateConfig()
+ *  891:     function procesIncludes()
+ *  915:     function mergeConstantsFromPageTSconfig($constArray)
+ *  944:     function flattenSetup($setupArray, $prefix, $resourceFlag)
+ *  968:     function substituteConstants($all)
+ *  991:     function substituteConstantsCallBack($matches)
  *
  *              SECTION: Various API functions, used from elsewhere in the frontend classes
  *
  *              SECTION: Various API functions, used from elsewhere in the frontend classes
- *  977:     function splitConfArray($conf,$splitCount)
- * 1054:     function getFileName($fileFromSetup)
- * 1111:     function extractFromResources($res,$file)
- * 1139:     function checkFile($name,$menuArr)
- * 1156:     function printTitle($title,$no_title=0,$titleFirst=0)
- * 1179:     function fileContent($fName)
- * 1199:     function wrap($content,$wrap)
- * 1213:     function removeQueryString($url)
- * 1230:     function sortedKeyList($setupArr, $acceptOnlyProperties=FALSE)
+ * 1022:     function splitConfArray($conf,$splitCount)
+ * 1099:     function getFileName($fileFromSetup)
+ * 1156:     function extractFromResources($res,$file)
+ * 1184:     function checkFile($name,$menuArr)
+ * 1201:     function printTitle($title,$no_title=0,$titleFirst=0)
+ * 1224:     function fileContent($fName)
+ * 1244:     function wrap($content,$wrap)
+ * 1258:     function removeQueryString($url)
+ * 1275:     function sortedKeyList($setupArr, $acceptOnlyProperties=FALSE)
  *
  *              SECTION: Functions for creating links
  *
  *              SECTION: Functions for creating links
- * 1277:     function linkData($page,$oTarget,$no_cache,$script,$overrideArray='',$addParams='',$typeOverride='')
- * 1396:     function getFromMPmap($pageId=0)
- * 1432:     function initMPmap_create($id,$MP_array=array(),$level=0)
+ * 1322:     function linkData($page,$oTarget,$no_cache,$script,$overrideArray='',$addParams='',$typeOverride='')
+ * 1449:     function getFromMPmap($pageId=0)
+ * 1485:     function initMPmap_create($id,$MP_array=array(),$level=0)
  *
  *
- * TOTAL FUNCTIONS: 26
+ * TOTAL FUNCTIONS: 28
  * (This index is automatically created/updated by the extension "extdeveval")
  *
  */
  * (This index is automatically created/updated by the extension "extdeveval")
  *
  */
@@ -121,7 +123,8 @@ class t3lib_TStemplate      {
        var $ext_constants_BRP=0;
        var $ext_config_BRP=0;
        var $ext_editorcfg_BRP=0;
        var $ext_constants_BRP=0;
        var $ext_config_BRP=0;
        var $ext_editorcfg_BRP=0;
-       var $ext_regLinenumbers=FALSE;
+       var $ext_regLinenumbers=false;
+       var $ext_regComments=false;
 
                // Constants:
        var $uplPath = 'uploads/tf/';
 
                // Constants:
        var $uplPath = 'uploads/tf/';
@@ -132,7 +135,6 @@ class t3lib_TStemplate      {
        var $whereClause = '';                          // This MUST be initialized by the init() function
        var $debug = 0;
        var $allowedPaths = array();            // This is the only paths (relative!!) that are allowed for resources in TypoScript. Should all be appended with '/'. You can extend these by the global array TYPO3_CONF_VARS. See init() function.
        var $whereClause = '';                          // This MUST be initialized by the init() function
        var $debug = 0;
        var $allowedPaths = array();            // This is the only paths (relative!!) that are allowed for resources in TypoScript. Should all be appended with '/'. You can extend these by the global array TYPO3_CONF_VARS. See init() function.
-       var $currentPageData = '';                      // Contains "currentPageData" when rendered/fetched from cache. See getCurrentPageData()
        var $simulationHiddenOrTime=0;          // See init(); Set if preview of some kind is enabled.
 
        var $loaded = 0;                                        // Set, if the TypoScript template structure is loaded and OK, see ->start()
        var $simulationHiddenOrTime=0;          // See init(); Set if preview of some kind is enabled.
 
        var $loaded = 0;                                        // Set, if the TypoScript template structure is loaded and OK, see ->start()
@@ -151,7 +153,8 @@ class t3lib_TStemplate      {
                'config.' => Array (
                        'extTarget' => '_top',
                        'stat' => 1,
                'config.' => Array (
                        'extTarget' => '_top',
                        'stat' => 1,
-                       'stat_typeNumList' => '0,1'
+                       'stat_typeNumList' => '0,1',
+                       'uniqueLinkVars' => 1
                )
        );
        var $flatSetup = Array (
                )
        );
        var $flatSetup = Array (
@@ -207,16 +210,16 @@ class t3lib_TStemplate    {
         * @see tslib_fe::initTemplate()
         */
        function init() {
         * @see tslib_fe::initTemplate()
         */
        function init() {
-                       // $this->whereClause is used only to select templates from sys_template.
-                       // $GLOBALS['SIM_EXEC_TIME'] is used so that we're able to simulate a later time as a test...
+                       // $this->whereClause is used only to select templates from sys_template.
+                       // $GLOBALS['SIM_ACCESS_TIME'] is used so that we're able to simulate a later time as a test...
                $this->whereClause='AND deleted=0 ';
                if (!$GLOBALS['TSFE']->showHiddenRecords)       {
                        $this->whereClause.='AND hidden=0 ';
                }
                $this->whereClause='AND deleted=0 ';
                if (!$GLOBALS['TSFE']->showHiddenRecords)       {
                        $this->whereClause.='AND hidden=0 ';
                }
-               if ($GLOBALS['TSFE']->showHiddenRecords || $GLOBALS['SIM_EXEC_TIME']!=$GLOBALS['EXEC_TIME'])    {       // Set the simulation flag, if simulation is detected!
+               if ($GLOBALS['TSFE']->showHiddenRecords || $GLOBALS['SIM_ACCESS_TIME']!=$GLOBALS['ACCESS_TIME'])        {       // Set the simulation flag, if simulation is detected!
                        $this->simulationHiddenOrTime=1;
                }
                        $this->simulationHiddenOrTime=1;
                }
-               $this->whereClause.= 'AND (starttime<='.$GLOBALS['SIM_EXEC_TIME'].') AND (endtime=0 OR endtime>'.$GLOBALS['SIM_EXEC_TIME'].')';
+               $this->whereClause.= 'AND (starttime<='.$GLOBALS['SIM_ACCESS_TIME'].') AND (endtime=0 OR endtime>'.$GLOBALS['SIM_ACCESS_TIME'].')';
                if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'])       {
                        $this->menuclasses='tmenu,jsmenu,gmenu';
                }
                if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'])       {
                        $this->menuclasses='tmenu,jsmenu,gmenu';
                }
@@ -237,29 +240,29 @@ class t3lib_TStemplate    {
         *
         * NOTE about currentPageData:
         * It holds information about the TypoScript conditions along with the list of template uid's which is used on the page.
         *
         * NOTE about currentPageData:
         * It holds information about the TypoScript conditions along with the list of template uid's which is used on the page.
-        * In the getFromCache function in TSFE, currentPageData is used to evaluate if there is a template and if the matching conditions are alright
+        * In the getFromCache function in TSFE, currentPageData is used to evaluate if there is a template and if the matching conditions are alright.
         * Unfortunately this does not take into account if the templates in the rowSum of currentPageData has changed composition, eg. due to hidden fields or start/end time.
         * Unfortunately this does not take into account if the templates in the rowSum of currentPageData has changed composition, eg. due to hidden fields or start/end time.
-        * So if a template is hidden or times out, it'll not be discovered unless the page is regenerated - at least the this->start function must be called, because this will make a new portion of data in currentPageData string
+        * So if a template is hidden or times out, it'll not be discovered unless the page is regenerated - at least the this->start function must be called, because this will make a new portion of data in currentPageData string.
         *
         *
-        * @return      mixed           The array $this->currentPageData if found cached in "cache_pagesection". If the string "none" was returned it means the array must be generated and stored in the cache-table
-        * @see start(), t3lib_fe::getFromCache()
+        * @return      array           Returns the unmatched array $currentPageData if found cached in "cache_pagesection". Otherwise false is returned which means that the array must be generated and stored in the cache-table
+        * @see start(), tslib_fe::getFromCache()
         */
        function getCurrentPageData()   {
                $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('content', 'cache_pagesection', 'page_id='.intval($GLOBALS['TSFE']->id).' AND mpvar_hash='.t3lib_div::md5int($GLOBALS['TSFE']->MP));
                if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
         */
        function getCurrentPageData()   {
                $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('content', 'cache_pagesection', 'page_id='.intval($GLOBALS['TSFE']->id).' AND mpvar_hash='.t3lib_div::md5int($GLOBALS['TSFE']->MP));
                if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
-                       $this->currentPageData = unserialize($row['content']);
+                       $currentPageData = unserialize($row['content']);
                } else {
                } else {
-                       $this->currentPageData = 'none';
+                       $currentPageData = false;
                }
                }
-               return $this->currentPageData;
+               return $currentPageData;        // 2008-02-03 / Stucki: Notice that $this->currentPageData is not used anymore!
        }
 
        /**
         * Fetches data about which TypoScript-matches there are at this page. Then it performs a matchingtest.
         *
        }
 
        /**
         * Fetches data about which TypoScript-matches there are at this page. Then it performs a matchingtest.
         *
-        * @param       array           An array with three keys, "all", "rowSum" and "rootLine" - all coming from the $this->currentPageData array
+        * @param       array           An array with three keys, "all", "rowSum" and "rootLine" - all coming from the "currentPageData" array
         * @return      array           The input array but with a new key added, "match" which contains the items from the "all" key which when passed to tslib_matchCondition returned true.
         * @return      array           The input array but with a new key added, "match" which contains the items from the "all" key which when passed to tslib_matchCondition returned true.
-        * @see t3lib_matchCondition, t3lib_fe::getFromCache()
+        * @see t3lib_matchCondition, tslib_fe::getFromCache()
         */
        function matching($cc)  {
                if (is_array($cc['all']))       {
         */
        function matching($cc)  {
                if (is_array($cc['all']))       {
@@ -278,54 +281,67 @@ class t3lib_TStemplate    {
 
        /**
         * This is all about fetching the right TypoScript template structure. If it's not cached then it must be generated and cached!
 
        /**
         * This is all about fetching the right TypoScript template structure. If it's not cached then it must be generated and cached!
-        * The method traverse the rootline structure from out to in, fetches the hierarchy of template records and based on this either finds the cached TypoScript template structure or parses the template and caches it for next time.
-        * Sets $this->setup to the parsed TypoScript Template array
+        * The method traverses the rootline structure from out to in, fetches the hierarchy of template records and based on this either finds the cached TypoScript template structure or parses the template and caches it for next time.
+        * Sets $this->setup to the parsed TypoScript template array
         *
         * @param       array           The rootline of the current page (going ALL the way to tree root)
         * @return      void
         * @see tslib_fe::getConfigArray()
         */
        function start($theRootLine)    {
         *
         * @param       array           The rootline of the current page (going ALL the way to tree root)
         * @return      void
         * @see tslib_fe::getConfigArray()
         */
        function start($theRootLine)    {
-               if (is_array($theRootLine))     {
-                       $setupData='';
-                       $cc=Array();
-                       $hash='';
+               if (is_array($theRootLine)) {
+                       $setupData = '';
+                       $hash = '';
+                       $isCached = false;      // Flag that indicates that the existing data in cache_pagesection could be used (this is the case if $TSFE->all is set, and the rowSum still matches). Based on this we decide if cache_pagesection needs to be updated...
                        $this->runThroughTemplates($theRootLine);
 
                        $this->runThroughTemplates($theRootLine);
 
-                               // Getting the currentPageData if not already found
-                       if (!$this->currentPageData)    {
-                               $this->getCurrentPageData();
+                       if ($GLOBALS['TSFE']->all) {
+                               $cc = $GLOBALS['TSFE']->all;
+
+                                       // The two rowSums must NOT be different from each other - which they will be if start/endtime or hidden has changed!
+                               if (strcmp(serialize($this->rowSum),serialize($cc['rowSum']))) {
+                                       unset($cc);     // If the two rowSums differ, we need to re-make the current page data and therefore clear the existing values.
+                               } else {
+                                               // If $TSFE->all contains valid data, we don't need to update cache_pagesection (because this data was fetched from there already)
+                                       if (!strcmp(serialize($this->rootLine),serialize($cc['rootLine']))) {
+                                               $isCached = true;
+                                       }
+                                               // When the data is serialized below (ROWSUM hash), it must not contain the rootline by concept. So this must be removed (and added again later)...
+                                       unset($cc['rootLine']);
+                               }
                        }
 
                                // This is about getting the hash string which is used to fetch the cached TypoScript template.
                        }
 
                                // This is about getting the hash string which is used to fetch the cached TypoScript template.
-                               // If there was some cached currentPageData that's good (it gives us the hash),
-                               // However if the actual rowSum and the rowSum of currentPageData is different from each other, thats a problem, and we should re-make the current page data.
-                       if (is_array($this->currentPageData) &&
-                               !strcmp(serialize($this->rowSum), serialize($this->currentPageData['rowSum']))  // The two ROWsums must NOT be different from each other - which they will be if start/endtime or hidden has changed!
-                       )       {
-                                       // If currentPageData was actually there, we match the result...
-                               $cc['all'] = $this->currentPageData['all'];
-                               $cc['rowSum'] = $this->currentPageData['rowSum'];
-                               $cc = $this->matching($cc);
+                               // If there was some cached currentPageData ($cc) then that's good (it gives us the hash).
+                       if (is_array($cc)) {
+                                       // If currentPageData was actually there, we match the result (if this wasn't done already in $TSFE->getFromCache()...)
+                               if (!$cc['match']) {
+                                               // TODO: check if this can ever be the case - otherwise remove
+                                       $cc = $this->matching($cc);
+                                       ksort($cc);
+                               }
                                $hash = md5(serialize($cc));
                        } else {
                                $hash = md5(serialize($cc));
                        } else {
-                                       // If currentPageData was not there, we first find $rowSum (freshly generated). After that we try to see, if rowSum is stored with a list of all matching-parameters. If so we match the result
+                                       // If currentPageData was not there, we first find $rowSum (freshly generated). After that we try to see, if it is stored with a list of all conditions. If so we match the result.
                                $rowSumHash = md5('ROWSUM:'.serialize($this->rowSum));
                                $result = t3lib_pageSelect::getHash($rowSumHash, 0);
                                $rowSumHash = md5('ROWSUM:'.serialize($this->rowSum));
                                $result = t3lib_pageSelect::getHash($rowSumHash, 0);
-                               if ($result)    {
+
+                               if ($result) {
+                                       $cc = array();
                                        $cc['all'] = unserialize($result);
                                        $cc['rowSum'] = $this->rowSum;
                                        $cc = $this->matching($cc);
                                        $cc['all'] = unserialize($result);
                                        $cc['rowSum'] = $this->rowSum;
                                        $cc = $this->matching($cc);
+                                       ksort($cc);
                                        $hash = md5(serialize($cc));
                                }
                        }
 
                                        $hash = md5(serialize($cc));
                                }
                        }
 
-                       if ($hash)      {
+                       if ($hash) {
                                        // Get TypoScript setup array
                                $setupData = t3lib_pageSelect::getHash($hash, 0);
                        }
 
                                        // Get TypoScript setup array
                                $setupData = t3lib_pageSelect::getHash($hash, 0);
                        }
 
-                       if ($hash && $setupData && !$this->forceTemplateParsing)                {
+                       if ($setupData && !$this->forceTemplateParsing) {
                                        // If TypoScript setup structure was cached we unserialize it here:
                                $this->setup = unserialize($setupData);
                        } else {
                                        // If TypoScript setup structure was cached we unserialize it here:
                                $this->setup = unserialize($setupData);
                        } else {
@@ -333,10 +349,11 @@ class t3lib_TStemplate    {
                                $this->generateConfig();
 
                                        // This stores the template hash thing
                                $this->generateConfig();
 
                                        // This stores the template hash thing
-                               $cc=Array();
-                               $cc['all']=$this->sections;     // All sections in the template at this point is found
-                               $cc['rowSum']=$this->rowSum;    // The line of templates is collected
+                               $cc = array();
+                               $cc['all'] = $this->sections;   // All sections in the template at this point is found
+                               $cc['rowSum'] = $this->rowSum;  // The line of templates is collected
                                $cc = $this->matching($cc);
                                $cc = $this->matching($cc);
+                               ksort($cc);
 
                                $hash = md5(serialize($cc));
 
 
                                $hash = md5(serialize($cc));
 
@@ -346,23 +363,30 @@ class t3lib_TStemplate    {
                                if ($this->tt_track)    $GLOBALS['TT']->setTSlogMessage('TS template size, serialized: '.strlen(serialize($this->setup)).' bytes');
 
                                $rowSumHash = md5('ROWSUM:'.serialize($this->rowSum));
                                if ($this->tt_track)    $GLOBALS['TT']->setTSlogMessage('TS template size, serialized: '.strlen(serialize($this->setup)).' bytes');
 
                                $rowSumHash = md5('ROWSUM:'.serialize($this->rowSum));
-                               t3lib_pageSelect::storeHash($rowSumHash, serialize($cc['all']), 'TMPL CONDITIONS - AL');
+                               t3lib_pageSelect::storeHash($rowSumHash, serialize($cc['all']), 'TMPL CONDITIONS - ALL');
                        }
                                // Add rootLine
                        $cc['rootLine'] = $this->rootLine;
                        }
                                // Add rootLine
                        $cc['rootLine'] = $this->rootLine;
-                               // Make global and save.
-                       $GLOBALS['TSFE']->all=$cc;
+                       ksort($cc);
+
+                               // Make global and save
+                       $GLOBALS['TSFE']->all = $cc;
+
+                               // Matching must be executed for every request, so this must never be part of the pagesection cache!
+                       unset($cc['match']);
 
 
-                       if (!$this->simulationHiddenOrTime)     {       // Only save currentPageData, if we're not simulating by hidden/starttime/endtime
-                               $insertFields = array(
-                                       'page_id' => intval($GLOBALS['TSFE']->id),
-                                       'mpvar_hash' => t3lib_div::md5int($GLOBALS['TSFE']->MP),
+                       if (!$isCached && !$this->simulationHiddenOrTime && !$GLOBALS['TSFE']->no_cache) {      // Only save the data if we're not simulating by hidden/starttime/endtime
+                               $dbFields = array(
                                        'content' => serialize($cc),
                                        'tstamp' => $GLOBALS['EXEC_TIME']
                                );
                                        'content' => serialize($cc),
                                        'tstamp' => $GLOBALS['EXEC_TIME']
                                );
-                               $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pagesection', 'page_id='.intval($GLOBALS['TSFE']->id).' AND mpvar_hash='.t3lib_div::md5int($GLOBALS['TSFE']->MP));
-
-                               $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_pagesection', $insertFields);
+                               $mpvar_hash = t3lib_div::md5int($GLOBALS['TSFE']->MP);
+                               $GLOBALS['TYPO3_DB']->exec_UPDATEquery('cache_pagesection', 'page_id=' . intval($GLOBALS['TSFE']->id) . ' AND mpvar_hash=' . $mpvar_hash, $dbFields);
+                               if ($GLOBALS['TYPO3_DB']->sql_affected_rows() == 0) {
+                                       $dbFields['page_id'] = intval($GLOBALS['TSFE']->id);
+                                       $dbFields['mpvar_hash'] = $mpvar_hash;
+                                       $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_pagesection', $dbFields);
+                               }
                        }
                                // If everything OK.
                        if ($this->rootId && $this->rootLine && $this->setup)   {
                        }
                                // If everything OK.
                        if ($this->rootId && $this->rootLine && $this->setup)   {
@@ -416,8 +440,11 @@ class t3lib_TStemplate     {
                                $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'uid='.intval($this->nextLevel).' '.$this->whereClause);
                                $this->nextLevel = 0;
                                if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
                                $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'uid='.intval($this->nextLevel).' '.$this->whereClause);
                                $this->nextLevel = 0;
                                if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
-                                       $this->processTemplate($row,'sys_'.$row['uid'],$this->absoluteRootLine[$a]['uid'],'sys_'.$row['uid']);
-                                       $this->outermostRootlineIndexWithTemplate=$a;
+                                       $this->versionOL($row);
+                                       if (is_array($row))     {
+                                               $this->processTemplate($row,'sys_'.$row['uid'],$this->absoluteRootLine[$a]['uid'],'sys_'.$row['uid']);
+                                               $this->outermostRootlineIndexWithTemplate=$a;
+                                       }
                                }
                                $GLOBALS['TYPO3_DB']->sql_free_result($res);
                        }
                                }
                                $GLOBALS['TYPO3_DB']->sql_free_result($res);
                        }
@@ -428,8 +455,11 @@ class t3lib_TStemplate     {
 
                        $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'pid='.intval($this->absoluteRootLine[$a]['uid']).$addC.' '.$this->whereClause,'','sorting',1);
                        if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
 
                        $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'pid='.intval($this->absoluteRootLine[$a]['uid']).$addC.' '.$this->whereClause,'','sorting',1);
                        if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
-                               $this->processTemplate($row,'sys_'.$row['uid'],$this->absoluteRootLine[$a]['uid'],'sys_'.$row['uid']);
-                               $this->outermostRootlineIndexWithTemplate=$a;
+                               $this->versionOL($row);
+                               if (is_array($row))     {
+                                       $this->processTemplate($row,'sys_'.$row['uid'],$this->absoluteRootLine[$a]['uid'],'sys_'.$row['uid']);
+                                       $this->outermostRootlineIndexWithTemplate=$a;
+                               }
                        }
                        $GLOBALS['TYPO3_DB']->sql_free_result($res);
                        $this->rootLine[] = $this->absoluteRootLine[$a];
                        }
                        $GLOBALS['TYPO3_DB']->sql_free_result($res);
                        $this->rootLine[] = $this->absoluteRootLine[$a];
@@ -486,7 +516,10 @@ class t3lib_TStemplate     {
                                if ($id && !t3lib_div::inList($idList,'sys_'.$id))      {       // if $id is not allready included ...
                                        $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'uid='.$id.' '.$this->whereClause);
                                        if ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {       // there was a template, then we fetch that
                                if ($id && !t3lib_div::inList($idList,'sys_'.$id))      {       // if $id is not allready included ...
                                        $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'uid='.$id.' '.$this->whereClause);
                                        if ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {       // there was a template, then we fetch that
-                                               $this->processTemplate($subrow,$idList.',sys_'.$id,$pid, 'sys_'.$id,$templateID);
+                                               $this->versionOL($subrow);
+                                               if (is_array($subrow))  {
+                                                       $this->processTemplate($subrow,$idList.',sys_'.$id,$pid, 'sys_'.$id,$templateID);
+                                               }
                                        }
                                        $GLOBALS['TYPO3_DB']->sql_free_result($res);
                                }
                                        }
                                        $GLOBALS['TYPO3_DB']->sql_free_result($res);
                                }
@@ -496,7 +529,10 @@ class t3lib_TStemplate     {
                                        if (!t3lib_div::inList($idList,'sys_'.$id))     {       // if $id is not allready included ...
                                                $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'uid='.intval($id).' '.$this->whereClause);
                                                if ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {       // there was a template, then we fetch that
                                        if (!t3lib_div::inList($idList,'sys_'.$id))     {       // if $id is not allready included ...
                                                $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_template', 'uid='.intval($id).' '.$this->whereClause);
                                                if ($subrow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {       // there was a template, then we fetch that
-                                                       $this->processTemplate($subrow,$idList.',sys_'.$id,$pid, 'sys_'.$id,$templateID);
+                                                       $this->versionOL($subrow);
+                                                       if (is_array($subrow))  {
+                                                               $this->processTemplate($subrow,$idList.',sys_'.$id,$pid, 'sys_'.$id,$templateID);
+                                                       }
                                                }
                                                $GLOBALS['TYPO3_DB']->sql_free_result($res);
                                        }
                                                }
                                                $GLOBALS['TYPO3_DB']->sql_free_result($res);
                                        }
@@ -598,6 +634,7 @@ class t3lib_TStemplate      {
                                                                'config'=>              @is_file($ISF_filePath.'setup.txt')             ?t3lib_div::getUrl($ISF_filePath.'setup.txt'):'',
                                                                'editorcfg'=>   @is_file($ISF_filePath.'editorcfg.txt') ?t3lib_div::getUrl($ISF_filePath.'editorcfg.txt'):'',
                                                                'include_static'=>      @is_file($ISF_filePath.'include_static.txt')?implode(',',array_unique(t3lib_div::intExplode(',',t3lib_div::getUrl($ISF_filePath.'include_static.txt')))):'',
                                                                'config'=>              @is_file($ISF_filePath.'setup.txt')             ?t3lib_div::getUrl($ISF_filePath.'setup.txt'):'',
                                                                'editorcfg'=>   @is_file($ISF_filePath.'editorcfg.txt') ?t3lib_div::getUrl($ISF_filePath.'editorcfg.txt'):'',
                                                                'include_static'=>      @is_file($ISF_filePath.'include_static.txt')?implode(',',array_unique(t3lib_div::intExplode(',',t3lib_div::getUrl($ISF_filePath.'include_static.txt')))):'',
+                                                               'include_static_file'=> @is_file($ISF_filePath.'include_static_file.txt')?implode(',',array_unique(explode(',',t3lib_div::getUrl($ISF_filePath.'include_static_file.txt')))):'',
                                                                'title' =>              $ISF_file,
                                                                'uid' =>                $mExtKey
                                                        );
                                                                'title' =>              $ISF_file,
                                                                'uid' =>                $mExtKey
                                                        );
@@ -664,6 +701,20 @@ class t3lib_TStemplate     {
                return $subrow;
        }
 
                return $subrow;
        }
 
+       /**
+        * Creating versioning overlay of a sys_template record. This will use either frontend or backend overlay functionality depending on environment.
+        *
+        * @param       array           Row to overlay.
+        * @return      void            Row is passed by reference.
+        */
+       function versionOL(&$row)       {
+               if (is_object($GLOBALS['TSFE']))        {       // Frontend:
+                       $GLOBALS['TSFE']->sys_page->versionOL('sys_template',$row);
+               } else {        // Backend:
+                       t3lib_BEfunc::workspaceOL('sys_template',$row);
+               }
+       }
+
 
 
 
 
 
 
@@ -742,6 +793,7 @@ class t3lib_TStemplate      {
                $config = t3lib_div::makeInstance('t3lib_TSparser');
                $config->breakPointLN = intval($this->ext_config_BRP);
                $config->regLinenumbers = $this->ext_regLinenumbers;
                $config = t3lib_div::makeInstance('t3lib_TSparser');
                $config->breakPointLN = intval($this->ext_config_BRP);
                $config->regLinenumbers = $this->ext_regLinenumbers;
+               $config->regComments = $this->ext_regComments;
                $config->setup = $this->setup;
 
                        // Transfer information about conditions found in "Constants" and which of them returned true.
                $config->setup = $this->setup;
 
                        // Transfer information about conditions found in "Constants" and which of them returned true.
@@ -768,7 +820,7 @@ class t3lib_TStemplate      {
                                $constLen=t3lib_div::intInRange(strcspn($constVal,'}'),0,50);
                                $theConstList[]='{$'.substr($constVal,0,$constLen+1);
                        }
                                $constLen=t3lib_div::intInRange(strcspn($constVal,'}'),0,50);
                                $theConstList[]='{$'.substr($constVal,0,$constLen+1);
                        }
-                       if ($this->tt_track)    $GLOBALS['TT']->setTSlogMessage(implode(',',$theConstList).': Constants may remain un-substituted!!',2);
+                       if ($this->tt_track)    $GLOBALS['TT']->setTSlogMessage(implode(', ',$theConstList).': Constants may remain un-substituted!!',2);
                }
 
                        // Logging the textual size of the TypoScript Setup field text with all constants substituted:
                }
 
                        // Logging the textual size of the TypoScript Setup field text with all constants substituted:
@@ -938,15 +990,31 @@ class t3lib_TStemplate    {
         */
        function substituteConstants($all)      {
                if ($this->tt_track)    $GLOBALS['TT']->setTSlogMessage('Constants to substitute: '.count($this->flatSetup));
         */
        function substituteConstants($all)      {
                if ($this->tt_track)    $GLOBALS['TT']->setTSlogMessage('Constants to substitute: '.count($this->flatSetup));
-               reset($this->flatSetup);
-               while (list($const,$val)=each($this->flatSetup))        {
-                       if (!is_array($val))    {
-                               $all = str_replace('{$'.$const.'}',$val,$all);
+
+               $noChange = false;
+               // recursive substitution of constants (up to 10 nested levels)
+               for ($i = 0; $i < 10 && !$noChange; $i++) {
+                       $old_all = $all;
+                       $all = preg_replace_callback('/\{\$(.[^}]*)\}/', array($this, 'substituteConstantsCallBack'), $all);
+                       if ($old_all == $all) {
+                               $noChange = true;
                        }
                }
                        }
                }
+
                return $all;
        }
 
                return $all;
        }
 
+       /**
+        * Call back method for preg_replace_callback in substituteConstants
+        *
+        * @param       array           Regular expression matches
+        * @return      string          Replacement
+        * @see substituteConstants()
+        */
+       function substituteConstantsCallBack($matches) {
+               // replace {$CONST} if found in $this->flatSetup, else leave unchanged
+               return isset($this->flatSetup[$matches[1]]) && !is_array($this->flatSetup[$matches[1]]) ? $this->flatSetup[$matches[1]] : $matches[0];
+       }
 
 
 
 
 
 
@@ -1053,7 +1121,12 @@ class t3lib_TStemplate   {
         */
        function getFileName($fileFromSetup)    {
                $file = trim($fileFromSetup);
         */
        function getFileName($fileFromSetup)    {
                $file = trim($fileFromSetup);
-               if (!$file)     return;
+               if (!$file)     {
+                       return;
+               } elseif (strstr($file,'../'))  {
+                       if ($this->tt_track)    $GLOBALS['TT']->setTSlogMessage('File path "'.$file.'" contained illegal string "../"!',3);
+                       return;
+               }
                        // cache
                $hash = md5($file);
                if (isset($this->fileCache[$hash]))     {
                        // cache
                $hash = md5($file);
                if (isset($this->fileCache[$hash]))     {
@@ -1075,6 +1148,7 @@ class t3lib_TStemplate    {
 
                        // find
                if (strstr($file,'/')) {        // here it is manual media
 
                        // find
                if (strstr($file,'/')) {        // here it is manual media
+                       if(!strcmp(substr($file,0,6),'media/')) $file = 'typo3/sysext/cms/tslib/'.$file;
                        if (@is_file($this->getFileName_backPath.$file))        {
                                $outFile = $file;
                                $fileInfo = t3lib_div::split_fileref($outFile);
                        if (@is_file($this->getFileName_backPath.$file))        {
                                $outFile = $file;
                                $fileInfo = t3lib_div::split_fileref($outFile);
@@ -1133,7 +1207,7 @@ class t3lib_TStemplate    {
         * @param       string          Property name in the menu array
         * @param       array           Menu array to traverse
         * @return      array           Modified menu array
         * @param       string          Property name in the menu array
         * @param       array           Menu array to traverse
         * @return      array           Modified menu array
-        * @depreciated
+        * @deprecated
         * @internal
         */
        function checkFile($name,$menuArr)      {
         * @internal
         */
        function checkFile($name,$menuArr)      {
@@ -1170,7 +1244,7 @@ class t3lib_TStemplate    {
 
        /**
         * Reads the fileContent of $fName and returns it.
 
        /**
         * Reads the fileContent of $fName and returns it.
-        * The same as t3lib_div::getUrl()
+        * Similar to t3lib_div::getUrl()
         *
         * @param       string          Absolute filepath to record
         * @return      string          The content returned
         *
         * @param       string          Absolute filepath to record
         * @return      string          The content returned
@@ -1178,13 +1252,8 @@ class t3lib_TStemplate   {
         */
        function fileContent($fName)    {
                $incFile = $this->getFileName($fName);
         */
        function fileContent($fName)    {
                $incFile = $this->getFileName($fName);
-               if ($incFile && $fd=fopen($incFile,'rb'))       {
-                       $content = '';
-                       while (!feof($fd))      {
-                               $content.=fread($fd, 5000);
-                       }
-                       fclose( $fd );
-                       return $content;
+               if ($incFile)   {
+                       return @file_get_contents($incFile);
                }
        }
 
                }
        }
 
@@ -1244,6 +1313,22 @@ class t3lib_TStemplate   {
        }
 
 
        }
 
 
+       /**
+        * Returns the level of the given page in the rootline - Multiple pages can be given by separating the UIDs by comma.
+        *
+        * @param       string          A list of UIDs for which the rootline-level should get returned
+        * @return      integer The level in the rootline. If more than one page was given the lowest level will get returned.
+        */
+       function getRootlineLevel($list)        {
+               $idx = 0;
+               foreach($this->rootLine as $page)       {
+                       if (t3lib_div::inList($list, $page['uid'])) {
+                               return $idx;
+                       }
+                       $idx++;
+               }
+               return false;
+       }
 
 
 
 
 
 
@@ -1311,7 +1396,7 @@ class t3lib_TStemplate    {
 
                        // typeNum
                $typeNum = $this->setup[$LD['target'].'.']['typeNum'];
 
                        // typeNum
                $typeNum = $this->setup[$LD['target'].'.']['typeNum'];
-               if (!$typeOverride && intval($GLOBALS['TSFE']->config['config']['forceTypeValue']))     {
+               if (!t3lib_div::testInt($typeOverride) && intval($GLOBALS['TSFE']->config['config']['forceTypeValue'])) {
                        $typeOverride = intval($GLOBALS['TSFE']->config['config']['forceTypeValue']);
                }
                if (strcmp($typeOverride,''))   { $typeNum = $typeOverride; }   // Override...
                        $typeOverride = intval($GLOBALS['TSFE']->config['config']['forceTypeValue']);
                }
                if (strcmp($typeOverride,''))   { $typeNum = $typeOverride; }   // Override...
@@ -1326,7 +1411,15 @@ class t3lib_TStemplate   {
                $LD['no_cache'] = (trim($page['no_cache']) || $no_cache) ? '&no_cache=1' : '';
 
                        // linkVars
                $LD['no_cache'] = (trim($page['no_cache']) || $no_cache) ? '&no_cache=1' : '';
 
                        // linkVars
-               $LD['linkVars'] = $GLOBALS['TSFE']->linkVars.$addParams;
+               if ($GLOBALS['TSFE']->config['config']['uniqueLinkVars']) {
+                       if ($addParams) {
+                               $LD['linkVars'] = t3lib_div::implodeArrayForUrl('',t3lib_div::explodeUrl2Array($GLOBALS['TSFE']->linkVars.$addParams));
+                       } else {
+                               $LD['linkVars'] = $GLOBALS['TSFE']->linkVars;
+                       }
+               } else {
+                       $LD['linkVars'] = $GLOBALS['TSFE']->linkVars.$addParams;
+               }
 
                        // If simulateStaticDocuments is enabled:
                if ($GLOBALS['TSFE']->config['config']['simulateStaticDocuments'])      {
 
                        // If simulateStaticDocuments is enabled:
                if ($GLOBALS['TSFE']->config['config']['simulateStaticDocuments'])      {
@@ -1345,7 +1438,7 @@ class t3lib_TStemplate    {
                                                        $page['alias'] ? $page['alias'] : $page['uid'],
                                                        intval($typeNum),
                                                        $LD['linkVars'],
                                                        $page['alias'] ? $page['alias'] : $page['uid'],
                                                        intval($typeNum),
                                                        $LD['linkVars'],
-                                                       $LD['no_cache']?1:0
+                                                       $LD['no_cache'] ? true : false
                                                );
 
                        if ($flag_simulateStaticDocuments_pEnc) {
                                                );
 
                        if ($flag_simulateStaticDocuments_pEnc) {
@@ -1363,7 +1456,7 @@ class t3lib_TStemplate    {
                $LD['url'] = $GLOBALS['TSFE']->absRefPrefix.$LD['url'];
 
                        // If the special key 'sectionIndex_uid' (added 'manually' in tslib/menu.php to the page-record) is set, then the link jumps directly to a section on the page.
                $LD['url'] = $GLOBALS['TSFE']->absRefPrefix.$LD['url'];
 
                        // If the special key 'sectionIndex_uid' (added 'manually' in tslib/menu.php to the page-record) is set, then the link jumps directly to a section on the page.
-               $LD['sectionIndex'] = $page['sectionIndex_uid'] ? '#'.$page['sectionIndex_uid'] : '';
+               $LD['sectionIndex'] = $page['sectionIndex_uid'] ? '#c'.$page['sectionIndex_uid'] : '';
 
                        // Compile the normal total url
                $LD['totalURL']= $this->removeQueryString($LD['url'].$LD['type'].$LD['no_cache'].$LD['linkVars'].$GLOBALS['TSFE']->getMethodUrlIdToken).$LD['sectionIndex'];
 
                        // Compile the normal total url
                $LD['totalURL']= $this->removeQueryString($LD['url'].$LD['type'].$LD['no_cache'].$LD['linkVars'].$GLOBALS['TSFE']->getMethodUrlIdToken).$LD['sectionIndex'];
@@ -1375,7 +1468,7 @@ class t3lib_TStemplate    {
                                                        'args' => array('page'=>$page, 'oTarget'=>$oTarget, 'no_cache'=>$no_cache, 'script'=>$script, 'overrideArray'=>$overrideArray, 'addParams'=>$addParams, 'typeOverride'=>$typeOverride),
                                                        'typeNum' => $typeNum
                                                );
                                                        'args' => array('page'=>$page, 'oTarget'=>$oTarget, 'no_cache'=>$no_cache, 'script'=>$script, 'overrideArray'=>$overrideArray, 'addParams'=>$addParams, 'typeOverride'=>$typeOverride),
                                                        'typeNum' => $typeNum
                                                );
-                       foreach($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tstemplate.php']['linkData-PostProc'] as $_funcRef)   {
+                       foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tstemplate.php']['linkData-PostProc'] as $_funcRef)  {
                                t3lib_div::callUserFunction($_funcRef,$_params,$this);
                        }
                }
                                t3lib_div::callUserFunction($_funcRef,$_params,$this);
                        }
                }
@@ -1508,4 +1601,4 @@ class t3lib_TStemplate    {
 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tstemplate.php'])       {
        include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tstemplate.php']);
 }
 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tstemplate.php'])       {
        include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tstemplate.php']);
 }
-?>
\ No newline at end of file
+?>