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