[BUGFIX] Escape regex chars when building sWordRegEx
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Page / PageGenerator.php
1 <?php
2 namespace TYPO3\CMS\Frontend\Page;
3
4 /**
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Utility\GeneralUtility;
18 use TYPO3\CMS\Extbase\Service\TypoScriptService;
19 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
20
21 /**
22 * Class for starting TypoScript page generation
23 *
24 * The class is not instantiated as an objects but called directly with the "::" operator.
25 * eg: TSpagegen::pagegenInit()
26 *
27 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
28 */
29 class PageGenerator {
30
31 /**
32 * Do not render title tag
33 * Typoscript setting: [config][noPageTitle]
34 */
35 const NO_PAGE_TITLE = 2;
36
37 /**
38 * Setting some vars in TSFE, primarily based on TypoScript config settings.
39 *
40 * @return void
41 */
42 static public function pagegenInit() {
43 if ($GLOBALS['TSFE']->page['content_from_pid'] > 0) {
44 // make REAL copy of TSFE object - not reference!
45 $temp_copy_TSFE = clone $GLOBALS['TSFE'];
46 // Set ->id to the content_from_pid value - we are going to evaluate this pid as was it a given id for a page-display!
47 $temp_copy_TSFE->id = $GLOBALS['TSFE']->page['content_from_pid'];
48 $temp_copy_TSFE->MP = '';
49 $temp_copy_TSFE->getPageAndRootlineWithDomain($GLOBALS['TSFE']->config['config']['content_from_pid_allowOutsideDomain'] ? 0 : $GLOBALS['TSFE']->domainStartPage);
50 $GLOBALS['TSFE']->contentPid = (int)$temp_copy_TSFE->id;
51 unset($temp_copy_TSFE);
52 }
53 if ($GLOBALS['TSFE']->config['config']['MP_defaults']) {
54 $temp_parts = GeneralUtility::trimExplode('|', $GLOBALS['TSFE']->config['config']['MP_defaults'], TRUE);
55 foreach ($temp_parts as $temp_p) {
56 list($temp_idP, $temp_MPp) = explode(':', $temp_p, 2);
57 $temp_ids = GeneralUtility::intExplode(',', $temp_idP);
58 foreach ($temp_ids as $temp_id) {
59 $GLOBALS['TSFE']->MP_defaults[$temp_id] = $temp_MPp;
60 }
61 }
62 }
63 // Global vars...
64 $GLOBALS['TSFE']->indexedDocTitle = $GLOBALS['TSFE']->page['title'];
65 $GLOBALS['TSFE']->debug = '' . $GLOBALS['TSFE']->config['config']['debug'];
66 // Base url:
67 if (isset($GLOBALS['TSFE']->config['config']['baseURL'])) {
68 $GLOBALS['TSFE']->baseUrl = $GLOBALS['TSFE']->config['config']['baseURL'];
69 $GLOBALS['TSFE']->anchorPrefix = substr(GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL'), strlen(GeneralUtility::getIndpEnv('TYPO3_SITE_URL')));
70 }
71 // Internal and External target defaults
72 $GLOBALS['TSFE']->intTarget = '' . $GLOBALS['TSFE']->config['config']['intTarget'];
73 $GLOBALS['TSFE']->extTarget = '' . $GLOBALS['TSFE']->config['config']['extTarget'];
74 $GLOBALS['TSFE']->fileTarget = '' . $GLOBALS['TSFE']->config['config']['fileTarget'];
75 if ($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses'] === 'ascii') {
76 $GLOBALS['TSFE']->spamProtectEmailAddresses = 'ascii';
77 } else {
78 $GLOBALS['TSFE']->spamProtectEmailAddresses = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses'], -10, 10, 0);
79 }
80 $GLOBALS['TSFE']->absRefPrefix = $GLOBALS['TSFE']->config['config']['absRefPrefix'] ? trim($GLOBALS['TSFE']->config['config']['absRefPrefix']) : '';
81 if ($GLOBALS['TSFE']->type && $GLOBALS['TSFE']->config['config']['frameReloadIfNotInFrameset']) {
82 $tdlLD = $GLOBALS['TSFE']->tmpl->linkData($GLOBALS['TSFE']->page, '_top', $GLOBALS['TSFE']->no_cache, '');
83 $GLOBALS['TSFE']->additionalJavaScript['JSCode'] .= 'if(!parent.' . trim($GLOBALS['TSFE']->sPre) . ' && !parent.view_frame) top.location.href="' . $GLOBALS['TSFE']->baseUrlWrap($tdlLD['totalURL']) . '"';
84 }
85 $GLOBALS['TSFE']->compensateFieldWidth = '' . $GLOBALS['TSFE']->config['config']['compensateFieldWidth'];
86 $GLOBALS['TSFE']->lockFilePath = '' . $GLOBALS['TSFE']->config['config']['lockFilePath'];
87 $GLOBALS['TSFE']->lockFilePath = $GLOBALS['TSFE']->lockFilePath ?: $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'];
88 $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_noScaleUp'] = isset($GLOBALS['TSFE']->config['config']['noScaleUp']) ? '' . $GLOBALS['TSFE']->config['config']['noScaleUp'] : $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_noScaleUp'];
89 $GLOBALS['TSFE']->TYPO3_CONF_VARS['GFX']['im_noScaleUp'] = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_noScaleUp'];
90 $GLOBALS['TSFE']->ATagParams = trim($GLOBALS['TSFE']->config['config']['ATagParams']) ? ' ' . trim($GLOBALS['TSFE']->config['config']['ATagParams']) : '';
91 if ($GLOBALS['TSFE']->config['config']['setJS_mouseOver']) {
92 $GLOBALS['TSFE']->setJS('mouseOver');
93 }
94 if ($GLOBALS['TSFE']->config['config']['setJS_openPic']) {
95 $GLOBALS['TSFE']->setJS('openPic');
96 }
97 static::initializeSearchWordDataInTsfe();
98 // linkVars
99 $GLOBALS['TSFE']->calculateLinkVars();
100 // dtdAllowsFrames indicates whether to use the target attribute in links
101 $GLOBALS['TSFE']->dtdAllowsFrames = FALSE;
102 if ($GLOBALS['TSFE']->config['config']['doctype']) {
103 if (in_array(
104 (string) $GLOBALS['TSFE']->config['config']['doctype'],
105 array('xhtml_trans', 'xhtml_frames', 'xhtml_basic', 'xhtml_2', 'html5'),
106 TRUE)
107 ) {
108 $GLOBALS['TSFE']->dtdAllowsFrames = TRUE;
109 }
110 } else {
111 $GLOBALS['TSFE']->dtdAllowsFrames = TRUE;
112 }
113 // Setting XHTML-doctype from doctype
114 if (!$GLOBALS['TSFE']->config['config']['xhtmlDoctype']) {
115 $GLOBALS['TSFE']->config['config']['xhtmlDoctype'] = $GLOBALS['TSFE']->config['config']['doctype'];
116 }
117 if ($GLOBALS['TSFE']->config['config']['xhtmlDoctype']) {
118 $GLOBALS['TSFE']->xhtmlDoctype = $GLOBALS['TSFE']->config['config']['xhtmlDoctype'];
119 // Checking XHTML-docytpe
120 switch ((string) $GLOBALS['TSFE']->config['config']['xhtmlDoctype']) {
121 case 'xhtml_trans':
122
123 case 'xhtml_strict':
124
125 case 'xhtml_frames':
126 $GLOBALS['TSFE']->xhtmlVersion = 100;
127 break;
128 case 'xhtml_basic':
129 $GLOBALS['TSFE']->xhtmlVersion = 105;
130 break;
131 case 'xhtml_11':
132
133 case 'xhtml+rdfa_10':
134 $GLOBALS['TSFE']->xhtmlVersion = 110;
135 break;
136 case 'xhtml_2':
137 $GLOBALS['TSFE']->xhtmlVersion = 200;
138 break;
139 default:
140 $GLOBALS['TSFE']->getPageRenderer()->setRenderXhtml(FALSE);
141 $GLOBALS['TSFE']->xhtmlDoctype = '';
142 $GLOBALS['TSFE']->xhtmlVersion = 0;
143 }
144 } else {
145 $GLOBALS['TSFE']->getPageRenderer()->setRenderXhtml(FALSE);
146 }
147 }
148
149 /**
150 * Returns an array with files to include. These files are the ones set up in TypoScript config.
151 *
152 * @return array Files to include. Paths are relative to PATH_site.
153 */
154 static public function getIncFiles() {
155 $incFilesArray = array();
156 // Get files from config.includeLibrary
157 $includeLibrary = trim('' . $GLOBALS['TSFE']->config['config']['includeLibrary']);
158 if ($includeLibrary) {
159 $incFile = $GLOBALS['TSFE']->tmpl->getFileName($includeLibrary);
160 if ($incFile) {
161 $incFilesArray[] = $incFile;
162 }
163 }
164 if (is_array($GLOBALS['TSFE']->pSetup['includeLibs.'])) {
165 $incLibs = $GLOBALS['TSFE']->pSetup['includeLibs.'];
166 } else {
167 $incLibs = array();
168 }
169 if (is_array($GLOBALS['TSFE']->tmpl->setup['includeLibs.'])) {
170 // toplevel 'includeLibs' is added to the PAGE.includeLibs. In that way, PAGE-libs get first priority, because if the key already exist, it's not altered. (Due to investigation by me)
171 $incLibs += $GLOBALS['TSFE']->tmpl->setup['includeLibs.'];
172 }
173 if (count($incLibs)) {
174 foreach ($incLibs as $theLib) {
175 if (!is_array($theLib) && ($incFile = $GLOBALS['TSFE']->tmpl->getFileName($theLib))) {
176 $incFilesArray[] = $incFile;
177 }
178 }
179 }
180 return $incFilesArray;
181 }
182
183 /**
184 * Processing JavaScript handlers
185 *
186 * @return array Array with a) a JavaScript section with event handlers and variables set and b) an array with attributes for the body tag.
187 */
188 static public function JSeventFunctions() {
189 $functions = array();
190 $setEvents = array();
191 $setBody = array();
192 foreach ($GLOBALS['TSFE']->JSeventFuncCalls as $event => $handlers) {
193 if (count($handlers)) {
194 $functions[] = ' function T3_' . $event . 'Wrapper(e) { ' . implode(' ', $handlers) . ' }';
195 $setEvents[] = ' document.' . $event . '=T3_' . $event . 'Wrapper;';
196 if ($event == 'onload') {
197 // Dubiuos double setting breaks on some browser - do we need it?
198 $setBody[] = 'onload="T3_onloadWrapper();"';
199 }
200 }
201 }
202 return array(count($functions) ? implode(LF, $functions) . LF . implode(LF, $setEvents) : '', $setBody);
203 }
204
205 /**
206 * Rendering the page content
207 *
208 * @return void
209 */
210 static public function renderContent() {
211 // PAGE CONTENT
212 $GLOBALS['TT']->incStackPointer();
213 $GLOBALS['TT']->push($GLOBALS['TSFE']->sPre, 'PAGE');
214 $pageContent = $GLOBALS['TSFE']->cObj->cObjGet($GLOBALS['TSFE']->pSetup);
215 if ($GLOBALS['TSFE']->pSetup['wrap']) {
216 $pageContent = $GLOBALS['TSFE']->cObj->wrap($pageContent, $GLOBALS['TSFE']->pSetup['wrap']);
217 }
218 if ($GLOBALS['TSFE']->pSetup['stdWrap.']) {
219 $pageContent = $GLOBALS['TSFE']->cObj->stdWrap($pageContent, $GLOBALS['TSFE']->pSetup['stdWrap.']);
220 }
221 // PAGE HEADER (after content - maybe JS is inserted!
222 // if 'disableAllHeaderCode' is set, all the header-code is discarded!
223 if ($GLOBALS['TSFE']->config['config']['disableAllHeaderCode']) {
224 $GLOBALS['TSFE']->content = $pageContent;
225 } else {
226 self::renderContentWithHeader($pageContent);
227 }
228 $GLOBALS['TT']->pull($GLOBALS['TT']->LR ? $GLOBALS['TSFE']->content : '');
229 $GLOBALS['TT']->decStackPointer();
230 }
231
232 /**
233 * Rendering normal HTML-page with header by wrapping the generated content ($pageContent) in body-tags and setting the header accordingly.
234 *
235 * @param string $pageContent The page content which TypoScript objects has generated
236 * @return void
237 */
238 static public function renderContentWithHeader($pageContent) {
239 /** @var $pageRenderer \TYPO3\CMS\Core\Page\PageRenderer */
240 $pageRenderer = $GLOBALS['TSFE']->getPageRenderer();
241 if ($GLOBALS['TSFE']->config['config']['moveJsFromHeaderToFooter']) {
242 $pageRenderer->enableMoveJsFromHeaderToFooter();
243 }
244 if ($GLOBALS['TSFE']->config['config']['pageRendererTemplateFile']) {
245 $file = $GLOBALS['TSFE']->tmpl->getFileName($GLOBALS['TSFE']->config['config']['pageRendererTemplateFile']);
246 if ($file) {
247 $pageRenderer->setTemplateFile($file);
248 }
249 }
250 $headerComment = $GLOBALS['TSFE']->config['config']['headerComment'];
251 if (trim($headerComment)) {
252 $pageRenderer->addInlineComment(TAB . str_replace(LF, (LF . TAB), trim($headerComment)) . LF);
253 }
254 // Setting charset:
255 $theCharset = $GLOBALS['TSFE']->metaCharset;
256 // Reset the content variables:
257 $GLOBALS['TSFE']->content = '';
258 $htmlTagAttributes = array();
259 $htmlLang = $GLOBALS['TSFE']->config['config']['htmlTag_langKey'] ?: 'en';
260 // Set content direction: (More info: http://www.tau.ac.il/~danon/Hebrew/HTML_and_Hebrew.html)
261 if ($GLOBALS['TSFE']->config['config']['htmlTag_dir']) {
262 $htmlTagAttributes['dir'] = htmlspecialchars($GLOBALS['TSFE']->config['config']['htmlTag_dir']);
263 }
264 // Setting document type:
265 $docTypeParts = array();
266 $xmlDocument = TRUE;
267 // Part 1: XML prologue
268 switch ((string) $GLOBALS['TSFE']->config['config']['xmlprologue']) {
269 case 'none':
270 $xmlDocument = FALSE;
271 $GLOBALS['TSFE']->config['config']['xhtml_cleaning'] = 'none';
272 break;
273 case 'xml_10':
274 $docTypeParts[] = '<?xml version="1.0" encoding="' . $theCharset . '"?>';
275 break;
276 case 'xml_11':
277 $docTypeParts[] = '<?xml version="1.1" encoding="' . $theCharset . '"?>';
278 break;
279 case '':
280 if ($GLOBALS['TSFE']->xhtmlVersion) {
281 $docTypeParts[] = '<?xml version="1.0" encoding="' . $theCharset . '"?>';
282 }
283 break;
284 default:
285 $docTypeParts[] = $GLOBALS['TSFE']->config['config']['xmlprologue'];
286 }
287 // Part 2: DTD
288 $doctype = $GLOBALS['TSFE']->config['config']['doctype'];
289 if ($doctype) {
290 switch ($doctype) {
291 case 'xhtml_trans':
292 $docTypeParts[] = '<!DOCTYPE html
293 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
294 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
295 break;
296 case 'xhtml_strict':
297 $docTypeParts[] = '<!DOCTYPE html
298 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
299 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
300 break;
301 case 'xhtml_frames':
302 $docTypeParts[] = '<!DOCTYPE html
303 PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
304 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">';
305 break;
306 case 'xhtml_basic':
307 $docTypeParts[] = '<!DOCTYPE html
308 PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
309 "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">';
310 break;
311 case 'xhtml_11':
312 $docTypeParts[] = '<!DOCTYPE html
313 PUBLIC "-//W3C//DTD XHTML 1.1//EN"
314 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';
315 break;
316 case 'xhtml_2':
317 $docTypeParts[] = '<!DOCTYPE html
318 PUBLIC "-//W3C//DTD XHTML 2.0//EN"
319 "http://www.w3.org/TR/xhtml2/DTD/xhtml2.dtd">';
320 break;
321 case 'xhtml+rdfa_10':
322 $docTypeParts[] = '<!DOCTYPE html
323 PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
324 "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">';
325 break;
326 case 'html5':
327 $docTypeParts[] = '<!DOCTYPE html>';
328 if ($xmlDocument) {
329 $pageRenderer->setMetaCharsetTag('<meta charset="|" />');
330 } else {
331 $pageRenderer->setMetaCharsetTag('<meta charset="|">');
332 }
333 break;
334 case 'none':
335 break;
336 default:
337 $docTypeParts[] = $doctype;
338 }
339 } else {
340 $docTypeParts[] = '<!DOCTYPE html>';
341 if ($xmlDocument){
342 $pageRenderer->setMetaCharsetTag('<meta charset="|" />');
343 } else {
344 $pageRenderer->setMetaCharsetTag('<meta charset="|">');
345 }
346 }
347 if ($GLOBALS['TSFE']->xhtmlVersion) {
348 $htmlTagAttributes['xml:lang'] = $htmlLang;
349 }
350 if ($GLOBALS['TSFE']->xhtmlVersion < 110 || $doctype === 'html5') {
351 $htmlTagAttributes['lang'] = $htmlLang;
352 }
353 if ($GLOBALS['TSFE']->xhtmlVersion || $doctype === 'html5' && $xmlDocument) {
354 // We add this to HTML5 to achieve a slightly better backwards compatibility
355 $htmlTagAttributes['xmlns'] = 'http://www.w3.org/1999/xhtml';
356 if (is_array($GLOBALS['TSFE']->config['config']['namespaces.'])) {
357 foreach ($GLOBALS['TSFE']->config['config']['namespaces.'] as $prefix => $uri) {
358 // $uri gets htmlspecialchared later
359 $htmlTagAttributes['xmlns:' . htmlspecialchars($prefix)] = $uri;
360 }
361 }
362 }
363 // Swap XML and doctype order around (for MSIE / Opera standards compliance)
364 if ($GLOBALS['TSFE']->config['config']['doctypeSwitch']) {
365 $docTypeParts = array_reverse($docTypeParts);
366 }
367 // Adding doctype parts:
368 if (count($docTypeParts)) {
369 $pageRenderer->setXmlPrologAndDocType(implode(LF, $docTypeParts));
370 }
371 // Begin header section:
372 if ($GLOBALS['TSFE']->config['config']['htmlTag_setParams'] !== 'none') {
373 $_attr = $GLOBALS['TSFE']->config['config']['htmlTag_setParams'] ? $GLOBALS['TSFE']->config['config']['htmlTag_setParams'] : GeneralUtility::implodeAttributes($htmlTagAttributes);
374 } else {
375 $_attr = '';
376 }
377 $htmlTag = '<html' . ($_attr ? ' ' . $_attr : '') . '>';
378 if (isset($GLOBALS['TSFE']->config['config']['htmlTag_stdWrap.'])) {
379 $htmlTag = $GLOBALS['TSFE']->cObj->stdWrap($htmlTag, $GLOBALS['TSFE']->config['config']['htmlTag_stdWrap.']);
380 }
381 $pageRenderer->setHtmlTag($htmlTag);
382 // Head tag:
383 $headTag = $GLOBALS['TSFE']->pSetup['headTag'] ?: '<head>';
384 $pageRenderer->setHeadTag($headTag);
385 // Setting charset meta tag:
386 $pageRenderer->setCharSet($theCharset);
387 $pageRenderer->addInlineComment(' This website is powered by TYPO3 - inspiring people to share!
388 TYPO3 is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.
389 TYPO3 is copyright ' . TYPO3_copyright_year . ' of Kasper Skaarhoj. Extensions are copyright of their respective owners.
390 Information and contribution at ' . TYPO3_URL_ORG . '
391 ');
392 if ($GLOBALS['TSFE']->baseUrl) {
393 $pageRenderer->setBaseUrl($GLOBALS['TSFE']->baseUrl);
394 }
395 if ($GLOBALS['TSFE']->pSetup['shortcutIcon']) {
396 $favIcon = $GLOBALS['TSFE']->tmpl->getFileName($GLOBALS['TSFE']->pSetup['shortcutIcon']);
397 if (is_file(PATH_site . $favIcon)) {
398 if (function_exists('finfo_open')) {
399 if ($finfo = @finfo_open(FILEINFO_MIME)) {
400 $iconMimeType = ' type="' . finfo_file($finfo, (PATH_site . $favIcon)) . '"';
401 finfo_close($finfo);
402 $pageRenderer->setIconMimeType($iconMimeType);
403 }
404 }
405 $pageRenderer->setFavIcon(GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . $favIcon);
406 }
407 }
408 // Including CSS files
409 if (is_array($GLOBALS['TSFE']->tmpl->setup['plugin.'])) {
410 $temp_styleLines = array();
411 foreach ($GLOBALS['TSFE']->tmpl->setup['plugin.'] as $key => $iCSScode) {
412 if (is_array($iCSScode)) {
413 if ($iCSScode['_CSS_DEFAULT_STYLE'] && empty($GLOBALS['TSFE']->config['config']['removeDefaultCss'])) {
414 if (isset($iCSScode['_CSS_DEFAULT_STYLE.'])) {
415 $cssDefaultStyle = $GLOBALS['TSFE']->cObj->stdWrap($iCSScode['_CSS_DEFAULT_STYLE'], $iCSScode['_CSS_DEFAULT_STYLE.']);
416 } else {
417 $cssDefaultStyle = $iCSScode['_CSS_DEFAULT_STYLE'];
418 }
419 $temp_styleLines[] = '/* default styles for extension "' . substr($key, 0, -1) . '" */' . LF . $cssDefaultStyle;
420 }
421 if ($iCSScode['_CSS_PAGE_STYLE'] && empty($GLOBALS['TSFE']->config['config']['removePageCss'])) {
422 $cssPageStyle = implode(LF, $iCSScode['_CSS_PAGE_STYLE']);
423 if (isset($iCSScode['_CSS_PAGE_STYLE.'])) {
424 $cssPageStyle = $GLOBALS['TSFE']->cObj->stdWrap($cssPageStyle, $iCSScode['_CSS_PAGE_STYLE.']);
425 }
426 $temp_styleLines[] = '/* specific page styles for extension "' . substr($key, 0, -1) . '" */' . LF . $cssPageStyle;
427 }
428 }
429 }
430 if (count($temp_styleLines)) {
431 if ($GLOBALS['TSFE']->config['config']['inlineStyle2TempFile']) {
432 $pageRenderer->addCssFile(self::inline2TempFile(implode(LF, $temp_styleLines), 'css'));
433 } else {
434 $pageRenderer->addCssInlineBlock('TSFEinlineStyle', implode(LF, $temp_styleLines));
435 }
436 }
437 }
438 if ($GLOBALS['TSFE']->pSetup['stylesheet']) {
439 $ss = $GLOBALS['TSFE']->tmpl->getFileName($GLOBALS['TSFE']->pSetup['stylesheet']);
440 if ($ss) {
441 $pageRenderer->addCssFile($ss);
442 }
443 }
444 /**********************************************************************/
445 /* config.includeCSS / config.includeCSSLibs
446 /**********************************************************************/
447 if (is_array($GLOBALS['TSFE']->pSetup['includeCSS.'])) {
448 foreach ($GLOBALS['TSFE']->pSetup['includeCSS.'] as $key => $CSSfile) {
449 if (!is_array($CSSfile)) {
450 $cssFileConfig = &$GLOBALS['TSFE']->pSetup['includeCSS.'][$key . '.'];
451 if (isset($cssFileConfig['if.']) && !$GLOBALS['TSFE']->cObj->checkIf($cssFileConfig['if.'])) {
452 continue;
453 }
454 $ss = $cssFileConfig['external'] ? $CSSfile : $GLOBALS['TSFE']->tmpl->getFileName($CSSfile);
455 if ($ss) {
456 if ($cssFileConfig['import']) {
457 if (!$cssFileConfig['external'] && $ss[0] !== '/') {
458 // To fix MSIE 6 that cannot handle these as relative paths (according to Ben v Ende)
459 $ss = GeneralUtility::dirname(GeneralUtility::getIndpEnv('SCRIPT_NAME')) . '/' . $ss;
460 }
461 $pageRenderer->addCssInlineBlock('import_' . $key, '@import url("' . htmlspecialchars($ss) . '") ' . htmlspecialchars($cssFileConfig['media']) . ';', empty($cssFileConfig['disableCompression']), $cssFileConfig['forceOnTop'] ? TRUE : FALSE, '');
462 } else {
463 $pageRenderer->addCssFile(
464 $ss,
465 $cssFileConfig['alternate'] ? 'alternate stylesheet' : 'stylesheet',
466 $cssFileConfig['media'] ?: 'all',
467 $cssFileConfig['title'] ?: '',
468 empty($cssFileConfig['disableCompression']),
469 $cssFileConfig['forceOnTop'] ? TRUE : FALSE,
470 $cssFileConfig['allWrap'],
471 $cssFileConfig['excludeFromConcatenation'] ? TRUE : FALSE,
472 $cssFileConfig['allWrap.']['splitChar']
473 );
474 unset($cssFileConfig);
475 }
476 }
477 }
478 }
479 }
480 if (is_array($GLOBALS['TSFE']->pSetup['includeCSSLibs.'])) {
481 foreach ($GLOBALS['TSFE']->pSetup['includeCSSLibs.'] as $key => $CSSfile) {
482 if (!is_array($CSSfile)) {
483 $cssFileConfig = &$GLOBALS['TSFE']->pSetup['includeCSSLibs.'][$key . '.'];
484 if (isset($cssFileConfig['if.']) && !$GLOBALS['TSFE']->cObj->checkIf($cssFileConfig['if.'])) {
485 continue;
486 }
487 $ss = $cssFileConfig['external'] ? $CSSfile : $GLOBALS['TSFE']->tmpl->getFileName($CSSfile);
488 if ($ss) {
489 if ($cssFileConfig['import']) {
490 if (!$cssFileConfig['external'] && $ss[0] !== '/') {
491 // To fix MSIE 6 that cannot handle these as relative paths (according to Ben v Ende)
492 $ss = GeneralUtility::dirname(GeneralUtility::getIndpEnv('SCRIPT_NAME')) . '/' . $ss;
493 }
494 $pageRenderer->addCssInlineBlock('import_' . $key, '@import url("' . htmlspecialchars($ss) . '") ' . htmlspecialchars($cssFileConfig['media']) . ';', empty($cssFileConfig['disableCompression']), $cssFileConfig['forceOnTop'] ? TRUE : FALSE, '');
495 } else {
496 $pageRenderer->addCssLibrary(
497 $ss,
498 $cssFileConfig['alternate'] ? 'alternate stylesheet' : 'stylesheet',
499 $cssFileConfig['media'] ?: 'all',
500 $cssFileConfig['title'] ?: '',
501 empty($cssFileConfig['disableCompression']),
502 $cssFileConfig['forceOnTop'] ? TRUE : FALSE,
503 $cssFileConfig['allWrap'],
504 $cssFileConfig['excludeFromConcatenation'] ? TRUE : FALSE,
505 $cssFileConfig['allWrap.']['splitChar']
506 );
507 unset($cssFileConfig);
508 }
509 }
510 }
511 }
512 }
513
514 // Stylesheets
515 $style = '';
516 if ($GLOBALS['TSFE']->pSetup['insertClassesFromRTE']) {
517 $pageTSConfig = $GLOBALS['TSFE']->getPagesTSconfig();
518 $RTEclasses = $pageTSConfig['RTE.']['classes.'];
519 if (is_array($RTEclasses)) {
520 foreach ($RTEclasses as $RTEclassName => $RTEvalueArray) {
521 if ($RTEvalueArray['value']) {
522 $style .= '
523 .' . substr($RTEclassName, 0, -1) . ' {' . $RTEvalueArray['value'] . '}';
524 }
525 }
526 }
527 if ($GLOBALS['TSFE']->pSetup['insertClassesFromRTE.']['add_mainStyleOverrideDefs'] && is_array($pageTSConfig['RTE.']['default.']['mainStyleOverride_add.'])) {
528 $mSOa_tList = GeneralUtility::trimExplode(',', strtoupper($GLOBALS['TSFE']->pSetup['insertClassesFromRTE.']['add_mainStyleOverrideDefs']), TRUE);
529 foreach ($pageTSConfig['RTE.']['default.']['mainStyleOverride_add.'] as $mSOa_key => $mSOa_value) {
530 if (!is_array($mSOa_value) && (in_array('*', $mSOa_tList) || in_array($mSOa_key, $mSOa_tList))) {
531 $style .= '
532 ' . $mSOa_key . ' {' . $mSOa_value . '}';
533 }
534 }
535 }
536 }
537 // Setting body tag margins in CSS:
538 if (isset($GLOBALS['TSFE']->pSetup['bodyTagMargins']) && $GLOBALS['TSFE']->pSetup['bodyTagMargins.']['useCSS']) {
539 $margins = (int)$GLOBALS['TSFE']->pSetup['bodyTagMargins'];
540 $style .= '
541 BODY {margin: ' . $margins . 'px ' . $margins . 'px ' . $margins . 'px ' . $margins . 'px;}';
542 }
543 if ($GLOBALS['TSFE']->pSetup['adminPanelStyles']) {
544 $style .= '
545
546 /* Default styles for the Admin Panel */
547 TABLE.typo3-adminPanel { border: 1px solid black; background-color: #F6F2E6; }
548 TABLE.typo3-adminPanel TR.typo3-adminPanel-hRow TD { background-color: #9BA1A8; }
549 TABLE.typo3-adminPanel TR.typo3-adminPanel-itemHRow TD { background-color: #ABBBB4; }
550 TABLE.typo3-adminPanel TABLE, TABLE.typo3-adminPanel TD { border: 0px; }
551 TABLE.typo3-adminPanel TD FONT { font-family: verdana; font-size: 10px; color: black; }
552 TABLE.typo3-adminPanel TD A FONT { font-family: verdana; font-size: 10px; color: black; }
553 TABLE.typo3-editPanel { border: 1px solid black; background-color: #F6F2E6; }
554 TABLE.typo3-editPanel TD { border: 0px; }
555 ';
556 }
557 // CSS_inlineStyle from TS
558 $style .= trim($GLOBALS['TSFE']->pSetup['CSS_inlineStyle']);
559 $style .= $GLOBALS['TSFE']->cObj->cObjGet($GLOBALS['TSFE']->pSetup['cssInline.'], 'cssInline.');
560 if (trim($style)) {
561 if ($GLOBALS['TSFE']->config['config']['inlineStyle2TempFile']) {
562 $pageRenderer->addCssFile(self::inline2TempFile($style, 'css'));
563 } else {
564 $pageRenderer->addCssInlineBlock('additionalTSFEInlineStyle', $style);
565 }
566 }
567 // Javascript Libraries
568 if (is_array($GLOBALS['TSFE']->pSetup['javascriptLibs.'])) {
569 if ($GLOBALS['TSFE']->pSetup['javascriptLibs.']['SVG']) {
570 $pageRenderer->loadSvg();
571 if ($GLOBALS['TSFE']->pSetup['javascriptLibs.']['SVG.']['debug']) {
572 $pageRenderer->enableSvgDebug();
573 }
574 if ($GLOBALS['TSFE']->pSetup['javascriptLibs.']['SVG.']['forceFlash']) {
575 $pageRenderer->svgForceFlash();
576 }
577 }
578 if ($GLOBALS['TSFE']->pSetup['javascriptLibs.']['Prototype']) {
579 $pageRenderer->loadPrototype();
580 }
581 if ($GLOBALS['TSFE']->pSetup['javascriptLibs.']['Scriptaculous']) {
582 $modules = $GLOBALS['TSFE']->pSetup['javascriptLibs.']['Scriptaculous.']['modules'] ?: '';
583 $pageRenderer->loadScriptaculous($modules);
584 }
585 if ($GLOBALS['TSFE']->pSetup['javascriptLibs.']['ExtCore']) {
586 $pageRenderer->loadExtCore();
587 if ($GLOBALS['TSFE']->pSetup['javascriptLibs.']['ExtCore.']['debug']) {
588 $pageRenderer->enableExtCoreDebug();
589 }
590 }
591 // Include jQuery into the page renderer
592 if (!empty($GLOBALS['TSFE']->pSetup['javascriptLibs.']['jQuery'])) {
593 $jQueryTS = $GLOBALS['TSFE']->pSetup['javascriptLibs.']['jQuery.'];
594 // Check if version / source is set, if not set variable to "NULL" to use the default of the page renderer
595 $version = isset($jQueryTS['version']) ? $jQueryTS['version'] : NULL;
596 $source = isset($jQueryTS['source']) ? $jQueryTS['source'] : NULL;
597 // When "noConflict" is not set or "1" enable the default jQuery noConflict mode, otherwise disable the namespace
598 if (!isset($jQueryTS['noConflict']) || !empty($jQueryTS['noConflict'])) {
599 // Set namespace to the "noConflict.namespace" value if "noConflict.namespace" has a value
600 if (!empty($jQueryTS['noConflict.']['namespace'])) {
601 $namespace = $jQueryTS['noConflict.']['namespace'];
602 } else {
603 $namespace = \TYPO3\CMS\Core\Page\PageRenderer::JQUERY_NAMESPACE_DEFAULT_NOCONFLICT;
604 }
605 } else {
606 $namespace = \TYPO3\CMS\Core\Page\PageRenderer::JQUERY_NAMESPACE_NONE;
607 }
608 $pageRenderer->loadJQuery($version, $source, $namespace);
609 }
610 if ($GLOBALS['TSFE']->pSetup['javascriptLibs.']['ExtJs']) {
611 $css = $GLOBALS['TSFE']->pSetup['javascriptLibs.']['ExtJs.']['css'] ? TRUE : FALSE;
612 $theme = $GLOBALS['TSFE']->pSetup['javascriptLibs.']['ExtJs.']['theme'] ? TRUE : FALSE;
613 $adapter = $GLOBALS['TSFE']->pSetup['javascriptLibs.']['ExtJs.']['adapter'] ?: '';
614 $pageRenderer->loadExtJs($css, $theme, $adapter);
615 if ($GLOBALS['TSFE']->pSetup['javascriptLibs.']['ExtJs.']['debug']) {
616 $pageRenderer->enableExtJsDebug();
617 }
618 if ($GLOBALS['TSFE']->pSetup['javascriptLibs.']['ExtJs.']['quickTips']) {
619 $pageRenderer->enableExtJSQuickTips();
620 }
621 }
622 }
623 // JavaScript library files
624 if (is_array($GLOBALS['TSFE']->pSetup['includeJSlibs.'])) {
625 foreach ($GLOBALS['TSFE']->pSetup['includeJSlibs.'] as $key => $JSfile) {
626 if (!is_array($JSfile)) {
627 if (isset($GLOBALS['TSFE']->pSetup['includeJSlibs.'][$key . '.']['if.']) && !$GLOBALS['TSFE']->cObj->checkIf($GLOBALS['TSFE']->pSetup['includeJSlibs.'][($key . '.')]['if.'])) {
628 continue;
629 }
630 $ss = $GLOBALS['TSFE']->pSetup['includeJSlibs.'][$key . '.']['external'] ? $JSfile : $GLOBALS['TSFE']->tmpl->getFileName($JSfile);
631 if ($ss) {
632 $jsFileConfig = &$GLOBALS['TSFE']->pSetup['includeJSlibs.'][$key . '.'];
633 $type = $jsFileConfig['type'];
634 if (!$type) {
635 $type = 'text/javascript';
636 }
637
638 $pageRenderer->addJsLibrary(
639 $key,
640 $ss,
641 $type,
642 empty($jsFileConfig['disableCompression']),
643 $jsFileConfig['forceOnTop'] ? TRUE : FALSE,
644 $jsFileConfig['allWrap'],
645 $jsFileConfig['excludeFromConcatenation'] ? TRUE : FALSE,
646 $jsFileConfig['allWrap.']['splitChar']
647 );
648 unset($jsFileConfig);
649 }
650 }
651 }
652 }
653 if (is_array($GLOBALS['TSFE']->pSetup['includeJSFooterlibs.'])) {
654 foreach ($GLOBALS['TSFE']->pSetup['includeJSFooterlibs.'] as $key => $JSfile) {
655 if (!is_array($JSfile)) {
656 if (isset($GLOBALS['TSFE']->pSetup['includeJSFooterlibs.'][$key . '.']['if.']) && !$GLOBALS['TSFE']->cObj->checkIf($GLOBALS['TSFE']->pSetup['includeJSFooterlibs.'][($key . '.')]['if.'])) {
657 continue;
658 }
659 $ss = $GLOBALS['TSFE']->pSetup['includeJSFooterlibs.'][$key . '.']['external'] ? $JSfile : $GLOBALS['TSFE']->tmpl->getFileName($JSfile);
660 if ($ss) {
661 $jsFileConfig = &$GLOBALS['TSFE']->pSetup['includeJSFooterlibs.'][$key . '.'];
662 $type = $jsFileConfig['type'];
663 if (!$type) {
664 $type = 'text/javascript';
665 }
666 $pageRenderer->addJsFooterLibrary(
667 $key,
668 $ss,
669 $type,
670 empty($jsFileConfig['disableCompression']),
671 $jsFileConfig['forceOnTop'] ? TRUE : FALSE,
672 $jsFileConfig['allWrap'],
673 $jsFileConfig['excludeFromConcatenation'] ? TRUE : FALSE,
674 $jsFileConfig['allWrap.']['splitChar']
675 );
676 unset($jsFileConfig);
677 }
678 }
679 }
680 }
681 // JavaScript files
682 if (is_array($GLOBALS['TSFE']->pSetup['includeJS.'])) {
683 foreach ($GLOBALS['TSFE']->pSetup['includeJS.'] as $key => $JSfile) {
684 if (!is_array($JSfile)) {
685 if (isset($GLOBALS['TSFE']->pSetup['includeJS.'][$key . '.']['if.']) && !$GLOBALS['TSFE']->cObj->checkIf($GLOBALS['TSFE']->pSetup['includeJS.'][($key . '.')]['if.'])) {
686 continue;
687 }
688 $ss = $GLOBALS['TSFE']->pSetup['includeJS.'][$key . '.']['external'] ? $JSfile : $GLOBALS['TSFE']->tmpl->getFileName($JSfile);
689 if ($ss) {
690 $jsConfig = &$GLOBALS['TSFE']->pSetup['includeJS.'][$key . '.'];
691 $type = $jsConfig['type'];
692 if (!$type) {
693 $type = 'text/javascript';
694 }
695 $pageRenderer->addJsFile(
696 $ss,
697 $type,
698 empty($jsConfig['disableCompression']),
699 $jsConfig['forceOnTop'] ? TRUE : FALSE,
700 $jsConfig['allWrap'],
701 $jsConfig['excludeFromConcatenation'] ? TRUE : FALSE,
702 $jsConfig['allWrap.']['splitChar']
703 );
704 unset($jsConfig);
705 }
706 }
707 }
708 }
709 if (is_array($GLOBALS['TSFE']->pSetup['includeJSFooter.'])) {
710 foreach ($GLOBALS['TSFE']->pSetup['includeJSFooter.'] as $key => $JSfile) {
711 if (!is_array($JSfile)) {
712 if (isset($GLOBALS['TSFE']->pSetup['includeJSFooter.'][$key . '.']['if.']) && !$GLOBALS['TSFE']->cObj->checkIf($GLOBALS['TSFE']->pSetup['includeJSFooter.'][($key . '.')]['if.'])) {
713 continue;
714 }
715 $ss = $GLOBALS['TSFE']->pSetup['includeJSFooter.'][$key . '.']['external'] ? $JSfile : $GLOBALS['TSFE']->tmpl->getFileName($JSfile);
716 if ($ss) {
717 $jsConfig = &$GLOBALS['TSFE']->pSetup['includeJSFooter.'][$key . '.'];
718 $type = $jsConfig['type'];
719 if (!$type) {
720 $type = 'text/javascript';
721 }
722 $pageRenderer->addJsFooterFile(
723 $ss,
724 $type,
725 empty($jsConfig['disableCompression']),
726 $jsConfig['forceOnTop'] ? TRUE : FALSE,
727 $jsConfig['allWrap'],
728 $jsConfig['excludeFromConcatenation'] ? TRUE : FALSE,
729 $jsConfig['allWrap.']['splitChar']
730 );
731 unset($jsConfig);
732 }
733 }
734 }
735 }
736 // Headerdata
737 if (is_array($GLOBALS['TSFE']->pSetup['headerData.'])) {
738 $pageRenderer->addHeaderData($GLOBALS['TSFE']->cObj->cObjGet($GLOBALS['TSFE']->pSetup['headerData.'], 'headerData.'));
739 }
740 // Footerdata
741 if (is_array($GLOBALS['TSFE']->pSetup['footerData.'])) {
742 $pageRenderer->addFooterData($GLOBALS['TSFE']->cObj->cObjGet($GLOBALS['TSFE']->pSetup['footerData.'], 'footerData.'));
743 }
744 static::generatePageTitle();
745
746 $metaTagsHtml = static::generateMetaTagHtml(
747 isset($GLOBALS['TSFE']->pSetup['meta.']) ? $GLOBALS['TSFE']->pSetup['meta.'] : array(),
748 $GLOBALS['TSFE']->xhtmlVersion,
749 $GLOBALS['TSFE']->cObj
750 );
751 foreach ($metaTagsHtml as $metaTag) {
752 $pageRenderer->addMetaTag($metaTag);
753 }
754
755 unset($GLOBALS['TSFE']->additionalHeaderData['JSCode']);
756 unset($GLOBALS['TSFE']->additionalHeaderData['JSImgCode']);
757 if (is_array($GLOBALS['TSFE']->config['INTincScript'])) {
758 // Storing the JSCode and JSImgCode vars...
759 $GLOBALS['TSFE']->additionalHeaderData['JSCode'] = $GLOBALS['TSFE']->JSCode;
760 $GLOBALS['TSFE']->additionalHeaderData['JSImgCode'] = $GLOBALS['TSFE']->JSImgCode;
761 $GLOBALS['TSFE']->config['INTincScript_ext']['divKey'] = $GLOBALS['TSFE']->uniqueHash();
762 $GLOBALS['TSFE']->config['INTincScript_ext']['additionalHeaderData'] = $GLOBALS['TSFE']->additionalHeaderData;
763 // Storing the header-data array
764 $GLOBALS['TSFE']->config['INTincScript_ext']['additionalFooterData'] = $GLOBALS['TSFE']->additionalFooterData;
765 // Storing the footer-data array
766 $GLOBALS['TSFE']->config['INTincScript_ext']['additionalJavaScript'] = $GLOBALS['TSFE']->additionalJavaScript;
767 // Storing the JS-data array
768 $GLOBALS['TSFE']->config['INTincScript_ext']['additionalCSS'] = $GLOBALS['TSFE']->additionalCSS;
769 // Storing the Style-data array
770 $GLOBALS['TSFE']->additionalHeaderData = array('<!--HD_' . $GLOBALS['TSFE']->config['INTincScript_ext']['divKey'] . '-->');
771 // Clearing the array
772 $GLOBALS['TSFE']->additionalFooterData = array('<!--FD_' . $GLOBALS['TSFE']->config['INTincScript_ext']['divKey'] . '-->');
773 // Clearing the array
774 $GLOBALS['TSFE']->divSection .= '<!--TDS_' . $GLOBALS['TSFE']->config['INTincScript_ext']['divKey'] . '-->';
775 } else {
776 $GLOBALS['TSFE']->INTincScript_loadJSCode();
777 }
778 $JSef = self::JSeventFunctions();
779 $scriptJsCode = $JSef[0];
780
781 if ($GLOBALS['TSFE']->spamProtectEmailAddresses && $GLOBALS['TSFE']->spamProtectEmailAddresses !== 'ascii') {
782 $scriptJsCode .= '
783 // decrypt helper function
784 function decryptCharcode(n,start,end,offset) {
785 n = n + offset;
786 if (offset > 0 && n > end) {
787 n = start + (n - end - 1);
788 } else if (offset < 0 && n < start) {
789 n = end - (start - n - 1);
790 }
791 return String.fromCharCode(n);
792 }
793 // decrypt string
794 function decryptString(enc,offset) {
795 var dec = "";
796 var len = enc.length;
797 for(var i=0; i < len; i++) {
798 var n = enc.charCodeAt(i);
799 if (n >= 0x2B && n <= 0x3A) {
800 dec += decryptCharcode(n,0x2B,0x3A,offset); // 0-9 . , - + / :
801 } else if (n >= 0x40 && n <= 0x5A) {
802 dec += decryptCharcode(n,0x40,0x5A,offset); // A-Z @
803 } else if (n >= 0x61 && n <= 0x7A) {
804 dec += decryptCharcode(n,0x61,0x7A,offset); // a-z
805 } else {
806 dec += enc.charAt(i);
807 }
808 }
809 return dec;
810 }
811 // decrypt spam-protected emails
812 function linkTo_UnCryptMailto(s) {
813 location.href = decryptString(s,' . $GLOBALS['TSFE']->spamProtectEmailAddresses * -1 . ');
814 }
815 ';
816 }
817 // Add inline JS
818 $inlineJS = '';
819 // defined in php
820 if (is_array($GLOBALS['TSFE']->inlineJS)) {
821 foreach ($GLOBALS['TSFE']->inlineJS as $key => $val) {
822 if (!is_array($val)) {
823 $inlineJS .= LF . $val . LF;
824 }
825 }
826 }
827 // defined in TS with page.inlineJS
828 // Javascript inline code
829 $inline = $GLOBALS['TSFE']->cObj->cObjGet($GLOBALS['TSFE']->pSetup['jsInline.'], 'jsInline.');
830 if ($inline) {
831 $inlineJS .= LF . $inline . LF;
832 }
833 // Javascript inline code for Footer
834 $inlineFooterJs = $GLOBALS['TSFE']->cObj->cObjGet($GLOBALS['TSFE']->pSetup['jsFooterInline.'], 'jsFooterInline.');
835 // Should minify?
836 if ($GLOBALS['TSFE']->config['config']['compressJs']) {
837 $pageRenderer->enableCompressJavascript();
838 $minifyErrorScript = ($minifyErrorInline = '');
839 $scriptJsCode = GeneralUtility::minifyJavaScript($scriptJsCode, $minifyErrorScript);
840 if ($minifyErrorScript) {
841 $GLOBALS['TT']->setTSlogMessage($minifyErrorScript, 3);
842 }
843 if ($inlineJS) {
844 $inlineJS = GeneralUtility::minifyJavaScript($inlineJS, $minifyErrorInline);
845 if ($minifyErrorInline) {
846 $GLOBALS['TT']->setTSlogMessage($minifyErrorInline, 3);
847 }
848 }
849 if ($inlineFooterJs) {
850 $inlineFooterJs = GeneralUtility::minifyJavaScript($inlineFooterJs, $minifyErrorInline);
851 if ($minifyErrorInline) {
852 $GLOBALS['TT']->setTSlogMessage($minifyErrorInline, 3);
853 }
854 }
855 }
856 if (!$GLOBALS['TSFE']->config['config']['removeDefaultJS']) {
857 // inlude default and inlineJS
858 if ($scriptJsCode) {
859 $pageRenderer->addJsInlineCode('_scriptCode', $scriptJsCode, $GLOBALS['TSFE']->config['config']['compressJs']);
860 }
861 if ($inlineJS) {
862 $pageRenderer->addJsInlineCode('TS_inlineJS', $inlineJS, $GLOBALS['TSFE']->config['config']['compressJs']);
863 }
864 if ($inlineFooterJs) {
865 $pageRenderer->addJsFooterInlineCode('TS_inlineFooter', $inlineFooterJs, $GLOBALS['TSFE']->config['config']['compressJs']);
866 }
867 } elseif ($GLOBALS['TSFE']->config['config']['removeDefaultJS'] === 'external') {
868 /*
869 * This keeps inlineJS from *_INT Objects from being moved to external files.
870 * At this point in frontend rendering *_INT Objects only have placeholders instead
871 * of actual content so moving these placeholders to external files would
872 * a) break the JS file (syntax errors due to the placeholders)
873 * b) the needed JS would never get included to the page
874 * Therefore inlineJS from *_INT Objects must not be moved to external files but
875 * kept internal.
876 */
877 $inlineJSint = '';
878 self::stripIntObjectPlaceholder($inlineJS, $inlineJSint);
879 if ($inlineJSint) {
880 $pageRenderer->addJsInlineCode('TS_inlineJSint', $inlineJSint, $GLOBALS['TSFE']->config['config']['compressJs']);
881 }
882 if (trim($scriptJsCode . $inlineJS)) {
883 $pageRenderer->addJsFile(self::inline2TempFile($scriptJsCode . $inlineJS, 'js'), 'text/javascript', $GLOBALS['TSFE']->config['config']['compressJs']);
884 }
885 if ($inlineFooterJs) {
886 $inlineFooterJSint = '';
887 self::stripIntObjectPlaceholder($inlineFooterJs, $inlineFooterJSint);
888 if ($inlineFooterJSint) {
889 $pageRenderer->addJsFooterInlineCode('TS_inlineFooterJSint', $inlineFooterJSint, $GLOBALS['TSFE']->config['config']['compressJs']);
890 }
891 $pageRenderer->addJsFooterFile(self::inline2TempFile($inlineFooterJs, 'js'), 'text/javascript', $GLOBALS['TSFE']->config['config']['compressJs']);
892 }
893 } else {
894 // Include only inlineJS
895 if ($inlineJS) {
896 $pageRenderer->addJsInlineCode('TS_inlineJS', $inlineJS, $GLOBALS['TSFE']->config['config']['compressJs']);
897 }
898 if ($inlineFooterJs) {
899 $pageRenderer->addJsFooterInlineCode('TS_inlineFooter', $inlineFooterJs, $GLOBALS['TSFE']->config['config']['compressJs']);
900 }
901 }
902 // ExtJS specific code
903 if (is_array($GLOBALS['TSFE']->pSetup['inlineLanguageLabel.'])) {
904 $pageRenderer->addInlineLanguageLabelArray($GLOBALS['TSFE']->pSetup['inlineLanguageLabel.']);
905 }
906 if (is_array($GLOBALS['TSFE']->pSetup['inlineSettings.'])) {
907 $pageRenderer->addInlineSettingArray('TS', $GLOBALS['TSFE']->pSetup['inlineSettings.']);
908 }
909 if (is_array($GLOBALS['TSFE']->pSetup['extOnReady.'])) {
910 $pageRenderer->addExtOnReadyCode($GLOBALS['TSFE']->cObj->cObjGet($GLOBALS['TSFE']->pSetup['extOnReady.'], 'extOnReady.'));
911 }
912 // Compression and concatenate settings
913 if ($GLOBALS['TSFE']->config['config']['compressCss']) {
914 $pageRenderer->enableCompressCss();
915 }
916 if ($GLOBALS['TSFE']->config['config']['compressJs']) {
917 $pageRenderer->enableCompressJavascript();
918 }
919 if ($GLOBALS['TSFE']->config['config']['concatenateCss']) {
920 $pageRenderer->enableConcatenateCss();
921 }
922 if ($GLOBALS['TSFE']->config['config']['concatenateJs']) {
923 $pageRenderer->enableConcatenateJavascript();
924 }
925 // Backward compatibility for old configuration
926 if ($GLOBALS['TSFE']->config['config']['concatenateJsAndCss']) {
927 $pageRenderer->enableConcatenateFiles();
928 }
929 // Add header data block
930 if ($GLOBALS['TSFE']->additionalHeaderData) {
931 $pageRenderer->addHeaderData(implode(LF, $GLOBALS['TSFE']->additionalHeaderData));
932 }
933 // Add footer data block
934 if ($GLOBALS['TSFE']->additionalFooterData) {
935 $pageRenderer->addFooterData(implode(LF, $GLOBALS['TSFE']->additionalFooterData));
936 }
937 // Header complete, now add content
938 if ($GLOBALS['TSFE']->pSetup['frameSet.']) {
939 $fs = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\FramesetRenderer');
940 $pageRenderer->addBodyContent($fs->make($GLOBALS['TSFE']->pSetup['frameSet.']));
941 $pageRenderer->addBodyContent(LF . '<noframes>' . LF);
942 }
943 // Bodytag:
944 if ($GLOBALS['TSFE']->config['config']['disableBodyTag']) {
945 $bodyTag = '';
946 } else {
947 $defBT = $GLOBALS['TSFE']->pSetup['bodyTagCObject'] ? $GLOBALS['TSFE']->cObj->cObjGetSingle($GLOBALS['TSFE']->pSetup['bodyTagCObject'], $GLOBALS['TSFE']->pSetup['bodyTagCObject.'], 'bodyTagCObject') : '';
948 if (!$defBT) {
949 $defBT = $GLOBALS['TSFE']->defaultBodyTag;
950 }
951 $bodyTag = $GLOBALS['TSFE']->pSetup['bodyTag'] ? $GLOBALS['TSFE']->pSetup['bodyTag'] : $defBT;
952 if ($bgImg = $GLOBALS['TSFE']->cObj->getImgResource($GLOBALS['TSFE']->pSetup['bgImg'], $GLOBALS['TSFE']->pSetup['bgImg.'])) {
953 $bodyTag = preg_replace('/>$/', '', trim($bodyTag)) . ' background="' . $GLOBALS['TSFE']->absRefPrefix . $bgImg[3] . '">';
954 }
955 if (isset($GLOBALS['TSFE']->pSetup['bodyTagMargins'])) {
956 $margins = (int)$GLOBALS['TSFE']->pSetup['bodyTagMargins'];
957 if ($GLOBALS['TSFE']->pSetup['bodyTagMargins.']['useCSS']) {
958
959 } else {
960 $bodyTag = preg_replace('/>$/', '', trim($bodyTag)) . ' leftmargin="' . $margins . '" topmargin="' . $margins . '" marginwidth="' . $margins . '" marginheight="' . $margins . '">';
961 }
962 }
963 if (trim($GLOBALS['TSFE']->pSetup['bodyTagAdd'])) {
964 $bodyTag = preg_replace('/>$/', '', trim($bodyTag)) . ' ' . trim($GLOBALS['TSFE']->pSetup['bodyTagAdd']) . '>';
965 }
966 // Event functions
967 if (count($JSef[1])) {
968 $bodyTag = preg_replace('/>$/', '', trim($bodyTag)) . ' ' . trim(implode(' ', $JSef[1])) . '>';
969 }
970 }
971 $pageRenderer->addBodyContent(LF . $bodyTag);
972 // Div-sections
973 if ($GLOBALS['TSFE']->divSection) {
974 $pageRenderer->addBodyContent(LF . $GLOBALS['TSFE']->divSection);
975 }
976 // Page content
977 $pageRenderer->addBodyContent(LF . $pageContent);
978 if (!empty($GLOBALS['TSFE']->config['INTincScript']) && is_array($GLOBALS['TSFE']->config['INTincScript'])) {
979 // Store the serialized pageRenderer in configuration
980 $GLOBALS['TSFE']->config['INTincScript_ext']['pageRenderer'] = serialize($pageRenderer);
981 // Render complete page, keep placeholders for JavaScript and CSS
982 $GLOBALS['TSFE']->content = $pageRenderer->renderPageWithUncachedObjects($GLOBALS['TSFE']->config['INTincScript_ext']['divKey']);
983 } else {
984 // Render complete page
985 $GLOBALS['TSFE']->content = $pageRenderer->render();
986 }
987 // Ending page
988 if ($GLOBALS['TSFE']->pSetup['frameSet.']) {
989 $GLOBALS['TSFE']->content .= LF . '</noframes>';
990 }
991 }
992
993 /*************************
994 *
995 * Helper functions
996 * Remember: Calls internally must still be done on the non-instantiated class: TSpagegen::inline2TempFile()
997 *
998 *************************/
999 /**
1000 * Searches for placeholder created from *_INT cObjects, removes them from
1001 * $searchString and merges them to $intObjects
1002 *
1003 * @param string $searchString The String which should be cleaned from int-object markers
1004 * @param string $intObjects The String the found int-placeholders are moved to (for further processing)
1005 */
1006 static protected function stripIntObjectPlaceholder(&$searchString, &$intObjects) {
1007 $tempArray = array();
1008 preg_match_all('/\\<\\!--INT_SCRIPT.[a-z0-9]*--\\>/', $searchString, $tempArray);
1009 $searchString = preg_replace('/\\<\\!--INT_SCRIPT.[a-z0-9]*--\\>/', '', $searchString);
1010 $intObjects = implode('', $tempArray[0]);
1011 }
1012
1013 /**
1014 * Writes string to a temporary file named after the md5-hash of the string
1015 *
1016 * @param string $str CSS styles / JavaScript to write to file.
1017 * @param string $ext Extension: "css" or "js
1018 * @return string <script> or <link> tag for the file.
1019 */
1020 static public function inline2TempFile($str, $ext) {
1021 // Create filename / tags:
1022 $script = '';
1023 switch ($ext) {
1024 case 'js':
1025 $script = 'typo3temp/javascript_' . substr(md5($str), 0, 10) . '.js';
1026 break;
1027 case 'css':
1028 $script = 'typo3temp/stylesheet_' . substr(md5($str), 0, 10) . '.css';
1029 break;
1030 }
1031 // Write file:
1032 if ($script) {
1033 if (!@is_file((PATH_site . $script))) {
1034 GeneralUtility::writeFile(PATH_site . $script, $str);
1035 }
1036 }
1037 return $script;
1038 }
1039
1040 /**
1041 * Checks if the value defined in "config.linkVars" contains an allowed value. Otherwise, return FALSE which means the value will not be added to any links.
1042 *
1043 * @param string $haystack The string in which to find $needle
1044 * @param string $needle The string to find in $haystack
1045 * @return boolean Returns TRUE if $needle matches or is found in $haystack
1046 */
1047 static public function isAllowedLinkVarValue($haystack, $needle) {
1048 $OK = FALSE;
1049 // Integer
1050 if ($needle == 'int' || $needle == 'integer') {
1051 if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($haystack)) {
1052 $OK = TRUE;
1053 }
1054 } elseif (preg_match('/^\\/.+\\/[imsxeADSUXu]*$/', $needle)) {
1055 // Regular expression, only "//" is allowed as delimiter
1056 if (@preg_match($needle, $haystack)) {
1057 $OK = TRUE;
1058 }
1059 } elseif (strstr($needle, '-')) {
1060 // Range
1061 if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($haystack)) {
1062 $range = explode('-', $needle);
1063 if ($range[0] <= $haystack && $range[1] >= $haystack) {
1064 $OK = TRUE;
1065 }
1066 }
1067 } elseif (strstr($needle, '|')) {
1068 // List
1069 // Trim the input
1070 $haystack = str_replace(' ', '', $haystack);
1071 if (strstr('|' . $needle . '|', '|' . $haystack . '|')) {
1072 $OK = TRUE;
1073 }
1074 } elseif ((string)$needle === (string)$haystack) {
1075 // String comparison
1076 $OK = TRUE;
1077 }
1078 return $OK;
1079 }
1080
1081 /**
1082 * Generate title for page.
1083 * Takes the settings ['config']['noPageTitle'], ['config']['pageTitleFirst'], ['config']['titleTagFunction']
1084 * and ['config']['noPageTitle'] into account.
1085 * Furthermore $GLOBALS['TSFE']->altPageTitle is observed.
1086 *
1087 * @return void
1088 */
1089 static public function generatePageTitle() {
1090 $titleTagContent = $GLOBALS['TSFE']->tmpl->printTitle(
1091 $GLOBALS['TSFE']->altPageTitle ? $GLOBALS['TSFE']->altPageTitle : $GLOBALS['TSFE']->page['title'],
1092 $GLOBALS['TSFE']->config['config']['noPageTitle'],
1093 $GLOBALS['TSFE']->config['config']['pageTitleFirst']
1094 );
1095 if ($GLOBALS['TSFE']->config['config']['titleTagFunction']) {
1096 $titleTagContent = $GLOBALS['TSFE']->cObj->callUserFunction(
1097 $GLOBALS['TSFE']->config['config']['titleTagFunction'],
1098 array(),
1099 $titleTagContent
1100 );
1101 }
1102 if ($titleTagContent !== '' && (int)$GLOBALS['TSFE']->config['config']['noPageTitle'] !== self::NO_PAGE_TITLE) {
1103 $GLOBALS['TSFE']->getPageRenderer()->setTitle($titleTagContent);
1104 }
1105 }
1106
1107 /**
1108 * Generate meta tags from meta tag TypoScript
1109 *
1110 * @param array $metaTagTypoScript TypoScript configuration for meta tags (e.g. $GLOBALS['TSFE']->pSetup['meta.'])
1111 * @param bool $xhtml Whether xhtml tag-style should be used. (e.g. pass $GLOBALS['TSFE']->xhtmlVersion here)
1112 * @param ContentObjectRenderer $cObj
1113 * @return array Array of HTML meta tags
1114 */
1115 static protected function generateMetaTagHtml(array $metaTagTypoScript, $xhtml, ContentObjectRenderer $cObj) {
1116 // Add ending slash only to documents rendered as xhtml
1117 $endingSlash = $xhtml ? ' /' : '';
1118
1119 $metaTags = array(
1120 '<meta name="generator" content="TYPO3 ' . TYPO3_branch . ' CMS"' . $endingSlash . '>'
1121 );
1122
1123 /** @var TypoScriptService $typoScriptService */
1124 $typoScriptService = GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Service\\TypoScriptService');
1125 $conf = $typoScriptService->convertTypoScriptArrayToPlainArray($metaTagTypoScript);
1126 foreach ($conf as $key => $properties) {
1127 if (is_array($properties)) {
1128 $nodeValue = isset($properties['_typoScriptNodeValue']) ? $properties['_typoScriptNodeValue'] : '';
1129 $value = trim($cObj->stdWrap($nodeValue, $metaTagTypoScript[$key . '.']));
1130 } else {
1131 $value = $properties;
1132 }
1133 if ($value !== '') {
1134 $attribute = 'name';
1135 if ( (is_array($properties) && !empty($properties['httpEquivalent'])) || strtolower($key) === 'refresh') {
1136 $attribute = 'http-equiv';
1137 }
1138 $metaTags[] = '<meta ' . $attribute . '="' . $key . '" content="' . htmlspecialchars($value) . '"' . $endingSlash . '>';
1139 }
1140 }
1141 return $metaTags;
1142 }
1143
1144 /**
1145 * Fills the sWordList property and builds the regular expression in TSFE that can be used to split
1146 * strings by the submitted search words.
1147 *
1148 * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::sWordList
1149 * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::sWordRegEx
1150 */
1151 static protected function initializeSearchWordDataInTsfe() {
1152 $GLOBALS['TSFE']->sWordRegEx = '';
1153 $GLOBALS['TSFE']->sWordList = GeneralUtility::_GP('sword_list');
1154 if (is_array($GLOBALS['TSFE']->sWordList)) {
1155 $space = !empty($GLOBALS['TSFE']->config['config']['sword_standAlone']) ? '[[:space:]]' : '';
1156 foreach ($GLOBALS['TSFE']->sWordList as $val) {
1157 if (trim($val) !== '') {
1158 $GLOBALS['TSFE']->sWordRegEx .= $space . preg_quote($val, '/') . $space . '|';
1159 }
1160 }
1161 $GLOBALS['TSFE']->sWordRegEx = rtrim($GLOBALS['TSFE']->sWordRegEx, '|');
1162 }
1163 }
1164 }