TYPO3 API  SVNRelease
class.tslib_fe.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00027 
00028 /**
00029  * Class for the built TypoScript based Front End
00030  *
00031  * This class has a lot of functions and internal variable which are use from index_ts.php.
00032  * The class is instantiated as $GLOBALS['TSFE'] in index_ts.php.
00033  * The use of this class should be inspired by the order of function calls as found in index_ts.php.
00034  *
00035  * $Id: class.tslib_fe.php 10547 2011-02-22 20:03:57Z lolli $
00036  * Revised for TYPO3 3.6 June/2003 by Kasper Skårhøj
00037  * XHTML compliant
00038  *
00039  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00040  */
00041 
00042 /**
00043  * [CLASS/FUNCTION INDEX of SCRIPT]
00044  *
00045  *
00046  *
00047  *  213: class tslib_fe
00048  *  382:     function tslib_fe($TYPO3_CONF_VARS, $id, $type, $no_cache='', $cHash='', $jumpurl='',$MP='',$RDCT='')
00049  *  415:     function connectToMySQL()
00050  *  425:     function connectToDB()
00051  *  470:     function sendRedirect()
00052  *
00053  *              SECTION: Initializing, resolving page id
00054  *  508:     function initFEuser()
00055  *  558:     function initUserGroups()
00056  *  593:     function isUserOrGroupSet()
00057  *  618:     function checkAlternativeIdMethods()
00058  *  670:     function clear_preview()
00059  *  683:     function determineId()
00060  *  817:     function fetch_the_id()
00061  *  911:     function getPageAndRootline()
00062  *  994:     function getPageShortcut($SC,$mode,$thisUid,$itera=20,$pageLog=array())
00063  * 1044:     function checkRootlineForIncludeSection()
00064  * 1081:     function checkEnableFields($row,$bypassGroupCheck=FALSE)
00065  * 1097:     function checkPageGroupAccess($row, $groupList=NULL)
00066  * 1116:     function checkPagerecordForIncludeSection($row)
00067  * 1125:     function checkIfLoginAllowedInBranch()
00068  * 1150:     function getPageAccessFailureReasons()
00069  * 1182:     function setIDfromArgV()
00070  * 1198:     function getPageAndRootlineWithDomain($domainStartPage)
00071  * 1225:     function setSysPageWhereClause()
00072  * 1237:     function findDomainRecord($recursive=0)
00073  * 1257:     function pageNotFoundAndExit($reason='', $header='')
00074  * 1272:     function pageNotFoundHandler($code, $header='', $reason='')
00075  * 1316:     function checkAndSetAlias()
00076  * 1335:     function idPartsAnalyze($str)
00077  * 1360:     function mergingWithGetVars($GET_VARS)
00078  * 1390:     function ADMCMD_preview()
00079  * 1433:     function ADMCMD_preview_postInit($previewConfig)
00080  *
00081  *              SECTION: Template and caching related functions.
00082  * 1465:     function makeCacheHash()
00083  * 1489:     function reqCHash()
00084  * 1511:     function cHashParams($addQueryParams)
00085  * 1520:     function initTemplate()
00086  * 1532:     function getFromCache()
00087  * 1578:     function getFromCache_queryRow()
00088  * 1608:     function headerNoCache()
00089  * 1637:     function getHash()
00090  * 1657:     function getConfigArray()
00091  *
00092  *              SECTION: Further initialization and data processing
00093  * 1818:     function getCompressedTCarray()
00094  * 1872:     function includeTCA($TCAloaded=1)
00095  * 1899:     function settingLanguage()
00096  * 1992:     function settingLocale()
00097  * 2017:     function checkDataSubmission()
00098  * 2050:     function fe_tce()
00099  * 2064:     function locDataCheck($locationData)
00100  * 2080:     function sendFormmail()
00101  * 2131:     function extractRecipientCopy($bodytext)
00102  * 2145:     function setExternalJumpUrl()
00103  * 2156:     function checkJumpUrlReferer()
00104  * 2171:     function jumpUrl()
00105  * 2215:     function setUrlIdToken()
00106  *
00107  *              SECTION: Page generation; cache handling
00108  * 2258:     function isGeneratePage()
00109  * 2268:     function tempPageCacheContent()
00110  * 2325:     function realPageCacheContent()
00111  * 2355:     function setPageCacheContent($content,$data,$tstamp)
00112  * 2382:     function clearPageCacheContent()
00113  * 2392:     function clearPageCacheContent_pidList($pidList)
00114  * 2426:     function setSysLastChanged()
00115  *
00116  *              SECTION: Page generation; rendering and inclusion
00117  * 2462:     function generatePage_preProcessing()
00118  * 2484:     function generatePage_whichScript()
00119  * 2496:     function generatePage_postProcessing()
00120  * 2588:     function INTincScript()
00121  * 2648:     function INTincScript_loadJSCode()
00122  * 2689:     function isINTincScript()
00123  * 2698:     function doXHTML_cleaning()
00124  * 2707:     function doLocalAnchorFix()
00125  *
00126  *              SECTION: Finished off; outputting, storing session data, statistics...
00127  * 2738:     function isOutputting()
00128  * 2761:     function processOutput()
00129  * 2834:     function sendCacheHeaders()
00130  * 2902:     function isStaticCacheble()
00131  * 2915:     function contentStrReplace()
00132  * 2941:     function isEXTincScript()
00133  * 2950:     function storeSessionData()
00134  * 2960:     function setParseTime()
00135  * 2972:     function statistics()
00136  * 3066:     function previewInfo()
00137  * 3101:     function hook_eofe()
00138  * 3117:     function beLoginLinkIPList()
00139  * 3138:     function addTempContentHttpHeaders()
00140  *
00141  *              SECTION: Various internal API functions
00142  * 3184:     function makeSimulFileName($inTitle,$page,$type,$addParams='',$no_cache='')
00143  * 3231:     function simulateStaticDocuments_pEnc_onlyP_proc($linkVars)
00144  * 3260:     function getSimulFileName()
00145  * 3271:     function setSimulReplacementChar()
00146  * 3291:     function fileNameASCIIPrefix($inTitle,$titleChars,$mergeChar='.')
00147  * 3314:     function encryptEmail($string,$back=0)
00148  * 3340:     function codeString($string, $decode=FALSE)
00149  * 3366:     function roundTripCryptString($string)
00150  * 3386:     function checkFileInclude($incFile)
00151  * 3401:     function newCObj()
00152  * 3414:     function setAbsRefPrefix()
00153  * 3428:     function baseUrlWrap($url)
00154  * 3447:     function printError($label,$header='Error!')
00155  * 3458:     function updateMD5paramsRecord($hash)
00156  * 3469:     function tidyHTML($content)
00157  * 3495:     function prefixLocalAnchorsWithScript()
00158  * 3505:     function workspacePreviewInit()
00159  * 3521:     function doWorkspacePreview()
00160  * 3531:     function whichWorkspace($returnTitle = FALSE)
00161  *
00162  *              SECTION: Various external API functions - for use in plugins etc.
00163  * 3589:     function getStorageSiterootPids()
00164  * 3604:     function getPagesTSconfig()
00165  * 3637:     function setJS($key,$content='')
00166  * 3677:     function setCSS($key,$content)
00167  * 3692:     function make_seed()
00168  * 3705:     function uniqueHash($str='')
00169  * 3714:     function set_no_cache()
00170  * 3724:     function set_cache_timeout_default($seconds)
00171  * 3740:     function plainMailEncoded($email,$subject,$message,$headers='')
00172  *
00173  *              SECTION: Localization and character set conversion
00174  * 3784:     function sL($input)
00175  * 3813:     function readLLfile($fileRef)
00176  * 3824:     function getLLL($index,$LOCAL_LANG)
00177  * 3838:     function initLLvars()
00178  * 3872:     function csConv($str,$from='')
00179  * 3890:     function convOutputCharset($content,$label='')
00180  * 3903:     function convPOSTCharset()
00181  *
00182  * TOTAL FUNCTIONS: 116
00183  * (This index is automatically created/updated by the extension "extdeveval")
00184  *
00185  */
00186 /**
00187  * Main frontend class, instantiated in the index_ts.php script as the global object TSFE
00188  *
00189  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00190  * @package TYPO3
00191  * @subpackage tslib
00192  */
00193  class tslib_fe {
00194 
00195         // CURRENT PAGE:
00196     var $id='';                         // The page id (int)
00197     var $type='';                       // RO The type (int)
00198     var $idParts=array();               // Loaded with the id, exploded by ','
00199     var $cHash='';                      // The submitted cHash
00200     var $no_cache='';                   // Page will not be cached. Write only true. Never clear value (some other code might have reasons to set it true)
00201     var $rootLine='';                   // The rootLine (all the way to tree root, not only the current site!) (array)
00202     var $page='';                       // The pagerecord (array)
00203     var $contentPid=0;                  // This will normally point to the same value as id, but can be changed to point to another page from which content will then be displayed instead.
00204     protected $originalShortcutPage = null; // gets set when we are processing a page of type shortcut in the early stages opf init.php when we do not know about languages yet, used later in init.php to determine the correct shortcut in case a translation changes the shortcut target (array)
00205 
00206     /**
00207      * sys_page-object, pagefunctions
00208      *
00209      * @var t3lib_pageSelect
00210      */
00211     var $sys_page='';
00212     var $jumpurl='';
00213     var $pageNotFound=0;                // Is set to 1 if a pageNotFound handler could have been called.
00214     var $domainStartPage=0;             // Domain start page
00215     var $pageAccessFailureHistory=array();  // Array containing a history of why a requested page was not accessible.
00216     var $MP='';
00217     var $RDCT='';
00218     var $page_cache_reg1=0;             // This can be set from applications as a way to tag cached versions of a page and later perform some external cache management, like clearing only a part of the cache of a page...
00219     var $siteScript='';                 // Contains the value of the current script path that activated the frontend. Typically "index.php" but by rewrite rules it could be something else! Used for Speaking Urls / Simulate Static Documents.
00220 
00221         // USER
00222 
00223     /**
00224      * The FE user
00225      *
00226      * @var tslib_feUserAuth
00227      */
00228     var $fe_user='';
00229     var $loginUser='';                  // Global flag indicating that a front-end user is logged in. This is set only if a user really IS logged in. The group-list may show other groups (like added by IP filter or so) even though there is no user.
00230     var $gr_list='';                    // (RO=readonly) The group list, sorted numerically. Group '0,-1' is the default group, but other groups may be added by other means than a user being logged in though...
00231     var $beUserLogin='';                // Flag that indicates if a Backend user is logged in!
00232     var $workspacePreview='';           // Integer, that indicates which workspace is being previewed.
00233     var $loginAllowedInBranch = TRUE;   // Shows whether logins are allowed in branch
00234     var $loginAllowedInBranch_mode = '';    // Shows specific mode (all or groups)
00235     var $ADMCMD_preview_BEUSER_uid = 0; // Integer, set to backend user ID to initialize when keyword-based preview is used.
00236 
00237         // PREVIEW
00238     var $fePreview='';                  // Flag indication that preview is active. This is based on the login of a backend user and whether the backend user has read access to the current page. A value of 1 means ordinary preview, 2 means preview of a non-live workspace
00239     var $showHiddenPage='';             // Flag indicating that hidden pages should be shown, selected and so on. This goes for almost all selection of pages!
00240     var $showHiddenRecords='';          // Flag indicating that hidden records should be shown. This includes sys_template, pages_language_overlay and even fe_groups in addition to all other regular content. So in effect, this includes everything except pages.
00241     var $simUserGroup='0';              // Value that contains the simulated usergroup if any
00242 
00243         // CONFIGURATION
00244     var $TYPO3_CONF_VARS=array();       // The configuration array as set up in t3lib/config_default.php. Should be an EXACT copy of the global array.
00245     var $config='';                     // "CONFIG" object from TypoScript. Array generated based on the TypoScript configuration of the current page. Saved with the cached pages.
00246     var $TCAcachedExtras=array();       // Array of cached information from TCA. This is NOT TCA itself!
00247 
00248         // TEMPLATE / CACHE
00249 
00250     /**
00251      * The TypoScript template object. Used to parse the TypoScript template
00252      *
00253      * @var t3lib_TStemplate
00254      */
00255     var $tmpl='';
00256     var $cacheTimeOutDefault = FALSE;       // Is set to the time-to-live time of cached pages. If false, default is 60*60*24, which is 24 hours.
00257     var $cacheContentFlag = 0;          // Set internally if cached content is fetched from the database
00258     var $cacheExpires=0;                // Set to the expire time of cached content
00259     var $isClientCachable=FALSE;        // Set if cache headers allowing caching are sent.
00260     var $all='';                        // $all used by template fetching system. This array is an identification of the template. If $this->all is empty it's because the template-data is not cached, which it must be.
00261     var $sPre='';                       // toplevel - objArrayName, eg 'page'
00262     var $pSetup='';                     // TypoScript configuration of the page-object pointed to by sPre. $this->tmpl->setup[$this->sPre.'.']
00263     var $newHash='';                    // This hash is unique to the template, the $this->id and $this->type vars and the gr_list (list of groups). Used to get and later store the cached data
00264     var $getMethodUrlIdToken='';        // If config.ftu (Frontend Track User) is set in TypoScript for the current page, the string value of this var is substituted in the rendered source-code with the string, '&ftu=[token...]' which enables GET-method usertracking as opposed to cookie based
00265     var $no_CacheBeforePageGen='';      // This flag is set before inclusion of pagegen.php IF no_cache is set. If this flag is set after the inclusion of pagegen.php, no_cache is forced to be set. This is done in order to make sure that php-code from pagegen does not falsely clear the no_cache flag.
00266     var $tempContent = FALSE;           // This flag indicates if temporary content went into the cache during page-generation.
00267     var $forceTemplateParsing='';               // Boolean, passed to TypoScript template class and tells it to render the template forcibly
00268     var $cHash_array=array();           // The array which cHash_calc is based on, see ->makeCacheHash().
00269     var $hash_base='';                  // Loaded with the serialized array that is used for generating a hashstring for the cache
00270     var $pagesTSconfig='';              // May be set to the pagesTSconfig
00271         // PAGE-GENERATION / cOBJ
00272     /*
00273         Eg. insert JS-functions in this array ($additionalHeaderData) to include them once. Use associative keys.
00274         Keys in use:
00275             JSFormValidate  :       <script type="text/javascript" src="'.$GLOBALS["TSFE"]->absRefPrefix.'t3lib/jsfunc.validateform.js"></script>
00276             JSincludeFormupdate :   <script type="text/javascript" src="t3lib/jsfunc.updateform.js"></script>
00277             JSMenuCode, JSMenuCode_menu :           JavaScript for the JavaScript menu
00278             JSCode : reserved
00279             JSImgCode : reserved
00280     */
00281     var $additionalHeaderData=array();  // used to accumulate additional HTML-code for the header-section, <head>...</head>. Insert either associative keys (like additionalHeaderData['myStyleSheet'], see reserved keys above) or num-keys (like additionalHeaderData[] = '...')
00282     var $additionalJavaScript=array();  // used to accumulate additional JavaScript-code. Works like additionalHeaderData. Reserved keys at 'openPic' and 'mouseOver'
00283     var $additionalCSS=array();         // used to accumulate additional Style code. Works like additionalHeaderData.
00284     var $JSeventFuncCalls = array(      // you can add JavaScript functions to each entry in these arrays. Please see how this is done in the GMENU_LAYERS script. The point is that many applications on a page can set handlers for onload, onmouseover and onmouseup
00285         'onmousemove' => array(),
00286         'onmouseup' => array(),
00287         'onmousemove' => array(),
00288         'onkeydown' => array(),
00289         'onkeyup' => array(),
00290         'onkeypress' => array(),
00291         'onload' => array(),
00292         'onunload' => array(),
00293     );
00294     /**
00295      * Adds JavaScript code
00296      *
00297      * @var string
00298      * @deprecated since TYPO3 3.5 - use additionalJavaScript instead.
00299      */
00300     var $JSCode='';
00301     var $JSImgCode='';                  // Used to accumulate JavaScript loaded images (by menus)
00302     var $divSection='';                 // Used to accumulate DHTML-layers.
00303     var $defaultBodyTag='<body>';       // Default bodytag, if nothing else is set. This can be overridden by applications like TemplaVoila.
00304 
00305         // RENDERING configuration, settings from TypoScript is loaded into these vars. See pagegen.php
00306     var $debug='';                      // Debug flag, may output special debug html-code.
00307     var $intTarget='';                  // Default internal target
00308     var $extTarget='';                  // Default external target
00309     var $fileTarget='';                 // Default file link target
00310     var $MP_defaults=array();           // Keys are page ids and values are default &MP (mount point) values to set when using the linking features...)
00311     var $spamProtectEmailAddresses=0;   // If set, typolink() function encrypts email addresses. Is set in pagegen-class.
00312     var $absRefPrefix='';               // Absolute Reference prefix
00313     var $absRefPrefix_force=0;          // Absolute Reference prefix force flag. This is set, if the type and id is retrieve from PATH_INFO and thus we NEED to prefix urls with at least '/'
00314     var $compensateFieldWidth='';       // Factor for form-field widths compensation
00315     var $lockFilePath='';               // Lock file path
00316     var $ATagParams='';                 // <A>-tag parameters
00317     var $sWordRegEx='';                 // Search word regex, calculated if there has been search-words send. This is used to mark up the found search words on a page when jumped to from a link in a search-result.
00318     var $sWordList='';                  // Is set to the incoming array sword_list in case of a page-view jumped to from a search-result.
00319     var $linkVars='';                   // A string prepared for insertion in all links on the page as url-parameters. Based on configuration in TypoScript where you defined which GET_VARS you would like to pass on.
00320     var $excludeCHashVars='';           // A string set with a comma list of additional GET vars which should NOT be included in the cHash calculation. These vars should otherwise be detected and involved in caching, eg. through a condition in TypoScript.
00321     var $displayEditIcons='';           // If set, edit icons are rendered aside content records. Must be set only if the ->beUserLogin flag is set and set_no_cache() must be called as well.
00322     var $displayFieldEditIcons='';      // If set, edit icons are rendered aside individual fields of content. Must be set only if the ->beUserLogin flag is set and set_no_cache() must be called as well.
00323     var $sys_language_uid=0;            // Site language, 0 (zero) is default, int+ is uid pointing to a sys_language record. Should reflect which language menus, templates etc is displayed in (master language) - but not necessarily the content which could be falling back to default (see sys_language_content)
00324     var $sys_language_mode='';          // Site language mode for content fall back.
00325     var $sys_language_content=0;        // Site content selection uid (can be different from sys_language_uid if content is to be selected from a fall-back language. Depends on sys_language_mode)
00326     var $sys_language_contentOL=0;      // Site content overlay flag; If set - and sys_language_content is > 0 - , records selected will try to look for a translation pointing to their uid. (If configured in [ctrl][languageField] / [ctrl][transOrigP...]
00327     var $sys_language_isocode = '';     // Is set to the iso code of the sys_language_content if that is properly defined by the sys_language record representing the sys_language_uid. (Requires the extension "static_info_tables")
00328 
00329         // RENDERING data
00330     var $applicationData=Array();       //   'Global' Storage for various applications. Keys should be 'tx_'.extKey for extensions.
00331     var $register=Array();
00332     var $registerStack=Array();         // Stack used for storing array and retrieving register arrays (see LOAD_REGISTER and CLEAR_REGISTER)
00333     var $cObjectDepthCounter = 50;      // Checking that the function is not called eternally. This is done by interrupting at a depth of 50
00334     var $recordRegister = Array();      // used by cObj->RECORDS and cObj->CONTENT to ensure the a records is NOT rendered twice through it!
00335     var $currentRecord = '';            // This is set to the [table]:[uid] of the latest record rendered. Note that class tslib_cObj has an equal value, but that is pointing to the record delivered in the $data-array of the tslib_cObj instance, if the cObjects CONTENT or RECORD created that instance
00336     var $accessKey =array();            // Used by class tslib_menu to keep track of access-keys.
00337     var $imagesOnPage=array();          // Numerical array where image filenames are added if they are referenced in the rendered document. This includes only TYPO3 generated/inserted images.
00338     var $lastImageInfo=array();         // Is set in tslib_cObj->cImage() function to the info-array of the most recent rendered image. The information is used in tslib_cObj->IMGTEXT
00339     var $uniqueCounter=0;               // Used to generate page-unique keys. Point is that uniqid() functions is very slow, so a unikey key is made based on this, see function uniqueHash()
00340     var $uniqueString='';
00341     var $indexedDocTitle='';            // This value will be used as the title for the page in the indexer (if indexing happens)
00342     var $altPageTitle='';               // Alternative page title (normally the title of the page record). Can be set from applications you make.
00343     /**
00344      * An array that holds parameter names (keys) of GET parameters which MAY be MD5/base64 encoded with simulate_static_documents method.
00345      * @var array
00346      * @deprecated since TYPO3 4.3, remove in TYPO3 4.5
00347      */
00348     var $pEncAllowedParamNames=array();
00349     var $baseUrl='';                    // The base URL set for the page header.
00350     var $anchorPrefix='';               // The proper anchor prefix needed when using speaking urls. (only set if baseUrl is set)
00351 
00352     /**
00353      * Page content render object
00354      *
00355      * @var tslib_cObj
00356      */
00357     var $cObj ='';
00358 
00359         // CONTENT accumulation
00360     var $content='';                    // All page content is accumulated in this variable. See pagegen.php
00361 
00362         // GENERAL
00363     var $clientInfo='';                 // Set to the browser: net / msie if 4+ browsers
00364     var $scriptParseTime=0;
00365     var $TCAloaded = 0;                 // Set ONLY if the full TCA is loaded
00366 
00367         // Character set (charset) conversion object:
00368 
00369     /**
00370      * charset conversion class. May be used by any application.
00371      *
00372      * @var t3lib_cs
00373      */
00374     var $csConvObj;
00375     var $defaultCharSet = 'iso-8859-1'; // The default charset used in the frontend if nothing else is set.
00376     var $renderCharset='';              // Internal charset of the frontend during rendering: Defaults to "forceCharset" and if that is not set, to ->defaultCharSet
00377     var $metaCharset='';                // Output charset of the websites content. This is the charset found in the header, meta tag etc. If different from $renderCharset a conversion happens before output to browser. Defaults to ->renderCharset if not set.
00378     var $localeCharset='';              // Assumed charset of locale strings.
00379 
00380         // LANG:
00381     var $lang='';                       // Set to the system language key (used on the site)
00382     var $langSplitIndex=0;              // Set to the index number of the language key
00383     var $LL_labels_cache=array();
00384     var $LL_files_cache=array();
00385 
00386     /**
00387      * Locking object
00388      *
00389      * @var t3lib_lock
00390      */
00391     var $pagesection_lockObj;               // Locking object for accessing "cache_pagesection"
00392 
00393     /**
00394      * Locking object
00395      *
00396      * @var t3lib_lock
00397      */
00398     var $pages_lockObj;                 // Locking object for accessing "cache_pages"
00399 
00400     /**
00401      * @var t3lib_PageRenderer
00402      */
00403     protected $pageRenderer;
00404 
00405     /**
00406      * the page cache object, use this to save pages to the cache and to
00407      * retrieve them again
00408      *
00409      * @var t3lib_cache_AbstractBackend
00410      */
00411     protected $pageCache;
00412     protected $pageCacheTags = array();
00413 
00414 
00415     /**
00416      * Class constructor
00417      * Takes a number of GET/POST input variable as arguments and stores them internally.
00418      * The processing of these variables goes on later in this class.
00419      * Also sets internal clientInfo array (browser information) and a unique string (->uniqueString) for this script instance; A md5 hash of the microtime()
00420      *
00421      * @param   array       The global $TYPO3_CONF_VARS array. Will be set internally in ->TYPO3_CONF_VARS
00422      * @param   mixed       The value of t3lib_div::_GP('id')
00423      * @param   integer     The value of t3lib_div::_GP('type')
00424      * @param   boolean     The value of t3lib_div::_GP('no_cache'), evaluated to 1/0
00425      * @param   string      The value of t3lib_div::_GP('cHash')
00426      * @param   string      The value of t3lib_div::_GP('jumpurl')
00427      * @param   string      The value of t3lib_div::_GP('MP')
00428      * @param   string      The value of t3lib_div::_GP('RDCT')
00429      * @return  void
00430      * @see index_ts.php
00431      */
00432     function tslib_fe($TYPO3_CONF_VARS, $id, $type, $no_cache='', $cHash='', $jumpurl='',$MP='',$RDCT='')   {
00433 
00434             // Setting some variables:
00435         $this->TYPO3_CONF_VARS = $TYPO3_CONF_VARS;
00436         $this->id = $id;
00437         $this->type = $type;
00438         if ($no_cache) {
00439             if ($this->TYPO3_CONF_VARS['FE']['disableNoCacheParameter']) {
00440                 $warning = '&no_cache=1 has been ignored because $TYPO3_CONF_VARS[\'FE\'][\'disableNoCacheParameter\'] is set!';
00441                 $GLOBALS['TT']->setTSlogMessage($warning,2);
00442             } else {
00443                 $warning = '&no_cache=1 has been supplied, so caching is disabled! URL: "'.t3lib_div::getIndpEnv('TYPO3_REQUEST_URL').'"';
00444                 $this->disableCache();
00445             }
00446             t3lib_div::sysLog($warning, 'cms', 2);
00447         }
00448         $this->cHash = $cHash;
00449         $this->jumpurl = $jumpurl;
00450         $this->MP = $this->TYPO3_CONF_VARS['FE']['enable_mount_pids'] ? (string)$MP : '';
00451         $this->RDCT = $RDCT;
00452         $this->clientInfo = t3lib_div::clientInfo();
00453         $this->uniqueString=md5(microtime());
00454 
00455         $this->csConvObj = t3lib_div::makeInstance('t3lib_cs');
00456 
00457             // Call post processing function for constructor:
00458         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['tslib_fe-PostProc']))    {
00459             $_params = array('pObj' => &$this);
00460             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['tslib_fe-PostProc'] as $_funcRef) {
00461                 t3lib_div::callUserFunction($_funcRef,$_params,$this);
00462             }
00463         }
00464 
00465         if (TYPO3_UseCachingFramework) {
00466             $this->initCaches();
00467         }
00468     }
00469 
00470     /**
00471      * Connect to SQL database
00472      * May exit after outputting an error message or some JavaScript redirecting to the install tool.
00473      *
00474      * @return  void
00475      */
00476     function connectToDB()  {
00477         if (!TYPO3_db) {
00478                 // jump into Install Tool 1-2-3 mode, if no DB name is defined (fresh installation)
00479             t3lib_utility_Http::redirect(TYPO3_mainDir.'install/index.php?mode=123&step=1&password=joh316');
00480         }
00481 
00482             // sql_pconnect() can throw an Exception in case of some failures, or it returns FALSE
00483         $link = $GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password);
00484         if ($link !== FALSE) {
00485                 // Connection to DB server ok, now select the database
00486             if (!$GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
00487                 if ($this->checkPageUnavailableHandler())   {
00488                     $this->pageUnavailableAndExit('Cannot connect to the configured database "'.TYPO3_db.'"');
00489                 } else {
00490                     $message = 'Cannot connect to the configured database "'.TYPO3_db.'"';
00491                     t3lib_div::sysLog($message, 'cms', t3lib_div::SYSLOG_SEVERITY_ERROR);
00492                     header('HTTP/1.0 503 Service Temporarily Unavailable');
00493                     throw new RuntimeException('Database Error: ' . $message, 1293617736);
00494                 }
00495             }
00496         } else {
00497             if ($this->checkPageUnavailableHandler())   {
00498                 $this->pageUnavailableAndExit('The current username, password or host was not accepted when the connection to the database was attempted to be established!');
00499             } else {
00500                 $message = 'The current username, password or host was not accepted when the connection to the database was attempted to be established!';
00501                 t3lib_div::sysLog($message, 'cms', t3lib_div::SYSLOG_SEVERITY_ERROR);
00502                 header('HTTP/1.0 503 Service Temporarily Unavailable');
00503                 throw new RuntimeException('Database Error: ' . $message, 1293617741);
00504             }
00505         }
00506 
00507 
00508             // Call post processing function for DB connection:
00509         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['connectToDB']))  {
00510             $_params = array('pObj' => &$this);
00511             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['connectToDB'] as $_funcRef)   {
00512                 t3lib_div::callUserFunction($_funcRef,$_params,$this);
00513             }
00514         }
00515     }
00516 
00517     /**
00518      * Looks up the value of $this->RDCT in the database and if it is found to be associated with a redirect URL then the redirection is carried out with a 'Location:' header
00519      * May exit after sending a location-header.
00520      *
00521      * @return  void
00522      */
00523     function sendRedirect() {
00524         $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('params', 'cache_md5params', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->RDCT, 'cache_md5params'));
00525         if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
00526             $this->updateMD5paramsRecord($this->RDCT);
00527             header('Location: '.$row['params']);
00528             exit;
00529         }
00530     }
00531 
00532     /**
00533      * Gets instance of PageRenderer
00534      *
00535      * @return  t3lib_PageRenderer
00536      */
00537     public function getPageRenderer() {
00538         if (!isset($this->pageRenderer)) {
00539             $this->pageRenderer = t3lib_div::makeInstance('t3lib_PageRenderer');
00540             $this->pageRenderer->setTemplateFile(PATH_tslib . 'templates/tslib_page_frontend.html');
00541             $this->pageRenderer->setBackPath(TYPO3_mainDir);
00542         }
00543         return $this->pageRenderer;
00544     }
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561     /********************************************
00562      *
00563      * Initializing, resolving page id
00564      *
00565      ********************************************/
00566 
00567     /**
00568      * Initializes the caching system.
00569      *
00570      * @return  void
00571      */
00572     protected function initCaches() {
00573         if (TYPO3_UseCachingFramework) {
00574             $GLOBALS['TT']->push('Initializing the Caching System','');
00575 
00576             $GLOBALS['typo3CacheManager'] = t3lib_div::makeInstance('t3lib_cache_Manager');
00577             $GLOBALS['typo3CacheFactory'] = t3lib_div::makeInstance('t3lib_cache_Factory');
00578             $GLOBALS['typo3CacheFactory']->setCacheManager($GLOBALS['typo3CacheManager']);
00579 
00580             try {
00581                 $this->pageCache = $GLOBALS['typo3CacheManager']->getCache(
00582                     'cache_pages'
00583                 );
00584             } catch(t3lib_cache_exception_NoSuchCache $e) {
00585                 t3lib_cache::initPageCache();
00586 
00587                 $this->pageCache = $GLOBALS['typo3CacheManager']->getCache(
00588                     'cache_pages'
00589                 );
00590             }
00591 
00592             t3lib_cache::initPageSectionCache();
00593             t3lib_cache::initContentHashCache();
00594 
00595             $GLOBALS['TT']->pull();
00596         }
00597     }
00598 
00599     /**
00600      * Initializes the front-end login user.
00601      *
00602      * @return  void
00603      */
00604     function initFEuser()   {
00605         $this->fe_user = t3lib_div::makeInstance('tslib_feUserAuth');
00606 
00607         $this->fe_user->lockIP = $this->TYPO3_CONF_VARS['FE']['lockIP'];
00608         $this->fe_user->checkPid = $this->TYPO3_CONF_VARS['FE']['checkFeUserPid'];
00609         $this->fe_user->lifetime = intval($this->TYPO3_CONF_VARS['FE']['lifetime']);
00610         $this->fe_user->checkPid_value = $GLOBALS['TYPO3_DB']->cleanIntList(t3lib_div::_GP('pid')); // List of pid's acceptable
00611 
00612             // Check if a session is transferred:
00613         if (t3lib_div::_GP('FE_SESSION_KEY'))   {
00614             $fe_sParts = explode('-',t3lib_div::_GP('FE_SESSION_KEY'));
00615             if (!strcmp(md5($fe_sParts[0].'/'.$this->TYPO3_CONF_VARS['SYS']['encryptionKey']), $fe_sParts[1]))  {   // If the session key hash check is OK:
00616                 $_COOKIE[$this->fe_user->name] = $fe_sParts[0];
00617                 $this->fe_user->forceSetCookie = 1;
00618             }
00619         }
00620 
00621         if ($this->TYPO3_CONF_VARS['FE']['dontSetCookie'])  {
00622             $this->fe_user->dontSetCookie=1;
00623         }
00624 
00625         $this->fe_user->start();
00626         $this->fe_user->unpack_uc('');
00627         $this->fe_user->fetchSessionData(); // Gets session data
00628         $recs = t3lib_div::_GP('recs');
00629         if (is_array($recs))    {   // If any record registration is submitted, register the record.
00630             $this->fe_user->record_registration($recs, $this->TYPO3_CONF_VARS['FE']['maxSessionDataSize']);
00631         }
00632 
00633             // Call hook for possible manipulation of frontend user object
00634         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['initFEuser']))   {
00635             $_params = array('pObj' => &$this);
00636             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['initFEuser'] as $_funcRef)    {
00637                 t3lib_div::callUserFunction($_funcRef,$_params,$this);
00638             }
00639         }
00640 
00641             // For every 60 seconds the is_online timestamp is updated.
00642         if (is_array($this->fe_user->user) && $this->fe_user->user['uid'] && $this->fe_user->user['is_online']<($GLOBALS['EXEC_TIME']-60))  {
00643             $GLOBALS['TYPO3_DB']->exec_UPDATEquery('fe_users', 'uid='.intval($this->fe_user->user['uid']), array('is_online' => $GLOBALS['EXEC_TIME']));
00644         }
00645     }
00646 
00647     /**
00648      * Initializes the front-end user groups.
00649      * Sets ->loginUser and ->gr_list based on front-end user status.
00650      *
00651      * @return  void
00652      */
00653     function initUserGroups() {
00654 
00655         $this->fe_user->showHiddenRecords = $this->showHiddenRecords;       // This affects the hidden-flag selecting the fe_groups for the user!
00656         $this->fe_user->fetchGroupData();   // no matter if we have an active user we try to fetch matching groups which can be set without an user (simulation for instance!)
00657 
00658         if (is_array($this->fe_user->user) && count($this->fe_user->groupData['uid']))  {
00659             $this->loginUser=1; // global flag!
00660             $this->gr_list = '0,-2';    // group -2 is not an existing group, but denotes a 'default' group when a user IS logged in. This is used to let elements be shown for all logged in users!
00661             $gr_array = $this->fe_user->groupData['uid'];
00662         } else {
00663             $this->loginUser=0;
00664             $this->gr_list = '0,-1';    // group -1 is not an existing group, but denotes a 'default' group when not logged in. This is used to let elements be hidden, when a user is logged in!
00665 
00666             if ($this->loginAllowedInBranch)    {
00667                 $gr_array = $this->fe_user->groupData['uid'];   // For cases where logins are not banned from a branch usergroups can be set based on IP masks so we should add the usergroups uids.
00668             } else {
00669                 $gr_array = array();        // Set to blank since we will NOT risk any groups being set when no logins are allowed!
00670             }
00671         }
00672 
00673             // Clean up.
00674         $gr_array = array_unique($gr_array);    // Make unique...
00675         sort($gr_array);    // sort
00676         if (count($gr_array) && !$this->loginAllowedInBranch_mode)  {
00677             $this->gr_list.=','.implode(',',$gr_array);
00678         }
00679 
00680         if ($this->fe_user->writeDevLog)    t3lib_div::devLog('Valid usergroups for TSFE: '.$this->gr_list, 'tslib_fe');
00681     }
00682 
00683     /**
00684      * Checking if a user is logged in or a group constellation different from "0,-1"
00685      *
00686      * @return  boolean     TRUE if either a login user is found (array fe_user->user) OR if the gr_list is set to something else than '0,-1' (could be done even without a user being logged in!)
00687      */
00688     function isUserOrGroupSet() {
00689         return is_array($this->fe_user->user) || $this->gr_list!=='0,-1';
00690     }
00691 
00692     /**
00693      * Provides ways to bypass the '?id=[xxx]&type=[xx]' format, using either PATH_INFO or virtual HTML-documents (using Apache mod_rewrite)
00694      *
00695      * Two options:
00696      * 1) Use PATH_INFO (also Apache) to extract id and type from that var. Does not require any special modules compiled with apache. (less typical)
00697      * 2) Using hook which enables features like those provided from "simulatestatic" or "realurl" extension (AKA "Speaking URLs")
00698      *
00699      * @return  void
00700      */
00701     function checkAlternativeIdMethods()    {
00702         $this->siteScript = t3lib_div::getIndpEnv('TYPO3_SITE_SCRIPT');
00703 
00704             // Call post processing function for custom URL methods.
00705         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['checkAlternativeIdMethods-PostProc']))   {
00706             $_params = array('pObj' => &$this);
00707             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['checkAlternativeIdMethods-PostProc'] as $_funcRef)    {
00708                 t3lib_div::callUserFunction($_funcRef,$_params,$this);
00709             }
00710         }
00711     }
00712 
00713     /**
00714      * Clears the preview-flags, sets sim_exec_time to current time.
00715      * Hidden pages must be hidden as default, $GLOBALS['SIM_EXEC_TIME'] is set to $GLOBALS['EXEC_TIME'] in t3lib/config_default.inc. Alter it by adding or subtracting seconds.
00716      *
00717      * @return  void
00718      */
00719     function clear_preview()    {
00720         $this->showHiddenPage = 0;
00721         $this->showHiddenRecords = 0;
00722         $GLOBALS['SIM_EXEC_TIME'] = $GLOBALS['EXEC_TIME'];
00723         $GLOBALS['SIM_ACCESS_TIME'] = $GLOBALS['ACCESS_TIME'];
00724         $this->fePreview = 0;
00725     }
00726 
00727     /**
00728      * Determines the id and evaluates any preview settings
00729      * Basically this function is about determining whether a backend user is logged in, if he has read access to the page and if he's previewing the page. That all determines which id to show and how to initialize the id.
00730      *
00731      * @return  void
00732      */
00733     function determineId()  {
00734 
00735             // Getting ARG-v values if some
00736         $this->setIDfromArgV();
00737 
00738             // If there is a Backend login we are going to check for any preview settings:
00739         $GLOBALS['TT']->push('beUserLogin','');
00740         if ($this->beUserLogin || $this->doWorkspacePreview())  {
00741 
00742                 // Backend user preview features:
00743             if ($this->beUserLogin && ($GLOBALS['BE_USER']->adminPanel instanceof tslib_AdminPanel)) {
00744                 $this->fePreview = $GLOBALS['BE_USER']->adminPanel->extGetFeAdminValue('preview') ? true : false;
00745 
00746                     // If admin panel preview is enabled...
00747                 if ($this->fePreview)   {
00748                     $fe_user_OLD_USERGROUP = $this->fe_user->user['usergroup'];
00749 
00750                     $this->showHiddenPage = $GLOBALS['BE_USER']->adminPanel->extGetFeAdminValue('preview', 'showHiddenPages');
00751                     $this->showHiddenRecords = $GLOBALS['BE_USER']->adminPanel->extGetFeAdminValue('preview', 'showHiddenRecords');
00752                         // simulate date
00753                     $simTime = $GLOBALS['BE_USER']->adminPanel->extGetFeAdminValue('preview', 'simulateDate');
00754                     if ($simTime)   {
00755                         $GLOBALS['SIM_EXEC_TIME'] = $simTime;
00756                         $GLOBALS['SIM_ACCESS_TIME'] = $simTime - ($simTime % 60);
00757                     }
00758                         // simulate user
00759                     $simUserGroup = $GLOBALS['BE_USER']->adminPanel->extGetFeAdminValue('preview', 'simulateUserGroup');
00760                     $this->simUserGroup = $simUserGroup;
00761                     if ($simUserGroup)  $this->fe_user->user['usergroup']=$simUserGroup;
00762                     if (!$simUserGroup && !$simTime && !$this->showHiddenPage && !$this->showHiddenRecords) {
00763                         $this->fePreview=0;
00764                     }
00765                 }
00766             }
00767 
00768             if ($this->id)  {
00769 
00770                     // Now it's investigated if the raw page-id points to a hidden page and if so, the flag is set.
00771                     // This does not require the preview flag to be set in the admin panel
00772                 $idQ = t3lib_div::testInt($this->id) ? 'uid='.intval($this->id) : 'alias='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->id, 'pages').' AND pid>=0';    // pid>=0 added for the sake of versioning...
00773                 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', 'pages', $idQ . ' AND hidden!=0 AND deleted=0');
00774                 if ($count) {
00775                     $this->fePreview = 1;   // The preview flag is set only if the current page turns out to actually be hidden!
00776                     $this->showHiddenPage = 1;
00777                 }
00778 
00779                     // For Live workspace: Check root line for proper connection to tree root (done because of possible preview of page / branch versions)
00780                 if (!$this->fePreview && $this->whichWorkspace()===0)   {
00781 
00782                         // Initialize the page-select functions to check rootline:
00783                     $temp_sys_page = t3lib_div::makeInstance('t3lib_pageSelect');
00784                     $temp_sys_page->init($this->showHiddenPage);
00785                         // If root line contained NO records and ->error_getRootLine_failPid tells us that it was because of a pid=-1 (indicating a "version" record)...:
00786                     if (!count($temp_sys_page->getRootLine($this->id,$this->MP)) && $temp_sys_page->error_getRootLine_failPid==-1)  {
00787 
00788                             // Setting versioningPreview flag and try again:
00789                         $temp_sys_page->versioningPreview = TRUE;
00790                         if (count($temp_sys_page->getRootLine($this->id,$this->MP)))    {
00791                                 // Finally, we got a root line (meaning that it WAS due to versioning preview of a page somewhere) and we set the fePreview flag which in itself will allow sys_page class to display previews of versionized records.
00792                             $this->fePreview = 1;
00793                         }
00794                     }
00795                 }
00796             }
00797 
00798                 // The preview flag will be set if a backend user is in an offline workspace
00799             if (($GLOBALS['BE_USER']->user['workspace_preview'] || t3lib_div::_GP('ADMCMD_view') || $this->doWorkspacePreview()) && ($this->whichWorkspace()===-1 || $this->whichWorkspace()>0))    {
00800                 $this->fePreview = 2;   // Will show special preview message.
00801             }
00802 
00803                 // If the front-end is showing a preview, caching MUST be disabled.
00804             if ($this->fePreview)   {
00805                 $this->disableCache();
00806             }
00807         }
00808         $GLOBALS['TT']->pull();
00809 
00810             // Now, get the id, validate access etc:
00811         $this->fetch_the_id();
00812 
00813             // Check if backend user has read access to this page. If not, recalculate the id.
00814         if ($this->beUserLogin && $this->fePreview) {
00815             if (!$GLOBALS['BE_USER']->doesUserHaveAccess($this->page,1))    {
00816 
00817                     // Resetting
00818                 $this->clear_preview();
00819                 $this->fe_user->user['usergroup'] = $fe_user_OLD_USERGROUP;
00820 
00821                     // Fetching the id again, now with the preview settings reset.
00822                 $this->fetch_the_id();
00823             }
00824         }
00825 
00826             // Checks if user logins are blocked for a certain branch and if so, will unset user login and re-fetch ID.
00827         $this->loginAllowedInBranch = $this->checkIfLoginAllowedInBranch();
00828         if (!$this->loginAllowedInBranch)   {   // Logins are not allowed:
00829             if ($this->isUserOrGroupSet())  {   // Only if there is a login will we run this...
00830                 if ($this->loginAllowedInBranch_mode=='all')    {
00831                         // Clear out user and group:
00832                     unset($this->fe_user->user);
00833                     $this->gr_list = '0,-1';
00834                 } else {
00835                     $this->gr_list = '0,-2';
00836                 }
00837 
00838                     // Fetching the id again, now with the preview settings reset.
00839                 $this->fetch_the_id();
00840             }
00841         }
00842 
00843             // Final cleaning.
00844         $this->id = $this->contentPid = intval($this->id);  // Make sure it's an integer
00845         $this->type = intval($this->type);  // Make sure it's an integer
00846 
00847             // Look for alternative content PID if page is under version preview:
00848         if ($this->fePreview)   {
00849             if ($this->page['_ORIG_pid']==-1 && $this->page['t3ver_swapmode']==0)   {   // Current page must have been an offline version and have swapmode set to 0:
00850                     // Setting contentPid here for preview might not be completely correct to do. Strictly the "_ORIG_uid" value should be used for tables where "versioning_followPages" is set and for others not. However this is a working quick-fix to display content elements at least!
00851                 $this->contentPid = $this->page['_ORIG_uid'];
00852             }
00853         }
00854 
00855             // Call post processing function for id determination:
00856         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['determineId-PostProc'])) {
00857             $_params = array('pObj' => &$this);
00858             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['determineId-PostProc'] as $_funcRef)  {
00859                 t3lib_div::callUserFunction($_funcRef,$_params,$this);
00860             }
00861         }
00862     }
00863 
00864     /**
00865      * Get The Page ID
00866      * This gets the id of the page, checks if the page is in the domain and if the page is accessible
00867      * Sets variables such as $this->sys_page, $this->loginUser, $this->gr_list, $this->id, $this->type, $this->domainStartPage, $this->idParts
00868      *
00869      * @return  void
00870      * @access private
00871      */
00872     function fetch_the_id() {
00873         $GLOBALS['TT']->push('fetch_the_id initialize/','');
00874 
00875             // Initialize the page-select functions.
00876         $this->sys_page = t3lib_div::makeInstance('t3lib_pageSelect');
00877         $this->sys_page->versioningPreview = ($this->fePreview===2 || intval($this->workspacePreview) || t3lib_div::_GP('ADMCMD_view')) ? TRUE : FALSE;
00878         $this->sys_page->versioningWorkspaceId = $this->whichWorkspace();
00879         $this->sys_page->init($this->showHiddenPage);
00880 
00881             // Set the valid usergroups for FE
00882         $this->initUserGroups();
00883 
00884             // Sets sys_page where-clause
00885         $this->setSysPageWhereClause();
00886 
00887             // Splitting $this->id by a period (.). First part is 'id' and second part - if exists - will overrule the &type param if given
00888         $pParts = explode('.',$this->id);
00889         $this->id = $pParts[0]; // Set it.
00890         if (isset($pParts[1]))  {$this->type=$pParts[1];}
00891 
00892             // Splitting $this->id by a comma (,). First part is 'id' and other parts are just stored for use in scripts.
00893         $this->idParts = explode(',',$this->id);
00894 
00895             // Splitting by a '+' sign - used for base64/md5 methods of parameter encryption for simulate static documents.
00896         list($pgID,$SSD_p)=explode('+',$this->idParts[0],2);
00897         if ($SSD_p) {   $this->idPartsAnalyze($SSD_p);  }
00898         $this->id = $pgID;  // Set id
00899 
00900             // If $this->id is a string, it's an alias
00901         $this->checkAndSetAlias();
00902 
00903             // The id and type is set to the integer-value - just to be sure...
00904         $this->id = intval($this->id);
00905         $this->type = intval($this->type);
00906         $GLOBALS['TT']->pull();
00907 
00908             // We find the first page belonging to the current domain
00909         $GLOBALS['TT']->push('fetch_the_id domain/','');
00910         $this->domainStartPage = $this->findDomainRecord($this->TYPO3_CONF_VARS['SYS']['recursiveDomainSearch']);   // the page_id of the current domain
00911         if (!$this->id) {
00912             if ($this->domainStartPage) {
00913                 $this->id = $this->domainStartPage; // If the id was not previously set, set it to the id of the domain.
00914             } else {
00915                 $theFirstPage = $this->sys_page->getFirstWebPage($this->id);    // Find the first 'visible' page in that domain
00916                 if ($theFirstPage)  {
00917                     $this->id = $theFirstPage['uid'];
00918                 } else {
00919                     if ($this->checkPageUnavailableHandler())   {
00920                         $this->pageUnavailableAndExit('No pages are found on the rootlevel!');
00921                     } else {
00922                         $message = 'No pages are found on the rootlevel!';
00923                         t3lib_div::sysLog($message, 'cms', t3lib_div::SYSLOG_SEVERITY_ERROR);
00924                         header('HTTP/1.0 503 Service Temporarily Unavailable');
00925                         throw new RuntimeException($message);
00926                     }
00927                 }
00928             }
00929         }
00930         $GLOBALS['TT']->pull();
00931 
00932         $GLOBALS['TT']->push('fetch_the_id rootLine/','');
00933         $requestedId = $this->id;       // We store the originally requested id
00934         $this->getPageAndRootlineWithDomain($this->domainStartPage);
00935         $GLOBALS['TT']->pull();
00936 
00937         if ($this->pageNotFound && $this->TYPO3_CONF_VARS['FE']['pageNotFound_handling'])   {
00938             $pNotFoundMsg = array(
00939                 1 => 'ID was not an accessible page',
00940                 2 => 'Subsection was found and not accessible',
00941                 3 => 'ID was outside the domain',
00942                 4 => 'The requested page alias does not exist'
00943             );
00944             $this->pageNotFoundAndExit($pNotFoundMsg[$this->pageNotFound]);
00945         }
00946 
00947         if ($this->page['url_scheme'] > 0) {
00948             $newUrl = '';
00949             $requestUrlScheme = parse_url(t3lib_div::getIndpEnv('TYPO3_REQUEST_URL'), PHP_URL_SCHEME);
00950             if ((int) $this->page['url_scheme'] === t3lib_utility_http::SCHEME_HTTP && $requestUrlScheme == 'https') {
00951                 $newUrl = 'http://' . substr(t3lib_div::getIndpEnv('TYPO3_REQUEST_URL'), 8);
00952             } elseif ((int) $this->page['url_scheme'] === t3lib_utility_http::SCHEME_HTTPS && $requestUrlScheme == 'http') {
00953                 $newUrl = 'https://' . substr(t3lib_div::getIndpEnv('TYPO3_REQUEST_URL'), 7);
00954             }
00955             if ($newUrl !== '') {
00956                 if ($_SERVER['REQUEST_METHOD'] === 'POST') {
00957                     $headerCode = t3lib_utility_Http::HTTP_STATUS_303;
00958                 } else {
00959                     $headerCode = t3lib_utility_Http::HTTP_STATUS_301;
00960                 }
00961                 t3lib_utility_http::redirect($newUrl, $headerCode);
00962             }
00963         }
00964             // set no_cache if set
00965         if ($this->page['no_cache'])    {
00966             $this->set_no_cache();
00967         }
00968 
00969             // Init SYS_LASTCHANGED
00970         $this->register['SYS_LASTCHANGED'] = intval($this->page['tstamp']);
00971         if ($this->register['SYS_LASTCHANGED'] < intval($this->page['SYS_LASTCHANGED']))    {
00972             $this->register['SYS_LASTCHANGED'] = intval($this->page['SYS_LASTCHANGED']);
00973         }
00974     }
00975 
00976     /**
00977      * Gets the page and rootline arrays based on the id, $this->id
00978      *
00979      * If the id does not correspond to a proper page, the 'previous' valid page in the rootline is found
00980      * If the page is a shortcut (doktype=4), the ->id is loaded with that id
00981      *
00982      * Whether or not the ->id is changed to the shortcut id or the previous id in rootline (eg if a page is hidden), the ->page-array and ->rootline is found and must also be valid.
00983      *
00984      * Sets or manipulates internal variables such as: $this->id, $this->page, $this->rootLine, $this->MP, $this->pageNotFound
00985      *
00986      * @return  void
00987      * @access private
00988      */
00989     function getPageAndRootline() {
00990         $this->page = $this->sys_page->getPage($this->id);
00991         if (!count($this->page))    {
00992                 // If no page, we try to find the page before in the rootLine.
00993             $this->pageNotFound=1;          // Page is 'not found' in case the id itself was not an accessible page. code 1
00994             $this->rootLine = $this->sys_page->getRootLine($this->id,$this->MP);
00995             if (count($this->rootLine)) {
00996                 $c=count($this->rootLine)-1;
00997                 while($c>0) {
00998 
00999                         // Add to page access failure history:
01000                     $this->pageAccessFailureHistory['direct_access'][] = $this->rootLine[$c];
01001 
01002                         // Decrease to next page in rootline and check the access to that, if OK, set as page record and ID value.
01003                     $c--;
01004                     $this->id = $this->rootLine[$c]['uid'];
01005                     $this->page = $this->sys_page->getPage($this->id);
01006                     if (count($this->page)) { break; }
01007                 }
01008             }
01009                 // If still no page...
01010             if (!count($this->page))    {
01011                 if ($this->TYPO3_CONF_VARS['FE']['pageNotFound_handling'])  {
01012                     $this->pageNotFoundAndExit('The requested page does not exist!');
01013                 } else {
01014                     $message = 'The requested page does not exist!';
01015                     header('HTTP/1.0 404 Page Not Found');
01016                     t3lib_div::sysLog($message, 'cms', t3lib_div::SYSLOG_SEVERITY_ERROR);
01017                     throw new RuntimeException($message);
01018                 }
01019             }
01020         }
01021 
01022             // Spacer is not accessible in frontend
01023         if ($this->page['doktype'] == t3lib_pageSelect::DOKTYPE_SPACER) {
01024             if ($this->TYPO3_CONF_VARS['FE']['pageNotFound_handling'])  {
01025                 $this->pageNotFoundAndExit('The requested page does not exist!');
01026             } else {
01027                 $message = 'The requested page does not exist!';
01028                 header('HTTP/1.0 404 Page Not Found');
01029                 t3lib_div::sysLog($message, 'cms', t3lib_div::SYSLOG_SEVERITY_ERROR);
01030                 throw new RuntimeException($message);
01031             }
01032         }
01033 
01034             // Is the ID a link to another page??
01035         if ($this->page['doktype'] == t3lib_pageSelect::DOKTYPE_SHORTCUT) {
01036             $this->MP = '';     // We need to clear MP if the page is a shortcut. Reason is if the short cut goes to another page, then we LEAVE the rootline which the MP expects.
01037 
01038                 // saving the page so that we can check later - when we know
01039                 // about languages - whether we took the correct shortcut or
01040                 // whether a translation of the page overwrites the shortcut
01041                 // target and we need to follow the new target
01042             $this->originalShortcutPage = $this->page;
01043 
01044             $this->page = $this->getPageShortcut($this->page['shortcut'],$this->page['shortcut_mode'],$this->page['uid']);
01045             $this->id = $this->page['uid'];
01046         }
01047 
01048             // Gets the rootLine
01049         $this->rootLine = $this->sys_page->getRootLine($this->id,$this->MP);
01050 
01051             // If not rootline we're off...
01052         if (!count($this->rootLine))    {
01053             $ws = $this->whichWorkspace();
01054             if ($this->sys_page->error_getRootLine_failPid==-1 && $ws) {
01055                 $this->sys_page->versioningPreview = TRUE;
01056                 $this->versioningWorkspaceId = $ws;
01057                 $this->rootLine = $this->sys_page->getRootLine($this->id,$this->MP);
01058             }
01059             if (!count($this->rootLine))    {
01060                 if ($this->checkPageUnavailableHandler())   {
01061                     $this->pageUnavailableAndExit('The requested page didn\'t have a proper connection to the tree-root!');
01062                 } else {
01063                     $message = 'The requested page didn\'t have a proper connection to the tree-root! <br /><br />('.$this->sys_page->error_getRootLine.')';
01064                     header('HTTP/1.0 503 Service Temporarily Unavailable');
01065                     t3lib_div::sysLog(str_replace('<br /><br />','',$message), 'cms', t3lib_div::SYSLOG_SEVERITY_ERROR);
01066                     throw new RuntimeException($message);
01067                 }
01068             }
01069             $this->fePreview = 1;
01070         }
01071 
01072             // Checking for include section regarding the hidden/starttime/endtime/fe_user (that is access control of a whole subbranch!)
01073         if ($this->checkRootlineForIncludeSection())    {
01074             if (!count($this->rootLine))    {
01075                 if ($this->checkPageUnavailableHandler())   {
01076                     $this->pageUnavailableAndExit('The requested page was not accessible!');
01077                 } else {
01078                     $message = 'The requested page was not accessible!';
01079                     header('HTTP/1.0 503 Service Temporarily Unavailable');
01080                     t3lib_div::sysLog($message, 'cms', t3lib_div::SYSLOG_SEVERITY_ERROR);
01081                     throw new RuntimeException($message);
01082                 }
01083             } else {
01084                 $el = reset($this->rootLine);
01085                 $this->id = $el['uid'];
01086                 $this->page = $this->sys_page->getPage($this->id);
01087                 $this->rootLine = $this->sys_page->getRootLine($this->id,$this->MP);
01088             }
01089         }
01090     }
01091 
01092     /**
01093      * Get page shortcut; Finds the records pointed to by input value $SC (the shortcut value)
01094      *
01095      * @param   integer     The value of the "shortcut" field from the pages record
01096      * @param   integer     The shortcut mode: 1 will select first subpage, 2 a random subpage, 3 the parent page; default is the page pointed to by $SC
01097      * @param   integer     The current page UID of the page which is a shortcut
01098      * @param   integer     Safety feature which makes sure that the function is calling itself recursively max 20 times (since this function can find shortcuts to other shortcuts to other shortcuts...)
01099      * @param   array       An array filled with previous page uids tested by the function - new page uids are evaluated against this to avoid going in circles.
01100      * @return  mixed       Returns the page record of the page that the shortcut pointed to.
01101      * @access private
01102      * @see getPageAndRootline()
01103      */
01104     function getPageShortcut($SC,$mode,$thisUid,$itera=20,$pageLog=array()) {
01105         $idArray = t3lib_div::intExplode(',',$SC);
01106 
01107             // Find $page record depending on shortcut mode:
01108         switch($mode)   {
01109             case t3lib_pageSelect::SHORTCUT_MODE_FIRST_SUBPAGE:
01110             case t3lib_pageSelect::SHORTCUT_MODE_RANDOM_SUBPAGE:
01111                 $pageArray = $this->sys_page->getMenu(($idArray[0] ? $idArray[0] : $thisUid), '*', 'sorting', 'AND pages.doktype<199 AND pages.doktype!=' . t3lib_pageSelect::DOKTYPE_BE_USER_SECTION);
01112                 $pO = 0;
01113                 if ($mode == t3lib_pageSelect::SHORTCUT_MODE_RANDOM_SUBPAGE && count($pageArray)) {
01114                     $randval = intval(rand(0,count($pageArray)-1));
01115                     $pO = $randval;
01116                 }
01117                 $c = 0;
01118                 foreach ($pageArray as $pV) {
01119                     if ($c==$pO)    {
01120                         $page = $pV;
01121                         break;
01122                     }
01123                     $c++;
01124                 }
01125             break;
01126             case t3lib_pageSelect::SHORTCUT_MODE_PARENT_PAGE:
01127                 $parent = $this->sys_page->getPage($thisUid);
01128                 $page = $this->sys_page->getPage($parent['pid']);
01129             break;
01130             default:
01131                 $page = $this->sys_page->getPage($idArray[0]);
01132             break;
01133         }
01134 
01135             // Check if short cut page was a shortcut itself, if so look up recursively:
01136         if ($page['doktype'] == t3lib_pageSelect::DOKTYPE_SHORTCUT) {
01137             if (!in_array($page['uid'],$pageLog) && $itera>0)   {
01138                 $pageLog[] = $page['uid'];
01139                 $page = $this->getPageShortcut($page['shortcut'],$page['shortcut_mode'],$page['uid'],$itera-1,$pageLog);
01140             } else {
01141                 $pageLog[] = $page['uid'];
01142                 $message = 'Page shortcuts were looping in uids '.implode(',',$pageLog).'...!';
01143                 header('HTTP/1.0 500 Internal Server Error');
01144                 t3lib_div::sysLog($message, 'cms', t3lib_div::SYSLOG_SEVERITY_ERROR);
01145                 throw new RuntimeException($message);
01146             }
01147         }
01148             // Return resulting page:
01149         return $page;
01150     }
01151 
01152     /**
01153      * Checks the current rootline for defined sections.
01154      *
01155      * @return  boolean
01156      * @access private
01157      */
01158     function checkRootlineForIncludeSection()   {
01159         $c=count($this->rootLine);
01160         $removeTheRestFlag=0;
01161 
01162         for ($a=0;$a<$c;$a++)   {
01163             if (!$this->checkPagerecordForIncludeSection($this->rootLine[$a]))  {
01164                     // Add to page access failure history:
01165                 $this->pageAccessFailureHistory['sub_section'][] = $this->rootLine[$a];
01166                 $removeTheRestFlag=1;
01167             }
01168             if ($this->rootLine[$a]['doktype'] == t3lib_pageSelect::DOKTYPE_BE_USER_SECTION) {
01169                 if ($this->beUserLogin) {   // If there is a backend user logged in, check if he has read access to the page:
01170                     $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'uid='.intval($this->id).' AND '.$GLOBALS['BE_USER']->getPagePermsClause(1)); // versionOL()?
01171                     list($isPage) = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
01172                     if (!$isPage)   $removeTheRestFlag=1;   // If there was no page selected, the user apparently did not have read access to the current PAGE (not position in rootline) and we set the remove-flag...
01173                 } else {    // Dont go here, if there is no backend user logged in.
01174                     $removeTheRestFlag=1;
01175                 }
01176             }
01177             if ($removeTheRestFlag) {
01178                 $this->pageNotFound=2;          // Page is 'not found' in case a subsection was found and not accessible, code 2
01179                 unset($this->rootLine[$a]);
01180             }
01181         }
01182         return $removeTheRestFlag;
01183     }
01184 
01185     /**
01186      * Checks page record for enableFields
01187      * Returns true if enableFields does not disable the page record.
01188      * Takes notice of the ->showHiddenPage flag and uses SIM_ACCESS_TIME for start/endtime evaluation
01189      *
01190      * @param   array       The page record to evaluate (needs fields: hidden, starttime, endtime, fe_group)
01191      * @param   boolean     Bypass group-check
01192      * @return  boolean     True, if record is viewable.
01193      * @see tslib_cObj::getTreeList(), checkPagerecordForIncludeSection()
01194      */
01195     function checkEnableFields($row,$bypassGroupCheck=FALSE)    {
01196         if ((!$row['hidden'] || $this->showHiddenPage)
01197             && $row['starttime']<=$GLOBALS['SIM_ACCESS_TIME']
01198             && ($row['endtime']==0 || $row['endtime']>$GLOBALS['SIM_ACCESS_TIME'])
01199             && ($bypassGroupCheck || $this->checkPageGroupAccess($row))
01200         ) { return TRUE; }
01201     }
01202 
01203     /**
01204      * Check group access against a page record
01205      *
01206      * @param   array       The page record to evaluate (needs field: fe_group)
01207      * @param   mixed       List of group id's (comma list or array). Default is $this->gr_list
01208      * @return  boolean     True, if group access is granted.
01209      * @access private
01210      */
01211     function checkPageGroupAccess($row, $groupList=NULL) {
01212         if(is_null($groupList)) {
01213             $groupList = $this->gr_list;
01214         }
01215         if(!is_array($groupList)) {
01216             $groupList = explode(',', $groupList);
01217         }
01218         $pageGroupList = explode(',', $row['fe_group'] ? $row['fe_group'] : 0);
01219         return count(array_intersect($groupList, $pageGroupList)) > 0;
01220     }
01221 
01222     /**
01223      * Checks page record for include section
01224      *
01225      * @param   array       The page record to evaluate (needs fields: extendToSubpages + hidden, starttime, endtime, fe_group)
01226      * @return  boolean     Returns true if either extendToSubpages is not checked or if the enableFields does not disable the page record.
01227      * @access private
01228      * @see checkEnableFields(), tslib_cObj::getTreeList(), checkRootlineForIncludeSection()
01229      */
01230     function checkPagerecordForIncludeSection($row) {
01231         return (!$row['extendToSubpages'] || $this->checkEnableFields($row)) ? 1 : 0;
01232     }
01233 
01234     /**
01235      * Checks if logins are allowed in the current branch of the page tree. Traverses the full root line and returns TRUE if logins are OK, otherwise false (and then the login user must be unset!)
01236      *
01237      * @return  boolean     returns TRUE if logins are OK, otherwise false (and then the login user must be unset!)
01238      */
01239     function checkIfLoginAllowedInBranch()  {
01240 
01241             // Initialize:
01242         $c = count($this->rootLine);
01243         $disable = FALSE;
01244 
01245             // Traverse root line from root and outwards:
01246         for ($a=0; $a<$c; $a++) {
01247 
01248                 // If a value is set for login state:
01249             if ($this->rootLine[$a]['fe_login_mode'] > 0)   {
01250 
01251                     // Determine state from value:
01252                 if ((int)$this->rootLine[$a]['fe_login_mode'] === 1)    {
01253                     $disable = TRUE;
01254                     $this->loginAllowedInBranch_mode = 'all';
01255                 } elseif ((int)$this->rootLine[$a]['fe_login_mode'] === 3)  {
01256                     $disable = TRUE;
01257                     $this->loginAllowedInBranch_mode = 'groups';
01258                 } else {
01259                     $disable = FALSE;
01260                 }
01261             }
01262         }
01263 
01264         return !$disable;
01265     }
01266 
01267     /**
01268      * Analysing $this->pageAccessFailureHistory into a summary array telling which features disabled display and on which pages and conditions. That data can be used inside a page-not-found handler
01269      *
01270      * @return  array       Summary of why page access was not allowed.
01271      */
01272     function getPageAccessFailureReasons()  {
01273         $output = array();
01274 
01275         $combinedRecords = array_merge(
01276             is_array($this->pageAccessFailureHistory['direct_access']) ? $this->pageAccessFailureHistory['direct_access'] : array(array('fe_group'=>0)),    // Adding fake first record for direct access if none, otherwise $k==0 below will be indicating a sub-section record to be first direct_access record which is of course false!
01277             is_array($this->pageAccessFailureHistory['sub_section']) ? $this->pageAccessFailureHistory['sub_section'] : array()
01278         );
01279 
01280         if (count($combinedRecords))    {
01281             foreach($combinedRecords as $k => $pagerec) {
01282                 // If $k=0 then it is the very first page the original ID was pointing at and that will get a full check of course
01283                 // If $k>0 it is parent pages being tested. They are only significant for the access to the first page IF they had the extendToSubpages flag set, hence checked only then!
01284                 if (!$k || $pagerec['extendToSubpages'])    {
01285                     if ($pagerec['hidden']) $output['hidden'][$pagerec['uid']] = TRUE;
01286                     if ($pagerec['starttime'] > $GLOBALS['SIM_ACCESS_TIME'])    $output['starttime'][$pagerec['uid']] = $pagerec['starttime'];
01287                     if ($pagerec['endtime']!=0 && $pagerec['endtime'] <= $GLOBALS['SIM_ACCESS_TIME'])   $output['endtime'][$pagerec['uid']] = $pagerec['endtime'];
01288                     if (!$this->checkPageGroupAccess($pagerec)) $output['fe_group'][$pagerec['uid']] = $pagerec['fe_group'];
01289                 }
01290             }
01291         }
01292 
01293         return $output;
01294     }
01295 
01296     /**
01297      * This checks if there are ARGV-parameters in the QUERY_STRING and if so, those are used for the id
01298      * $this->id must be 'false' in order for any processing to happen in here
01299      * If an id/alias value is extracted from the QUERY_STRING it is set in $this->id
01300      *
01301      * @return  void
01302      * @access private
01303      */
01304     function setIDfromArgV()    {
01305         if (!$this->id) {
01306             list($theAlias) = explode('&',t3lib_div::getIndpEnv('QUERY_STRING'));
01307             $theAlias = trim($theAlias);
01308             $this->id = ($theAlias != '' && strpos($theAlias, '=') === false) ? $theAlias : 0;
01309         }
01310     }
01311 
01312     /**
01313      * Gets ->page and ->rootline information based on ->id. ->id may change during this operation.
01314      * If not inside domain, then default to first page in domain.
01315      *
01316      * @param   integer     Page uid of the page where the found domain record is (pid of the domain record)
01317      * @return  void
01318      * @access private
01319      */
01320     function getPageAndRootlineWithDomain($domainStartPage) {
01321         $this->getPageAndRootline();
01322 
01323         // Checks if the $domain-startpage is in the rootLine. This is necessary so that references to page-id's from other domains are not possible.
01324         if ($domainStartPage && is_array($this->rootLine)) {
01325             $idFound = 0;
01326             foreach ($this->rootLine as $key => $val) {
01327                 if ($val['uid']==$domainStartPage)  {
01328                     $idFound=1;
01329                     break;
01330                 }
01331             }
01332             if (!$idFound)  {
01333                 $this->pageNotFound=3;          // Page is 'not found' in case the id was outside the domain, code 3
01334                 $this->id = $domainStartPage;
01335                 $this->getPageAndRootline();        //re-get the page and rootline if the id was not found.
01336             }
01337         }
01338     }
01339 
01340     /**
01341      * Sets sys_page where-clause
01342      *
01343      * @return  void
01344      * @access private
01345      */
01346     function setSysPageWhereClause()    {
01347         $this->sys_page->where_hid_del.=' AND pages.doktype<200';
01348         $this->sys_page->where_groupAccess = $this->sys_page->getMultipleGroupsWhereClause('pages.fe_group', 'pages');
01349     }
01350 
01351     /**
01352      * Looking up a domain record based on HTTP_HOST
01353      *
01354      * @param   boolean     If set, it looks "recursively" meaning that a domain like "123.456.typo3.com" would find a domain record like "typo3.com" if "123.456.typo3.com" or "456.typo3.com" did not exist.
01355      * @return  integer     Returns the page id of the page where the domain record was found.
01356      * @access private
01357      */
01358     function findDomainRecord($recursive=0) {
01359         if ($recursive) {
01360             $host = explode('.',t3lib_div::getIndpEnv('HTTP_HOST'));
01361             while(count($host)) {
01362                 $pageUid = $this->sys_page->getDomainStartPage(implode('.',$host),t3lib_div::getIndpEnv('SCRIPT_NAME'),t3lib_div::getIndpEnv('REQUEST_URI'));
01363                 if ($pageUid)   return $pageUid; else array_shift($host);
01364             }
01365             return $pageUid;
01366         } else {
01367             return $this->sys_page->getDomainStartPage(t3lib_div::getIndpEnv('HTTP_HOST'),t3lib_div::getIndpEnv('SCRIPT_NAME'),t3lib_div::getIndpEnv('REQUEST_URI'));
01368         }
01369     }
01370 
01371     /**
01372      * Page unavailable handler for use in frontend plugins from extensions.
01373      *
01374      * @param   string      Reason text
01375      * @param   string      HTTP header to send
01376      * @return  void        Function exits.
01377      */
01378     function pageUnavailableAndExit($reason='', $header='') {
01379         $header = $header ? $header : $this->TYPO3_CONF_VARS['FE']['pageUnavailable_handling_statheader'];
01380         $this->pageUnavailableHandler($this->TYPO3_CONF_VARS['FE']['pageUnavailable_handling'], $header, $reason);
01381         exit;
01382     }
01383 
01384     /**
01385      * Page-not-found handler for use in frontend plugins from extensions.
01386      *
01387      * @param   string      Reason text
01388      * @param   string      HTTP header to send
01389      * @return  void        Function exits.
01390      */
01391     function pageNotFoundAndExit($reason='', $header='')    {
01392         $header = $header ? $header : $this->TYPO3_CONF_VARS['FE']['pageNotFound_handling_statheader'];
01393         $this->pageNotFoundHandler($this->TYPO3_CONF_VARS['FE']['pageNotFound_handling'], $header, $reason);
01394         exit;
01395     }
01396 
01397     /**
01398      * Checks whether the pageUnavailableHandler should be used. To be used, pageUnavailable_handling must be set
01399      * and devIPMask must not match the current visitor's IP address.
01400      *
01401      * @return  boolean     True/false whether the pageUnavailable_handler should be used.
01402      */
01403     function checkPageUnavailableHandler()  {
01404         if($this->TYPO3_CONF_VARS['FE']['pageUnavailable_handling'] &&
01405            !t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $this->TYPO3_CONF_VARS['SYS']['devIPmask'])) {
01406             $checkPageUnavailableHandler = TRUE;
01407         } else {
01408             $checkPageUnavailableHandler = FALSE;
01409         }
01410 
01411         return $checkPageUnavailableHandler;
01412     }
01413 
01414     /**
01415      * Page unavailable handler. Acts a wrapper for the pageErrorHandler method.
01416      *
01417      * @param   mixed       Which type of handling; If a true PHP-boolean or TRUE then a ->t3lib_message_ErrorPageMessage is outputted. If integer an error message with that number is shown. Otherwise the $code value is expected to be a "Location:" header value.
01418      * @param   string      If set, this is passed directly to the PHP function, header()
01419      * @param   string      If set, error messages will also mention this as the reason for the page-not-found.
01420      * @return  void        (The function exits!)
01421      */
01422     function pageUnavailableHandler($code, $header, $reason)    {
01423         $this->pageErrorHandler($code, $header, $reason);
01424     }
01425 
01426     /**
01427      * Page not found handler. Acts a wrapper for the pageErrorHandler method.
01428      *
01429      * @param   mixed       Which type of handling; If a true PHP-boolean or TRUE then a ->t3lib_message_ErrorPageMessage is outputted. If integer an error message with that number is shown. Otherwise the $code value is expected to be a "Location:" header value.
01430      * @param   string      If set, this is passed directly to the PHP function, header()
01431      * @param   string      If set, error messages will also mention this as the reason for the page-not-found.
01432      * @return  void        (The function exits!)
01433      */
01434     function pageNotFoundHandler($code, $header='', $reason='') {
01435         $this->pageErrorHandler($code, $header, $reason);
01436     }
01437 
01438     /**
01439      * Generic error page handler.
01440      * Exits.
01441      *
01442      * @param   mixed       Which type of handling; If a true PHP-boolean or TRUE then a ->t3lib_message_ErrorPageMessage is outputted. If integer an error message with that number is shown. Otherwise the $code value is expected to be a "Location:" header value.
01443      * @param   string      If set, this is passed directly to the PHP function, header()
01444      * @param   string      If set, error messages will also mention this as the reason for the page-not-found.
01445      * @return  void        (The function exits!)
01446      */
01447     function pageErrorHandler($code, $header='', $reason='')    {
01448 
01449             // Issue header in any case:
01450         if ($header)    {
01451             $headerArr = preg_split('/\r|\n/',$header,-1,PREG_SPLIT_NO_EMPTY);
01452             foreach ($headerArr as $header) {
01453                 header ($header);
01454             }
01455         }
01456 
01457             // Create response:
01458         if (gettype($code)=='boolean' || !strcmp($code,1))  {   // Simply boolean; Just shows TYPO3 error page with reason:
01459             throw new RuntimeException('The page did not exist or was inaccessible.' . ($reason ? ' Reason: ' . htmlspecialchars($reason) : ''));
01460         } elseif (t3lib_div::isFirstPartOfStr($code,'USER_FUNCTION:')) {
01461             $funcRef = trim(substr($code,14));
01462             $params = array(
01463                 'currentUrl' => t3lib_div::getIndpEnv('REQUEST_URI'),
01464                 'reasonText' => $reason,
01465                 'pageAccessFailureReasons' => $this->getPageAccessFailureReasons()
01466             );
01467             echo t3lib_div::callUserFunction($funcRef,$params,$this);
01468         } elseif (t3lib_div::isFirstPartOfStr($code,'READFILE:')) {
01469             $readFile = t3lib_div::getFileAbsFileName(trim(substr($code,9)));
01470             if (@is_file($readFile))    {
01471                 $fileContent = t3lib_div::getUrl($readFile);
01472                 $fileContent = str_replace('###CURRENT_URL###', t3lib_div::getIndpEnv('REQUEST_URI'), $fileContent);
01473                 $fileContent = str_replace('###REASON###', htmlspecialchars($reason), $fileContent);
01474                 echo $fileContent;
01475             } else {
01476                 throw new RuntimeException('Configuration Error: 404 page "' . $readFile.'" could not be found.');
01477             }
01478         } elseif (t3lib_div::isFirstPartOfStr($code,'REDIRECT:')) {
01479             t3lib_utility_Http::redirect(substr($code, 9));
01480         } elseif (strlen($code))    {
01481                 // Check if URL is relative
01482             $url_parts = parse_url($code);
01483             if ($url_parts['host'] == '')   {
01484                 $url_parts['host'] = t3lib_div::getIndpEnv('HTTP_HOST');
01485                 $code = t3lib_div::getIndpEnv('TYPO3_REQUEST_HOST') . $code;
01486                 $checkBaseTag = false;
01487             } else {
01488                 $checkBaseTag = true;
01489             }
01490 
01491                 // Check recursion
01492             if ($code == t3lib_div::getIndpEnv('TYPO3_REQUEST_URL')) {
01493                 if ($reason == '') {
01494                     $reason = 'Page cannot be found.';
01495                 }
01496                 $reason.= LF . LF . 'Additionally, ' . $code . ' was not found while trying to retrieve the error document.';
01497                 throw new RuntimeException('Reason: ' . nl2br(htmlspecialchars($reason)));
01498             }
01499 
01500                 // Prepare headers
01501             $headerArr = array(
01502                 'User-agent: ' . t3lib_div::getIndpEnv('HTTP_USER_AGENT'),
01503                 'Referer: ' . t3lib_div::getIndpEnv('TYPO3_REQUEST_URL')
01504             );
01505             $res = t3lib_div::getURL($code, 1, $headerArr);
01506 
01507                 // Header and content are separated by an empty line
01508             list($header, $content) = explode(CRLF . CRLF, $res, 2);
01509             $content.= CRLF;
01510 
01511             if (false === $res) {
01512                     // Last chance -- redirect
01513                 t3lib_utility_Http::redirect($code);
01514             } else {
01515 
01516                 $forwardHeaders = array(    // Forward these response headers to the client
01517                     'Content-Type:',
01518                 );
01519                 $headerArr = preg_split('/\r|\n/',$header,-1,PREG_SPLIT_NO_EMPTY);
01520                 foreach ($headerArr as $header) {
01521                     foreach ($forwardHeaders as $h) {
01522                         if (preg_match('/^'.$h.'/', $header))   {
01523                             header ($header);
01524                         }
01525                     }
01526                 }
01527                     // Put <base> if necesary
01528                 if ($checkBaseTag)  {
01529 
01530                         // If content already has <base> tag, we do not need to do anything
01531                     if (false === stristr($content, '<base '))  {
01532 
01533                             // Generate href for base tag
01534                         $base = $url_parts['scheme'] . '://';
01535                         if ($url_parts['user'] != '')   {
01536                             $base.= $url_parts['user'];
01537                             if ($url_parts['pass'] != '')   {
01538                                 $base.= ':' . $url_parts['pass'];
01539                             }
01540                             $base.= '@';
01541                         }
01542                         $base.= $url_parts['host'];
01543 
01544                             // Add path portion skipping possible file name
01545                         $base.= preg_replace('/(.*\/)[^\/]*/', '${1}', $url_parts['path']);
01546 
01547                             // Put it into content (generate also <head> if necessary)
01548                         $replacement = LF . '<base href="' . htmlentities($base) . '" />' . LF;
01549                         if (stristr($content, '<head>'))    {
01550                             $content = preg_replace('/(<head>)/i', '\1' . $replacement, $content);
01551                         } else {
01552                             $content = preg_replace('/(<html[^>]*>)/i', '\1<head>' . $replacement . '</head>', $content);
01553                         }
01554                     }
01555                 }
01556                 echo $content;  // Output the content
01557             }
01558         } else {
01559             throw new RuntimeException($reason ? 'Reason: '.htmlspecialchars($reason) : 'Page cannot be found.');
01560         }
01561         exit();
01562     }
01563 
01564     /**
01565      * Fetches the integer page id for a page alias.
01566      * Looks if ->id is not an integer and if so it will search for a page alias and if found the page uid of that page is stored in $this->id
01567      *
01568      * @return  void
01569      * @access private
01570      */
01571     function checkAndSetAlias() {
01572         if ($this->id && !t3lib_div::testInt($this->id))    {
01573             $aid = $this->sys_page->getPageIdFromAlias($this->id);
01574             if ($aid)   {
01575                 $this->id = $aid;
01576             } else {
01577                 $this->pageNotFound = 4;
01578             }
01579         }
01580     }
01581 
01582     /**
01583      * Analyzes the second part of a id-string (after the "+"), looking for B6 or M5 encoding and if found it will resolve it and restore the variables in global $_GET
01584      * If values for ->cHash, ->no_cache, ->jumpurl and ->MP is found, they are also loaded into the internal vars of this class.
01585      *
01586      * @param   string      String to analyze
01587      * @return  void
01588      * @access private
01589      * @deprecated since TYPO3 4.3, will be removed in TYPO3 4.5, please use the "simulatestatic" sysext directly
01590      * @todo    Deprecated but still used in the Core!
01591      */
01592     function idPartsAnalyze($str)   {
01593         $GET_VARS = '';
01594         switch(substr($str,0,2))    {
01595             case 'B6':
01596                 $addParams = base64_decode(str_replace('_','=',str_replace('-','/',substr($str,2))));
01597                 parse_str($addParams,$GET_VARS);
01598             break;
01599             case 'M5':
01600                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('params', 'cache_md5params', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr(substr($str,2), 'cache_md5params'));
01601                 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
01602 
01603                 $this->updateMD5paramsRecord(substr($str,2));
01604                 parse_str($row['params'],$GET_VARS);
01605             break;
01606         }
01607 
01608         $this->mergingWithGetVars($GET_VARS);
01609     }
01610 
01611     /**
01612      * Merging values into the global $_GET
01613      *
01614      * @param   array       Array of key/value pairs that will be merged into the current GET-vars. (Non-escaped values)
01615      * @return  void
01616      */
01617     function mergingWithGetVars($GET_VARS)  {
01618         if (is_array($GET_VARS))    {
01619             $realGet = t3lib_div::_GET();       // Getting $_GET var, unescaped.
01620             if (!is_array($realGet))    $realGet = array();
01621 
01622                 // Merge new values on top:
01623             $realGet = t3lib_div::array_merge_recursive_overrule($realGet,$GET_VARS);
01624 
01625                 // Write values back to $_GET:
01626             t3lib_div::_GETset($realGet);
01627 
01628                 // Setting these specifically (like in the init-function):
01629             if (isset($GET_VARS['type']))       $this->type = intval($GET_VARS['type']);
01630             if (isset($GET_VARS['cHash']))      $this->cHash = $GET_VARS['cHash'];
01631             if (isset($GET_VARS['jumpurl']))    $this->jumpurl = $GET_VARS['jumpurl'];
01632             if (isset($GET_VARS['MP']))         $this->MP = $this->TYPO3_CONF_VARS['FE']['enable_mount_pids'] ? $GET_VARS['MP'] : '';
01633 
01634             if (isset($GET_VARS['no_cache']) && $GET_VARS['no_cache'])  $this->set_no_cache();
01635         }
01636     }
01637 
01638     /**
01639      * Looking for a ADMCMD_prev code, looks it up if found and returns configuration data.
01640      * Background: From the backend a request to the frontend to show a page, possibly with workspace preview can be "recorded" and associated with a keyword. When the frontend is requested with this keyword the associated request parameters are restored from the database AND the backend user is loaded - only for that request.
01641      * The main point is that a special URL valid for a limited time, eg. http://localhost/typo3site/index.php?ADMCMD_prev=035d9bf938bd23cb657735f68a8cedbf will open up for a preview that doesn't require login. Thus it's useful for sending in an email to someone without backend account.
01642      * This can also be used to generate previews of hidden pages, start/endtimes, usergroups and those other settings from the Admin Panel - just not implemented yet.
01643      *
01644      * @return  array       Preview configuration array from sys_preview record.
01645      * @see t3lib_BEfunc::compilePreviewKeyword()
01646      */
01647     function ADMCMD_preview(){
01648         $inputCode = t3lib_div::_GP('ADMCMD_prev');
01649 
01650             // If no inputcode and a cookie is set, load input code from cookie:
01651         if (!$inputCode && $_COOKIE['ADMCMD_prev']) {
01652             $inputCode = $_COOKIE['ADMCMD_prev'];
01653         }
01654 
01655             // If inputcode now, look up the settings:
01656         if ($inputCode) {
01657 
01658             if ($inputCode=='LOGOUT') { // "log out":
01659                 SetCookie('ADMCMD_prev', '', 0, t3lib_div::getIndpEnv('TYPO3_SITE_PATH'));
01660                 if ($this->TYPO3_CONF_VARS['FE']['workspacePreviewLogoutTemplate']) {
01661                     if (@is_file(PATH_site.$this->TYPO3_CONF_VARS['FE']['workspacePreviewLogoutTemplate'])) {
01662                         $message = t3lib_div::getUrl(PATH_site.$this->TYPO3_CONF_VARS['FE']['workspacePreviewLogoutTemplate']);
01663                     } else {
01664                         $message = '<strong>ERROR!</strong><br>Template File "'.$this->TYPO3_CONF_VARS['FE']['workspacePreviewLogoutTemplate'].'" configured with $TYPO3_CONF_VARS["FE"]["workspacePreviewLogoutTemplate"] not found. Please contact webmaster about this problem.';
01665                     }
01666                 } else {
01667                     $message = 'You logged out from Workspace preview mode. Click this link to <a href="%1$s">go back to the website</a>';
01668                 }
01669 
01670                 $returnUrl = t3lib_div::sanitizeLocalUrl(t3lib_div::_GET('returnUrl'));
01671                 die(sprintf($message,
01672                     htmlspecialchars(preg_replace('/\&?ADMCMD_prev=[[:alnum:]]+/', '', $returnUrl))
01673                     ));
01674             }
01675 
01676                 // Look for keyword configuration record:
01677             $previewData = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
01678                 '*',
01679                 'sys_preview',
01680                 'keyword='.$GLOBALS['TYPO3_DB']->fullQuoteStr($inputCode, 'sys_preview').
01681                     ' AND endtime>' . $GLOBALS['EXEC_TIME']
01682             );
01683 
01684                 // Get: Backend login status, Frontend login status
01685                 // - Make sure to remove fe/be cookies (temporarily); BE already done in ADMCMD_preview_postInit()
01686             if (is_array($previewData)) {
01687                 if (!count(t3lib_div::_POST())) {
01688                         // Unserialize configuration:
01689                     $previewConfig = unserialize($previewData['config']);
01690 
01691                     if ($previewConfig['fullWorkspace']) {  // For full workspace preview we only ADD a get variable to set the preview of the workspace - so all other Get vars are accepted. Hope this is not a security problem. Still posting is not allowed and even if a backend user get initialized it shouldn't lead to situations where users can use those credentials.
01692 
01693                             // Set the workspace preview value:
01694                         t3lib_div::_GETset($previewConfig['fullWorkspace'],'ADMCMD_previewWS');
01695 
01696                             // If ADMCMD_prev is set the $inputCode value cannot come from a cookie and we set that cookie here. Next time it will be found from the cookie if ADMCMD_prev is not set again...
01697                         if (t3lib_div::_GP('ADMCMD_prev'))  {
01698                             SetCookie('ADMCMD_prev', t3lib_div::_GP('ADMCMD_prev'), 0, t3lib_div::getIndpEnv('TYPO3_SITE_PATH'));   // Lifetime is 1 hour, does it matter much? Requires the user to click the link from their email again if it expires.
01699                         }
01700                         return $previewConfig;
01701                     } elseif (t3lib_div::getIndpEnv('TYPO3_SITE_URL').'index.php?ADMCMD_prev='.$inputCode === t3lib_div::getIndpEnv('TYPO3_REQUEST_URL'))   {
01702 
01703                             // Set GET variables:
01704                         $GET_VARS = '';
01705                         parse_str($previewConfig['getVars'], $GET_VARS);
01706                         t3lib_div::_GETset($GET_VARS);
01707 
01708                             // Return preview keyword configuration:
01709                         return $previewConfig;
01710                     } else die(htmlspecialchars('Request URL did not match "'.t3lib_div::getIndpEnv('TYPO3_SITE_URL').'index.php?ADMCMD_prev='.$inputCode.'"'));    // This check is to prevent people from setting additional GET vars via realurl or other URL path based ways of passing parameters.
01711                 } else die('POST requests are incompatible with keyword preview.');
01712             } else die('ADMCMD command could not be executed! (No keyword configuration found)');
01713         }
01714     }
01715 
01716     /**
01717      * Configuration after initialization of TSFE object.
01718      * Basically this unsets the BE cookie if any and forces the BE user set according to the preview configuration.
01719      *
01720      * @param   array       Preview configuration, see ADMCMD_preview()
01721      * @return  void
01722      * @see ADMCMD_preview(), index_ts.php
01723      */
01724     function ADMCMD_preview_postInit($previewConfig){
01725         if (is_array($previewConfig))   {
01726 
01727                 // Clear cookies:
01728             unset($_COOKIE['be_typo_user']);
01729             $this->ADMCMD_preview_BEUSER_uid = $previewConfig['BEUSER_uid'];
01730 
01731         } else die('Error in preview configuration.');
01732     }
01733 
01734 
01735 
01736 
01737 
01738 
01739 
01740 
01741 
01742 
01743 
01744     /********************************************
01745      *
01746      * Template and caching related functions.
01747      *
01748      *******************************************/
01749 
01750     /**
01751      * Calculates a hash string based on additional parameters in the url. This is used to cache pages with more parameters than just id and type
01752      *
01753      * @return  void
01754      * @see reqCHash()
01755      */
01756     function makeCacheHash()    {
01757         // No need to test anything if caching was already disabled.
01758         if ($this->no_cache && !$this->TYPO3_CONF_VARS['FE']['pageNotFoundOnCHashError']) {
01759             return;
01760         }
01761 
01762         $GET = t3lib_div::_GET();
01763         if ($this->cHash && is_array($GET)) {
01764             $this->cHash_array = t3lib_div::cHashParams(t3lib_div::implodeArrayForUrl('',$GET));
01765             $cHash_calc = t3lib_div::calculateCHash($this->cHash_array);
01766 
01767             if ($cHash_calc!=$this->cHash)  {
01768                 if ($this->TYPO3_CONF_VARS['FE']['pageNotFoundOnCHashError']) {
01769                     $this->pageNotFoundAndExit('Request parameters could not be validated (&cHash comparison failed)');
01770                 } else {
01771                     $this->set_no_cache();
01772                     $GLOBALS['TT']->setTSlogMessage('The incoming cHash "'.$this->cHash.'" and calculated cHash "'.$cHash_calc.'" did not match, so caching was disabled. The fieldlist used was "'.implode(',',array_keys($this->cHash_array)).'"',2);
01773                 }
01774             }
01775         }
01776     }
01777 
01778     /**
01779      * Will disable caching if the cHash value was not set.
01780      * This function should be called to check the _existence_ of "&cHash" whenever a plugin generating cachable output is using extra GET variables. If there _is_ a cHash value the validation of it automatically takes place in makeCacheHash() (see above)
01781      *
01782      * @return  void
01783      * @see makeCacheHash(), tslib_pibase::pi_cHashCheck()
01784      */
01785     function reqCHash() {
01786         if (!$this->cHash)  {
01787             if ($this->TYPO3_CONF_VARS['FE']['pageNotFoundOnCHashError']) {
01788                 if ($this->tempContent) { $this->clearPageCacheContent(); }
01789                 $this->pageNotFoundAndExit('Request parameters could not be validated (&cHash empty)');
01790             } else {
01791                 $this->set_no_cache();
01792                 $GLOBALS['TT']->setTSlogMessage('TSFE->reqCHash(): No &cHash parameter was sent for GET vars though required so caching is disabled',2);
01793             }
01794         }
01795     }
01796 
01797     /**
01798      * Splits the input query-parameters into an array with certain parameters filtered out.
01799      * Used to create the cHash value
01800      *
01801      * @param   string      Query-parameters: "&xxx=yyy&zzz=uuu"
01802      * @return  array       Array with key/value pairs of query-parameters WITHOUT a certain list of variable names (like id, type, no_cache etc) and WITH a variable, encryptionKey, specific for this server/installation
01803      * @access private
01804      * @see makeCacheHash(), tslib_cObj::typoLink()
01805      * @obsolete
01806      */
01807     function cHashParams($addQueryParams) {
01808         return t3lib_div::cHashParams($addQueryParams);
01809     }
01810 
01811     /**
01812      * Initialize the TypoScript template parser
01813      *
01814      * @return  void
01815      */
01816     function initTemplate() {
01817         $this->tmpl = t3lib_div::makeInstance('t3lib_TStemplate');
01818         $this->tmpl->init();
01819         $this->tmpl->tt_track= $this->beUserLogin ? 1 : 0;
01820     }
01821 
01822     /**
01823      * See if page is in cache and get it if so
01824      * Stores the page content in $this->content if something is found.
01825      *
01826      * @return  void
01827      */
01828     function getFromCache() {
01829         if (!$this->no_cache) {
01830             $cc = $this->tmpl->getCurrentPageData();
01831 
01832             if (!is_array($cc)) {
01833                 $key = $this->id.'::'.$this->MP;
01834                 $isLocked = $this->acquirePageGenerationLock($this->pagesection_lockObj, $key); // Returns true if the lock is active now
01835 
01836                 if (!$isLocked) {
01837                         // Lock is no longer active, the data in "cache_pagesection" is now ready
01838                     $cc = $this->tmpl->getCurrentPageData();
01839                     if (is_array($cc)) {
01840                         $this->releasePageGenerationLock($this->pagesection_lockObj);   // Release the lock
01841                     }
01842                 }
01843             }
01844 
01845             if (is_array($cc)) {
01846                     // BE CAREFUL to change the content of the cc-array. This array is serialized and an md5-hash based on this is used for caching the page.
01847                     // If this hash is not the same in here in this section and after page-generation, then the page will not be properly cached!
01848                 $cc = $this->tmpl->matching($cc);   // This array is an identification of the template. If $this->all is empty it's because the template-data is not cached, which it must be.
01849                 ksort($cc);
01850 
01851                 $this->all = $cc;
01852             }
01853             unset($cc);
01854         }
01855 
01856         $this->content = '';    // clearing the content-variable, which will hold the pagecontent
01857         unset($this->config);   // Unsetting the lowlevel config
01858         $this->cacheContentFlag = 0;
01859 
01860             // Look for page in cache only if caching is not disabled and if a shift-reload is not sent to the server.
01861         if (!$this->no_cache && !$this->headerNoCache()) {
01862             $lockHash = $this->getLockHash();
01863 
01864             if ($this->all) {
01865                 $this->newHash = $this->getHash();
01866 
01867                 $GLOBALS['TT']->push('Cache Row','');
01868                     $row = $this->getFromCache_queryRow();
01869 
01870                     if (!is_array($row)) {
01871                         $isLocked = $this->acquirePageGenerationLock($this->pages_lockObj, $lockHash);
01872 
01873                         if (!$isLocked) {
01874                                 // Lock is no longer active, the data in "cache_pages" is now ready
01875                             $row = $this->getFromCache_queryRow();
01876                             if (is_array($row)) {
01877                                 $this->releasePageGenerationLock($this->pages_lockObj); // Release the lock
01878                             }
01879                         }
01880                     }
01881 
01882                     if (is_array($row)) {
01883                             // Release this lock
01884                         $this->releasePageGenerationLock($this->pages_lockObj);
01885 
01886                             // Call hook when a page is retrieved from cache:
01887                         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['pageLoadedFromCache']))  {
01888                             $_params = array('pObj' => &$this, 'cache_pages_row' => &$row);
01889                             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['pageLoadedFromCache'] as $_funcRef)   {
01890                                 t3lib_div::callUserFunction($_funcRef,$_params,$this);
01891                             }
01892                         }
01893 
01894                         $this->config = (array)unserialize($row['cache_data']);     // Fetches the lowlevel config stored with the cached data
01895                         $this->content = (TYPO3_UseCachingFramework ? $row['content'] : $row['HTML']);  // Getting the content
01896                         $this->tempContent = $row['temp_content'];  // Flag for temp content
01897                         $this->cacheContentFlag = 1;    // Setting flag, so we know, that some cached content has been loaded
01898                         $this->cacheExpires = $row['expires'];
01899 
01900                         if ($this->TYPO3_CONF_VARS['FE']['debug'] || (isset($this->config['config']['debug']) && $this->config['config']['debug'])) {
01901                             $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'];
01902                             $timeFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
01903 
01904                             $this->content.= LF.'<!-- Cached page generated '.date($dateFormat.' '.$timeFormat, $row['tstamp']).'. Expires '.Date($dateFormat.' '.$timeFormat, $row['expires']).' -->';
01905                         }
01906                     }
01907                 $GLOBALS['TT']->pull();
01908 
01909             } else {
01910                 $this->acquirePageGenerationLock($this->pages_lockObj, $lockHash);
01911             }
01912         }
01913     }
01914 
01915     /**
01916      * Returning the cached version of page with hash = newHash
01917      *
01918      * @return  array       Cached row, if any. Otherwise void.
01919      */
01920     function getFromCache_queryRow() {
01921         if (TYPO3_UseCachingFramework) {
01922             $GLOBALS['TT']->push('Cache Query', '');
01923             $row = $this->pageCache->get($this->newHash);
01924             $GLOBALS['TT']->pull();
01925         } else {
01926             $GLOBALS['TT']->push('Cache Query','');
01927             $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
01928                 'S.*',
01929                 'cache_pages S,pages P',
01930                 'S.hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->newHash, 'cache_pages').'
01931                     AND S.page_id=P.uid
01932                     AND S.expires > '.intval($GLOBALS['ACCESS_TIME']).'
01933                     AND P.deleted=0
01934                     AND P.hidden=0
01935                     AND P.starttime<='.intval($GLOBALS['ACCESS_TIME']).'
01936                     AND (P.endtime=0 OR P.endtime>'.intval($GLOBALS['ACCESS_TIME']).')'
01937             );
01938             $GLOBALS['TT']->pull();
01939 
01940             if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
01941                 $this->pageCachePostProcess($row,'get');
01942             }
01943             $GLOBALS['TYPO3_DB']->sql_free_result($res);
01944         }
01945         return $row;
01946     }
01947 
01948     /**
01949      * Detecting if shift-reload has been clicked
01950      * Will not be called if re-generation of page happens by other reasons (for instance that the page is not in cache yet!)
01951      * Also, a backend user MUST be logged in for the shift-reload to be detected due to DoS-attack-security reasons.
01952      *
01953      * @return  boolean     If shift-reload in client browser has been clicked, disable getting cached page (and regenerate it).
01954      */
01955     function headerNoCache()    {
01956         $disableAcquireCacheData = FALSE;
01957 
01958         if ($this->beUserLogin) {
01959             if (strtolower($_SERVER['HTTP_CACHE_CONTROL'])==='no-cache' || strtolower($_SERVER['HTTP_PRAGMA'])==='no-cache')    {
01960                 $disableAcquireCacheData = TRUE;
01961             }
01962         }
01963 
01964             // Call hook for possible by-pass of requiring of page cache (for recaching purpose)
01965         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['headerNoCache']))    {
01966             $_params = array('pObj' => &$this, 'disableAcquireCacheData' => &$disableAcquireCacheData);
01967             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['headerNoCache'] as $_funcRef) {
01968                 t3lib_div::callUserFunction($_funcRef,$_params,$this);
01969             }
01970         }
01971 
01972         return $disableAcquireCacheData;
01973     }
01974 
01975     /**
01976      * Calculates the cache-hash
01977      * This hash is unique to the template, the variables ->id, ->type, ->gr_list (list of groups), ->MP (Mount Points) and cHash array
01978      * Used to get and later store the cached data.
01979      *
01980      * @return  string      MD5 hash of $this->hash_base which is a serialized version of there variables.
01981      * @access private
01982      * @see getFromCache(), getLockHash()
01983      */
01984     function getHash()  {
01985         $this->hash_base = serialize(
01986             array(
01987                 'all' => $this->all,
01988                 'id' => intval($this->id),
01989                 'type' => intval($this->type),
01990                 'gr_list' => (string)$this->gr_list,
01991                 'MP' => (string)$this->MP,
01992                 'cHash' => $this->cHash_array,
01993                 'domainStartPage' => $this->domainStartPage,
01994             )
01995         );
01996 
01997         return md5($this->hash_base);
01998     }
01999 
02000     /**
02001      * Calculates the lock-hash
02002      * This hash is unique to the above hash, except that it doesn't contain the template information in $this->all.
02003      *
02004      * @return  string      MD5 hash
02005      * @access private
02006      * @see getFromCache(), getHash()
02007      */
02008     function getLockHash()  {
02009         $lockHash = serialize(
02010             array(
02011                 'id' => intval($this->id),
02012                 'type' => intval($this->type),
02013                 'gr_list' => (string)$this->gr_list,
02014                 'MP' => (string)$this->MP,
02015                 'cHash' => $this->cHash_array,
02016                 'domainStartPage' => $this->domainStartPage,
02017             )
02018         );
02019 
02020         return md5($lockHash);
02021     }
02022 
02023     /**
02024      * Checks if config-array exists already but if not, gets it
02025      *
02026      * @return  void
02027      */
02028     function getConfigArray()   {
02029         $setStatPageName = false;
02030 
02031         if (!is_array($this->config) || is_array($this->config['INTincScript']) || $this->forceTemplateParsing) {   // If config is not set by the cache (which would be a major mistake somewhere) OR if INTincScripts-include-scripts have been registered, then we must parse the template in order to get it
02032                 $GLOBALS['TT']->push('Parse template','');
02033 
02034                 // Force parsing, if set?:
02035             $this->tmpl->forceTemplateParsing = $this->forceTemplateParsing;
02036 
02037                 // Start parsing the TS template. Might return cached version.
02038             $this->tmpl->start($this->rootLine);
02039                 $GLOBALS['TT']->pull();
02040 
02041             if ($this->tmpl->loaded)    {
02042                 $GLOBALS['TT']->push('Setting the config-array','');
02043             //  t3lib_div::print_array($this->tmpl->setup);
02044                 $this->sPre = $this->tmpl->setup['types.'][$this->type];    // toplevel - objArrayName
02045                 $this->pSetup = $this->tmpl->setup[$this->sPre.'.'];
02046 
02047                 if (!is_array($this->pSetup))   {
02048                     if ($this->checkPageUnavailableHandler())   {
02049                         $this->pageUnavailableAndExit('The page is not configured! [type= '.$this->type.']['.$this->sPre.']');
02050                     } else {
02051                         $message = 'The page is not configured! [type= '.$this->type.']['.$this->sPre.']';
02052                         header('HTTP/1.0 503 Service Temporarily Unavailable');
02053                         t3lib_div::sysLog($message, 'cms', t3lib_div::SYSLOG_SEVERITY_ERROR);
02054                         throw new RuntimeException($message);
02055                     }
02056                 } else {
02057                     $this->config['config'] = array();
02058 
02059                     // Filling the config-array, first with the main "config." part
02060                     if (is_array($this->tmpl->setup['config.'])) {
02061                         $this->config['config'] = $this->tmpl->setup['config.'];
02062                     }
02063                     // override it with the page/type-specific "config."
02064                     if (is_array($this->pSetup['config.'])) {
02065                         $this->config['config'] = t3lib_div::array_merge_recursive_overrule($this->config['config'], $this->pSetup['config.']);
02066                     }
02067 
02068                     if ($this->config['config']['typolinkEnableLinksAcrossDomains']) {
02069                         $this->config['config']['typolinkCheckRootline'] = true;
02070                     }
02071 
02072                         // Set default values for removeDefaultJS, inlineStyle2TempFile and minifyJS so CSS and JS are externalized/minified if compatversion is higher than 4.0
02073                     if (t3lib_div::compat_version('4.0')) {
02074                         if (!isset($this->config['config']['removeDefaultJS'])) {
02075                             $this->config['config']['removeDefaultJS'] = 'external';
02076                         }
02077                         if (!isset($this->config['config']['inlineStyle2TempFile'])) {
02078                             $this->config['config']['inlineStyle2TempFile'] = 1;
02079                         }
02080                         if (!isset($this->config['config']['minifyJS'])) {
02081                             $this->config['config']['minifyJS'] = 1;
02082                         }
02083                     }
02084 
02085                             // Processing for the config_array:
02086                     $this->config['rootLine'] = $this->tmpl->rootLine;
02087                     $this->config['mainScript'] = trim($this->config['config']['mainScript']) ? trim($this->config['config']['mainScript']) : 'index.php';
02088 
02089                         // Initialize statistics handling: Check filename and permissions
02090                     $setStatPageName = $this->statistics_init();
02091 
02092                     $this->config['FEData'] = $this->tmpl->setup['FEData'];
02093                     $this->config['FEData.'] = $this->tmpl->setup['FEData.'];
02094 
02095                         // class for render Header and Footer parts
02096                     $template = '';
02097                     if ($this->pSetup['pageHeaderFooterTemplateFile']) {
02098                         $file = $this->tmpl->getFileName($this->pSetup['pageHeaderFooterTemplateFile']);
02099                         if ($file) {
02100                             $this->setTemplateFile($file);
02101                         }
02102                     }
02103 
02104                 }
02105                 $GLOBALS['TT']->pull();
02106             } else {
02107                 if ($this->checkPageUnavailableHandler())   {
02108                     $this->pageUnavailableAndExit('No TypoScript template found!');
02109                 } else {
02110                     $message = 'No TypoScript template found!';
02111                     header('HTTP/1.0 503 Service Temporarily Unavailable');
02112                     t3lib_div::sysLog($message, 'cms', t3lib_div::SYSLOG_SEVERITY_ERROR);
02113                     throw new RuntimeException($message);
02114                 }
02115             }
02116         }
02117 
02118             // Initialize charset settings etc.
02119         $this->initLLvars();
02120 
02121             // We want nice names, so we need to handle the charset
02122         if ($setStatPageName)   {
02123             $this->statistics_init_pagename();
02124         }
02125 
02126             // No cache
02127         if ($this->config['config']['no_cache'])    { $this->set_no_cache(); }      // Set $this->no_cache true if the config.no_cache value is set!
02128 
02129             // merge GET with defaultGetVars
02130         if (!empty($this->config['config']['defaultGetVars.'])) {
02131             $modifiedGetVars = t3lib_div::array_merge_recursive_overrule(
02132                 t3lib_div::removeDotsFromTS($this->config['config']['defaultGetVars.']),
02133                 t3lib_div::_GET()
02134             );
02135 
02136             t3lib_div::_GETset($modifiedGetVars);
02137         }
02138 
02139             // Hook for postProcessing the configuration array
02140         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['configArrayPostProc'])) {
02141             $params = array('config' => &$this->config['config']);
02142             foreach ($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['configArrayPostProc'] as $funcRef) {
02143                 t3lib_div::callUserFunction($funcRef, $params, $this);
02144             }
02145         }
02146     }
02147 
02148 
02149 
02150 
02151 
02152 
02153 
02154 
02155 
02156 
02157 
02158 
02159 
02160 
02161     /********************************************
02162      *
02163      * Further initialization and data processing
02164      * (jumpurl/submission of forms)
02165      *
02166      *******************************************/
02167 
02168     /**
02169      * Get the compressed $TCA array for use in the front-end
02170      * A compressed $TCA array holds only the ctrl- and feInterface-part for each table. But the column-definitions are omitted in order to save some memory and be more efficient.
02171      * Operates on the global variable, $TCA
02172      *
02173      * @return  void
02174      * @see includeTCA()
02175      */
02176     function getCompressedTCarray() {
02177         global $TCA;
02178 
02179         $GLOBALS['TT']->push('Get Compressed TC array');
02180         if (!$this->TCAloaded)  {
02181                 // Create hash string for storage / retrieval of cached content:
02182             $tempHash = md5('tables.php:'.
02183                 filemtime(TYPO3_extTableDef_script ? PATH_typo3conf.TYPO3_extTableDef_script : PATH_t3lib.'stddb/tables.php').
02184                 (TYPO3_extTableDef_script?filemtime(PATH_typo3conf.TYPO3_extTableDef_script):'').
02185                 ($GLOBALS['TYPO3_LOADED_EXT']['_CACHEFILE'] ? filemtime(PATH_typo3conf.$GLOBALS['TYPO3_LOADED_EXT']['_CACHEFILE'].'_ext_tables.php') : '')
02186             );
02187 
02188             if ($this->TYPO3_CONF_VARS['EXT']['extCache'] != 0) {
02189                 // Try to fetch if cache is enabled
02190                 list($TCA, $this->TCAcachedExtras) = unserialize($this->sys_page->getHash($tempHash));
02191             }
02192 
02193                 // If no result, create it:
02194             if (!is_array($TCA))    {
02195                 $this->includeTCA(0);
02196                 $newTc = Array();
02197                 $this->TCAcachedExtras = array();   // Collects other information
02198 
02199                 foreach($TCA as $key => $val)       {
02200                     $newTc[$key]['ctrl'] = $val['ctrl'];
02201                     $newTc[$key]['feInterface'] = $val['feInterface'];
02202 
02203                         // Collect information about localization exclusion of fields:
02204                     t3lib_div::loadTCA($key);
02205                     if (is_array($TCA[$key]['columns']))    {
02206                         $this->TCAcachedExtras[$key]['l10n_mode'] = array();
02207                         foreach($TCA[$key]['columns'] as $fN => $fV)    {
02208                             if ($fV['l10n_mode'])   {
02209                                 $this->TCAcachedExtras[$key]['l10n_mode'][$fN] = $fV['l10n_mode'];
02210                             }
02211                         }
02212                     }
02213                 }
02214 
02215                 $TCA = $newTc;
02216                 // Store it in cache if cache is enabled
02217                 if ($this->TYPO3_CONF_VARS['EXT']['extCache'] != 0) {
02218                     $this->sys_page->storeHash($tempHash, serialize(array($newTc,$this->TCAcachedExtras)), 'SHORT_TC');
02219                 }
02220             }
02221         }
02222         $GLOBALS['TT']->pull();
02223     }
02224 
02225     /**
02226      * Includes TCA definitions from loaded extensions (ext_table.php files).
02227      * Normally in the frontend only a part of the global $TCA array is loaded,
02228      * namely the "ctrl" part. Thus it doesn't take up too much memory. To load
02229      * full TCA for the table, use t3lib_div::loadTCA($tableName) after calling
02230      * this function.
02231      *
02232      * @param   boolean     Probably, keep hands of this value. Just don't set it. (This may affect the first-ever time this function is called since if you set it to zero/false any subsequent call will still trigger the inclusion; In other words, this value will be set in $this->TCAloaded after inclusion and therefore if its false, another inclusion will be possible on the next call. See ->getCompressedTCarray())
02233      * @return  void
02234      * @see getCompressedTCarray()
02235      */
02236     function includeTCA($TCAloaded=1)   {
02237         global $TCA, $PAGES_TYPES, $TBE_MODULES;
02238         if (!$this->TCAloaded)  {
02239             $TCA = Array();
02240             include (TYPO3_tables_script ? PATH_typo3conf.TYPO3_tables_script : PATH_t3lib.'stddb/tables.php');
02241                 // Extension additions
02242             if ($GLOBALS['TYPO3_LOADED_EXT']['_CACHEFILE']) {
02243                 include(PATH_typo3conf.$GLOBALS['TYPO3_LOADED_EXT']['_CACHEFILE'].'_ext_tables.php');
02244             } else {
02245                 include(PATH_t3lib.'stddb/load_ext_tables.php');
02246             }
02247                 // ext-script
02248             if (TYPO3_extTableDef_script)   {
02249                 include (PATH_typo3conf.TYPO3_extTableDef_script);
02250             }
02251 
02252             $this->TCAloaded = $TCAloaded;
02253         }
02254     }
02255 
02256     /**
02257      * Setting the language key that will be used by the current page.
02258      * In this function it should be checked, 1) that this language exists, 2) that a page_overlay_record exists, .. and if not the default language, 0 (zero), should be set.
02259      *
02260      * @return  void
02261      * @access private
02262      */
02263     function settingLanguage()  {
02264 
02265         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['settingLanguage_preProcess']))   {
02266             $_params = array();
02267             foreach ($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['settingLanguage_preProcess'] as $_funcRef)   {
02268                 t3lib_div::callUserFunction($_funcRef, $_params, $this);
02269             }
02270         }
02271 
02272             // Get values from TypoScript:
02273         $this->sys_language_uid = $this->sys_language_content = intval($this->config['config']['sys_language_uid']);
02274         list($this->sys_language_mode,$sys_language_content) = t3lib_div::trimExplode(';', $this->config['config']['sys_language_mode']);
02275         $this->sys_language_contentOL = $this->config['config']['sys_language_overlay'];
02276 
02277             // If sys_language_uid is set to another language than default:
02278         if ($this->sys_language_uid>0)  {
02279 
02280                 // check whether a shortcut is overwritten by a translated page
02281                 // we can only do this now, as this is the place where we get
02282                 // to know about translations
02283             $this->checkTranslatedShortcut();
02284 
02285                 // Request the overlay record for the sys_language_uid:
02286             $olRec = $this->sys_page->getPageOverlay($this->id, $this->sys_language_uid);
02287             if (!count($olRec)) {
02288 
02289                     // If no OL record exists and a foreign language is asked for...
02290                 if ($this->sys_language_uid)    {
02291 
02292                         // If requested translation is not available:
02293                     if (t3lib_div::hideIfNotTranslated($this->page['l18n_cfg']))    {
02294                         $this->pageNotFoundAndExit('Page is not available in the requested language.');
02295                     } else {
02296                         switch((string)$this->sys_language_mode)    {
02297                             case 'strict':
02298                                 $this->pageNotFoundAndExit('Page is not available in the requested language (strict).');
02299                             break;
02300                             case 'content_fallback':
02301                                 $fallBackOrder = t3lib_div::intExplode(',', $sys_language_content);
02302                                 foreach($fallBackOrder as $orderValue)  {
02303                                     if (!strcmp($orderValue,'0') || count($this->sys_page->getPageOverlay($this->id, $orderValue))) {
02304                                         $this->sys_language_content = $orderValue;  // Setting content uid (but leaving the sys_language_uid)
02305                                         break;
02306                                     }
02307                                 }
02308                             break;
02309                             case 'ignore':
02310                                 $this->sys_language_content = $this->sys_language_uid;
02311                             break;
02312                             default:
02313                                     // Default is that everything defaults to the default language...
02314                                 $this->sys_language_uid = $this->sys_language_content = 0;
02315                             break;
02316                         }
02317                     }
02318                 }
02319             } else {
02320                     // Setting sys_language if an overlay record was found (which it is only if a language is used)
02321                 $this->page = $this->sys_page->getPageOverlay($this->page, $this->sys_language_uid);
02322             }
02323         }
02324 
02325             // Setting sys_language_uid inside sys-page:
02326         $this->sys_page->sys_language_uid = $this->sys_language_uid;
02327 
02328             // If default translation is not available:
02329         if ((!$this->sys_language_uid || !$this->sys_language_content) && $this->page['l18n_cfg']&1)    {
02330             $message = 'Page is not available in default language.';
02331             t3lib_div::sysLog($message, 'cms', t3lib_div::SYSLOG_SEVERITY_ERROR);
02332             $this->pageNotFoundAndExit($message);
02333         }
02334 
02335             // Updating content of the two rootLines IF the language key is set!
02336         if ($this->sys_language_uid && is_array($this->tmpl->rootLine)) {
02337             foreach ($this->tmpl->rootLine as $rLk => $value) {
02338                 $this->tmpl->rootLine[$rLk] = $this->sys_page->getPageOverlay($this->tmpl->rootLine[$rLk]);
02339             }
02340         }
02341         if ($this->sys_language_uid && is_array($this->rootLine))   {
02342             foreach ($this->rootLine as $rLk => $value) {
02343                 $this->rootLine[$rLk] = $this->sys_page->getPageOverlay($this->rootLine[$rLk]);
02344             }
02345         }
02346 
02347             // Finding the ISO code:
02348         if (t3lib_extMgm::isLoaded('static_info_tables') && $this->sys_language_content)    {   // using sys_language_content because the ISO code only (currently) affect content selection from FlexForms - which should follow "sys_language_content"
02349             $sys_language_row = $this->sys_page->getRawRecord('sys_language',$this->sys_language_content,'static_lang_isocode');
02350             if (is_array($sys_language_row) && $sys_language_row['static_lang_isocode'])    {
02351                 $stLrow = $this->sys_page->getRawRecord('static_languages',$sys_language_row['static_lang_isocode'],'lg_iso_2');
02352                 $this->sys_language_isocode = $stLrow['lg_iso_2'];
02353             }
02354         }
02355 
02356             // Setting softMergeIfNotBlank:
02357         $table_fields = t3lib_div::trimExplode(',', $this->config['config']['sys_language_softMergeIfNotBlank'],1);
02358         foreach($table_fields as $TF)   {
02359             list($tN,$fN) = explode(':',$TF);
02360             $this->TCAcachedExtras[$tN]['l10n_mode'][$fN] = 'mergeIfNotBlank';
02361         }
02362 
02363             // Setting softExclude:
02364         $table_fields = t3lib_div::trimExplode(',', $this->config['config']['sys_language_softExclude'],1);
02365         foreach($table_fields as $TF)   {
02366             list($tN,$fN) = explode(':',$TF);
02367             $this->TCAcachedExtras[$tN]['l10n_mode'][$fN] = 'exclude';
02368         }
02369 
02370         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['settingLanguage_postProcess']))  {
02371             $_params = array();
02372             foreach ($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['settingLanguage_postProcess'] as $_funcRef)  {
02373                 t3lib_div::callUserFunction($_funcRef, $_params, $this);
02374             }
02375         }
02376     }
02377 
02378     /**
02379      * Setting locale for frontend rendering
02380      *
02381      * @return  void
02382      */
02383     function settingLocale()    {
02384 
02385             // Setting locale
02386         if ($this->config['config']['locale_all'])  {
02387             # Change by René Fritz, 22/10 2002
02388             # there's a problem that PHP parses float values in scripts wrong if the locale LC_NUMERIC is set to something with a comma as decimal point
02389             # this does not work in php 4.2.3
02390             #setlocale('LC_ALL',$this->config['config']['locale_all']);
02391             #setlocale('LC_NUMERIC','en_US');
02392 
02393             # so we set all except LC_NUMERIC
02394             $locale = setlocale(LC_COLLATE, $this->config['config']['locale_all']);
02395             if ($locale) {
02396 
02397                     // PHP fatals with uppercase I characters in method names with turkish locale LC_CTYPE
02398                     // @see http://bugs.php.net/bug.php?id=35050
02399                 if (substr($this->config['config']['locale_all'], 0, 2) != 'tr') {
02400                     setlocale(LC_CTYPE, $this->config['config']['locale_all']);
02401                 }
02402 
02403                 setlocale(LC_MONETARY, $this->config['config']['locale_all']);
02404                 setlocale(LC_TIME, $this->config['config']['locale_all']);
02405 
02406                 $this->localeCharset = $this->csConvObj->get_locale_charset($this->config['config']['locale_all']);
02407             } else {
02408                 $GLOBALS['TT']->setTSlogMessage('Locale "'.htmlspecialchars($this->config['config']['locale_all']).'" not found.', 3);
02409             }
02410         }
02411     }
02412 
02413     /**
02414      * checks whether a translated shortcut page has a different shortcut
02415      * target than the original language page.
02416      * If that is the case, things get corrected to follow that alternative
02417      * shortcut
02418      *
02419      * @return  void
02420      * @author  Ingo Renner <ingo@typo3.org>
02421      */
02422     protected function checkTranslatedShortcut() {
02423 
02424         if (!is_null($this->originalShortcutPage)) {
02425             $originalShortcutPageOverlay = $this->sys_page->getPageOverlay($this->originalShortcutPage['uid'], $this->sys_language_uid);
02426 
02427             if (!empty($originalShortcutPageOverlay['shortcut']) && $originalShortcutPageOverlay['shortcut'] != $this->id) {
02428                     // the translation of the original shortcut page has a different shortcut target!
02429                     // set the correct page and id
02430 
02431                 $shortcut = $this->getPageShortcut(
02432                     $originalShortcutPageOverlay['shortcut'],
02433                     $originalShortcutPageOverlay['shortcut_mode'],
02434                     $originalShortcutPageOverlay['uid']
02435                 );
02436 
02437                 $this->id   = $this->contentPid = $shortcut['uid'];
02438                 $this->page = $this->sys_page->getPage($this->id);
02439 
02440                     // fix various effects on things like menus f.e.
02441                 $this->fetch_the_id();
02442                 $this->tmpl->rootLine = array_reverse($this->rootLine);
02443             }
02444         }
02445     }
02446 
02447     /**
02448      * Checks if any email-submissions or submission via the fe_tce
02449      *
02450      * @return  string      "email" if a formmail has been sent, "fe_tce" if front-end data submission (like forums, guestbooks) is sent. "" if none.
02451      */
02452     function checkDataSubmission()  {
02453         $ret = '';
02454         $formtype_db = isset($_POST['formtype_db']) || isset($_POST['formtype_db_x']);
02455         $formtype_mail = isset($_POST['formtype_mail']) || isset($_POST['formtype_mail_x']);
02456         if ($formtype_db || $formtype_mail) {
02457             $refInfo = parse_url(t3lib_div::getIndpEnv('HTTP_REFERER'));
02458             if (t3lib_div::getIndpEnv('TYPO3_HOST_ONLY')==$refInfo['host'] || $this->TYPO3_CONF_VARS['SYS']['doNotCheckReferer'])   {
02459                 if ($this->locDataCheck($_POST['locationData']))    {
02460                     if ($formtype_mail) {
02461                         $ret = 'email';
02462                     } elseif ($formtype_db && is_array($_POST['data'])) {
02463                         $ret = 'fe_tce';
02464                     }
02465                     $GLOBALS['TT']->setTSlogMessage('"Check Data Submission": Return value: '.$ret,0);
02466                     return $ret;
02467                 }
02468             } else $GLOBALS['TT']->setTSlogMessage('"Check Data Submission": HTTP_HOST and REFERER HOST did not match when processing submitted formdata!',3);
02469         }
02470 
02471             // Hook for processing data submission to extensions:
02472         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['checkDataSubmission']))  {
02473             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['checkDataSubmission'] as $_classRef)  {
02474                 $_procObj = t3lib_div::getUserObj($_classRef);
02475                 $_procObj->checkDataSubmission($this);
02476             }
02477         }
02478         return $ret;
02479     }
02480 
02481     /**
02482      * Processes submitted user data (obsolete "Frontend TCE")
02483      *
02484      * @return  void
02485      * @see tslib_feTCE
02486      */
02487     function fe_tce()   {
02488         $fe_tce = t3lib_div::makeInstance('tslib_feTCE');
02489         $fe_tce->start(t3lib_div::_POST('data'),$this->config['FEData.']);
02490         $fe_tce->includeScripts();
02491     }
02492 
02493     /**
02494      * Checks if a formmail submission can be sent as email
02495      *
02496      * @param   string      The input from $_POST['locationData']
02497      * @return  void
02498      * @access private
02499      * @see checkDataSubmission()
02500      */
02501     function locDataCheck($locationData)    {
02502         $locData = explode(':',$locationData);
02503         if (!$locData[1] ||  $this->sys_page->checkRecord($locData[1],$locData[2],1))   {
02504             if (count($this->sys_page->getPage($locData[0])))   {   // $locData[1] -check means that a record is checked only if the locationData has a value for a record else than the page.
02505                 return 1;
02506             } else $GLOBALS['TT']->setTSlogMessage('LocationData Error: The page pointed to by location data ('.$locationData.') was not accessible.',2);
02507         } else $GLOBALS['TT']->setTSlogMessage('LocationData Error: Location data ('.$locationData.') record pointed to was not accessible.',2);
02508     }
02509 
02510     /**
02511      * Sends the emails from the formmail content object.
02512      *
02513      * @return  void
02514      * @access private
02515      * @see checkDataSubmission()
02516      */
02517     function sendFormmail() {
02518         $formmail = t3lib_div::makeInstance('t3lib_formmail');
02519 
02520         $EMAIL_VARS = t3lib_div::_POST();
02521         $locationData = $EMAIL_VARS['locationData'];
02522         unset($EMAIL_VARS['locationData']);
02523         unset($EMAIL_VARS['formtype_mail'], $EMAIL_VARS['formtype_mail_x'], $EMAIL_VARS['formtype_mail_y']);
02524 
02525         $integrityCheck = $this->TYPO3_CONF_VARS['FE']['strictFormmail'];
02526 
02527         if (!$this->TYPO3_CONF_VARS['FE']['secureFormmail'])    {
02528                 // Check recipient field:
02529             $encodedFields = explode(',','recipient,recipient_copy');   // These two fields are the ones which contain recipient addresses that can be misused to send mail from foreign servers.
02530             foreach ($encodedFields as $fieldKey)   {
02531                 if (strlen($EMAIL_VARS[$fieldKey])) {
02532                     if ($res = $this->codeString($EMAIL_VARS[$fieldKey], TRUE)) {   // Decode...
02533                         $EMAIL_VARS[$fieldKey] = $res;  // Set value if OK
02534                     } elseif ($integrityCheck)  {   // Otherwise abort:
02535                         $GLOBALS['TT']->setTSlogMessage('"Formmail" discovered a field ('.$fieldKey.') which could not be decoded to a valid string. Sending formmail aborted due to security reasons!',3);
02536                         return false;
02537                     } else {
02538                         $GLOBALS['TT']->setTSlogMessage('"Formmail" discovered a field ('.$fieldKey.') which could not be decoded to a valid string. The security level accepts this, but you should consider a correct coding though!',2);
02539                     }
02540                 }
02541             }
02542         } else  {
02543             $locData = explode(':',$locationData);
02544             $record = $this->sys_page->checkRecord($locData[1],$locData[2],1);
02545             $EMAIL_VARS['recipient'] = $record['subheader'];
02546             $EMAIL_VARS['recipient_copy'] = $this->extractRecipientCopy($record['bodytext']);
02547         }
02548 
02549             // Hook for preprocessing of the content for formmails:
02550         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['sendFormmail-PreProcClass']))    {
02551             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['sendFormmail-PreProcClass'] as $_classRef)    {
02552                 $_procObj = t3lib_div::getUserObj($_classRef);
02553                 $EMAIL_VARS = $_procObj->sendFormmail_preProcessVariables($EMAIL_VARS,$this);
02554             }
02555         }
02556 
02557         $formmail->start($EMAIL_VARS);
02558         $formmail->sendtheMail();
02559         $GLOBALS['TT']->setTSlogMessage('"Formmail" invoked, sending mail to '.$EMAIL_VARS['recipient'],0);
02560     }
02561 
02562     /**
02563      * Extracts the value of recipient copy field from a formmail CE bodytext
02564      *
02565      * @param   string      $bodytext The content of the related bodytext field
02566      * @return  string      The value of the recipient_copy field, or an empty string
02567      */
02568     function extractRecipientCopy($bodytext) {
02569         $recipient_copy = '';
02570         $fdef = array();
02571         //|recipient_copy=hidden|karsten@localhost.localdomain
02572         preg_match('/^[\s]*\|[\s]*recipient_copy[\s]*=[\s]*hidden[\s]*\|(.*)$/m', $bodytext, $fdef);
02573         $recipient_copy = (!empty($fdef[1])) ? $fdef[1] : '';
02574         return $recipient_copy;
02575     }
02576 
02577     /**
02578      * Sets the jumpurl for page type "External URL"
02579      *
02580      * @return  void
02581      */
02582     function setExternalJumpUrl()   {
02583         if ($extUrl = $this->sys_page->getExtURL($this->page, $this->config['config']['disablePageExternalUrl']))   {
02584             $this->jumpurl = $extUrl;
02585         }
02586     }
02587 
02588     /**
02589      * Check the jumpUrl referer if required
02590      *
02591      * @return  void
02592      */
02593     function checkJumpUrlReferer()  {
02594         if (strlen($this->jumpurl) && !$this->TYPO3_CONF_VARS['SYS']['doNotCheckReferer']) {
02595             $referer = parse_url(t3lib_div::getIndpEnv('HTTP_REFERER'));
02596             if (isset($referer['host']) && !($referer['host'] == t3lib_div::getIndpEnv('TYPO3_HOST_ONLY'))) {
02597                 unset($this->jumpurl);
02598             }
02599         }
02600     }
02601 
02602     /**
02603      * Sends a header "Location" to jumpUrl, if jumpurl is set.
02604      * Will exit if a location header is sent (for instance if jumpUrl was triggered)
02605      *
02606      * "jumpUrl" is a concept where external links are redirected from the index_ts.php script, which first logs the URL.
02607      * This feature is only interesting if config.sys_stat is used.
02608      *
02609      * @return  void
02610      */
02611     function jumpUrl()  {
02612         if ($this->jumpurl) {
02613             if (t3lib_div::_GP('juSecure')) {
02614                 $locationData = (string)t3lib_div::_GP('locationData');
02615                 $mimeType = (string)t3lib_div::_GP('mimeType');  // Need a type cast here because mimeType is optional!
02616 
02617                 $hArr = array(
02618                     $this->jumpurl,
02619                     $locationData,
02620                     $mimeType
02621                 );
02622                 $calcJuHash = t3lib_div::hmac(serialize($hArr));
02623                 $juHash = (string)t3lib_div::_GP('juHash');
02624                 if ($juHash === $calcJuHash)    {
02625                     if ($this->locDataCheck($locationData)) {
02626                         $this->jumpurl = rawurldecode($this->jumpurl);  // 211002 - goes with cObj->filelink() rawurlencode() of filenames so spaces can be allowed.
02627                             // Deny access to files that match TYPO3_CONF_VARS[SYS][fileDenyPattern] and whose parent directory is typo3conf/ (there could be a backup file in typo3conf/ which does not match against the fileDenyPattern)
02628                         $absoluteFileName = t3lib_div::getFileAbsFileName(t3lib_div::resolveBackPath($this->jumpurl), FALSE);
02629                         if (t3lib_div::isAllowedAbsPath($absoluteFileName) && t3lib_div::verifyFilenameAgainstDenyPattern($absoluteFileName) && !t3lib_div::isFirstPartOfStr($absoluteFileName, PATH_site . 'typo3conf')) {
02630                             if (@is_file($absoluteFileName)) {
02631                                 $mimeType = $mimeType ? $mimeType : 'application/octet-stream';
02632                                 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
02633                                 header('Content-Type: '.$mimeType);
02634                                 header('Content-Disposition: attachment; filename="'.basename($absoluteFileName) . '"');
02635                                 readfile($absoluteFileName);
02636                                 exit;
02637                             } else die('jumpurl Secure: "'.$this->jumpurl.'" was not a valid file!');
02638                         } else die('jumpurl Secure: The requested file was not allowed to be accessed through jumpUrl (path or file not allowed)!');
02639                     } else die('jumpurl Secure: locationData, '.$locationData.', was not accessible.');
02640                 } else die('jumpurl Secure: Calculated juHash did not match the submitted juHash.');
02641             } else {
02642                 $TSConf = $this->getPagesTSconfig();
02643                 if ($TSConf['TSFE.']['jumpUrl_transferSession'])    {
02644                     $uParts = parse_url($this->jumpurl);
02645                     $params = '&FE_SESSION_KEY='.rawurlencode($this->fe_user->id.'-'.md5($this->fe_user->id.'/'.$this->TYPO3_CONF_VARS['SYS']['encryptionKey']));
02646                     $this->jumpurl.= ($uParts['query']?'':'?').$params; // Add the session parameter ...
02647                 }
02648                 if ($TSConf['TSFE.']['jumpURL_HTTPStatusCode']) {
02649                     switch (intval($TSConf['TSFE.']['jumpURL_HTTPStatusCode'])){
02650                         case 301:
02651                             $statusCode = t3lib_utility_Http::HTTP_STATUS_301;
02652                             break;
02653                         case 302:
02654                             $statusCode = t3lib_utility_Http::HTTP_STATUS_302;
02655                             break;
02656                         case 307:
02657                             $statusCode = t3lib_utility_Http::HTTP_STATUS_307;
02658                             break;
02659                         case 303:
02660                         default:
02661                             $statusCode = t3lib_utility_Http::HTTP_STATUS_303;
02662                             break;
02663                     }
02664                 }
02665                 t3lib_utility_Http::redirect($this->jumpurl, $statusCode);
02666             }
02667         }
02668     }
02669 
02670     /**
02671      * Sets the URL_ID_TOKEN in the internal var, $this->getMethodUrlIdToken
02672      * This feature allows sessions to use a GET-parameter instead of a cookie.
02673      *
02674      * @return  void
02675      * @access private
02676      */
02677     function setUrlIdToken()    {
02678         if ($this->config['config']['ftu']) {
02679             $this->getMethodUrlIdToken = $this->TYPO3_CONF_VARS['FE']['get_url_id_token'];
02680         } else {
02681             $this->getMethodUrlIdToken = '';
02682         }
02683     }
02684 
02685 
02686 
02687 
02688 
02689 
02690 
02691 
02692 
02693 
02694 
02695 
02696 
02697 
02698 
02699 
02700 
02701 
02702 
02703 
02704 
02705 
02706 
02707     /********************************************
02708      *
02709      * Page generation; cache handling
02710      *
02711      *******************************************/
02712 
02713     /**
02714      * Returns true if the page should be generated
02715      * That is if jumpurl is not set and the cacheContentFlag is not set.
02716      *
02717      * @return  boolean
02718      */
02719     function isGeneratePage()   {
02720         return (!$this->cacheContentFlag && !$this->jumpurl);
02721     }
02722 
02723     /**
02724      * Temp cache content
02725      * The temporary cache will expire after a few seconds (typ. 30) or will be cleared by the rendered page, which will also clear and rewrite the cache.
02726      *
02727      * @return  void
02728      */
02729     function tempPageCacheContent() {
02730         $this->tempContent = false;
02731 
02732         if (!$this->no_cache)   {
02733             $seconds = 30;
02734             $title = htmlspecialchars($this->tmpl->printTitle($this->page['title']));
02735             $request_uri = htmlspecialchars(t3lib_div::getIndpEnv('REQUEST_URI'));
02736 
02737             $stdMsg = '
02738         <strong>Page is being generated.</strong><br />
02739         If this message does not disappear within '.$seconds.' seconds, please reload.';
02740 
02741             $message = $this->config['config']['message_page_is_being_generated'];
02742             if (strcmp('', $message))   {
02743                 $message = $this->csConvObj->utf8_encode($message,$this->renderCharset);    // This page is always encoded as UTF-8
02744                 $message = str_replace('###TITLE###', $title, $message);
02745                 $message = str_replace('###REQUEST_URI###', $request_uri, $message);
02746             } else $message = $stdMsg;
02747 
02748             $temp_content = '<?xml version="1.0" encoding="UTF-8"?>
02749 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
02750   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
02751 <html xmlns="http://www.w3.org/1999/xhtml">
02752     <head>
02753         <title>'.$title.'</title>
02754         <meta http-equiv="refresh" content="10" />
02755     </head>
02756     <body style="background-color:white; font-family:Verdana,Arial,Helvetica,sans-serif; color:#cccccc; text-align:center;">'.
02757         $message.'
02758     </body>
02759 </html>';
02760 
02761                 // Fix 'nice errors' feature in modern browsers
02762             $padSuffix = '<!--pad-->';  // prevent any trims
02763             $padSize = 768 - strlen($padSuffix) - strlen($temp_content);
02764             if ($padSize > 0) {
02765                 $temp_content = str_pad($temp_content, $padSize, LF) . $padSuffix;
02766             }
02767 
02768             if (!$this->headerNoCache() && $cachedRow = $this->getFromCache_queryRow()) {
02769                     // We are here because between checking for cached content earlier and now some other HTTP-process managed to store something in cache AND it was not due to a shift-reload by-pass.
02770                     // This is either the "Page is being generated" screen or it can be the final result.
02771                     // In any case we should not begin another rendering process also, so we silently disable caching and render the page ourselves and thats it.
02772                     // Actually $cachedRow contains content that we could show instead of rendering. Maybe we should do that to gain more performance but then we should set all the stuff done in $this->getFromCache()... For now we stick to this...
02773                 $this->set_no_cache();
02774             } else {
02775                 $this->tempContent = TRUE;      // This flag shows that temporary content is put in the cache
02776                 $this->setPageCacheContent($temp_content, $this->config, $GLOBALS['EXEC_TIME']+$seconds);
02777             }
02778         }
02779     }
02780 
02781     /**
02782      * Set cache content to $this->content
02783      *
02784      * @return  void
02785      */
02786     function realPageCacheContent() {
02787         $cache_timeout = $this->get_cache_timeout();        // seconds until a cached page is too old
02788         $timeOutTime = $GLOBALS['EXEC_TIME']+$cache_timeout;
02789         if ($this->config['config']['cache_clearAtMidnight'])   {
02790             $midnightTime = mktime (0,0,0,date('m',$timeOutTime),date('d',$timeOutTime),date('Y',$timeOutTime));
02791             if ($midnightTime > $GLOBALS['EXEC_TIME'])  {       // If the midnight time of the expire-day is greater than the current time, we may set the timeOutTime to the new midnighttime.
02792                 $timeOutTime = $midnightTime;
02793             }
02794         }
02795         $this->tempContent = false;
02796         $this->setPageCacheContent($this->content, $this->config, $timeOutTime);
02797 
02798             // Hook for cache post processing (eg. writing static files!)
02799         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['insertPageIncache']))    {
02800             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['insertPageIncache'] as $_classRef)    {
02801                 $_procObj = t3lib_div::getUserObj($_classRef);
02802                 $_procObj->insertPageIncache($this,$timeOutTime);
02803             }
02804         }
02805     }
02806 
02807     /**
02808      * Sets cache content; Inserts the content string into the cache_pages cache.
02809      *
02810      * @param   string      The content to store in the HTML field of the cache table
02811      * @param   mixed       The additional cache_data array, fx. $this->config
02812      * @param   integer     Expiration timestamp
02813      * @return  void
02814      * @see realPageCacheContent(), tempPageCacheContent()
02815      */
02816     function setPageCacheContent($content, $data, $expirationTstamp) {
02817 
02818         if (TYPO3_UseCachingFramework) {
02819             $cacheData = array(
02820                 'identifier'    => $this->newHash,
02821                 'page_id'       => $this->id,
02822                 'content'           => $content,
02823                 'temp_content'  => $this->tempContent,
02824                 'cache_data'    => serialize($data),
02825                 'expires'       => $expirationTstamp,
02826                 'tstamp'        => $GLOBALS['EXEC_TIME']
02827             );
02828 
02829             $this->cacheExpires = $expirationTstamp;
02830 
02831             $this->pageCacheTags[] = 'pageId_' . $cacheData['page_id'];
02832 
02833             if ($this->page_cache_reg1) {
02834                 $reg1 = intval($this->page_cache_reg1);
02835 
02836                 $cacheData['reg1']     = $reg1;
02837                 $this->pageCacheTags[] = 'reg1_' . $reg1;
02838             }
02839 
02840             $this->pageCache->set(
02841                 $this->newHash,
02842                 $cacheData,
02843                 $this->pageCacheTags,
02844                 $expirationTstamp - $GLOBALS['EXEC_TIME']
02845             );
02846         } else {
02847             $this->clearPageCacheContent();
02848             $insertFields = array(
02849                 'hash' => $this->newHash,
02850                 'page_id' => $this->id,
02851                 'HTML' => $content,
02852                 'temp_content' => $this->tempContent,
02853                 'cache_data' => serialize($data),
02854                 'expires' => $expirationTstamp,
02855                 'tstamp' => $GLOBALS['EXEC_TIME']
02856             );
02857 
02858             $this->cacheExpires = $expirationTstamp;
02859 
02860             if ($this->page_cache_reg1) {
02861                 $insertFields['reg1'] = intval($this->page_cache_reg1);
02862             }
02863             $this->pageCachePostProcess($insertFields,'set');
02864             $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_pages', $insertFields);
02865         }
02866     }
02867 
02868     /**
02869      * Clears cache content (for $this->newHash)
02870      *
02871      * @return  void
02872      */
02873     function clearPageCacheContent() {
02874         if (TYPO3_UseCachingFramework) {
02875             $this->pageCache->remove($this->newHash);
02876         } else {
02877             $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages', 'hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->newHash, 'cache_pages'));
02878         }
02879     }
02880 
02881     /**
02882      * Post processing page cache rows for both get and set.
02883      *
02884      * @param   array       Input "cache_pages" row, passed by reference!
02885      * @param   string      Type of operation, either "get" or "set"
02886      * @return  void
02887      */
02888     function pageCachePostProcess(&$row,$type)  {
02889 
02890         if ($this->TYPO3_CONF_VARS['FE']['pageCacheToExternalFiles'])   {
02891             $cacheFileName = PATH_site.'typo3temp/cache_pages/'.$row['hash']{0}.$row['hash']{1}.'/'.$row['hash'].'.html';
02892             switch((string)$type)   {
02893                 case 'get':
02894                     $row['HTML'] = @is_file($cacheFileName) ? t3lib_div::getUrl($cacheFileName) : '<!-- CACHING ERROR, sorry -->';
02895                 break;
02896                 case 'set':
02897                     t3lib_div::writeFileToTypo3tempDir($cacheFileName, $row['HTML']);
02898                     $row['HTML'] = '';
02899                 break;
02900             }
02901         }
02902     }
02903 
02904     /**
02905      * Clears cache content for a list of page ids
02906      *
02907      * @param   string      A list of INTEGER numbers which points to page uids for which to clear entries in the cache_pages cache (page content cache)
02908      * @return  void
02909      */
02910     function clearPageCacheContent_pidList($pidList) {
02911         if (TYPO3_UseCachingFramework) {
02912             $pageIds = t3lib_div::trimExplode(',', $pidList);
02913             foreach ($pageIds as $pageId) {
02914                 $this->pageCache->flushByTag('pageId_' . (int) $pageId);
02915             }
02916         } else {
02917             $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages', 'page_id IN ('.$GLOBALS['TYPO3_DB']->cleanIntList($pidList).')');
02918         }
02919     }
02920 
02921     /**
02922      * Sets sys last changed
02923      * Setting the SYS_LASTCHANGED value in the pagerecord: This value will thus be set to the highest tstamp of records rendered on the page. This includes all records with no regard to hidden records, userprotection and so on.
02924      *
02925      * @return  void
02926      * @see tslib_cObj::lastChanged()
02927      */
02928     function setSysLastChanged()    {
02929         if ($this->page['SYS_LASTCHANGED'] < intval($this->register['SYS_LASTCHANGED']))    {
02930             $GLOBALS['TYPO3_DB']->exec_UPDATEquery('pages', 'uid='.intval($this->id), array('SYS_LASTCHANGED' => intval($this->register['SYS_LASTCHANGED'])));
02931         }
02932     }
02933 
02934     /**
02935      * Lock the page generation process
02936      * The lock is used to queue page requests until this page is successfully stored in the cache.
02937      *
02938      * @param   t3lib_lock  Reference to a locking object
02939      * @param   string      String to identify the lock in the system
02940      * @return  boolean     Returns true if the lock could be obtained, false otherwise (= process had to wait for existing lock to be released)
02941      * @see releasePageGenerationLock()
02942      */
02943     function acquirePageGenerationLock(&$lockObj, $key) {
02944         if ($this->no_cache || $this->headerNoCache()) {
02945             t3lib_div::sysLog('Locking: Page is not cached, no locking required', 'cms', t3lib_div::SYSLOG_SEVERITY_INFO);
02946             return true;    // No locking is needed if caching is disabled
02947         }
02948 
02949         try {
02950             if (!is_object($lockObj)) {
02951                 $lockObj = t3lib_div::makeInstance('t3lib_lock', $key, $this->TYPO3_CONF_VARS['SYS']['lockingMode']);
02952             }
02953 
02954             $success = false;
02955             if (strlen($key)) {
02956                     // true = Page could get locked without blocking
02957                     // false = Page could get locked but process was blocked before
02958                 $success = $lockObj->acquire();
02959                 if ($lockObj->getLockStatus()) {
02960                     $lockObj->sysLog('Acquired lock');
02961                 }
02962             }
02963         } catch (Exception $e) {
02964             t3lib_div::sysLog('Locking: Failed to acquire lock: '.$e->getMessage(), 'cms', t3lib_div::SYSLOG_SEVERITY_ERROR);
02965             $success = false;   // If locking fails, return with false and continue without locking
02966         }
02967 
02968         return $success;
02969     }
02970 
02971     /**
02972      * Release the page generation lock
02973      *
02974      * @param   t3lib_lock  Reference to a locking object
02975      * @return  boolean     Returns true on success, false otherwise
02976      * @see acquirePageGenerationLock()
02977      */
02978     function releasePageGenerationLock(&$lockObj) {
02979         $success = false;
02980             // If lock object is set and was acquired (may also happen if no_cache was enabled during runtime), release it:
02981         if (is_object($lockObj) && $lockObj instanceof t3lib_lock && $lockObj->getLockStatus()) {
02982             $success = $lockObj->release();
02983             $lockObj->sysLog('Released lock');
02984             $lockObj = null;
02985             // Otherwise, if caching is disabled, no locking is required:
02986         } elseif ($this->no_cache || $this->headerNoCache()) {
02987             $success = true;
02988         }
02989         return $success;
02990     }
02991 
02992     /**
02993      * adds tags to this page's cache entry, you can then f.e. remove cache
02994      * entries by tag
02995      *
02996      * @param array an array of tag
02997      * @return  void
02998      */
02999     public function addCacheTags(array $tags) {
03000         $this->pageCacheTags = array_merge($this->pageCacheTags, $tags);
03001     }
03002 
03003 
03004 
03005 
03006 
03007 
03008 
03009 
03010 
03011 
03012 
03013 
03014 
03015 
03016 
03017 
03018 
03019 
03020 
03021 
03022     /********************************************
03023      *
03024      * Page generation; rendering and inclusion
03025      *
03026      *******************************************/
03027 
03028     /**
03029      * Does some processing BEFORE the pagegen script is included.
03030      *
03031      * @return  void
03032      */
03033     function generatePage_preProcessing()   {
03034         $this->newHash = $this->getHash();  // Same codeline as in getFromCache(). But $this->all has been changed by t3lib_TStemplate::start() in the meantime, so this must be called again!
03035         $this->config['hash_base'] = $this->hash_base;  // For cache management informational purposes.
03036 
03037         if (!is_object($this->pages_lockObj) || $this->pages_lockObj->getLockStatus()==false) {
03038                 // Here we put some temporary stuff in the cache in order to let the first hit generate the page. The temporary cache will expire after a few seconds (typ. 30) or will be cleared by the rendered page, which will also clear and rewrite the cache.
03039             $this->tempPageCacheContent();
03040         }
03041 
03042             // Setting cache_timeout_default. May be overridden by PHP include scritps.
03043         $this->cacheTimeOutDefault = intval($this->config['config']['cache_period']);
03044 
03045             // page is generated
03046         $this->no_cacheBeforePageGen = $this->no_cache;
03047     }
03048 
03049     /**
03050      * Determines to include custom or pagegen.php script
03051      * returns script-filename if a TypoScript (config) script is defined and should be include instead of pagegen.php
03052      *
03053      * @return  string      The relative filepath of "config.pageGenScript" if found and allowed
03054      */
03055     function generatePage_whichScript() {
03056         if (!$this->TYPO3_CONF_VARS['FE']['noPHPscriptInclude'] && $this->config['config']['pageGenScript'])    {
03057             return $this->tmpl->getFileName($this->config['config']['pageGenScript']);
03058         }
03059     }
03060 
03061     /**
03062      * Does some processing AFTER the pagegen script is included.
03063      * This includes calling tidy (if configured), XHTML cleaning (if configured), caching the page, indexing the page (if configured) and setting sysLastChanged
03064      *
03065      * @return  void
03066      */
03067     function generatePage_postProcessing()  {
03068             // This is to ensure, that the page is NOT cached if the no_cache parameter was set before the page was generated. This is a safety precaution, as it could have been unset by some script.
03069         if ($this->no_cacheBeforePageGen) $this->set_no_cache();
03070 
03071             // Tidy up the code, if flag...
03072         if ($this->TYPO3_CONF_VARS['FE']['tidy_option'] == 'all') {
03073             $GLOBALS['TT']->push('Tidy, all','');
03074                 $this->content = $this->tidyHTML($this->content);
03075             $GLOBALS['TT']->pull();
03076         }
03077 
03078             // XHTML-clean the code, if flag set
03079         if ($this->doXHTML_cleaning() == 'all') {
03080             $GLOBALS['TT']->push('XHTML clean, all','');
03081                 $XHTML_clean = t3lib_div::makeInstance('t3lib_parsehtml');
03082                 $this->content = $XHTML_clean->XHTML_clean($this->content);
03083             $GLOBALS['TT']->pull();
03084         }
03085 
03086             // Fix local anchors in links, if flag set
03087         if ($this->doLocalAnchorFix() == 'all') {
03088             $GLOBALS['TT']->push('Local anchor fix, all','');
03089                 $this->prefixLocalAnchorsWithScript();
03090             $GLOBALS['TT']->pull();
03091         }
03092 
03093             // Hook for post-processing of page content cached/non-cached:
03094         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-all'])) {
03095             $_params = array('pObj' => &$this);
03096             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-all'] as $_funcRef)   {
03097                 t3lib_div::callUserFunction($_funcRef,$_params,$this);
03098             }
03099         }
03100 
03101             // Processing if caching is enabled:
03102         if (!$this->no_cache) {
03103                     // Tidy up the code, if flag...
03104             if ($this->TYPO3_CONF_VARS['FE']['tidy_option'] == 'cached') {
03105                 $GLOBALS['TT']->push('Tidy, cached','');
03106                     $this->content = $this->tidyHTML($this->content);
03107                 $GLOBALS['TT']->pull();
03108             }
03109                 // XHTML-clean the code, if flag set
03110             if ($this->doXHTML_cleaning() == 'cached')      {
03111                 $GLOBALS['TT']->push('XHTML clean, cached','');
03112                     $XHTML_clean = t3lib_div::makeInstance('t3lib_parsehtml');
03113                     $this->content = $XHTML_clean->XHTML_clean($this->content);
03114                 $GLOBALS['TT']->pull();
03115             }
03116                 // Fix local anchors in links, if flag set
03117             if ($this->doLocalAnchorFix() == 'cached')      {
03118                 $GLOBALS['TT']->push('Local anchor fix, cached','');
03119                     $this->prefixLocalAnchorsWithScript();
03120                 $GLOBALS['TT']->pull();
03121             }
03122 
03123                 // Hook for post-processing of page content before being cached:
03124             if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-cached']))   {
03125                 $_params = array('pObj' => &$this);
03126                 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-cached'] as $_funcRef)    {
03127                     t3lib_div::callUserFunction($_funcRef,$_params,$this);
03128                 }
03129             }
03130         }
03131 
03132             // Convert char-set for output: (should be BEFORE indexing of the content (changed 22/4 2005)), because otherwise indexed search might convert from the wrong charset! One thing is that the charset mentioned in the HTML header would be wrong since the output charset (metaCharset) has not been converted to from renderCharset. And indexed search will internally convert from metaCharset to renderCharset so the content MUST be in metaCharset already!
03133         $this->content = $this->convOutputCharset($this->content,'mainpage');
03134 
03135             // Hook for indexing pages
03136         if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['pageIndexing'])) {
03137             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['pageIndexing'] as $_classRef) {
03138                 $_procObj = t3lib_div::getUserObj($_classRef);
03139                 $_procObj->hook_indexContent($this);
03140             }
03141         }
03142 
03143             // Storing for cache:
03144         if (!$this->no_cache)   {
03145             $this->realPageCacheContent();
03146         } elseif ($this->tempContent)   {       // If there happens to be temporary content in the cache and the cache was not cleared due to new content, put it in... ($this->no_cache=0)
03147             $this->clearPageCacheContent();
03148             $this->tempContent = false;
03149         }
03150 
03151             // Release open locks
03152         $this->releasePageGenerationLock($this->pagesection_lockObj);
03153         $this->releasePageGenerationLock($this->pages_lockObj);
03154 
03155             // Sets sys-last-change:
03156         $this->setSysLastChanged();
03157     }
03158 
03159     /**
03160      * Processes the INTinclude-scripts
03161      *
03162      * @return  void
03163      */
03164     function INTincScript() {
03165             // Deprecated stuff:
03166         $this->additionalHeaderData = is_array($this->config['INTincScript_ext']['additionalHeaderData']) ? $this->config['INTincScript_ext']['additionalHeaderData'] : array();
03167         $this->additionalJavaScript = $this->config['INTincScript_ext']['additionalJavaScript'];
03168         $this->additionalCSS = $this->config['INTincScript_ext']['additionalCSS'];
03169         $this->JSCode = $this->additionalHeaderData['JSCode'];
03170         $this->JSImgCode = $this->additionalHeaderData['JSImgCode'];
03171         $this->divSection='';
03172 
03173         do {
03174             $INTiS_config = $this->config['INTincScript'];
03175             $this->INTincScript_includeLibs($INTiS_config);
03176             $this->INTincScript_process($INTiS_config);
03177                 // Check if there were new items added to INTincScript during the previous execution:
03178             $INTiS_config = array_diff_assoc($this->config['INTincScript'], $INTiS_config);
03179             $reprocess = (count($INTiS_config) ? true : false);
03180         } while($reprocess);
03181 
03182         $GLOBALS['TT']->push('Substitute header section');
03183         $this->INTincScript_loadJSCode();
03184         $this->content = str_replace('<!--HD_'.$this->config['INTincScript_ext']['divKey'].'-->', $this->convOutputCharset(implode(LF,$this->additionalHeaderData),'HD'), $this->content);
03185         $this->content = str_replace('<!--TDS_'.$this->config['INTincScript_ext']['divKey'].'-->', $this->convOutputCharset($this->divSection,'TDS'), $this->content);
03186         $this->setAbsRefPrefix();
03187         $GLOBALS['TT']->pull();
03188     }
03189 
03190     /**
03191      * Include libraries for uncached objects.
03192      *
03193      * @param   array       $INTiS_config: $GLOBALS['TSFE']->config['INTincScript'] or part of it
03194      * @return  void
03195      * @see     INTincScript()
03196      */
03197     protected function INTincScript_includeLibs($INTiS_config) {
03198         foreach($INTiS_config as $INTiS_cPart) {
03199             if (isset($INTiS_cPart['conf']['includeLibs']) && $INTiS_cPart['conf']['includeLibs']) {
03200                 $INTiS_resourceList = t3lib_div::trimExplode(',', $INTiS_cPart['conf']['includeLibs'], true);
03201                 $this->includeLibraries($INTiS_resourceList);
03202             }
03203         }
03204     }
03205 
03206     /**
03207      * Processes the INTinclude-scripts and substitue in content.
03208      *
03209      * @param   array       $INTiS_config: $GLOBALS['TSFE']->config['INTincScript'] or part of it
03210      * @return  void
03211      * @see     INTincScript()
03212      */
03213     protected function INTincScript_process($INTiS_config)  {
03214         $GLOBALS['TT']->push('Split content');
03215         $INTiS_splitC = explode('<!--INT_SCRIPT.',$this->content);          // Splits content with the key.
03216         $this->content = '';
03217         $GLOBALS['TT']->setTSlogMessage('Parts: '.count($INTiS_splitC));
03218         $GLOBALS['TT']->pull();
03219 
03220         foreach($INTiS_splitC as $INTiS_c => $INTiS_cPart)  {
03221             if (substr($INTiS_cPart,32,3)=='-->')   {   // If the split had a comment-end after 32 characters it's probably a split-string
03222                 $INTiS_key = 'INT_SCRIPT.'.substr($INTiS_cPart,0,32);
03223                 $GLOBALS['TT']->push('Include '.$INTiS_config[$INTiS_key]['file'],'');
03224                 $incContent='';
03225                 if (is_array($INTiS_config[$INTiS_key]))    {
03226                     $INTiS_cObj = unserialize($INTiS_config[$INTiS_key]['cObj']);
03227                     /* @var $INTiS_cObj tslib_cObj */
03228                     $INTiS_cObj->INT_include=1;
03229                     switch($INTiS_config[$INTiS_key]['type'])   {
03230                         case 'SCRIPT':
03231                             $incContent = $INTiS_cObj->PHP_SCRIPT($INTiS_config[$INTiS_key]['conf']);
03232                         break;
03233                         case 'COA':
03234                             $incContent = $INTiS_cObj->COBJ_ARRAY($INTiS_config[$INTiS_key]['conf']);
03235                         break;
03236                         case 'FUNC':
03237                             $incContent = $INTiS_cObj->USER($INTiS_config[$INTiS_key]['conf']);
03238                         break;
03239                         case 'POSTUSERFUNC':
03240                             $incContent = $INTiS_cObj->callUserFunction($INTiS_config[$INTiS_key]['postUserFunc'], $INTiS_config[$INTiS_key]['conf'], $INTiS_config[$INTiS_key]['content']);
03241                         break;
03242                     }
03243                 }
03244                 $this->content.= $this->convOutputCharset($incContent,'INC-'.$INTiS_c);
03245                 $this->content.= substr($INTiS_cPart,35);
03246                 $GLOBALS['TT']->pull($incContent);
03247             } else {
03248                 $this->content.= ($INTiS_c?'<!--INT_SCRIPT.':'').$INTiS_cPart;
03249             }
03250         }
03251     }
03252 
03253     /**
03254      * Loads the JavaScript code for INTincScript
03255      *
03256      * @return  void
03257      * @access private
03258      */
03259     function INTincScript_loadJSCode()  {
03260         if ($this->JSImgCode)   {   // If any images added, then add them to the javascript section
03261             $this->additionalHeaderData['JSImgCode']='
03262 <script type="text/javascript">
03263     /*<![CDATA[*/
03264 <!--
03265 if (version == "n3") {
03266 '.trim($this->JSImgCode).'
03267 }
03268 // -->
03269     /*]]>*/
03270 </script>';
03271         }
03272         if ($this->JSCode || count($this->additionalJavaScript))    {   // Add javascript
03273             $this->additionalHeaderData['JSCode']='
03274 <script type="text/javascript">
03275     /*<![CDATA[*/
03276 <!--
03277 '.implode(LF,$this->additionalJavaScript).'
03278 '.trim($this->JSCode).'
03279 // -->
03280     /*]]>*/
03281 </script>';
03282         }
03283         if (count($this->additionalCSS))    {   // Add javascript
03284             $this->additionalHeaderData['_CSS']='
03285 <style type="text/css">
03286     /*<![CDATA[*/
03287 <!--
03288 '.implode(LF,$this->additionalCSS).'
03289 // -->
03290     /*]]>*/
03291 </style>';
03292         }
03293     }
03294 
03295     /**
03296      * Determines if there are any INTincScripts to include
03297      *
03298      * @return  boolean     Returns true if scripts are found (and not jumpurl)
03299      */
03300     function isINTincScript()   {
03301         return  (is_array($this->config['INTincScript']) && !$this->jumpurl);
03302     }
03303 
03304     /**
03305      * Returns the mode of XHTML cleaning
03306      *
03307      * @return  string      Keyword: "all", "cached" or "output"
03308      */
03309     function doXHTML_cleaning() {
03310         return $this->config['config']['xhtml_cleaning'];
03311     }
03312 
03313     /**
03314      * Returns the mode of Local Anchor prefixing
03315      *
03316      * @return  string      Keyword: "all", "cached" or "output"
03317      */
03318     function doLocalAnchorFix() {
03319         return (isset($this->config['config']['prefixLocalAnchors'])) ? $this->config['config']['prefixLocalAnchors'] : NULL;
03320     }
03321 
03322 
03323 
03324 
03325 
03326 
03327 
03328 
03329 
03330 
03331 
03332 
03333 
03334 
03335 
03336 
03337     /********************************************
03338      *
03339      * Finished off; outputting, storing session data, statistics...
03340      *
03341      *******************************************/
03342 
03343     /**
03344      * Determines if content should be outputted.
03345      * Outputting content is done only if jumpUrl is NOT set.
03346      *
03347      * @return  boolean     Returns true if $this->jumpurl is not set.
03348      */
03349     function isOutputting() {
03350 
03351             // Initialize by status of jumpUrl:
03352         $enableOutput = (!$this->jumpurl);
03353 
03354             // Call hook for possible disabling of output:
03355         if (isset($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['isOutputting'])
03356             && is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['isOutputting'])) {
03357 
03358             $_params = array('pObj' => &$this, 'enableOutput' => &$enableOutput);
03359             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['isOutputting'] as $_funcRef)  {
03360                 t3lib_div::callUserFunction($_funcRef,$_params,$this);
03361             }
03362         }
03363 
03364         return $enableOutput;
03365     }
03366 
03367     /**
03368      * Process the output before it's actually outputted. Sends headers also.
03369      * This includes substituting the "username" comment, sending additional headers (as defined in the TypoScript "config.additionalheaders" object), tidy'ing content, XHTML cleaning content (if configured)
03370      * Works on $this->content.
03371      *
03372      * @return  void
03373      */
03374     function processOutput() {
03375 
03376             // Set header for charset-encoding unless disabled
03377         if (empty($this->config['config']['disableCharsetHeader'])) {
03378             $headLine = 'Content-Type: text/html; charset='.trim($this->metaCharset);
03379             header($headLine);
03380         }
03381 
03382             // Set cache related headers to client (used to enable proxy / client caching!)
03383         if (!empty($this->config['config']['sendCacheHeaders'])) {
03384             $this->sendCacheHeaders();
03385         }
03386 
03387             // Set headers, if any
03388         if (!empty($this->config['config']['additionalHeaders'])) {
03389             $headerArray = explode('|', $this->config['config']['additionalHeaders']);
03390             foreach ($headerArray as $headLine) {
03391                 $headLine = trim($headLine);
03392                 header($headLine);
03393             }
03394         }
03395 
03396             // Send appropriate status code in case of temporary content
03397         if ($this->tempContent) {
03398             $this->addTempContentHttpHeaders();
03399         }
03400 
03401             // Make substitution of eg. username/uid in content only if cache-headers for client/proxy caching is NOT sent!
03402         if (!$this->isClientCachable) {
03403             $this->contentStrReplace();
03404         }
03405 
03406             // Tidy up the code, if flag...
03407         if ($this->TYPO3_CONF_VARS['FE']['tidy_option'] == 'output') {
03408             $GLOBALS['TT']->push('Tidy, output','');
03409                 $this->content = $this->tidyHTML($this->content);
03410             $GLOBALS['TT']->pull();
03411         }
03412             // XHTML-clean the code, if flag set
03413         if ($this->doXHTML_cleaning() == 'output') {
03414             $GLOBALS['TT']->push('XHTML clean, output','');
03415                 $XHTML_clean = t3lib_div::makeInstance('t3lib_parsehtml');
03416                 $this->content = $XHTML_clean->XHTML_clean($this->content);
03417             $GLOBALS['TT']->pull();
03418         }
03419             // Fix local anchors in links, if flag set
03420         if ($this->doLocalAnchorFix() == 'output') {
03421             $GLOBALS['TT']->push('Local anchor fix, output','');
03422                 $this->prefixLocalAnchorsWithScript();
03423             $GLOBALS['TT']->pull();
03424         }
03425 
03426             // Hook for post-processing of page content before output:
03427         if (isset($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-output']) && is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-output'])) {
03428             $_params = array('pObj' => &$this);
03429             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-output'] as $_funcRef) {
03430                 t3lib_div::callUserFunction($_funcRef,$_params,$this);
03431             }
03432         }
03433 
03434             // Send content-lenght header.
03435             // Notice that all HTML content outside the length of the content-length header will be cut off! Therefore content of unknown length from included PHP-scripts and if admin users are logged in (admin panel might show...) or if debug mode is turned on, we disable it!
03436         if (!empty($this->config['config']['enableContentLengthHeader']) &&
03437             !$this->isEXTincScript() &&
03438             !$this->beUserLogin  &&
03439             !$this->TYPO3_CONF_VARS['FE']['debug'] &&
03440             !$this->config['config']['debug'] &&
03441             !$this->doWorkspacePreview()
03442         ) {
03443             header('Content-Length: '.strlen($this->content));
03444         }
03445     }
03446 
03447     /**
03448      * Send cache headers good for client/reverse proxy caching
03449      * This function should not be called if the page content is temporary (like for "Page is being generated..." message, but in that case it is ok because the config-variables are not yet available and so will not allow to send cache headers)
03450      *
03451      * @return  void
03452      * @co-author   Ole Tange, Forbrugernes Hus, Denmark
03453      */
03454     function sendCacheHeaders() {
03455 
03456             // Getting status whether we can send cache control headers for proxy caching:
03457         $doCache = $this->isStaticCacheble();
03458 
03459             // This variable will be TRUE unless cache headers are configured to be sent ONLY if a branch does not allow logins and logins turns out to be allowed anyway...
03460         $loginsDeniedCfg = (empty($this->config['config']['sendCacheHeaders_onlyWhenLoginDeniedInBranch']) || empty($this->loginAllowedInBranch));
03461 
03462             // Finally, when backend users are logged in, do not send cache headers at all (Admin Panel might be displayed for instance).
03463         if ($doCache
03464                 && !$this->beUserLogin
03465                 && !$this->doWorkspacePreview()
03466                 && $loginsDeniedCfg)    {
03467 
03468                 // Build headers:
03469             $headers = array(
03470                 'Last-Modified: '.gmdate('D, d M Y H:i:s T', $this->register['SYS_LASTCHANGED']),
03471                 'Expires: '.gmdate('D, d M Y H:i:s T', $this->cacheExpires),
03472                 'ETag: "' . md5($this->content) . '"',
03473                 'Cache-Control: max-age='.($this->cacheExpires - $GLOBALS['EXEC_TIME']),        // no-cache
03474                 'Pragma: public',
03475             );
03476 
03477             $this->isClientCachable = TRUE;
03478         } else {
03479                 // Build headers:
03480             $headers = array(
03481                 #'Last-Modified: '.gmdate('D, d M Y H:i:s T', $this->register['SYS_LASTCHANGED']),
03482                 #'ETag: '.md5($this->content),
03483 
03484                 #'Cache-Control: no-cache',
03485                 #'Pragma: no-cache',
03486                 'Cache-Control: private',       // Changed to this according to Ole Tange, FI.dk
03487             );
03488 
03489             $this->isClientCachable = FALSE;
03490 
03491                 // Now, if a backend user is logged in, tell him in the Admin Panel log what the caching status would have been:
03492             if ($this->beUserLogin) {
03493                 if ($doCache)   {
03494                     $GLOBALS['TT']->setTSlogMessage('Cache-headers with max-age "'.($this->cacheExpires - $GLOBALS['EXEC_TIME']).'" would have been sent');
03495                 } else {
03496                     $reasonMsg = '';
03497                     $reasonMsg.= !$this->no_cache ? '' : 'Caching disabled (no_cache). ';
03498                     $reasonMsg.= !$this->isINTincScript() ? '' : '*_INT object(s) on page. ';
03499                     $reasonMsg.= !$this->isEXTincScript() ? '' : '*_EXT object(s) on page. ';
03500                     $reasonMsg.= !is_array($this->fe_user->user) ? '' : 'Frontend user logged in. ';
03501                     $GLOBALS['TT']->setTSlogMessage('Cache-headers would disable proxy caching! Reason(s): "'.$reasonMsg.'"',1);
03502                 }
03503             }
03504         }
03505 
03506             // Send headers:
03507         foreach($headers as $hL)    {
03508             header($hL);
03509         }
03510     }
03511 
03512     /**
03513      * Reporting status whether we can send cache control headers for proxy caching or publishing to static files
03514      *
03515      * Rules are:
03516      * no_cache cannot be set: If it is, the page might contain dynamic content and should never be cached.
03517      * There can be no USER_INT objects on the page ("isINTincScript()" / "isEXTincScript()") because they implicitly indicate dynamic content
03518      * There can be no logged in user because user sessions are based on a cookie and thereby does not offer client caching a chance to know if the user is logged in. Actually, there will be a reverse problem here; If a page will somehow change when a user is logged in he may not see it correctly if the non-login version sent a cache-header! So do NOT use cache headers in page sections where user logins change the page content. (unless using such as realurl to apply a prefix in case of login sections)
03519      *
03520      * @return  boolean
03521      */
03522     function isStaticCacheble() {
03523         $doCache = !$this->no_cache
03524                 && !$this->isINTincScript()
03525                 && !$this->isEXTincScript()
03526                 && !$this->isUserOrGroupSet();
03527         return $doCache;
03528     }
03529 
03530     /**
03531      * Substitute various tokens in content. This should happen only if the content is not cached by proxies or client browsers.
03532      *
03533      * @return  void
03534      */
03535     function contentStrReplace()    {
03536         $search = array();
03537         $replace = array();
03538 
03539             // Substitutes username mark with the username
03540         if ($this->fe_user->user['uid'])    {
03541 
03542                 // User name:
03543             $token = (isset($this->config['config']['USERNAME_substToken'])) ? trim($this->config['config']['USERNAME_substToken']) : '';
03544             $search[] = ($token ? $token : '<!--###USERNAME###-->');
03545             $replace[] = $this->fe_user->user['username'];
03546 
03547                 // User uid (if configured):
03548             $token = (isset($this->config['config']['USERUID_substToken'])) ? trim($this->config['config']['USERUID_substToken']) : '';
03549             if ($token) {
03550                 $search[] = $token;
03551                 $replace[] = $this->fe_user->user['uid'];
03552             }
03553         }
03554 
03555             // Substitutes get_URL_ID in case of GET-fallback
03556         if ($this->getMethodUrlIdToken) {
03557             $search[] = $this->getMethodUrlIdToken;
03558             $replace[] = $this->fe_user->get_URL_ID;
03559         }
03560 
03561             // Hook for supplying custom search/replace data
03562         if (isset($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['tslib_fe-contentStrReplace'])) {
03563             $contentStrReplaceHooks = &$this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['tslib_fe-contentStrReplace'];
03564             if (is_array($contentStrReplaceHooks)) {
03565                 $_params = array(
03566                     'search' => &$search,
03567                     'replace' => &$replace,
03568                 );
03569                 foreach ($contentStrReplaceHooks as $_funcRef) {
03570                     t3lib_div::callUserFunction($_funcRef, $_params, $this);
03571                 }
03572             }
03573         }
03574 
03575         if (count($search)) {
03576             $this->content = str_replace($search, $replace, $this->content);
03577         }
03578     }
03579 
03580     /**
03581      * Determines if any EXTincScripts should be included
03582      *
03583      * @return  boolean     True, if external php scripts should be included (set by PHP_SCRIPT_EXT cObjects)
03584      * @see tslib_cObj::PHP_SCRIPT
03585      */
03586     function isEXTincScript()   {
03587         return (isset($this->config['EXTincScript']) && is_array($this->config['EXTincScript']));
03588     }
03589 
03590     /**
03591      * Stores session data for the front end user
03592      *
03593      * @return  void
03594      */
03595     function storeSessionData() {
03596         $this->fe_user->storeSessionData();
03597     }
03598 
03599     /**
03600      * Sets the parsetime of the page.
03601      *
03602      * @return  void
03603      * @access private
03604      */
03605     function setParseTime() {
03606         // Compensates for the time consumed with Back end user initialization.
03607         $microtime_start            = (isset($GLOBALS['TYPO3_MISC']['microtime_start'])) ? $GLOBALS['TYPO3_MISC']['microtime_start'] : NULL;
03608         $microtime_end              = (isset($GLOBALS['TYPO3_MISC']['microtime_end'])) ? $GLOBALS['TYPO3_MISC']['microtime_end'] : NULL;
03609         $microtime_BE_USER_start    = (isset($GLOBALS['TYPO3_MISC']['microtime_BE_USER_start'])) ? $GLOBALS['TYPO3_MISC']['microtime_BE_USER_start'] : NULL;
03610         $microtime_BE_USER_end      = (isset($GLOBALS['TYPO3_MISC']['microtime_BE_USER_end'])) ? $GLOBALS['TYPO3_MISC']['microtime_BE_USER_end'] : NULL;
03611 
03612         $this->scriptParseTime = $GLOBALS['TT']->getMilliseconds($microtime_end) - $GLOBALS['TT']->getMilliseconds($microtime_start)
03613                                 - ($GLOBALS['TT']->getMilliseconds($microtime_BE_USER_end) - $GLOBALS['TT']->getMilliseconds($microtime_BE_USER_start));
03614     }
03615 
03616     /**
03617      * Initialize file-based statistics handling: Check filename and permissions, and create the logfile if it does not exist yet.
03618      * This function should be called with care because it might overwrite existing settings otherwise.
03619      *
03620      * @return  boolean     True if statistics are enabled (will require some more processing after charset handling is initialized)
03621      * @access private
03622      */
03623     protected function statistics_init()    {
03624         $setStatPageName = false;
03625         $theLogFile = $this->TYPO3_CONF_VARS['FE']['logfile_dir'].strftime($this->config['config']['stat_apache_logfile']);
03626 
03627             // Add PATH_site left to $theLogFile if the path is not absolute yet
03628         if (!t3lib_div::isAbsPath($theLogFile)) {
03629             $theLogFile = PATH_site.$theLogFile;
03630         }
03631 
03632         if ($this->config['config']['stat_apache'] && $this->config['config']['stat_apache_logfile'] && !strstr($this->config['config']['stat_apache_logfile'],'/')) {
03633             if (t3lib_div::isAllowedAbsPath($theLogFile)) {
03634                 if (!@is_file($theLogFile)) {
03635                     touch($theLogFile); // Try to create the logfile
03636                     t3lib_div::fixPermissions($theLogFile);
03637                 }
03638 
03639                 if (@is_file($theLogFile) && @is_writable($theLogFile)) {
03640                     $this->config['stat_vars']['logFile'] = $theLogFile;
03641                     $setStatPageName = true;    // Set page name later on
03642                 } else {
03643                     $GLOBALS['TT']->setTSlogMessage('Could not set logfile path. Check filepath and permissions.',3);
03644                 }
03645             }
03646         }
03647 
03648         return $setStatPageName;
03649     }
03650 
03651     /**
03652      * Set the pagename for the logfile entry
03653      *
03654      * @return  void
03655      * @access private
03656      */
03657     protected function statistics_init_pagename()   {
03658         if (preg_match('/utf-?8/i', $this->config['config']['stat_apache_niceTitle'])) {    // Make life easier and accept variants for utf-8
03659             $this->config['config']['stat_apache_niceTitle'] = 'utf-8';
03660         }
03661 
03662         if ($this->config['config']['stat_apache_niceTitle'] == 'utf-8') {
03663             $shortTitle = $this->csConvObj->utf8_encode($this->page['title'],$this->renderCharset);
03664         } elseif ($this->config['config']['stat_apache_niceTitle']) {
03665             $shortTitle = $this->csConvObj->specCharsToASCII($this->renderCharset,$this->page['title']);
03666         } else {
03667             $shortTitle = $this->page['title'];
03668         }
03669 
03670         $len = t3lib_div::intInRange($this->config['config']['stat_apache_pageLen'],1,100,30);
03671         if ($this->config['config']['stat_apache_niceTitle'] == 'utf-8') {
03672             $shortTitle = rawurlencode($this->csConvObj->substr('utf-8',$shortTitle,0,$len));
03673         } else {
03674             $shortTitle = substr(preg_replace('/[^.[:alnum:]_-]/','_',$shortTitle),0,$len);
03675         }
03676 
03677         $pageName = $this->config['config']['stat_apache_pagenames'] ? $this->config['config']['stat_apache_pagenames'] : '[path][title]--[uid].html';
03678         $pageName = str_replace('[title]', $shortTitle ,$pageName);
03679         $pageName = str_replace('[uid]',$this->page['uid'],$pageName);
03680         $pageName = str_replace('[alias]',$this->page['alias'],$pageName);
03681         $pageName = str_replace('[type]',$this->type,$pageName);
03682         $pageName = str_replace('[request_uri]',t3lib_div::getIndpEnv('REQUEST_URI'),$pageName);
03683 
03684         $temp = $this->config['rootLine'];
03685         if ($temp) {    // rootLine does not exist if this function is called at early stage (e.g. if DB connection failed)
03686             array_pop($temp);
03687             if ($this->config['config']['stat_apache_noRoot']) {
03688                 array_shift($temp);
03689             }
03690 
03691             $len = t3lib_div::intInRange($this->config['config']['stat_titleLen'],1,100,20);
03692             if ($this->config['config']['stat_apache_niceTitle'] == 'utf-8') {
03693                 $path = '';
03694                 $c = count($temp);
03695                 for ($i=0; $i<$c; $i++) {
03696                     if ($temp[$i]['uid']) {
03697                         $p = $this->csConvObj->crop('utf-8',$this->csConvObj->utf8_encode($temp[$i]['title'],$this->renderCharset),$len,"\xE2\x80\xA6");    // U+2026; HORIZONTAL ELLIPSIS
03698                         $path.= '/' . rawurlencode($p);
03699                     }
03700                 }
03701             } elseif ($this->config['config']['stat_apache_niceTitle']) {
03702                 $path = $this->csConvObj->specCharsToASCII($this->renderCharset,$this->sys_page->getPathFromRootline($temp,$len));
03703             } else {
03704                 $path = $this->sys_page->getPathFromRootline($temp,$len);
03705             }
03706         } else {
03707             $path = ''; // If rootLine is missing, we just drop the path...
03708         }
03709 
03710         if ($this->config['config']['stat_apache_niceTitle'] == 'utf-8') {
03711             $this->config['stat_vars']['pageName'] = str_replace('[path]', $path.'/', $pageName);
03712         } else {
03713             $this->config['stat_vars']['pageName'] = str_replace('[path]', preg_replace('/[^.[:alnum:]\/_-]/','_',$path.'/'), $pageName);
03714         }
03715     }
03716 
03717     /**
03718      * Saves hit statistics
03719      *
03720      * @return  void
03721      */
03722     function statistics()   {
03723         if (!empty($this->config['config']['stat']) &&
03724                 (!strcmp('',$this->config['config']['stat_typeNumList']) || t3lib_div::inList(str_replace(' ','',$this->config['config']['stat_typeNumList']), $this->type)) &&
03725                 (empty($this->config['config']['stat_excludeBEuserHits']) || !$this->beUserLogin) &&
03726                 (empty($this->config['config']['stat_excludeIPList']) || !t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'),str_replace(' ','',$this->config['config']['stat_excludeIPList'])))) {
03727 
03728             $GLOBALS['TT']->push('Stat');
03729                 if (t3lib_extMgm::isLoaded('sys_stat') && !empty($this->config['config']['stat_mysql'])) {
03730 
03731                         // Jumpurl:
03732                     $sword = t3lib_div::_GP('sword');
03733                     if ($sword) {
03734                         $jumpurl_msg = 'sword:'.$sword;
03735                     } elseif ($this->jumpurl) {
03736                         $jumpurl_msg = 'jumpurl:'.$this->jumpurl;
03737                     } else {
03738                         $jumpurl_msg = '';
03739                     }
03740 
03741                         // Flags: bits: 0 = BE_user, 1=Cached page?
03742                     $flags=0;
03743                     if ($this->beUserLogin) {$flags|=1;}
03744                     if ($this->cacheContentFlag) {$flags|=2;}
03745 
03746                         // Ref url:
03747                     $refUrl = t3lib_div::getIndpEnv('HTTP_REFERER');
03748                     $thisUrl = t3lib_div::getIndpEnv('TYPO3_REQUEST_DIR');
03749                     if (t3lib_div::isFirstPartOfStr($refUrl,$thisUrl))  {
03750                         $refUrl='[LOCAL]';
03751                     }
03752 
03753                     $insertFields = array(
03754                         'page_id' => intval($this->id),                         // id
03755                         'page_type' => intval($this->type),                     // type
03756                         'jumpurl' => $jumpurl_msg,                              // jumpurl message
03757                         'feuser_id' => $this->fe_user->user['uid'],             // fe_user id, integer
03758                         'cookie' => $this->fe_user->id,                         // cookie as set or retrieve. If people has cookies disabled this will vary all the time...
03759                         'sureCookie' => hexdec(substr($this->fe_user->cookieId,0,8)),   // This is the cookie value IF the cookie WAS actually set. However the first hit where the cookie is set will thus NOT be logged here. So this lets you select for a session of at least two clicks...
03760                         'rl0' => $this->config['rootLine'][0]['uid'],           // RootLevel 0 uid
03761                         'rl1' => $this->config['rootLine'][1]['uid'],           // RootLevel 1 uid
03762                         'client_browser' => $GLOBALS['CLIENT']['BROWSER'],      // Client browser (net, msie, opera)
03763                         'client_version' => $GLOBALS['CLIENT']['VERSION'],      // Client version (double value)
03764                         'client_os' => $GLOBALS['CLIENT']['SYSTEM'],            // Client Operating system (win, mac, unix)
03765                         'parsetime' => intval($this->scriptParseTime),          // Parsetime for the page.
03766                         'flags' => $flags,                                      // Flags: Is be user logged in? Is page cached?
03767                         'IP' => t3lib_div::getIndpEnv('REMOTE_ADDR'),           // Remote IP address
03768                         'host' => t3lib_div::getIndpEnv('REMOTE_HOST'),         // Remote Host Address
03769                         'referer' => $refUrl,                                   // Referer URL
03770                         'browser' => t3lib_div::getIndpEnv('HTTP_USER_AGENT'),  // User Agent Info.
03771                         'tstamp' => $GLOBALS['EXEC_TIME']                       // Time stamp
03772                     );
03773 
03774                         // Hook for preprocessing the list of fields to insert into sys_stat:
03775                     if (isset($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['sys_stat-PreProcClass']) && is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['sys_stat-PreProcClass'])) {
03776                         foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['sys_stat-PreProcClass'] as $_classRef)    {
03777                             $_procObj = t3lib_div::getUserObj($_classRef);
03778                             $insertFields = $_procObj->sysstat_preProcessFields($insertFields,$this);
03779                         }
03780                     }
03781 
03782 
03783                     $GLOBALS['TT']->push('Store SQL');
03784                     $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_stat', $insertFields);
03785                     $GLOBALS['TT']->pull();
03786                 }
03787 
03788                     // Apache:
03789                 if (!empty($this->config['config']['stat_apache']) && !empty($this->config['stat_vars']['pageName'])) {
03790                     if (@is_file($this->config['stat_vars']['logFile'])) {
03791                             // Build a log line (format is derived from the NCSA extended/combined log format)
03792                             // Log part 1: Remote hostname / address
03793                         $LogLine = (t3lib_div::getIndpEnv('REMOTE_HOST') && empty($this->config['config']['stat_apache_noHost'])) ? t3lib_div::getIndpEnv('REMOTE_HOST') : t3lib_div::getIndpEnv('REMOTE_ADDR');
03794                             // Log part 2: Fake the remote logname
03795                         $LogLine.= ' -';
03796                             // Log part 3: Remote username
03797                         $LogLine.= ' '.($this->loginUser ? $this->fe_user->user['username'] : '-');
03798                             // Log part 4: Time
03799                         $LogLine.= ' '.date('[d/M/Y:H:i:s +0000]',$GLOBALS['EXEC_TIME']);
03800                             // Log part 5: First line of request (the request filename)
03801                         $LogLine.= ' "GET '.$this->config['stat_vars']['pageName'].' HTTP/1.1"';
03802                             // Log part 6: Status and content length (ignores special content like admin panel!)
03803                         $LogLine.= ' 200 '.strlen($this->content);
03804 
03805                         if (empty($this->config['config']['stat_apache_notExtended'])) {
03806                             $referer = t3lib_div::getIndpEnv('HTTP_REFERER');
03807                             $LogLine.= ' "'.($referer ? $referer : '-').'" "'.t3lib_div::getIndpEnv('HTTP_USER_AGENT').'"';
03808                         }
03809 
03810                         $GLOBALS['TT']->push('Write to log file (fputs)');
03811                             $logfilehandle = fopen($this->config['stat_vars']['logFile'], 'a');
03812                             fputs($logfilehandle, $LogLine.LF);
03813                             @fclose($logfilehandle);
03814                         $GLOBALS['TT']->pull();
03815 
03816                         $GLOBALS['TT']->setTSlogMessage('Writing to logfile: OK',0);
03817                     } else {
03818                         $GLOBALS['TT']->setTSlogMessage('Writing to logfile: Error - logFile did not exist!',3);
03819                     }
03820                 }
03821             $GLOBALS['TT']->pull();
03822         }
03823     }
03824 
03825     /**
03826      * Outputs preview info.
03827      *
03828      * @return  void
03829      */
03830     function previewInfo()  {
03831         if ($this->fePreview && (!isset($this->config['config']['disablePreviewNotification']) || intval($this->config['config']['disablePreviewNotification']) !== 1)) {
03832                 if ($this->fePreview === 2) {
03833                     $onclickForStoppingPreview = 'document.location="'.t3lib_div::getIndpEnv('TYPO3_SITE_URL').'index.php?ADMCMD_prev=LOGOUT&returnUrl='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI')).'";return false;';
03834                     $text = 'Preview of workspace "'.$this->whichWorkspace(TRUE).'" ('.$this->whichWorkspace().')';
03835                     $html = $this->doWorkspacePreview() ? '<br/><input name="_" type="submit" value="Stop preview" onclick="'.htmlspecialchars($onclickForStoppingPreview).'" />' : '';
03836                 } else {
03837                     $text = 'PREVIEW!';
03838                     $html = '';
03839                 }
03840 
03841                 $stdMsg = '<div id="typo3-previewInfo" style="position: absolute; top: 20px; right: 20px; border: 2px solid #000; padding: 5px 5px; background: #f00; font: 1em Verdana; color: #000; font-weight: bold; z-index: 10001">'.htmlspecialchars($text).$html.'</div>';
03842 
03843                 if ($this->fePreview === 2) {
03844                     $temp_content = $this->config['config']['message_preview_workspace'] ?
03845                         @sprintf($this->config['config']['message_preview_workspace'], $this->whichWorkspace(TRUE),$this->whichWorkspace()) :
03846                         $stdMsg;
03847                 } else {
03848                     $temp_content = $this->config['config']['message_preview'] ? $this->config['config']['message_preview'] : $stdMsg;
03849                 }
03850                 echo $temp_content;
03851         }
03852     }
03853 
03854     /**
03855      * End-Of-Frontend hook
03856      *
03857      * @return  void
03858      */
03859     function hook_eofe()    {
03860 
03861             // Call hook for end-of-frontend processing:
03862         if (isset($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['hook_eofe']) && is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['hook_eofe'])) {
03863             $_params = array('pObj' => &$this);
03864             foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['hook_eofe'] as $_funcRef) {
03865                 t3lib_div::callUserFunction($_funcRef,$_params,$this);
03866             }
03867         }
03868     }
03869 
03870     /**
03871      * Returns a link to the BE login screen with redirect to the front-end
03872      *
03873      * @return  string      HTML, a tag for a link to the backend.
03874      */
03875     function beLoginLinkIPList()    {
03876         if (!empty($this->config['config']['beLoginLinkIPList'])) {
03877             if (t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $this->config['config']['beLoginLinkIPList']))   {
03878                 $label = !$this->beUserLogin ? $this->config['config']['beLoginLinkIPList_login'] : $this->config['config']['beLoginLinkIPList_logout'];
03879                 if ($label) {
03880                     if (!$this->beUserLogin)    {
03881                         $link = '<a href="'.htmlspecialchars(TYPO3_mainDir.'index.php?redirect_url='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'))).'">'.$label.'</a>';
03882                     } else {
03883                         $link = '<a href="'.htmlspecialchars(TYPO3_mainDir.'index.php?L=OUT&redirect_url='.rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'))).'">'.$label.'</a>';
03884                     }
03885                     return $link;
03886                 }
03887             }
03888         }
03889     }
03890 
03891     /**
03892      * Sends HTTP headers for temporary content. These headers prevent search engines from caching temporary content and asks them to revisit this page again.
03893      *
03894      * @return  void
03895      */
03896     function addTempContentHttpHeaders() {
03897         header('HTTP/1.0 503 Service unavailable');
03898         header('Retry-after: 3600');
03899         header('Pragma: no-cache');
03900         header('Cache-control: no-cache');
03901         header('Expire: 0');
03902     }
03903 
03904 
03905 
03906 
03907 
03908 
03909 
03910 
03911 
03912 
03913 
03914 
03915 
03916 
03917 
03918 
03919 
03920 
03921 
03922 
03923 
03924     /********************************************
03925      *
03926      * Various internal API functions
03927      *
03928      *******************************************/
03929 
03930 
03931     /**
03932      * Make simulation filename (without the ".html" ending, only body of filename)
03933      *
03934      * @param   string      The page title to use
03935      * @param   mixed       The page id (integer) or alias (string)
03936      * @param   integer     The type number
03937      * @param   string      Query-parameters to encode (will be done only if caching is enabled and TypoScript configured for it. I don't know it this makes much sense in fact...)
03938      * @param   boolean     The "no_cache" status of the link.
03939      * @return  string      The body of the filename.
03940      * @see getSimulFileName(), t3lib_tstemplate::linkData(), tslib_frameset::frameParams()
03941      * @deprecated since TYPO3 4.3, will be removed in TYPO3 4.6, please use the "simulatestatic" sysext directly
03942      * @todo    Deprecated but still used in the Core!
03943      */
03944     function makeSimulFileName($inTitle, $page, $type, $addParams = '', $no_cache = false) {
03945         t3lib_div::logDeprecatedFunction();
03946 
03947         if (t3lib_extMgm::isLoaded('simulatestatic')) {
03948             $parameters = array(
03949                 'inTitle' => $inTitle,
03950                 'page' => $page,
03951                 'type' => $type,
03952                 'addParams' => $addParams,
03953                 'no_cache' => $no_cache,
03954             );
03955             return t3lib_div::callUserFunction(
03956                 'EXT:simulatestatic/class.tx_simulatestatic.php:&tx_simulatestatic->makeSimulatedFileNameCompat',
03957                 $parameters,
03958                 $this
03959             );
03960         } else {
03961             return false;
03962         }
03963     }
03964 
03965     /**
03966      * Processes a query-string with GET-parameters and returns two strings, one with the parameters that CAN be encoded and one array with those which can't be encoded (encoded by the M5 or B6 methods)
03967      *
03968      * @param   string      Query string to analyse
03969      * @return  array       Two num keys returned, first is the parameters that MAY be encoded, second is the non-encodable parameters.
03970      * @see makeSimulFileName(), t3lib_tstemplate::linkData()
03971      * @deprecated since TYPO3 4.3, will be removed in TYPO3 4.6, please use the "simulatestatic" sysext directly
03972      */
03973     function simulateStaticDocuments_pEnc_onlyP_proc($linkVars) {
03974         t3lib_div::logDeprecatedFunction();
03975 
03976         if (t3lib_extMgm::isLoaded('simulatestatic')) {
03977             return t3lib_div::callUserFunction(
03978                 'EXT:simulatestatic/class.tx_simulatestatic.php:&tx_simulatestatic->processEncodedQueryString',
03979                 $linkVars,
03980                 $this
03981             );
03982         } else {
03983             return false;
03984         }
03985     }
03986 
03987     /**
03988      * Returns the simulated static file name (*.html) for the current page (using the page record in $this->page)
03989      *
03990      * @return  string      The filename (without path)
03991      * @see makeSimulFileName(), publish.php
03992      * @deprecated since TYPO3 4.3, will be removed in TYPO3 4.6, please use the "simulatestatic" sysext directly
03993      * @todo    Deprecated but still used in the Core!
03994      */
03995     function getSimulFileName() {
03996         t3lib_div::logDeprecatedFunction();
03997 
03998         return $this->makeSimulFileName(
03999             $this->page['title'],
04000             ($this->page['alias'] ? $this->page['alias'] : $this->id),
04001             $this->type
04002         ) . '.html';
04003     }
04004 
04005     /**
04006      * Checks and sets replacement character for simulateStaticDocuments. Default is underscore.
04007      *
04008      * @return  void
04009      * @deprecated since TYPO3 4.3, will be removed in TYPO3 4.6, please use the "simulatestatic" sysext directly
04010      */
04011     function setSimulReplacementChar() {
04012         t3lib_div::logDeprecatedFunction();
04013 
04014         $replacement = $defChar = t3lib_div::compat_version('4.0') ? '-' : '_';
04015         if (isset($this->config['config']['simulateStaticDocuments_replacementChar'])) {
04016             $replacement = trim($this->config['config']['simulateStaticDocuments_replacementChar']);
04017             if (urlencode($replacement) != $replacement) {
04018                     // Invalid character
04019                 $replacement = $defChar;
04020             }
04021         }
04022         $this->config['config']['simulateStaticDocuments_replacementChar'] = $replacement;
04023     }
04024 
04025     /**
04026      * Converts input string to an ASCII based file name prefix
04027      *
04028      * @param   string      String to base output on
04029      * @param   integer     Number of characters in the string
04030      * @param   string      Character to put in the end of string to merge it with the next value.
04031      * @return  string      String
04032      * @deprecated since TYPO3, 4.3, will be removed in TYPO3 4.6, please use the "simulatestatic" sysext directly
04033      * @todo    Deprecated but still used in the Core!
04034      */
04035     function fileNameASCIIPrefix($inTitle,$titleChars,$mergeChar='.')   {
04036         t3lib_div::logDeprecatedFunction();
04037         $out = $this->csConvObj->specCharsToASCII($this->renderCharset, $inTitle);
04038             // Get replacement character
04039         $replacementChar = $this->config['config']['simulateStaticDocuments_replacementChar'];
04040         $replacementChars = '_\-' . ($replacementChar != '_' && $replacementChar != '-' ? $replacementChar : '');
04041         $out = preg_replace('/[^A-Za-z0-9_-]/', $replacementChar, trim(substr($out, 0, $titleChars)));
04042         $out = preg_replace('/([' . $replacementChars . ']){2,}/', '\1', $out);
04043         $out = preg_replace('/[' . $replacementChars . ']?$/', '', $out);
04044         $out = preg_replace('/^[' . $replacementChars . ']?/', '', $out);
04045         if (strlen($out)) {
04046             $out.= $mergeChar;
04047         }
04048 
04049         return $out;
04050     }
04051 
04052     /**
04053      * Encryption (or decryption) of a single character.
04054      * Within the given range the character is shifted with the supplied offset.
04055      *
04056      * @param   int     Ordinal of input character
04057      * @param   int     Start of range
04058      * @param   int     End of range
04059      * @param   int     Offset
04060      * @return  string      encoded/decoded version of character
04061      */
04062     function encryptCharcode($n,$start,$end,$offset)    {
04063         $n = $n + $offset;
04064         if ($offset > 0 && $n > $end)   {
04065             $n = $start + ($n - $end - 1);
04066         } else if ($offset < 0 && $n < $start)  {
04067             $n = $end - ($start - $n - 1);
04068         }
04069         return chr($n);
04070     }
04071 
04072     /**
04073      * Encryption of email addresses for <A>-tags See the spam protection setup in TS 'config.'
04074      *
04075      * @param   string      Input string to en/decode: "mailto:blabla@bla.com"
04076      * @param   boolean     If set, the process is reversed, effectively decoding, not encoding.
04077      * @return  string      encoded/decoded version of $string
04078      */
04079     function encryptEmail($string,$back=0)  {
04080         $out = '';
04081 
04082         if ($this->spamProtectEmailAddresses === 'ascii') {
04083             for ($a=0; $a<strlen($string); $a++) {
04084                 $out .= '&#'.ord(substr($string, $a, 1)).';';
04085             }
04086         } else  {
04087                 // like str_rot13() but with a variable offset and a wider character range
04088             $len = strlen($string);
04089             $offset = intval($this->spamProtectEmailAddresses)*($back?-1:1);
04090             for ($i=0; $i<$len; $i++)   {
04091                 $charValue = ord($string{$i});
04092                 if ($charValue >= 0x2B && $charValue <= 0x3A)   {   // 0-9 . , - + / :
04093                     $out .= $this->encryptCharcode($charValue,0x2B,0x3A,$offset);
04094                 } elseif ($charValue >= 0x40 && $charValue <= 0x5A) {   // A-Z @
04095                     $out .= $this->encryptCharcode($charValue,0x40,0x5A,$offset);
04096                 } else if ($charValue >= 0x61 && $charValue <= 0x7A)    {   // a-z
04097                     $out .= $this->encryptCharcode($charValue,0x61,0x7A,$offset);
04098                 } else {
04099                     $out .= $string{$i};
04100                 }
04101             }
04102         }
04103         return $out;
04104     }
04105 
04106     /**
04107      * En/decodes strings with lightweight encryption and a hash containing the server encryptionKey (salt)
04108      * Can be used for authentication of information sent from server generated pages back to the server to establish that the server generated the page. (Like hidden fields with recipient mail addresses)
04109      * Encryption is mainly to avoid spam-bots to pick up information.
04110      *
04111      * @param   string      Input string to en/decode
04112      * @param   boolean     If set, string is decoded, not encoded.
04113      * @return  string      encoded/decoded version of $string
04114      */
04115     function codeString($string, $decode=FALSE) {
04116 
04117         if ($decode)    {
04118             list($md5Hash, $str) = explode(':',$string,2);
04119             $newHash = substr(md5($this->TYPO3_CONF_VARS['SYS']['encryptionKey'].':'.$str),0,10);
04120             if (!strcmp($md5Hash, $newHash))    {
04121                 $str = base64_decode($str);
04122                 $str = $this->roundTripCryptString($str);
04123                 return $str;
04124             } else return FALSE;    // Decoding check failed! Original string not produced by this server!
04125         } else {
04126             $str = $string;
04127             $str = $this->roundTripCryptString($str);
04128             $str = base64_encode($str);
04129             $newHash = substr(md5($this->TYPO3_CONF_VARS['SYS']['encryptionKey'].':'.$str),0,10);
04130             return $newHash.':'.$str;
04131         }
04132     }
04133 
04134     /**
04135      * Encrypts a strings by XOR'ing all characters with a key derived from the
04136      * TYPO3 encryption key.
04137      *
04138      * Using XOR means that the string can be decrypted by simply calling the
04139      * function again - just like rot-13 works (but in this case for ANY byte
04140      * value).
04141      *
04142      * @param string $string string to crypt, may be empty
04143      *
04144      * @return string binary crypt string, will have the same length as $string
04145      */
04146     protected function roundTripCryptString($string) {
04147         $out = '';
04148 
04149         $cleartextLength = strlen($string);
04150         $key = sha1($this->TYPO3_CONF_VARS['SYS']['encryptionKey']);
04151         $keyLength = strlen($key);
04152 
04153         for ($a = 0; $a < $cleartextLength; $a++) {
04154             $xorVal = ord($key{($a % $keyLength)});
04155             $out .= chr(ord($string{$a}) ^ $xorVal);
04156         }
04157 
04158         return $out;
04159     }
04160 
04161     /**
04162      * Checks if a PHPfile may be included.
04163      *
04164      * @param   string      Relative path to php file
04165      * @return  boolean     Returns true if $GLOBALS['TYPO3_CONF_VARS']['FE']['noPHPscriptInclude'] is not set OR if the file requested for inclusion is found in one of the allowed paths.
04166      * @see tslib_cObj::PHP_SCRIPT(), tslib_feTCE::includeScripts(), tslib_menu::includeMakeMenu()
04167      */
04168     function checkFileInclude($incFile) {
04169         return !$this->TYPO3_CONF_VARS['FE']['noPHPscriptInclude']
04170             || substr($incFile,0,14)=='media/scripts/'
04171             || substr($incFile,0,4+strlen(TYPO3_mainDir))==TYPO3_mainDir.'ext/'
04172             || substr($incFile,0,7+strlen(TYPO3_mainDir))==TYPO3_mainDir.'sysext/'
04173             || substr($incFile,0,14)=='typo3conf/ext/';
04174     }
04175 
04176     /**
04177      * Creates an instance of tslib_cObj in $this->cObj
04178      * This instance is used to start the rendering of the TypoScript template structure
04179      *
04180      * @return  void
04181      * @see pagegen.php
04182      */
04183     function newCObj()  {
04184         $this->cObj =t3lib_div::makeInstance('tslib_cObj');
04185         $this->cObj->start($this->page,'pages');
04186     }
04187 
04188     /**
04189      * Converts relative paths in the HTML source to absolute paths for fileadmin/, typo3conf/ext/ and media/ folders.
04190      *
04191      * @return  void
04192      * @access private
04193      * @see pagegen.php, INTincScript()
04194      */
04195     function setAbsRefPrefix()  {
04196         if ($this->absRefPrefix)    {
04197             $this->content = str_replace('"media/', '"'.t3lib_extMgm::siteRelPath('cms').'tslib/media/', $this->content);
04198             $this->content = str_replace('"typo3conf/ext/', '"'.$this->absRefPrefix.'typo3conf/ext/', $this->content);
04199             $this->content = str_replace('"' . TYPO3_mainDir . 'contrib/', '"' . $this->absRefPrefix . TYPO3_mainDir . 'contrib/', $this->content);
04200             $this->content = str_replace('"' . TYPO3_mainDir . 'ext/', '"' . $this->absRefPrefix . TYPO3_mainDir . 'ext/', $this->content);
04201             $this->content = str_replace('"' . TYPO3_mainDir . 'sysext/' , '"' . $this->absRefPrefix . TYPO3_mainDir . 'sysext/', $this->content);
04202             $this->content = str_replace('"'.$GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], '"'.$this->absRefPrefix.$GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], $this->content);
04203             $this->content = str_replace('"' . $GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_imageStorageDir'], '"' . $this->absRefPrefix . $GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_imageStorageDir'], $this->content);
04204             // Process additional directories
04205             $directories = t3lib_div::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['FE']['additionalAbsRefPrefixDirectories'], true);
04206             foreach ($directories as $directory) {
04207                 $this->content = str_replace('"' . $directory, '"' . $this->absRefPrefix . $directory, $this->content);
04208             }
04209         }
04210     }
04211 
04212     /**
04213      * Prefixing the input URL with ->baseUrl If ->baseUrl is set and the input url is not absolute in some way.
04214      * Designed as a wrapper functions for use with all frontend links that are processed by JavaScript (for "realurl" compatibility!). So each time a URL goes into window.open, window.location.href or otherwise, wrap it with this function!
04215      *
04216      * @param   string      Input URL, relative or absolute
04217      * @return  string      Processed input value.
04218      */
04219     function baseUrlWrap($url)  {
04220         if ($this->baseUrl) {
04221             $urlParts = parse_url($url);
04222             if (!strlen($urlParts['scheme']) && $url{0}!=='/')  {
04223                 $url = $this->baseUrl.$url;
04224             }
04225         }
04226         return $url;
04227     }
04228 
04229     /**
04230      * Prints error msg/header.
04231      * Echoes out the HTML content
04232      *
04233      * @param   string      Message string
04234      * @param   string      Header string
04235      * @return  void
04236      * @see t3lib_timeTrack::debug_typo3PrintError()
04237      * @see t3lib_message_ErrorPageMessage
04238      * @deprecated since TYPO3 4.5, will be removed in TYPO3 4.7
04239      */
04240     function printError($label,$header='Error!') {
04241         t3lib_div::logDeprecatedFunction();
04242         t3lib_timeTrack::debug_typo3PrintError($header, $label, 0, t3lib_div::getIndpEnv('TYPO3_SITE_URL'));
04243     }
04244 
04245     /**
04246      * Logs access to deprecated TypoScript objects and properties.
04247      *
04248      * Dumps message to the TypoScript message log (admin panel) and the TYPO3 deprecation log.
04249      * Note: The second parameter was introduced in TYPO3 4.5 and is not available in older versions
04250      *
04251      * @param   string      Deprecated object or property
04252      * @param   string      Message or additional information
04253      * @return  void
04254      * @see t3lib_div::deprecationLog(), t3lib_timeTrack::setTSlogMessage()
04255      */
04256     function logDeprecatedTyposcript($typoScriptProperty, $explanation = '') {
04257         $explanationText = (strlen($explanation) ? ' - ' . $explanation : '');
04258         $GLOBALS['TT']->setTSlogMessage($typoScriptProperty . ' is deprecated.' . $explanationText, 2);
04259         t3lib_div::deprecationLog('TypoScript ' . $typoScriptProperty . ' is deprecated' . $explanationText);
04260     }
04261 
04262     /**
04263      * Updates the tstamp field of a cache_md5params record to the current time.
04264      *
04265      * @param   string      The hash string identifying the cache_md5params record for which to update the "tstamp" field to the current time.
04266      * @return  void
04267      * @access private
04268      */
04269     function updateMD5paramsRecord($hash)   {
04270         $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
04271             'cache_md5params',
04272             'md5hash=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($hash, 'cache_md5params'), array('tstamp' => $GLOBALS['EXEC_TIME'])
04273         );
04274     }
04275 
04276     /**
04277      * Pass the content through tidy - a little program that cleans up HTML-code.
04278      * Requires $this->TYPO3_CONF_VARS['FE']['tidy'] to be true and $this->TYPO3_CONF_VARS['FE']['tidy_path'] to contain the filename/path of tidy including clean-up arguments for tidy. See default value in TYPO3_CONF_VARS in t3lib/config_default.php
04279      *
04280      * @param   string      The page content to clean up. Will be written to a temporary file which "tidy" is then asked to clean up. File content is read back and returned.
04281      * @return  string      Returns the
04282      */
04283     function tidyHTML($content)     {
04284         if ($this->TYPO3_CONF_VARS['FE']['tidy'] && $this->TYPO3_CONF_VARS['FE']['tidy_path'])  {
04285             $oldContent = $content;
04286             $fname = t3lib_div::tempnam('typo3_tidydoc_');      // Create temporary name
04287             @unlink ($fname);   // Delete if exists, just to be safe.
04288             $fp = fopen ($fname,'wb');  // Open for writing
04289             fputs ($fp, $content);  // Put $content
04290             @fclose ($fp);  // Close
04291 
04292             exec ($this->TYPO3_CONF_VARS['FE']['tidy_path'].' '.$fname, $output);           // run the $content through 'tidy', which formats the HTML to nice code.
04293             @unlink ($fname);   // Delete the tempfile again
04294             $content = implode(LF,$output);
04295             if (!trim($content))    {
04296                 $content = $oldContent; // Restore old content due empty return value.
04297                 $GLOBALS['TT']->setTSlogMessage('"tidy" returned an empty value!',2);
04298             }
04299             $GLOBALS['TT']->setTSlogMessage('"tidy" content lenght: '.strlen($content),0);
04300         }
04301         return $content;
04302     }
04303 
04304     /**
04305      * Substitutes all occurencies of <a href="#"... in $this->content with <a href="[path-to-url]#"...
04306      *
04307      * @return  void        Works directly on $this->content
04308      */
04309     function prefixLocalAnchorsWithScript() {
04310         $scriptPath = $GLOBALS['TSFE']->absRefPrefix . substr(t3lib_div::getIndpEnv('TYPO3_REQUEST_URL'),strlen(t3lib_div::getIndpEnv('TYPO3_SITE_URL')));
04311         $originalContent = $this->content;
04312         $this->content = preg_replace('/(<(?:a|area).*?href=")(#[^"]*")/i', '${1}' . htmlspecialchars($scriptPath) . '${2}', $originalContent);
04313             // There was an error in the call to preg_replace, so keep the original content (behavior prior to PHP 5.2)
04314         if (preg_last_error() > 0) {
04315             t3lib_div::sysLog('preg_replace returned error-code: ' . preg_last_error().' in function prefixLocalAnchorsWithScript. Replacement not done!' , 'cms', 4);
04316             $this->content = $originalContent;
04317         }
04318     }
04319 
04320     /**
04321      * Initialize workspace preview
04322      *
04323      * @return  void
04324      */
04325     function workspacePreviewInit() {
04326         $previewWS = t3lib_div::_GP('ADMCMD_previewWS');
04327         if ($this->beUserLogin && is_object($GLOBALS['BE_USER']) && t3lib_div::testInt($previewWS)) {
04328             if ($previewWS==0 || ($previewWS>=-1 && $GLOBALS['BE_USER']->checkWorkspace($previewWS))) { // Check Access to workspace. Live (0) is OK to preview for all.
04329                 $this->workspacePreview = intval($previewWS);
04330             } else {
04331                 $this->workspacePreview = -99;  // No preview, will default to "Live" at the moment
04332             }
04333         }
04334     }
04335 
04336     /**
04337      * Returns true if workspace preview is enabled
04338      *
04339      * @return  boolean     Returns true if workspace preview is enabled
04340      */
04341     function doWorkspacePreview()   {
04342         return (string)$this->workspacePreview!=='';
04343     }
04344 
04345     /**
04346      * Returns the name of the workspace
04347      *
04348      * @param   boolean     If set, returns title of current workspace being previewed
04349      * @return  mixed       If $returnTitle is set, returns string (title), otherwise workspace integer for which workspace is being preview. False if none.
04350      */
04351     function whichWorkspace($returnTitle = FALSE)   {
04352         if ($this->doWorkspacePreview())    {
04353             $ws = intval($this->workspacePreview);
04354         } elseif ($this->beUserLogin) {
04355             $ws = $GLOBALS['BE_USER']->workspace;
04356         } else return FALSE;
04357 
04358         if ($returnTitle)   {
04359             if ($ws===-1)   {
04360                 return 'Default Draft Workspace';
04361             } elseif (t3lib_extMgm::isLoaded('workspaces')) {
04362                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('title', 'sys_workspace', 'uid='.intval($ws));
04363                 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
04364                     return $row['title'];
04365                 }
04366             }
04367         } else {
04368             return $ws;
04369         }
04370     }
04371 
04372     /**
04373      * Includes a comma-separated list of library files by PHP function include_once.
04374      *
04375      * @param   array       $libraries: The libraries to be included.
04376      * @return  void
04377      */
04378     public function includeLibraries(array $libraries) {
04379         global $TYPO3_CONF_VARS;
04380 
04381         $GLOBALS['TT']->push('Include libraries');
04382         $GLOBALS['TT']->setTSlogMessage('Files for inclusion: "' . implode(', ', $libraries) . '"');
04383 
04384         foreach ($libraries as $library) {
04385             $file = $GLOBALS['TSFE']->tmpl->getFileName($library);
04386             if ($file) {
04387                 include_once('./' . $file);
04388             } else {
04389                 $GLOBALS['TT']->setTSlogMessage('Include file "' . $file . '" did not exist!', 2);
04390             }
04391         }
04392 
04393         $GLOBALS['TT']->pull();
04394     }
04395 
04396 
04397 
04398 
04399 
04400 
04401 
04402 
04403 
04404 
04405 
04406 
04407 
04408 
04409 
04410 
04411 
04412 
04413 
04414 
04415 
04416 
04417 
04418 
04419 
04420 
04421 
04422     /********************************************
04423      *
04424      * Various external API functions - for use in plugins etc.
04425      *
04426      *******************************************/
04427 
04428 
04429     /**
04430      * Traverses the ->rootLine and returns an array with the first occurrance of storage pid and siteroot pid
04431      *
04432      * @return  array       Array with keys '_STORAGE_PID' and '_SITEROOT' set to the first occurances found.
04433      */
04434     function getStorageSiterootPids()   {
04435         $res=array();
04436 
04437         if(!is_array($this->rootLine)) {
04438             return array();
04439         }
04440 
04441         foreach ($this->rootLine as $rC) {
04442             if (!$res['_STORAGE_PID'])  $res['_STORAGE_PID']=intval($rC['storage_pid']);
04443             if (!$res['_SITEROOT']) $res['_SITEROOT']=$rC['is_siteroot']?intval($rC['uid']):0;
04444         }
04445         return $res;
04446     }
04447 
04448     /**
04449      * Returns the pages TSconfig array based on the currect ->rootLine
04450      *
04451      * @return  array
04452      */
04453     function getPagesTSconfig() {
04454         if (!is_array($this->pagesTSconfig))    {
04455             $TSdataArray = array();
04456             $TSdataArray[] = $this->TYPO3_CONF_VARS['BE']['defaultPageTSconfig'];   // Setting default configuration:
04457             foreach ($this->rootLine as $k => $v) {
04458                 $TSdataArray[]=$v['TSconfig'];
04459             }
04460                 // Parsing the user TS (or getting from cache)
04461             $TSdataArray = t3lib_TSparser::checkIncludeLines_array($TSdataArray);
04462             $userTS = implode(LF.'[GLOBAL]'.LF,$TSdataArray);
04463             $hash = md5('pageTS:'.$userTS);
04464             $cachedContent = $this->sys_page->getHash($hash);
04465             if (isset($cachedContent))  {
04466                 $this->pagesTSconfig = unserialize($cachedContent);
04467             } else {
04468                 $parseObj = t3lib_div::makeInstance('t3lib_TSparser');
04469                 $parseObj->parse($userTS);
04470                 $this->pagesTSconfig = $parseObj->setup;
04471                 $this->sys_page->storeHash($hash,serialize($this->pagesTSconfig),'PAGES_TSconfig');
04472             }
04473         }
04474         return $this->pagesTSconfig;
04475     }
04476 
04477     /**
04478      * Sets JavaScript code in the additionalJavaScript array
04479      *
04480      * @param   string      $key is the key in the array, for num-key let the value be empty. Note reserved keys 'openPic' and 'mouseOver'
04481      * @param   string      $content is the content if you want any
04482      * @return  void
04483      * @see tslib_gmenu::writeMenu(), tslib_cObj::imageLinkWrap()
04484      */
04485     function setJS($key,$content='')    {
04486         if ($key)   {
04487             switch($key)    {
04488                 case 'mouseOver':
04489                     $this->additionalJavaScript[$key]=
04490 '       // JS function for mouse-over
04491     function over(name,imgObj)  {   //
04492         if (version == "n3" && document[name]) {document[name].src = eval(name+"_h.src");}
04493         else if (document.getElementById && document.getElementById(name)) {document.getElementById(name).src = eval(name+"_h.src");}
04494         else if (imgObj)    {imgObj.src = eval(name+"_h.src");}
04495     }
04496         // JS function for mouse-out
04497     function out(name,imgObj)   {   //
04498         if (version == "n3" && document[name]) {document[name].src = eval(name+"_n.src");}
04499         else if (document.getElementById && document.getElementById(name)) {document.getElementById(name).src = eval(name+"_n.src");}
04500         else if (imgObj)    {imgObj.src = eval(name+"_n.src");}
04501     }';
04502                 break;
04503                 case 'openPic':
04504                     $this->additionalJavaScript[$key]=
04505 '   function openPic(url,winName,winParams) {   //
04506         var theWindow = window.open(url,winName,winParams);
04507         if (theWindow)  {theWindow.focus();}
04508     }';
04509                 break;
04510                 default:
04511                     $this->additionalJavaScript[$key]=$content;
04512                 break;
04513             }
04514         }
04515     }
04516 
04517     /**
04518      * Sets CSS data in the additionalCSS array
04519      *
04520      * @param   string      $key is the key in the array, for num-key let the value be empty
04521      * @param   string      $content is the content if you want any
04522      * @return  void
04523      * @see setJS()
04524      */
04525     function setCSS($key,$content)  {
04526         if ($key)   {
04527             switch($key)    {
04528                 default:
04529                     $this->additionalCSS[$key]=$content;
04530                 break;
04531             }
04532         }
04533     }
04534 
04535     /**
04536      * Returns a unique md5 hash.
04537      * There is no special magic in this, the only point is that you don't have to call md5(uniqid()) which is slow and by this you are sure to get a unique string each time in a little faster way.
04538      *
04539      * @param   string      Some string to include in what is hashed. Not significant at all.
04540      * @return  string      MD5 hash of ->uniqueString, input string and uniqueCounter
04541      */
04542     function uniqueHash($str='')    {
04543         return md5($this->uniqueString.'_'.$str.$this->uniqueCounter++);
04544     }
04545 
04546     /**
04547      * Sets the cache-flag to 1. Could be called from user-included php-files in order to ensure that a page is not cached.
04548      *
04549      * @param   string      $reason: An optional reason to be written to the syslog.
04550      *                      If not set, debug_backtrace() will be used to track down the call.
04551      * @return  void
04552      */
04553     function set_no_cache($reason = '') {
04554         if (strlen($reason)) {
04555             $warning = '$TSFE->set_no_cache() was triggered. Reason: ' . $reason . '.';
04556         } else {
04557             $trace = debug_backtrace();
04558                 // This is a hack to work around ___FILE___ resolving symbolic links
04559             $PATH_site_real = str_replace('t3lib','',realpath(PATH_site.'t3lib'));
04560             $file = $trace[0]['file'];
04561             if (substr($file,0,strlen($PATH_site_real))===$PATH_site_real) {
04562                 $file = str_replace($PATH_site_real,'',$file);
04563             } else {
04564                 $file = str_replace(PATH_site,'',$file);
04565             }
04566             $line = $trace[0]['line'];
04567             $trigger = $file.' on line '.$line;
04568 
04569             $warning = '$TSFE->set_no_cache() was triggered by ' . $trigger.'.';
04570         }
04571 
04572         if ($this->TYPO3_CONF_VARS['FE']['disableNoCacheParameter']) {
04573             $warning.= ' However, $TYPO3_CONF_VARS[\'FE\'][\'disableNoCacheParameter\'] is set, so it will be ignored!';
04574             $GLOBALS['TT']->setTSlogMessage($warning,2);
04575         } else {
04576             $warning.= ' Caching is disabled!';
04577             $this->disableCache();
04578         }
04579 
04580         t3lib_div::sysLog($warning, 'cms', 2);
04581     }
04582 
04583     /**
04584      * Disables caching of the current page.
04585      *
04586      * @return void
04587      * @internal
04588      */
04589     protected function disableCache() {
04590         $this->no_cache = 1;
04591     }
04592 
04593     /**
04594      * Sets the cache-timeout in seconds
04595      *
04596      * @param   integer     cache-timeout in seconds
04597      * @return  void
04598      */
04599     function set_cache_timeout_default($seconds)    {
04600         $this->cacheTimeOutDefault = intval($seconds);
04601     }
04602 
04603     /**
04604      * Get the cache timeout for the current page.
04605      *
04606      * @return  integer     The cache timeout for the current page.
04607      */
04608     function get_cache_timeout() {
04609             // Cache period was set for the page:
04610         if ($this->page['cache_timeout']) {
04611             $cacheTimeout = intval($this->page['cache_timeout']);
04612             // Cache period was set for the whole site:
04613         } elseif ($this->cacheTimeOutDefault) {
04614             $cacheTimeout = $this->cacheTimeOutDefault;
04615             // No cache period set at all, so we take one day (60*60*24 seconds = 86400 seconds):
04616         } else {
04617             $cacheTimeout = 86400;
04618         }
04619         return $cacheTimeout;
04620     }
04621 
04622     /**
04623      * Substitute function for the PHP mail() function.
04624      * It will encode the email with the setting of TS 'config.notification_email_encoding' (base64 or none)
04625      * It will also find all links to http:// in the text and substitute with a shorter link using the redirect feature which stores the long link in the database. Depends on configuration in TS 'config.notification_email_urlmode'
04626      *
04627      * @param   string      recipient email address (or list of)
04628      * @param   string      The subject
04629      * @param   string      The message
04630      * @param   string      The headers (string with lines)
04631      * @return  void
04632      * @see t3lib_div::plainMailEncoded()
04633      */
04634     function plainMailEncoded($email,$subject,$message,$headers='') {
04635         $urlmode = $this->config['config']['notification_email_urlmode'];   // '76', 'all', ''
04636 
04637         if ($urlmode)   {
04638             $message = t3lib_div::substUrlsInPlainText($message,$urlmode);
04639         }
04640 
04641         $encoding = $this->config['config']['notification_email_encoding'] ? $this->config['config']['notification_email_encoding'] : '';
04642         $charset = $this->renderCharset;
04643 
04644         $convCharset = FALSE;   // do we need to convert mail data?
04645         if ($this->config['config']['notification_email_charset'])  {   // Respect config.notification_email_charset if it was set
04646             $charset = $this->csConvObj->parse_charset($this->config['config']['notification_email_charset']);
04647             if ($charset != $this->renderCharset)   {
04648                 $convCharset = TRUE;
04649             }
04650 
04651         } elseif ($this->metaCharset != $this->renderCharset)   {   // Use metaCharset for mail if different from renderCharset
04652             $charset = $this->metaCharset;
04653             $convCharset = TRUE;
04654         }
04655 
04656         if ($convCharset)   {
04657             $email = $this->csConvObj->conv($email,$this->renderCharset,$charset);
04658             $subject = $this->csConvObj->conv($subject,$this->renderCharset,$charset);
04659             $message = $this->csConvObj->conv($message,$this->renderCharset,$charset);
04660             $headers = $this->csConvObj->conv($headers,$this->renderCharset,$charset);
04661         }
04662 
04663         t3lib_div::plainMailEncoded(
04664             $email,
04665             $subject,
04666             $message,
04667             $headers,
04668             $encoding,
04669             $charset
04670         );
04671     }
04672 
04673 
04674 
04675 
04676 
04677 
04678 
04679 
04680 
04681 
04682 
04683 
04684 
04685     /*********************************************
04686      *
04687      * Localization and character set conversion
04688      *
04689      *********************************************/
04690 
04691     /**
04692      * Split Label function for front-end applications.
04693      *
04694      * @param   string      Key string. Accepts the "LLL:" prefix.
04695      * @return  string      Label value, if any.
04696      */
04697     function sL($input) {
04698         if (strcmp(substr($input,0,4),'LLL:'))  {
04699             $t = explode('|',$input);
04700             return $t[$this->langSplitIndex] ? $t[$this->langSplitIndex] : $t[0];
04701         } else {
04702             if (!isset($this->LL_labels_cache[$this->lang][$input])) {  // If cached label
04703                 $restStr = trim(substr($input,4));
04704                 $extPrfx='';
04705                 if (!strcmp(substr($restStr,0,4),'EXT:'))   {
04706                     $restStr = trim(substr($restStr,4));
04707                     $extPrfx='EXT:';
04708                 }
04709                 $parts = explode(':',$restStr);
04710                 $parts[0] = $extPrfx.$parts[0];
04711                 if (!isset($this->LL_files_cache[$parts[0]]))   {   // Getting data if not cached
04712                     $this->LL_files_cache[$parts[0]] = $this->readLLfile($parts[0]);
04713                 }
04714                 $this->LL_labels_cache[$this->lang][$input] = $this->getLLL($parts[1],$this->LL_files_cache[$parts[0]]);
04715             }
04716             return $this->LL_labels_cache[$this->lang][$input];
04717         }
04718     }
04719 
04720     /**
04721      * Read locallang files - for frontend applications
04722      *
04723      * @param   string      Reference to a relative filename to include.
04724      * @return  array       Returns the $LOCAL_LANG array found in the file. If no array found, returns empty array.
04725      */
04726     function readLLfile($fileRef)   {
04727         return t3lib_div::readLLfile($fileRef, $this->lang, $this->renderCharset);
04728     }
04729 
04730     /**
04731      * Returns 'locallang' label - may need initializing by initLLvars
04732      *
04733      * @param   string      Local_lang key for which to return label (language is determined by $this->lang)
04734      * @param   array       The locallang array in which to search
04735      * @return  string      Label value of $index key.
04736      */
04737     function getLLL($index, &$LOCAL_LANG)   {
04738         if (strcmp($LOCAL_LANG[$this->lang][$index],''))    {
04739             return $LOCAL_LANG[$this->lang][$index];
04740         } else {
04741             return $LOCAL_LANG['default'][$index];
04742         }
04743     }
04744 
04745     /**
04746      * Initializing the getLL variables needed.
04747      * Sets $this->langSplitIndex based on $this->config['config']['language']
04748      *
04749      * @return  void
04750      */
04751     function initLLvars()   {
04752 
04753             // Setting language key and split index:
04754         $this->lang = $this->config['config']['language'] ? $this->config['config']['language'] : 'default';
04755         $this->getPageRenderer()->setLanguage($this->lang);
04756 
04757         $ls = explode('|',TYPO3_languages);
04758         foreach ($ls as $i => $v) {
04759             if ($v==$this->lang)    {$this->langSplitIndex=$i; break;}
04760         }
04761 
04762             // Setting charsets:
04763         $this->renderCharset = $this->csConvObj->parse_charset($this->config['config']['renderCharset'] ? $this->config['config']['renderCharset'] : ($this->TYPO3_CONF_VARS['BE']['forceCharset'] ? $this->TYPO3_CONF_VARS['BE']['forceCharset'] : $this->defaultCharSet));    // Rendering charset of HTML page.
04764         $this->metaCharset = $this->csConvObj->parse_charset($this->config['config']['metaCharset'] ? $this->config['config']['metaCharset'] : $this->renderCharset);   // Output charset of HTML page.
04765     }
04766 
04767     /**
04768      * Converts the charset of the input string if applicable.
04769      * The "to" charset is determined by the currently used charset for the page which is "iso-8859-1" by default or set by $GLOBALS['TSFE']->config['config']['renderCharset']
04770      * Only if there is a difference between the two charsets will a conversion be made
04771      * The conversion is done real-time - no caching for performance at this point!
04772      *
04773      * @param   string      String to convert charset for
04774      * @param   string      Optional "from" charset.
04775      * @return  string      Output string, converted if needed.
04776      * @see t3lib_cs
04777      */
04778     function csConv($str,$from='')  {
04779         if ($from)  {
04780             $output = $this->csConvObj->conv($str,$this->csConvObj->parse_charset($from),$this->renderCharset,1);
04781             return $output ? $output : $str;
04782         } else {
04783             return $str;
04784         }
04785     }
04786 
04787     /**
04788      * Converts input string from renderCharset to metaCharset IF the two charsets are different.
04789      *
04790      * @param   string      Content to be converted.
04791      * @param   string      Label (just for fun, no function)
04792      * @return  string      Converted content string.
04793      */
04794     function convOutputCharset($content,$label='')  {
04795         if ($this->renderCharset != $this->metaCharset) {
04796             $content = $this->csConvObj->conv($content,$this->renderCharset,$this->metaCharset,TRUE);
04797         }
04798 
04799         return $content;
04800     }
04801 
04802     /**
04803      * Converts the $_POST array from metaCharset (page HTML charset from input form) to renderCharset (internal processing) IF the two charsets are different.
04804      *
04805      * @return  void
04806      */
04807     function convPOSTCharset()  {
04808         if ($this->renderCharset != $this->metaCharset && is_array($_POST) && count($_POST))    {
04809             $this->csConvObj->convArray($_POST,$this->metaCharset,$this->renderCharset);
04810             $GLOBALS['HTTP_POST_VARS'] = $_POST;
04811         }
04812     }
04813 }
04814 
04815 
04816 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_fe.php'])) {
04817     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_fe.php']);
04818 }
04819 
04820 ?>