TYPO3 CMS  TYPO3_6-2
ContentObjectRenderer.php
Go to the documentation of this file.
1 <?php
3 
21 
34 
38  public $align = array(
39  'center',
40  'right',
41  'left'
42  );
43 
50  public $stdWrapOrder = array(
51  'stdWrapPreProcess' => 'hook',
52  // this is a placeholder for the first Hook
53  'cacheRead' => 'hook',
54  // this is a placeholder for checking if the content is available in cache
55  'setContentToCurrent' => 'boolean',
56  'setContentToCurrent.' => 'array',
57  'addPageCacheTags' => 'string',
58  'addPageCacheTags.' => 'array',
59  'setCurrent' => 'string',
60  'setCurrent.' => 'array',
61  'lang.' => 'array',
62  'data' => 'getText',
63  'data.' => 'array',
64  'field' => 'fieldName',
65  'field.' => 'array',
66  'current' => 'boolean',
67  'current.' => 'array',
68  'cObject' => 'cObject',
69  'cObject.' => 'array',
70  'numRows.' => 'array',
71  'filelist' => 'dir',
72  'filelist.' => 'array',
73  'preUserFunc' => 'functionName',
74  'stdWrapOverride' => 'hook',
75  // this is a placeholder for the second Hook
76  'override' => 'string',
77  'override.' => 'array',
78  'preIfEmptyListNum' => 'listNum',
79  'preIfEmptyListNum.' => 'array',
80  'ifNull' => 'string',
81  'ifNull.' => 'array',
82  'ifEmpty' => 'string',
83  'ifEmpty.' => 'array',
84  'ifBlank' => 'string',
85  'ifBlank.' => 'array',
86  'listNum' => 'listNum',
87  'listNum.' => 'array',
88  'trim' => 'boolean',
89  'trim.' => 'array',
90  'strPad.' => 'array',
91  'stdWrap' => 'stdWrap',
92  'stdWrap.' => 'array',
93  'stdWrapProcess' => 'hook',
94  // this is a placeholder for the third Hook
95  'required' => 'boolean',
96  'required.' => 'array',
97  'if.' => 'array',
98  'fieldRequired' => 'fieldName',
99  'fieldRequired.' => 'array',
100  'csConv' => 'string',
101  'csConv.' => 'array',
102  'parseFunc' => 'objectpath',
103  'parseFunc.' => 'array',
104  'HTMLparser' => 'boolean',
105  'HTMLparser.' => 'array',
106  'split.' => 'array',
107  'replacement.' => 'array',
108  'prioriCalc' => 'boolean',
109  'prioriCalc.' => 'array',
110  'char' => 'integer',
111  'char.' => 'array',
112  'intval' => 'boolean',
113  'intval.' => 'array',
114  'hash' => 'string',
115  'hash.' => 'array',
116  'round' => 'boolean',
117  'round.' => 'array',
118  'numberFormat.' => 'array',
119  'expandList' => 'boolean',
120  'expandList.' => 'array',
121  'date' => 'dateconf',
122  'date.' => 'array',
123  'strftime' => 'strftimeconf',
124  'strftime.' => 'array',
125  'age' => 'boolean',
126  'age.' => 'array',
127  'case' => 'case',
128  'case.' => 'array',
129  'bytes' => 'boolean',
130  'bytes.' => 'array',
131  'substring' => 'parameters',
132  'substring.' => 'array',
133  'removeBadHTML' => 'boolean',
134  'removeBadHTML.' => 'array',
135  'cropHTML' => 'crop',
136  'cropHTML.' => 'array',
137  'stripHtml' => 'boolean',
138  'stripHtml.' => 'array',
139  'crop' => 'crop',
140  'crop.' => 'array',
141  'rawUrlEncode' => 'boolean',
142  'rawUrlEncode.' => 'array',
143  'htmlSpecialChars' => 'boolean',
144  'htmlSpecialChars.' => 'array',
145  'encodeForJavaScriptValue' => 'boolean',
146  'encodeForJavaScriptValue.' => 'array',
147  'doubleBrTag' => 'string',
148  'doubleBrTag.' => 'array',
149  'br' => 'boolean',
150  'br.' => 'array',
151  'brTag' => 'string',
152  'brTag.' => 'array',
153  'encapsLines.' => 'array',
154  'keywords' => 'boolean',
155  'keywords.' => 'array',
156  'innerWrap' => 'wrap',
157  'innerWrap.' => 'array',
158  'innerWrap2' => 'wrap',
159  'innerWrap2.' => 'array',
160  'fontTag' => 'wrap',
161  'fontTag.' => 'array',
162  'addParams.' => 'array',
163  'textStyle.' => 'array',
164  'tableStyle.' => 'array',
165  'filelink.' => 'array',
166  'preCObject' => 'cObject',
167  'preCObject.' => 'array',
168  'postCObject' => 'cObject',
169  'postCObject.' => 'array',
170  'wrapAlign' => 'align',
171  'wrapAlign.' => 'array',
172  'typolink.' => 'array',
173  'TCAselectItem.' => 'array',
174  'space' => 'space',
175  'space.' => 'array',
176  'spaceBefore' => 'int',
177  'spaceBefore.' => 'array',
178  'spaceAfter' => 'int',
179  'spaceAfter.' => 'array',
180  'wrap' => 'wrap',
181  'wrap.' => 'array',
182  'noTrimWrap' => 'wrap',
183  'noTrimWrap.' => 'array',
184  'wrap2' => 'wrap',
185  'wrap2.' => 'array',
186  'dataWrap' => 'dataWrap',
187  'dataWrap.' => 'array',
188  'prepend' => 'cObject',
189  'prepend.' => 'array',
190  'append' => 'cObject',
191  'append.' => 'array',
192  'wrap3' => 'wrap',
193  'wrap3.' => 'array',
194  'orderedStdWrap' => 'stdWrap',
195  'orderedStdWrap.' => 'array',
196  'outerWrap' => 'wrap',
197  'outerWrap.' => 'array',
198  'insertData' => 'boolean',
199  'insertData.' => 'array',
200  'offsetWrap' => 'space',
201  'offsetWrap.' => 'array',
202  'postUserFunc' => 'functionName',
203  'postUserFuncInt' => 'functionName',
204  'prefixComment' => 'string',
205  'prefixComment.' => 'array',
206  'editIcons' => 'string',
207  'editIcons.' => 'array',
208  'editPanel' => 'boolean',
209  'editPanel.' => 'array',
210  'cacheStore' => 'hook',
211  // this is a placeholder for storing the content in cache
212  'stdWrapPostProcess' => 'hook',
213  // this is a placeholder for the last Hook
214  'debug' => 'boolean',
215  'debug.' => 'array',
216  'debugFunc' => 'boolean',
217  'debugFunc.' => 'array',
218  'debugData' => 'boolean',
219  'debugData.' => 'array'
220  );
221 
227  protected $contentObjectClassMapping = array(
228  'TEXT' => 'Text',
229  'CASE' => 'Case',
230  'CLEARGIF' => 'ClearGif',
231  'COBJ_ARRAY' => 'ContentObjectArray',
232  'COA' => 'ContentObjectArray',
233  'COA_INT' => 'ContentObjectArrayInternal',
234  'USER' => 'User',
235  'USER_INT' => 'UserInternal',
236  'FILE' => 'File',
237  'FILES' => 'Files',
238  'IMAGE' => 'Image',
239  'IMG_RESOURCE' => 'ImageResource',
240  'IMGTEXT' => 'ImageText',
241  'CONTENT' => 'Content',
242  'RECORDS' => 'Records',
243  'HMENU' => 'HierarchicalMenu',
244  'CTABLE' => 'ContentTable',
245  'OTABLE' => 'OffsetTable',
246  'COLUMNS' => 'Columns',
247  'HRULER' => 'HorizontalRuler',
248  'CASEFUNC' => 'Case',
249  'LOAD_REGISTER' => 'LoadRegister',
250  'RESTORE_REGISTER' => 'RestoreRegister',
251  'FORM' => 'Form',
252  'SEARCHRESULT' => 'SearchResult',
253  'TEMPLATE' => 'Template',
254  'FLUIDTEMPLATE' => 'FluidTemplate',
255  'MULTIMEDIA' => 'Multimedia',
256  'MEDIA' => 'Media',
257  'SWFOBJECT' => 'ShockwaveFlashObject',
258  'FLOWPLAYER' => 'FlowPlayer',
259  'QTOBJECT' => 'QuicktimeObject',
260  'SVG' => 'ScalableVectorGraphics',
261  'EDITPANEL' => 'EditPanel',
262  );
263 
270  public $image_compression = array(
271  10 => array(
272  'params' => '',
273  'ext' => 'gif'
274  ),
275  11 => array(
276  'params' => '-colors 128',
277  'ext' => 'gif'
278  ),
279  12 => array(
280  'params' => '-colors 64',
281  'ext' => 'gif'
282  ),
283  13 => array(
284  'params' => '-colors 32',
285  'ext' => 'gif'
286  ),
287  14 => array(
288  'params' => '-colors 16',
289  'ext' => 'gif'
290  ),
291  15 => array(
292  'params' => '-colors 8',
293  'ext' => 'gif'
294  ),
295  20 => array(
296  'params' => '-quality 100',
297  'ext' => 'jpg'
298  ),
299  21 => array(
300  'params' => '-quality 90',
301  'ext' => 'jpg'
302  ),
303  22 => array(
304  'params' => '-quality 80',
305  'ext' => 'jpg'
306  ),
307  23 => array(
308  'params' => '-quality 70',
309  'ext' => 'jpg'
310  ),
311  24 => array(
312  'params' => '-quality 60',
313  'ext' => 'jpg'
314  ),
315  25 => array(
316  'params' => '-quality 50',
317  'ext' => 'jpg'
318  ),
319  26 => array(
320  'params' => '-quality 40',
321  'ext' => 'jpg'
322  ),
323  27 => array(
324  'params' => '-quality 30',
325  'ext' => 'jpg'
326  ),
327  28 => array(
328  'params' => '-quality 20',
329  'ext' => 'jpg'
330  ),
331  30 => array(
332  'params' => '-colors 256',
333  'ext' => 'png'
334  ),
335  31 => array(
336  'params' => '-colors 128',
337  'ext' => 'png'
338  ),
339  32 => array(
340  'params' => '-colors 64',
341  'ext' => 'png'
342  ),
343  33 => array(
344  'params' => '-colors 32',
345  'ext' => 'png'
346  ),
347  34 => array(
348  'params' => '-colors 16',
349  'ext' => 'png'
350  ),
351  35 => array(
352  'params' => '-colors 8',
353  'ext' => 'png'
354  ),
355  39 => array(
356  'params' => '',
357  'ext' => 'png'
358  )
359  );
360 
367  public $image_effects = array(
368  1 => '-rotate 90',
369  2 => '-rotate 270',
370  3 => '-rotate 180',
371  10 => '-colorspace GRAY',
372  11 => '-sharpen 70',
373  20 => '-normalize',
374  23 => '-contrast',
375  25 => '-gamma 1.3',
376  26 => '-gamma 0.8'
377  );
378 
388  public $data = array();
389 
390  protected $table = '';
391 
392  // Used for backup...
396  public $oldData = array();
397 
398  // If this is set with an array before stdWrap, it's used instead of $this->data in the data-property in stdWrap
402  public $alternativeData = '';
403 
404  // Used by the parseFunc function and is loaded with tag-parameters when parsing tags.
408  public $parameters = array();
409 
413  public $currentValKey = 'currentValue_kidjls9dksoje';
414 
415  // This is set to the [table]:[uid] of the record delivered in the $data-array, if the cObjects CONTENT or RECORD is in operation.
416  // Note that $GLOBALS['TSFE']->currentRecord is set to an equal value but always indicating the latest record rendered.
420  public $currentRecord = '';
421 
422  // Set in cObj->RECORDS and cObj->CONTENT to the current number of records selected in a query.
427 
428  // Incremented in cObj->RECORDS and cObj->CONTENT before each record rendering.
433 
434  // Incremented in parent cObj->RECORDS and cObj->CONTENT before each record rendering.
439 
440  // If the ContentObjectRender was started from CONTENT, RECORD or SEARCHRESULT cObject's this array has two keys, 'data' and 'currentRecord' which indicates the record and data for the parent cObj.
444  public $parentRecord = array();
445 
446  // This may be set as a reference to the calling object of eg. cObjGetSingle. Anyway, just use it as you like. It's used in productsLib.inc for example.
450  public $regObj;
451 
452  // internal
453  // Is set to 1 if the instance of this cObj is executed from a *_INT plugin (see pagegen, bottom of document)
457  public $INT_include = 0;
458 
459  // This is used by checkPid, that checks if pages are accessible. The $checkPid_cache['page_uid'] is set TRUE or FALSE upon this check featuring a caching function for the next request.
463  public $checkPid_cache = array();
464 
468  public $checkPid_badDoktypeList = '255';
469 
470  // This will be set by typoLink() to the url of the most recent link created.
474  public $lastTypoLinkUrl = '';
475 
476  // DO. link target.
480  public $lastTypoLinkTarget = '';
481 
485  public $lastTypoLinkLD = array();
486 
487  // Caching substituteMarkerArrayCached function
491  public $substMarkerCache = array();
492 
493  // array that registers rendered content elements (or any table) to make sure they are not rendered recursively!
497  public $recordRegister = array();
498 
499  // Containing hooks for userdefined cObjects
504  protected $cObjHookObjectsRegistry = array();
505 
509  public $cObjHookObjectsArr = array();
510 
511  // Containing hook objects for stdWrap
512  protected $stdWrapHookObjects = array();
513 
514  // Containing hook objects for getImgResource
516 
520  protected $currentFile = NULL;
521 
526 
532  protected $userObjectType = FALSE;
533 
537  protected $stopRendering = array();
538 
542  protected $stdWrapRecursionLevel = 0;
543 
555  const OBJECTTYPE_USER = 2;
566  public function start($data, $table = '') {
567  global $TYPO3_CONF_VARS;
568  if ($TYPO3_CONF_VARS['FE']['activateContentAdapter'] && is_array($data) && !empty($data) && !empty($table)) {
569  \TYPO3\CMS\Core\Resource\Service\FrontendContentAdapterService::modifyDBRow($data, $table);
570  }
571  $this->data = $data;
572  $this->table = $table;
573  $this->currentRecord = $table ? $table . ':' . $this->data['uid'] : '';
574  $this->parameters = array();
575  if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'])) {
576  foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'] as $classArr) {
577  $this->cObjHookObjectsRegistry[$classArr[0]] = $classArr[1];
578  }
579  }
580  $this->stdWrapHookObjects = array();
581  if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'])) {
582  foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap'] as $classData) {
583  $hookObject = GeneralUtility::getUserObj($classData);
584  if (!$hookObject instanceof \TYPO3\CMS\Frontend\ContentObject\ContentObjectStdWrapHookInterface) {
585  throw new \UnexpectedValueException($classData . ' must implement interface TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectStdWrapHookInterface', 1195043965);
586  }
587  $this->stdWrapHookObjects[] = $hookObject;
588  }
589  }
590  if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'])) {
591  foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'] as $classData) {
592  $postInitializationProcessor = GeneralUtility::getUserObj($classData);
593  if (!$postInitializationProcessor instanceof \TYPO3\CMS\Frontend\ContentObject\ContentObjectPostInitHookInterface) {
594  throw new \UnexpectedValueException($classData . ' must implement interface TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectPostInitHookInterface', 1274563549);
595  }
596  $postInitializationProcessor->postProcessContentObjectInitialization($this);
597  }
598  }
599  }
600 
606  public function getCurrentTable() {
607  return $this->table;
608  }
609 
616  protected function getGetImgResourceHookObjects() {
617  if (!isset($this->getImgResourceHookObjects)) {
618  $this->getImgResourceHookObjects = array();
619  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'])) {
620  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImgResource'] as $classData) {
621  $hookObject = GeneralUtility::getUserObj($classData);
622  if (!$hookObject instanceof \TYPO3\CMS\Frontend\ContentObject\ContentObjectGetImageResourceHookInterface) {
623  throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectGetImageResourceHookInterface', 1218636383);
624  }
625  $this->getImgResourceHookObjects[] = $hookObject;
626  }
627  }
628  }
630  }
631 
642  public function setParent($data, $currentRecord) {
643  $this->parentRecord = array(
644  'data' => $data,
645  'currentRecord' => $currentRecord
646  );
647  }
648 
649  /***********************************************
650  *
651  * CONTENT_OBJ:
652  *
653  ***********************************************/
663  public function getCurrentVal() {
664  return $this->data[$this->currentValKey];
665  }
666 
675  public function setCurrentVal($value) {
676  $this->data[$this->currentValKey] = $value;
677  }
678 
689  public function cObjGet($setup, $addKey = '') {
690  if (is_array($setup)) {
692  $content = '';
693  foreach ($sKeyArray as $theKey) {
694  $theValue = $setup[$theKey];
695  if ((int)$theKey && strpos($theKey, '.') === FALSE) {
696  $conf = $setup[$theKey . '.'];
697  $content .= $this->cObjGetSingle($theValue, $conf, $addKey . $theKey);
698  }
699  }
700  return $content;
701  }
702  }
703 
714  public function cObjGetSingle($name, $conf, $TSkey = '__') {
715  global $TYPO3_CONF_VARS;
716  $content = '';
717  // Checking that the function is not called eternally. This is done by interrupting at a depth of 100
718  $GLOBALS['TSFE']->cObjectDepthCounter--;
719  if ($GLOBALS['TSFE']->cObjectDepthCounter > 0) {
720  $name = trim($name);
721  if ($GLOBALS['TT']->LR) {
722  $GLOBALS['TT']->push($TSkey, $name);
723  }
724  // Checking if the COBJ is a reference to another object. (eg. name of 'blabla.blabla = < styles.something')
725  if ($name[0] === '<') {
726  $key = trim(substr($name, 1));
727  $cF = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\Parser\\TypoScriptParser');
728  // $name and $conf is loaded with the referenced values.
729  $confOverride = is_array($conf) ? $conf : array();
730  list($name, $conf) = $cF->getVal($key, $GLOBALS['TSFE']->tmpl->setup);
731  $conf = array_replace_recursive(is_array($conf) ? $conf : array(), $confOverride);
732  // Getting the cObject
733  $GLOBALS['TT']->incStackPointer();
734  $content .= $this->cObjGetSingle($name, $conf, $key);
735  $GLOBALS['TT']->decStackPointer();
736  } else {
737  $hooked = FALSE;
738  // Application defined cObjects
739  if (!empty($this->cObjHookObjectsRegistry[$name])) {
740  if (empty($this->cObjHookObjectsArr[$name])) {
741  $this->cObjHookObjectsArr[$name] = GeneralUtility::getUserObj($this->cObjHookObjectsRegistry[$name]);
742  }
743  $hookObj = $this->cObjHookObjectsArr[$name];
744  if (method_exists($hookObj, 'cObjGetSingleExt')) {
745  $content .= $hookObj->cObjGetSingleExt($name, $conf, $TSkey, $this);
746  $hooked = TRUE;
747  }
748  }
749  if (!$hooked) {
750  $contentObject = $this->getContentObject($name);
751  if ($contentObject) {
752  $content .= $contentObject->render($conf);
753  } else {
754  // Call hook functions for extra processing
755  if ($name && is_array($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'])) {
756  foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClassDefault'] as $classData) {
757  $hookObject = GeneralUtility::getUserObj($classData);
758  if (!$hookObject instanceof \TYPO3\CMS\Frontend\ContentObject\ContentObjectGetSingleHookInterface) {
759  throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectGetSingleHookInterface', 1195043731);
760  }
762  $content .= $hookObject->getSingleContentObject($name, (array) $conf, $TSkey, $this);
763  }
764  } else {
765  // Log error in AdminPanel
766  $warning = sprintf('Content Object "%s" does not exist', $name);
767  $GLOBALS['TT']->setTSlogMessage($warning, 2);
768  }
769  }
770  }
771  }
772  if ($GLOBALS['TT']->LR) {
773  $GLOBALS['TT']->pull($content);
774  }
775  }
776  // Increasing on exit...
777  $GLOBALS['TSFE']->cObjectDepthCounter++;
778  return $content;
779  }
780 
787  public function getContentObject($name) {
788  if (!isset($this->contentObjectClassMapping[$name])) {
789  return NULL;
790  }
791  $fullyQualifiedClassName = 'TYPO3\\CMS\\Frontend\\ContentObject\\' . $this->contentObjectClassMapping[$name] . 'ContentObject';
792  return GeneralUtility::makeInstance($fullyQualifiedClassName, $this);
793  }
794 
795  /********************************************
796  *
797  * Functions rendering content objects (cObjects)
798  *
799  ********************************************/
800 
808  public function FLOWPLAYER($conf) {
809  return $this->getContentObject('FLOWPLAYER')->render($conf);
810  }
811 
819  public function TEXT($conf) {
820  return $this->getContentObject('TEXT')->render($conf);
821  }
822 
830  public function CLEARGIF($conf) {
831  return $this->getContentObject('CLEARGIF')->render($conf);
832  }
833 
842  public function COBJ_ARRAY($conf, $ext = '') {
843  if ($ext === 'INT') {
844  return $this->getContentObject('COA_INT')->render($conf);
845  } else {
846  return $this->getContentObject('COA')->render($conf);
847  }
848  }
849 
858  public function USER($conf, $ext = '') {
859  if ($ext === 'INT') {
860  return $this->getContentObject('USER_INT')->render($conf);
861  } else {
862  return $this->getContentObject('USER')->render($conf);
863  }
864  }
865 
874  public function getUserObjectType() {
875  return $this->userObjectType;
876  }
877 
885  $this->userObjectType = $userObjectType;
886  }
887 
893  public function convertToUserIntObject() {
894  if ($this->userObjectType !== self::OBJECTTYPE_USER) {
895  $GLOBALS['TT']->setTSlogMessage('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer::convertToUserIntObject() ' . 'is called in the wrong context or for the wrong object type', 2);
896  } else {
897  $this->doConvertToUserIntObject = TRUE;
898  }
899  }
900 
908  public function FILE($conf) {
909  return $this->getContentObject('FILE')->render($conf);
910  }
911 
919  public function FILES($conf) {
920  return $this->getContentObject('FILES')->render($conf);
921  }
922 
931  public function IMAGE($conf) {
932  return $this->getContentObject('IMAGE')->render($conf);
933  }
934 
943  public function IMG_RESOURCE($conf) {
944  return $this->getContentObject('IMG_RESOURCE')->render($conf);
945  }
946 
954  public function IMGTEXT($conf) {
955  return $this->getContentObject('IMGTEXT')->render($conf);
956  }
957 
965  public function CONTENT($conf) {
966  return $this->getContentObject('CONTENT')->render($conf);
967  }
968 
976  public function RECORDS($conf) {
977  return $this->getContentObject('RECORDS')->render($conf);
978  }
979 
987  public function HMENU($conf) {
988  return $this->getContentObject('HMENU')->render($conf);
989  }
990 
998  public function CTABLE($conf) {
999  return $this->getContentObject('CTABLE')->render($conf);
1000  }
1001 
1009  public function OTABLE($conf) {
1010  return $this->getContentObject('OTABLE')->render($conf);
1011  }
1012 
1020  public function COLUMNS($conf) {
1021  return $this->getContentObject('COLUMNS')->render($conf);
1022  }
1023 
1031  public function HRULER($conf) {
1032  return $this->getContentObject('HRULER')->render($conf);
1033  }
1034 
1042  public function CASEFUNC($conf) {
1043  return $this->getContentObject('CASE')->render($conf);
1044  }
1045 
1055  public function LOAD_REGISTER($conf, $name) {
1056  if ($name === 'RESTORE_REGISTER') {
1057  return $this->getContentObject('RESTORE_REGISTER')->render();
1058  } else {
1059  return $this->getContentObject('LOAD_REGISTER')->render($conf);
1060  }
1061  }
1062 
1071  public function FORM($conf, $formData = '') {
1072  return $this->getContentObject('FORM')->render($conf, $formData);
1073  }
1074 
1082  public function SEARCHRESULT($conf) {
1083  return $this->getContentObject('SEARCHRESULT')->render($conf);
1084  }
1085 
1094  public function TEMPLATE($conf) {
1095  return $this->getContentObject('TEMPLATE')->render($conf);
1096  }
1097 
1106  protected function FLUIDTEMPLATE(array $conf) {
1107  return $this->getContentObject('FLUIDTEMPLATE')->render($conf);
1108  }
1109 
1117  public function MULTIMEDIA($conf) {
1118  return $this->getContentObject('MULTIMEDIA')->render($conf);
1119  }
1120 
1127  public function MEDIA($conf) {
1128  return $this->getContentObject('MEDIA')->render($conf);
1129  }
1130 
1137  public function SWFOBJECT($conf) {
1138  return $this->getContentObject('SWFOBJECT')->render($conf);
1139  }
1140 
1147  public function QTOBJECT($conf) {
1148  return $this->getContentObject('QTOBJECT')->render($conf);
1149  }
1150 
1157  public function SVG($conf) {
1158  return $this->getContentObject('SVG')->render($conf);
1159  }
1160 
1161  /************************************
1162  *
1163  * Various helper functions for content objects:
1164  *
1165  ************************************/
1174  public function readFlexformIntoConf($flexData, &$conf, $recursive = FALSE) {
1175  if ($recursive === FALSE && is_string($flexData)) {
1176  $flexData = GeneralUtility::xml2array($flexData, 'T3');
1177  }
1178  if (is_array($flexData) && isset($flexData['data']['sDEF']['lDEF'])) {
1179  $flexData = $flexData['data']['sDEF']['lDEF'];
1180  }
1181  if (!is_array($flexData)) {
1182  return;
1183  }
1184  foreach ($flexData as $key => $value) {
1185  if (!is_array($value)) {
1186  continue;
1187  }
1188  if (isset($value['el'])) {
1189  if (is_array($value['el']) && count($value['el']) > 0) {
1190  foreach ($value['el'] as $ekey => $element) {
1191  if (isset($element['vDEF'])) {
1192  $conf[$ekey] = $element['vDEF'];
1193  } else {
1194  if (is_array($element)) {
1195  $this->readFlexformIntoConf($element, $conf[$key][key($element)][$ekey], TRUE);
1196  } else {
1197  $this->readFlexformIntoConf($element, $conf[$key][$ekey], TRUE);
1198  }
1199  }
1200  }
1201  } else {
1202  $this->readFlexformIntoConf($value['el'], $conf[$key], TRUE);
1203  }
1204  }
1205  if (isset($value['vDEF'])) {
1206  $conf[$key] = $value['vDEF'];
1207  }
1208  }
1209  }
1210 
1220  public function getSlidePids($pidList, $pidConf) {
1221  $pidList = isset($pidConf) ? trim($this->stdWrap($pidList, $pidConf)) : trim($pidList);
1222  if ($pidList === '') {
1223  $pidList = 'this';
1224  }
1225  if (trim($pidList)) {
1226  $listArr = GeneralUtility::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $pidList));
1227  $listArr = $this->checkPidArray($listArr);
1228  }
1229  $pidList = array();
1230  if (is_array($listArr) && count($listArr)) {
1231  foreach ($listArr as $uid) {
1232  $page = $GLOBALS['TSFE']->sys_page->getPage($uid);
1233  if (!$page['is_siteroot']) {
1234  $pidList[] = $page['pid'];
1235  }
1236  }
1237  }
1238  return implode(',', $pidList);
1239  }
1240 
1252  public function getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal) {
1253  if (!$GLOBALS['TSFE']->no_cache || !isset($_POST[$fieldName]) && !isset($_GET[$fieldName]) || $noValueInsert) {
1254  return $defaultVal;
1255  } else {
1256  return GeneralUtility::_GP($fieldName);
1257  }
1258  }
1259 
1272  public function cImage($file, $conf) {
1273  $info = $this->getImgResource($file, $conf['file.']);
1274  $GLOBALS['TSFE']->lastImageInfo = $info;
1275  if (!is_array($info)) {
1276  return '';
1277  }
1278  if (is_file(PATH_site . $info['3'])) {
1280  $source = $GLOBALS['TSFE']->absRefPrefix . $source;
1281  } else {
1282  $source = $info[3];
1283  }
1284 
1285  $layoutKey = $this->stdWrap($conf['layoutKey'], $conf['layoutKey.']);
1286  $imageTagTemplate = $this->getImageTagTemplate($layoutKey, $conf);
1287  $sourceCollection = $this->getImageSourceCollection($layoutKey, $conf, $file);
1288 
1289  // This array is used to collect the image-refs on the page...
1290  $GLOBALS['TSFE']->imagesOnPage[] = $source;
1291  $altParam = $this->getAltParam($conf);
1292  $params = $this->stdWrapValue('params', $conf);
1293  if ($params !== '' && $params{0} !== ' ') {
1294  $params = ' ' . $params;
1295  }
1296 
1297  $imageTagValues = array(
1298  'width' => $info[0],
1299  'height' => $info[1],
1300  'src' => htmlspecialchars($source),
1301  'params' => $params,
1302  'altParams' => $altParam,
1303  'border' => $this->getBorderAttr(' border="' . (int)$conf['border'] . '"'),
1304  'sourceCollection' => $sourceCollection,
1305  'selfClosingTagSlash' => (!empty($GLOBALS['TSFE']->xhtmlDoctype) ? ' /' : ''),
1306  );
1307 
1308  $theValue = $this->substituteMarkerArray($imageTagTemplate, $imageTagValues, '###|###', TRUE, TRUE);
1309 
1310  $linkWrap = isset($conf['linkWrap.']) ? $this->stdWrap($conf['linkWrap'], $conf['linkWrap.']) : $conf['linkWrap'];
1311  if ($linkWrap) {
1312  $theValue = $this->linkWrap($theValue, $linkWrap);
1313  } elseif ($conf['imageLinkWrap']) {
1314  $originalFile = !empty($info['originalFile']) ? $info['originalFile'] : $info['origFile'];
1315  $theValue = $this->imageLinkWrap($theValue, $originalFile, $conf['imageLinkWrap.']);
1316  }
1317  $wrap = isset($conf['wrap.']) ? $this->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
1318  if ($wrap) {
1319  $theValue = $this->wrap($theValue, $conf['wrap']);
1320  }
1321  return $theValue;
1322  }
1323 
1332  public function getBorderAttr($borderAttr) {
1333  if (!GeneralUtility::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype) && $GLOBALS['TSFE']->config['config']['doctype'] != 'html5' && !$GLOBALS['TSFE']->config['config']['disableImgBorderAttr']) {
1334  return $borderAttr;
1335  }
1336  }
1337 
1346  public function getImageTagTemplate($layoutKey, $conf) {
1347  if ($layoutKey && isset($conf['layout.']) && isset($conf['layout.'][$layoutKey . '.'])) {
1348  $imageTagLayout = $this->stdWrap($conf['layout.'][$layoutKey . '.']['element'], $conf['layout.'][$layoutKey . '.']['element.']);
1349  } else {
1350  $imageTagLayout = '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>';
1351  }
1352  return $imageTagLayout;
1353  }
1354 
1364  public function getImageSourceCollection($layoutKey, $conf, $file) {
1365  $sourceCollection = '';
1366  if ($layoutKey && $conf['sourceCollection.'] && ($conf['layout.'][$layoutKey . '.']['source'] || $conf['layout.'][$layoutKey . '.']['source.'])) {
1367 
1368  // find active sourceCollection
1369  $activeSourceCollections = array();
1370  foreach ($conf['sourceCollection.'] as $sourceCollectionKey => $sourceCollectionConfiguration) {
1371  if (substr($sourceCollectionKey, -1) == '.') {
1372  if (empty($sourceCollectionConfiguration['if.']) || $this->checkIf($sourceCollectionConfiguration['if.'])) {
1373  $activeSourceCollections[] = $sourceCollectionConfiguration;
1374  }
1375  }
1376  }
1377 
1378  // apply option split to configurations
1379  $srcLayoutOptionSplitted = $GLOBALS['TSFE']->tmpl->splitConfArray($conf['layout.'][$layoutKey . '.'], count($activeSourceCollections));
1380 
1381  // render sources
1382  foreach ($activeSourceCollections as $key => $sourceConfiguration) {
1383  $sourceLayout = $this->stdWrap($srcLayoutOptionSplitted[$key]['source'], $srcLayoutOptionSplitted[$key]['source.']);
1384 
1385  $sourceRenderConfiguration = array (
1386  'file' => $file,
1387  'file.' => $conf['file.']
1388  );
1389 
1390  if (isset($sourceConfiguration['pixelDensity'])) {
1391  $pixelDensity = (int)$this->stdWrap($sourceConfiguration['pixelDensity'], $sourceConfiguration['pixelDensity.']);
1392  } else {
1393  $pixelDensity = 1;
1394  }
1395  $dimensionKeys = array('width', 'height', 'maxW', 'minW', 'maxH', 'minH');
1396  foreach ($dimensionKeys as $dimensionKey) {
1397  $dimension = $this->stdWrap($sourceConfiguration[$dimensionKey], $sourceConfiguration[$dimensionKey . '.']);
1398  if (!$dimension) {
1399  $dimension = $this->stdWrap($conf['file.'][$dimensionKey], $conf['file.'][$dimensionKey . '.']);
1400  }
1401  if ($dimension) {
1402  if (strstr($dimension, 'c') !== FALSE && ($dimensionKey === 'width' || $dimensionKey === 'height')) {
1403  $dimensionParts = explode('c', $dimension, 2);
1404  $dimension = (int)($dimensionParts[0] * $pixelDensity) . 'c';
1405  if ($dimensionParts[1]) {
1406  $dimension .= $dimensionParts[1];
1407  }
1408  } else {
1409  $dimension = (int)($dimension * $pixelDensity);
1410  }
1411  $sourceRenderConfiguration['file.'][$dimensionKey] = $dimension;
1412  // Remove the stdWrap properties for dimension as they have been processed already above.
1413  unset($sourceRenderConfiguration['file.'][$dimensionKey . '.']);
1414  }
1415  }
1416  $sourceInfo = $this->getImgResource($sourceRenderConfiguration['file'], $sourceRenderConfiguration['file.']);
1417  if ($sourceInfo) {
1418  $sourceConfiguration['width'] = $sourceInfo[0];
1419  $sourceConfiguration['height'] = $sourceInfo[1];
1420  $urlPrefix = '';
1421  if (parse_url($sourceInfo[3], PHP_URL_HOST) === NULL) {
1422  $urlPrefix = $GLOBALS['TSFE']->absRefPrefix;
1423  }
1424  $sourceConfiguration['src'] = htmlspecialchars($urlPrefix . $sourceInfo[3]);
1425  $sourceConfiguration['selfClosingTagSlash'] = (!empty($GLOBALS['TSFE']->xhtmlDoctype) ? ' /' : '');
1426 
1427  $oneSourceCollection = $this->substituteMarkerArray($sourceLayout, $sourceConfiguration, '###|###', TRUE, TRUE);
1428 
1429  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImageSourceCollection'])) {
1430  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImageSourceCollection'] as $classData) {
1431  $hookObject = GeneralUtility::getUserObj($classData);
1432  if (!$hookObject instanceof ContentObjectOneSourceCollectionHookInterface) {
1433  throw new \UnexpectedValueException(
1434  '$hookObject must implement interface TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectOneSourceCollectionHookInterface',
1435  1380007853
1436  );
1437  }
1438  $oneSourceCollection = $hookObject->getOneSourceCollection((array) $sourceRenderConfiguration, (array) $sourceConfiguration, $oneSourceCollection, $this);
1439  }
1440  }
1441 
1442  $sourceCollection .= $oneSourceCollection;
1443  }
1444  }
1445  }
1446  return $sourceCollection;
1447  }
1448 
1459  public function imageLinkWrap($string, $imageFile, $conf) {
1460  $a1 = '';
1461  $a2 = '';
1462  $content = $string;
1463  $enable = isset($conf['enable.']) ? $this->stdWrap($conf['enable'], $conf['enable.']) : $conf['enable'];
1464  if ($enable) {
1465  $content = $this->typolink($string, $conf['typolink.']);
1466  if (isset($conf['file.'])) {
1467  $imageFile = $this->stdWrap($imageFile, $conf['file.']);
1468  }
1469 
1470  if ($imageFile instanceof \TYPO3\CMS\Core\Resource\File) {
1471  $file = $imageFile;
1472  } elseif ($imageFile instanceof \TYPO3\CMS\Core\Resource\FileReference) {
1473  $file = $imageFile->getOriginalFile();
1474  } else {
1475  if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($imageFile)) {
1476  $file = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileObject((int)$imageFile);
1477  } else {
1478  $file = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileObjectFromCombinedIdentifier($imageFile);
1479  }
1480  }
1481 
1482  // Create imageFileLink if not created with typolink
1483  if ($content == $string) {
1484  $parameterNames = array('width', 'height', 'effects', 'bodyTag', 'title', 'wrap');
1485  $parameters = array();
1486  $sample = isset($conf['sample.']) ? $this->stdWrap($conf['sample'], $conf['sample.']) : $conf['sample'];
1487  if ($sample) {
1488  $parameters['sample'] = 1;
1489  }
1490  foreach ($parameterNames as $parameterName) {
1491  if (isset($conf[$parameterName . '.'])) {
1492  $conf[$parameterName] = $this->stdWrap($conf[$parameterName], $conf[$parameterName . '.']);
1493  }
1494  if (isset($conf[$parameterName]) && $conf[$parameterName]) {
1495  $parameters[$parameterName] = $conf[$parameterName];
1496  }
1497  }
1498  $parametersEncoded = base64_encode(serialize($parameters));
1499  $hmac = GeneralUtility::hmac(implode('|', array($file->getUid(), $parametersEncoded)));
1500  $params = '&md5=' . $hmac;
1501  foreach (str_split($parametersEncoded, 64) as $index => $chunk) {
1502  $params .= '&parameters' . rawurlencode('[') . $index . rawurlencode(']') . '=' . rawurlencode($chunk);
1503  }
1504  $url = $GLOBALS['TSFE']->absRefPrefix . 'index.php?eID=tx_cms_showpic&file=' . $file->getUid() . $params;
1505  $directImageLink = isset($conf['directImageLink.']) ? $this->stdWrap($conf['directImageLink'], $conf['directImageLink.']) : $conf['directImageLink'];
1506  if ($directImageLink) {
1507  $imgResourceConf = array(
1508  'file' => $imageFile,
1509  'file.' => $conf
1510  );
1511  $url = $this->IMG_RESOURCE($imgResourceConf);
1512  if (!$url) {
1513  // If no imagemagick / gm is available
1514  $url = $imageFile;
1515  }
1516  }
1517  // Create TARGET-attribute only if the right doctype is used
1518  if (!GeneralUtility::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype)) {
1519  $target = isset($conf['target.']) ? $this->stdWrap($conf['target'], $conf['target.']) : $conf['target'];
1520  if ($target) {
1521  $target = ' target="' . htmlspecialchars($target) . '"';
1522  } else {
1523  $target = ' target="thePicture"';
1524  }
1525  } else {
1526  $target = '';
1527  }
1528  $conf['JSwindow'] = isset($conf['JSwindow.']) ? $this->stdWrap($conf['JSwindow'], $conf['JSwindow.']) : $conf['JSwindow'];
1529  if ($conf['JSwindow']) {
1530  if ($conf['JSwindow.']['altUrl'] || $conf['JSwindow.']['altUrl.']) {
1531  $altUrl = isset($conf['JSwindow.']['altUrl.']) ? $this->stdWrap($conf['JSwindow.']['altUrl'], $conf['JSwindow.']['altUrl.']) : $conf['JSwindow.']['altUrl'];
1532  if ($altUrl) {
1533  $url = $altUrl . ($conf['JSwindow.']['altUrl_noDefaultParams'] ? '' : '?file=' . rawurlencode($imageFile) . $params);
1534  }
1535  }
1536 
1537  $processedFile = $file->process('Image.CropScaleMask', $conf);
1538  $JSwindowExpand = isset($conf['JSwindow.']['expand.']) ? $this->stdWrap($conf['JSwindow.']['expand'], $conf['JSwindow.']['expand.']) : $conf['JSwindow.']['expand'];
1539  $offset = GeneralUtility::intExplode(',', $JSwindowExpand . ',');
1540  $newWindow = isset($conf['JSwindow.']['newWindow.']) ? $this->stdWrap($conf['JSwindow.']['newWindow'], $conf['JSwindow.']['newWindow.']) : $conf['JSwindow.']['newWindow'];
1541  $a1 = '<a href="' . htmlspecialchars($url) . '" onclick="' . htmlspecialchars(('openPic(\'' . $GLOBALS['TSFE']->baseUrlWrap($url) . '\',\'' . ($newWindow ? md5($url) : 'thePicture') . '\',\'width=' . ($processedFile->getProperty('width') + $offset[0]) . ',height=' . ($processedFile->getProperty('height') + $offset[1]) . ',status=0,menubar=0\'); return false;')) . '"' . $target . $GLOBALS['TSFE']->ATagParams . '>';
1542  $a2 = '</a>';
1543  $GLOBALS['TSFE']->setJS('openPic');
1544  } else {
1545  $conf['linkParams.']['parameter'] = $url;
1546  $string = $this->typoLink($string, $conf['linkParams.']);
1547  }
1548  if (isset($conf['stdWrap.'])) {
1549  $string = $this->stdWrap($string, $conf['stdWrap.']);
1550  }
1551  $content = $a1 . $string . $a2;
1552  }
1553  }
1554  return $content;
1555  }
1556 
1566  public function fileResource($fName, $addParams = 'alt="" title=""') {
1567  $incFile = $GLOBALS['TSFE']->tmpl->getFileName($fName);
1568  if ($incFile && file_exists($incFile)) {
1569  $fileinfo = GeneralUtility::split_fileref($incFile);
1570  if (GeneralUtility::inList('jpg,gif,jpeg,png', $fileinfo['fileext'])) {
1571  $imgFile = $incFile;
1572  $imgInfo = @getImageSize($imgFile);
1573  return '<img src="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix . $imgFile) . '" width="' . $imgInfo[0] . '" height="' . $imgInfo[1] . '"' . $this->getBorderAttr(' border="0"') . ' ' . $addParams . ' />';
1574  } elseif (filesize($incFile) < 1024 * 1024) {
1575  return $GLOBALS['TSFE']->tmpl->fileContent($incFile);
1576  }
1577  }
1578  }
1579 
1590  public function lastChanged($tstamp) {
1591  $tstamp = (int)$tstamp;
1592  if ($tstamp > (int)$GLOBALS['TSFE']->register['SYS_LASTCHANGED']) {
1593  $GLOBALS['TSFE']->register['SYS_LASTCHANGED'] = $tstamp;
1594  }
1595  }
1596 
1607  public function linkWrap($content, $wrap) {
1608  $wrapArr = explode('|', $wrap);
1609  if (preg_match('/\\{([0-9]*)\\}/', $wrapArr[0], $reg)) {
1610  if ($uid = $GLOBALS['TSFE']->tmpl->rootLine[$reg[1]]['uid']) {
1611  $wrapArr[0] = str_replace($reg[0], $uid, $wrapArr[0]);
1612  }
1613  }
1614  return trim($wrapArr[0]) . $content . trim($wrapArr[1]);
1615  }
1616 
1627  public function getAltParam($conf, $longDesc = TRUE) {
1628  $altText = isset($conf['altText.']) ? trim($this->stdWrap($conf['altText'], $conf['altText.'])) : trim($conf['altText']);
1629  $titleText = isset($conf['titleText.']) ? trim($this->stdWrap($conf['titleText'], $conf['titleText.'])) : trim($conf['titleText']);
1630  if (isset($conf['longdescURL.']) && $GLOBALS['TSFE']->config['config']['doctype'] != 'html5') {
1631  $longDesc = $this->typoLink_URL($conf['longdescURL.']);
1632  } else {
1633  $longDesc = trim($conf['longdescURL']);
1634  }
1635  $longDescUrl = strip_tags($longDescUrl);
1636  // "alt":
1637  $altParam = ' alt="' . htmlspecialchars($altText) . '"';
1638  // "title":
1639  $emptyTitleHandling = 'useAlt';
1640  $emptyTitleHandling = isset($conf['emptyTitleHandling.']) ? $this->stdWrap($conf['emptyTitleHandling'], $conf['emptyTitleHandling.']) : $conf['emptyTitleHandling'];
1641  // Choices: 'keepEmpty' | 'useAlt' | 'removeAttr'
1642  if ($titleText || $emptyTitleHandling == 'keepEmpty') {
1643  $altParam .= ' title="' . htmlspecialchars($titleText) . '"';
1644  } elseif (!$titleText && $emptyTitleHandling == 'useAlt') {
1645  $altParam .= ' title="' . htmlspecialchars($altText) . '"';
1646  }
1647  // "longDesc" URL
1648  if ($longDesc && !empty($longDescUrl)) {
1649  $altParam .= ' longdesc="' . htmlspecialchars($longDescUrl) . '"';
1650  }
1651  return $altParam;
1652  }
1653 
1662  public function cleanFormName($name) {
1663  // Turn data[x][y] into data:x:y:
1664  $name = preg_replace('/\\[|\\]\\[?/', ':', trim($name));
1665  // Remove illegal chars like _
1666  return preg_replace('#[^:a-zA-Z0-9]#', '', $name);
1667  }
1668 
1679  public function getATagParams($conf, $addGlobal = 1) {
1680  $aTagParams = '';
1681  if ($conf['ATagParams.']) {
1682  $aTagParams = ' ' . $this->stdWrap($conf['ATagParams'], $conf['ATagParams.']);
1683  } elseif ($conf['ATagParams']) {
1684  $aTagParams = ' ' . $conf['ATagParams'];
1685  }
1686  if ($addGlobal) {
1687  $aTagParams = ' ' . trim(($GLOBALS['TSFE']->ATagParams . $aTagParams));
1688  }
1689  // Extend params
1690  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getATagParamsPostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getATagParamsPostProc'])) {
1691  $_params = array(
1692  'conf' => &$conf,
1693  'aTagParams' => &$aTagParams
1694  );
1695  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getATagParamsPostProc'] as $objRef) {
1696  $processor =& GeneralUtility::getUserObj($objRef);
1697  $aTagParams = $processor->process($_params, $this);
1698  }
1699  }
1700 
1701  $aTagParams = trim($aTagParams);
1702  if (!empty($aTagParams)) {
1703  $aTagParams = ' ' . $aTagParams;
1704  }
1705 
1706  return $aTagParams;
1707  }
1708 
1718  public function extLinkATagParams($URL, $TYPE) {
1719  $out = '';
1720  if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']) {
1721  $extLinkATagParamsHandler = GeneralUtility::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['extLinkATagParamsHandler']);
1722  if (method_exists($extLinkATagParamsHandler, 'main')) {
1723  $out .= trim($extLinkATagParamsHandler->main($URL, $TYPE, $this));
1724  }
1725  }
1726  return trim($out) ? ' ' . trim($out) : '';
1727  }
1728 
1729  /***********************************************
1730  *
1731  * HTML template processing functions
1732  *
1733  ***********************************************/
1752  public function getSubpart($content, $marker) {
1753  return \TYPO3\CMS\Core\Html\HtmlParser::getSubpart($content, $marker);
1754  }
1755 
1768  public function substituteSubpart($content, $marker, $subpartContent, $recursive = 1) {
1769  return \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpart($content, $marker, $subpartContent, $recursive);
1770  }
1771 
1779  public function substituteSubpartArray($content, array $subpartsContent) {
1780  return \TYPO3\CMS\Core\Html\HtmlParser::substituteSubpartArray($content, $subpartsContent);
1781  }
1782 
1793  public function substituteMarker($content, $marker, $markContent) {
1794  return \TYPO3\CMS\Core\Html\HtmlParser::substituteMarker($content, $marker, $markContent);
1795  }
1796 
1829  public function substituteMarkerArrayCached($content, array $markContentArray = NULL, array $subpartContentArray = NULL, array $wrappedSubpartContentArray = NULL) {
1830  $GLOBALS['TT']->push('substituteMarkerArrayCached');
1831  // If not arrays then set them
1832  if (is_null($markContentArray)) {
1833  // Plain markers
1834  $markContentArray = array();
1835  }
1836  if (is_null($subpartContentArray)) {
1837  // Subparts being directly substituted
1838  $subpartContentArray = array();
1839  }
1840  if (is_null($wrappedSubpartContentArray)) {
1841  // Subparts being wrapped
1842  $wrappedSubpartContentArray = array();
1843  }
1844  // Finding keys and check hash:
1845  $sPkeys = array_keys($subpartContentArray);
1846  $wPkeys = array_keys($wrappedSubpartContentArray);
1847  $keysToReplace = array_merge(array_keys($markContentArray), $sPkeys, $wPkeys);
1848  if (empty($keysToReplace)) {
1849  $GLOBALS['TT']->pull();
1850  return $content;
1851  }
1852  asort($keysToReplace);
1853  $storeKey = md5('substituteMarkerArrayCached_storeKey:' . serialize(array(
1854  $content,
1855  $keysToReplace
1856  )));
1857  if ($this->substMarkerCache[$storeKey]) {
1858  $storeArr = $this->substMarkerCache[$storeKey];
1859  $GLOBALS['TT']->setTSlogMessage('Cached', 0);
1860  } else {
1861  $storeArrDat = $GLOBALS['TSFE']->sys_page->getHash($storeKey);
1862  if (is_array($storeArrDat)) {
1863  $storeArr = $storeArrDat;
1864  // Setting cache:
1865  $this->substMarkerCache[$storeKey] = $storeArr;
1866  $GLOBALS['TT']->setTSlogMessage('Cached from DB', 0);
1867  } else {
1868  // Finding subparts and substituting them with the subpart as a marker
1869  foreach ($sPkeys as $sPK) {
1870  $content = $this->substituteSubpart($content, $sPK, $sPK);
1871  }
1872  // Finding subparts and wrapping them with markers
1873  foreach ($wPkeys as $wPK) {
1874  $content = $this->substituteSubpart($content, $wPK, array(
1875  $wPK,
1876  $wPK
1877  ));
1878  }
1879 
1880  $storeArr = array();
1881  $result = preg_match_all('/###([^#](?:[^#]*+|#{1,2}[^#])+)###/', $content, $markersInContent);
1882  if ($result !== FALSE && !empty($markersInContent[1])) {
1883  $keysToReplaceFlipped = array_flip($keysToReplace);
1884  $regexKeys = array();
1885  $wrappedKeys = array();
1886  // Traverse keys and quote them for reg ex.
1887  foreach ($markersInContent[1] as $key) {
1888  if (isset($keysToReplaceFlipped['###' . $key . '###'])) {
1889  $regexKeys[] = preg_quote($key, '/');
1890  $wrappedKeys[] = '###' . $key . '###';
1891  }
1892  }
1893  $regex = '/###(?:' . implode('|', $regexKeys) . ')###/';
1894  $storeArr['c'] = preg_split($regex, $content); // contains all content parts around markers
1895  $storeArr['k'] = $wrappedKeys; // contains all markers incl. ###
1896  // Setting cache:
1897  $this->substMarkerCache[$storeKey] = $storeArr;
1898  // Storing the cached data:
1899  $GLOBALS['TSFE']->sys_page->storeHash($storeKey, $storeArr, 'substMarkArrayCached');
1900  }
1901  $GLOBALS['TT']->setTSlogMessage('Parsing', 0);
1902  }
1903  }
1904  if (!empty($storeArr['k']) && is_array($storeArr['k'])) {
1905  // Substitution/Merging:
1906  // Merging content types together, resetting
1907  $valueArr = array_merge($markContentArray, $subpartContentArray, $wrappedSubpartContentArray);
1908  $wSCA_reg = array();
1909  $content = '';
1910  // Traversing the keyList array and merging the static and dynamic content
1911  foreach ($storeArr['k'] as $n => $keyN) {
1912  // add content before marker
1913  $content .= $storeArr['c'][$n];
1914  if (!is_array($valueArr[$keyN])) {
1915  // fetch marker replacement from $markContentArray or $subpartContentArray
1916  $content .= $valueArr[$keyN];
1917  } else {
1918  if (!isset($wSCA_reg[$keyN])) {
1919  $wSCA_reg[$keyN] = 0;
1920  }
1921  // fetch marker replacement from $wrappedSubpartContentArray
1922  $content .= $valueArr[$keyN][$wSCA_reg[$keyN] % 2];
1923  $wSCA_reg[$keyN]++;
1924  }
1925  }
1926  // add remaining content
1927  $content .= $storeArr['c'][count($storeArr['k'])];
1928  }
1929  $GLOBALS['TT']->pull();
1930  return $content;
1931  }
1932 
1952  public function substituteMarkerArray($content, array $markContentArray, $wrap = '', $uppercase = FALSE, $deleteUnused = FALSE) {
1953  return \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($content, $markContentArray, $wrap, $uppercase, $deleteUnused);
1954  }
1955 
1964  public function substituteMarkerInObject(&$tree, array $markContentArray) {
1965  if (is_array($tree)) {
1966  foreach ($tree as $key => $value) {
1967  $this->substituteMarkerInObject($tree[$key], $markContentArray);
1968  }
1969  } else {
1970  $tree = $this->substituteMarkerArray($tree, $markContentArray);
1971  }
1972  return $tree;
1973  }
1974 
1985  public function substituteMarkerAndSubpartArrayRecursive($content, array $markersAndSubparts, $wrap = '', $uppercase = FALSE, $deleteUnused = FALSE) {
1986  return \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerAndSubpartArrayRecursive($content, $markersAndSubparts, $wrap, $uppercase, $deleteUnused);
1987  }
1988 
2001  public function fillInMarkerArray(array $markContentArray, array $row, $fieldList = '', $nl2br = TRUE, $prefix = 'FIELD_', $HSC = FALSE) {
2002  if ($fieldList) {
2003  $fArr = GeneralUtility::trimExplode(',', $fieldList, TRUE);
2004  foreach ($fArr as $field) {
2005  $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($row[$field], !empty($GLOBALS['TSFE']->xhtmlDoctype)) : $row[$field];
2006  }
2007  } else {
2008  if (is_array($row)) {
2009  foreach ($row as $field => $value) {
2010  if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($field)) {
2011  if ($HSC) {
2012  $value = htmlspecialchars($value);
2013  }
2014  $markContentArray['###' . $prefix . $field . '###'] = $nl2br ? nl2br($value, !empty($GLOBALS['TSFE']->xhtmlDoctype)) : $value;
2015  }
2016  }
2017  }
2018  }
2019  return $markContentArray;
2020  }
2021 
2027  public function setCurrentFile($fileObject) {
2028  $this->currentFile = $fileObject;
2029  }
2030 
2036  public function getCurrentFile() {
2037  return $this->currentFile;
2038  }
2039 
2040  /***********************************************
2041  *
2042  * "stdWrap" + sub functions
2043  *
2044  ***********************************************/
2056  public function stdWrap($content = '', $conf = array()) {
2057  // If there is any hook object, activate all of the process and override functions.
2058  // The hook interface ContentObjectStdWrapHookInterface takes care that all 4 methods exist.
2059  if ($this->stdWrapHookObjects) {
2060  $conf['stdWrapPreProcess'] = 1;
2061  $conf['stdWrapOverride'] = 1;
2062  $conf['stdWrapProcess'] = 1;
2063  $conf['stdWrapPostProcess'] = 1;
2064  }
2065 
2066  if (!is_array($conf) || !$conf) {
2067  return $content;
2068  }
2069 
2070  // Cache handling
2071  if (is_array($conf['cache.'])) {
2072  $conf['cache.']['key'] = $this->stdWrap($conf['cache.']['key'], $conf['cache.']['key.']);
2073  $conf['cache.']['tags'] = $this->stdWrap($conf['cache.']['tags'], $conf['cache.']['tags.']);
2074  $conf['cache.']['lifetime'] = $this->stdWrap($conf['cache.']['lifetime'], $conf['cache.']['lifetime.']);
2075  $conf['cacheRead'] = 1;
2076  $conf['cacheStore'] = 1;
2077  }
2078  // Check, which of the available stdWrap functions is needed for the current conf Array
2079  // and keep only those but still in the same order
2080  $sortedConf = array_intersect_key($this->stdWrapOrder, $conf);
2081  // Functions types that should not make use of nested stdWrap function calls to avoid conflicts with internal TypoScript used by these functions
2082  $stdWrapDisabledFunctionTypes = 'cObject,functionName,stdWrap';
2083  // Additional Array to check whether a function has already been executed
2084  $isExecuted = array();
2085  // Additional switch to make sure 'required', 'if' and 'fieldRequired'
2086  // will still stop rendering immediately in case they return FALSE
2087  $this->stdWrapRecursionLevel++;
2088  $this->stopRendering[$this->stdWrapRecursionLevel] = FALSE;
2089  // execute each function in the predefined order
2090  foreach ($sortedConf as $stdWrapName => $functionType) {
2091  // eliminate the second key of a pair 'key'|'key.' to make sure functions get called only once and check if rendering has been stopped
2092  if (!$isExecuted[$stdWrapName] && !$this->stopRendering[$this->stdWrapRecursionLevel]) {
2093  $functionName = rtrim($stdWrapName, '.');
2094  $functionProperties = $functionName . '.';
2095  // If there is any code one the next level, check if it contains "official" stdWrap functions
2096  // if yes, execute them first - will make each function stdWrap aware
2097  // so additional stdWrap calls within the functions can be removed, since the result will be the same
2098  // exception: the recursive stdWrap function and cObject will still be using their own stdWrap call, since it modifies the content and not a property
2099  if (count($conf[$functionProperties]) && !GeneralUtility::inList($stdWrapDisabledFunctionTypes, $functionType)) {
2100  if (array_intersect_key($this->stdWrapOrder, $conf[$functionProperties])) {
2101  $conf[$functionName] = $this->stdWrap($conf[$functionName], $conf[$functionProperties]);
2102  }
2103  }
2104  // Check if key is still containing something, since it might have been changed by next level stdWrap before
2105  if ((isset($conf[$functionName]) || $conf[$functionProperties]) && ($functionType !== 'boolean' || $conf[$functionName])) {
2106  // Get just that part of $conf that is needed for the particular function
2107  $singleConf = array(
2108  $functionName => $conf[$functionName],
2109  $functionProperties => $conf[$functionProperties]
2110  );
2111  // In this special case 'spaceBefore' and 'spaceAfter' need additional stuff from 'space.''
2112  if ($functionName === 'spaceBefore' || $functionName === 'spaceAfter') {
2113  $singleConf['space.'] = $conf['space.'];
2114  }
2115  // Hand over the whole $conf array to the stdWrapHookObjects
2116  if ($functionType === 'hook') {
2117  $singleConf = $conf;
2118  }
2119  // Add both keys - with and without the dot - to the set of executed functions
2120  $isExecuted[$functionName] = TRUE;
2121  $isExecuted[$functionProperties] = TRUE;
2122  // Call the function with the prefix stdWrap_ to make sure nobody can execute functions just by adding their name to the TS Array
2123  $functionName = 'stdWrap_' . $functionName;
2124  $content = $this->{$functionName}($content, $singleConf);
2125  } elseif ($functionType == 'boolean' && !$conf[$functionName]) {
2126  $isExecuted[$functionName] = TRUE;
2127  $isExecuted[$functionProperties] = TRUE;
2128  }
2129  }
2130  }
2131  unset($this->stopRendering[$this->stdWrapRecursionLevel]);
2132  $this->stdWrapRecursionLevel--;
2133 
2134  return $content;
2135  }
2136 
2145  public function stdWrapValue($key, array $config, $defaultValue = '') {
2146  if (isset($config[$key])) {
2147  if (!isset($config[$key . '.'])) {
2148  return $config[$key];
2149  }
2150  } elseif (isset($config[$key . '.'])) {
2151  $config[$key] = '';
2152  } else {
2153  return $defaultValue;
2154  }
2155  $stdWrapped = $this->stdWrap($config[$key], $config[$key . '.']);
2156  return $stdWrapped ?: $defaultValue;
2157  }
2158 
2168  public function stdWrap_stdWrapPreProcess($content = '', $conf = array()) {
2169  foreach ($this->stdWrapHookObjects as $hookObject) {
2170  $content = $hookObject->stdWrapPreProcess($content, $conf, $this);
2171  }
2172  return $content;
2173  }
2174 
2182  public function stdWrap_cacheRead($content = '', $conf = array()) {
2183  if (!empty($conf['cache.']['key'])) {
2185  $cacheFrontend = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager')->getCache('cache_hash');
2186  if ($cacheFrontend && $cacheFrontend->has($conf['cache.']['key'])) {
2187  $content = $cacheFrontend->get($conf['cache.']['key']);
2188  $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
2189  }
2190  }
2191  return $content;
2192  }
2193 
2201  public function stdWrap_addPageCacheTags($content = '', $conf = array()) {
2202  $tags = isset($conf['addPageCacheTags.'])
2203  ? $this->stdWrap($conf['addPageCacheTags'], $conf['addPageCacheTags.'])
2204  : $conf['addPageCacheTags'];
2205  if (!empty($tags)) {
2206  $cacheTags = GeneralUtility::trimExplode(',', $tags, TRUE);
2207  $GLOBALS['TSFE']->addCacheTags($cacheTags);
2208  }
2209  return $content;
2210  }
2211 
2220  public function stdWrap_setContentToCurrent($content = '', $conf = array()) {
2221  $this->data[$this->currentValKey] = $content;
2222  return $content;
2223  }
2224 
2233  public function stdWrap_setCurrent($content = '', $conf = array()) {
2234  $this->data[$this->currentValKey] = $conf['setCurrent'];
2235  return $content;
2236  }
2237 
2246  public function stdWrap_lang($content = '', $conf = array()) {
2247  if (isset($conf['lang.']) && $GLOBALS['TSFE']->config['config']['language'] && isset($conf['lang.'][$GLOBALS['TSFE']->config['config']['language']])) {
2248  $content = $conf['lang.'][$GLOBALS['TSFE']->config['config']['language']];
2249  }
2250  return $content;
2251  }
2252 
2261  public function stdWrap_data($content = '', $conf = array()) {
2262  $content = $this->getData($conf['data'], is_array($this->alternativeData) ? $this->alternativeData : $this->data);
2263  // This must be unset directly after
2264  $this->alternativeData = '';
2265  return $content;
2266  }
2267 
2276  public function stdWrap_field($content = '', $conf = array()) {
2277  return $this->getFieldVal($conf['field']);
2278  }
2279 
2289  public function stdWrap_current($content = '', $conf = array()) {
2290  return $this->data[$this->currentValKey];
2291  }
2292 
2302  public function stdWrap_cObject($content = '', $conf = array()) {
2303  return $this->cObjGetSingle($conf['cObject'], $conf['cObject.'], '/stdWrap/.cObject');
2304  }
2305 
2315  public function stdWrap_numRows($content = '', $conf = array()) {
2316  return $this->numRows($conf['numRows.']);
2317  }
2318 
2327  public function stdWrap_filelist($content = '', $conf = array()) {
2328  return $this->filelist($conf['filelist']);
2329  }
2330 
2339  public function stdWrap_preUserFunc($content = '', $conf = array()) {
2340  return $this->callUserFunction($conf['preUserFunc'], $conf['preUserFunc.'], $content);
2341  }
2342 
2352  public function stdWrap_stdWrapOverride($content = '', $conf = array()) {
2353  foreach ($this->stdWrapHookObjects as $hookObject) {
2354  $content = $hookObject->stdWrapOverride($content, $conf, $this);
2355  }
2356  return $content;
2357  }
2358 
2367  public function stdWrap_override($content = '', $conf = array()) {
2368  if (trim($conf['override'])) {
2369  $content = $conf['override'];
2370  }
2371  return $content;
2372  }
2373 
2383  public function stdWrap_preIfEmptyListNum($content = '', $conf = array()) {
2384  return $this->listNum($content, $conf['preIfEmptyListNum'], $conf['preIfEmptyListNum.']['splitChar']);
2385  }
2386 
2395  public function stdWrap_ifNull($content = '', $conf = array()) {
2396  return $content !== NULL ? $content : $conf['ifNull'];
2397  }
2398 
2408  public function stdWrap_ifEmpty($content = '', $conf = array()) {
2409  if (!trim($content)) {
2410  $content = $conf['ifEmpty'];
2411  }
2412  return $content;
2413  }
2414 
2424  public function stdWrap_ifBlank($content = '', $conf = array()) {
2425  if (!strlen(trim($content))) {
2426  $content = $conf['ifBlank'];
2427  }
2428  return $content;
2429  }
2430 
2441  public function stdWrap_listNum($content = '', $conf = array()) {
2442  return $this->listNum($content, $conf['listNum'], $conf['listNum.']['splitChar']);
2443  }
2444 
2453  public function stdWrap_trim($content = '', $conf = array()) {
2454  return trim($content);
2455  }
2456 
2465  public function stdWrap_strPad($content = '', $conf = array()) {
2466  // Must specify a length in conf for this to make sense
2467  $length = 0;
2468  // Padding with space is PHP-default
2469  $padWith = ' ';
2470  // Padding on the right side is PHP-default
2471  $padType = STR_PAD_RIGHT;
2472  if (!empty($conf['strPad.']['length'])) {
2473  $length = isset($conf['strPad.']['length.']) ? $this->stdWrap($conf['strPad.']['length'], $conf['strPad.']['length.']) : $conf['strPad.']['length'];
2474  $length = (int)$length;
2475  }
2476  if (isset($conf['strPad.']['padWith']) && strlen($conf['strPad.']['padWith']) > 0) {
2477  $padWith = isset($conf['strPad.']['padWith.']) ? $this->stdWrap($conf['strPad.']['padWith'], $conf['strPad.']['padWith.']) : $conf['strPad.']['padWith'];
2478  }
2479  if (!empty($conf['strPad.']['type'])) {
2480  $type = isset($conf['strPad.']['type.']) ? $this->stdWrap($conf['strPad.']['type'], $conf['strPad.']['type.']) : $conf['strPad.']['type'];
2481  if (strtolower($type) === 'left') {
2482  $padType = STR_PAD_LEFT;
2483  } elseif (strtolower($type) === 'both') {
2484  $padType = STR_PAD_BOTH;
2485  }
2486  }
2487  $content = str_pad($content, $length, $padWith, $padType);
2488  return $content;
2489  }
2490 
2502  public function stdWrap_stdWrap($content = '', $conf = array()) {
2503  return $this->stdWrap($content, $conf['stdWrap.']);
2504  }
2505 
2515  public function stdWrap_stdWrapProcess($content = '', $conf = array()) {
2516  foreach ($this->stdWrapHookObjects as $hookObject) {
2517  $content = $hookObject->stdWrapProcess($content, $conf, $this);
2518  }
2519  return $content;
2520  }
2521 
2531  public function stdWrap_required($content = '', $conf = array()) {
2532  if ((string) $content === '') {
2533  $content = '';
2534  $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
2535  }
2536  return $content;
2537  }
2538 
2548  public function stdWrap_if($content = '', $conf = array()) {
2549  if (empty($conf['if.']) || $this->checkIf($conf['if.'])) {
2550  return $content;
2551  }
2552  $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
2553  return '';
2554  }
2555 
2565  public function stdWrap_fieldRequired($content = '', $conf = array()) {
2566  if (!trim($this->data[$conf['fieldRequired']])) {
2567  $content = '';
2568  $this->stopRendering[$this->stdWrapRecursionLevel] = TRUE;
2569  }
2570  return $content;
2571  }
2572 
2581  public function stdWrap_csConv($content = '', $conf = array()) {
2582  return $GLOBALS['TSFE']->csConv($content, $conf['csConv']);
2583  }
2584 
2594  public function stdWrap_parseFunc($content = '', $conf = array()) {
2595  return $this->parseFunc($content, $conf['parseFunc.'], $conf['parseFunc']);
2596  }
2597 
2607  public function stdWrap_HTMLparser($content = '', $conf = array()) {
2608  if (is_array($conf['HTMLparser.'])) {
2609  $content = $this->HTMLparser_TSbridge($content, $conf['HTMLparser.']);
2610  }
2611  return $content;
2612  }
2613 
2623  public function stdWrap_split($content = '', $conf = array()) {
2624  return $this->splitObj($content, $conf['split.']);
2625  }
2626 
2635  public function stdWrap_replacement($content = '', $conf = array()) {
2636  return $this->replacement($content, $conf['replacement.']);
2637  }
2638 
2648  public function stdWrap_prioriCalc($content = '', $conf = array()) {
2650  if ($conf['prioriCalc'] == 'intval') {
2651  $content = (int)$content;
2652  }
2653  return $content;
2654  }
2655 
2664  public function stdWrap_char($content = '', $conf = array()) {
2665  return chr((int)$conf['char']);
2666  }
2667 
2676  public function stdWrap_intval($content = '', $conf = array()) {
2677  return (int)$content;
2678  }
2679 
2688  public function stdWrap_hash($content = '', array $conf = array()) {
2689  $algorithm = isset($conf['hash.']) ? $this->stdWrap($conf['hash'], $conf['hash.']) : $conf['hash'];
2690  if (function_exists('hash') && in_array($algorithm, hash_algos())) {
2691  $content = hash($algorithm, $content);
2692  } else {
2693  // Non-existing hashing algorithm
2694  $content = '';
2695  }
2696  return $content;
2697  }
2698 
2707  public function stdWrap_round($content = '', $conf = array()) {
2708  return $this->round($content, $conf['round.']);
2709  }
2710 
2719  public function stdWrap_numberFormat($content = '', $conf = array()) {
2720  return $this->numberFormat($content, $conf['numberFormat.']);
2721  }
2722 
2731  public function stdWrap_expandList($content = '', $conf = array()) {
2732  return GeneralUtility::expandList($content);
2733  }
2734 
2744  public function stdWrap_date($content = '', $conf = array()) {
2745  // Check for zero length string to mimic default case of date/gmdate.
2746  $content = $content == '' ? $GLOBALS['EXEC_TIME'] : (int)$content;
2747  $content = $conf['date.']['GMT'] ? gmdate($conf['date'], $content) : date($conf['date'], $content);
2748  return $content;
2749  }
2750 
2760  public function stdWrap_strftime($content = '', $conf = array()) {
2761  // Check for zero length string to mimic default case of strtime/gmstrftime
2762  $content = $content == '' ? $GLOBALS['EXEC_TIME'] : (int)$content;
2763  $content = $conf['strftime.']['GMT'] ? gmstrftime($conf['strftime'], $content) : strftime($conf['strftime'], $content);
2764  $tmp_charset = $conf['strftime.']['charset'] ? $conf['strftime.']['charset'] : $GLOBALS['TSFE']->localeCharset;
2765  if ($tmp_charset) {
2766  $content = $GLOBALS['TSFE']->csConv($content, $tmp_charset);
2767  }
2768  return $content;
2769  }
2770 
2779  public function stdWrap_age($content = '', $conf = array()) {
2780  return $this->calcAge($GLOBALS['EXEC_TIME'] - $content, $conf['age']);
2781  }
2782 
2792  public function stdWrap_case($content = '', $conf = array()) {
2793  return $this->HTMLcaseshift($content, $conf['case']);
2794  }
2795 
2804  public function stdWrap_bytes($content = '', $conf = array()) {
2805  return GeneralUtility::formatSize($content, $conf['bytes.']['labels']);
2806  }
2807 
2816  public function stdWrap_substring($content = '', $conf = array()) {
2817  return $this->substring($content, $conf['substring']);
2818  }
2819 
2828  public function stdWrap_removeBadHTML($content = '', $conf = array()) {
2829  return $this->removeBadHTML($content, $conf['removeBadHTML.']);
2830  }
2831 
2840  public function stdWrap_cropHTML($content = '', $conf = array()) {
2841  return $this->cropHTML($content, $conf['cropHTML']);
2842  }
2843 
2852  public function stdWrap_stripHtml($content = '', $conf = array()) {
2853  return strip_tags($content);
2854  }
2855 
2864  public function stdWrap_crop($content = '', $conf = array()) {
2865  return $this->crop($content, $conf['crop']);
2866  }
2867 
2876  public function stdWrap_rawUrlEncode($content = '', $conf = array()) {
2877  return rawurlencode($content);
2878  }
2879 
2889  public function stdWrap_htmlSpecialChars($content = '', $conf = array()) {
2890  if (!empty($conf['htmlSpecialChars.']['preserveEntities'])) {
2891  $content = htmlspecialchars($content, ENT_COMPAT, 'UTF-8', FALSE);
2892  } else {
2893  $content = htmlspecialchars($content);
2894  }
2895  return $content;
2896  }
2897 
2907  public function stdWrap_encodeForJavaScriptValue($content = '', $conf = array()) {
2908  return GeneralUtility::quoteJSvalue($content);
2909  }
2910 
2919  public function stdWrap_doubleBrTag($content = '', $conf = array()) {
2920  return preg_replace('/
2921 ?
2922 [ ]*
2923 ?
2924 /', $conf['doubleBrTag'], $content);
2925  }
2926 
2936  public function stdWrap_br($content = '', $conf = array()) {
2937  return nl2br($content, !empty($GLOBALS['TSFE']->xhtmlDoctype));
2938  }
2939 
2948  public function stdWrap_brTag($content = '', $conf = array()) {
2949  return str_replace(LF, $conf['brTag'], $content);
2950  }
2951 
2961  public function stdWrap_encapsLines($content = '', $conf = array()) {
2962  return $this->encaps_lineSplit($content, $conf['encapsLines.']);
2963  }
2964 
2973  public function stdWrap_keywords($content = '', $conf = array()) {
2974  return $this->keywords($content);
2975  }
2976 
2986  public function stdWrap_innerWrap($content = '', $conf = array()) {
2987  return $this->wrap($content, $conf['innerWrap']);
2988  }
2989 
2999  public function stdWrap_innerWrap2($content = '', $conf = array()) {
3000  return $this->wrap($content, $conf['innerWrap2']);
3001  }
3002 
3013  public function stdWrap_fontTag($content = '', $conf = array()) {
3014  return $this->wrap($content, $conf['fontTag']);
3015  }
3016 
3025  public function stdWrap_addParams($content = '', $conf = array()) {
3026  return $this->addParams($content, $conf['addParams.']);
3027  }
3028 
3038  public function stdWrap_textStyle($content = '', $conf = array()) {
3039  return $this->textStyle($content, $conf['textStyle.']);
3040  }
3041 
3051  public function stdWrap_tableStyle($content = '', $conf = array()) {
3052  return $this->tableStyle($content, $conf['tableStyle.']);
3053  }
3054 
3064  public function stdWrap_filelink($content = '', $conf = array()) {
3065  return $this->filelink($content, $conf['filelink.']);
3066  }
3067 
3076  public function stdWrap_preCObject($content = '', $conf = array()) {
3077  return $this->cObjGetSingle($conf['preCObject'], $conf['preCObject.'], '/stdWrap/.preCObject') . $content;
3078  }
3079 
3088  public function stdWrap_postCObject($content = '', $conf = array()) {
3089  return $content . $this->cObjGetSingle($conf['postCObject'], $conf['postCObject.'], '/stdWrap/.postCObject');
3090  }
3091 
3101  public function stdWrap_wrapAlign($content = '', $conf = array()) {
3102  $wrapAlign = trim($conf['wrapAlign']);
3103  if ($wrapAlign) {
3104  $content = $this->wrap($content, '<div style="text-align:' . htmlspecialchars($wrapAlign) . ';">|</div>');
3105  }
3106  return $content;
3107  }
3108 
3119  public function stdWrap_typolink($content = '', $conf = array()) {
3120  return $this->typolink($content, $conf['typolink.']);
3121  }
3122 
3131  public function stdWrap_TCAselectItem($content = '', $conf = array()) {
3132  if (is_array($conf['TCAselectItem.'])) {
3133  $content = $this->TCAlookup($content, $conf['TCAselectItem.']);
3134  }
3135  return $content;
3136  }
3137 
3147  public function stdWrap_spaceBefore($content = '', $conf = array()) {
3148  return $this->wrapSpace($content, trim($conf['spaceBefore']) . '|', $conf['space.']);
3149  }
3150 
3160  public function stdWrap_spaceAfter($content = '', $conf = array()) {
3161  return $this->wrapSpace($content, '|' . trim($conf['spaceAfter']), $conf['space.']);
3162  }
3163 
3174  public function stdWrap_space($content = '', $conf = array()) {
3175  return $this->wrapSpace($content, trim($conf['space']), $conf['space.']);
3176  }
3177 
3190  public function stdWrap_wrap($content = '', $conf = array()) {
3191  return $this->wrap($content, $conf['wrap'], $conf['wrap.']['splitChar'] ? $conf['wrap.']['splitChar'] : '|');
3192  }
3193 
3203  public function stdWrap_noTrimWrap($content = '', $conf = array()) {
3204  $splitChar = isset($conf['noTrimWrap.']['splitChar.'])
3205  ? $this->stdWrap($conf['noTrimWrap.']['splitChar'], $conf['noTrimWrap.']['splitChar.'])
3206  : $conf['noTrimWrap.']['splitChar'];
3207  if ($splitChar === NULL || $splitChar === '') {
3208  $splitChar = '|';
3209  }
3210  $content = $this->noTrimWrap(
3211  $content,
3212  $conf['noTrimWrap'],
3213  $splitChar
3214  );
3215  return $content;
3216  }
3217 
3227  public function stdWrap_wrap2($content = '', $conf = array()) {
3228  return $this->wrap($content, $conf['wrap2'], $conf['wrap2.']['splitChar'] ? $conf['wrap2.']['splitChar'] : '|');
3229  }
3230 
3240  public function stdWrap_dataWrap($content = '', $conf = array()) {
3241  return $this->dataWrap($content, $conf['dataWrap']);
3242  }
3243 
3252  public function stdWrap_prepend($content = '', $conf = array()) {
3253  return $this->cObjGetSingle($conf['prepend'], $conf['prepend.'], '/stdWrap/.prepend') . $content;
3254  }
3255 
3264  public function stdWrap_append($content = '', $conf = array()) {
3265  return $content . $this->cObjGetSingle($conf['append'], $conf['append.'], '/stdWrap/.append');
3266  }
3267 
3277  public function stdWrap_wrap3($content = '', $conf = array()) {
3278  return $this->wrap($content, $conf['wrap3'], $conf['wrap3.']['splitChar'] ? $conf['wrap3.']['splitChar'] : '|');
3279  }
3280 
3289  public function stdWrap_orderedStdWrap($content = '', $conf = array()) {
3290  $sortedKeysArray = \TYPO3\CMS\Core\TypoScript\TemplateService::sortedKeyList($conf['orderedStdWrap.'], TRUE);
3291  foreach ($sortedKeysArray as $key) {
3292  $content = $this->stdWrap($content, $conf['orderedStdWrap.'][$key . '.']);
3293  }
3294  return $content;
3295  }
3296 
3305  public function stdWrap_outerWrap($content = '', $conf = array()) {
3306  return $this->wrap($content, $conf['outerWrap']);
3307  }
3308 
3317  public function stdWrap_insertData($content = '', $conf = array()) {
3318  return $this->insertData($content);
3319  }
3320 
3330  public function stdWrap_offsetWrap($content = '', $conf = array()) {
3331  $controlTable = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\OffsetTableContentObject');
3332  if ($conf['offsetWrap.']['tableParams'] || $conf['offsetWrap.']['tableParams.']) {
3333  $controlTable->tableParams = isset($conf['offsetWrap.']['tableParams.']) ? $this->stdWrap($conf['offsetWrap.']['tableParams'], $conf['offsetWrap.']['tableParams.']) : $conf['offsetWrap.']['tableParams'];
3334  }
3335  if ($conf['offsetWrap.']['tdParams'] || $conf['offsetWrap.']['tdParams.']) {
3336  $controlTable->tdParams = ' ' . (isset($conf['offsetWrap.']['tdParams.']) ? $this->stdWrap($conf['offsetWrap.']['tdParams'], $conf['offsetWrap.']['tdParams.']) : $conf['offsetWrap.']['tdParams']);
3337  }
3338  $content = $controlTable->start($content, $conf['offsetWrap']);
3339  if ($conf['offsetWrap.']['stdWrap.']) {
3340  $content = $this->stdWrap($content, $conf['offsetWrap.']['stdWrap.']);
3341  }
3342  return $content;
3343  }
3344 
3353  public function stdWrap_postUserFunc($content = '', $conf = array()) {
3354  return $this->callUserFunction($conf['postUserFunc'], $conf['postUserFunc.'], $content);
3355  }
3356 
3366  public function stdWrap_postUserFuncInt($content = '', $conf = array()) {
3367  $substKey = 'INT_SCRIPT.' . $GLOBALS['TSFE']->uniqueHash();
3368  $GLOBALS['TSFE']->config['INTincScript'][$substKey] = array(
3369  'content' => $content,
3370  'postUserFunc' => $conf['postUserFuncInt'],
3371  'conf' => $conf['postUserFuncInt.'],
3372  'type' => 'POSTUSERFUNC',
3373  'cObj' => serialize($this)
3374  );
3375  $content = '<!--' . $substKey . '-->';
3376  return $content;
3377  }
3378 
3387  public function stdWrap_prefixComment($content = '', $conf = array()) {
3388  if (!$GLOBALS['TSFE']->config['config']['disablePrefixComment'] && !empty($conf['prefixComment'])) {
3389  $content = $this->prefixComment($conf['prefixComment'], array(), $content);
3390  }
3391  return $content;
3392  }
3393 
3402  public function stdWrap_editIcons($content = '', $conf = array()) {
3403  if ($GLOBALS['TSFE']->beUserLogin && $conf['editIcons']) {
3404  if (!is_array($conf['editIcons.'])) {
3405  $conf['editIcons.'] = array();
3406  }
3407  $content = $this->editIcons($content, $conf['editIcons'], $conf['editIcons.']);
3408  }
3409  return $content;
3410  }
3411 
3420  public function stdWrap_editPanel($content = '', $conf = array()) {
3421  if ($GLOBALS['TSFE']->beUserLogin) {
3422  $content = $this->editPanel($content, $conf['editPanel.']);
3423  }
3424  return $content;
3425  }
3426 
3434  public function stdWrap_cacheStore($content = '', $conf = array()) {
3435  if (!empty($conf['cache.']['key'])) {
3437  $cacheFrontend = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager')->getCache('cache_hash');
3438  if ($cacheFrontend) {
3439  $tags = !empty($conf['cache.']['tags']) ? GeneralUtility::trimExplode(',', $conf['cache.']['tags']) : array();
3440  if (strtolower($conf['cache.']['lifetime']) == 'unlimited') {
3441  // unlimited
3442  $lifetime = 0;
3443  } elseif (strtolower($conf['cache.']['lifetime']) == 'default') {
3444  // default lifetime
3445  $lifetime = NULL;
3446  } elseif ((int)$conf['cache.']['lifetime'] > 0) {
3447  // lifetime in seconds
3448  $lifetime = (int)$conf['cache.']['lifetime'];
3449  } else {
3450  // default lifetime
3451  $lifetime = NULL;
3452  }
3453  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap_cacheStore'])) {
3454  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap_cacheStore'] as $_funcRef) {
3455  $params = array(
3456  'key' => $conf['cache.']['key'],
3457  'content' => $content,
3458  'lifetime' => $lifetime,
3459  'tags' => $tags
3460  );
3461  GeneralUtility::callUserFunction($_funcRef, $params, $this);
3462  }
3463  }
3464  $cacheFrontend->set($conf['cache.']['key'], $content, $tags, $lifetime);
3465  }
3466  }
3467  return $content;
3468  }
3469 
3479  public function stdWrap_stdWrapPostProcess($content = '', $conf = array()) {
3480  foreach ($this->stdWrapHookObjects as $hookObject) {
3481  $content = $hookObject->stdWrapPostProcess($content, $conf, $this);
3482  }
3483  return $content;
3484  }
3485 
3494  public function stdWrap_debug($content = '', $conf = array()) {
3495  return '<pre>' . htmlspecialchars($content) . '</pre>';
3496  }
3497 
3506  public function stdWrap_debugFunc($content = '', $conf = array()) {
3507  debug($conf['debugFunc'] == 2 ? array(
3508  $content
3509  ) : $content);
3510  return $content;
3511  }
3512 
3521  public function stdWrap_debugData($content = '', $conf = array()) {
3522  debug($this->data, '$cObj->data:');
3523  if (is_array($this->alternativeData)) {
3524  debug($this->alternativeData, '$this->alternativeData');
3525  }
3526  return $content;
3527  }
3528 
3539  public function numRows($conf) {
3540  $result = FALSE;
3541  $conf['select.']['selectFields'] = 'count(*)';
3542  $res = $this->exec_getQuery($conf['table'], $conf['select.']);
3543  if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
3544  $GLOBALS['TT']->setTSlogMessage($error, 3);
3545  } else {
3546  $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
3547  $result = (int)$row[0];
3548  }
3549  $GLOBALS['TYPO3_DB']->sql_free_result($res);
3550  return $result;
3551  }
3552 
3562  public function listNum($content, $listNum, $char) {
3563  $char = $char ?: ',';
3564  if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($char)) {
3565  $char = chr($char);
3566  }
3567  $temp = explode($char, $content);
3568  $last = '' . (count($temp) - 1);
3569  // Take a random item if requested
3570  if ($listNum === 'rand') {
3571  $listNum = rand(0, count($temp) - 1);
3572  }
3573  $index = $this->calc(str_ireplace('last', $last, $listNum));
3574  return $temp[$index];
3575  }
3576 
3586  public function checkIf($conf) {
3587  if (!is_array($conf)) {
3588  return TRUE;
3589  }
3590  if (isset($conf['directReturn'])) {
3591  return $conf['directReturn'] ? 1 : 0;
3592  }
3593  $flag = TRUE;
3594  if (isset($conf['isNull.'])) {
3595  $isNull = $this->stdWrap('', $conf['isNull.']);
3596  if ($isNull !== NULL) {
3597  $flag = 0;
3598  }
3599  }
3600  if (isset($conf['isTrue']) || isset($conf['isTrue.'])) {
3601  $isTrue = isset($conf['isTrue.']) ? trim($this->stdWrap($conf['isTrue'], $conf['isTrue.'])) : trim($conf['isTrue']);
3602  if (!$isTrue) {
3603  $flag = 0;
3604  }
3605  }
3606  if (isset($conf['isFalse']) || isset($conf['isFalse.'])) {
3607  $isFalse = isset($conf['isFalse.']) ? trim($this->stdWrap($conf['isFalse'], $conf['isFalse.'])) : trim($conf['isFalse']);
3608  if ($isFalse) {
3609  $flag = 0;
3610  }
3611  }
3612  if (isset($conf['isPositive']) || isset($conf['isPositive.'])) {
3613  $number = isset($conf['isPositive.']) ? $this->calc($this->stdWrap($conf['isPositive'], $conf['isPositive.'])) : $this->calc($conf['isPositive']);
3614  if ($number < 1) {
3615  $flag = 0;
3616  }
3617  }
3618  if ($flag) {
3619  $value = isset($conf['value.']) ? trim($this->stdWrap($conf['value'], $conf['value.'])) : trim($conf['value']);
3620  if (isset($conf['isGreaterThan']) || isset($conf['isGreaterThan.'])) {
3621  $number = isset($conf['isGreaterThan.']) ? trim($this->stdWrap($conf['isGreaterThan'], $conf['isGreaterThan.'])) : trim($conf['isGreaterThan']);
3622  if ($number <= $value) {
3623  $flag = 0;
3624  }
3625  }
3626  if (isset($conf['isLessThan']) || isset($conf['isLessThan.'])) {
3627  $number = isset($conf['isLessThan.']) ? trim($this->stdWrap($conf['isLessThan'], $conf['isLessThan.'])) : trim($conf['isLessThan']);
3628  if ($number >= $value) {
3629  $flag = 0;
3630  }
3631  }
3632  if (isset($conf['equals']) || isset($conf['equals.'])) {
3633  $number = isset($conf['equals.']) ? trim($this->stdWrap($conf['equals'], $conf['equals.'])) : trim($conf['equals']);
3634  if ($number != $value) {
3635  $flag = 0;
3636  }
3637  }
3638  if (isset($conf['isInList']) || isset($conf['isInList.'])) {
3639  $number = isset($conf['isInList.']) ? trim($this->stdWrap($conf['isInList'], $conf['isInList.'])) : trim($conf['isInList']);
3640  if (!GeneralUtility::inList($value, $number)) {
3641  $flag = 0;
3642  }
3643  }
3644  }
3645  if ($conf['negate']) {
3646  $flag = $flag ? 0 : 1;
3647  }
3648  return $flag;
3649  }
3650 
3661  public function filelist($data) {
3662  $data = trim($data);
3663  if ($data) {
3664  $data_arr = explode('|', $data);
3665  // read directory:
3666  // MUST exist!
3667  if ($GLOBALS['TSFE']->lockFilePath) {
3668  // Cleaning name..., only relative paths accepted.
3669  $path = $this->clean_directory($data_arr[0]);
3670  // See if path starts with lockFilePath, the additional '/' is needed because clean_directory gets rid of it
3671  $path = GeneralUtility::isFirstPartOfStr($path . '/', $GLOBALS['TSFE']->lockFilePath) ? $path : '';
3672  }
3673  if ($path) {
3674  $items = array(
3675  'files' => array(),
3676  'sorting' => array()
3677  );
3678  $ext_list = strtolower(GeneralUtility::uniqueList($data_arr[1]));
3679  $sorting = trim($data_arr[2]);
3680  // Read dir:
3681  $d = @dir($path);
3682  $tempArray = array();
3683  if (is_object($d)) {
3684  $count = 0;
3685  while ($entry = $d->read()) {
3686  if ($entry != '.' && $entry != '..') {
3687  // Because of odd PHP-error where <br />-tag is sometimes placed after a filename!!
3688  $wholePath = $path . '/' . $entry;
3689  if (file_exists($wholePath) && filetype($wholePath) == 'file') {
3690  $info = GeneralUtility::split_fileref($wholePath);
3691  if (!$ext_list || GeneralUtility::inList($ext_list, $info['fileext'])) {
3692  $items['files'][] = $info['file'];
3693  switch ($sorting) {
3694  case 'name':
3695  $items['sorting'][] = strtolower($info['file']);
3696  break;
3697  case 'size':
3698  $items['sorting'][] = filesize($wholePath);
3699  break;
3700  case 'ext':
3701  $items['sorting'][] = $info['fileext'];
3702  break;
3703  case 'date':
3704  $items['sorting'][] = filectime($wholePath);
3705  break;
3706  case 'mdate':
3707  $items['sorting'][] = filemtime($wholePath);
3708  break;
3709  default:
3710  $items['sorting'][] = $count;
3711  }
3712  $count++;
3713  }
3714  }
3715  }
3716  }
3717  $d->close();
3718  }
3719  // Sort if required
3720  if (count($items['sorting'])) {
3721  if (strtolower(trim($data_arr[3])) != 'r') {
3722  asort($items['sorting']);
3723  } else {
3724  arsort($items['sorting']);
3725  }
3726  }
3727  if (count($items['files'])) {
3728  // Make list
3729  reset($items['sorting']);
3730  $fullPath = trim($data_arr[4]);
3731  $list_arr = array();
3732  foreach ($items['sorting'] as $key => $v) {
3733  $list_arr[] = $fullPath ? $path . '/' . $items['files'][$key] : $items['files'][$key];
3734  }
3735  return implode(',', $list_arr);
3736  }
3737  }
3738  }
3739  }
3740 
3750  public function clean_directory($theDir) {
3751  // proceeds if no '//', '..' or '\' is in the $theFile
3752  if (GeneralUtility::validPathStr($theDir)) {
3753  // Removes all dots, slashes and spaces after a path...
3754  $theDir = preg_replace('/[\\/\\. ]*$/', '', $theDir);
3755  if (!GeneralUtility::isAbsPath($theDir) && @is_dir($theDir)) {
3756  return $theDir;
3757  }
3758  }
3759  }
3760 
3772  public function HTMLparser_TSbridge($theValue, $conf) {
3773  $htmlParser = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Html\\HtmlParser');
3774  $htmlParserCfg = $htmlParser->HTMLparserConfig($conf);
3775  return $htmlParser->HTMLcleaner($theValue, $htmlParserCfg[0], $htmlParserCfg[1], $htmlParserCfg[2], $htmlParserCfg[3]);
3776  }
3777 
3787  public function dataWrap($content, $wrap) {
3788  return $this->wrap($content, $this->insertData($wrap));
3789  }
3790 
3800  public function insertData($str) {
3801  $inside = 0;
3802  $newVal = '';
3803  $pointer = 0;
3804  $totalLen = strlen($str);
3805  do {
3806  if (!$inside) {
3807  $len = strcspn(substr($str, $pointer), '{');
3808  $newVal .= substr($str, $pointer, $len);
3809  $inside = 1;
3810  } else {
3811  $len = strcspn(substr($str, $pointer), '}') + 1;
3812  $newVal .= $this->getData(substr($str, $pointer + 1, $len - 2), $this->data);
3813  $inside = 0;
3814  }
3815  $pointer += $len;
3816  } while ($pointer < $totalLen);
3817  return $newVal;
3818  }
3819 
3831  public function prefixComment($str, $conf, $content) {
3832  if (empty($str)) {
3833  return $content;
3834  }
3835  $parts = explode('|', $str);
3836  $indent = (int)$parts[0];
3837  $comment = htmlspecialchars($this->insertData($parts[1]));
3838  $output = LF
3839  . str_pad('', $indent, TAB) . '<!-- ' . $comment . ' [begin] -->' . LF
3840  . str_pad('', ($indent + 1), TAB) . $content . LF
3841  . str_pad('', $indent, TAB) . '<!-- ' . $comment . ' [end] -->' . LF
3842  . str_pad('', ($indent + 1), TAB);
3843  return $output;
3844  }
3845 
3856  public function substring($content, $options) {
3857  $options = GeneralUtility::intExplode(',', $options . ',');
3858  if ($options[1]) {
3859  return $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, $options[0], $options[1]);
3860  } else {
3861  return $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, $options[0]);
3862  }
3863  }
3864 
3875  public function crop($content, $options) {
3876  $options = explode('|', $options);
3877  $chars = (int)$options[0];
3878  $afterstring = trim($options[1]);
3879  $crop2space = trim($options[2]);
3880  if ($chars) {
3881  if ($GLOBALS['TSFE']->csConvObj->strlen($GLOBALS['TSFE']->renderCharset, $content) > abs($chars)) {
3882  $truncatePosition = FALSE;
3883  if ($chars < 0) {
3884  $content = $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, $chars);
3885  if ($crop2space) {
3886  $truncatePosition = strpos($content, ' ');
3887  }
3888  $content = $truncatePosition ? $afterstring . substr($content, $truncatePosition) : $afterstring . $content;
3889  } else {
3890  $content = $GLOBALS['TSFE']->csConvObj->substr($GLOBALS['TSFE']->renderCharset, $content, 0, $chars);
3891  if ($crop2space) {
3892  $truncatePosition = strrpos($content, ' ');
3893  }
3894  $content = $truncatePosition ? substr($content, 0, $truncatePosition) . $afterstring : $content . $afterstring;
3895  }
3896  }
3897  }
3898  return $content;
3899  }
3900 
3915  public function cropHTML($content, $options) {
3916  $options = explode('|', $options);
3917  $chars = (int)$options[0];
3918  $absChars = abs($chars);
3919  $replacementForEllipsis = trim($options[1]);
3920  $crop2space = trim($options[2]) === '1' ? TRUE : FALSE;
3921  // Split $content into an array(even items in the array are outside the tags, odd numbers are tag-blocks).
3922  $tags = 'a|abbr|address|area|article|aside|audio|b|bdi|bdo|blockquote|body|br|button|caption|cite|code|col|colgroup|data|datalist|dd|del|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|h1|h2|h3|h4|h5|h6|header|hr|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|main|map|mark|meter|nav|object|ol|optgroup|option|output|p|param|pre|progress|q|rb|rp|rt|rtc|ruby|s|samp|section|select|small|source|span|strong|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|tr|track|u|ul|ut|var|video|wbr';
3923  $tagsRegEx = '
3924  (
3925  (?:
3926  <!--.*?--> # a comment
3927  |
3928  <canvas[^>]*>.*?</canvas> # a canvas tag
3929  |
3930  <script[^>]*>.*?</script> # a script tag
3931  |
3932  <noscript[^>]*>.*?</noscript> # a noscript tag
3933  |
3934  <template[^>]*>.*?</template> # a template tag
3935  )
3936  |
3937  </?(?:' . $tags . ')+ # opening tag (\'<tag\') or closing tag (\'</tag\')
3938  (?:
3939  (?:
3940  (?:
3941  \\s+\\w[\\w-]* # EITHER spaces, followed by attribute names
3942  (?:
3943  \\s*=?\\s* # equals
3944  (?>
3945  ".*?" # attribute values in double-quotes
3946  |
3947  \'.*?\' # attribute values in single-quotes
3948  |
3949  [^\'">\\s]+ # plain attribute values
3950  )
3951  )?
3952  )
3953  | # OR a single dash (for TYPO3 link tag)
3954  (?:
3955  \\s+-
3956  )
3957  )+\\s*
3958  | # OR only spaces
3959  \\s*
3960  )
3961  /?> # closing the tag with \'>\' or \'/>\'
3962  )';
3963  $splittedContent = preg_split('%' . $tagsRegEx . '%xs', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
3964  // Reverse array if we are cropping from right.
3965  if ($chars < 0) {
3966  $splittedContent = array_reverse($splittedContent);
3967  }
3968  // Crop the text (chars of tag-blocks are not counted).
3969  $strLen = 0;
3970  // This is the offset of the content item which was cropped.
3971  $croppedOffset = NULL;
3972  $countSplittedContent = count($splittedContent);
3973  for ($offset = 0; $offset < $countSplittedContent; $offset++) {
3974  if ($offset % 2 === 0) {
3975  $tempContent = $GLOBALS['TSFE']->csConvObj->utf8_encode($splittedContent[$offset], $GLOBALS['TSFE']->renderCharset);
3976  $thisStrLen = $GLOBALS['TSFE']->csConvObj->strlen('utf-8', html_entity_decode($tempContent, ENT_COMPAT, 'UTF-8'));
3977  if ($strLen + $thisStrLen > $absChars) {
3978  $croppedOffset = $offset;
3979  $cropPosition = $absChars - $strLen;
3980  // The snippet "&[^&\s;]{2,8};" in the RegEx below represents entities.
3981  $patternMatchEntityAsSingleChar = '(&[^&\\s;]{2,8};|.)';
3982  $cropRegEx = $chars < 0 ? '#' . $patternMatchEntityAsSingleChar . '{0,' . ($cropPosition + 1) . '}$#uis' : '#^' . $patternMatchEntityAsSingleChar . '{0,' . ($cropPosition + 1) . '}#uis';
3983  if (preg_match($cropRegEx, $tempContent, $croppedMatch)) {
3984  $tempContentPlusOneCharacter = $croppedMatch[0];
3985  } else {
3986  $tempContentPlusOneCharacter = FALSE;
3987  }
3988  $cropRegEx = $chars < 0 ? '#' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}$#uis' : '#^' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}#uis';
3989  if (preg_match($cropRegEx, $tempContent, $croppedMatch)) {
3990  $tempContent = $croppedMatch[0];
3991  if ($crop2space && $tempContentPlusOneCharacter !== FALSE) {
3992  $cropRegEx = $chars < 0 ? '#(?<=\\s)' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}$#uis' : '#^' . $patternMatchEntityAsSingleChar . '{0,' . $cropPosition . '}(?=\\s)#uis';
3993  if (preg_match($cropRegEx, $tempContentPlusOneCharacter, $croppedMatch)) {
3994  $tempContent = $croppedMatch[0];
3995  }
3996  }
3997  }
3998  $splittedContent[$offset] = $GLOBALS['TSFE']->csConvObj->utf8_decode($tempContent, $GLOBALS['TSFE']->renderCharset);
3999  break;
4000  } else {
4001  $strLen += $thisStrLen;
4002  }
4003  }
4004  }
4005  // Close cropped tags.
4006  $closingTags = array();
4007  if ($croppedOffset !== NULL) {
4008  $tagName = '';
4009  $openingTagRegEx = '#^<(\\w+)(?:\\s|>)#';
4010  $closingTagRegEx = '#^</(\\w+)(?:\\s|>)#';
4011  for ($offset = $croppedOffset - 1; $offset >= 0; $offset = $offset - 2) {
4012  if (substr($splittedContent[$offset], -2) === '/>') {
4013  // Ignore empty element tags (e.g. <br />).
4014  continue;
4015  }
4016  preg_match($chars < 0 ? $closingTagRegEx : $openingTagRegEx, $splittedContent[$offset], $matches);
4017  $tagName = isset($matches[1]) ? $matches[1] : NULL;
4018  if ($tagName !== NULL) {
4019  // Seek for the closing (or opening) tag.
4020  $seekingTagName = '';
4021  $countSplittedContent = count($splittedContent);
4022  for ($seekingOffset = $offset + 2; $seekingOffset < $countSplittedContent; $seekingOffset = $seekingOffset + 2) {
4023  preg_match($chars < 0 ? $openingTagRegEx : $closingTagRegEx, $splittedContent[$seekingOffset], $matches);
4024  $seekingTagName = isset($matches[1]) ? $matches[1] : NULL;
4025  if ($tagName === $seekingTagName) {
4026  // We found a matching tag.
4027  // Add closing tag only if it occurs after the cropped content item.
4028  if ($seekingOffset > $croppedOffset) {
4029  $closingTags[] = $splittedContent[$seekingOffset];
4030  }
4031  break;
4032  }
4033  }
4034  }
4035  }
4036  // Drop the cropped items of the content array. The $closingTags will be added later on again.
4037  array_splice($splittedContent, $croppedOffset + 1);
4038  }
4039  $splittedContent = array_merge($splittedContent, array(
4040  $croppedOffset !== NULL ? $replacementForEllipsis : ''
4041  ), $closingTags);
4042  // Reverse array once again if we are cropping from the end.
4043  if ($chars < 0) {
4044  $splittedContent = array_reverse($splittedContent);
4045  }
4046  return implode('', $splittedContent);
4047  }
4048 
4061  public function removeBadHTML($text, $conf) {
4062  // Copyright 2002-2003 Thomas Bley
4063  $text = preg_replace(array(
4064  '\'<script[^>]*?>.*?</script[^>]*?>\'si',
4065  '\'<applet[^>]*?>.*?</applet[^>]*?>\'si',
4066  '\'<object[^>]*?>.*?</object[^>]*?>\'si',
4067  '\'<iframe[^>]*?>.*?</iframe[^>]*?>\'si',
4068  '\'<frameset[^>]*?>.*?</frameset[^>]*?>\'si',
4069  '\'<style[^>]*?>.*?</style[^>]*?>\'si',
4070  '\'<marquee[^>]*?>.*?</marquee[^>]*?>\'si',
4071  '\'<script[^>]*?>\'si',
4072  '\'<meta[^>]*?>\'si',
4073  '\'<base[^>]*?>\'si',
4074  '\'<applet[^>]*?>\'si',
4075  '\'<object[^>]*?>\'si',
4076  '\'<link[^>]*?>\'si',
4077  '\'<iframe[^>]*?>\'si',
4078  '\'<frame[^>]*?>\'si',
4079  '\'<frameset[^>]*?>\'si',
4080  '\'<input[^>]*?>\'si',
4081  '\'<form[^>]*?>\'si',
4082  '\'<embed[^>]*?>\'si',
4083  '\'background-image:url\'si',
4084  '\'<\\w+.*?(onabort|onbeforeunload|onblur|onchange|onclick|ondblclick|ondragdrop|onerror|onfilterchange|onfocus|onhelp|onkeydown|onkeypress|onkeyup|onload|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onmove|onreadystatechange|onreset|onresize|onscroll|onselect|onselectstart|onsubmit|onunload).*?>\'si'
4085  ), '', $text);
4086  $text = preg_replace('/<a[^>]*href[[:space:]]*=[[:space:]]*["\']?[[:space:]]*javascript[^>]*/i', '', $text);
4087  // Return clean content
4088  return $text;
4089  }
4090 
4101  public function textStyle($theValue, $conf) {
4102  $conf['face.'][1] = 'Times New Roman';
4103  $conf['face.'][2] = 'Verdana,Arial,Helvetica,Sans serif';
4104  $conf['face.'][3] = 'Arial,Helvetica,Sans serif';
4105  $conf['size.'][1] = 1;
4106  $conf['size.'][2] = 2;
4107  $conf['size.'][3] = 3;
4108  $conf['size.'][4] = 4;
4109  $conf['size.'][5] = 5;
4110  $conf['size.'][10] = '+1';
4111  $conf['size.'][11] = '-1';
4112  $conf['color.'][240] = 'black';
4113  $conf['color.'][241] = 'white';
4114  $conf['color.'][242] = '#333333';
4115  $conf['color.'][243] = 'gray';
4116  $conf['color.'][244] = 'silver';
4117  $conf['color.'][245] = 'red';
4118  $conf['color.'][246] = 'navy';
4119  $conf['color.'][247] = 'yellow';
4120  $conf['color.'][248] = 'green';
4121  $conf['color.'][249] = 'olive';
4122  $conf['color.'][250] = 'maroon';
4123  $face = $this->data[$conf['face.']['field']];
4124  $size = $this->data[$conf['size.']['field']];
4125  $color = $this->data[$conf['color.']['field']];
4126  $align = $this->data[$conf['align.']['field']];
4127  $properties = $this->data[$conf['properties.']['field']];
4128  if (!$properties) {
4129  $properties = isset($conf['properties.']['default.']) ? $this->stdWrap($conf['properties.']['default'], $conf['properties.']['default.']) : $conf['properties.']['default'];
4130  }
4131  // Properties
4132  if ($properties & 8) {
4133  $theValue = $this->HTMLcaseshift($theValue, 'upper');
4134  }
4135  if ($properties & 1) {
4136  $theValue = '<strong>' . $theValue . '</strong>';
4137  }
4138  if ($properties & 2) {
4139  $theValue = '<i>' . $theValue . '</i>';
4140  }
4141  if ($properties & 4) {
4142  $theValue = '<u>' . $theValue . '</u>';
4143  }
4144  // Fonttag
4145  $theFace = $conf['face.'][$face];
4146  if (!$theFace) {
4147  $theFace = isset($conf['face.']['default.']) ? $this->stdWrap($conf['face.']['default'], $conf['face.']['default.']) : $conf['face.']['default'];
4148  }
4149  $theSize = $conf['size.'][$size];
4150  if (!$theSize) {
4151  $theSize = isset($conf['size.']['default.']) ? $this->stdWrap($conf['size.']['default'], $conf['size.']['default.']) : $conf['size.']['default'];
4152  }
4153  $theColor = $conf['color.'][$color];
4154  if (!$theColor) {
4155  $theColor = isset($conf['color.']['default.']) ? $this->stdWrap($conf['color.']['default'], $conf['color.']['default.']) : $conf['color.']['default.'];
4156  }
4157  if ($conf['altWrap']) {
4158  $theValue = $this->wrap($theValue, $conf['altWrap']);
4159  } elseif ($theFace || $theSize || $theColor) {
4160  $theValue = '<font' . ($theFace ? ' face="' . htmlspecialchars($theFace) . '"' : '') . ($theSize ? ' size="' . (int)$theSize . '"' : '') . ($theColor ? ' color="' . htmlspecialchars($theColor) . '"' : '') . '>' . $theValue . '</font>';
4161  }
4162  // Align
4163  if ($align) {
4164  $theValue = $this->wrap($theValue, '<div style="text-align:' . htmlspecialchars($align) . ';">|</div>');
4165  }
4166  // Return
4167  return $theValue;
4168  }
4169 
4180  public function tableStyle($theValue, $conf) {
4181  $conf['color.'][240] = 'black';
4182  $conf['color.'][241] = 'white';
4183  $conf['color.'][242] = '#333333';
4184  $conf['color.'][243] = 'gray';
4185  $conf['color.'][244] = 'silver';
4186  $align = isset($conf['align.']) ? $this->stdWrap($conf['align'], $conf['align.']) : $conf['align'];
4187  $border = isset($conf['border.']) ? (int)$this->stdWrap($conf['border'], $conf['border.']) : (int)$conf['border'];
4188  $cellspacing = isset($conf['cellspacing.']) ? (int)$this->stdWrap($conf['cellspacing'], $conf['cellspacing.']) : (int)$conf['cellspacing'];
4189  $cellpadding = isset($conf['cellpadding.']) ? (int)$this->stdWrap($conf['cellpadding'], $conf['cellpadding.']) : (int)$conf['cellpadding'];
4190  $color = $this->data[$conf['color.']['field']];
4191  $theColor = $conf['color.'][$color] ? $conf['color.'][$color] : $conf['color.']['default'];
4192  // Assembling the table tag
4193  $tableTagArray = array(
4194  '<table'
4195  );
4196  $tableTagArray[] = 'border="' . (int)$border . '"';
4197  $tableTagArray[] = 'cellspacing="' . (int)$cellspacing . '"';
4198  $tableTagArray[] = 'cellpadding="' . (int)$cellpadding . '"';
4199  if ($align) {
4200  $tableTagArray[] = 'align="' . htmlspecialchars($align) . '"';
4201  }
4202  if ($theColor) {
4203  $tableTagArray[] = 'bgcolor="' . htmlspecialchars($theColor) . '"';
4204  }
4205  if ($conf['params']) {
4206  $tableTagArray[] = $conf['params'];
4207  }
4208  $tableWrap = implode(' ', $tableTagArray) . '> | </table>';
4209  $theValue = $this->wrap($theValue, $tableWrap);
4210  // return
4211  return $theValue;
4212  }
4213 
4223  public function addParams($content, $conf) {
4224  // For XHTML compliance.
4225  $lowerCaseAttributes = TRUE;
4226  if (!is_array($conf)) {
4227  return $content;
4228  }
4229  $key = 1;
4230  $parts = explode('<', $content);
4231  if ((int)$conf['_offset']) {
4232  $key = (int)$conf['_offset'] < 0 ? count($parts) + (int)$conf['_offset'] : (int)$conf['_offset'];
4233  }
4234  $subparts = explode('>', $parts[$key]);
4235  if (trim($subparts[0])) {
4236  // Get attributes and name
4237  $attribs = GeneralUtility::get_tag_attributes('<' . $subparts[0] . '>');
4238  list($tagName) = explode(' ', $subparts[0], 2);
4239  // adds/overrides attributes
4240  foreach ($conf as $pkey => $val) {
4241  if (substr($pkey, -1) !== '.' && $pkey[0] !== '_') {
4242  $tmpVal = isset($conf[$pkey . '.']) ? $this->stdWrap($conf[$pkey], $conf[$pkey . '.']) : (string)$val;
4243  if ($lowerCaseAttributes) {
4244  $pkey = strtolower($pkey);
4245  }
4246  if ($tmpVal !== '') {
4247  $attribs[$pkey] = $tmpVal;
4248  }
4249  }
4250  }
4251  // Re-assembles the tag and content
4252  $subparts[0] = trim($tagName . ' ' . GeneralUtility::implodeAttributes($attribs));
4253  $parts[$key] = implode('>', $subparts);
4254  $content = implode('<', $parts);
4255  }
4256  return $content;
4257  }
4258 
4270  public function filelink($theValue, $conf) {
4271  $conf['path'] = isset($conf['path.']) ? $this->stdWrap($conf['path'], $conf['path.']) : $conf['path'];
4272  $theFile = trim($conf['path']) . $theValue;
4273  if (@is_file($theFile)) {
4274  $theFileEnc = str_replace('%2F', '/', rawurlencode($theFile));
4275  $title = $conf['title'];
4276  if (isset($conf['title.'])) {
4277  $title = $this->stdWrap($title, $conf['title.']);
4278  }
4279  $target = $conf['target'];
4280  if (isset($conf['target.'])) {
4281  $target = $this->stdWrap($target, $conf['target.']);
4282  }
4283  // The jumpURL feature will be taken care of by typoLink, only "jumpurl.secure = 1" is applyable needed for special link creation
4284  if ($conf['jumpurl.']['secure']) {
4285  $alternativeJumpUrlParameter = isset($conf['jumpurl.']['parameter.']) ? $this->stdWrap($conf['jumpurl.']['parameter'], $conf['jumpurl.']['parameter.']) : $conf['jumpurl.']['parameter'];
4286  $typoLinkConf = array(
4287  'parameter' => $alternativeJumpUrlParameter ? $alternativeJumpUrlParameter : $GLOBALS['TSFE']->id . ',' . $GLOBALS['TSFE']->type,
4288  'fileTarget' => $target,
4289  'title' => $title,
4290  'ATagParams' => $this->getATagParams($conf),
4291  'additionalParams' => '&jumpurl=' . rawurlencode($theFileEnc) . $this->locDataJU($theFileEnc, $conf['jumpurl.']['secure.']) . $GLOBALS['TSFE']->getMethodUrlIdToken
4292  );
4293  } else {
4294  $typoLinkConf = array(
4295  'parameter' => $theFileEnc,
4296  'fileTarget' => $target,
4297  'title' => $title,
4298  'ATagParams' => $this->getATagParams($conf)
4299  );
4300  }
4301  // If the global jumpURL feature is activated, but is disabled for this
4302  // filelink, the global parameter needs to be disabled as well for this link creation
4303  $globalJumpUrlEnabled = $GLOBALS['TSFE']->config['config']['jumpurl_enable'];
4304  if ($globalJumpUrlEnabled && isset($conf['jumpurl']) && $conf['jumpurl'] == 0) {
4305  $GLOBALS['TSFE']->config['config']['jumpurl_enable'] = 0;
4306  } elseif (!$globalJumpUrlEnabled && $conf['jumpurl']) {
4307  $GLOBALS['TSFE']->config['config']['jumpurl_enable'] = 1;
4308  }
4309  $theLinkWrap = $this->typoLink('|', $typoLinkConf);
4310  // Now the original value is set again
4311  $GLOBALS['TSFE']->config['config']['jumpurl_enable'] = $globalJumpUrlEnabled;
4312  $theSize = filesize($theFile);
4313  $fI = GeneralUtility::split_fileref($theFile);
4314  if ($conf['icon']) {
4315  $conf['icon.']['path'] = isset($conf['icon.']['path.']) ? $this->stdWrap($conf['icon.']['path'], $conf['icon.']['path.']) : $conf['icon.']['path'];
4316  $iconP = !empty($conf['icon.']['path']) ? $conf['icon.']['path'] : TYPO3_mainDir . '/gfx/fileicons/';
4317  $conf['icon.']['ext'] = isset($conf['icon.']['ext.']) ? $this->stdWrap($conf['icon.']['ext'], $conf['icon.']['ext.']) : $conf['icon.']['ext'];
4318  $iconExt = !empty($conf['icon.']['ext']) ? '.' . $conf['icon.']['ext'] : '.gif';
4319  $icon = @is_file(($iconP . $fI['fileext'] . $iconExt)) ? $iconP . $fI['fileext'] . $iconExt : $iconP . 'default' . $iconExt;
4320  // Checking for images: If image, then return link to thumbnail.
4321  $IEList = isset($conf['icon_image_ext_list.']) ? $this->stdWrap($conf['icon_image_ext_list'], $conf['icon_image_ext_list.']) : $conf['icon_image_ext_list'];
4322  $image_ext_list = str_replace(' ', '', strtolower($IEList));
4323  if ($fI['fileext'] && GeneralUtility::inList($image_ext_list, $fI['fileext'])) {
4324  if ($conf['iconCObject']) {
4325  $icon = $this->cObjGetSingle($conf['iconCObject'], $conf['iconCObject.'], 'iconCObject');
4326  } else {
4327  if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['thumbnails']) {
4328  $thumbSize = '';
4329  if ($conf['icon_thumbSize'] || $conf['icon_thumbSize.']) {
4330  $thumbSize = '&size=' . (isset($conf['icon_thumbSize.']) ? $this->stdWrap($conf['icon_thumbSize'], $conf['icon_thumbSize.']) : $conf['icon_thumbSize']);
4331  }
4332  $check = basename($theFile) . ':' . filemtime($theFile) . ':' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'];
4333  $md5sum = '&md5sum=' . md5($check);
4334  $icon = 'typo3/thumbs.php?file=' . rawurlencode(('../' . $theFile)) . $thumbSize . $md5sum;
4335  } else {
4336  $icon = TYPO3_mainDir . 'gfx/fileicons/notfound_thumb.gif';
4337  }
4338  $icon = '<img src="' . htmlspecialchars(($GLOBALS['TSFE']->absRefPrefix . $icon)) . '"' . $this->getBorderAttr(' border="0"') . $this->getAltParam($conf) . ' />';
4339  }
4340  } else {
4341  $conf['icon.']['widthAttribute'] = isset($conf['icon.']['widthAttribute.']) ? $this->stdWrap($conf['icon.']['widthAttribute'], $conf['icon.']['widthAttribute.']) : $conf['icon.']['widthAttribute'];
4342  $iconWidth = !empty($conf['icon.']['widthAttribute']) ? $conf['icon.']['widthAttribute'] : 18;
4343  $conf['icon.']['heightAttribute'] = isset($conf['icon.']['heightAttribute.']) ? $this->stdWrap($conf['icon.']['heightAttribute'], $conf['icon.']['heightAttribute.']) : $conf['icon.']['heightAttribute'];
4344  $iconHeight = !empty($conf['icon.']['heightAttribute']) ? $conf['icon.']['heightAttribute'] : 16;
4345  $icon = '<img src="' . htmlspecialchars(($GLOBALS['TSFE']->absRefPrefix . $icon)) . '" width="' . $iconWidth . '" height="' . $iconHeight . '"' . $this->getBorderAttr(' border="0"') . $this->getAltParam($conf) . ' />';
4346  }
4347  if ($conf['icon_link'] && !$conf['combinedLink']) {
4348  $icon = $this->wrap($icon, $theLinkWrap);
4349  }
4350  $icon = isset($conf['icon.']) ? $this->stdWrap($icon, $conf['icon.']) : $icon;
4351  }
4352  if ($conf['size']) {
4353  $size = isset($conf['size.']) ? $this->stdWrap($theSize, $conf['size.']) : $theSize;
4354  }
4355  // Wrapping file label
4356  if ($conf['removePrependedNumbers']) {
4357  $theValue = preg_replace('/_[0-9][0-9](\\.[[:alnum:]]*)$/', '\\1', $theValue);
4358  }
4359  if (isset($conf['labelStdWrap.'])) {
4360  $theValue = $this->stdWrap($theValue, $conf['labelStdWrap.']);
4361  }
4362  // Wrapping file
4363  $wrap = isset($conf['wrap.']) ? $this->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
4364  if ($conf['combinedLink']) {
4365  $theValue = $icon . $theValue;
4366  if ($conf['ATagBeforeWrap']) {
4367  $theValue = $this->wrap($this->wrap($theValue, $wrap), $theLinkWrap);
4368  } else {
4369  $theValue = $this->wrap($this->wrap($theValue, $theLinkWrap), $wrap);
4370  }
4371  $file = isset($conf['file.']) ? $this->stdWrap($theValue, $conf['file.']) : $theValue;
4372  // output
4373  $output = $file . $size;
4374  } else {
4375  if ($conf['ATagBeforeWrap']) {
4376  $theValue = $this->wrap($this->wrap($theValue, $wrap), $theLinkWrap);
4377  } else {
4378  $theValue = $this->wrap($this->wrap($theValue, $theLinkWrap), $wrap);
4379  }
4380  $file = isset($conf['file.']) ? $this->stdWrap($theValue, $conf['file.']) : $theValue;
4381  // output
4382  $output = $icon . $file . $size;
4383  }
4384  if (isset($conf['stdWrap.'])) {
4385  $output = $this->stdWrap($output, $conf['stdWrap.']);
4386  }
4387  return $output;
4388  }
4389  }
4390 
4402  public function locDataJU($jumpUrl, $conf) {
4403  $fI = pathinfo($jumpUrl);
4404  $mimetype = '';
4405  $mimetypeValue = '';
4406  if ($fI['extension']) {
4407  $mimeTypes = GeneralUtility::trimExplode(',', $conf['mimeTypes'], TRUE);
4408  foreach ($mimeTypes as $v) {
4409  $parts = explode('=', $v, 2);
4410  if (strtolower($fI['extension']) == strtolower(trim($parts[0]))) {
4411  $mimetypeValue = trim($parts[1]);
4412  $mimetype = '&mimeType=' . rawurlencode($mimetypeValue);
4413  break;
4414  }
4415  }
4416  }
4417  $locationData = $GLOBALS['TSFE']->id . ':' . $this->currentRecord;
4418  $rec = '&locationData=' . rawurlencode($locationData);
4419  $hArr = array(
4420  $jumpUrl,
4421  $locationData,
4422  $mimetypeValue
4423  );
4424  $juHash = '&juHash=' . GeneralUtility::hmac(serialize($hArr));
4425  return '&juSecure=1' . $mimetype . $rec . $juHash;
4426  }
4427 
4436  public function calc($val) {
4437  $parts = GeneralUtility::splitCalc($val, '+-*/');
4438  $value = 0;
4439  foreach ($parts as $part) {
4440  $theVal = $part[1];
4441  $sign = $part[0];
4442  if ((string) (int)$theVal === (string) $theVal) {
4443  $theVal = (int)$theVal;
4444  } else {
4445  $theVal = 0;
4446  }
4447  if ($sign == '-') {
4448  $value -= $theVal;
4449  }
4450  if ($sign == '+') {
4451  $value += $theVal;
4452  }
4453  if ($sign == '/') {
4454  if ((int)$theVal) {
4455  $value /= (int)$theVal;
4456  }
4457  }
4458  if ($sign == '*') {
4459  $value *= $theVal;
4460  }
4461  }
4462  return $value;
4463  }
4464 
4475  public function calcIntExplode($delim, $string) {
4476  $temp = explode($delim, $string);
4477  foreach ($temp as $key => $val) {
4478  $temp[$key] = (int)$this->calc($val);
4479  }
4480  return $temp;
4481  }
4482 
4495  public function splitObj($value, $conf) {
4496  $conf['token'] = isset($conf['token.']) ? $this->stdWrap($conf['token'], $conf['token.']) : $conf['token'];
4497  if ($conf['token'] === '') {
4498  return $value;
4499  }
4500  $conf['max'] = isset($conf['max.']) ? (int)$this->stdWrap($conf['max'], $conf['max.']) : (int)$conf['max'];
4501  $conf['min'] = isset($conf['min.']) ? (int)$this->stdWrap($conf['min'], $conf['min.']) : (int)$conf['min'];
4502  $valArr = explode($conf['token'], $value);
4503  if (count($valArr) && (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($conf['returnKey']) || $conf['returnKey.'])) {
4504  $key = isset($conf['returnKey.']) ? (int)$this->stdWrap($conf['returnKey'], $conf['returnKey.']) : (int)$conf['returnKey'];
4505  $content = isset($valArr[$key]) ? $valArr[$key] : '';
4506  } else {
4507  // calculate splitCount
4508  $splitCount = count($valArr);
4509  $max = isset($conf['max.']) ? $this->stdWrap($conf['max'], $conf['max.']) : $conf['max'];
4510  if ($max && $splitCount > $max) {
4511  $splitCount = $max;
4512  }
4513  $min = isset($conf['min.']) ? $this->stdWrap($conf['min'], $conf['min.']) : $conf['min'];
4514  if ($min && $splitCount < $min) {
4515  $splitCount = $min;
4516  }
4517  $wrap = isset($conf['wrap.']) ? $this->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
4518  $cObjNum = isset($conf['cObjNum.']) ? $this->stdWrap($conf['cObjNum'], $conf['cObjNum.']) : $conf['cObjNum'];
4519  if ($wrap || $cObjNum) {
4520  $splitArr = array();
4521  $splitArr['wrap'] = $wrap;
4522  $splitArr['cObjNum'] = $cObjNum;
4523  $splitArr = $GLOBALS['TSFE']->tmpl->splitConfArray($splitArr, $splitCount);
4524  }
4525  $content = '';
4526  for ($a = 0; $a < $splitCount; $a++) {
4527  $GLOBALS['TSFE']->register['SPLIT_COUNT'] = $a;
4528  $value = '' . $valArr[$a];
4529  $this->data[$this->currentValKey] = $value;
4530  if ($splitArr[$a]['cObjNum']) {
4531  $objName = (int)$splitArr[$a]['cObjNum'];
4532  $value = isset($conf[$objName . '.']) ? $this->stdWrap($this->cObjGet($conf[$objName . '.'], $objName . '.'), $conf[$objName . '.']) : $this->cObjGet($conf[$objName . '.'], $objName . '.');
4533  }
4534  $wrap = isset($splitArr[$a]['wrap.']) ? $this->stdWrap($splitArr[$a]['wrap'], $splitArr[$a]['wrap.']) : $splitArr[$a]['wrap'];
4535  if ($wrap) {
4536  $value = $this->wrap($value, $wrap);
4537  }
4538  $content .= $value;
4539  }
4540  }
4541  return $content;
4542  }
4543 
4551  protected function replacement($content, array $configuration) {
4552  // Sorts actions in configuration by numeric index
4553  ksort($configuration, SORT_NUMERIC);
4554  foreach ($configuration as $index => $action) {
4555  // Checks whether we have an valid action and a numeric key ending with a dot ("10.")
4556  if (is_array($action) && substr($index, -1) === '.' && \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger(substr($index, 0, -1))) {
4557  $content = $this->replacementSingle($content, $action);
4558  }
4559  }
4560  return $content;
4561  }
4562 
4570  protected function replacementSingle($content, array $configuration) {
4571  if ((isset($configuration['search']) || isset($configuration['search.'])) && (isset($configuration['replace']) || isset($configuration['replace.']))) {
4572  // Gets the strings
4573  $search = isset($configuration['search.']) ? $this->stdWrap($configuration['search'], $configuration['search.']) : $configuration['search'];
4574  $replace = isset($configuration['replace.']) ? $this->stdWrap($configuration['replace'], $configuration['replace.']) : $configuration['replace'];
4575  // Determines whether regular expression shall be used
4576  if (isset($configuration['useRegExp']) || $configuration['useRegExp.']) {
4577  $useRegularExpression = isset($configuration['useRegExp.']) ? $this->stdWrap($configuration['useRegExp'], $configuration['useRegExp.']) : $configuration['useRegExp'];
4578  }
4579  // Determines whether replace-pattern uses option-split
4580  if (isset($configuration['useOptionSplitReplace']) || isset($configuration['useOptionSplitReplace.'])) {
4581  $useOptionSplitReplace = isset($configuration['useOptionSplitReplace.']) ? $this->stdWrap($configuration['useOptionSplitReplace'], $configuration['useOptionSplitReplace.']) : $configuration['useOptionSplitReplace'];
4582  }
4583 
4584  // Performs a replacement by preg_replace()
4585  if (isset($useRegularExpression)) {
4586  // Get separator-character which precedes the string and separates search-string from the modifiers
4587  $separator = $search[0];
4588  $startModifiers = strrpos($search, $separator);
4589  if ($separator !== FALSE && $startModifiers > 0) {
4590  $modifiers = substr($search, $startModifiers + 1);
4591  // remove "e" (eval-modifier), which would otherwise allow to run arbitrary PHP-code
4592  $modifiers = str_replace('e', '', $modifiers);
4593  $search = substr($search, 0, ($startModifiers + 1)) . $modifiers;
4594  }
4595  if (empty($useOptionSplitReplace)) {
4596  $content = preg_replace($search, $replace, $content);
4597  } else {
4598  // init for replacement
4599  $splitCount = preg_match_all($search, $content, $matches);
4600  $replaceArray = $GLOBALS['TSFE']->tmpl->splitConfArray(array($replace), $splitCount);
4601  $replaceCount = 0;
4602 
4603  $replaceCallback = function($match) use ($replaceArray, $search, &$replaceCount) {
4604  $replaceCount++;
4605  return preg_replace($search, $replaceArray[$replaceCount - 1][0], $match[0]);
4606  };
4607  $content = preg_replace_callback($search, $replaceCallback, $content);
4608  }
4609  } else {
4610  if (empty($useOptionSplitReplace)) {
4611  $content = str_replace($search, $replace, $content);
4612  } else {
4613  // turn search-string into a preg-pattern
4614  $searchPreg = '#' . preg_quote($search, '#') . '#';
4615 
4616  // init for replacement
4617  $splitCount = preg_match_all($searchPreg, $content, $matches);
4618  $replaceArray = $GLOBALS['TSFE']->tmpl->splitConfArray(array($replace), $splitCount);
4619  $replaceCount = 0;
4620 
4621  $replaceCallback = function($match) use ($replaceArray, $search, &$replaceCount) {
4622  $replaceCount++;
4623  return $replaceArray[$replaceCount - 1][0];
4624  };
4625  $content = preg_replace_callback($searchPreg, $replaceCallback, $content);
4626  }
4627  }
4628  }
4629  return $content;
4630  }
4631 
4640  protected function round($content, array $conf = array()) {
4641  $decimals = isset($conf['decimals.']) ? $this->stdWrap($conf['decimals'], $conf['decimals.']) : $conf['decimals'];
4642  $type = isset($conf['roundType.']) ? $this->stdWrap($conf['roundType'], $conf['roundType.']) : $conf['roundType'];
4643  $floatVal = floatval($content);
4644  switch ($type) {
4645  case 'ceil':
4646  $content = ceil($floatVal);
4647  break;
4648  case 'floor':
4649  $content = floor($floatVal);
4650  break;
4651  case 'round':
4652 
4653  default:
4654  $content = round($floatVal, (int)$decimals);
4655  }
4656  return $content;
4657  }
4658 
4668  public function numberFormat($content, $conf) {
4669  $decimals = isset($conf['decimals.']) ? $this->stdWrap($conf['decimals'], $conf['decimals.']) : $conf['decimals'];
4670  $dec_point = isset($conf['dec_point.']) ? $this->stdWrap($conf['dec_point'], $conf['dec_point.']) : $conf['dec_point'];
4671  $thousands_sep = isset($conf['thousands_sep.']) ? $this->stdWrap($conf['thousands_sep'], $conf['thousands_sep.']) : $conf['thousands_sep'];
4672  return number_format(floatval($content), $decimals, $dec_point, $thousands_sep);
4673  }
4674 
4696  public function parseFunc($theValue, $conf, $ref = '') {
4697  // Fetch / merge reference, if any
4698  if ($ref) {
4699  $temp_conf = array(
4700  'parseFunc' => $ref,
4701  'parseFunc.' => $conf
4702  );
4703  $temp_conf = $this->mergeTSRef($temp_conf, 'parseFunc');
4704  $conf = $temp_conf['parseFunc.'];
4705  }
4706  // Process:
4707  if ((string)$conf['externalBlocks'] !== '') {
4708  $tags = strtolower(implode(',', GeneralUtility::trimExplode(',', $conf['externalBlocks'])));
4709  $htmlParser = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Html\\HtmlParser');
4710  $parts = $htmlParser->splitIntoBlock($tags, $theValue);
4711  foreach ($parts as $k => $v) {
4712  if ($k % 2) {
4713  // font:
4714  $tagName = strtolower($htmlParser->getFirstTagName($v));
4715  $cfg = $conf['externalBlocks.'][$tagName . '.'];
4716  if ($cfg['stripNLprev'] || $cfg['stripNL']) {
4717  $parts[$k - 1] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $parts[$k - 1]);
4718  }
4719  if ($cfg['stripNLnext'] || $cfg['stripNL']) {
4720  $parts[$k + 1] = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $parts[$k + 1]);
4721  }
4722  }
4723  }
4724  foreach ($parts as $k => $v) {
4725  if ($k % 2) {
4726  $tag = $htmlParser->getFirstTag($v);
4727  $tagName = strtolower($htmlParser->getFirstTagName($v));
4728  $cfg = $conf['externalBlocks.'][$tagName . '.'];
4729  if ($cfg['callRecursive']) {
4730  $parts[$k] = $this->parseFunc($htmlParser->removeFirstAndLastTag($v), $conf);
4731  if (!$cfg['callRecursive.']['dontWrapSelf']) {
4732  if ($cfg['callRecursive.']['alternativeWrap']) {
4733  $parts[$k] = $this->wrap($parts[$k], $cfg['callRecursive.']['alternativeWrap']);
4734  } else {
4735  if (is_array($cfg['callRecursive.']['tagStdWrap.'])) {
4736  $tag = $this->stdWrap($tag, $cfg['callRecursive.']['tagStdWrap.']);
4737  }
4738  $parts[$k] = $tag . $parts[$k] . '</' . $tagName . '>';
4739  }
4740  }
4741  } elseif ($cfg['HTMLtableCells']) {
4742  $rowParts = $htmlParser->splitIntoBlock('tr', $parts[$k]);
4743  foreach ($rowParts as $kk => $vv) {
4744  if ($kk % 2) {
4745  $colParts = $htmlParser->splitIntoBlock('td,th', $vv);
4746  $cc = 0;
4747  foreach ($colParts as $kkk => $vvv) {
4748  if ($kkk % 2) {
4749  $cc++;
4750  $tag = $htmlParser->getFirstTag($vvv);
4751  $tagName = strtolower($htmlParser->getFirstTagName($vvv));
4752  $colParts[$kkk] = $htmlParser->removeFirstAndLastTag($vvv);
4753  if ($cfg['HTMLtableCells.'][$cc . '.']['callRecursive'] || !isset($cfg['HTMLtableCells.'][($cc . '.')]['callRecursive']) && $cfg['HTMLtableCells.']['default.']['callRecursive']) {
4754  if ($cfg['HTMLtableCells.']['addChr10BetweenParagraphs']) {
4755  $colParts[$kkk] = str_replace('</p><p>', '</p>' . LF . '<p>', $colParts[$kkk]);
4756  }
4757  $colParts[$kkk] = $this->parseFunc($colParts[$kkk], $conf);
4758  }
4759  $tagStdWrap = is_array($cfg['HTMLtableCells.'][$cc . '.']['tagStdWrap.']) ? $cfg['HTMLtableCells.'][$cc . '.']['tagStdWrap.'] : $cfg['HTMLtableCells.']['default.']['tagStdWrap.'];
4760  if (is_array($tagStdWrap)) {
4761  $tag = $this->stdWrap($tag, $tagStdWrap);
4762  }
4763  $stdWrap = is_array($cfg['HTMLtableCells.'][$cc . '.']['stdWrap.']) ? $cfg['HTMLtableCells.'][$cc . '.']['stdWrap.'] : $cfg['HTMLtableCells.']['default.']['stdWrap.'];
4764  if (is_array($stdWrap)) {
4765  $colParts[$kkk] = $this->stdWrap($colParts[$kkk], $stdWrap);
4766  }
4767  $colParts[$kkk] = $tag . $colParts[$kkk] . '</' . $tagName . '>';
4768  }
4769  }
4770  $rowParts[$kk] = implode('', $colParts);
4771  }
4772  }
4773  $parts[$k] = implode('', $rowParts);
4774  }
4775  if (is_array($cfg['stdWrap.'])) {
4776  $parts[$k] = $this->stdWrap($parts[$k], $cfg['stdWrap.']);
4777  }
4778  } else {
4779  $parts[$k] = $this->_parseFunc($parts[$k], $conf);
4780  }
4781  }
4782  return implode('', $parts);
4783  } else {
4784  return $this->_parseFunc($theValue, $conf);
4785  }
4786  }
4787 
4798  public function _parseFunc($theValue, $conf) {
4799  if (!empty($conf['if.']) && !$this->checkIf($conf['if.'])) {
4800  return $theValue;
4801  }
4802  // Indicates that the data is from within a tag.
4803  $inside = 0;
4804  // Pointer to the total string position
4805  $pointer = 0;
4806  // Loaded with the current typo-tag if any.
4807  $currentTag = '';
4808  $stripNL = 0;
4809  $contentAccum = array();
4810  $contentAccumP = 0;
4811  $allowTags = strtolower(str_replace(' ', '', $conf['allowTags']));
4812  $denyTags = strtolower(str_replace(' ', '', $conf['denyTags']));
4813  $totalLen = strlen($theValue);
4814  do {
4815  if (!$inside) {
4816  if (!is_array($currentTag)) {
4817  // These operations should only be performed on code outside the typotags...
4818  // data: this checks that we enter tags ONLY if the first char in the tag is alphanumeric OR '/'
4819  $len_p = 0;
4820  $c = 100;
4821  do {
4822  $len = strcspn(substr($theValue, $pointer + $len_p), '<');
4823  $len_p += $len + 1;
4824  $endChar = ord(strtolower(substr($theValue, $pointer + $len_p, 1)));
4825  $c--;
4826  } while ($c > 0 && $endChar && ($endChar < 97 || $endChar > 122) && $endChar != 47);
4827  $len = $len_p - 1;
4828  } else {
4829  // If we're inside a currentTag, just take it to the end of that tag!
4830  $tempContent = strtolower(substr($theValue, $pointer));
4831  $len = strpos($tempContent, '</' . $currentTag[0]);
4832  if (is_string($len) && !$len) {
4833  $len = strlen($tempContent);
4834  }
4835  }
4836  // $data is the content until the next <tag-start or end is detected.
4837  // In case of a currentTag set, this would mean all data between the start- and end-tags
4838  $data = substr($theValue, $pointer, $len);
4839  if ($data != '') {
4840  if ($stripNL) {
4841  // If the previous tag was set to strip NewLines in the beginning of the next data-chunk.
4842  $data = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $data);
4843  }
4844  // These operations should only be performed on code outside the tags...
4845  if (!is_array($currentTag)) {
4846  // Constants
4847  $tmpConstants = $GLOBALS['TSFE']->tmpl->setup['constants.'];
4848  if ($conf['constants'] && is_array($tmpConstants)) {
4849  foreach ($tmpConstants as $key => $val) {
4850  if (is_string($val)) {
4851  $data = str_replace('###' . $key . '###', $val, $data);
4852  }
4853  }
4854  }
4855  // Short
4856  if (is_array($conf['short.'])) {
4857  $shortWords = $conf['short.'];
4858  krsort($shortWords);
4859  foreach ($shortWords as $key => $val) {
4860  if (is_string($val)) {
4861  $data = str_replace($key, $val, $data);
4862  }
4863  }
4864  }
4865  // stdWrap
4866  if (is_array($conf['plainTextStdWrap.'])) {
4867  $data = $this->stdWrap($data, $conf['plainTextStdWrap.']);
4868  }
4869  // userFunc
4870  if ($conf['userFunc']) {
4871  $data = $this->callUserFunction($conf['userFunc'], $conf['userFunc.'], $data);
4872  }
4873  // Makelinks: (Before search-words as we need the links to be generated when searchwords go on...!)
4874  if ($conf['makelinks']) {
4875  $data = $this->http_makelinks($data, $conf['makelinks.']['http.']);
4876  $data = $this->mailto_makelinks($data, $conf['makelinks.']['mailto.']);
4877  }
4878  // Search Words:
4879  if ($GLOBALS['TSFE']->no_cache && $conf['sword'] && is_array($GLOBALS['TSFE']->sWordList) && $GLOBALS['TSFE']->sWordRegEx) {
4880  $newstring = '';
4881  do {
4882  $pregSplitMode = 'i';
4883  if (isset($GLOBALS['TSFE']->config['config']['sword_noMixedCase']) && !empty($GLOBALS['TSFE']->config['config']['sword_noMixedCase'])) {
4884  $pregSplitMode = '';
4885  }
4886  $pieces = preg_split('/' . $GLOBALS['TSFE']->sWordRegEx . '/' . $pregSplitMode, $data, 2);
4887  $newstring .= $pieces[0];
4888  $match_len = strlen($data) - (strlen($pieces[0]) + strlen($pieces[1]));
4889  if (strstr($pieces[0], '<') || strstr($pieces[0], '>')) {
4890  // Returns TRUE, if a '<' is closer to the string-end than '>'.
4891  // This is the case if we're INSIDE a tag (that could have been
4892  // made by makelinks...) and we must secure, that the inside of a tag is
4893  // not marked up.
4894  $inTag = strrpos($pieces[0], '<') > strrpos($pieces[0], '>');
4895  }
4896  // The searchword:
4897  $match = substr($data, strlen($pieces[0]), $match_len);
4898  if (trim($match) && strlen($match) > 1 && !$inTag) {
4899  $match = $this->wrap($match, $conf['sword']);
4900  }
4901  // Concatenate the Search Word again.
4902  $newstring .= $match;
4903  $data = $pieces[1];
4904  } while ($pieces[1]);
4905  $data = $newstring;
4906  }
4907  }
4908  $contentAccum[$contentAccumP] .= $data;
4909  }
4910  $inside = 1;
4911  } else {
4912  // tags
4913  $len = strcspn(substr($theValue, $pointer), '>') + 1;
4914  $data = substr($theValue, $pointer, $len);
4916  $tagContent = substr($data, 1, -2);
4917  } else {
4918  $tagContent = substr($data, 1, -1);
4919  }
4920  $tag = explode(' ', trim($tagContent), 2);
4921  $tag[0] = strtolower($tag[0]);
4922  if ($tag[0][0] === '/') {
4923  $tag[0] = substr($tag[0], 1);
4924  $tag['out'] = 1;
4925  }
4926  if ($conf['tags.'][$tag[0]]) {
4927  $treated = 0;
4928  $stripNL = 0;
4929  // in-tag
4930  if (!$currentTag && !$tag['out']) {
4931  // $currentTag (array!) is the tag we are currently processing
4932  $currentTag = $tag;
4933  $contentAccumP++;
4934  $treated = 1;
4935  // in-out-tag: img and other empty tags
4936  if (preg_match('/^(area|base|br|col|hr|img|input|meta|param)$/i', $tag[0])) {
4937  $tag['out'] = 1;
4938  }
4939  }
4940  // out-tag
4941  if ($currentTag[0] == $tag[0] && $tag['out']) {
4942  $theName = $conf['tags.'][$tag[0]];
4943  $theConf = $conf['tags.'][$tag[0] . '.'];
4944  // This flag indicates, that NL- (13-10-chars) should be stripped first and last.
4945  $stripNL = $theConf['stripNL'] ? 1 : 0;
4946  // This flag indicates, that this TypoTag section should NOT be included in the nonTypoTag content.
4947  $breakOut = $theConf['breakoutTypoTagContent'] ? 1 : 0;
4948  $this->parameters = array();
4949  if ($currentTag[1]) {
4950  $params = GeneralUtility::get_tag_attributes($currentTag[1]);
4951  if (is_array($params)) {
4952  foreach ($params as $option => $val) {
4953  $this->parameters[strtolower($option)] = $val;
4954  }
4955  }
4956  }
4957  $this->parameters['allParams'] = trim($currentTag[1]);
4958  // Removes NL in the beginning and end of the tag-content AND at the end of the currentTagBuffer.
4959  // $stripNL depends on the configuration of the current tag
4960  if ($stripNL) {
4961  $contentAccum[$contentAccumP - 1] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $contentAccum[$contentAccumP - 1]);
4962  $contentAccum[$contentAccumP] = preg_replace('/^[ ]*' . CR . '?' . LF . '/', '', $contentAccum[$contentAccumP]);
4963  $contentAccum[$contentAccumP] = preg_replace('/' . CR . '?' . LF . '[ ]*$/', '', $contentAccum[$contentAccumP]);
4964  }
4965  $this->data[$this->currentValKey] = $contentAccum[$contentAccumP];
4966  $newInput = $this->cObjGetSingle($theName, $theConf, '/parseFunc/.tags.' . $tag[0]);
4967  // fetch the content object
4968  $contentAccum[$contentAccumP] = $newInput;
4969  $contentAccumP++;
4970  // If the TypoTag section
4971  if (!$breakOut) {
4972  $contentAccum[$contentAccumP - 2] .= $contentAccum[($contentAccumP - 1)] . $contentAccum[$contentAccumP];
4973  unset($contentAccum[$contentAccumP]);
4974  unset($contentAccum[$contentAccumP - 1]);
4975  $contentAccumP -= 2;
4976  }
4977  unset($currentTag);
4978  $treated = 1;
4979  }
4980  // other tags...
4981  if (!$treated) {
4982  $contentAccum[$contentAccumP] .= $data;
4983  }
4984  } else {
4985  // If a tag was not a typo tag, then it is just added to the content
4986  $stripNL = 0;
4987  if (GeneralUtility::inList($allowTags, $tag[0]) || $denyTags != '*' && !GeneralUtility::inList($denyTags, $tag[0])) {
4988  $contentAccum[$contentAccumP] .= $data;
4989  } else {
4990  $contentAccum[$contentAccumP] .= HTMLSpecialChars($data);
4991  }
4992  }
4993  $inside = 0;
4994  }
4995  $pointer += $len;
4996  } while ($pointer < $totalLen);
4997  // Parsing nonTypoTag content (all even keys):
4998  reset($contentAccum);
4999  $contentAccumCount = count($contentAccum);
5000  for ($a = 0; $a < $contentAccumCount; $a++) {
5001  if ($a % 2 != 1) {
5002  // stdWrap
5003  if (is_array($conf['nonTypoTagStdWrap.'])) {
5004  $contentAccum[$a] = $this->stdWrap($contentAccum[$a], $conf['nonTypoTagStdWrap.']);
5005  }
5006  // userFunc
5007  if ($conf['nonTypoTagUserFunc']) {
5008  $contentAccum[$a] = $this->callUserFunction($conf['nonTypoTagUserFunc'], $conf['nonTypoTagUserFunc.'], $contentAccum[$a]);
5009  }
5010  }
5011  }
5012  return implode('', $contentAccum);
5013  }
5014 
5024  public function encaps_lineSplit($theValue, $conf) {
5025  $lParts = explode(LF, $theValue);
5026  $encapTags = GeneralUtility::trimExplode(',', strtolower($conf['encapsTagList']), TRUE);
5027  $nonWrappedTag = $conf['nonWrappedTag'];
5028  $defaultAlign = isset($conf['defaultAlign.']) ? trim($this->stdWrap($conf['defaultAlign'], $conf['defaultAlign.'])) : trim($conf['defaultAlign']);
5029  if ((string)$theValue === '') {
5030  return '';
5031  }
5032  foreach ($lParts as $k => $l) {
5033  $sameBeginEnd = 0;
5034  $emptyTag = 0;
5035  $l = trim($l);
5036  $attrib = array();
5037  $nWrapped = 0;
5038  if ($l[0] === '<' && substr($l, -1) === '>') {
5039  $fwParts = explode('>', substr($l, 1), 2);
5040  list($tagName, $tagParams) = explode(' ', $fwParts[0], 2);
5041  if (!$fwParts[1]) {
5042  if (substr($tagName, -1) == '/') {
5043  $tagName = substr($tagName, 0, -1);
5044  }
5045  if (substr($fwParts[0], -1) == '/') {
5046  $sameBeginEnd = 1;
5047  $emptyTag = 1;
5048  $attrib = GeneralUtility::get_tag_attributes('<' . substr($fwParts[0], 0, -1) . '>');
5049  }
5050  } else {
5051  $backParts = GeneralUtility::revExplode('<', substr($fwParts[1], 0, -1), 2);
5052  $attrib = GeneralUtility::get_tag_attributes('<' . $fwParts[0] . '>');
5053  $str_content = $backParts[0];
5054  $sameBeginEnd = substr(strtolower($backParts[1]), 1, strlen($tagName)) == strtolower($tagName);
5055  }
5056  }
5057  if ($sameBeginEnd && in_array(strtolower($tagName), $encapTags)) {
5058  $uTagName = strtoupper($tagName);
5059  $uTagName = strtoupper($conf['remapTag.'][$uTagName] ? $conf['remapTag.'][$uTagName] : $uTagName);
5060  } else {
5061  $uTagName = strtoupper($nonWrappedTag);
5062  // The line will be wrapped: $uTagName should not be an empty tag
5063  $emptyTag = 0;
5064  $str_content = $lParts[$k];
5065  $nWrapped = 1;
5066  $attrib = array();
5067  }
5068  // Wrapping all inner-content:
5069  if (is_array($conf['innerStdWrap_all.'])) {
5070  $str_content = $this->stdWrap($str_content, $conf['innerStdWrap_all.']);
5071  }
5072  if ($uTagName) {
5073  // Setting common attributes
5074  if (is_array($conf['addAttributes.'][$uTagName . '.'])) {
5075  foreach ($conf['addAttributes.'][$uTagName . '.'] as $kk => $vv) {
5076  if (!is_array($vv)) {
5077  if ((string) $conf['addAttributes.'][($uTagName . '.')][($kk . '.')]['setOnly'] == 'blank') {
5078  if ((string)$attrib[$kk] === '') {
5079  $attrib[$kk] = $vv;
5080  }
5081  } elseif ((string) $conf['addAttributes.'][($uTagName . '.')][($kk . '.')]['setOnly'] == 'exists') {
5082  if (!isset($attrib[$kk])) {
5083  $attrib[$kk] = $vv;
5084  }
5085  } else {
5086  $attrib[$kk] = $vv;
5087  }
5088  }
5089  }
5090  }
5091  // Wrapping all inner-content:
5092  if (is_array($conf['encapsLinesStdWrap.'][$uTagName . '.'])) {
5093  $str_content = $this->stdWrap($str_content, $conf['encapsLinesStdWrap.'][$uTagName . '.']);
5094  }
5095  // Default align
5096  if (!$attrib['align'] && $defaultAlign) {
5097  $attrib['align'] = $defaultAlign;
5098  }
5099  $params = GeneralUtility::implodeAttributes($attrib, 1);
5100  if ($conf['removeWrapping'] && !($emptyTag && $conf['removeWrapping.']['keepSingleTag'])) {
5101  $str_content = $str_content;
5102  } else {
5103  if ($emptyTag) {
5104  $str_content = '<' . strtolower($uTagName) . (trim($params) ? ' ' . trim($params) : '') . ' />';
5105  } else {
5106  $str_content = '<' . strtolower($uTagName) . (trim($params) ? ' ' . trim($params) : '') . '>' . $str_content . '</' . strtolower($uTagName) . '>';
5107  }
5108  }
5109  }
5110  if ($nWrapped && $conf['wrapNonWrappedLines']) {
5111  $str_content = $this->wrap($str_content, $conf['wrapNonWrappedLines']);
5112  }
5113  $lParts[$k] = $str_content;
5114  }
5115  return implode(LF, $lParts);
5116  }
5117 
5129  public function http_makelinks($data, $conf) {
5130  $aTagParams = $this->getATagParams($conf);
5131  $schemes = array('http://', 'https://');
5132  foreach ($schemes as $scheme) {
5133  $textpieces = explode($scheme, $data);
5134  $pieces = count($textpieces);
5135  $textstr = $textpieces[0];
5136  $initP = '?id=' . $GLOBALS['TSFE']->id . '&type=' . $GLOBALS['TSFE']->type;
5137  for ($i = 1; $i < $pieces; $i++) {
5138  $len = strcspn($textpieces[$i], chr(32) . TAB . CRLF);
5139  if (trim(substr($textstr, -1)) == '' && $len) {
5140  $lastChar = substr($textpieces[$i], $len - 1, 1);
5141  if (!preg_match('/[A-Za-z0-9\\/#_-]/', $lastChar)) {
5142  $len--;
5143  }
5144  // Included '\/' 3/12
5145  $parts[0] = substr($textpieces[$i], 0, $len);
5146  $parts[1] = substr($textpieces[$i], $len);
5147  $keep = $conf['keep'];
5148  $linkParts = parse_url($scheme . $parts[0]);
5149  $linktxt = '';
5150  if (strstr($keep, 'scheme')) {
5151  $linktxt = $scheme;
5152  }
5153  $linktxt .= $linkParts['host'];
5154  if (strstr($keep, 'path')) {
5155  $linktxt .= $linkParts['path'];
5156  // Added $linkParts['query'] 3/12
5157  if (strstr($keep, 'query') && $linkParts['query']) {
5158  $linktxt .= '?' . $linkParts['query'];
5159  } elseif ($linkParts['path'] == '/') {
5160  $linktxt = substr($linktxt, 0, -1);
5161  }
5162  }
5163  if (isset($conf['extTarget'])) {
5164  if (isset($conf['extTarget.'])) {
5165  $target = $this->stdWrap($conf['extTarget'], $conf['extTarget.']);
5166  } else {
5167  $target = $conf['extTarget'];
5168  }
5169  } else {
5170  $target = $GLOBALS['TSFE']->extTarget;
5171  }
5172  if ($GLOBALS['TSFE']->config['config']['jumpurl_enable']) {
5173  $jumpurl = 'http://' . $parts[0];
5174  $juHash = GeneralUtility::hmac($jumpurl, 'jumpurl');
5175  $res = '<a' . ' href="' . htmlspecialchars(($GLOBALS['TSFE']->absRefPrefix . $GLOBALS['TSFE']->config['mainScript'] . $initP . '&jumpurl=' . rawurlencode($jumpurl))) . '&juHash=' . $juHash . $GLOBALS['TSFE']->getMethodUrlIdToken . '"' . ($target ? ' target="' . htmlspecialchars($target) . '"' : '') . $aTagParams . $this->extLinkATagParams(('http://' . $parts[0]), 'url') . '>';
5176  } else {
5177  $res = '<a' . ' href="' . $scheme . htmlspecialchars($parts[0]) . '"' . ($target ? ' target="' . htmlspecialchars($target) . '"' : '') . $aTagParams . $this->extLinkATagParams(('http://' . $parts[0]), 'url') . '>';
5178  }
5179  $wrap = isset($conf['wrap.']) ? $this->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
5180  if ($conf['ATagBeforeWrap']) {
5181  $res = $res . $this->wrap($linktxt, $wrap) . '</a>';
5182  } else {
5183  $res = $this->wrap($res . $linktxt . '</a>', $wrap);
5184  }
5185  $textstr .= $res . $parts[1];
5186  } else {
5187  $textstr .= $scheme . $textpieces[$i];
5188  }
5189  }
5190  $data = $textstr;
5191  }
5192  return $textstr;
5193  }
5194 
5205  public function mailto_makelinks($data, $conf) {
5206  // http-split
5207  $aTagParams = $this->getATagParams($conf);
5208  $textpieces = explode('mailto:', $data);
5209  $pieces = count($textpieces);
5210  $textstr = $textpieces[0];
5211  $initP = '?id=' . $GLOBALS['TSFE']->id . '&type=' . $GLOBALS['TSFE']->type;
5212  for ($i = 1; $i < $pieces; $i++) {
5213  $len = strcspn($textpieces[$i], chr(32) . TAB . CRLF);
5214  if (trim(substr($textstr, -1)) == '' && $len) {
5215  $lastChar = substr($textpieces[$i], $len - 1, 1);
5216  if (!preg_match('/[A-Za-z0-9]/', $lastChar)) {
5217  $len--;
5218  }
5219  $parts[0] = substr($textpieces[$i], 0, $len);
5220  $parts[1] = substr($textpieces[$i], $len);
5221  $linktxt = preg_replace('/\\?.*/', '', $parts[0]);
5222  list($mailToUrl, $linktxt) = $this->getMailTo($parts[0], $linktxt, $initP);
5223  $mailToUrl = $GLOBALS['TSFE']->spamProtectEmailAddresses === 'ascii' ? $mailToUrl : htmlspecialchars($mailToUrl);
5224  $res = '<a href="' . $mailToUrl . '"' . $aTagParams . '>';
5225  $wrap = isset($conf['wrap.']) ? $this->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
5226  if ($conf['ATagBeforeWrap']) {
5227  $res = $res . $this->wrap($linktxt, $wrap) . '</a>';
5228  } else {
5229  $res = $this->wrap($res . $linktxt . '</a>', $wrap);
5230  }
5231  $textstr .= $res . $parts[1];
5232  } else {
5233  $textstr .= 'mailto:' . $textpieces[$i];
5234  }
5235  }
5236  return $textstr;
5237  }
5238 
5263  public function getImgResource($file, $fileArray) {
5264  if (empty($file) && empty($fileArray)) {
5265  return NULL;
5266  }
5267  if (!is_array($fileArray)) {
5268  $fileArray = (array) $fileArray;
5269  }
5270  $imageResource = NULL;
5271  if ($file === 'GIFBUILDER') {
5273  $gifCreator = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Imaging\\GifBuilder');
5274  $gifCreator->init();
5275  $theImage = '';
5276  if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) {
5277  $gifCreator->start($fileArray, $this->data);
5278  $theImage = $gifCreator->gifBuild();
5279  }
5280  $imageResource = $gifCreator->getImageDimensions($theImage);
5281  $imageResource['origFile'] = $theImage;
5282  } else {
5283  if ($file instanceof \TYPO3\CMS\Core\Resource\File) {
5284  $fileObject = $file;
5285  } elseif ($file instanceof \TYPO3\CMS\Core\Resource\FileReference) {
5286  $fileObject = $file->getOriginalFile();
5287  } else {
5288  try {
5289  if ($fileArray['import.']) {
5290  $importedFile = trim($this->stdWrap('', $fileArray['import.']));
5291  if (!empty($importedFile)) {
5292  $file = $importedFile;
5293  }
5294  }
5295 
5296  if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($file)) {
5297  if (!empty($fileArray['treatIdAsReference'])) {
5298  $fileObject = $this->getResourceFactory()->getFileReferenceObject($file)->getOriginalFile();
5299  } else {
5300  $fileObject = $this->getResourceFactory()->getFileObject($file);
5301  }
5302  } elseif (preg_match('/^(0|[1-9][0-9]*):/', $file)) { // combined identifier
5303  $fileObject = $this->getResourceFactory()->retrieveFileOrFolderObject($file);
5304  } else {
5305  if (isset($importedFile) && !empty($importedFile) && !empty($fileArray['import'])) {
5306  $file = $fileArray['import'] . $file;
5307  }
5308  // clean ../ sections of the path and resolve to proper string. This is necessary for the Tx_File_BackwardsCompatibility_TslibContentAdapter to work.
5309  $file = GeneralUtility::resolveBackPath($file);
5310  $fileObject = $this->getResourceFactory()->retrieveFileOrFolderObject($file);
5311  }
5312  } catch (\TYPO3\CMS\Core\Resource\Exception $exception) {
5314  $logger = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager')->getLogger(__CLASS__);
5315  $logger->warning('The image "' . $file . '" could not be found and won\'t be included in frontend output');
5316  return NULL;
5317  }
5318  }
5319  if ($fileObject instanceof \TYPO3\CMS\Core\Resource\File) {
5320  $processingConfiguration = array();
5321  $processingConfiguration['width'] = isset($fileArray['width.']) ? $this->stdWrap($fileArray['width'], $fileArray['width.']) : $fileArray['width'];
5322  $processingConfiguration['height'] = isset($fileArray['height.']) ? $this->stdWrap($fileArray['height'], $fileArray['height.']) : $fileArray['height'];
5323  $processingConfiguration['fileExtension'] = isset($fileArray['ext.']) ? $this->stdWrap($fileArray['ext'], $fileArray['ext.']) : $fileArray['ext'];
5324  $processingConfiguration['maxWidth'] = isset($fileArray['maxW.']) ? (int)$this->stdWrap($fileArray['maxW'], $fileArray['maxW.']) : (int)$fileArray['maxW'];
5325  $processingConfiguration['maxHeight'] = isset($fileArray['maxH.']) ? (int)$this->stdWrap($fileArray['maxH'], $fileArray['maxH.']) : (int)$fileArray['maxH'];
5326  $processingConfiguration['minWidth'] = isset($fileArray['minW.']) ? (int)$this->stdWrap($fileArray['minW'], $fileArray['minW.']) : (int)$fileArray['minW'];
5327  $processingConfiguration['minHeight'] = isset($fileArray['minH.']) ? (int)$this->stdWrap($fileArray['minH'], $fileArray['minH.']) : (int)$fileArray['minH'];
5328  $processingConfiguration['noScale'] = isset($fileArray['noScale.']) ? $this->stdWrap($fileArray['noScale'], $fileArray['noScale.']) : $fileArray['noScale'];
5329  $processingConfiguration['additionalParameters'] = isset($fileArray['params.']) ? $this->stdWrap($fileArray['params'], $fileArray['params.']) : $fileArray['params'];
5330  $processingConfiguration['frame'] = isset($fileArray['frame.']) ? (int)$this->stdWrap($fileArray['frame'], $fileArray['frame.']) : (int)$fileArray['frame'];
5331  // Possibility to cancel/force profile extraction
5332  // see $TYPO3_CONF_VARS['GFX']['im_stripProfileCommand']
5333  if (isset($fileArray['stripProfile'])) {
5334  $processingConfiguration['stripProfile'] = $fileArray['stripProfile'];
5335  }
5336  // Check if we can handle this type of file for editing
5337  if (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileObject->getExtension())) {
5338  $maskArray = $fileArray['m.'];
5339  // Must render mask images and include in hash-calculating
5340  // - otherwise we cannot be sure the filename is unique for the setup!
5341  if (is_array($maskArray)) {
5342  $mask = $this->getImgResource($maskArray['mask'], $maskArray['mask.']);
5343  $bgImg = $this->getImgResource($maskArray['bgImg'], $maskArray['bgImg.']);
5344  $bottomImg = $this->getImgResource($maskArray['bottomImg'], $maskArray['bottomImg.']);
5345  $bottomImg_mask = $this->getImgResource($maskArray['bottomImg_mask'], $maskArray['bottomImg_mask.']);
5346 
5347  $processingConfiguration['maskImages']['maskImage'] = $mask['processedFile'];
5348  $processingConfiguration['maskImages']['backgroundImage'] = $bgImg['processedFile'];
5349  $processingConfiguration['maskImages']['maskBottomImage'] = $bottomImg['processedFile'];
5350  $processingConfiguration['maskImages']['maskBottomImageMask'] = $bottomImg_mask['processedFile'];
5351  }
5352  if ($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix']) {
5353  $processingConfiguration['useTargetFileNameAsPrefix'] = 1;
5354  }
5355  $processedFileObject = $fileObject->process(\TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $processingConfiguration);
5356  $hash = $processedFileObject->calculateChecksum();
5357  // store info in the TSFE template cache (kept for backwards compatibility)
5358  if ($processedFileObject->isProcessed() && !isset($GLOBALS['TSFE']->tmpl->fileCache[$hash])) {
5359  $GLOBALS['TSFE']->tmpl->fileCache[$hash] = array(
5360  0 => $processedFileObject->getProperty('width'),
5361  1 => $processedFileObject->getProperty('height'),
5362  2 => $processedFileObject->getExtension(),
5363  3 => $processedFileObject->getPublicUrl(),
5364  'origFile' => $fileObject->getPublicUrl(),
5365  'origFile_mtime' => $fileObject->getModificationTime(),
5366  // This is needed by \TYPO3\CMS\Frontend\Imaging\GifBuilder,
5367  // in order for the setup-array to create a unique filename hash.
5368  'originalFile' => $fileObject,
5369  'processedFile' => $processedFileObject,
5370  'fileCacheHash' => $hash
5371  );
5372  }
5373  $imageResource = $GLOBALS['TSFE']->tmpl->fileCache[$hash];
5374  }
5375  }
5376  }
5377  // If image was processed by GIFBUILDER:
5378  // ($imageResource indicates that it was processed the regular way)
5379  if (!isset($imageResource)) {
5380  $theImage = $GLOBALS['TSFE']->tmpl->getFileName($file);
5381  if ($theImage) {
5382  $gifCreator = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Imaging\\GifBuilder');
5384  $gifCreator->init();
5385  $info = $gifCreator->imageMagickConvert($theImage, 'WEB');
5386  $info['origFile'] = $theImage;
5387  // This is needed by \TYPO3\CMS\Frontend\Imaging\GifBuilder, ln 100ff in order for the setup-array to create a unique filename hash.
5388  $info['origFile_mtime'] = @filemtime($theImage);
5389  $imageResource = $info;
5390  }
5391  }
5392  // Hook 'getImgResource': Post-processing of image resources
5393  if (isset($imageResource)) {
5395  foreach ($this->getGetImgResourceHookObjects() as $hookObject) {
5396  $imageResource = $hookObject->getImgResourcePostProcess($file, (array) $fileArray, $imageResource, $this);
5397  }
5398  }
5399  return $imageResource;
5400  }
5401 
5402  /***********************************************
5403  *
5404  * Data retrieval etc.
5405  *
5406  ***********************************************/
5414  public function getFieldVal($field) {
5415  if (!strstr($field, '//')) {
5416  return $this->data[trim($field)];
5417  } else {
5418  $sections = GeneralUtility::trimExplode('//', $field, TRUE);
5419  foreach ($sections as $k) {
5420  if ((string)$this->data[$k] !== '') {
5421  return $this->data[$k];
5422  }
5423  }
5424  }
5425  }
5426 
5436  public function getData($string, $fieldArray = NULL) {
5437  if (!is_array($fieldArray)) {
5438  $fieldArray = $GLOBALS['TSFE']->page;
5439  }
5440  $retVal = '';
5441  $sections = explode('//', $string);
5442  while (!$retVal and list($secKey, $secVal) = each($sections)) {
5443  $parts = explode(':', $secVal, 2);
5444  $type = strtolower(trim($parts[0]));
5445  $typesWithOutParameters = array('level', 'date', 'current');
5446  $key = trim($parts[1]);
5447  if (($key != '') || in_array($type, $typesWithOutParameters)) {
5448  switch ($type) {
5449  case 'gp':
5450  // Merge GET and POST and get $key out of the merged array
5451  $getPostArray = GeneralUtility::_GET();
5453  $retVal = $this->getGlobal($key, $getPostArray);
5454  break;
5455  case 'tsfe':
5456  $retVal = $this->getGlobal('TSFE|' . $key);
5457  break;
5458  case 'getenv':
5459  $retVal = getenv($key);
5460  break;
5461  case 'getindpenv':
5462  $retVal = $this->getEnvironmentVariable($key);
5463  break;
5464  case 'field':
5465  $retVal = $fieldArray[$key];
5466  break;
5467  case 'file':
5468  $retVal = $this->getFileDataKey($key);
5469  break;
5470  case 'parameters':
5471  $retVal = $this->parameters[$key];
5472  break;
5473  case 'register':
5474  $retVal = $GLOBALS['TSFE']->register[$key];
5475  break;
5476  case 'global':
5477  $retVal = $this->getGlobal($key);
5478  break;
5479  case 'level':
5480  $retVal = count($GLOBALS['TSFE']->tmpl->rootLine) - 1;
5481  break;
5482  case 'leveltitle':
5483  $keyParts = GeneralUtility::trimExplode(',', $key);
5484  $numericKey = $this->getKey($keyParts[0], $GLOBALS['TSFE']->tmpl->rootLine);
5485  $retVal = $this->rootLineValue($numericKey, 'title', strtolower($keyParts[1]) === 'slide');
5486  break;
5487  case 'levelmedia':
5488  $keyParts = GeneralUtility::trimExplode(',', $key);
5489  $numericKey = $this->getKey($keyParts[0], $GLOBALS['TSFE']->tmpl->rootLine);
5490  $retVal = $this->rootLineValue($numericKey, 'media', strtolower($keyParts[1]) === 'slide');
5491  break;
5492  case 'leveluid':
5493  $numericKey = $this->getKey($key, $GLOBALS['TSFE']->tmpl->rootLine);
5494  $retVal = $this->rootLineValue($numericKey, 'uid');
5495  break;
5496  case 'levelfield':
5497  $keyParts = GeneralUtility::trimExplode(',', $key);
5498  $numericKey = $this->getKey($keyParts[0], $GLOBALS['TSFE']->tmpl->rootLine);
5499  $retVal = $this->rootLineValue($numericKey, $keyParts[1], strtolower($keyParts[2]) === 'slide');
5500  break;
5501  case 'fullrootline':
5502  $keyParts = GeneralUtility::trimExplode(',', $key);
5503  $fullKey = (int)$keyParts[0] - count($GLOBALS['TSFE']->tmpl->rootLine) + count($GLOBALS['TSFE']->rootLine);
5504  if ($fullKey >= 0) {
5505  $retVal = $this->rootLineValue($fullKey, $keyParts[1], stristr($keyParts[2], 'slide'), $GLOBALS['TSFE']->rootLine);
5506  }
5507  break;
5508  case 'date':
5509  if (!$key) {
5510  $key = 'd/m Y';
5511  }
5512  $retVal = date($key, $GLOBALS['EXEC_TIME']);
5513  break;
5514  case 'page':
5515  $retVal = $GLOBALS['TSFE']->page[$key];
5516  break;
5517  case 'current':
5518  $retVal = $this->data[$this->currentValKey];
5519  break;
5520  case 'db':
5521  $selectParts = GeneralUtility::trimExplode(':', $key);
5522  $db_rec = $GLOBALS['TSFE']->sys_page->getRawRecord($selectParts[0], $selectParts[1]);
5523  if (is_array($db_rec) && $selectParts[2]) {
5524  $retVal = $db_rec[$selectParts[2]];
5525  }
5526  break;
5527  case 'lll':
5528  $retVal = $GLOBALS['TSFE']->sL('LLL:' . $key);
5529  break;
5530  case 'path':
5531  $retVal = $GLOBALS['TSFE']->tmpl->getFileName($key);
5532  break;
5533  case 'cobj':
5534  switch ($key) {
5535  case 'parentRecordNumber':
5536  $retVal = $this->parentRecordNumber;
5537  break;
5538  }
5539  break;
5540  case 'debug':
5541  switch ($key) {
5542  case 'rootLine':
5543  $retVal = \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($GLOBALS['TSFE']->tmpl->rootLine);
5544  break;
5545  case 'fullRootLine':
5546  $retVal = \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($GLOBALS['TSFE']->rootLine);
5547  break;
5548  case 'data':
5549  $retVal = \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($this->data);
5550  break;
5551  case 'register':
5552  $retVal = \TYPO3\CMS\Core\Utility\DebugUtility::viewArray($GLOBALS['TSFE']->register);
5553  break;
5554  case 'page':
5556  break;
5557  }
5558  break;
5559  }
5560  }
5561  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getData'])) {
5562  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getData'] as $classData) {
5563  $hookObject = GeneralUtility::getUserObj($classData);
5564  if (!$hookObject instanceof \TYPO3\CMS\Frontend\ContentObject\ContentObjectGetDataHookInterface) {
5565  throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectGetDataHookInterface', 1195044480);
5566  }
5567  $retVal = $hookObject->getDataExtension($string, $fieldArray, $secVal, $retVal, $this);
5568  }
5569  }
5570  }
5571  return $retVal;
5572  }
5573 
5583  protected function getFileDataKey($key) {
5584  $parts = explode(':', $key);
5585  $fileUidOrCurrentKeyword = $parts[0];
5586  $requestedFileInformationKey = $parts[1];
5587  try {
5588  if ($fileUidOrCurrentKeyword === 'current') {
5589  $fileObject = $this->getCurrentFile();
5590  } elseif (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($fileUidOrCurrentKeyword)) {
5592  $fileFactory = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory');
5593  $fileObject = $fileFactory->getFileObject($fileUidOrCurrentKeyword);
5594  } else {
5595  $fileObject = NULL;
5596  }
5597  } catch (\TYPO3\CMS\Core\Resource\Exception $exception) {
5599  $logger = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager')->getLogger(__CLASS__);
5600  $logger->warning('The file "' . $fileUidOrCurrentKeyword . '" could not be found and won\'t be included in frontend output');
5601  $fileObject = NULL;
5602  }
5603 
5604  if ($fileObject instanceof \TYPO3\CMS\Core\Resource\FileInterface) {
5605  // All properties of the \TYPO3\CMS\Core\Resource\FileInterface are available here:
5606  switch ($requestedFileInformationKey) {
5607  case 'name':
5608  return $fileObject->getName();
5609  break;
5610  case 'uid':
5611  return $fileObject->getUid();
5612  break;
5613  case 'originalUid':
5614  if ($fileObject instanceof \TYPO3\CMS\Core\Resource\FileReference) {
5615  return $fileObject->getOriginalFile()->getUid();
5616  } else {
5617  return NULL;
5618  }
5619  break;
5620  case 'size':
5621  return $fileObject->getSize();
5622  break;
5623  case 'sha1':
5624  return $fileObject->getSha1();
5625  break;
5626  case 'extension':
5627  return $fileObject->getExtension();
5628  break;
5629  case 'mimetype':
5630  return $fileObject->getMimeType();
5631  break;
5632  case 'contents':
5633  return $fileObject->getContents();
5634  break;
5635  case 'publicUrl':
5636  return $fileObject->getPublicUrl();
5637  break;
5638  case 'localPath':
5639  return $fileObject->getForLocalProcessing(FALSE);
5640  break;
5641  default:
5642  // Generic alternative here
5643  return $fileObject->getProperty($requestedFileInformationKey);
5644  }
5645  } else {
5646  // TODO: fail silently as is common in tslib_content
5647  return 'Error: no file object';
5648  }
5649  }
5650 
5663  public function rootLineValue($key, $field, $slideBack = 0, $altRootLine = '') {
5664  $rootLine = is_array($altRootLine) ? $altRootLine : $GLOBALS['TSFE']->tmpl->rootLine;
5665  if (!$slideBack) {
5666  return $rootLine[$key][$field];
5667  } else {
5668  for ($a = $key; $a >= 0; $a--) {
5669  $val = $rootLine[$a][$field];
5670  if ($val) {
5671  return $val;
5672  }
5673  }
5674  }
5675  }
5676 
5687  public function getGlobal($keyString, $source = NULL) {
5688  $keys = explode('|', $keyString);
5689  $numberOfLevels = count($keys);
5690  $rootKey = trim($keys[0]);
5691  $value = isset($source) ? $source[$rootKey] : $GLOBALS[$rootKey];
5692  for ($i = 1; $i < $numberOfLevels && isset($value); $i++) {
5693  $currentKey = trim($keys[$i]);
5694  if (is_object($value)) {
5695  $value = $value->{$currentKey};
5696  } elseif (is_array($value)) {
5697  $value = $value[$currentKey];
5698  } else {
5699  $value = '';
5700  break;
5701  }
5702  }
5703  if (!is_scalar($value)) {
5704  $value = '';
5705  }
5706  return $value;
5707  }
5708 
5720  public function getKey($key, $arr) {
5721  $key = (int)$key;
5722  if (is_array($arr)) {
5723  if ($key < 0) {
5724  $key = count($arr) + $key;
5725  }
5726  if ($key < 0) {
5727  $key = 0;
5728  }
5729  }
5730  return $key;
5731  }
5732 
5743  public function TCAlookup($inputValue, $conf) {
5744  $table = $conf['table'];
5745  $field = $conf['field'];
5746  $delimiter = $conf['delimiter'] ? $conf['delimiter'] : ' ,';
5747  if (is_array($GLOBALS['TCA'][$table]) && is_array($GLOBALS['TCA'][$table]['columns'][$field]) && is_array($GLOBALS['TCA'][$table]['columns'][$field]['config']['items'])) {
5748  $values = GeneralUtility::trimExplode(',', $inputValue);
5749  $output = array();
5750  foreach ($values as $value) {
5751  // Traverse the items-array...
5752  foreach ($GLOBALS['TCA'][$table]['columns'][$field]['config']['items'] as $item) {
5753  // ... and return the first found label where the value was equal to $key
5754  if ((string)$item[1] === trim($value)) {
5755  $output[] = $GLOBALS['TSFE']->sL($item[0]);
5756  }
5757  }
5758  }
5759  $returnValue = implode($delimiter, $output);
5760  } else {
5761  $returnValue = $inputValue;
5762  }
5763  return $returnValue;
5764  }
5765 
5766  /***********************************************
5767  *
5768  * Link functions (typolink)
5769  *
5770  ***********************************************/
5786  public function typoLink($linktxt, $conf) {
5787  $LD = array();
5788  $finalTagParts = array();
5789  $finalTagParts['aTagParams'] = $this->getATagParams($conf);
5790  $link_param = isset($conf['parameter.']) ? trim($this->stdWrap($conf['parameter'], $conf['parameter.'])) : trim($conf['parameter']);
5791  $sectionMark = isset($conf['section.']) ? trim($this->stdWrap($conf['section'], $conf['section.'])) : trim($conf['section']);
5792  $sectionMark = $sectionMark ? (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($sectionMark) ? '#c' : '#') . $sectionMark : '';
5793  $initP = '?id=' . $GLOBALS['TSFE']->id . '&type=' . $GLOBALS['TSFE']->type;
5794  $this->lastTypoLinkUrl = '';
5795  $this->lastTypoLinkTarget = '';
5796  if ($link_param) {
5797  $enableLinksAcrossDomains = $GLOBALS['TSFE']->config['config']['typolinkEnableLinksAcrossDomains'];
5798  $link_paramA = GeneralUtility::unQuoteFilenames($link_param, TRUE);
5799  // Check for link-handler keyword:
5800  list($linkHandlerKeyword, $linkHandlerValue) = explode(':', trim($link_paramA[0]), 2);
5801  if ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword] && (string)$linkHandlerValue !== '') {
5802  $linkHandlerObj = GeneralUtility::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$linkHandlerKeyword]);
5803  if (method_exists($linkHandlerObj, 'main')) {
5804  return $linkHandlerObj->main($linktxt, $conf, $linkHandlerKeyword, $linkHandlerValue, $link_param, $this);
5805  }
5806  }
5807  // Resolve FAL-api "file:UID-of-sys_file-record" and "file:combined-identifier"
5808  if ($linkHandlerKeyword === 'file' && !GeneralUtility::isFirstPartOfStr($link_paramA[0], 'file://')) {
5809  try {
5810  $fileOrFolderObject = $this->getResourceFactory()->retrieveFileOrFolderObject($linkHandlerValue);
5811  // Link to a folder or file
5812  if ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\ResourceInterface) {
5813  $link_paramA[0] = $fileOrFolderObject->getPublicUrl();
5814  } else {
5815  $link_paramA[0] = NULL;
5816  }
5817  } catch (\RuntimeException $e) {
5818  // Element wasn't found
5819  $link_paramA[0] = NULL;
5820  } catch (\TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException $e) {
5821  // Resource was not found
5822  return $linktxt;
5823  }
5824  // Disallow direct javascript: or data: links
5825  } elseif (in_array(strtolower(trim($linkHandlerKeyword)), array('javascript', 'data'), TRUE)) {
5826  return $linktxt;
5827  }
5828  // Link parameter value
5829  $link_param = trim($link_paramA[0]);
5830  // Link class
5831  $linkClass = trim($link_paramA[2]);
5832  if ($linkClass == '-') {
5833  // The '-' character means 'no class'. Necessary in order to specify a title as fourth parameter without setting the target or class!
5834  $linkClass = '';
5835  }
5836  // Target value
5837  $forceTarget = trim($link_paramA[1]);
5838  if ($forceTarget == '-') {
5839  // The '-' character means 'no target'. Necessary in order to specify a class as third parameter without setting the target!
5840  $forceTarget = '';
5841  }
5842  // Title value
5843  $forceTitle = trim($link_paramA[3]);
5844  if ($forceTitle == '-') {
5845  // The '-' character means 'no title'. Necessary in order to specify further parameters without setting the title!
5846  $forceTitle = '';
5847  }
5848  if (isset($link_paramA[4]) && strlen(trim($link_paramA[4])) > 0) {
5849  $forceParams = trim($link_paramA[4]);
5850  // params value
5851  $conf['additionalParams'] .= $forceParams[0] == '&' ? $forceParams : '&' . $forceParams;
5852  }
5853  // Check, if the target is coded as a JS open window link:
5854  $JSwindowParts = array();
5855  $JSwindowParams = '';
5856  $onClick = '';
5857  if ($forceTarget && preg_match('/^([0-9]+)x([0-9]+)(:(.*)|.*)$/', $forceTarget, $JSwindowParts)) {
5858  // Take all pre-configured and inserted parameters and compile parameter list, including width+height:
5859  $JSwindow_tempParamsArr = GeneralUtility::trimExplode(',', strtolower($conf['JSwindow_params'] . ',' . $JSwindowParts[4]), TRUE);
5860  $JSwindow_paramsArr = array();
5861  foreach ($JSwindow_tempParamsArr as $JSv) {
5862  list($JSp, $JSv) = explode('=', $JSv);
5863  $JSwindow_paramsArr[$JSp] = $JSp . '=' . $JSv;
5864  }
5865  // Add width/height:
5866  $JSwindow_paramsArr['width'] = 'width=' . $JSwindowParts[1];
5867  $JSwindow_paramsArr['height'] = 'height=' . $JSwindowParts[2];
5868  // Imploding into string:
5869  $JSwindowParams = implode(',', $JSwindow_paramsArr);
5870  // Resetting the target since we will use onClick.
5871  $forceTarget = '';
5872  }
5873  // Internal target:
5874  if ($GLOBALS['TSFE']->dtdAllowsFrames) {
5875  $target = isset($conf['target']) ? $conf['target'] : $GLOBALS['TSFE']->intTarget;
5876  } else {
5877  $target = isset($conf['target']) ? $conf['target'] : '';
5878  }
5879  if ($conf['target.']) {
5880  $target = $this->stdWrap($target, $conf['target.']);
5881  }
5882  // Title tag
5883  $title = $conf['title'];
5884  if ($conf['title.']) {
5885  $title = $this->stdWrap($title, $conf['title.']);
5886  }
5887  // Parse URL:
5888  $pU = parse_url($link_param);
5889  // Detecting kind of link:
5890  // If it's a mail address:
5891  if (strstr($link_param, '@') && (!$pU['scheme'] || $pU['scheme'] == 'mailto')) {
5892  $link_param = preg_replace('/^mailto:/i', '', $link_param);
5893  list($this->lastTypoLinkUrl, $linktxt) = $this->getMailTo($link_param, $linktxt, $initP);
5894  $finalTagParts['url'] = $this->lastTypoLinkUrl;
5895  $finalTagParts['TYPE'] = 'mailto';
5896  } else {
5897  $isLocalFile = 0;
5898  $fileChar = (int)strpos($link_param, '/');
5899  $urlChar = (int)strpos($link_param, '.');
5900  // Firsts, test if $link_param is numeric and page with such id exists. If yes, do not attempt to link to file
5901  if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($link_param) || count($GLOBALS['TSFE']->sys_page->getPage_noCheck($link_param)) == 0) {
5902  // Detects if a file is found in site-root and if so it will be treated like a normal file.
5903  list($rootFileDat) = explode('?', rawurldecode($link_param));
5904  $containsSlash = strstr($rootFileDat, '/');
5905  $rFD_fI = pathinfo($rootFileDat);
5906  if (trim($rootFileDat) && !$containsSlash && (@is_file((PATH_site . $rootFileDat)) || GeneralUtility::inList('php,html,htm', strtolower($rFD_fI['extension'])))) {
5907  $isLocalFile = 1;
5908  } elseif ($containsSlash) {
5909  // Adding this so realurl directories are linked right (non-existing).
5910  $isLocalFile = 2;
5911  }
5912  }
5913  if ($pU['scheme'] || $isLocalFile != 1 && $urlChar && (!$containsSlash || $urlChar < $fileChar)) {
5914  // url (external): If doubleSlash or if a '.' comes before a '/'.
5915  if ($GLOBALS['TSFE']->dtdAllowsFrames) {
5916  $target = isset($conf['extTarget']) ? $conf['extTarget'] : $GLOBALS['TSFE']->extTarget;
5917  } else {
5918  $target = isset($conf['extTarget']) ? $conf['extTarget'] : '';
5919  }
5920  if ($conf['extTarget.']) {
5921  $target = $this->stdWrap($target, $conf['extTarget.']);
5922  }
5923  if ($forceTarget) {
5924  $target = $forceTarget;
5925  }
5926  if ($linktxt == '') {
5927  $linktxt = $this->parseFunc($link_param, array('makelinks' => 0), '< lib.parseFunc');
5928  }
5929  if (!$pU['scheme']) {
5930  $scheme = 'http://';
5931  } else {
5932  $scheme = '';
5933  }
5934  if ($GLOBALS['TSFE']->config['config']['jumpurl_enable']) {
5935  $url = $GLOBALS['TSFE']->absRefPrefix . $GLOBALS['TSFE']->config['mainScript'] . $initP;
5936  $jumpurl = $scheme . $link_param;
5937  $juHash = GeneralUtility::hmac($jumpurl, 'jumpurl');
5938  $this->lastTypoLinkUrl = $url . '&jumpurl=' . rawurlencode($jumpurl) . '&juHash='. $juHash . $GLOBALS['TSFE']->getMethodUrlIdToken;
5939  } else {
5940  $this->lastTypoLinkUrl = $scheme . $link_param;
5941  }
5942  $this->lastTypoLinkTarget = $target;
5943  $finalTagParts['url'] = $this->lastTypoLinkUrl;
5944  $finalTagParts['targetParams'] = $target ? ' target="' . htmlspecialchars($target) . '"' : '';
5945  $finalTagParts['TYPE'] = 'url';
5946  $finalTagParts['aTagParams'] .= $this->extLinkATagParams($finalTagParts['url'], $finalTagParts['TYPE']);
5947  } elseif ($containsSlash || $isLocalFile) {
5948  // file (internal)
5949  $splitLinkParam = explode('?', $link_param);
5950  if (file_exists(rawurldecode($splitLinkParam[0])) || $isLocalFile) {
5951  if ($linktxt == '') {
5952  $linktxt = $this->parseFunc(rawurldecode($link_param), array('makelinks' => 0), '< lib.parseFunc');
5953  }
5954  if ($GLOBALS['TSFE']->config['config']['jumpurl_enable'] || $conf['jumpurl']) {
5955  $theFileEnc = str_replace('%2F', '/', rawurlencode(rawurldecode($link_param)));
5956  $url = $GLOBALS['TSFE']->absRefPrefix . $GLOBALS['TSFE']->config['mainScript'] . $initP . '&jumpurl=' . rawurlencode($link_param);
5957  if ($conf['jumpurl.']['secure']) {
5958  $url .= $this->locDataJU($theFileEnc, $conf['jumpurl.']['secure.']);
5959  } else {
5960  $url .= '&juHash=' . GeneralUtility::hmac($link_param, 'jumpurl');
5961  }
5962  $this->lastTypoLinkUrl = $url . $GLOBALS['TSFE']->getMethodUrlIdToken;
5963  } else {
5964  $this->lastTypoLinkUrl = $GLOBALS['TSFE']->absRefPrefix . $link_param;
5965  }
5966  $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
5967  $target = isset($conf['fileTarget']) ? $conf['fileTarget'] : $GLOBALS['TSFE']->fileTarget;
5968  if ($conf['fileTarget.']) {
5969  $target = $this->stdWrap($target, $conf['fileTarget.']);
5970  }
5971  if ($forceTarget) {
5972  $target = $forceTarget;
5973  }
5974  $this->lastTypoLinkTarget = $target;
5975  $finalTagParts['url'] = $this->lastTypoLinkUrl;
5976  $finalTagParts['targetParams'] = $target ? ' target="' . htmlspecialchars($target) . '"' : '';
5977  $finalTagParts['TYPE'] = 'file';
5978  $finalTagParts['aTagParams'] .= $this->extLinkATagParams($finalTagParts['url'], $finalTagParts['TYPE']);
5979  } else {
5980  $GLOBALS['TT']->setTSlogMessage('typolink(): File \'' . $splitLinkParam[0] . '\' did not exist, so \'' . $linktxt . '\' was not linked.', 1);
5981  return $linktxt;
5982  }
5983  } else {
5984  // Integer or alias (alias is without slashes or periods or commas, that is
5985  // 'nospace,alphanum_x,lower,unique' according to definition in $GLOBALS['TCA']!)
5986  if ($conf['no_cache.']) {
5987  $conf['no_cache'] = $this->stdWrap($conf['no_cache'], $conf['no_cache.']);
5988  }
5989  // Splitting the parameter by ',' and if the array counts more than 1 element it's a id/type/parameters triplet
5990  $pairParts = GeneralUtility::trimExplode(',', $link_param, TRUE);
5991  $link_param = $pairParts[0];
5992  $link_params_parts = explode('#', $link_param);
5993  // Link-data del
5994  $link_param = trim($link_params_parts[0]);
5995  // If no id or alias is given
5996  if ($link_param === '') {
5997  $link_param = $GLOBALS['TSFE']->id;
5998  }
5999  if ($link_params_parts[1] && !$sectionMark) {
6000  $sectionMark = trim($link_params_parts[1]);
6001  $sectionMark = (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($sectionMark) ? '#c' : '#') . $sectionMark;
6002  }
6003  if (count($pairParts) > 1) {
6004  // Overruling 'type'
6005  $theTypeP = isset($pairParts[1]) ? $pairParts[1] : 0;
6006  $conf['additionalParams'] .= isset($pairParts[2]) ? $pairParts[2] : '';
6007  }
6008  // Checking if the id-parameter is an alias.
6009  if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($link_param)) {
6010  $link_param = $GLOBALS['TSFE']->sys_page->getPageIdFromAlias($link_param);
6011  }
6012  // Link to page even if access is missing?
6013  if (strlen($conf['linkAccessRestrictedPages'])) {
6014  $disableGroupAccessCheck = $conf['linkAccessRestrictedPages'] ? TRUE : FALSE;
6015  } else {
6016  $disableGroupAccessCheck = $GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages'] ? TRUE : FALSE;
6017  }
6018  // Looking up the page record to verify its existence:
6019  $page = $GLOBALS['TSFE']->sys_page->getPage($link_param, $disableGroupAccessCheck);
6020  if (count($page)) {
6021  // MointPoints, look for closest MPvar:
6022  $MPvarAcc = array();
6023  if (!$GLOBALS['TSFE']->config['config']['MP_disableTypolinkClosestMPvalue']) {
6024  $temp_MP = $this->getClosestMPvalueForPage($page['uid'], TRUE);
6025  if ($temp_MP) {
6026  $MPvarAcc['closest'] = $temp_MP;
6027  }
6028  }
6029  // Look for overlay Mount Point:
6030  $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($page['uid'], $page);
6031  if (is_array($mount_info) && $mount_info['overlay']) {
6032  $page = $GLOBALS['TSFE']->sys_page->getPage($mount_info['mount_pid'], $disableGroupAccessCheck);
6033  if (!count($page)) {
6034  $GLOBALS['TT']->setTSlogMessage('typolink(): Mount point \'' . $mount_info['mount_pid'] . '\' was not available, so \'' . $linktxt . '\' was not linked.', 1);
6035  return $linktxt;
6036  }
6037  $MPvarAcc['re-map'] = $mount_info['MPvar'];
6038  }
6039  // Setting title if blank value to link:
6040  if ($linktxt == '') {
6041  $linktxt = $this->parseFunc($page['title'], array('makelinks' => 0), '< lib.parseFunc');
6042  }
6043  // Query Params:
6044  $addQueryParams = $conf['addQueryString'] ? $this->getQueryArguments($conf['addQueryString.']) : '';
6045  $addQueryParams .= isset($conf['additionalParams.']) ? trim($this->stdWrap($conf['additionalParams'], $conf['additionalParams.'])) : trim($conf['additionalParams']);
6046  if ($addQueryParams === '&' || $addQueryParams[0] !== '&') {
6047  $addQueryParams = '';
6048  }
6049  $targetDomain = '';
6050  $currentDomain = $this->getEnvironmentVariable('HTTP_HOST');
6051  // Mount pages are always local and never link to another domain
6052  if (count($MPvarAcc)) {
6053  // Add "&MP" var:
6054  $addQueryParams .= '&MP=' . rawurlencode(implode(',', $MPvarAcc));
6055  } elseif (strpos($addQueryParams, '&MP=') === FALSE && $GLOBALS['TSFE']->config['config']['typolinkCheckRootline']) {
6056  // We do not come here if additionalParams had '&MP='. This happens when typoLink is called from
6057  // menu. Mount points always work in the content of the current domain and we must not change
6058  // domain if MP variables exist.
6059  // If we link across domains and page is free type shortcut, we must resolve the shortcut first!
6060  // If we do not do it, TYPO3 will fail to (1) link proper page in RealURL/CoolURI because
6061  // they return relative links and (2) show proper page if no RealURL/CoolURI exists when link is clicked
6062  if ($enableLinksAcrossDomains && $page['doktype'] == \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_SHORTCUT && $page['shortcut_mode'] == \TYPO3\CMS\Frontend\Page\PageRepository::SHORTCUT_MODE_NONE) {
6063  // Save in case of broken destination or endless loop
6064  $page2 = $page;
6065  // Same as in RealURL, seems enough
6066  $maxLoopCount = 20;
6067  while ($maxLoopCount && is_array($page) && $page['doktype'] == \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_SHORTCUT && $page['shortcut_mode'] == \TYPO3\CMS\Frontend\Page\PageRepository::SHORTCUT_MODE_NONE) {
6068  $page = $GLOBALS['TSFE']->sys_page->getPage($page['shortcut'], $disableGroupAccessCheck);
6069  $maxLoopCount--;
6070  }
6071  if (count($page) == 0 || $maxLoopCount == 0) {
6072  // We revert if shortcut is broken or maximum number of loops is exceeded (indicates endless loop)
6073  $page = $page2;
6074  }
6075  }
6076 
6077  $targetDomain = $GLOBALS['TSFE']->getDomainNameForPid($page['uid']);
6078  // Do not prepend the domain if it is the current hostname
6079  if (!$targetDomain || $GLOBALS['TSFE']->domainNameMatchesCurrentRequest($targetDomain)) {
6080  $targetDomain = '';
6081  }
6082  }
6083  if ($conf['useCacheHash']) {
6084  $params = $GLOBALS['TSFE']->linkVars . $addQueryParams . '&id=' . $page['uid'];
6085  if (trim($params, '& ') != '') {
6087  $cacheHash = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\CacheHashCalculator');
6088  $cHash = $cacheHash->generateForParameters($params);
6089  $addQueryParams .= $cHash ? '&cHash=' . $cHash : '';
6090  }
6091  unset($params);
6092  }
6093  $absoluteUrlScheme = 'http';
6094  // URL shall be absolute:
6095  if (isset($conf['forceAbsoluteUrl']) && $conf['forceAbsoluteUrl'] || $page['url_scheme'] > 0) {
6096  // Override scheme:
6097  if (isset($conf['forceAbsoluteUrl.']['scheme']) && $conf['forceAbsoluteUrl.']['scheme']) {
6098  $absoluteUrlScheme = $conf['forceAbsoluteUrl.']['scheme'];
6099  } elseif ($page['url_scheme'] > 0) {
6100  $absoluteUrlScheme = (int)$page['url_scheme'] === \TYPO3\CMS\Core\Utility\HttpUtility::SCHEME_HTTP ? 'http' : 'https';
6101  } elseif ($this->getEnvironmentVariable('TYPO3_SSL')) {
6102  $absoluteUrlScheme = 'https';
6103  }
6104  // If no domain records are defined, use current domain:
6105  $currentUrlScheme = parse_url($this->getEnvironmentVariable('TYPO3_REQUEST_URL'), PHP_URL_SCHEME);
6106  if ($targetDomain === '' && ($conf['forceAbsoluteUrl'] || $absoluteUrlScheme !== $currentUrlScheme)) {
6107  $targetDomain = $currentDomain;
6108  }
6109  // If go for an absolute link, add site path if it's not taken care about by absRefPrefix
6110  if (!$GLOBALS['TSFE']->config['config']['absRefPrefix'] && $targetDomain == $currentDomain) {
6111  $targetDomain = $currentDomain . rtrim($this->getEnvironmentVariable('TYPO3_SITE_PATH'), '/');
6112  }
6113  }
6114  // If target page has a different domain and the current domain's linking scheme (e.g. RealURL/...) should not be used
6115  if (strlen($targetDomain) && $targetDomain !== $currentDomain && !$enableLinksAcrossDomains) {
6116  $target = isset($conf['extTarget']) ? $conf['extTarget'] : $GLOBALS['TSFE']->extTarget;
6117  if ($conf['extTarget.']) {
6118  $target = $this->stdWrap($target, $conf['extTarget.']);
6119  }
6120  if ($forceTarget) {
6121  $target = $forceTarget;
6122  }
6123  $LD['target'] = $target;
6124  // Convert IDNA-like domain (if any)
6125  if (!preg_match('/^[a-z0-9.\\-]*$/i', $targetDomain)) {
6126  $targetDomain = GeneralUtility::idnaEncode($targetDomain);
6127  }
6128  $this->lastTypoLinkUrl = $this->URLqMark(($absoluteUrlScheme . '://' . $targetDomain . '/index.php?id=' . $page['uid']), $addQueryParams) . $sectionMark;
6129  } else {
6130  // Internal link or current domain's linking scheme should be used
6131  if ($forceTarget) {
6132  $target = $forceTarget;
6133  }
6134  $LD = $GLOBALS['TSFE']->tmpl->linkData($page, $target, $conf['no_cache'], '', '', $addQueryParams, $theTypeP, $targetDomain);
6135  if (strlen($targetDomain)) {
6136  // We will add domain only if URL does not have it already.
6137  if ($enableLinksAcrossDomains && $targetDomain !== $currentDomain) {
6138  // Get rid of the absRefPrefix if necessary. absRefPrefix is applicable only
6139  // to the current web site. If we have domain here it means we link across
6140  // domains. absRefPrefix can contain domain name, which will screw up
6141  // the link to the external domain.
6142  $prefixLength = strlen($GLOBALS['TSFE']->config['config']['absRefPrefix']);
6143  if (substr($LD['totalURL'], 0, $prefixLength) == $GLOBALS['TSFE']->config['config']['absRefPrefix']) {
6144  $LD['totalURL'] = substr($LD['totalURL'], $prefixLength);
6145  }
6146  }
6147  $urlParts = parse_url($LD['totalURL']);
6148  if ($urlParts['host'] == '') {
6149  $LD['totalURL'] = $absoluteUrlScheme . '://' . $targetDomain . ($LD['totalURL'][0] == '/' ? '' : '/') . $LD['totalURL'];
6150  }
6151  }
6152  $this->lastTypoLinkUrl = $this->URLqMark($LD['totalURL'], '') . $sectionMark;
6153  }
6154  $this->lastTypoLinkTarget = $LD['target'];
6155  $targetPart = $LD['target'] ? ' target="' . htmlspecialchars($LD['target']) . '"' : '';
6156  // If sectionMark is set, there is no baseURL AND the current page is the page the link is to, check if there are any additional parameters or addQueryString parameters and if not, drop the url.
6157  if ($sectionMark && !$GLOBALS['TSFE']->config['config']['baseURL'] && $page['uid'] == $GLOBALS['TSFE']->id && !trim($addQueryParams) && !($conf['addQueryString'] && $conf['addQueryString.'])) {
6158  list(, $URLparams) = explode('?', $this->lastTypoLinkUrl);
6159  list($URLparams) = explode('#', $URLparams);
6160  parse_str($URLparams . $LD['orig_type'], $URLparamsArray);
6161  // Type nums must match as well as page ids
6162  if ((int)$URLparamsArray['type'] == $GLOBALS['TSFE']->type) {
6163  unset($URLparamsArray['id']);
6164  unset($URLparamsArray['type']);
6165  // If there are no parameters left.... set the new url.
6166  if (!count($URLparamsArray)) {
6167  $this->lastTypoLinkUrl = $sectionMark;
6168  }
6169  }
6170  }
6171  // If link is to a access restricted page which should be redirected, then find new URL:
6172  if (empty($conf['linkAccessRestrictedPages']) && $GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages'] && $GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages'] !== 'NONE' && !$GLOBALS['TSFE']->checkPageGroupAccess($page)) {
6173  $thePage = $GLOBALS['TSFE']->sys_page->getPage($GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages']);
6174  $addParams = str_replace(
6175  array(
6176  '###RETURN_URL###',
6177  '###PAGE_ID###'
6178  ),
6179  array(
6180  rawurlencode($this->lastTypoLinkUrl),
6181  $page['uid']
6182  ),
6183  $GLOBALS['TSFE']->config['config']['typolinkLinkAccessRestrictedPages_addParams']
6184  );
6185  $this->lastTypoLinkUrl = $this->getTypoLink_URL($thePage['uid'] . ($theTypeP ? ',' . $theTypeP : ''), $addParams, $target);
6186  $this->lastTypoLinkUrl = $this->forceAbsoluteUrl($this->lastTypoLinkUrl, $conf);
6187  $this->lastTypoLinkLD['totalUrl'] = $this->lastTypoLinkUrl;
6188  $LD = $this->lastTypoLinkLD;
6189  }
6190  // Rendering the tag.
6191  $finalTagParts['url'] = $this->lastTypoLinkUrl;
6192  $finalTagParts['targetParams'] = $targetPart;
6193  $finalTagParts['TYPE'] = 'page';
6194  } else {
6195  $GLOBALS['TT']->setTSlogMessage('typolink(): Page id \'' . $link_param . '\' was not found, so \'' . $linktxt . '\' was not linked.', 1);
6196  return $linktxt;
6197  }
6198  }
6199  }
6200  $this->lastTypoLinkLD = $LD;
6201  if ($forceTitle) {
6202  $title = $forceTitle;
6203  }
6204  if ($JSwindowParams) {
6205  // Create TARGET-attribute only if the right doctype is used
6206  if (!GeneralUtility::inList('xhtml_strict,xhtml_11,xhtml_2', $GLOBALS['TSFE']->xhtmlDoctype)) {
6207  $target = ' target="FEopenLink"';
6208  } else {
6209  $target = '';
6210  }
6211  $onClick = 'vHWin=window.open(' . GeneralUtility::quoteJSvalue($GLOBALS['TSFE']->baseUrlWrap($finalTagParts['url']), TRUE) . ',\'FEopenLink\',' . GeneralUtility::quoteJSvalue($JSwindowParams) . ');vHWin.focus();return false;';
6212  $res = '<a href="' . htmlspecialchars($finalTagParts['url']) . '"' . $target . ' onclick="' . htmlspecialchars($onClick) . '"' . ($title ? ' title="' . htmlspecialchars($title) . '"' : '') . ($linkClass ? ' class="' . htmlspecialchars($linkClass) . '"' : '') . $finalTagParts['aTagParams'] . '>';
6213  } else {
6214  if ($GLOBALS['TSFE']->spamProtectEmailAddresses === 'ascii' && $finalTagParts['TYPE'] === 'mailto') {
6215  $res = '<a href="' . $finalTagParts['url'] . '"' . ($title ? ' title="' . htmlspecialchars($title) . '"' : '') . $finalTagParts['targetParams'] . ($linkClass ? ' class="' . htmlspecialchars($linkClass) . '"' : '') . $finalTagParts['aTagParams'] . '>';
6216  } else {
6217  $res = '<a href="' . htmlspecialchars($finalTagParts['url']) . '"' . ($title ? ' title="' . $title . '"' : '') . $finalTagParts['targetParams'] . ($linkClass ? ' class="' . htmlspecialchars($linkClass) . '"' : '') . $finalTagParts['aTagParams'] . '>';
6218  }
6219  }
6220  // Call user function:
6221  if ($conf['userFunc']) {
6222  $finalTagParts['TAG'] = $res;
6223  $res = $this->callUserFunction($conf['userFunc'], $conf['userFunc.'], $finalTagParts);
6224  }
6225  // Hook: Call post processing function for link rendering:
6226  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'])) {
6227  $_params = array(
6228  'conf' => &$conf,
6229  'linktxt' => &$linktxt,
6230  'finalTag' => &$res,
6231  'finalTagParts' => &$finalTagParts
6232  );
6233  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typoLink_PostProc'] as $_funcRef) {
6234  GeneralUtility::callUserFunction($_funcRef, $_params, $this);
6235  }
6236  }
6237  // If flag "returnLastTypoLinkUrl" set, then just return the latest URL made:
6238  if ($conf['returnLast']) {
6239  switch ($conf['returnLast']) {
6240  case 'url':
6241  return $this->lastTypoLinkUrl;
6242  break;
6243  case 'target':
6245  break;
6246  }
6247  }
6248  $wrap = isset($conf['wrap.']) ? $this->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
6249  if ($conf['ATagBeforeWrap']) {
6250  return $res . $this->wrap($linktxt, $wrap) . '</a>';
6251  } else {
6252  return $this->wrap($res . $linktxt . '</a>', $wrap);
6253  }
6254  } else {
6255  return $linktxt;
6256  }
6257  }
6258 
6266  protected function forceAbsoluteUrl($url, array $configuration) {
6267  if (!empty($url) && isset($configuration['forceAbsoluteUrl']) && $configuration['forceAbsoluteUrl']) {
6268  if (preg_match('#^(?:([a-z]+)(://)([^/]*)/?)?(.*)$#', $url, $matches)) {
6269  $urlParts = array(
6270  'scheme' => $matches[1],
6271  'delimiter' => '://',
6272  'host' => $matches[3],
6273  'path' => $matches[4]
6274  );
6275  $isUrlModified = FALSE;
6276  // Set scheme and host if not yet part of the URL:
6277  if (empty($urlParts['host'])) {
6278  $urlParts['scheme'] = 'http';
6279  $urlParts['host'] = $this->getEnvironmentVariable('HTTP_HOST');
6280  $urlParts['path'] = '/' . ltrim($urlParts['path'], '/');
6281  // absRefPrefix has been prepended to $url beforehand
6282  // so we only modify the path if no absRefPrefix has been set
6283  // otherwise we would destroy the path
6284  if ($GLOBALS['TSFE']->absRefPrefix === '') {
6285  $urlParts['path'] = $this->getEnvironmentVariable('TYPO3_SITE_PATH') . ltrim($urlParts['path'], '/');
6286  }
6287  $isUrlModified = TRUE;
6288  }
6289  // Override scheme:
6290  $forceAbsoluteUrl = &$configuration['forceAbsoluteUrl.']['scheme'];
6291  if (!empty($forceAbsoluteUrl) && $urlParts['scheme'] !== $forceAbsoluteUrl) {
6292  $urlParts['scheme'] = $forceAbsoluteUrl;
6293  $isUrlModified = TRUE;
6294  }
6295  // Recreate the absolute URL:
6296  if ($isUrlModified) {
6297  $url = implode('', $urlParts);
6298  }
6299  }
6300  }
6301  return $url;
6302  }
6303 
6312  public function typoLink_URL($conf) {
6313  $this->typolink('|', $conf);
6314  return $this->lastTypoLinkUrl;
6315  }
6316 
6331  public function getTypoLink($label, $params, $urlParameters = array(), $target = '') {
6332  $conf = array();
6333  $conf['parameter'] = $params;
6334  if ($target) {
6335  $conf['target'] = $target;
6336  $conf['extTarget'] = $target;
6337  $conf['fileTarget'] = $target;
6338  }
6339  if (is_array($urlParameters)) {
6340  if (count($urlParameters)) {
6341  $conf['additionalParams'] .= GeneralUtility::implodeArrayForUrl('', $urlParameters);
6342  }
6343  } else {
6344  $conf['additionalParams'] .= $urlParameters;
6345  }
6346  $out = $this->typolink($label, $conf);
6347  return $out;
6348  }
6349 
6357  public function getUrlToCurrentLocation($addQueryString = TRUE) {
6358  $conf = array();
6359  $conf['parameter'] = $GLOBALS['TSFE']->id . ',' . $GLOBALS['TSFE']->type;
6360  if ($addQueryString) {
6361  $conf['addQueryString'] = '1';
6362  $linkVars = implode(',', array_keys(GeneralUtility::explodeUrl2Array($GLOBALS['TSFE']->linkVars)));
6363  $conf['addQueryString.'] = array(
6364  'method' => 'GET',
6365  'exclude' => 'id,type,cHash' . ($linkVars ? ',' . $linkVars : '')
6366  );
6367  $conf['useCacheHash'] = GeneralUtility::_GET('cHash') ? '1' : '0';
6368  }
6369 
6370  return $this->typoLink_URL($conf);
6371  }
6372 
6383  public function getTypoLink_URL($params, $urlParameters = array(), $target = '') {
6384  $this->getTypoLink('', $params, $urlParameters, $target);
6385  return $this->lastTypoLinkUrl;
6386  }
6387 
6396  public function typolinkWrap($conf) {
6397  $k = md5(microtime());
6398  return explode($k, $this->typolink($k, $conf));
6399  }
6400 
6410  public function currentPageUrl($urlParameters = array(), $id = 0) {
6411  return $this->getTypoLink_URL($id ? $id : $GLOBALS['TSFE']->id, $urlParameters, $GLOBALS['TSFE']->sPre);
6412  }
6413 
6424  public function getClosestMPvalueForPage($pageId, $raw = FALSE) {
6425  // MountPoints:
6426  if ($GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids'] && $GLOBALS['TSFE']->MP) {
6427  // Same page as current.
6428  if ((int)$GLOBALS['TSFE']->id === (int)$pageId) {
6429  $MP = $GLOBALS['TSFE']->MP;
6430  } else {
6431  // ... otherwise find closest meeting point:
6432  // Gets rootline of linked-to page
6433  $tCR_rootline = $GLOBALS['TSFE']->sys_page->getRootLine($pageId, '', TRUE);
6434  $inverseTmplRootline = array_reverse($GLOBALS['TSFE']->tmpl->rootLine);
6435  $rl_mpArray = array();
6436  $startMPaccu = FALSE;
6437  // Traverse root line of link uid and inside of that the REAL root line of current position.
6438  foreach ($tCR_rootline as $tCR_data) {
6439  foreach ($inverseTmplRootline as $rlKey => $invTmplRLRec) {
6440  // Force accumulating when in overlay mode: Links to this page have to stay within the current branch
6441  if ($invTmplRLRec['_MOUNT_OL'] && $tCR_data['uid'] == $invTmplRLRec['uid']) {
6442  $startMPaccu = TRUE;
6443  }
6444  // Accumulate MP data:
6445  if ($startMPaccu && $invTmplRLRec['_MP_PARAM']) {
6446  $rl_mpArray[] = $invTmplRLRec['_MP_PARAM'];
6447  }
6448  // If two PIDs matches and this is NOT the site root, start accumulation of MP data (on the next level):
6449  // (The check for site root is done so links to branches outsite the site but sharing the site roots PID
6450  // is NOT detected as within the branch!)
6451  if ($tCR_data['pid'] == $invTmplRLRec['pid'] && count($inverseTmplRootline) != $rlKey + 1) {
6452  $startMPaccu = TRUE;
6453  }
6454  }
6455  if ($startMPaccu) {
6456  // Good enough...
6457  break;
6458  }
6459  }
6460  if (count($rl_mpArray)) {
6461  $MP = implode(',', array_reverse($rl_mpArray));
6462  }
6463  }
6464  }
6465  return !$raw ? ($MP ? '&MP=' . rawurlencode($MP) : '') : $MP;
6466  }
6467 
6479  public function getMailTo($mailAddress, $linktxt, $initP = '?') {
6480  if ((string)$linktxt === '') {
6481  $linktxt = htmlspecialchars($mailAddress);
6482  }
6483  $mailToUrl = 'mailto:' . $mailAddress;
6484  if (!$GLOBALS['TSFE']->config['config']['jumpurl_enable'] || $GLOBALS['TSFE']->config['config']['jumpurl_mailto_disable']) {
6485  if ($GLOBALS['TSFE']->spamProtectEmailAddresses) {
6486  if ($GLOBALS['TSFE']->spamProtectEmailAddresses === 'ascii') {
6487  $mailToUrl = $GLOBALS['TSFE']->encryptEmail($mailToUrl);
6488  } else {
6489  $mailToUrl = 'javascript:linkTo_UnCryptMailto(\'' . $GLOBALS['TSFE']->encryptEmail($mailToUrl) . '\');';
6490  }
6491  if ($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_atSubst']) {
6492  $atLabel = trim($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_atSubst']);
6493  }
6494  $spamProtectedMailAddress = str_replace('@', $atLabel ? $atLabel : '(at)', htmlspecialchars($mailAddress));
6495  if ($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_lastDotSubst']) {
6496  $lastDotLabel = trim($GLOBALS['TSFE']->config['config']['spamProtectEmailAddresses_lastDotSubst']);
6497  $lastDotLabel = $lastDotLabel ? $lastDotLabel : '(dot)';
6498  $spamProtectedMailAddress = preg_replace('/\\.([^\\.]+)$/', $lastDotLabel . '$1', $spamProtectedMailAddress);
6499  }
6500  $linktxt = str_ireplace($mailAddress, $spamProtectedMailAddress, $linktxt);
6501  }
6502  } else {
6503  $juHash = GeneralUtility::hmac($mailToUrl, 'jumpurl');
6504  $mailToUrl = $GLOBALS['TSFE']->absRefPrefix . $GLOBALS['TSFE']->config['mainScript'] . $initP . '&jumpurl=' . rawurlencode($mailToUrl) . '&juHash=' . $juHash . $GLOBALS['TSFE']->getMethodUrlIdToken;
6505  }
6506  return array(
6507  $mailToUrl,
6508  $linktxt
6509  );
6510  }
6511 
6521  public function getQueryArguments($conf, $overruleQueryArguments = array(), $forceOverruleArguments = FALSE) {
6522  switch ((string) $conf['method']) {
6523  case 'GET':
6524  $currentQueryArray = GeneralUtility::_GET();
6525  break;
6526  case 'POST':
6527  $currentQueryArray = GeneralUtility::_POST();
6528  break;
6529  case 'GET,POST':
6530  $currentQueryArray = GeneralUtility::_GET();
6531  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($currentQueryArray, GeneralUtility::_POST());
6532  break;
6533  case 'POST,GET':
6534  $currentQueryArray = GeneralUtility::_POST();
6535  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($currentQueryArray, GeneralUtility::_GET());
6536  break;
6537  default:
6538  $currentQueryArray = GeneralUtility::explodeUrl2Array($this->getEnvironmentVariable('QUERY_STRING'), TRUE);
6539  }
6540  if ($conf['exclude']) {
6541  $exclude = str_replace(',', '&', $conf['exclude']);
6542  $exclude = GeneralUtility::explodeUrl2Array($exclude, TRUE);
6543  // never repeat id
6544  $exclude['id'] = 0;
6545  $newQueryArray = GeneralUtility::arrayDiffAssocRecursive($currentQueryArray, $exclude);
6546  } else {
6547  $newQueryArray = $currentQueryArray;
6548  }
6549  if ($forceOverruleArguments) {
6550  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($newQueryArray, $overruleQueryArguments);
6551  } else {
6552  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($newQueryArray, $overruleQueryArguments, FALSE);
6553  }
6554  return GeneralUtility::implodeArrayForUrl('', $newQueryArray, '', FALSE, TRUE);
6555  }
6556 
6557  /***********************************************
6558  *
6559  * Miscellaneous functions, stand alone
6560  *
6561  ***********************************************/
6574  public function wrap($content, $wrap, $char = '|') {
6575  if ($wrap) {
6576  $wrapArr = explode($char, $wrap);
6577  return trim($wrapArr[0]) . $content . trim($wrapArr[1]);
6578  } else {
6579  return $content;
6580  }
6581  }
6582 
6594  public function noTrimWrap($content, $wrap, $char = '|') {
6595  if ($wrap) {
6596  $wrapArr = explode($char, $wrap);
6597  return $wrapArr[1] . $content . $wrapArr[2];
6598  } else {
6599  return $content;
6600  }
6601  }
6602 
6612  public function wrapSpace($content, $wrap, array $conf = NULL) {
6613  if (trim($wrap)) {
6614  $wrapArray = explode('|', $wrap);
6615  $wrapBefore = (int)$wrapArray[0];
6616  $wrapAfter = (int)$wrapArray[1];
6617  $useDivTag = isset($conf['useDiv']) && $conf['useDiv'];
6618  if ($wrapBefore) {
6619  if ($useDivTag) {
6620  $content = '<div class="content-spacer spacer-before" style="height:' . $wrapBefore . 'px;"></div>' . $content;
6621  } else {
6622  $content = '<img src="' . $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="1" height="' . $wrapBefore . '"' . $this->getBorderAttr(' border="0"') . ' class="spacer-gif" alt="" title="" /><br />' . $content;
6623  }
6624  }
6625  if ($wrapAfter) {
6626  if ($useDivTag) {
6627  $content .= '<div class="content-spacer spacer-after" style="height:' . $wrapAfter . 'px;"></div>';
6628  } else {
6629  $content .= '<img src="' . $GLOBALS['TSFE']->absRefPrefix . 'clear.gif" width="1" height="' . $wrapAfter . '"' . $this->getBorderAttr(' border="0"') . ' class="spacer-gif" alt="" title="" /><br />';
6630  }
6631  }
6632  }
6633  return $content;
6634  }
6635 
6647  public function callUserFunction($funcName, $conf, $content) {
6648  // Split parts
6649  $parts = explode('->', $funcName);
6650  if (count($parts) == 2) {
6651  // Class
6652  // Check whether class is available and try to reload includeLibs if possible:
6653  if ($this->isClassAvailable($parts[0], $conf)) {
6654  $classObj = GeneralUtility::makeInstance($parts[0]);
6655  if (is_object($classObj) && method_exists($classObj, $parts[1])) {
6656  $classObj->cObj = $this;
6657  $content = call_user_func_array(array(
6658  $classObj,
6659  $parts[1]
6660  ), array(
6661  $content,
6662  $conf
6663  ));
6664  } else {
6665  $GLOBALS['TT']->setTSlogMessage('Method "' . $parts[1] . '" did not exist in class "' . $parts[0] . '"', 3);
6666  }
6667  } else {
6668  $GLOBALS['TT']->setTSlogMessage('Class "' . $parts[0] . '" did not exist', 3);
6669  }
6670  } else {
6671  // Function
6672  if (function_exists($funcName)) {
6673  $content = call_user_func($funcName, $content, $conf);
6674  } else {
6675  $GLOBALS['TT']->setTSlogMessage('Function "' . $funcName . '" did not exist', 3);
6676  }
6677  }
6678  return $content;
6679  }
6680 
6689  public function processParams($params) {
6690  $paramArr = array();
6691  $lines = GeneralUtility::trimExplode(LF, $params, TRUE);
6692  foreach ($lines as $val) {
6693  $pair = explode('=', $val, 2);
6694  $pair[0] = trim($pair[0]);
6695  if (!GeneralUtility::inList('#,/', $pair[0][0])) {
6696  $paramArr[$pair[0]] = trim($pair[1]);
6697  }
6698  }
6699  return $paramArr;
6700  }
6701 
6709  public function keywords($content) {
6710  $listArr = preg_split('/[,;' . LF . ']/', $content);
6711  foreach ($listArr as $k => $v) {
6712  $listArr[$k] = trim($v);
6713  }
6714  return implode(',', $listArr);
6715  }
6716 
6726  public function caseshift($theValue, $case) {
6727  $case = strtolower($case);
6728  switch ($case) {
6729  case 'upper':
6730  $theValue = $GLOBALS['TSFE']->csConvObj->conv_case($GLOBALS['TSFE']->renderCharset, $theValue, 'toUpper');
6731  break;
6732  case 'lower':
6733  $theValue = $GLOBALS['TSFE']->csConvObj->conv_case($GLOBALS['TSFE']->renderCharset, $theValue, 'toLower');
6734  break;
6735  case 'capitalize':
6736  $theValue = ucwords($theValue);
6737  break;
6738  case 'ucfirst':
6739  $theValue = $GLOBALS['TSFE']->csConvObj->convCaseFirst($GLOBALS['TSFE']->renderCharset, $theValue, 'toUpper');
6740  break;
6741  case 'lcfirst':
6742  $theValue = $GLOBALS['TSFE']->csConvObj->convCaseFirst($GLOBALS['TSFE']->renderCharset, $theValue, 'toLower');
6743  break;
6744  }
6745  return $theValue;
6746  }
6747 
6757  public function HTMLcaseshift($theValue, $case) {
6758  $inside = 0;
6759  $newVal = '';
6760  $pointer = 0;
6761  $totalLen = strlen($theValue);
6762  do {
6763  if (!$inside) {
6764  $len = strcspn(substr($theValue, $pointer), '<');
6765  $newVal .= $this->caseshift(substr($theValue, $pointer, $len), $case);
6766  $inside = 1;
6767  } else {
6768  $len = strcspn(substr($theValue, $pointer), '>') + 1;
6769  $newVal .= substr($theValue, $pointer, $len);
6770  $inside = 0;
6771  }
6772  $pointer += $len;
6773  } while ($pointer < $totalLen);
6774  return $newVal;
6775  }
6776 
6785  public function calcAge($seconds, $labels) {
6786  if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($labels)) {
6787  $labels = ' min| hrs| days| yrs| min| hour| day| year';
6788  } else {
6789  $labels = str_replace('"', '', $labels);
6790  }
6791  $labelArr = explode('|', $labels);
6792  if (count($labelArr) == 4) {
6793  $labelArr = array_merge($labelArr, $labelArr);
6794  }
6795  $absSeconds = abs($seconds);
6796  $sign = $seconds > 0 ? 1 : -1;
6797  if ($absSeconds < 3600) {
6798  $val = round($absSeconds / 60);
6799  $seconds = $sign * $val . ($val == 1 ? $labelArr[4] : $labelArr[0]);
6800  } elseif ($absSeconds < 24 * 3600) {
6801  $val = round($absSeconds / 3600);
6802  $seconds = $sign * $val . ($val == 1 ? $labelArr[5] : $labelArr[1]);
6803  } elseif ($absSeconds < 365 * 24 * 3600) {
6804  $val = round($absSeconds / (24 * 3600));
6805  $seconds = $sign * $val . ($val == 1 ? $labelArr[6] : $labelArr[2]);
6806  } else {
6807  $val = round($absSeconds / (365 * 24 * 3600));
6808  $seconds = $sign * $val . ($val == 1 ? $labelArr[7] : $labelArr[3]);
6809  }
6810  return $seconds;
6811  }
6812 
6824  public function sendNotifyEmail($message, $recipients, $cc, $senderAddress, $senderName = '', $replyTo = '') {
6825  $result = FALSE;
6827  $mail = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
6828  $senderName = trim($senderName);
6829  $senderAddress = trim($senderAddress);
6830  if ($senderName !== '' && $senderAddress !== '') {
6831  $sender = array($senderAddress => $senderName);
6832  } elseif ($senderAddress !== '') {
6833  $sender = array($senderAddress);
6834  } else {
6835  $sender = \TYPO3\CMS\Core\Utility\MailUtility::getSystemFrom();
6836  }
6837  $mail->setFrom($sender);
6838  $parsedReplyTo = \TYPO3\CMS\Core\Utility\MailUtility::parseAddresses($replyTo);
6839  if (count($parsedReplyTo) > 0) {
6840  $mail->setReplyTo($parsedReplyTo);
6841  }
6842  $message = trim($message);
6843  if ($message !== '') {
6844  // First line is subject
6845  $messageParts = explode(LF, $message, 2);
6846  $subject = trim($messageParts[0]);
6847  $plainMessage = trim($messageParts[1]);
6848  $parsedRecipients = \TYPO3\CMS\Core\Utility\MailUtility::parseAddresses($recipients);
6849  if (count($parsedRecipients) > 0) {
6850  $mail->setTo($parsedRecipients)
6851  ->setSubject($subject)
6852  ->setBody($plainMessage);
6853  $mail->send();
6854  }
6855  $parsedCc = \TYPO3\CMS\Core\Utility\MailUtility::parseAddresses($cc);
6856  if (count($parsedCc) > 0) {
6858  $mail = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
6859  if (count($parsedReplyTo) > 0) {
6860  $mail->setReplyTo($parsedReplyTo);
6861  }
6862  $mail->setFrom($sender)
6863  ->setTo($parsedCc)
6864  ->setSubject($subject)
6865  ->setBody($plainMessage);
6866  $mail->send();
6867  }
6868  $result = TRUE;
6869  }
6870  return $result;
6871  }
6872 
6881  public function URLqMark($url, $params) {
6882  if ($params && !strstr($url, '?')) {
6883  return $url . '?' . $params;
6884  } else {
6885  return $url . $params;
6886  }
6887  }
6888 
6898  public function clearTSProperties($TSArr, $propList) {
6899  $list = explode(',', $propList);
6900  foreach ($list as $prop) {
6901  $prop = trim($prop);
6902  unset($TSArr[$prop]);
6903  unset($TSArr[$prop . '.']);
6904  }
6905  return $TSArr;
6906  }
6907 
6918  public function mergeTSRef($confArr, $prop) {
6919  if ($confArr[$prop][0] === '<') {
6920  $key = trim(substr($confArr[$prop], 1));
6921  $cF = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\Parser\\TypoScriptParser');
6922  // $name and $conf is loaded with the referenced values.
6923  $old_conf = $confArr[$prop . '.'];
6924  list($name, $conf) = $cF->getVal($key, $GLOBALS['TSFE']->tmpl->setup);
6925  if (is_array($old_conf) && count($old_conf)) {
6926  $conf = is_array($conf) ? array_replace_recursive($conf, $old_conf) : $old_conf;
6927  }
6928  $confArr[$prop . '.'] = $conf;
6929  }
6930  return $confArr;
6931  }
6932 
6943  public function joinTSarrays($conf, $old_conf) {
6944  GeneralUtility::logDeprecatedFunction();
6945  return array_replace_recursive($conf, $old_conf);
6946  }
6947 
6958  public function gifBuilderTextBox($gifbuilderConf, $conf, $text) {
6959  $chars = (int)$conf['chars'] ?: 20;
6960  $lineDist = (int)$conf['lineDist'] ?: 20;
6961  $Valign = strtolower(trim($conf['Valign']));
6962  $tmplObjNumber = (int)$conf['tmplObjNumber'];
6963  $maxLines = (int)$conf['maxLines'];
6964  if ($tmplObjNumber && $gifbuilderConf[$tmplObjNumber] == 'TEXT') {
6965  $textArr = $this->linebreaks($text, $chars, $maxLines);
6966  $angle = (int)$gifbuilderConf[$tmplObjNumber . '.']['angle'];
6967  foreach ($textArr as $c => $textChunk) {
6968  $index = $tmplObjNumber + 1 + $c * 2;
6969  // Workarea
6970  $gifbuilderConf = $this->clearTSProperties($gifbuilderConf, $index);
6971  $rad_angle = 2 * pi() / 360 * $angle;
6972  $x_d = sin($rad_angle) * $lineDist;
6973  $y_d = cos($rad_angle) * $lineDist;
6974  $diff_x_d = 0;
6975  $diff_y_d = 0;
6976  if ($Valign == 'center') {
6977  $diff_x_d = $x_d * count($textArr);
6978  $diff_x_d = $diff_x_d / 2;
6979  $diff_y_d = $y_d * count($textArr);
6980  $diff_y_d = $diff_y_d / 2;
6981  }
6982  $x_d = round($x_d * $c - $diff_x_d);
6983  $y_d = round($y_d * $c - $diff_y_d);
6984  $gifbuilderConf[$index] = 'WORKAREA';
6985  $gifbuilderConf[$index . '.']['set'] = $x_d . ',' . $y_d;
6986  // Text
6987  $index++;
6988  $gifbuilderConf = $this->clearTSProperties($gifbuilderConf, $index);
6989  $gifbuilderConf[$index] = 'TEXT';
6990  $gifbuilderConf[$index . '.'] = $this->clearTSProperties($gifbuilderConf[$tmplObjNumber . '.'], 'text');
6991  $gifbuilderConf[$index . '.']['text'] = $textChunk;
6992  }
6993  $gifbuilderConf = $this->clearTSProperties($gifbuilderConf, $tmplObjNumber);
6994  }
6995  return $gifbuilderConf;
6996  }
6997 
7009  public function linebreaks($string, $chars, $maxLines = 0) {
7010  $lines = explode(LF, $string);
7011  $lineArr = array();
7012  $c = 0;
7013  foreach ($lines as $paragraph) {
7014  $words = explode(' ', $paragraph);
7015  foreach ($words as $word) {
7016  if (strlen($lineArr[$c] . $word) > $chars) {
7017  $c++;
7018  }
7019  if (!$maxLines || $c < $maxLines) {
7020  $lineArr[$c] .= $word . ' ';
7021  }
7022  }
7023  $c++;
7024  }
7025  return $lineArr;
7026  }
7027 
7041  public function getUpdateJS($dataArray, $formName, $arrPrefix, $fieldList) {
7042  $JSPart = '';
7043  $updateValues = GeneralUtility::trimExplode(',', $fieldList);
7044  foreach ($updateValues as $fKey) {
7045  $value = $dataArray[$fKey];
7046  if (is_array($value)) {
7047  foreach ($value as $Nvalue) {
7048  $JSPart .= '
7049  updateForm(\'' . $formName . '\',\'' . $arrPrefix . '[' . $fKey . '][]\',' . GeneralUtility::quoteJSvalue($Nvalue, TRUE) . ');';
7050  }
7051  } else {
7052  $JSPart .= '
7053  updateForm(\'' . $formName . '\',\'' . $arrPrefix . '[' . $fKey . ']\',' . GeneralUtility::quoteJSvalue($value, TRUE) . ');';
7054  }
7055  }
7056  $JSPart = '<script type="text/javascript">
7057  /*<![CDATA[*/ ' . $JSPart . '
7058  /*]]>*/
7059 </script>
7060 ';
7061  $GLOBALS['TSFE']->additionalHeaderData['JSincludeFormupdate'] = '<script type="text/javascript" src="' . GeneralUtility::createVersionNumberedFilename(($GLOBALS['TSFE']->absRefPrefix . 'typo3/js/jsfunc.updateform.js')) . '"></script>';
7062  return $JSPart;
7063  }
7064 
7071  public function includeLibs(array $config) {
7072  $librariesIncluded = FALSE;
7073  if (isset($config['includeLibs']) && $config['includeLibs']) {
7074  $libraries = GeneralUtility::trimExplode(',', $config['includeLibs'], TRUE);
7075  $GLOBALS['TSFE']->includeLibraries($libraries);
7076  $librariesIncluded = TRUE;
7077  }
7078  return $librariesIncluded;
7079  }
7080 
7100  protected function isClassAvailable($className, array $config = NULL) {
7101  if (class_exists($className)) {
7102  return TRUE;
7103  } elseif ($config) {
7104  $pluginConfiguration = &$GLOBALS['TSFE']->tmpl->setup['plugin.'][$className . '.'];
7105  if (isset($pluginConfiguration['includeLibs']) && $pluginConfiguration['includeLibs']) {
7106  $config['includeLibs'] = $pluginConfiguration['includeLibs'];
7107  return $this->includeLibs($config);
7108  }
7109  }
7110  return FALSE;
7111  }
7112 
7113  /***********************************************
7114  *
7115  * Database functions, making of queries
7116  *
7117  ***********************************************/
7129  public function DBgetDelete($table, $uid, $doExec = FALSE) {
7130  if ((int)$uid) {
7131  $uid = (int)$uid;
7132  if ($GLOBALS['TCA'][$table]['ctrl']['delete']) {
7133  $updateFields = array();
7134  $updateFields[$GLOBALS['TCA'][$table]['ctrl']['delete']] = 1;
7135  if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
7136  $updateFields[$GLOBALS['TCA'][$table]['ctrl']['tstamp']] = $GLOBALS['EXEC_TIME'];
7137  }
7138 
7139  if ($doExec) {
7140  return $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . $uid, $updateFields);
7141  } else {
7142  return $GLOBALS['TYPO3_DB']->UPDATEquery($table, 'uid=' . $uid, $updateFields);
7143  }
7144  } else {
7145  if ($doExec) {
7146  return $GLOBALS['TYPO3_DB']->exec_DELETEquery($table, 'uid=' . $uid);
7147  } else {
7148  return $GLOBALS['TYPO3_DB']->DELETEquery($table, 'uid=' . $uid);
7149  }
7150  }
7151  }
7152  }
7153 
7169  public function DBgetUpdate($table, $uid, $dataArr, $fieldList, $doExec = FALSE) {
7170  // uid can never be set
7171  unset($dataArr['uid']);
7172  $uid = (int)$uid;
7173  if ($uid) {
7174  $fieldList = implode(',', GeneralUtility::trimExplode(',', $fieldList, TRUE));
7175  $updateFields = array();
7176  foreach ($dataArr as $f => $v) {
7177  if (GeneralUtility::inList($fieldList, $f)) {
7178  $updateFields[$f] = $v;
7179  }
7180  }
7181  if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
7182  $updateFields[$GLOBALS['TCA'][$table]['ctrl']['tstamp']] = $GLOBALS['EXEC_TIME'];
7183  }
7184  if (count($updateFields)) {
7185  if ($doExec) {
7186  return $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid=' . $uid, $updateFields);
7187  } else {
7188  return $GLOBALS['TYPO3_DB']->UPDATEquery($table, 'uid=' . $uid, $updateFields);
7189  }
7190  }
7191  }
7192  }
7193 
7209  public function DBgetInsert($table, $pid, $dataArr, $fieldList, $doExec = FALSE) {
7210  $extraList = 'pid';
7211  if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) {
7212  $field = $GLOBALS['TCA'][$table]['ctrl']['tstamp'];
7213  $dataArr[$field] = $GLOBALS['EXEC_TIME'];
7214  $extraList .= ',' . $field;
7215  }
7216  if ($GLOBALS['TCA'][$table]['ctrl']['crdate']) {
7217  $field = $GLOBALS['TCA'][$table]['ctrl']['crdate'];
7218  $dataArr[$field] = $GLOBALS['EXEC_TIME'];
7219  $extraList .= ',' . $field;
7220  }
7221  if ($GLOBALS['TCA'][$table]['ctrl']['cruser_id']) {
7222  $field = $GLOBALS['TCA'][$table]['ctrl']['cruser_id'];
7223  $dataArr[$field] = 0;
7224  $extraList .= ',' . $field;
7225  }
7226  if ($GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']) {
7227  $field = $GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id'];
7228  $dataArr[$field] = (int)$GLOBALS['TSFE']->fe_user->user['uid'];
7229  $extraList .= ',' . $field;
7230  }
7231  if ($GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']) {
7232  $field = $GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id'];
7233  list($dataArr[$field]) = explode(',', $GLOBALS['TSFE']->fe_user->user['usergroup']);
7234  $dataArr[$field] = (int)$dataArr[$field];
7235  $extraList .= ',' . $field;
7236  }
7237  // Uid can never be set
7238  unset($dataArr['uid']);
7239  if ($pid >= 0) {
7240  $dataArr['pid'] = $pid;
7241  }
7242  // Set pid < 0 and the dataarr-pid will be used!
7243  $fieldList = implode(',', GeneralUtility::trimExplode(',', $fieldList . ',' . $extraList, TRUE));
7244  $insertFields = array();
7245  foreach ($dataArr as $f => $v) {
7246  if (GeneralUtility::inList($fieldList, $f)) {
7247  $insertFields[$f] = $v;
7248  }
7249  }
7250  if ($doExec) {
7251  return $GLOBALS['TYPO3_DB']->exec_INSERTquery($table, $insertFields);
7252  } else {
7253  return $GLOBALS['TYPO3_DB']->INSERTquery($table, $insertFields);
7254  }
7255  }
7256 
7269  public function DBmayFEUserEdit($table, $row, $feUserRow, $allowedGroups = '', $feEditSelf = 0) {
7270  $groupList = $allowedGroups ? implode(',', array_intersect(GeneralUtility::trimExplode(',', $feUserRow['usergroup'], TRUE), GeneralUtility::trimExplode(',', $allowedGroups, TRUE))) : $feUserRow['usergroup'];
7271  $ok = 0;
7272  // Points to the field that allows further editing from frontend if not set. If set the record is locked.
7273  if (!$GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock'] || !$row[$GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock']]) {
7274  // Points to the field (integer) that holds the fe_users-id of the creator fe_user
7275  if ($GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']) {
7276  $rowFEUser = (int)$row[$GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']];
7277  if ($rowFEUser && $rowFEUser == $feUserRow['uid']) {
7278  $ok = 1;
7279  }
7280  }
7281  // If $feEditSelf is set, fe_users may always edit them selves...
7282  if ($feEditSelf && $table == 'fe_users' && (int)$feUserRow['uid'] === (int)$row['uid']) {
7283  $ok = 1;
7284  }
7285  // Points to the field (integer) that holds the fe_group-id of the creator fe_user's first group
7286  if ($GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']) {
7287  $rowFEUser = (int)$row[$GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']];
7288  if ($rowFEUser) {
7289  if (GeneralUtility::inList($groupList, $rowFEUser)) {
7290  $ok = 1;
7291  }
7292  }
7293  }
7294  }
7295  return $ok;
7296  }
7297 
7311  public function DBmayFEUserEditSelect($table, $feUserRow, $allowedGroups = '', $feEditSelf = 0) {
7312  // Returns where-definition that selects user-editable records.
7313  $groupList = $allowedGroups ? implode(',', array_intersect(GeneralUtility::trimExplode(',', $feUserRow['usergroup'], TRUE), GeneralUtility::trimExplode(',', $allowedGroups, TRUE))) : $feUserRow['usergroup'];
7314  $OR_arr = array();
7315  // Points to the field (integer) that holds the fe_users-id of the creator fe_user
7316  if ($GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id']) {
7317  $OR_arr[] = $GLOBALS['TCA'][$table]['ctrl']['fe_cruser_id'] . '=' . $feUserRow['uid'];
7318  }
7319  // Points to the field (integer) that holds the fe_group-id of the creator fe_user's first group
7320  if ($GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id']) {
7321  $values = GeneralUtility::intExplode(',', $groupList);
7322  foreach ($values as $theGroupUid) {
7323  if ($theGroupUid) {
7324  $OR_arr[] = $GLOBALS['TCA'][$table]['ctrl']['fe_crgroup_id'] . '=' . $theGroupUid;
7325  }
7326  }
7327  }
7328  // If $feEditSelf is set, fe_users may always edit them selves...
7329  if ($feEditSelf && $table == 'fe_users') {
7330  $OR_arr[] = 'uid=' . (int)$feUserRow['uid'];
7331  }
7332  $whereDef = ' AND 1=0';
7333  if (count($OR_arr)) {
7334  $whereDef = ' AND (' . implode(' OR ', $OR_arr) . ')';
7335  if ($GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock']) {
7336  $whereDef .= ' AND ' . $GLOBALS['TCA'][$table]['ctrl']['fe_admin_lock'] . '=0';
7337  }
7338  }
7339  return $whereDef;
7340  }
7341 
7357  public function enableFields($table, $show_hidden = FALSE, array $ignore_array = array()) {
7358  $show_hidden = $show_hidden ?: ($table === 'pages' ? $GLOBALS['TSFE']->showHiddenPage : $GLOBALS['TSFE']->showHiddenRecords);
7359  return $GLOBALS['TSFE']->sys_page->enableFields($table, $show_hidden, $ignore_array);
7360  }
7361 
7388  public function getTreeList($id, $depth, $begin = 0, $dontCheckEnableFields = FALSE, $addSelectFields = '', $moreWhereClauses = '', array $prevId_array = array(), $recursionLevel = 0) {
7389  $id = (int)$id;
7390  if (!$id) {
7391  return '';
7392  }
7393 
7394  // Init vars:
7395  $allFields = 'uid,hidden,starttime,endtime,fe_group,extendToSubpages,doktype,php_tree_stop,mount_pid,mount_pid_ol,t3ver_state' . $addSelectFields;
7396  $depth = (int)$depth;
7397  $begin = (int)$begin;
7398  $theList = array();
7399  $addId = 0;
7400  $requestHash = '';
7401 
7402  // First level, check id (second level, this is done BEFORE the recursive call)
7403  if (!$recursionLevel) {
7404  // Check tree list cache
7405  // First, create the hash for this request - not sure yet whether we need all these parameters though
7406  $parameters = array(
7407  $id,
7408  $depth,
7409  $begin,
7410  $dontCheckEnableFields,
7411  $addSelectFields,
7412  $moreWhereClauses,
7413  $prevId_array,
7414  $GLOBALS['TSFE']->gr_list
7415  );
7416  $requestHash = md5(serialize($parameters));
7417  $cacheEntry = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
7418  'treelist',
7419  'cache_treelist',
7420  'md5hash = \'' . $requestHash . '\' AND ( expires > ' . $GLOBALS['EXEC_TIME'] . ' OR expires = 0 )'
7421  );
7422  if (is_array($cacheEntry)) {
7423  // Cache hit
7424  return $cacheEntry['treelist'];
7425  }
7426  // If Id less than zero it means we should add the real id to list:
7427  if ($id < 0) {
7428  $addId = ($id = abs($id));
7429  }
7430  // Check start page:
7431  if ($GLOBALS['TSFE']->sys_page->getRawRecord('pages', $id, 'uid')) {
7432  // Find mount point if any:
7433  $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($id);
7434  if (is_array($mount_info)) {
7435  $id = $mount_info['mount_pid'];
7436  // In Overlay mode, use the mounted page uid as added ID!:
7437  if ($addId && $mount_info['overlay']) {
7438  $addId = $id;
7439  }
7440  }
7441  } else {
7442  // Return blank if the start page was NOT found at all!
7443  return '';
7444  }
7445  }
7446  // Add this ID to the array of IDs
7447  if ($begin <= 0) {
7448  $prevId_array[] = $id;
7449  }
7450  // Select sublevel:
7451  if ($depth > 0) {
7452  $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
7453  $allFields,
7454  'pages',
7455  'pid = ' . (int)$id . ' AND deleted = 0 ' . $moreWhereClauses,
7456  '',
7457  'sorting'
7458  );
7459  if (is_array($rows)) {
7460  foreach ($rows as $row) {
7461  $versionState = VersionState::cast($row['t3ver_state']);
7462  $GLOBALS['TSFE']->sys_page->versionOL('pages', $row);
7463  if ($row['doktype'] == \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_RECYCLER
7464  || $row['doktype'] == \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_BE_USER_SECTION
7465  || $versionState->indicatesPlaceholder()
7466  ) {
7467  // Doing this after the overlay to make sure changes
7468  // in the overlay are respected.
7469  // However, we do not process pages below of and
7470  // including of type recycler and BE user section
7471  continue;
7472  }
7473  // Find mount point if any:
7474  $next_id = $row['uid'];
7475  $mount_info = $GLOBALS['TSFE']->sys_page->getMountPointInfo($next_id, $row);
7476  // Overlay mode:
7477  if (is_array($mount_info) && $mount_info['overlay']) {
7478  $next_id = $mount_info['mount_pid'];
7479  $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
7480  $allFields,
7481  'pages',
7482  'uid = ' . (int)$next_id . ' AND deleted = 0 ' . $moreWhereClauses,
7483  '',
7484  'sorting'
7485  );
7486  $GLOBALS['TSFE']->sys_page->versionOL('pages', $row);
7487  if ($row['doktype'] == \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_RECYCLER
7488  || $row['doktype'] == \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_BE_USER_SECTION
7489  || $versionState->indicatesPlaceholder()
7490  ) {
7491  // Doing this after the overlay to make sure
7492  // changes in the overlay are respected.
7493  // see above
7494  continue;
7495  }
7496  }
7497  // Add record:
7498  if ($dontCheckEnableFields || $GLOBALS['TSFE']->checkPagerecordForIncludeSection($row)) {
7499  // Add ID to list:
7500  if ($begin <= 0) {
7501  if ($dontCheckEnableFields || $GLOBALS['TSFE']->checkEnableFields($row)) {
7502  $theList[] = $next_id;
7503  }
7504  }
7505  // Next level:
7506  if ($depth > 1 && !$row['php_tree_stop']) {
7507  // Normal mode:
7508  if (is_array($mount_info) && !$mount_info['overlay']) {
7509  $next_id = $mount_info['mount_pid'];
7510  }
7511  // Call recursively, if the id is not in prevID_array:
7512  if (!in_array($next_id, $prevId_array)) {
7513  $theList = array_merge(
7514  GeneralUtility::intExplode(
7515  ',',
7516  $this->getTreeList($next_id, $depth - 1, $begin - 1,
7517  $dontCheckEnableFields, $addSelectFields, $moreWhereClauses,
7518  $prevId_array, $recursionLevel + 1),
7519  TRUE
7520  ),
7521  $theList
7522  );
7523  }
7524  }
7525  }
7526  }
7527  }
7528  }
7529  // If first run, check if the ID should be returned:
7530  if (!$recursionLevel) {
7531  if ($addId) {
7532  if ($begin > 0) {
7533  $theList[] = 0;
7534  } else {
7535  $theList[] = $addId;
7536  }
7537  }
7538  $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_treelist', array(
7539  'md5hash' => $requestHash,
7540  'pid' => $id,
7541  'treelist' => implode(',', $theList),
7542  'tstamp' => $GLOBALS['EXEC_TIME']
7543  ));
7544  }
7545 
7546  return implode(',', $theList);
7547  }
7548 
7564  public function exec_mm_query($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '') {
7565  return $GLOBALS['TYPO3_DB']->exec_SELECTquery($select, $local_table . ',' . $mm_table . ($foreign_table ? ',' . $foreign_table : ''), $local_table . '.uid=' . $mm_table . '.uid_local' . ($foreign_table ? ' AND ' . $foreign_table . '.uid=' . $mm_table . '.uid_foreign' : '') . $whereClause, $groupBy, $orderBy, $limit);
7566  }
7567 
7584  public function exec_mm_query_uidList($select, $local_table_uidlist, $mm_table, $foreign_table = '', $whereClause = '', $groupBy = '', $orderBy = '', $limit = '') {
7585  return $GLOBALS['TYPO3_DB']->exec_SELECTquery($select, $mm_table . ($foreign_table ? ',' . $foreign_table : ''), $mm_table . '.uid_local IN (' . $local_table_uidlist . ')' . ($foreign_table ? ' AND ' . $foreign_table . '.uid=' . $mm_table . '.uid_foreign' : '') . $whereClause, $groupBy, $orderBy, $limit);
7586  }
7587 
7598  public function searchWhere($sw, $searchFieldList, $searchTable = '') {
7599  global $TYPO3_DB;
7600  $prefixTableName = $searchTable ? $searchTable . '.' : '';
7601  $where = '';
7602  if ($sw) {
7603  $searchFields = explode(',', $searchFieldList);
7604  $kw = preg_split('/[ ,]/', $sw);
7605  foreach ($kw as $val) {
7606  $val = trim($val);
7607  $where_p = array();
7608  if (strlen($val) >= 2) {
7609  $val = $TYPO3_DB->escapeStrForLike($TYPO3_DB->quoteStr($val, $searchTable), $searchTable);
7610  foreach ($searchFields as $field) {
7611  $where_p[] = $prefixTableName . $field . ' LIKE \'%' . $val . '%\'';
7612  }
7613  }
7614  if (count($where_p)) {
7615  $where .= ' AND (' . implode(' OR ', $where_p) . ')';
7616  }
7617  }
7618  }
7619  return $where;
7620  }
7621 
7632  public function exec_getQuery($table, $conf) {
7633  $queryParts = $this->getQuery($table, $conf, TRUE);
7634  return $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($queryParts);
7635  }
7636 
7649  public function getQuery($table, $conf, $returnQueryArray = FALSE) {
7650  // Resolve stdWrap in these properties first
7651  $properties = array(
7652  'pidInList',
7653  'uidInList',
7654  'languageField',
7655  'selectFields',
7656  'max',
7657  'begin',
7658  'groupBy',
7659  'orderBy',
7660  'join',
7661  'leftjoin',
7662  'rightjoin',
7663  'recursive',
7664  'where'
7665  );
7666  foreach ($properties as $property) {
7667  $conf[$property] = isset($conf[$property . '.']) ? trim($this->stdWrap($conf[$property], $conf[$property . '.'])) : trim($conf[$property]);
7668  if ($conf[$property] === '') {
7669  unset($conf[$property]);
7670  }
7671  if (isset($conf[$property . '.'])) {
7672  // stdWrapping already done, so remove the sub-array
7673  unset($conf[$property . '.']);
7674  }
7675  }
7676  // Handle PDO-style named parameter markers first
7677  $queryMarkers = $this->getQueryMarkers($table, $conf);
7678  // Replace the markers in the non-stdWrap properties
7679  foreach ($queryMarkers as $marker => $markerValue) {
7680  $properties = array(
7681  'uidInList',
7682  'selectFields',
7683  'where',
7684  'max',
7685  'begin',
7686  'groupBy',
7687  'orderBy',
7688  'join',
7689  'leftjoin',
7690  'rightjoin'
7691  );
7692  foreach ($properties as $property) {
7693  if ($conf[$property]) {
7694  $conf[$property] = str_replace('###' . $marker . '###', $markerValue, $conf[$property]);
7695  }
7696  }
7697  }
7698  // Construct WHERE clause:
7699  // Handle recursive function for the pidInList
7700  if (isset($conf['recursive'])) {
7701  $conf['recursive'] = (int)$conf['recursive'];
7702  if ($conf['recursive'] > 0) {
7703  $pidList = GeneralUtility::trimExplode(',', $conf['pidInList'], TRUE);
7704  array_walk($pidList, function (&$storagePid) {
7705  if ($storagePid === 'this') {
7706  $storagePid = $GLOBALS['TSFE']->id;
7707  }
7708  if ($storagePid > 0) {
7709  $storagePid = -$storagePid;
7710  }
7711  });
7712  $expandedPidList = array();
7713  foreach ($pidList as $value) {
7714  // Implementation of getTreeList allows to pass the id negative to include
7715  // it into the result otherwise only childpages are returned
7716  $expandedPidList = array_merge(
7717  GeneralUtility::intExplode(',', $this->getTreeList($value, $conf['recursive'])),
7718  $expandedPidList
7719  );
7720  }
7721  $conf['pidInList'] = implode(',', $expandedPidList);
7722  }
7723  }
7724  if ((string)$conf['pidInList'] === '') {
7725  $conf['pidInList'] = 'this';
7726  }
7727  $queryParts = $this->getWhere($table, $conf, TRUE);
7728  // Fields:
7729  if ($conf['selectFields']) {
7730  $queryParts['SELECT'] = $this->sanitizeSelectPart($conf['selectFields'], $table);
7731  } else {
7732  $queryParts['SELECT'] = '*';
7733  }
7734  // Setting LIMIT:
7735  if ($conf['max'] || $conf['begin']) {
7736  $error = 0;
7737  // Finding the total number of records, if used:
7738  if (strstr(strtolower($conf['begin'] . $conf['max']), 'total')) {
7739  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $table, $queryParts['WHERE'], $queryParts['GROUPBY']);
7740  if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
7741  $GLOBALS['TT']->setTSlogMessage($error);
7742  } else {
7743  $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
7744  $conf['max'] = str_ireplace('total', $row[0], $conf['max']);
7745  $conf['begin'] = str_ireplace('total', $row[0], $conf['begin']);
7746  }
7747  $GLOBALS['TYPO3_DB']->sql_free_result($res);
7748  }
7749  if (!$error) {
7750  $conf['begin'] = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange(ceil($this->calc($conf['begin'])), 0);
7751  $conf['max'] = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange(ceil($this->calc($conf['max'])), 0);
7752  if ($conf['begin'] && !$conf['max']) {
7753  $conf['max'] = 100000;
7754  }
7755  if ($conf['begin'] && $conf['max']) {
7756  $queryParts['LIMIT'] = $conf['begin'] . ',' . $conf['max'];
7757  } elseif (!$conf['begin'] && $conf['max']) {
7758  $queryParts['LIMIT'] = $conf['max'];
7759  }
7760  }
7761  }
7762  if (!$error) {
7763  // Setting up tablejoins:
7764  $joinPart = '';
7765  if ($conf['join']) {
7766  $joinPart = 'JOIN ' . $conf['join'];
7767  } elseif ($conf['leftjoin']) {
7768  $joinPart = 'LEFT OUTER JOIN ' . $conf['leftjoin'];
7769  } elseif ($conf['rightjoin']) {
7770  $joinPart = 'RIGHT OUTER JOIN ' . $conf['rightjoin'];
7771  }
7772  // Compile and return query:
7773  $queryParts['FROM'] = trim($table . ' ' . $joinPart);
7774  // Replace the markers in the queryParts to handle stdWrap
7775  // enabled properties
7776  foreach ($queryMarkers as $marker => $markerValue) {
7777  foreach ($queryParts as $queryPartKey => &$queryPartValue) {
7778  $queryPartValue = str_replace('###' . $marker . '###', $markerValue, $queryPartValue);
7779  }
7780  unset($queryPartValue);
7781  }
7782  $query = $GLOBALS['TYPO3_DB']->SELECTquery($queryParts['SELECT'], $queryParts['FROM'], $queryParts['WHERE'], $queryParts['GROUPBY'], $queryParts['ORDERBY'], $queryParts['LIMIT']);
7783  return $returnQueryArray ? $queryParts : $query;
7784  }
7785  }
7786 
7798  public function getWhere($table, $conf, $returnQueryArray = FALSE) {
7799  // Init:
7800  $query = '';
7801  $pid_uid_flag = 0;
7802  $enableFieldsIgnore = array();
7803  $queryParts = array(
7804  'SELECT' => '',
7805  'FROM' => '',
7806  'WHERE' => '',
7807  'GROUPBY' => '',
7808  'ORDERBY' => '',
7809  'LIMIT' => ''
7810  );
7811  $considerMovePlaceholders = (
7812  $GLOBALS['TSFE']->sys_page->versioningPreview && $table !== 'pages'
7813  && !empty($GLOBALS['TCA'][$table]['ctrl']['versioningWS'])
7814  && (int)$GLOBALS['TCA'][$table]['ctrl']['versioningWS'] >= 2
7815  );
7816  if (trim($conf['uidInList'])) {
7817  $listArr = GeneralUtility::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $conf['uidInList']));
7818  if (count($listArr) === 1) {
7819  $comparison = '=' . (int)$listArr[0];
7820  } else {
7821  $comparison = ' IN (' . implode(',', $GLOBALS['TYPO3_DB']->cleanIntArray($listArr)) . ')';
7822  }
7823  // If move placeholder shall be considered, select via t3ver_move_id
7824  if ($considerMovePlaceholders) {
7825  $movePlaceholderComparison = $table . '.t3ver_state=' . VersionState::cast(VersionState::MOVE_PLACEHOLDER) . ' AND ' . $table . '.t3ver_move_id' . $comparison;
7826  $query .= ' AND (' . $table . '.uid' . $comparison . ' OR ' . $movePlaceholderComparison .')';
7827  } else {
7828  $query .= ' AND ' . $table . '.uid' . $comparison;
7829  }
7830  $pid_uid_flag++;
7831  }
7832  // Static_* tables are allowed to be fetched from root page
7833  if (substr($table, 0, 7) == 'static_') {
7834  $pid_uid_flag++;
7835  }
7836  if (trim($conf['pidInList'])) {
7837  $listArr = GeneralUtility::intExplode(',', str_replace('this', $GLOBALS['TSFE']->contentPid, $conf['pidInList']));
7838  // Removes all pages which are not visible for the user!
7839  $listArr = $this->checkPidArray($listArr);
7840  if (GeneralUtility::inList($conf['pidInList'], 'root')) {
7841  $listArr[] = 0;
7842  }
7843  if (GeneralUtility::inList($conf['pidInList'], '-1')) {
7844  $listArr[] = -1;
7845  $enableFieldsIgnore['pid'] = TRUE;
7846  }
7847  if (count($listArr)) {
7848  $query .= ' AND ' . $table . '.pid IN (' . implode(',', array_map('intval', $listArr)) . ')';
7849  $pid_uid_flag++;
7850  } else {
7851  // If not uid and not pid then uid is set to 0 - which results in nothing!!
7852  $pid_uid_flag = 0;
7853  }
7854  }
7855  // If not uid and not pid then uid is set to 0 - which results in nothing!!
7856  if (!$pid_uid_flag) {
7857  $query .= ' AND ' . $table . '.uid=0';
7858  }
7859  $where = isset($conf['where.']) ? trim($this->stdWrap($conf['where'], $conf['where.'])) : trim($conf['where']);
7860  if ($where) {
7861  $query .= ' AND ' . $where;
7862  }
7863  if ($conf['languageField']) {
7864  // The sys_language record UID of the content of the page
7865  $sys_language_content = (int)$GLOBALS['TSFE']->sys_language_content;
7866 
7867  if ($GLOBALS['TSFE']->sys_language_contentOL
7868  && isset($GLOBALS['TCA'][$table])
7869  && !empty($GLOBALS['TCA'][$table]['ctrl']['languageField'])
7870  && !empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'])
7871  ) {
7872  // Sys language content is set to zero/-1 - and it is expected that whatever routine processes the output will
7873  // OVERLAY the records with localized versions!
7874  $languageQuery = $conf['languageField'] . ' IN (0,-1)';
7875  // Use this option to include records that don't have a default translation
7876  // (originalpointerfield is 0 and the language field contains the requested language)
7877  if (!empty($conf['includeRecordsWithoutDefaultTranslation'])) {
7878  $languageQuery .= ' OR (' . $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . ' = 0 AND ' .
7879  $conf['languageField'] . ' = ' . $sys_language_content . ')';
7880  }
7881  } else {
7882  $languageQuery = $conf['languageField'] . ' = ' . $sys_language_content;
7883  }
7884  $query .= ' AND (' . $languageQuery . ')';
7885  }
7886  $andWhere = isset($conf['andWhere.']) ? trim($this->stdWrap($conf['andWhere'], $conf['andWhere.'])) : trim($conf['andWhere']);
7887  if ($andWhere) {
7888  $query .= ' AND ' . $andWhere;
7889  }
7890  // Enablefields
7891  if ($table == 'pages') {
7892  $query .= ' ' . $GLOBALS['TSFE']->sys_page->where_hid_del . $GLOBALS['TSFE']->sys_page->where_groupAccess;
7893  } else {
7894  $query .= $this->enableFields($table, FALSE, $enableFieldsIgnore);
7895  }
7896  // MAKE WHERE:
7897  if ($query) {
7898  // Stripping of " AND"...
7899  $queryParts['WHERE'] = trim(substr($query, 4));
7900  $query = 'WHERE ' . $queryParts['WHERE'];
7901  }
7902  // GROUP BY
7903  if (trim($conf['groupBy'])) {
7904  $queryParts['GROUPBY'] = isset($conf['groupBy.']) ? trim($this->stdWrap($conf['groupBy'], $conf['groupBy.'])) : trim($conf['groupBy']);
7905  }
7906  // ORDER BY
7907  if (trim($conf['orderBy'])) {
7908  $queryParts['ORDERBY'] = isset($conf['orderBy.']) ? trim($this->stdWrap($conf['orderBy'], $conf['orderBy.'])) : trim($conf['orderBy']);
7909  $query .= ' ORDER BY ' . $queryParts['ORDERBY'];
7910  }
7911  // Return result:
7912  return $returnQueryArray ? $queryParts : $query;
7913  }
7914 
7927  protected function sanitizeSelectPart($selectPart, $table) {
7928  // Pattern matching parts
7929  $matchStart = '/(^\\s*|,\\s*|' . $table . '\\.)';
7930  $matchEnd = '(\\s*,|\\s*$)/';
7931  $necessaryFields = array('uid', 'pid');
7932  $wsFields = array('t3ver_state');
7933  if (isset($GLOBALS['TCA'][$table]) && !preg_match(($matchStart . '\\*' . $matchEnd), $selectPart) && !preg_match('/(count|max|min|avg|sum)\\([^\\)]+\\)/i', $selectPart)) {
7934  foreach ($necessaryFields as $field) {
7935  $match = $matchStart . $field . $matchEnd;
7936  if (!preg_match($match, $selectPart)) {
7937  $selectPart .= ', ' . $table . '.' . $field . ' as ' . $field;
7938  }
7939  }
7940  if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
7941  foreach ($wsFields as $field) {
7942  $match = $matchStart . $field . $matchEnd;
7943  if (!preg_match($match, $selectPart)) {
7944  $selectPart .= ', ' . $table . '.' . $field . ' as ' . $field;
7945  }
7946  }
7947  }
7948  }
7949  return $selectPart;
7950  }
7951 
7961  public function checkPidArray($listArr) {
7962  $outArr = array();
7963  if (is_array($listArr) && count($listArr)) {
7964  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'uid IN (' . implode(',', $listArr) . ')' . $this->enableFields('pages') . ' AND doktype NOT IN (' . $this->checkPid_badDoktypeList . ')');
7965  if ($error = $GLOBALS['TYPO3_DB']->sql_error()) {
7966  $GLOBALS['TT']->setTSlogMessage($error . ': ' . $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery, 3);
7967  } else {
7968  while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
7969  $outArr[] = $row['uid'];
7970  }
7971  }
7972  $GLOBALS['TYPO3_DB']->sql_free_result($res);
7973  }
7974  return $outArr;
7975  }
7976 
7986  public function checkPid($uid) {
7987  $uid = (int)$uid;
7988  if (!isset($this->checkPid_cache[$uid])) {
7989  $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', 'pages', 'uid=' . $uid . $this->enableFields('pages') . ' AND doktype NOT IN (' . $this->checkPid_badDoktypeList . ')');
7990  $this->checkPid_cache[$uid] = (bool) $count;
7991  }
7992  return $this->checkPid_cache[$uid];
7993  }
7994 
8006  public function getQueryMarkers($table, $conf) {
8007  // Parse markers and prepare their values
8008  $markerValues = array();
8009  if (is_array($conf['markers.'])) {
8010  foreach ($conf['markers.'] as $dottedMarker => $dummy) {
8011  $marker = rtrim($dottedMarker, '.');
8012  if ($dottedMarker == $marker . '.') {
8013  // Parse definition
8014  $tempValue = isset($conf['markers.'][$dottedMarker]) ? $this->stdWrap($conf['markers.'][$dottedMarker]['value'], $conf['markers.'][$dottedMarker]) : $conf['markers.'][$dottedMarker]['value'];
8015  // Quote/escape if needed
8016  if (is_numeric($tempValue)) {
8017  if ((int)$tempValue == $tempValue) {
8018  // Handle integer
8019  $markerValues[$marker] = (int)$tempValue;
8020  } else {
8021  // Handle float
8022  $markerValues[$marker] = floatval($tempValue);
8023  }
8024  } elseif (is_null($tempValue)) {
8025  // It represents NULL
8026  $markerValues[$marker] = 'NULL';
8027  } elseif ($conf['markers.'][$dottedMarker]['commaSeparatedList'] == 1) {
8028  // See if it is really a comma separated list of values
8029  $explodeValues = GeneralUtility::trimExplode(',', $tempValue);
8030  if (count($explodeValues) > 1) {
8031  // Handle each element of list separately
8032  $tempArray = array();
8033  foreach ($explodeValues as $listValue) {
8034  if (is_numeric($listValue)) {
8035  if ((int)$listValue == $listValue) {
8036  $tempArray[] = (int)$listValue;
8037  } else {
8038  $tempArray[] = floatval($listValue);
8039  }
8040  } else {
8041  // If quoted, remove quotes before
8042  // escaping.
8043  if (preg_match('/^\'([^\']*)\'$/', $listValue, $matches)) {
8044  $listValue = $matches[1];
8045  } elseif (preg_match('/^\\"([^\\"]*)\\"$/', $listValue, $matches)) {
8046  $listValue = $matches[1];
8047  }
8048  $tempArray[] = $GLOBALS['TYPO3_DB']->fullQuoteStr($listValue, $table);
8049  }
8050  }
8051  $markerValues[$marker] = implode(',', $tempArray);
8052  } else {
8053  // Handle remaining values as string
8054  $markerValues[$marker] = $GLOBALS['TYPO3_DB']->fullQuoteStr($tempValue, $table);
8055  }
8056  } else {
8057  // Handle remaining values as string
8058  $markerValues[$marker] = $GLOBALS['TYPO3_DB']->fullQuoteStr($tempValue, $table);
8059  }
8060  }
8061  }
8062  }
8063  return $markerValues;
8064  }
8065 
8066  /***********************************************
8067  *
8068  * Frontend editing functions
8069  *
8070  ***********************************************/
8083  public function editPanel($content, $conf, $currentRecord = '', $dataArr = array()) {
8084  if ($GLOBALS['TSFE']->beUserLogin && $GLOBALS['BE_USER']->frontendEdit instanceof \TYPO3\CMS\Core\FrontendEditing\FrontendEditingController) {
8085  if (!$currentRecord) {
8086  $currentRecord = $this->currentRecord;
8087  }
8088  if (!count($dataArr)) {
8089  $dataArr = $this->data;
8090  }
8091  // Delegate rendering of the edit panel to the frontend edit
8092  $content = $GLOBALS['BE_USER']->frontendEdit->displayEditPanel($content, $conf, $currentRecord, $dataArr);
8093  }
8094  return $content;
8095  }
8096 
8110  public function editIcons($content, $params, array $conf = array(), $currentRecord = '', $dataArr = array(), $addUrlParamStr = '') {
8111  if ($GLOBALS['TSFE']->beUserLogin && $GLOBALS['BE_USER']->frontendEdit instanceof \TYPO3\CMS\Core\FrontendEditing\FrontendEditingController) {
8112  if (!$currentRecord) {
8113  $currentRecord = $this->currentRecord;
8114  }
8115  if (!count($dataArr)) {
8116  $dataArr = $this->data;
8117  }
8118  // Delegate rendering of the edit panel to frontend edit class.
8119  $content = $GLOBALS['BE_USER']->frontendEdit->displayEditIcons($content, $params, $conf, $currentRecord, $dataArr, $addUrlParamStr);
8120  }
8121  return $content;
8122  }
8123 
8134  public function isDisabled($table, $row) {
8135  if ($GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'] && $row[$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled']] || $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['fe_group'] && $GLOBALS['TSFE']->simUserGroup && $row[$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['fe_group']] == $GLOBALS['TSFE']->simUserGroup || $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['starttime'] && $row[$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['starttime']] > $GLOBALS['EXEC_TIME'] || $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime'] && $row[$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime']] && $row[$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['endtime']] < $GLOBALS['EXEC_TIME']) {
8136  return TRUE;
8137  }
8138  }
8139 
8145  protected function getResourceFactory() {
8146  return \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance();
8147  }
8148 
8156  protected function getEnvironmentVariable($key) {
8157  return GeneralUtility::getIndpEnv($key);
8158  }
8159 }
rootLineValue($key, $field, $slideBack=0, $altRootLine='')
getTypoLink_URL($params, $urlParameters=array(), $target='')
editIcons($content, $params, array $conf=array(), $currentRecord='', $dataArr=array(), $addUrlParamStr='')
static implodeAttributes(array $arr, $xhtmlSafe=FALSE, $dontOmitBlankAttribs=FALSE)
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=TRUE, $includeEmptyValues=TRUE, $enableUnsetFeature=TRUE)
static uniqueList($in_list, $secondParameter=NULL)
$TYPO3_CONF_VARS['SYS']['contentTable']
editPanel($content, $conf, $currentRecord='', $dataArr=array())
static explodeUrl2Array($string, $multidim=FALSE)
substituteMarkerArray($content, array $markContentArray, $wrap='', $uppercase=FALSE, $deleteUnused=FALSE)
static isFirstPartOfStr($str, $partStr)
static intExplode($delimiter, $string, $removeEmptyValues=FALSE, $limit=0)
$uid
Definition: server.php:36
static getUserObj($classRef, $checkPrefix='', $silent=FALSE)
static hmac($input, $additionalSecret='')
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
static calculateWithParentheses($string)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
static unQuoteFilenames($parameters, $unQuote=FALSE)
static split_fileref($fileNameWithPath)
getFieldDefaultValue($noValueInsert, $fieldName, $defaultVal)
substituteMarkerArrayCached($content, array $markContentArray=NULL, array $subpartContentArray=NULL, array $wrappedSubpartContentArray=NULL)
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
static splitCalc($string, $operators)
static implodeArrayForUrl($name, array $theArray, $str='', $skipBlank=FALSE, $rawurlencodeParamName=FALSE)
static formatSize($sizeInBytes, $labels='')
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel=E_DEBUG)
substituteMarkerAndSubpartArrayRecursive($content, array $markersAndSubparts, $wrap='', $uppercase=FALSE, $deleteUnused=FALSE)
fillInMarkerArray(array $markContentArray, array $row, $fieldList='', $nl2br=TRUE, $prefix='FIELD_', $HSC=FALSE)
if(isset($ajaxID)) if(in_array( $ajaxID, $noUserAjaxIDs))
Re-apply pairs of single-quotes to the text.
Definition: ajax.php:40
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
static isLastPartOfString($haystack, $needle)
static revExplode($delimiter, $string, $count=0)
static xml2array($string, $NSprefix='', $reportDocTag=FALSE)
getTypoLink($label, $params, $urlParameters=array(), $target='')
static sortedKeyList($setupArr, $acceptOnlyProperties=FALSE)
substituteSubpart($content, $marker, $subpartContent, $recursive=1)