*** empty log message ***
[Packages/TYPO3.CMS.git] / typo3 / sysext / cms / tslib / class.tslib_fe.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Class for the built TypoScript based Front End
29 *
30 * This class has a lot of functions and internal variable which are use from index_ts.php.
31 * The class is instantiated as $GLOBALS['TSFE'] in index_ts.php.
32 * The use of this class should be inspired by the order of function calls as found in index_ts.php.
33 *
34 * $Id$
35 * Revised for TYPO3 3.6 June/2003 by Kasper Skaarhoj
36 * XHTML compliant
37 *
38 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
39 */
40 /**
41 * [CLASS/FUNCTION INDEX of SCRIPT]
42 *
43 *
44 *
45 * 201: class tslib_fe
46 * 368: function tslib_fe($TYPO3_CONF_VARS, $id, $type, $no_cache='', $cHash='', $jumpurl='',$MP='',$RDCT='')
47 * 401: function connectToMySQL()
48 * 411: function connectToDB()
49 * 456: function sendRedirect()
50 *
51 * SECTION: Initializing, resolving page id
52 * 494: function initFEuser()
53 * 544: function initUserGroups()
54 * 591: function checkAlternativeIdMethods()
55 * 643: function clear_preview()
56 * 656: function determineId()
57 * 773: function fetch_the_id()
58 * 868: function getPageAndRootline()
59 * 934: function getPageShortcut($SC,$mode,$thisUid,$itera=20,$pageLog=array())
60 * 984: function checkRootlineForIncludeSection()
61 * 1017: function checkEnableFields($row)
62 * 1035: function checkPageGroupAccess($row, $groupList=NULL)
63 * 1054: function checkPagerecordForIncludeSection($row)
64 * 1063: function checkIfLoginAllowedInBranch()
65 * 1091: function setIDfromArgV()
66 * 1107: function getPageAndRootlineWithDomain($domainStartPage)
67 * 1134: function setSysPageWhereClause()
68 * 1144: function getPagesGroupClause()
69 * 1155: function findDomainRecord($recursive=0)
70 * 1174: function pageNotFoundAndExit($reason='')
71 * 1188: function pageNotFoundHandler($code, $header='', $reason='')
72 * 1226: function checkAndSetAlias()
73 * 1241: function idPartsAnalyze($str)
74 * 1266: function mergingWithGetVars($GET_VARS)
75 *
76 * SECTION: Template and caching related functions.
77 * 1314: function makeCacheHash()
78 * 1337: function cHashParams($addQueryParams)
79 * 1346: function initTemplate()
80 * 1358: function getFromCache()
81 * 1417: function headerNoCache()
82 * 1444: function getHash()
83 * 1464: function getConfigArray()
84 *
85 * SECTION: Further initialization and data processing
86 * 1586: function getCompressedTCarray()
87 * 1640: function includeTCA($TCAloaded=1)
88 * 1667: function settingLanguage()
89 * 1757: function settingLocale()
90 * 1782: function checkDataSubmission()
91 * 1807: function fe_tce()
92 * 1821: function locDataCheck($locationData)
93 * 1837: function sendFormmail()
94 * 1888: function extractRecipientCopy($bodytext)
95 * 1903: function checkJumpUrl()
96 * 1985: function jumpUrl()
97 * 2028: function setUrlIdToken()
98 *
99 * SECTION: Page generation; cache handling
100 * 2071: function isGeneratePage()
101 * 2081: function tempPageCacheContent()
102 * 2113: function realPageCacheContent()
103 * 2143: function setPageCacheContent($c,$d,$t)
104 * 2168: function clearPageCacheContent()
105 * 2178: function clearPageCacheContent_pidList($pidList)
106 * 2189: function setSysLastChanged()
107 *
108 * SECTION: Page generation; rendering and inclusion
109 * 2225: function generatePage_preProcessing()
110 * 2247: function generatePage_whichScript()
111 * 2259: function generatePage_postProcessing()
112 * 2351: function INTincScript()
113 * 2411: function INTincScript_loadJSCode()
114 * 2452: function isINTincScript()
115 * 2461: function doXHTML_cleaning()
116 * 2470: function doLocalAnchorFix()
117 *
118 * SECTION: Finished off; outputting, storing session data, statistics...
119 * 2501: function isOutputting()
120 * 2524: function processOutput()
121 * 2596: function sendCacheHeaders()
122 * 2663: function isStaticCacheble()
123 * 2678: function contentStrReplace()
124 * 2704: function isEXTincScript()
125 * 2713: function storeSessionData()
126 * 2723: function setParseTime()
127 * 2735: function statistics()
128 * 2843: function previewInfo()
129 * 2864: function hook_eofe()
130 * 2880: function beLoginLinkIPList()
131 *
132 * SECTION: Various internal API functions
133 * 2935: function makeSimulFileName($inTitle,$page,$type,$addParams='',$no_cache='')
134 * 2982: function simulateStaticDocuments_pEnc_onlyP_proc($linkVars)
135 * 3011: function getSimulFileName()
136 * 3025: function fileNameASCIIPrefix($inTitle,$titleChars,$mergeChar='.')
137 * 3043: function encryptEmail($string,$back=0)
138 * 3069: function codeString($string, $decode=FALSE)
139 * 3095: function roundTripCryptString($string)
140 * 3115: function checkFileInclude($incFile)
141 * 3130: function newCObj()
142 * 3143: function setAbsRefPrefix()
143 * 3157: function baseUrlWrap($url)
144 * 3176: function printError($label,$header='Error!')
145 * 3187: function updateMD5paramsRecord($hash)
146 * 3198: function tidyHTML($content)
147 * 3224: function prefixLocalAnchorsWithScript()
148 *
149 * SECTION: Various external API functions - for use in plugins etc.
150 * 3268: function getStorageSiterootPids()
151 * 3283: function getPagesTSconfig()
152 * 3316: function setJS($key,$content='')
153 * 3354: function setCSS($key,$content)
154 * 3369: function make_seed()
155 * 3382: function uniqueHash($str='')
156 * 3391: function set_no_cache()
157 * 3401: function set_cache_timeout_default($seconds)
158 * 3417: function plainMailEncoded($email,$subject,$message,$headers='')
159 *
160 * SECTION: Localization
161 * 3458: function sL($input)
162 * 3487: function readLLfile($fileRef)
163 * 3502: function getLLL($index,$LOCAL_LANG)
164 * 3516: function initLLvars()
165 * 3550: function csConv($str,$from='')
166 * 3568: function convOutputCharset($content,$label)
167 * 3581: function convPOSTCharset()
168 *
169 * TOTAL FUNCTIONS: 104
170 * (This index is automatically created/updated by the extension "extdeveval")
171 *
172 */
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194 /**
195 * Main frontend class, instantiated in the index_ts.php script as the global object TSFE
196 *
197 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
198 * @package TYPO3
199 * @subpackage tslib
200 */
201 class tslib_fe {
202
203 // CURRENT PAGE:
204 var $id=''; // The page id (int)
205 var $type=''; // RO The type (int)
206 var $idParts=array(); // Loaded with the id, exploded by ','
207 var $cHash=''; // The submitted cHash
208 var $no_cache=''; // Page will not be cached. Write only true. Never clear value (some other code might have reasons to set it true)
209 var $rootLine=''; // The rootLine (all the way to tree root, not only the current site!) (array)
210 var $page=''; // The pagerecord (array)
211 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.
212 var $sys_page=''; // The object with pagefunctions (object)
213 var $jumpurl='';
214 var $pageNotFound=0; // Is set to 1 if a pageNotFound handler could have been called.
215 var $domainStartPage=0; // Domain start page
216 var $MP='';
217 var $RDCT='';
218 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...
219 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.
220
221 // USER
222 var $fe_user=''; // The user (object)
223 var $loginUser=''; // Global falg 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.
224 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...
225 var $beUserLogin=''; // Flag that indicates if a Backend user is logged in!
226 var $loginAllowedInBranch = TRUE; // Shows whether logins are allowed in branch
227
228 // PREVIEW
229 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.
230 var $showHiddenPage=''; // Flag indicating that hidden pages should be shown, selected and so on. This goes for almost all selection of pages!
231 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.
232 var $simUserGroup='0'; // Value that contains the simulated usergroup if any
233 var $versionPreviewMap=array(); // Versioning Preview record map (temporary, for sys_page)
234
235 // CONFIGURATION
236 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.
237 var $config=''; // 'CONFIG' object from TypoScript. Array generated based on the TypoScript configuration of the current page. Saved with the cached pages.
238 var $TCAcachedExtras=array(); // Array of cached information from TCA. This is NOT TCA itself!
239
240 // TEMPLATE / CACHE
241 var $tmpl=''; // The TypoScript template object. Used to parse the TypoScript template
242 var $cacheTimeOutDefault=''; // Is set to the time-to-live time of cached pages. If false, default is 60*60*24, which is 24 hours.
243 var $cacheContentFlag=''; // Set internally if cached content is fetched from the database
244 var $cacheExpires=0; // Set to the expire time of cached content
245 var $isClientCachable=FALSE; // Set if cache headers allowing caching are sent.
246 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.
247 var $sPre=''; // toplevel - objArrayName, eg 'page'
248 var $pSetup=''; // TypoScript configuration of the page-object pointed to by sPre. $this->tmpl->setup[$this->sPre.'.']
249 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
250 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
251 var $noCacheBeforePageGen=''; // 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.
252 var $tempContent=''; // This flag indicates if temporary content went into the cache during page-generation.
253 var $forceTemplateParsing=''; // Boolean, passed to TypoScript template class and tells it to render the template forcibly
254 var $cHash_array=array(); // The array which cHash_calc is based on, see ->makeCacheHash().
255 var $hash_base=''; // Loaded with the serialized array that is used for generating a hashstring for the cache
256 var $pagesTSconfig=''; // May be set to the pagesTSconfig
257 // PAGE-GENERATION / cOBJ
258 /*
259 Eg. insert JS-functions in this array ($additionalHeaderData) to include them once. Use associative keys.
260 Keys in use:
261 JSFormValidate : <script type="text/javascript" src="'.$GLOBALS["TSFE"]->absRefPrefix.'t3lib/jsfunc.validateform.js"></script>
262 JSincludeFormupdate : <script type="text/javascript" src="t3lib/jsfunc.updateform.js"></script>
263 JSMenuCode, JSMenuCode_menu : JavaScript for the JavaScript menu
264 JSCode : reserved
265 JSImgCode : reserved
266 */
267 var $defaultBodyTag='<body bgcolor="#FFFFFF">'; // Default bodytag, if nothing else is set. This can be overridden by applications like TemplaVoila.
268 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[] = '...')
269 var $additionalJavaScript=array(); // used to accumulate additional JavaScript-code. Works like additionalHeaderData. Reserved keys at 'openPic' and 'mouseOver'
270 var $additionalCSS=array(); // used to accumulate additional Style code. Works like additionalHeaderData.
271 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
272 'onmousemove' => array(),
273 'onmouseup' => array(),
274 'onload' => array(),
275 );
276 var $JSCode=''; // Depreciated, use additionalJavaScript instead.
277 var $JSImgCode=''; // Used to accumulate JavaScript loaded images (by menus)
278 var $divSection=''; // Used to accumulate DHTML-layers.
279
280 // RENDERING configuration, settings from TypoScript is loaded into these vars. See pagegen.php
281 var $debug=''; // Debug flag, may output special debug html-code.
282 var $intTarget=''; // Default internal target
283 var $extTarget=''; // Default external target
284 var $MP_defaults=array(); // Keys are page ids and values are default &MP (mount point) values to set when using the linking features...)
285 var $spamProtectEmailAddresses=0; // If set, typolink() function encrypts email addresses. Is set in pagegen-class.
286 var $absRefPrefix=''; // Absolute Reference prefix
287 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 '/'
288 var $compensateFieldWidth=''; // Factor for form-field widths compensation
289 var $lockFilePath=''; // Lock file path
290 var $ATagParams=''; // <A>-tag parameters
291 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.
292 var $sWordList=''; // Is set to the incoming array sword_list in case of a page-view jumped to from a search-result.
293 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.
294 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.
295 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.
296 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.
297 var $sys_language_uid=0; // Site language, 0 (zero) is default, int+ is uid pointing to a sys_language record. Should reflect which language it DOES actually display!
298 var $sys_language_mode=''; // Site language mode
299 var $sys_language_content=0; // Site content selection uid
300 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...]
301 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")
302
303 // RENDERING data
304 var $applicationData=Array(); // 'Global' Storage for various applications. Keys should be 'tx_'.extKey for extensions.
305 var $register=Array();
306 var $registerStack=Array(); // Stack used for storing array and retrieving register arrays (see LOAD_REGISTER and CLEAR_REGISTER)
307 var $cObjectDepthCounter = 50; // Checking that the function is not called eternally. This is done by interrupting at a depth of 50
308 var $recordRegister = Array(); // used by cObj->RECORDS and cObj->CONTENT to ensure the a records is NOT rendered twice through it!
309 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
310 var $accessKey =array(); // Used by class tslib_menu to keep track of access-keys.
311 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.
312 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
313 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()
314 var $uniqueString='';
315 var $indexedDocTitle=''; // This value will be used as the title for the page in the indexer (if indexing happens)
316 var $altPageTitle=''; // Alternative page title (normally the title of the page record). Can be set from applications you make.
317 var $pEncAllowedParamNames=array(); // An array that holds parameter names (keys) of GET parameters which MAY be MD5/base64 encoded with simulate_static_documents method.
318 var $baseUrl=''; // The Base url set for the page header.
319 var $anchorPrefix=''; // The proper anchor prefix needed when using speaking urls. (only set if baseUrl is set)
320
321 // Page content render object
322 var $cObj =''; // is instantiated object of tslib_cObj
323
324 // CONTENT accumulation
325 var $content=''; // All page content is accumulated in this variable. See pagegen.php
326
327 // GENERAL
328 var $clientInfo=''; // Set to the browser: net / msie if 4+ browsers
329 var $scriptParseTime=0;
330 var $TCAloaded = 0; // Set ONLY if the full TCA is loaded
331
332 // Character set (charset) conversion object:
333 var $csConvObj; // An instance of the "t3lib_cs" class. May be used by any application.
334 var $defaultCharSet = 'iso-8859-1'; // The default charset used in the frontend if nothing else is set.
335 var $renderCharset=''; // Internal charset of the frontend during rendering: Defaults to "forceCharset" and if that is not set, to ->defaultCharSet
336 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.
337 var $localeCharset=''; // Assumed charset of locale strings.
338
339 // LANG:
340 var $lang=''; // Set to the system language key (used on the site)
341 var $langSplitIndex=0; // Set to the index number of the language key
342 var $labelsCharset=''; // Charset of the labels from locallang (based on $this->lang)
343 var $convCharsetToFrom=''; // Set to the charsets to convert from/to IF there are any difference. Otherwise this stays a string
344 var $LL_labels_cache=array();
345 var $LL_files_cache=array();
346
347
348
349
350
351 /**
352 * Class constructor
353 * Takes a number of GET/POST input variable as arguments and stores them internally.
354 * The processing of these variables goes on later in this class.
355 * Also sets internal clientInfo array (browser information) and a unique string (->uniqueString) for this script instance; A md5 hash of the microtime()
356 *
357 * @param array The global $TYPO3_CONF_VARS array. Will be set internally in ->TYPO3_CONF_VARS
358 * @param mixed The value of t3lib_div::_GP('id')
359 * @param integer The value of t3lib_div::_GP('type')
360 * @param boolean The value of t3lib_div::_GP('no_cache'), evaluated to 1/0
361 * @param string The value of t3lib_div::_GP('cHash')
362 * @param string The value of t3lib_div::_GP('jumpurl')
363 * @param string The value of t3lib_div::_GP('MP')
364 * @param string The value of t3lib_div::_GP('RDCT')
365 * @return void
366 * @see index_ts.php
367 */
368 function tslib_fe($TYPO3_CONF_VARS, $id, $type, $no_cache='', $cHash='', $jumpurl='',$MP='',$RDCT='') {
369
370 // Setting some variables:
371 $this->TYPO3_CONF_VARS = $TYPO3_CONF_VARS;
372 $this->id = $id;
373 $this->type = $type;
374 $this->no_cache = $no_cache ? 1 : 0;
375 $this->cHash = $cHash;
376 $this->jumpurl = $jumpurl;
377 $this->MP = $this->TYPO3_CONF_VARS['FE']['enable_mount_pids'] ? (string)$MP : '';
378 $this->RDCT = $RDCT;
379 $this->clientInfo = t3lib_div::clientInfo();
380 $this->uniqueString=md5(microtime());
381
382 $this->csConvObj = t3lib_div::makeInstance('t3lib_cs');
383
384 // Call post processing function for constructor:
385 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['tslib_fe-PostProc'])) {
386 $_params = array('pObj' => &$this);
387 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['tslib_fe-PostProc'] as $_funcRef) {
388 t3lib_div::callUserFunction($_funcRef,$_params,$this);
389 }
390 }
391 }
392
393 /**
394 * Connect to MySQL database
395 * May exit after outputting an error message or some JavaScript redirecting to the install tool.
396 * Use connectToDB() instead!
397 *
398 * @return void
399 * @deprecated
400 */
401 function connectToMySQL() {
402 $this->connectToDB();
403 }
404
405 /**
406 * Connect to SQL database
407 * May exit after outputting an error message or some JavaScript redirecting to the install tool.
408 *
409 * @return void
410 */
411 function connectToDB() {
412 if ($GLOBALS['TYPO3_DB']->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
413 if (!TYPO3_db) {
414 $this->printError('No database selected','Database Error');
415 // Redirects to the Install Tool:
416 echo '<script type="text/javascript">
417 /*<![CDATA[*/
418 document.location = "'.TYPO3_mainDir.'install/index.php?mode=123&step=1&password=joh316";
419 /*]]>*/
420 </script>';
421 exit;
422 } elseif (!$GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db)) {
423 $this->printError('Cannot connect to the current database, "'.TYPO3_db.'"','Database Error');
424 exit;
425 }
426 } else {
427 if (!TYPO3_db) {
428 // Redirects to the Install Tool:
429 echo '<script type="text/javascript">
430 /*<![CDATA[*/
431 document.location = "'.TYPO3_mainDir.'install/index.php?mode=123&step=1&password=joh316";
432 /*]]>*/
433 </script>';
434 exit;
435 }
436 $this->printError('The current username, password or host was not accepted when the connection to the database was attempted to be established!','Database Error');
437 exit;
438 }
439
440
441 // Call post processing function for DB connection:
442 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['connectToDB'])) {
443 $_params = array('pObj' => &$this);
444 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['connectToDB'] as $_funcRef) {
445 t3lib_div::callUserFunction($_funcRef,$_params,$this);
446 }
447 }
448 }
449
450 /**
451 * 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
452 * May exit after sending a location-header.
453 *
454 * @return void
455 */
456 function sendRedirect() {
457 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('params', 'cache_md5params', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->RDCT, 'cache_md5params'));
458 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
459 $this->updateMD5paramsRecord($this->RDCT);
460 header('Location: '.$row['params']);
461 exit;
462 }
463 }
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482 /********************************************
483 *
484 * Initializing, resolving page id
485 *
486 ********************************************/
487
488
489 /**
490 * Initializes the front-end login user.
491 *
492 * @return void
493 */
494 function initFEuser() {
495 $this->fe_user = t3lib_div::makeInstance('tslib_feUserAuth');
496
497 $this->fe_user->lockIP = $this->TYPO3_CONF_VARS['FE']['lockIP'];
498 $this->fe_user->lockHashKeyWords = $this->TYPO3_CONF_VARS['FE']['lockHashKeyWords'];
499 $this->fe_user->checkPid = $this->TYPO3_CONF_VARS['FE']['checkFeUserPid'];
500 $this->fe_user->lifetime = intval($this->TYPO3_CONF_VARS['FE']['lifetime']);
501 $this->fe_user->checkPid_value = $GLOBALS['TYPO3_DB']->cleanIntList(t3lib_div::_GP('pid')); // List of pid's acceptable
502
503 // Check if a session is transferred:
504 if (t3lib_div::_GP('FE_SESSION_KEY')) {
505 $fe_sParts = explode('-',t3lib_div::_GP('FE_SESSION_KEY'));
506 if (!strcmp(md5($fe_sParts[0].'/'.$this->TYPO3_CONF_VARS['SYS']['encryptionKey']), $fe_sParts[1])) { // If the session key hash check is OK:
507 $_COOKIE[$this->fe_user->name] = $fe_sParts[0];
508 $this->fe_user->forceSetCookie = 1;
509 }
510 }
511
512 if ($this->TYPO3_CONF_VARS['FE']['dontSetCookie']) {
513 $this->fe_user->dontSetCookie=1;
514 }
515
516 $this->fe_user->start();
517 $this->fe_user->unpack_uc('');
518 $this->fe_user->fetchSessionData(); // Gets session data
519 $recs = t3lib_div::_GP('recs');
520 if (is_array($recs)) { // If any record registration is submitted, register the record.
521 $this->fe_user->record_registration($recs);
522 }
523
524 // Call hook for possible manipulation of frontend user object
525 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['initFEuser'])) {
526 $_params = array('pObj' => &$this);
527 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['initFEuser'] as $_funcRef) {
528 t3lib_div::callUserFunction($_funcRef,$_params,$this);
529 }
530 }
531
532 // For every 60 seconds the is_online timestamp is updated.
533 if (is_array($this->fe_user->user) && $this->fe_user->user['uid'] && $this->fe_user->user['is_online']<($GLOBALS['EXEC_TIME']-60)) {
534 $GLOBALS['TYPO3_DB']->exec_UPDATEquery('fe_users', 'uid='.intval($this->fe_user->user['uid']), array('is_online' => $GLOBALS['EXEC_TIME']));
535 }
536 }
537
538 /**
539 * Initializes the front-end user groups.
540 * Sets ->loginUser and ->gr_list based on front-end user status.
541 *
542 * @return void
543 */
544 function initUserGroups() {
545
546 $this->fe_user->showHiddenRecords = $this->showHiddenRecords; // This affects the hidden-flag selecting the fe_groups for the user!
547 $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!)
548
549 if (is_array($this->fe_user->user) && count($this->fe_user->groupData['uid'])) {
550 $this->loginUser=1; // global flag!
551 $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!
552 $gr_array = $this->fe_user->groupData['uid'];
553 } else {
554 $this->loginUser=0;
555 $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!
556 $gr_array = $this->fe_user->groupData['uid'];
557 }
558 // TYPO3_CONF_VARS']['FE']['IPmaskMountGroups'] moved to sysext/sv/class.tx_sv_auth.php service
559
560 // Clean up.
561 $gr_array = array_unique($gr_array); // Make unique...
562 sort($gr_array); // sort
563 if (count($gr_array)) {
564 $this->gr_list.=','.implode(',',$gr_array);
565 }
566
567 if ($this->fe_user->writeDevLog) t3lib_div::devLog('Valid usergroups for TSFE: '.$this->gr_list, 'tslib_fe');
568 }
569
570 /**
571 * Provides ways to bypass the '?id=[xxx]&type=[xx]' format, using either PATH_INFO or virtual HTML-documents (using Apache mod_rewrite)
572 *
573 * Three options:
574 * 1) Apache mod_rewrite: Here a .htaccess file maps all .html-files to index.php and then we extract the id and type from the name of that HTML-file. (AKA "simulateStaticDocuments")
575 * 2) Use PATH_INFO (also Apache) to extract id and type from that var. Does not require any special modules compiled with apache. (less typical)
576 * 3) Using hook which enables features like those provided from "realurl" extension (AKA "Speaking URLs")
577 *
578 * Support for RewriteRule to generate (simulateStaticDocuments)
579 * With the mod_rewrite compiled into apache, put these lines into a .htaccess in this directory:
580 * RewriteEngine On
581 * RewriteRule ^[^/]*\.html$ index.php
582 * The url must end with '.html' and the format must comply with either of these:
583 * 1: '[title].[id].[type].html' - title is just for easy recognition in the logfile!; no practical use of the title for TYPO3.
584 * 2: '[id].[type].html' - above, but title is omitted; no practical use of the title for TYPO3.
585 * 3: '[id].html' - only id, type is set to the default, zero!
586 * NOTE: In all case 'id' may be the uid-number OR the page alias (if any)
587 *
588 * @return void
589 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&cHash=4ad9d7acb4
590 */
591 function checkAlternativeIdMethods() {
592
593 $this->siteScript = t3lib_div::getIndpEnv('TYPO3_SITE_SCRIPT');
594
595 // Resolving of "simulateStaticDocuments" URLs:
596 if ($this->siteScript && substr($this->siteScript,0,9)!='index.php') { // If there has been a redirect (basically; we arrived here otherwise than via "index.php" in the URL) this can happend either due to a CGI-script or because of reWrite rule. Earlier we used $_SERVER['REDIRECT_URL'] to check but
597 $uParts = parse_url($this->siteScript); // Parse the path:
598 $fI = t3lib_div::split_fileref($uParts['path']);
599
600 if (!$fI['path'] && $fI['file'] && substr($fI['file'],-5)=='.html') {
601 $parts = explode('.',$fI['file']);
602 $pCount = count($parts);
603 if ($pCount>2) {
604 $this->type = intval($parts[$pCount-2]);
605 $this->id = $parts[$pCount-3];
606 } else {
607 $this->type = 0;
608 $this->id = $parts[0];
609 }
610 }
611 }
612
613 // If PATH_INFO
614 if (t3lib_div::getIndpEnv('PATH_INFO')) { // If pathinfo contains stuff...
615 $parts=t3lib_div::trimExplode('/',t3lib_div::getIndpEnv('PATH_INFO'),1);
616 $parts[]='html';
617 $pCount = count($parts);
618 if ($pCount>2) {
619 $this->type = intval($parts[$pCount-2]);
620 $this->id = $parts[$pCount-3];
621 } else {
622 $this->type = 0;
623 $this->id = $parts[0];
624 }
625 $this->absRefPrefix_force=1;
626 }
627
628 // Call post processing function for custom URL methods.
629 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['checkAlternativeIdMethods-PostProc'])) {
630 $_params = array('pObj' => &$this);
631 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['checkAlternativeIdMethods-PostProc'] as $_funcRef) {
632 t3lib_div::callUserFunction($_funcRef,$_params,$this);
633 }
634 }
635 }
636
637 /**
638 * Clears the preview-flags, sets sim_exec_time to current time.
639 * 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.
640 *
641 * @return void
642 */
643 function clear_preview() {
644 $this->showHiddenPage = 0;
645 $this->showHiddenRecords = 0;
646 $GLOBALS['SIM_EXEC_TIME'] = $GLOBALS['EXEC_TIME'];
647 $this->fePreview = 0;
648 }
649
650 /**
651 * Determines the id and evaluates any preview settings
652 * 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.
653 *
654 * @return void
655 */
656 function determineId() {
657
658 // Getting ARG-v values if some
659 $this->setIDfromArgV();
660
661 // If there is a Backend login we are going to check for any preview settings:
662 $GLOBALS['TT']->push('beUserLogin','');
663 if ($this->beUserLogin) {
664 $this->fePreview = $GLOBALS['BE_USER']->extGetFeAdminValue('preview');
665
666 // If admin panel preview is enabled...
667 if ($this->fePreview) {
668 $fe_user_OLD_USERGROUP = $this->fe_user->user['usergroup'];
669
670 $this->showHiddenPage = $GLOBALS['BE_USER']->extGetFeAdminValue('preview','showHiddenPages');
671 $this->showHiddenRecords = $GLOBALS['BE_USER']->extGetFeAdminValue('preview','showHiddenRecords');
672 // simulate date
673 $simTime = $GLOBALS['BE_USER']->extGetFeAdminValue('preview','simulateDate');
674 if ($simTime) $GLOBALS['SIM_EXEC_TIME']=$simTime;
675 // simulate user
676 $simUserGroup = $GLOBALS['BE_USER']->extGetFeAdminValue('preview','simulateUserGroup');
677 $this->simUserGroup = $simUserGroup;
678 if ($simUserGroup) $this->fe_user->user['usergroup']=$simUserGroup;
679 if (!$simUserGroup && !$simTime && !$this->showHiddenPage && !$this->showHiddenRecords) {
680 $this->fePreview=0;
681 }
682 }
683
684 // Now it's investigated if the raw page-id points to a hidden page and if so, the flag is set.
685 // This does not require the preview flag to be set in the admin panel
686 if ($this->id) {
687 $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...
688 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('hidden', 'pages', $idQ.' AND hidden!=0 AND deleted=0');
689 if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
690 $this->fePreview = 1; // The preview flag is set only if the current page turns out to actually be hidden!
691 $this->showHiddenPage = 1;
692 }
693
694 // Check root line for proper connection to tree root (done because of possible preview of page / branch versions)
695 if (!$this->fePreview) {
696
697 // Initialize the page-select functions to check rootline:
698 $temp_sys_page = t3lib_div::makeInstance('t3lib_pageSelect');
699 $temp_sys_page->init($this->showHiddenPage);
700
701 // If root line contained NO records and ->error_getRootLine_failPid tells us that it was because of a pid=-1 (indicating a "version" record)...:
702 if (!count($temp_sys_page->getRootLine($this->id,$this->MP)) && $temp_sys_page->error_getRootLine_failPid==-1) {
703
704 // Setting versioningPreview flag and try again:
705 $temp_sys_page->versioningPreview = TRUE;
706 if (count($temp_sys_page->getRootLine($this->id,$this->MP))) {
707 // 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.
708 $this->fePreview = 1;
709 #debug('version in rootline...');
710 }
711 }
712 }
713 }
714
715 // Checking for specific version preview of records:
716 if (is_array(t3lib_div::_GP('ADMCMD_vPrev'))) {
717 $this->fePreview = 1;
718 $this->versionPreviewMap = t3lib_div::_GP('ADMCMD_vPrev');
719 }
720
721 if ($this->fePreview) { // If the front-end is showing a preview, caching MUST be disabled.
722 $this->set_no_cache();
723 }
724 }
725 $GLOBALS['TT']->pull();
726
727 // Now, get the id, validate access etc:
728 $this->fetch_the_id();
729
730 // Check if backend user has read access to this page. If not, recalculate the id.
731 if ($this->beUserLogin && $this->fePreview) {
732 if (!$GLOBALS['BE_USER']->doesUserHaveAccess($this->page,1)) {
733 // Resetting
734 $this->clear_preview();
735 $this->fe_user->user['usergroup'] = $fe_user_OLD_USERGROUP;
736
737 // Fetching the id again, now with the preview settings reset.
738 $this->fetch_the_id();
739 }
740 }
741
742 // Checks if user logins are blocked for a certain branch and if so, will unset user login and re-fetch ID.
743 $this->loginAllowedInBranch = $this->checkIfLoginAllowedInBranch();
744 if (!$this->loginAllowedInBranch) { // Logins are not allowed:
745 if (is_array($this->fe_user->user)) { // Only if there is a login will we run this...
746 unset($this->fe_user->user);
747 // Fetching the id again, now with the preview settings reset.
748 $this->fetch_the_id();
749 }
750 }
751
752 // Final cleaning.
753 $this->id = $this->contentPid = intval($this->id); // Make sure it's an integer
754 $this->type = intval($this->type); // Make sure it's an integer
755
756 // Call post processing function for id determination:
757 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['determineId-PostProc'])) {
758 $_params = array('pObj' => &$this);
759 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['determineId-PostProc'] as $_funcRef) {
760 t3lib_div::callUserFunction($_funcRef,$_params,$this);
761 }
762 }
763 }
764
765 /**
766 * Get The Page ID
767 * This gets the id of the page, checks if the page is in the domain and if the page is accessible
768 * Sets variables such as $this->sys_page, $this->loginUser, $this->gr_list, $this->id, $this->type, $this->domainStartPage, $this->idParts
769 *
770 * @return void
771 * @access private
772 */
773 function fetch_the_id() {
774 $GLOBALS['TT']->push('fetch_the_id initialize/','');
775
776 // Initialize the page-select functions.
777 $this->sys_page = t3lib_div::makeInstance('t3lib_pageSelect');
778 $this->sys_page->init($this->showHiddenPage);
779 $this->sys_page->versioningPreview = $this->fePreview ? TRUE : FALSE;
780 if ($this->sys_page->versioningPreview) {
781 $this->sys_page->versionPreviewMap = $this->versionPreviewMap;
782 }
783
784 // Set the valid usergroups for FE
785 $this->initUserGroups();
786
787 // Sets sys_page where-clause
788 $this->setSysPageWhereClause();
789
790 // Splitting $this->id by a period (.). First part is 'id' and second part - if exists - will overrule the &type param if given
791 $pParts = explode('.',$this->id);
792 $this->id = $pParts[0]; // Set it.
793 if (isset($pParts[1])) {$this->type=$pParts[1];}
794
795 // Splitting $this->id by a comma (,). First part is 'id' and other parts are just stored for use in scripts.
796 $this->idParts = explode(',',$this->id);
797
798 // Splitting by a '+' sign - used for base64/md5 methods of parameter encryption for simulate static documents.
799 list($pgID,$SSD_p)=explode('+',$this->idParts[0],2);
800 if ($SSD_p) { $this->idPartsAnalyze($SSD_p); }
801 $this->id = $pgID; // Set id
802
803 // If $this->id is a string, it's an alias
804 $this->checkAndSetAlias();
805
806 // The id and type is set to the integer-value - just to be sure...
807 $this->id = intval($this->id);
808 $this->type = intval($this->type);
809 $GLOBALS['TT']->pull();
810
811 // We find the first page belonging to the current domain
812 $GLOBALS['TT']->push('fetch_the_id domain/','');
813 $this->domainStartPage = $this->findDomainRecord($this->TYPO3_CONF_VARS['SYS']['recursiveDomainSearch']); // the page_id of the current domain
814 if (!$this->id) {
815 if ($this->domainStartPage) {
816 $this->id = $this->domainStartPage; // If the id was not previously set, set it to the id of the domain.
817 } else {
818 $theFirstPage = $this->sys_page->getFirstWebPage($this->id); // Find the first 'visible' page in that domain
819 if ($theFirstPage) {
820 $this->id = $theFirstPage['uid'];
821 } else {
822 $this->printError('No pages are found on the rootlevel!');
823 exit;
824 }
825 }
826 }
827 $GLOBALS['TT']->pull();
828
829 $GLOBALS['TT']->push('fetch_the_id rootLine/','');
830 $requestedId = $this->id; // We store the originally requested id
831 $this->getPageAndRootlineWithDomain($this->domainStartPage);
832 $GLOBALS['TT']->pull();
833
834 if ($this->pageNotFound && $this->TYPO3_CONF_VARS['FE']['pageNotFound_handling']) {
835 $pNotFoundMsg = array(
836 1 => 'ID was not an accessible page',
837 2 => 'Subsection was found and not accessible',
838 3 => 'ID was outside the domain',
839 );
840 $this->pageNotFoundAndExit($pNotFoundMsg[$this->pageNotFound]);
841 }
842
843 // set no_cache if set
844 if ($this->page['no_cache']) {
845 $this->set_no_cache();
846 }
847
848 // Init SYS_LASTCHANGED
849 $this->register['SYS_LASTCHANGED'] = intval($this->page['tstamp']);
850 if ($this->register['SYS_LASTCHANGED'] < intval($this->page['SYS_LASTCHANGED'])) {
851 $this->register['SYS_LASTCHANGED'] = intval($this->page['SYS_LASTCHANGED']);
852 }
853 }
854
855 /**
856 * Gets the page and rootline arrays based on the id, $this->id
857 *
858 * If the id does not correspond to a proper page, the 'previous' valid page in the rootline is found
859 * If the page is a shortcut (doktype=4), the ->id is loaded with that id
860 *
861 * 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.
862 *
863 * Sets or manipulates internal variables such as: $this->id, $this->page, $this->rootLine, $this->MP, $this->pageNotFound
864 *
865 * @return void
866 * @access private
867 */
868 function getPageAndRootline() {
869 $this->page = $this->sys_page->getPage($this->id);
870 if (!count($this->page)) {
871 // If no page, we try to find the page before in the rootLine.
872 $this->pageNotFound=1; // Page is 'not found' in case the id itself was not an accessible page. code 1
873 $this->rootLine = $this->sys_page->getRootLine($this->id,$this->MP);
874 if (count($this->rootLine)) {
875 $c=count($this->rootLine)-1;
876 while($c>0) {
877 $c--;
878 $this->id=$this->rootLine[$c]['uid'];
879 $this->page = $this->sys_page->getPage($this->id);
880 if (count($this->page)){break;}
881 }
882 }
883 // If still no page...
884 if (!count($this->page)) {
885 if ($this->TYPO3_CONF_VARS['FE']['pageNotFound_handling']) {
886 $this->pageNotFoundAndExit('The requested page does not exist!');
887 } else {
888 $this->printError('The requested page does not exist!');
889 exit;
890 }
891 }
892 }
893 // Is the ID a link to another page??
894 if ($this->page['doktype']==4) {
895 $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.
896 $this->page = $this->getPageShortcut($this->page['shortcut'],$this->page['shortcut_mode'],$this->page['uid']);
897 $this->id = $this->page['uid'];
898 }
899 // Gets the rootLine
900 $this->rootLine = $this->sys_page->getRootLine($this->id,$this->MP);
901
902 // If not rootline we're off...
903 if (!count($this->rootLine)) {
904 $this->printError('The requested page didn\'t have a proper connection to the tree-root! <br /><br />('.$this->sys_page->error_getRootLine.')');
905 exit;
906 }
907
908 // Checking for include section regarding the hidden/starttime/endtime/fe_user (that is access control of a whole subbranch!)
909 if ($this->checkRootlineForIncludeSection()) {
910 if (!count($this->rootLine)) {
911 $this->printError('The requested page was not accessible!');
912 exit;
913 } else {
914 $el = reset($this->rootLine);
915 $this->id = $el['uid'];
916 $this->page = $this->sys_page->getPage($this->id);
917 $this->rootLine = $this->sys_page->getRootLine($this->id,$this->MP);
918 }
919 }
920 }
921
922 /**
923 * Get page shortcut; Finds the records pointed to by input value $SC (the shortcut value)
924 *
925 * @param integer The value of the "shortcut" field from the pages record
926 * @param integer The shortcut mode: 1 and 2 will select either first subpage or random subpage; the default is the page pointed to by $SC
927 * @param integer The current page UID of the page which is a shortcut
928 * @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...)
929 * @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.
930 * @return mixed Returns the page record of the page that the shortcut pointed to.
931 * @access private
932 * @see getPageAndRootline()
933 */
934 function getPageShortcut($SC,$mode,$thisUid,$itera=20,$pageLog=array()) {
935 $idArray = t3lib_div::intExplode(',',$SC);
936
937 // Find $page record depending on shortcut mode:
938 switch($mode) {
939 case 1:
940 case 2:
941 $pageArray = $this->sys_page->getMenu($idArray[0]?$idArray[0]:$thisUid,'*','sorting','AND pages.doktype<199 AND pages.doktype!=6');
942 $pO = 0;
943 if ($mode==2 && count($pageArray)) { // random
944 $this->make_seed();
945 $randval = intval(rand(0,count($pageArray)-1));
946 $pO = $randval;
947 }
948 $c = 0;
949 reset($pageArray);
950 while(list(,$pV)=each($pageArray)) {
951 if ($c==$pO) {
952 $page = $pV;
953 break;
954 }
955 $c++;
956 }
957 break;
958 default:
959 $page = $this->sys_page->getPage($idArray[0]);
960 break;
961 }
962
963 // Check if short cut page was a shortcut itself, if so look up recursively:
964 if ($page['doktype']==4) {
965 if (!in_array($page['uid'],$pageLog) && $itera>0) {
966 $pageLog[] = $page['uid'];
967 $page = $this->getPageShortcut($page['shortcut'],$page['shortcut_mode'],$page['uid'],$itera-1,$pageLog);
968 } else {
969 $pageLog[] = $page['uid'];
970 $this->printError('Page shortcuts were looping in uids '.implode(',',$pageLog).'...!');
971 exit;
972 }
973 }
974 // Return resulting page:
975 return $page;
976 }
977
978 /**
979 * Checks the current rootline for defined sections.
980 *
981 * @return boolean
982 * @access private
983 */
984 function checkRootlineForIncludeSection() {
985 $c=count($this->rootLine);
986 $removeTheRestFlag=0;
987 for ($a=0;$a<$c;$a++) {
988 if (!$this->checkPagerecordForIncludeSection($this->rootLine[$a])) {
989 $removeTheRestFlag=1;
990 }
991 if ($this->rootLine[$a]['doktype']==6) {
992 if ($this->beUserLogin) { // If there is a backend user logged in, check if he has read access to the page:
993 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'uid='.intval($this->id).' AND '.$GLOBALS['BE_USER']->getPagePermsClause(1));
994 list($isPage) = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
995 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...
996 } else { // Dont go here, if there is no backend user logged in.
997 $removeTheRestFlag=1;
998 }
999 }
1000 if ($removeTheRestFlag) {
1001 $this->pageNotFound=2; // Page is 'not found' in case a subsection was found and not accessible, code 2
1002 unset($this->rootLine[$a]);
1003 }
1004 }
1005 return $removeTheRestFlag;
1006 }
1007
1008 /**
1009 * Checks page record for enableFields
1010 * Returns true if enableFields does not disable the page record.
1011 * Takes notice of the ->showHiddenPage flag and uses SIM_EXEC_TIME for start/endtime evaluation
1012 *
1013 * @param array The page record to evaluate (needs fields: hidden, starttime, endtime, fe_group)
1014 * @return boolean True, if record is viewable.
1015 * @see tslib_cObj::getTreeList(), checkPagerecordForIncludeSection()
1016 */
1017 function checkEnableFields($row) {
1018 if ((!$row['hidden'] || $this->showHiddenPage)
1019 && $row['starttime']<=$GLOBALS['SIM_EXEC_TIME']
1020 && ($row['endtime']==0 || $row['endtime']>$GLOBALS['SIM_EXEC_TIME'])
1021 && $this->checkPageGroupAccess($row)
1022 ) {
1023 return 1;
1024 }
1025 }
1026
1027 /**
1028 * Check group access against a page record
1029 *
1030 * @param array The page record to evaluate (needs field: fe_group)
1031 * @param mixed List of group id's (comma list or array). Default is $this->gr_list
1032 * @return boolean True, if group access is granted.
1033 * @access private
1034 */
1035 function checkPageGroupAccess($row, $groupList=NULL) {
1036 if(is_null($groupList)) {
1037 $groupList = $this->gr_list;
1038 }
1039 if(!is_array($groupList)) {
1040 $groupList = explode(',', $groupList);
1041 }
1042 $pageGroupList = explode(',', $row['fe_group']);
1043 return count(array_intersect($groupList, $pageGroupList)) > 0;
1044 }
1045
1046 /**
1047 * Checks page record for include section
1048 *
1049 * @param array The page record to evaluate (needs fields: extendToSubpages + hidden, starttime, endtime, fe_group)
1050 * @return boolean Returns true if either extendToSubpages is not checked or if the enableFields does not disable the page record.
1051 * @access private
1052 * @see checkEnableFields(), tslib_cObj::getTreeList(), checkRootlineForIncludeSection()
1053 */
1054 function checkPagerecordForIncludeSection($row) {
1055 return (!$row['extendToSubpages'] || $this->checkEnableFields($row)) ? 1 : 0;
1056 }
1057
1058 /**
1059 * 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!)
1060 *
1061 * @return boolean returns TRUE if logins are OK, otherwise false (and then the login user must be unset!)
1062 */
1063 function checkIfLoginAllowedInBranch() {
1064
1065 // Initialize:
1066 $c = count($this->rootLine);
1067 $disable = FALSE;
1068
1069 // Traverse root line from root and outwards:
1070 for ($a=0; $a<$c; $a++) {
1071
1072 // If a value is set for login state:
1073 if ($this->rootLine[$a]['fe_login_mode'] > 0) {
1074
1075 // Determine state from value:
1076 $disable = (int)$this->rootLine[$a]['fe_login_mode'] === 1 ? TRUE : FALSE;
1077 }
1078 }
1079
1080 return !$disable;
1081 }
1082
1083 /**
1084 * This checks if there are ARGV-parameters in the QUERY_STRING and if so, those are used for the id
1085 * $this->id must be 'false' in order for any processing to happen in here
1086 * If an id/alias value is extracted from the QUERY_STRING it is set in $this->id
1087 *
1088 * @return void
1089 * @access private
1090 */
1091 function setIDfromArgV() {
1092 if (!$this->id) {
1093 list($theAlias) = explode('&',t3lib_div::getIndpEnv('QUERY_STRING'));
1094 $theAlias = trim($theAlias);
1095 $this->id = $theAlias ? $theAlias : 0;
1096 }
1097 }
1098
1099 /**
1100 * Gets ->page and ->rootline information based on ->id. ->id may change during this operation.
1101 * If not inside domain, then default to first page in domain.
1102 *
1103 * @param integer Page uid of the page where the found domain record is (pid of the domain record)
1104 * @return void
1105 * @access private
1106 */
1107 function getPageAndRootlineWithDomain($domainStartPage) {
1108 $this->getPageAndRootline();
1109
1110 // 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.
1111 if ($domainStartPage && is_array($this->rootLine)) {
1112 reset ($this->rootLine);
1113 $idFound = 0;
1114 while(list($key,$val)=each($this->rootLine)) {
1115 if ($val['uid']==$domainStartPage) {
1116 $idFound=1;
1117 break;
1118 }
1119 }
1120 if (!$idFound) {
1121 $this->pageNotFound=3; // Page is 'not found' in case the id was outside the domain, code 3
1122 $this->id = $domainStartPage;
1123 $this->getPageAndRootline(); //re-get the page and rootline if the id was not found.
1124 }
1125 }
1126 }
1127
1128 /**
1129 * Sets sys_page where-clause
1130 *
1131 * @return void
1132 * @access private
1133 */
1134 function setSysPageWhereClause() {
1135 $this->sys_page->where_hid_del.=' AND doktype<200'.$this->getPagesGroupClause();
1136 }
1137
1138 /**
1139 * Return where-clause for group access
1140 *
1141 * @return string Group where clause part
1142 * @access private
1143 */
1144 function getPagesGroupClause() {
1145 return ' AND fe_group IN ('.$this->gr_list.')';
1146 }
1147
1148 /**
1149 * Looking up a domain record based on HTTP_HOST
1150 *
1151 * @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.
1152 * @return integer Returns the page id of the page where the domain record was found.
1153 * @access private
1154 */
1155 function findDomainRecord($recursive=0) {
1156 if ($recursive) {
1157 $host = explode('.',t3lib_div::getIndpEnv('HTTP_HOST'));
1158 while(count($host)) {
1159 $pageUid = $this->sys_page->getDomainStartPage(implode('.',$host),t3lib_div::getIndpEnv('SCRIPT_NAME'),t3lib_div::getIndpEnv('REQUEST_URI'));
1160 if ($pageUid) return $pageUid; else array_shift($host);
1161 }
1162 return $pageUid;
1163 } else {
1164 return $this->sys_page->getDomainStartPage(t3lib_div::getIndpEnv('HTTP_HOST'),t3lib_div::getIndpEnv('SCRIPT_NAME'),t3lib_div::getIndpEnv('REQUEST_URI'));
1165 }
1166 }
1167
1168 /**
1169 * Page-not-found handler for use in frontend plugins from extensions.
1170 *
1171 * @param string Reason text
1172 * @return void Function exits.
1173 */
1174 function pageNotFoundAndExit($reason='') {
1175 $this->pageNotFoundHandler($this->TYPO3_CONF_VARS['FE']['pageNotFound_handling'], $this->TYPO3_CONF_VARS['FE']['pageNotFound_handling_statheader'], $reason);
1176 exit;
1177 }
1178
1179 /**
1180 * Page not found handler.
1181 * Exits.
1182 *
1183 * @param mixed Which type of handling; If a true PHP-boolean and TRUE then a ->printError message is outputted. If integer an error message with that number is shown. Otherwise the $code value is expected to be a "Location:" header value.
1184 * @param string If set, this is passed directly to the PHP function, header()
1185 * @param string If set, error messages will also mention this as the reason for the page-not-found.
1186 * @return void (The function exists!)
1187 */
1188 function pageNotFoundHandler($code, $header='', $reason='') {
1189 // Issue header in any case:
1190 if ($header) {header($header);}
1191
1192 // Create response:
1193 if (gettype($code)=='boolean' || !strcmp($code,1)) {
1194 $this->printError('The page did not exist or was inaccessible.'.($reason ? ' Reason: '.htmlspecialchars($reason) : ''));
1195 exit;
1196 } elseif (t3lib_div::testInt($code)) {
1197 $this->printError('Error '.$code.($reason ? ' Reason: '.htmlspecialchars($reason) : ''));
1198 exit;
1199 } elseif (t3lib_div::isFirstPartOfStr($code,'READFILE:')) {
1200 $readFile = t3lib_div::getFileAbsFileName(trim(substr($code,9)));
1201 if (@is_file($readFile)) {
1202 $fileContent = t3lib_div::getUrl($readFile);
1203 $fileContent = str_replace('###CURRENT_URL###', t3lib_div::getIndpEnv('REQUEST_URI'), $fileContent);
1204 $fileContent = str_replace('###REASON###', htmlspecialchars($reason), $fileContent);
1205 echo $fileContent;
1206 } else {
1207 $this->printError('Configuration Error: 404 page "'.$readFile.'" could not be found.');
1208 }
1209 exit;
1210 } elseif (strlen($code)) {
1211 header('Location: '.t3lib_div::locationHeaderUrl($code));
1212 exit;
1213 } else {
1214 $this->printError('Error.'.($reason ? ' Reason: '.htmlspecialchars($reason) : ''));
1215 exit;
1216 }
1217 }
1218
1219 /**
1220 * Fetches the integer page id for a page alias.
1221 * 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
1222 *
1223 * @return void
1224 * @access private
1225 */
1226 function checkAndSetAlias() {
1227 if ($this->id && !t3lib_div::testInt($this->id)) {
1228 $aid = $this->sys_page->getPageIdFromAlias($this->id);
1229 if ($aid) {$this->id=$aid;}
1230 }
1231 }
1232
1233 /**
1234 * 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 (but NOT $_GET - yet)
1235 * If values for ->cHash, ->no_cache, ->jumpurl and ->MP is found, they are also loaded into the internal vars of this class.
1236 *
1237 * @param string String to analyze
1238 * @return void
1239 * @access private
1240 */
1241 function idPartsAnalyze($str) {
1242 $GET_VARS = '';
1243 switch(substr($str,0,2)) {
1244 case 'B6':
1245 $addParams = base64_decode(str_replace('_','=',str_replace('-','/',substr($str,2))));
1246 parse_str($addParams,$GET_VARS);
1247 break;
1248 case 'M5':
1249 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('params', 'cache_md5params', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr(substr($str,2), 'cache_md5params'));
1250 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
1251
1252 $this->updateMD5paramsRecord(substr($str,2));
1253 parse_str($row['params'],$GET_VARS);
1254 break;
1255 }
1256
1257 $this->mergingWithGetVars($GET_VARS);
1258 }
1259
1260 /**
1261 * Merging values into the global $_GET
1262 *
1263 * @param array Array of key/value pairs that will be merged into the current GET-vars. (Non-escaped values)
1264 * @return void
1265 */
1266 function mergingWithGetVars($GET_VARS) {
1267 if (is_array($GET_VARS)) {
1268 $realGet = t3lib_div::_GET(); // Getting $_GET var, unescaped.
1269 if (!is_array($realGet)) $realGet = array();
1270
1271 // Merge new values on top:
1272 $realGet = t3lib_div::array_merge_recursive_overrule($realGet,$GET_VARS);
1273
1274 // Write values back to $_GET:
1275 t3lib_div::_GETset($realGet);
1276
1277 // Setting these specifically (like in the init-function):
1278 if (isset($GET_VARS['type'])) $this->type = intval($GET_VARS['type']);
1279 if (isset($GET_VARS['cHash'])) $this->cHash = $GET_VARS['cHash'];
1280 if (isset($GET_VARS['jumpurl'])) $this->jumpurl = $GET_VARS['jumpurl'];
1281 if (isset($GET_VARS['MP'])) $this->MP = $this->TYPO3_CONF_VARS['FE']['enable_mount_pids'] ? $GET_VARS['MP'] : '';
1282
1283 if (isset($GET_VARS['no_cache']) && $GET_VARS['no_cache']) $this->set_no_cache();
1284 }
1285 }
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303 /********************************************
1304 *
1305 * Template and caching related functions.
1306 *
1307 *******************************************/
1308
1309 /**
1310 * 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
1311 *
1312 * @return void
1313 */
1314 function makeCacheHash() {
1315 $GET = t3lib_div::_GET();
1316 if ($this->cHash && is_array($GET)) {
1317 $this->cHash_array = t3lib_div::cHashParams(t3lib_div::implodeArrayForUrl('',$GET));
1318 $cHash_calc = t3lib_div::shortMD5(serialize($this->cHash_array));
1319
1320 if ($cHash_calc!=$this->cHash) {
1321 $this->set_no_cache();
1322 $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);
1323 }
1324 }
1325 }
1326
1327 /**
1328 * Splits the input query-parameters into an array with certain parameters filtered out.
1329 * Used to create the cHash value
1330 *
1331 * @param string Query-parameters: "&xxx=yyy&zzz=uuu"
1332 * @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
1333 * @access private
1334 * @see makeCacheHash(), tslib_cObj::typoLink()
1335 * @obsolete
1336 */
1337 function cHashParams($addQueryParams) {
1338 return t3lib_div::cHashParams($addQueryParams);
1339 }
1340
1341 /**
1342 * Initialize the TypoScript template parser
1343 *
1344 * @return void
1345 */
1346 function initTemplate() {
1347 $this->tmpl = t3lib_div::makeInstance('t3lib_TStemplate');
1348 $this->tmpl->init();
1349 $this->tmpl->tt_track= $this->beUserLogin ? 1 : 0;
1350 }
1351
1352 /**
1353 * See if page is in cache and get it if so
1354 * Stores the page content in $this->content if something is found.
1355 *
1356 * @return void
1357 */
1358 function getFromCache() {
1359 $this->tmpl->getCurrentPageData();
1360 $cc = Array();
1361 if (is_array($this->tmpl->currentPageData)) {
1362 // BE CAREFULL 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.
1363 // If this hash is not the same in here in this section and after page-generation the page will not be properly cached!
1364
1365 $cc['all'] = $this->tmpl->currentPageData['all'];
1366 $cc['rowSum'] = $this->tmpl->currentPageData['rowSum'];
1367 $cc['rootLine'] = $this->tmpl->currentPageData['rootLine']; // This rootline is used with templates only (matching()-function)
1368 $this->all = $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.
1369 ksort($this->all);
1370 }
1371
1372 $this->content=''; // clearing the content-variable, which will hold the pagecontent
1373 unset($this->config); // Unsetting the lowlevel config
1374 $this->cacheContentFlag = 0;
1375
1376 // Look for page in cache only if caching is not disabled and if a shift-reload is not sent to the server.
1377 if ($this->all && !$this->no_cache && !$this->headerNoCache()) {
1378
1379 $this->newHash = $this->getHash();
1380
1381 $GLOBALS['TT']->push('Cache Query','');
1382 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1383 'S.*',
1384 'cache_pages S,pages P',
1385 'S.hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->newHash, 'cache_pages').'
1386 AND S.page_id=P.uid
1387 AND S.expires > '.intval($GLOBALS['EXEC_TIME']).'
1388 AND P.deleted=0
1389 AND P.hidden=0
1390 AND P.starttime<='.intval($GLOBALS['EXEC_TIME']).'
1391 AND (P.endtime=0 OR P.endtime>'.intval($GLOBALS['EXEC_TIME']).')'
1392 );
1393 $GLOBALS['TT']->pull();
1394 $GLOBALS['TT']->push('Cache Row','');
1395 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
1396 $this->config = (array)unserialize($row['cache_data']); // Fetches the lowlevel config stored with the cached data
1397 $this->content = $row['HTML']; // Getting the content
1398 $this->cacheContentFlag = 1; // Setting flag, so we know, that some cached content is gotten.
1399 $this->cacheExpires = $row['expires'];
1400
1401 if ($this->TYPO3_CONF_VARS['FE']['debug'] || $this->config['config']['debug']) {
1402 $this->content.=chr(10).'<!-- Cached page generated '.Date('d/m Y H:i', $row['tstamp']).'. Expires '.Date('d/m Y H:i', $row['expires']).' -->';
1403 }
1404 }
1405 $GLOBALS['TT']->pull();
1406
1407 $GLOBALS['TYPO3_DB']->sql_free_result($res);
1408 }
1409 }
1410
1411 /**
1412 * Detecting if shift-reload has been clicked
1413 * Will not be called if re-generation of page happens by other reasons (for instance that the page is not in cache yet!)
1414 *
1415 * @return boolean If shift-reload in client browser has been clicked, disable getting cached page (and regenerate it).
1416 */
1417 function headerNoCache() {
1418 $disableAcquireCacheData = FALSE;
1419
1420 if (strtolower($_SERVER['HTTP_CACHE_CONTROL'])==='no-cache' || strtolower($_SERVER['HTTP_PRAGMA'])==='no-cache') {
1421 $disableAcquireCacheData = TRUE;
1422 }
1423
1424 // Call hook for possible by-pass of requiring of page cache (for recaching purpose)
1425 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['headerNoCache'])) {
1426 $_params = array('pObj' => &$this, 'disableAcquireCacheData' => &$disableAcquireCacheData);
1427 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['headerNoCache'] as $_funcRef) {
1428 t3lib_div::callUserFunction($_funcRef,$_params,$this);
1429 }
1430 }
1431
1432 return $disableAcquireCacheData;
1433 }
1434
1435 /**
1436 * Calculates the cache-hash
1437 * This hash is unique to the template, the variables ->id, ->type, ->gr_list (list of groups), ->MP (Mount Points) and cHash array
1438 * Used to get and later store the cached data.
1439 *
1440 * @return string MD5 hash of $this->hash_base which is a serialized version of there variables.
1441 * @access private
1442 * @see getFromCache()
1443 */
1444 function getHash() {
1445 $this->hash_base = serialize(
1446 array(
1447 'all' => $this->all,
1448 'id' => intval($this->id),
1449 'type' => intval($this->type),
1450 'gr_list' => (string)$this->gr_list,
1451 'MP' => (string)$this->MP,
1452 'cHash' => $this->cHash_array
1453 )
1454 );
1455
1456 return md5($this->hash_base);
1457 }
1458
1459 /**
1460 * Checks if config-array exists already but if not, gets it
1461 *
1462 * @return void
1463 */
1464 function getConfigArray() {
1465 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
1466 $GLOBALS['TT']->push('Parse template','');
1467
1468 // Force parsing, if set?:
1469 $this->tmpl->forceTemplateParsing = $this->forceTemplateParsing;
1470
1471 // Start parsing the TS template. Might return cached version.
1472 $this->tmpl->start($this->rootLine);
1473 $GLOBALS['TT']->pull();
1474
1475 if ($this->tmpl->loaded) {
1476 $GLOBALS['TT']->push('Setting the config-array','');
1477 // t3lib_div::print_array($this->tmpl->setup);
1478 $this->sPre = $this->tmpl->setup['types.'][$this->type]; // toplevel - objArrayName
1479 $this->pSetup = $this->tmpl->setup[$this->sPre.'.'];
1480
1481 if (!is_array($this->pSetup)) {
1482 $this->printError('The page is not configured! [type= '.$this->type.']['.$this->sPre.']');
1483 exit;
1484 } else {
1485 $this->config['config']=Array();
1486
1487 // Filling the config-array.
1488 if (is_array($this->tmpl->setup['config.'])) {
1489 $this->config['config'] = $this->tmpl->setup['config.'];
1490 }
1491 if (is_array($this->pSetup['config.'])) {
1492 reset($this->pSetup['config.']);
1493 while(list($theK,$theV)=each($this->pSetup['config.'])) {
1494 $this->config['config'][$theK] = $theV;
1495 }
1496 }
1497 // if .simulateStaticDocuments was not present, the default value will rule.
1498 if (!isset($this->config['config']['simulateStaticDocuments'])) {
1499 $this->config['config']['simulateStaticDocuments'] = $this->TYPO3_CONF_VARS['FE']['simulateStaticDocuments'];
1500 }
1501
1502 // Processing for the config_array:
1503 $this->config['rootLine'] = $this->tmpl->rootLine;
1504 $this->config['mainScript'] = trim($this->config['config']['mainScript']) ? trim($this->config['config']['mainScript']) : 'index.php';
1505
1506 // STAT:
1507 $theLogFile = $this->TYPO3_CONF_VARS['FE']['logfile_dir'].$this->config['config']['stat_apache_logfile'];
1508 // Add PATH_site left to $theLogFile if the path is not absolute yet
1509 if(!t3lib_div::isAbsPath($theLogFile)) $theLogFile = PATH_site.$theLogFile;
1510
1511 if ($this->config['config']['stat_apache'] && $this->config['config']['stat_apache_logfile'] && !strstr($this->config['config']['stat_apache_logfile'],'/')) {
1512 if(t3lib_div::isAllowedAbsPath($theLogFile) && @is_file($theLogFile) && @is_writable($theLogFile)) {
1513 $this->config['stat_vars']['logFile'] = $theLogFile;
1514 $shortTitle = substr(ereg_replace('[^\.[:alnum:]_-]','_',$this->page['title']),0,30);
1515 $pageName = $this->config['config']['stat_apache_pagenames'] ? $this->config['config']['stat_apache_pagenames'] : '[path][title]--[uid].html';
1516 $pageName = str_replace('[title]', $shortTitle ,$pageName);
1517 $pageName = str_replace('[uid]',$this->page['uid'],$pageName);
1518 $pageName = str_replace('[alias]',$this->page['alias'],$pageName);
1519 $pageName = str_replace('[type]',$this->page['type'],$pageName);
1520 $temp = $this->config['rootLine'];
1521 array_pop($temp);
1522 $len = t3lib_div::intInRange($this->config['config']['stat_titleLen'],1,100,20);
1523 $pageName = str_replace('[path]', ereg_replace('[^\.[:alnum:]\/_-]','_',$this->sys_page->getPathFromRootline($temp,$len)).'/' ,$pageName);
1524 $this->config['stat_vars']['pageName'] = $pageName;
1525 } else {
1526 $GLOBALS['TT']->setTSlogMessage('Could not set logfile path. Check filepath and permissions.',3);
1527 }
1528 }
1529 $this->config['FEData'] = $this->tmpl->setup['FEData'];
1530 $this->config['FEData.'] = $this->tmpl->setup['FEData.'];
1531 }
1532 $GLOBALS['TT']->pull();
1533 } else {
1534 $this->printError('No template found!');
1535 exit;
1536 }
1537 }
1538
1539 // Initialize charset settings etc.
1540 $this->initLLvars();
1541
1542 // No cache
1543 if ($this->config['config']['no_cache']) { $this->set_no_cache(); } // Set $this->no_cache true if the config.no_cache value is set!
1544
1545 // Check PATH_INFO url
1546 if ($this->absRefPrefix_force && strcmp($this->config['config']['simulateStaticDocuments'],'PATH_INFO')) {
1547 $redirectUrl = t3lib_div::getIndpEnv('TYPO3_REQUEST_DIR').'index.php?id='.$this->id.'&type='.$this->type;
1548 if ($this->config['config']['simulateStaticDocuments_dontRedirectPathInfoError']) {
1549 $this->printError('PATH_INFO was not configured for this website, and the URL tries to find the page by PATH_INFO!<br /><br /><a href="'.htmlspecialchars($redirectUrl).'">Click here to get to the right page.</a>','Error: PATH_INFO not configured');
1550 } else {
1551 header('Location: '.t3lib_div::locationHeaderUrl($redirectUrl));
1552 }
1553 exit;
1554 // $this->set_no_cache(); // Set no_cache if PATH_INFO is NOT used as simulateStaticDoc. and if absRefPrefix_force shows that such an URL has been passed along.
1555 }
1556 }
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571 /********************************************
1572 *
1573 * Further initialization and data processing
1574 * (jumpurl/submission of forms)
1575 *
1576 *******************************************/
1577
1578 /**
1579 * Get the compressed $TCA array for use in the front-end
1580 * 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.
1581 * Operates on the global variable, $TCA
1582 *
1583 * @return void
1584 * @see includeTCA()
1585 */
1586 function getCompressedTCarray() {
1587 global $TCA;
1588
1589 $GLOBALS['TT']->push('Get Compressed TC array');
1590 if (!$this->TCAloaded) {
1591 // Create hash string for storage / retrieval of cached content:
1592 $tempHash = md5('tables.php:'.
1593 filemtime(TYPO3_extTableDef_script ? PATH_typo3conf.TYPO3_extTableDef_script : PATH_t3lib.'stddb/tables.php').
1594 (TYPO3_extTableDef_script?filemtime(PATH_typo3conf.TYPO3_extTableDef_script):'').
1595 ($GLOBALS['TYPO3_LOADED_EXT']['_CACHEFILE'] ? filemtime(PATH_typo3conf.$GLOBALS['TYPO3_LOADED_EXT']['_CACHEFILE'].'_ext_tables.php') : '')
1596 );
1597 // Try to fetch if:
1598 list($TCA,$this->TCAcachedExtras) = unserialize($this->sys_page->getHash($tempHash, 0));
1599 // If no result, create it:
1600 if (!is_array($TCA)) {
1601 $this->includeTCA(0);
1602 $newTc = Array();
1603 $this->TCAcachedExtras = array(); // Collects other information
1604
1605 foreach($TCA as $key => $val) {
1606 $newTc[$key]['ctrl'] = $val['ctrl'];
1607 $newTc[$key]['feInterface'] = $val['feInterface'];
1608
1609 // Collect information about localization exclusion of fields:
1610 t3lib_div::loadTCA($key);
1611 if (is_array($TCA[$key]['columns'])) {
1612 $this->TCAcachedExtras[$key]['l10n_mode'] = array();
1613 foreach($TCA[$key]['columns'] as $fN => $fV) {
1614 if ($fV['l10n_mode']) {
1615 $this->TCAcachedExtras[$key]['l10n_mode'][$fN] = $fV['l10n_mode'];
1616 }
1617 }
1618 }
1619 }
1620
1621 // Store it in cache:
1622 $TCA = $newTc;
1623 $this->sys_page->storeHash($tempHash, serialize(array($newTc,$this->TCAcachedExtras)), 'SHORT TC');
1624 }
1625 }
1626 $GLOBALS['TT']->pull();
1627 }
1628
1629 /**
1630 * Includes full TCA.
1631 * Normally in the frontend only a part of the global $TCA array is loaded, for instance the "ctrl" part. Thus it doesn't take up too much memory.
1632 * If you need the FULL TCA available for some reason (like plugins using it) you should call this function which will include the FULL TCA.
1633 * Global vars $TCA, $PAGES_TYPES, $LANG_GENERAL_LABELS can/will be affected.
1634 * The flag $this->TCAloaded will make sure that such an inclusion happens only once since; If $this->TCAloaded is set, nothing is included.
1635 *
1636 * @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())
1637 * @return void
1638 * @see getCompressedTCarray()
1639 */
1640 function includeTCA($TCAloaded=1) {
1641 global $TCA, $PAGES_TYPES, $LANG_GENERAL_LABELS, $TBE_MODULES;
1642 if (!$this->TCAloaded) {
1643 $TCA = Array();
1644 include (TYPO3_tables_script ? PATH_typo3conf.TYPO3_tables_script : PATH_t3lib.'stddb/tables.php');
1645 // Extension additions
1646 if ($GLOBALS['TYPO3_LOADED_EXT']['_CACHEFILE']) {
1647 include(PATH_typo3conf.$GLOBALS['TYPO3_LOADED_EXT']['_CACHEFILE'].'_ext_tables.php');
1648 } else {
1649 include(PATH_t3lib.'stddb/load_ext_tables.php');
1650 }
1651 // ext-script
1652 if (TYPO3_extTableDef_script) {
1653 include (PATH_typo3conf.TYPO3_extTableDef_script);
1654 }
1655
1656 $this->TCAloaded = $TCAloaded;
1657 }
1658 }
1659
1660 /**
1661 * Setting the language key that'll be used by the current page.
1662 * 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.
1663 *
1664 * @return void
1665 * @access private
1666 */
1667 function settingLanguage() {
1668
1669 // Get values from TypoScript:
1670 $this->sys_language_uid = $this->sys_language_content = intval($this->config['config']['sys_language_uid']);
1671 list($this->sys_language_mode,$sys_language_content) = t3lib_div::trimExplode(';', $this->config['config']['sys_language_mode']);
1672 $this->sys_language_contentOL = $this->config['config']['sys_language_overlay'];
1673
1674 // If sys_language_uid is set to another language than default:
1675 if ($this->sys_language_uid>0) {
1676 // Request the overlay record for the sys_language_uid:
1677 $olRec = $this->sys_page->getPageOverlay($this->id, $this->sys_language_uid);
1678 if (!count($olRec)) {
1679
1680 // If no OL record exists and a foreign language is asked for...
1681 if ($this->sys_language_uid) {
1682
1683 // If requested translation is not available:
1684 if ($this->page['l18n_cfg']&2) {
1685 $this->pageNotFoundAndExit('Page is not available in the requested language.');
1686 } else {
1687 switch((string)$this->sys_language_mode) {
1688 case 'strict':
1689 $this->pageNotFoundAndExit('Page is not available in the requested language (strict).');
1690 break;
1691 case 'content_fallback':
1692 $fallBackOrder = t3lib_div::intExplode(',', $sys_language_content);
1693 foreach($fallBackOrder as $orderValue) {
1694 if (!strcmp($orderValue,'0') || count($this->sys_page->getPageOverlay($this->id, $orderValue))) {
1695 $this->sys_language_content = $orderValue; // Setting content uid (but leaving the sys_language_uid)
1696 break;
1697 }
1698 }
1699 break;
1700 default:
1701 // Default is that everything defaults to the default language...
1702 $this->sys_language_uid = $this->sys_language_content = 0;
1703 break;
1704 }
1705 }
1706 }
1707 } else {
1708 // Setting sys_language if an overlay record was found (which it is only if a language is used)
1709 $this->page = $this->sys_page->getPageOverlay($this->page, $this->sys_language_uid);
1710 }
1711 }
1712
1713 // Setting sys_language_uid inside sys-page:
1714 $this->sys_page->sys_language_uid = $this->sys_language_uid;
1715
1716 // If default translation is not available:
1717 if ((!$this->sys_language_uid || !$this->sys_language_content) && $this->page['l18n_cfg']&1) {
1718 $this->pageNotFoundAndExit('Page is not available in default language.');
1719 }
1720
1721 // Updating content of the two rootLines IF the language key is set!
1722 if ($this->sys_language_uid && is_array($this->tmpl->rootLine)) {
1723 reset($this->tmpl->rootLine);
1724 while(list($rLk)=each($this->tmpl->rootLine)) {
1725 $this->tmpl->rootLine[$rLk] = $this->sys_page->getPageOverlay($this->tmpl->rootLine[$rLk]);
1726 }
1727 }
1728 if ($this->sys_language_uid && is_array($this->rootLine)) {
1729 reset($this->rootLine);
1730 while(list($rLk)=each($this->rootLine)) {
1731 $this->rootLine[$rLk] = $this->sys_page->getPageOverlay($this->rootLine[$rLk]);
1732 }
1733 }
1734
1735 // Finding the ISO code:
1736 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"
1737 $sys_language_row = $this->sys_page->getRawRecord('sys_language',$this->sys_language_content,'static_lang_isocode');
1738 if (is_array($sys_language_row) && $sys_language_row['static_lang_isocode']) {
1739 $stLrow = $this->sys_page->getRawRecord('static_languages',$sys_language_row['static_lang_isocode'],'lg_iso_2');
1740 $this->sys_language_isocode = $stLrow['lg_iso_2'];
1741 }
1742 }
1743
1744 // Setting softMergeIfNotBlank:
1745 $table_fields = t3lib_div::trimExplode(',', $this->config['config']['sys_language_softMergeIfNotBlank'],1);
1746 foreach($table_fields as $TF) {
1747 list($tN,$fN) = explode(':',$TF);
1748 $this->TCAcachedExtras[$tN]['l10n_mode'][$fN] = 'mergeIfNotBlank';
1749 }
1750 }
1751
1752 /**
1753 * Setting locale for frontend rendering
1754 *
1755 * @return void
1756 */
1757 function settingLocale() {
1758
1759 // Setting locale
1760 if ($this->config['config']['locale_all']) {
1761 # Change by Rene Fritz, 22/10 2002
1762 # there`s the problem that PHP parses float values in scripts wrong if the locale LC_NUMERIC is set to something with a komma as decimal point
1763 # this does not work in php 4.2.3
1764 #setlocale('LC_ALL',$this->config['config']['locale_all']);
1765 #setlocale('LC_NUMERIC','en_US');
1766
1767 # so we set all except LC_NUMERIC
1768 setlocale(LC_COLLATE,$this->config['config']['locale_all']);
1769 setlocale(LC_CTYPE,$this->config['config']['locale_all']);
1770 setlocale(LC_MONETARY,$this->config['config']['locale_all']);
1771 setlocale(LC_TIME,$this->config['config']['locale_all']);
1772
1773 $this->localeCharset = $this->csConvObj->get_locale_charset($this->config['config']['locale_all']);
1774 }
1775 }
1776
1777 /**
1778 * Checks if any email-submissions or submission via the fe_tce
1779 *
1780 * @return string 'email' if a formmail has been send, 'fe_tce' if front-end data submission (like forums, guestbooks) is send. '' if none.
1781 */
1782 function checkDataSubmission() {
1783 if ($_POST['formtype_db'] || $_POST['formtype_mail']) {
1784 $refInfo = parse_url(t3lib_div::getIndpEnv('HTTP_REFERER'));
1785 if (t3lib_div::getIndpEnv('TYPO3_HOST_ONLY')==$refInfo['host'] || $this->TYPO3_CONF_VARS['SYS']['doNotCheckReferer']) {
1786 if ($this->locDataCheck($_POST['locationData'])) {
1787 $ret = '';
1788 if ($_POST['formtype_mail']) {
1789 $ret = 'email';
1790 } elseif ($_POST['formtype_db'] && is_array($_POST['data'])) {
1791 $ret = 'fe_tce';
1792 }
1793 $GLOBALS['TT']->setTSlogMessage('"Check Data Submission": Return value: '.$ret,0);
1794 return $ret;
1795 }
1796 } else $GLOBALS['TT']->setTSlogMessage('"Check Data Submission": HTTP_HOST and REFERER HOST did not match when processing submitted formdata!',3);
1797 }
1798 }
1799
1800 /**
1801 * Processes submitted user data (obsolete "Frontend TCE")
1802 *
1803 * @return void
1804 * @see tslib_feTCE
1805 * @link http://typo3.org/doc.0.html?&tx_extrepmgm_pi1[extUid]=270&tx_extrepmgm_pi1[tocEl]=342&cHash=fdf55adb3b
1806 */
1807 function fe_tce() {
1808 $fe_tce = t3lib_div::makeInstance('tslib_feTCE');
1809 $fe_tce->start(t3lib_div::_POST('data'),$this->config['FEData.']);
1810 $fe_tce->includeScripts();
1811 }
1812
1813 /**
1814 * Checks if a formmail submission can be sent as email
1815 *
1816 * @param string The input from $_POST['locationData']
1817 * @return void
1818 * @access private
1819 * @see checkDataSubmission()
1820 */
1821 function locDataCheck($locationData) {
1822 $locData = explode(':',$locationData);
1823 if (!$locData[1] || $this->sys_page->checkRecord($locData[1],$locData[2],1)) {
1824 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.
1825 return 1;
1826 } else $GLOBALS['TT']->setTSlogMessage('LocationData Error: The page pointed to by location data ('.$locationData.') was not accessible.',2);
1827 } else $GLOBALS['TT']->setTSlogMessage('LocationData Error: Location data ('.$locationData.') record pointed to was not accessible.',2);
1828 }
1829
1830 /**
1831 * Sends the emails from the formmail content object.
1832 *
1833 * @return void
1834 * @access private
1835 * @see checkDataSubmission()
1836 */
1837 function sendFormmail() {
1838 $formmail = t3lib_div::makeInstance('t3lib_formmail');
1839
1840 $EMAIL_VARS = t3lib_div::_POST();
1841 $locationData = $EMAIL_VARS['locationData'];
1842 unset($EMAIL_VARS['locationData']);
1843 unset($EMAIL_VARS['formtype_mail']);
1844
1845 $integrityCheck = $this->TYPO3_CONF_VARS['FE']['strictFormmail'];
1846
1847 if(!$this->TYPO3_CONF_VARS['FE']['secureFormmail']) {
1848 // Check recipient field:
1849 $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.
1850 foreach($encodedFields as $fieldKey) {
1851 if (strlen($EMAIL_VARS[$fieldKey])) {
1852 if ($res = $this->codeString($EMAIL_VARS[$fieldKey], TRUE)) { // Decode...
1853 $EMAIL_VARS[$fieldKey] = $res; // Set value if OK
1854 } elseif ($integrityCheck) { // Otherwise abort:
1855 $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);
1856 return false;
1857 } else {
1858 $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);
1859 }
1860 }
1861 }
1862 } else {
1863 $locData = explode(':',$locationData);
1864 $record = $this->sys_page->checkRecord($locData[1],$locData[2],1);
1865 $EMAIL_VARS['recipient'] = $record['subheader'];
1866 $EMAIL_VARS['recipient_copy'] = $this->extractRecipientCopy($record['bodytext']);
1867 }
1868
1869 // Hook for preprocessing of the content for formmails:
1870 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['sendFormmail-PreProcClass'])) {
1871 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['sendFormmail-PreProcClass'] as $_classRef) {
1872 $_procObj = &t3lib_div::getUserObj($_classRef);
1873 $EMAIL_VARS = $_procObj->sendFormmail_preProcessVariables($EMAIL_VARS,$this);
1874 }
1875 }
1876
1877 $formmail->start($EMAIL_VARS);
1878 $formmail->sendtheMail();
1879 $GLOBALS['TT']->setTSlogMessage('"Formmail" invoked, sending mail to '.$EMAIL_VARS['recipient'],0);
1880 }
1881
1882 /**
1883 * Extracts the value of recipient copy field from a formmail CE bodytext
1884 *
1885 * @param string $bodytext The content of the related bodytext field
1886 * @return string The value of the recipient_copy field, or an empty string
1887 */
1888 function extractRecipientCopy($bodytext) {
1889 $recipient_copy = '';
1890 $fdef = array();
1891 //|recipient_copy=hidden|karsten@localhost.localdomain
1892 preg_match('/^[\s]*\|[\s]*recipient_copy[\s]*=[\s]*hidden[\s]*\|(.*)$/m', $bodytext, $fdef);
1893 $recipient_copy = (!empty($fdef[1])) ? $fdef[1] : '';
1894 return $recipient_copy;
1895 }
1896
1897 /**
1898 * Checks if jumpurl is set.
1899 * This function also takes care of jumpurl utilized by the Direct Mail module (ext: direct_mail) which may set an integer value for jumpurl which refers to a link in a certain mail-record, mid
1900 *
1901 * @return void
1902 */
1903 function checkJumpUrl() {
1904 global $TCA;
1905
1906 $mid = t3lib_div::_GP('mid'); // mail id, if direct mail link
1907 $rid = t3lib_div::_GP('rid'); // recipient id, if direct mail link
1908 if ((strcmp($this->jumpurl,'') && ((t3lib_div::getIndpEnv('HTTP_REFERER') || $this->TYPO3_CONF_VARS['SYS']['doNotCheckReferer']) || $mid)) || ($this->jumpurl = $this->sys_page->getExtURL($this->page,$this->config['config']['disablePageExternalUrl']))) {
1909 if ($mid && is_array($TCA['sys_dmail'])) { // Yes, it's OK if the link comes from a direct mail. AND sys_dmail module has installed the table, sys_dmail (and therefore we expect sys_dmail_maillog as well!)
1910 $temp_recip=explode('_',$rid);
1911 $url_id=0;
1912 if (t3lib_div::testInt($this->jumpurl)) {
1913 $temp_res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('mailContent', 'sys_dmail', 'uid='.intval($mid));
1914 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($temp_res)) {
1915 $temp_unpackedMail = unserialize($row['mailContent']);
1916 $url_id=$this->jumpurl;
1917 if ($this->jumpurl>=0) {
1918 $responseType=1; // Link (number)
1919 $this->jumpurl = $temp_unpackedMail['html']['hrefs'][$url_id]['absRef'];
1920 } else {
1921 $responseType=2; // Link (number, plaintext)
1922 $this->jumpurl = $temp_unpackedMail['plain']['link_ids'][abs($url_id)];
1923 }
1924 switch($temp_recip[0]) {
1925 case 't':
1926 $theTable = 'tt_address';
1927 break;
1928 case 'f':
1929 $theTable = 'fe_users';
1930 break;
1931 default:
1932 $theTable='';
1933 break;
1934 }
1935 if ($theTable) {
1936 $recipRow = $this->sys_page->getRawRecord($theTable,$temp_recip[1]);
1937 if (is_array($recipRow)) {
1938 // debug($recipRow);
1939 $authCode = t3lib_div::stdAuthCode($recipRow['uid']);
1940 $rowFieldsArray = explode(',', 'uid,name,title,email,phone,www,address,company,city,zip,country,fax,firstname');
1941 reset($rowFieldsArray);
1942 while(list(,$substField)=each($rowFieldsArray)) {
1943 $this->jumpurl = str_replace('###USER_'.$substField.'###', $recipRow[$substField], $this->jumpurl);
1944 }
1945 $this->jumpurl = str_replace('###SYS_TABLE_NAME###', $tableNameChar, $this->jumpurl); // Put in the tablename of the userinformation
1946 $this->jumpurl = str_replace('###SYS_MAIL_ID###', $mid, $this->jumpurl); // Put in the uid of the mail-record
1947 $this->jumpurl = str_replace('###SYS_AUTHCODE###', $authCode, $this->jumpurl);
1948
1949 // debug($this->jumpurl);
1950 }
1951 }
1952 }
1953
1954 $GLOBALS['TYPO3_DB']->sql_free_result($temp_res);
1955
1956 if (!$this->jumpurl) die('Error: No further link. Please report error to the mail sender.');
1957 } else {
1958 $responseType=-1; // received (url, dmailerping)
1959 }
1960 if ($responseType!=0) {
1961 $insertFields = array(
1962 'mid' => intval($mid),
1963 'rtbl' => $temp_recip[0],
1964 'rid' => intval($temp_recip[1]),
1965 'tstamp' => time(),
1966 'url' => $this->jumpurl,
1967 'response_type' => intval($responseType),
1968 'url_id' => intval($url_id)
1969 );
1970
1971 $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_dmail_maillog', $insertFields);
1972 }
1973 }
1974 } else {
1975 unset($this->jumpurl);
1976 }
1977 }
1978
1979 /**
1980 * Sends a header 'Location' to jumpurl, if jumpurl is set.
1981 * Will exit if a location header is sent (for instance if JumpUrl was triggered)
1982 *
1983 * @return void
1984 */
1985 function jumpUrl() {
1986 if ($this->jumpurl) {
1987 if (t3lib_div::_GP('juSecure')) {
1988 $hArr = array(
1989 $this->jumpurl,
1990 t3lib_div::_GP('locationData'),
1991 $this->TYPO3_CONF_VARS['SYS']['encryptionKey']
1992 );
1993 $calcJuHash=t3lib_div::shortMD5(serialize($hArr));
1994 $locationData = t3lib_div::_GP('locationData');
1995 $juHash = t3lib_div::_GP('juHash');
1996 if ($juHash == $calcJuHash) {
1997 if ($this->locDataCheck($locationData)) {
1998 $this->jumpurl = rawurldecode($this->jumpurl); // 211002 - goes with cObj->filelink() rawurlencode() of filenames so spaces can be allowed.
1999 if (@is_file($this->jumpurl)) {
2000 $mimeType = t3lib_div::_GP('mimeType');
2001 $mimeType = $mimeType ? $mimeType : 'application/octet-stream';
2002 Header('Content-Type: '.$mimeType);
2003 Header('Content-Disposition: attachment; filename='.basename($this->jumpurl));
2004 readfile($this->jumpurl);
2005 exit;
2006 } else die('jumpurl Secure: "'.$this->jumpurl.'" was not a valid file!');
2007 } else die('jumpurl Secure: locationData, '.$locationData.', was not accessible.');
2008 } else die('jumpurl Secure: Calculated juHash, '.$calcJuHash.', did not match the submitted juHash.');
2009 } else {
2010 $TSConf = $this->getPagesTSconfig();
2011 if ($TSConf['TSFE.']['jumpUrl_transferSession']) {
2012 $uParts = parse_url($this->jumpurl);
2013 $params = '&FE_SESSION_KEY='.rawurlencode($this->fe_user->id.'-'.md5($this->fe_user->id.'/'.$this->TYPO3_CONF_VARS['SYS']['encryptionKey']));
2014 $this->jumpurl.=($uParts['query']?'':'?').$params; // Add the session parameter ...
2015 }
2016 Header('Location: '.$this->jumpurl);
2017 exit;
2018 }
2019 }
2020 }
2021
2022 /**
2023 * Sets the URL_ID_TOKEN in the internal var, $this->getMethodUrlIdToken
2024 *
2025 * @return void
2026 * @access private
2027 */
2028 function setUrlIdToken() {
2029 if ($this->config['config']['ftu']) {
2030 $this->getMethodUrlIdToken = $this->TYPO3_CONF_VARS['FE']['get_url_id_token'];
2031 } else {
2032 $this->getMethodUrlIdToken = '';
2033 }
2034 }
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059 /********************************************
2060 *
2061 * Page generation; cache handling
2062 *
2063 *******************************************/
2064
2065 /**
2066 * Returns true if the page should be generated
2067 * That is if jumpurl is not set and the cacheContentFlag is not set.
2068 *
2069 * @return boolean
2070 */
2071 function isGeneratePage() {
2072 return (!$this->cacheContentFlag && !$this->jumpurl);
2073 }
2074
2075 /**
2076 * Temp cache content
2077 * 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.
2078 *
2079 * @return void
2080 */
2081 function tempPageCacheContent() {
2082 $this->tempContent = 0;
2083
2084 if (!$this->no_cache) {
2085 $seconds = 30;
2086 $stdMsg = '
2087 <html>
2088 <head>
2089 <title>'.htmlspecialchars($this->tmpl->printTitle($this->page['title'])).'</title>
2090 <meta http-equiv="refresh" content="3; URL='.htmlspecialchars(t3lib_div::getIndpEnv('REQUEST_URI')).'" />
2091 </head>
2092 <body bgcolor="white">
2093 <span style="font-family:Verdana,Arial,Helvetica" color="#cccccc">
2094 <div align="center">
2095 <strong>Page is being generated.</strong><br />
2096 If this message does not disappear within '.$seconds.' seconds, please reload.
2097 </div>
2098 </span>
2099 </body>
2100 </html>';
2101 $temp_content = $this->config['config']['message_page_is_being_generated'] ? $this->config['config']['message_page_is_being_generated'] : $stdMsg;
2102
2103 $this->setPageCacheContent($temp_content, '', $GLOBALS['EXEC_TIME']+$seconds);
2104 $this->tempContent = 1; // This flag shows that temporary content is put in the cache
2105 }
2106 }
2107
2108 /**
2109 * Set cache content to $this->content
2110 *
2111 * @return void
2112 */
2113 function realPageCacheContent() {
2114 $cache_timeout = $this->page['cache_timeout'] ? $this->page['cache_timeout'] : ($this->cacheTimeOutDefault ? $this->cacheTimeOutDefault : 60*60*24); // seconds until a cached page is too old
2115 $timeOutTime = $GLOBALS['EXEC_TIME']+$cache_timeout;
2116 if ($this->config['config']['cache_clearAtMidnight']) {
2117 $midnightTime = mktime (0,0,0,date('m',$timeOutTime),date('d',$timeOutTime),date('Y',$timeOutTime));
2118 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.
2119 $timeOutTime = $midnightTime;
2120 }
2121 }
2122 $this->config['hash_base'] = $this->hash_base;
2123 $this->setPageCacheContent($this->content, $this->config, $timeOutTime);
2124
2125 // Hook for cache post processing (eg. writing static files!)
2126 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['insertPageIncache'])) {
2127 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['insertPageIncache'] as $_classRef) {
2128 $_procObj = &t3lib_div::getUserObj($_classRef);
2129 $_procObj->insertPageIncache($this,$timeOutTime);
2130 }
2131 }
2132 }
2133
2134 /**
2135 * Sets cache content; Inserts the content string into the cache_pages table.
2136 *
2137 * @param string The content to store in the HTML field of the cache table
2138 * @param mixed The additional cache_data array, fx. $this->config
2139 * @param integer Timestamp
2140 * @return void
2141 * @see realPageCacheContent(), tempPageCacheContent()
2142 */
2143 function setPageCacheContent($c,$d,$t) {
2144 $this->clearPageCacheContent();
2145 $insertFields = array(
2146 'hash' => $this->newHash,
2147 'page_id' => $this->id,
2148 'HTML' => $c,
2149 'cache_data' => serialize($d),
2150 'expires' => $t,
2151 'tstamp' => $GLOBALS['EXEC_TIME']
2152 );
2153
2154 $this->cacheExpires = $t;
2155
2156 if ($this->page_cache_reg1) {
2157 $insertFields['reg1'] = intval($this->page_cache_reg1);
2158 }
2159
2160 $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_pages', $insertFields);
2161 }
2162
2163 /**
2164 * Clears cache content (for $this->newHash)
2165 *
2166 * @return void
2167 */
2168 function clearPageCacheContent() {
2169 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages', 'hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->newHash, 'cache_pages'));
2170 }
2171
2172 /**
2173 * Clears cache content for a list of page ids
2174 *
2175 * @param string A list of INTEGER numbers which points to page uids for which to clear entries in the cache_pages table (page content cache)
2176 * @return void
2177 */
2178 function clearPageCacheContent_pidList($pidList) {
2179 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_pages', 'page_id IN ('.$GLOBALS['TYPO3_DB']->cleanIntList($pidList).')');
2180 }
2181
2182 /**
2183 * Sets sys last changed
2184 * 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.
2185 *
2186 * @return void
2187 * @see tslib_cObj::lastChanged()
2188 */
2189 function setSysLastChanged() {
2190 if ($this->page['SYS_LASTCHANGED'] < intval($this->register['SYS_LASTCHANGED'])) {
2191 $GLOBALS['TYPO3_DB']->exec_UPDATEquery('pages', 'uid='.intval($this->id), array('SYS_LASTCHANGED' => intval($this->register['SYS_LASTCHANGED'])));
2192 }
2193 }
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214 /********************************************
2215 *
2216 * Page generation; rendering and inclusion
2217 *
2218 *******************************************/
2219
2220 /**
2221 * Does some processing BEFORE the pagegen script is included.
2222 *
2223 * @return void
2224 */
2225 function generatePage_preProcessing() {
2226 ksort($this->all);
2227 // Same codeline as in getFromCache(). BUT $this->all has been set in the meantime, so we can't just skip this line and let it be set above! Keep this line!
2228 $this->newHash = $this->getHash();
2229
2230 // 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.
2231 $this->tempPageCacheContent();
2232
2233
2234 // Setting cache_timeout_default. May be overridden by PHP include scritps.
2235 $this->cacheTimeOutDefault = intval($this->config['config']['cache_period']);
2236
2237 // page is generated
2238 $this->no_cacheBeforePageGen = $this->no_cache;
2239 }
2240
2241 /**
2242 * Determines to include custom or pagegen.php script
2243 * returns script-filename if a TypoScript (config) script is defined and should be include instead of pagegen.php
2244 *
2245 * @return string The relative filepath of "config.pageGenScript" if found and allowed
2246 */
2247 function generatePage_whichScript() {
2248 if (!$this->TYPO3_CONF_VARS['FE']['noPHPscriptInclude'] && $this->config['config']['pageGenScript']) {
2249 return $this->tmpl->getFileName($this->config['config']['pageGenScript']);
2250 }
2251 }
2252
2253 /**
2254 * Does some processing AFTER the pagegen script is included.
2255 * This includes calling tidy (if configured), XHTML cleaning (if configured), caching the page, indexing the page (if configured) and setting sysLastChanged
2256 *
2257 * @return void
2258 */
2259 function generatePage_postProcessing() {
2260 // 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.
2261 if ($this->no_cacheBeforePageGen) $this->set_no_cache();
2262
2263 // Tidy up the code, if flag...
2264 if ($this->TYPO3_CONF_VARS['FE']['tidy_option'] == 'all') {
2265 $GLOBALS['TT']->push('Tidy, all','');
2266 $this->content = $this->tidyHTML($this->content);
2267 $GLOBALS['TT']->pull();
2268 }
2269
2270 // XHTML-clean the code, if flag set
2271 if ($this->doXHTML_cleaning() == 'all') {
2272 $GLOBALS['TT']->push('XHTML clean, all','');
2273 $XHTML_clean = t3lib_div::makeInstance('t3lib_parsehtml');
2274 $this->content = $XHTML_clean->XHTML_clean($this->content);
2275 $GLOBALS['TT']->pull();
2276 }
2277
2278 // Fix local anchors in links, if flag set
2279 if ($this->doLocalAnchorFix() == 'all') {
2280 $GLOBALS['TT']->push('Local anchor fix, all','');
2281 $this->prefixLocalAnchorsWithScript();
2282 $GLOBALS['TT']->pull();
2283 }
2284
2285 // Hook for post-processing of page content cached/non-cached:
2286 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-all'])) {
2287 $_params = array('pObj' => &$this);
2288 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-all'] as $_funcRef) {
2289 t3lib_div::callUserFunction($_funcRef,$_params,$this);
2290 }
2291 }
2292
2293 // Processing if caching is enabled:
2294 if (!$this->no_cache) {
2295 // Tidy up the code, if flag...
2296 if ($this->TYPO3_CONF_VARS['FE']['tidy_option'] == 'cached') {
2297 $GLOBALS['TT']->push('Tidy, cached','');
2298 $this->content = $this->tidyHTML($this->content);
2299 $GLOBALS['TT']->pull();
2300 }
2301 // XHTML-clean the code, if flag set
2302 if ($this->doXHTML_cleaning() == 'cached') {
2303 $GLOBALS['TT']->push('XHTML clean, cached','');
2304 $XHTML_clean = t3lib_div::makeInstance('t3lib_parsehtml');
2305 $this->content = $XHTML_clean->XHTML_clean($this->content);
2306 $GLOBALS['TT']->pull();
2307 }
2308 // Fix local anchors in links, if flag set
2309 if ($this->doLocalAnchorFix() == 'cached') {
2310 $GLOBALS['TT']->push('Local anchor fix, cached','');
2311 $this->prefixLocalAnchorsWithScript();
2312 $GLOBALS['TT']->pull();
2313 }
2314
2315 // Hook for post-processing of page content before being cached:
2316 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-cached'])) {
2317 $_params = array('pObj' => &$this);
2318 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-cached'] as $_funcRef) {
2319 t3lib_div::callUserFunction($_funcRef,$_params,$this);
2320 }
2321 }
2322 }
2323
2324 // Hook for indexing pages
2325 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['pageIndexing'])) {
2326 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['pageIndexing'] as $_classRef) {
2327 $_procObj = &t3lib_div::getUserObj($_classRef);
2328 $_procObj->hook_indexContent($this);
2329 }
2330 }
2331
2332 // Convert char-set for output:
2333 $this->content = $this->convOutputCharset($this->content,'mainpage');
2334
2335 // Storing for cache:
2336 if (!$this->no_cache) {
2337 $this->realPageCacheContent();
2338 } elseif ($this->tempContent) { // If there happens to be temporary content in the cache and the cache was not cleared due to new content put in it... ($this->no_cache=0)
2339 $this->clearPageCacheContent();
2340 }
2341
2342 // Sets sys-last-change:
2343 $this->setSysLastChanged();
2344 }
2345
2346 /**
2347 * Processes the INTinclude-scripts
2348 *
2349 * @return void
2350 */
2351 function INTincScript() {
2352 $GLOBALS['TT']->push('Split content');
2353 $INTiS_splitC = explode('<!--INT_SCRIPT.',$this->content); // Splits content with the key.
2354 $this->content='';
2355 $GLOBALS['TT']->setTSlogMessage('Parts: '.count($INTiS_splitC));
2356 $GLOBALS['TT']->pull();
2357
2358 // Depreciated stuff:
2359 $this->additionalHeaderData = is_array($this->config['INTincScript_ext']['additionalHeaderData']) ? $this->config['INTincScript_ext']['additionalHeaderData'] : array();
2360 $this->additionalJavaScript = $this->config['INTincScript_ext']['additionalJavaScript'];
2361 $this->additionalCSS = $this->config['INTincScript_ext']['additionalCSS'];
2362 $this->JSCode = $this->additionalHeaderData['JSCode'];
2363 $this->JSImgCode = $this->additionalHeaderData['JSImgCode'];
2364 $this->divSection='';
2365
2366 $INTiS_config = $GLOBALS['TSFE']->config['INTincScript'];
2367 foreach($INTiS_splitC as $INTiS_c => $INTiS_cPart) {
2368 if (substr($INTiS_cPart,32,3)=='-->') { // If the split had a comment-end after 32 characters it's probably a split-string
2369 $GLOBALS['TT']->push('Include '.$INTiS_config[$INTiS_key]['file'],'');
2370 $INTiS_key = 'INT_SCRIPT.'.substr($INTiS_cPart,0,32);
2371 $incContent='';
2372 if (is_array($INTiS_config[$INTiS_key])) {
2373 $INTiS_cObj = unserialize($INTiS_config[$INTiS_key]['cObj']);
2374 $INTiS_cObj->INT_include=1;
2375 switch($INTiS_config[$INTiS_key]['type']) {
2376 case 'SCRIPT':
2377 $incContent = $INTiS_cObj->PHP_SCRIPT($INTiS_config[$INTiS_key]['conf']);
2378 break;
2379 case 'COA':
2380 $incContent = $INTiS_cObj->COBJ_ARRAY($INTiS_config[$INTiS_key]['conf']);
2381 break;
2382 case 'FUNC':
2383 $incContent = $INTiS_cObj->USER($INTiS_config[$INTiS_key]['conf']);
2384 break;
2385 case 'POSTUSERFUNC':
2386 $incContent = $INTiS_cObj->callUserFunction($INTiS_config[$INTiS_key]['postUserFunc'], $INTiS_config[$INTiS_key]['conf'], $INTiS_config[$INTiS_key]['content']);
2387 break;
2388 }
2389 }
2390 $this->content.= $this->convOutputCharset($incContent,'INC-'.$INTiS_c);
2391 $this->content.= substr($INTiS_cPart,35);
2392 $GLOBALS['TT']->pull($incContent);
2393 } else {
2394 $this->content.= ($INTiS_c?'<!--INT_SCRIPT.':'').$INTiS_cPart;
2395 }
2396 }
2397 $GLOBALS['TT']->push('Substitute header section');
2398 $this->INTincScript_loadJSCode();
2399 $this->content = str_replace('<!--HD_'.$this->config['INTincScript_ext']['divKey'].'-->', $this->convOutputCharset(implode(chr(10),$this->additionalHeaderData),'HD'), $this->content);
2400 $this->content = str_replace('<!--TDS_'.$this->config['INTincScript_ext']['divKey'].'-->', $this->convOutputCharset($this->divSection,'TDS'), $this->content);
2401 $this->setAbsRefPrefix();
2402 $GLOBALS['TT']->pull();
2403 }
2404
2405 /**
2406 * Loads the JavaScript code for INTincScript
2407 *
2408 * @return void
2409 * @access private
2410 */
2411 function INTincScript_loadJSCode() {
2412 if ($this->JSImgCode) { // If any images added, then add them to the javascript section
2413 $this->additionalHeaderData['JSImgCode']='
2414 <script type="text/javascript">
2415 /*<![CDATA[*/
2416 <!--
2417 if (version == "n3") {
2418 '.trim($this->JSImgCode).'
2419 }
2420 // -->
2421 /*]]>*/
2422 </script>';
2423 }
2424 if ($this->JSCode || count($this->additionalJavaScript)) { // Add javascript
2425 $this->additionalHeaderData['JSCode']='
2426 <script type="text/javascript">
2427 /*<![CDATA[*/
2428 <!--
2429 '.implode(chr(10),$this->additionalJavaScript).'
2430 '.trim($this->JSCode).'
2431 // -->
2432 /*]]>*/
2433 </script>';
2434 }
2435 if (count($this->additionalCSS)) { // Add javascript
2436 $this->additionalHeaderData['_CSS']='
2437 <style type="text/css">
2438 /*<![CDATA[*/
2439 <!--
2440 '.implode(chr(10),$this->additionalCSS).'
2441 // -->
2442 /*]]>*/
2443 </style>';
2444 }
2445 }
2446
2447 /**
2448 * Determines if there are any INTincScripts to include
2449 *
2450 * @return boolean Returns true if scripts are found (and not jumpurl)
2451 */
2452 function isINTincScript() {
2453 return (is_array($this->config['INTincScript']) && !$this->jumpurl);
2454 }
2455
2456 /**
2457 * Returns the mode of XHTML cleaning
2458 *
2459 * @return string Keyword: "all", "cached" or "output"
2460 */
2461 function doXHTML_cleaning() {
2462 return $this->config['config']['xhtml_cleaning'];
2463 }
2464
2465 /**
2466 * Returns the mode of Local Anchor prefixing
2467 *
2468 * @return string Keyword: "all", "cached" or "output"
2469 */
2470 function doLocalAnchorFix() {
2471 return $this->config['config']['prefixLocalAnchors'];
2472 }
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489 /********************************************
2490 *
2491 * Finished off; outputting, storing session data, statistics...
2492 *
2493 *******************************************/
2494
2495 /**
2496 * Determines if content should be outputted.
2497 * Outputting content is done only if jumpurl is NOT set.
2498 *
2499 * @return boolean Returns true if $this->jumpurl is not set.
2500 */
2501 function isOutputting() {
2502
2503 // Initialize by status of jumpUrl:
2504 $enableOutput = (!$this->jumpurl);
2505
2506 // Call hook for possible disabling of output:
2507 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['isOutputting'])) {
2508 $_params = array('pObj' => &$this, 'enableOutput' => &$enableOutput);
2509 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['isOutputting'] as $_funcRef) {
2510 t3lib_div::callUserFunction($_funcRef,$_params,$this);
2511 }
2512 }
2513
2514 return $enableOutput;
2515 }
2516
2517 /**
2518 * Processes the output before it's actually outputted. Sends headers also.
2519 * This includes substituting the USERNAME comment, getMethodUrlIdToken, sending additional headers (as defined in the TypoScript "config.additionalheaders" object), tidy'ing content, XHTML cleaning content (if configured)
2520 * Works on $this->content
2521 *
2522 * @return void
2523 */
2524 function processOutput() {
2525
2526 // Set header for charset-encoding unless disabled
2527 if (!$this->config['config']['disableCharsetHeader']) {
2528 $headLine = 'Content-Type:text/html;charset='.trim($this->metaCharset);
2529 header($headLine);
2530 }
2531
2532 // Set cache related headers to client (used to enable proxy / client caching!)
2533 if ($this->config['config']['sendCacheHeaders']) {
2534 $this->sendCacheHeaders();
2535 }
2536
2537 // Set headers, if any
2538 if ($this->config['config']['additionalHeaders']) {
2539 $headerArray = explode('|', $this->config['config']['additionalHeaders']);
2540 while(list(,$headLine)=each($headerArray)) {
2541 $headLine = trim($headLine);
2542 header($headLine);
2543 }
2544 }
2545
2546 // Make substitution of eg. username/uid in content only if cache-headers for client/proxy caching is NOT sent!
2547 if (!$this->isClientCachable) {
2548 $this->contentStrReplace();
2549 }
2550
2551 // Tidy up the code, if flag...
2552 if ($this->TYPO3_CONF_VARS['FE']['tidy_option'] == 'output') {
2553 $GLOBALS['TT']->push('Tidy, output','');
2554 $this->content = $this->tidyHTML($this->content);
2555 $GLOBALS['TT']->pull();
2556 }
2557 // XHTML-clean the code, if flag set
2558 if ($this->doXHTML_cleaning() == 'output') {
2559 $GLOBALS['TT']->push('XHTML clean, output','');
2560 $XHTML_clean = t3lib_div::makeInstance('t3lib_parsehtml');
2561 $this->content = $XHTML_clean->XHTML_clean($this->content);
2562 $GLOBALS['TT']->pull();
2563 }
2564 // Fix local anchors in links, if flag set
2565 if ($this->doLocalAnchorFix() == 'output') {
2566 $GLOBALS['TT']->push('Local anchor fix, output','');
2567 $this->prefixLocalAnchorsWithScript();
2568 $GLOBALS['TT']->pull();
2569 }
2570
2571 // Hook for post-processing of page content before output:
2572 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-output'])) {
2573 $_params = array('pObj' => &$this);
2574 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-output'] as $_funcRef) {
2575 t3lib_div::callUserFunction($_funcRef,$_params,$this);
2576 }
2577 }
2578
2579 /* if ($this->beUserLogin && t3lib_div::_GP('ADMCMD_view')) { // This is a try to change target=_top to target=_self if pages are shown in the Web>View module...
2580 $this->content = str_replace('target="_top"','target="_self"',$this->content);
2581 $this->content = str_replace('target=_top','target="_self"',$this->content);
2582 }*/
2583
2584 // Send content-lenght header. 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...) we disable it!
2585 if ($this->config['config']['enableContentLengthHeader'] && !$this->isEXTincScript() && !$this->beUserLogin) {
2586 header('Content-Length: '.strlen($this->content));
2587 }
2588 }
2589
2590 /**
2591 * Send cache headers good for client/reverse proxy caching
2592 *
2593 * @return void
2594 * @co-author Ole Tange, Forbrugernes Hus, Denmark
2595 */
2596 function sendCacheHeaders() {
2597
2598 // Getting status whether we can send cache control headers for proxy caching:
2599 $doCache = $this->isStaticCacheble();
2600
2601 // 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...
2602 $loginsDeniedCfg = !$this->config['config']['sendCacheHeaders_onlyWhenLoginDeniedInBranch'] || !$this->loginAllowedInBranch;
2603
2604 // Finally, when backend users are logged in, do not send cache headers at all (Admin Panel might be displayed for instance).
2605 if ($doCache
2606 && !$this->beUserLogin
2607 && $loginsDeniedCfg) {
2608
2609 // Build headers:
2610 $headers = array(
2611 'Last-Modified: '.gmdate('D, d M Y H:i:s T', $this->register['SYS_LASTCHANGED']),
2612 'Expires: '.gmdate('D, d M Y H:i:s T', $this->cacheExpires),
2613 'ETag: '.md5($this->content),
2614 'Cache-Control: max-age='.($this->cacheExpires - $GLOBALS['EXEC_TIME']), // no-cache
2615 'Pragma: public',
2616 );
2617
2618 $this->isClientCachable = TRUE;
2619 } else {
2620 // Build headers:
2621 $headers = array(
2622 #'Last-Modified: '.gmdate('D, d M Y H:i:s T', $this->register['SYS_LASTCHANGED']),
2623 #'ETag: '.md5($this->content),
2624
2625 #'Cache-Control: no-cache',
2626 #'Pragma: no-cache',
2627 'Cache-Control: private', // Changed to this according to Ole Tange, FI.dk
2628 );
2629
2630 $this->isClientCachable = FALSE;
2631
2632 // Now, if a backend user is logged in, tell him in the Admin Panel log what the caching status would have been:
2633 if ($this->beUserLogin) {
2634 if ($doCache) {
2635 $GLOBALS['TT']->setTSlogMessage('Cache-headers with max-age "'.($this->cacheExpires - $GLOBALS['EXEC_TIME']).'" would have been sent');
2636 } else {
2637 $reasonMsg = '';
2638 $reasonMsg.= !$this->no_cache ? '' : 'Caching disabled (no_cache). ';
2639 $reasonMsg.= !$this->isINTincScript() ? '' : '*_INT object(s) on page. ';
2640 $reasonMsg.= !$this->isEXTincScript() ? '' : '*_EXT object(s) on page. ';
2641 $reasonMsg.= !is_array($this->fe_user->user) ? '' : 'Frontend user logged in. ';
2642 $GLOBALS['TT']->setTSlogMessage('Cache-headers would disable proxy caching! Reason(s): "'.$reasonMsg.'"',1);
2643 }
2644 }
2645 }
2646
2647 // Send headers:
2648 foreach($headers as $hL) {
2649 header($hL);
2650 }
2651 }
2652
2653 /**
2654 * Reporting status whether we can send cache control headers for proxy caching or publishing to static files
2655 *
2656 * Rules are:
2657 * no_cache cannot be set: If it is, the page might contain dynamic content and should never be cached.
2658 * There can be no USER_INT objects on the page ("isINTincScript()" / "isEXTincScript()") because they implicitly indicate dynamic content
2659 * 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)
2660 *
2661 * @return boolean
2662 */
2663 function isStaticCacheble() {
2664
2665 $doCache = !$this->no_cache
2666 && !$this->isINTincScript()
2667 && !$this->isEXTincScript()
2668 && !is_array($this->fe_user->user);
2669
2670 return $doCache;
2671 }
2672
2673 /**
2674 * Substitute various tokens in content. This should happen only if the content is not cached by proxies or client browsers.
2675 *
2676 * @return void
2677 */
2678 function contentStrReplace() {
2679 // Substitutes username mark with the username
2680 if ($this->fe_user->user['uid']) {
2681
2682 // User name:
2683 $token = trim($this->config['config']['USERNAME_substToken']);
2684 $this->content = str_replace($token ? $token : '<!--###USERNAME###-->',$this->fe_user->user['username'],$this->content);
2685
2686 // User uid (if configured):
2687 $token = trim($this->config['config']['USERUID_substToken']);
2688 if ($token) {
2689 $this->content = str_replace($token, $this->fe_user->user['uid'], $this->content);
2690 }
2691 }
2692 // Substitutes get_URL_ID in case of GET-fallback
2693 if ($this->getMethodUrlIdToken) {
2694 $this->content = str_replace($this->getMethodUrlIdToken, $this->fe_user->get_URL_ID, $this->content);
2695 }
2696 }
2697
2698 /**
2699 * Determines if any EXTincScripts should be included
2700 *
2701 * @return boolean True, if external php scripts should be included (set by PHP_SCRIPT_EXT cObjects)
2702 * @see tslib_cObj::PHP_SCRIPT
2703 */
2704 function isEXTincScript() {
2705 return is_array($this->config['EXTincScript']);
2706 }
2707
2708 /**
2709 * Stores session data for the front end user
2710 *
2711 * @return void
2712 */
2713 function storeSessionData() {
2714 $this->fe_user->storeSessionData();
2715 }
2716
2717 /**
2718 * Sets the parsetime of the page.
2719 *
2720 * @return void
2721 * @access private
2722 */
2723 function setParseTime() {
2724 // Compensates for the time consumed with Back end user initialization.
2725 $this->scriptParseTime = $GLOBALS['TT']->convertMicrotime($GLOBALS['TYPO3_MISC']['microtime_end'])
2726 - $GLOBALS['TT']->convertMicrotime($GLOBALS['TYPO3_MISC']['microtime_start'])
2727 - ($GLOBALS['TT']->convertMicrotime($GLOBALS['TYPO3_MISC']['microtime_BE_USER_end'])-$GLOBALS['TT']->convertMicrotime($GLOBALS['TYPO3_MISC']['microtime_BE_USER_start']));
2728 }
2729
2730 /**
2731 * Saves hit statistics
2732 *
2733 * @return void
2734 */
2735 function statistics() {
2736 if ($this->config['config']['stat'] &&
2737 (!strcmp('',$this->config['config']['stat_typeNumList']) || t3lib_div::inList(str_replace(' ','',$this->config['config']['stat_typeNumList']), $this->type)) &&
2738 (!$this->config['config']['stat_excludeBEuserHits'] || !$this->beUserLogin) &&
2739 (!$this->config['config']['stat_excludeIPList'] || !t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'),str_replace(' ','',$this->config['config']['stat_excludeIPList'])))) {
2740
2741 $GLOBALS['TT']->push('Stat');
2742 if (t3lib_extMgm::isLoaded('sys_stat') && $this->config['config']['stat_mysql']) {
2743
2744 // Jumpurl:
2745 $sword = t3lib_div::_GP('sword');
2746 if ($sword) {
2747 $jumpurl_msg = 'sword:'.$sword;
2748 } elseif ($this->jumpurl) {
2749 $jumpurl_msg = 'jumpurl:'.$this->jumpurl;
2750 } else {
2751 $jumpurl_msg = '';
2752 }
2753
2754 // Flags: bits: 0 = BE_user, 1=Cached page?
2755 $flags=0;
2756 if ($this->beUserLogin) {$flags|=1;}
2757 if ($this->cacheContentFlag) {$flags|=2;}
2758
2759 // Ref url:
2760 $refUrl = t3lib_div::getIndpEnv('HTTP_REFERER');
2761 $thisUrl = t3lib_div::getIndpEnv('TYPO3_REQUEST_DIR');
2762 if (t3lib_div::isFirstPartOfStr($refUrl,$thisUrl)) {
2763 $refUrl='[LOCAL]';
2764 }
2765
2766 $insertFields = array(
2767 'page_id' => intval($this->id), // id
2768 'page_type' => intval($this->type), // type
2769 'jumpurl' => $jumpurl_msg, // jumpurl message
2770 'feuser_id' => $this->fe_user->user['uid'], // fe_user id, integer
2771 'cookie' => $this->fe_user->id, // cookie as set or retrieve. If people has cookies disabled this will vary all the time...
2772 '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...
2773 'rl0' => $this->config['rootLine'][0]['uid'], // RootLevel 0 uid
2774 'rl1' => $this->config['rootLine'][1]['uid'], // RootLevel 1 uid
2775 'client_browser' => $GLOBALS['CLIENT']['BROWSER'], // Client browser (net, msie, opera)
2776 'client_version' => $GLOBALS['CLIENT']['VERSION'], // Client version (double value)
2777 'client_os' => $GLOBALS['CLIENT']['SYSTEM'], // Client Operating system (win, mac, unix)
2778 'parsetime' => intval($this->scriptParseTime), // Parsetime for the page.
2779 'flags' => $flags, // Flags: Is be user logged in? Is page cached?
2780 'IP' => t3lib_div::getIndpEnv('REMOTE_ADDR'), // Remote IP address
2781 'host' => t3lib_div::getIndpEnv('REMOTE_HOST'), // Remote Host Address
2782 'referer' => $refUrl, // Referer URL
2783 'browser' => t3lib_div::getIndpEnv('HTTP_USER_AGENT'), // User Agent Info.
2784 'tstamp' => $GLOBALS['EXEC_TIME'] // Time stamp
2785 );
2786
2787 // Hook for preprocessing the list of fields to insert into sys_stat:
2788 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['sys_stat-PreProcClass'])) {
2789 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['sys_stat-PreProcClass'] as $_classRef) {
2790 $_procObj = &t3lib_div::getUserObj($_classRef);
2791 $insertFields = $_procObj->sysstat_preProcessFields($insertFields,$this);
2792 }
2793 }
2794
2795
2796 $GLOBALS['TT']->push('Store SQL');
2797 $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_stat', $insertFields);
2798 $GLOBALS['TT']->pull();
2799 }
2800
2801 // Apache:
2802 if ($this->config['config']['stat_apache'] && $this->config['stat_vars']['pageName']) {
2803 if (@is_file($this->config['stat_vars']['logFile'])) {
2804 $LogLine = ((t3lib_div::getIndpEnv('REMOTE_HOST') && !$this->config['config']['stat_apache_noHost']) ? t3lib_div::getIndpEnv('REMOTE_HOST') : t3lib_div::getIndpEnv('REMOTE_ADDR')).' - - '.Date('[d/M/Y:H:i:s +0000]',$GLOBALS['EXEC_TIME']).' "GET '.$this->config['stat_vars']['pageName'].' HTTP/1.1" 200 '.strlen($this->content);
2805 if (!$this->config['config']['stat_apache_notExtended']) {
2806 $LogLine.= ' "'.t3lib_div::getIndpEnv('HTTP_REFERER').'" "'.t3lib_div::getIndpEnv('HTTP_USER_AGENT').'"';
2807 }
2808
2809 switch($this->TYPO3_CONF_VARS['FE']['logfile_write']) {
2810 case 'fputs':
2811 $GLOBALS['TT']->push('Write to log file (fputs)');
2812 $logfilehandle = fopen($this->config['stat_vars']['logFile'], 'a');
2813 fputs($logfilehandle, $LogLine."\n");
2814 @fclose($logfilehandle);
2815 $GLOBALS['TT']->pull();
2816 break;
2817 default:
2818 $GLOBALS['TT']->push('Write to log file (echo)');
2819 if (TYPO3_OS=="WIN") {
2820 $execCmd = 'echo '.$LogLine.' >> '.$this->config['stat_vars']['logFile'];
2821 } else {
2822 $execCmd = 'echo "'.addslashes($LogLine).'" >> '.$this->config['stat_vars']['logFile'];
2823 }
2824 exec($execCmd);
2825 $GLOBALS['TT']->pull();
2826 break;
2827 }
2828
2829 $GLOBALS['TT']->setTSlogMessage('Writing to logfile: OK',0);
2830 } else {
2831 $GLOBALS['TT']->setTSlogMessage('Writing to logfile: Error - logFile did not exist or OS is Windows!',3);
2832 }
2833 }
2834 $GLOBALS['TT']->pull();
2835 }
2836 }
2837
2838 /**
2839 * Outputs preview info.
2840 *
2841 * @return void
2842 */
2843 function previewInfo() {
2844 if ($this->fePreview) {
2845 $stdMsg = '
2846 <br />
2847 <div align="center">
2848 <table border="3" bordercolor="black" cellpadding="2" bgcolor="red">
2849 <tr>
2850 <td>&nbsp;&nbsp;<font face="Verdana" size="1"><b>PREVIEW!</b></font>&nbsp;&nbsp;</td>
2851 </tr>
2852 </table>
2853 </div>';
2854 $temp_content = $this->config['config']['message_preview'] ? $this->config['config']['message_preview'] : $stdMsg;
2855 echo $temp_content;
2856 }
2857 }
2858
2859 /**
2860 * End-Of-Frontend hook
2861 *
2862 * @return void
2863 */
2864 function hook_eofe() {
2865
2866 // Call hook for end-of-frontend processing:
2867 if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['hook_eofe'])) {
2868 $_params = array('pObj' => &$this);
2869 foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['hook_eofe'] as $_funcRef) {
2870 t3lib_div::callUserFunction($_funcRef,$_params,$this);
2871 }
2872 }
2873 }
2874
2875 /**
2876 * Returns a link to the login screen with redirect to the front-end
2877 *
2878 * @return string HTML, a tag for a link to the backend.
2879 */
2880 function beLoginLinkIPList() {
2881 if ($this->config['config']['beLoginLinkIPList']) {
2882 if (t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $this->config['config']['beLoginLinkIPList'])) {
2883 $label = !$this->beUserLogin ? $this->config['config']['beLoginLinkIPList_login'] : $this->config['config']['beLoginLinkIPList_logout'];
2884 if ($label) {
2885 if (!$this->beUserLogin) {
2886 $link = '<a href="'.htmlspecialchars(TYPO3_mainDir.'index.php?redirect_url='.rawurlencode(t3lib_div::getIndpEnv("REQUEST_URI"))).'">'.$label.'</a>';
2887 } else {
2888 $link = '<a href="'.htmlspecialchars(TYPO3_mainDir.'index.php?L=OUT&redirect_url='.rawurlencode(t3lib_div::getIndpEnv("REQUEST_URI"))).'">'.$label.'</a>';
2889 }
2890 return $link;
2891 }
2892 }
2893 }
2894 }
2895
2896