TYPO3 CMS  TYPO3_6-2
RteHtmlParser.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Html;
3 
20 
27 
28  // Static:
32  public $blockElementList = 'PRE,UL,OL,H1,H2,H3,H4,H5,H6,ADDRESS,DL,DD,HEADER,SECTION,FOOTER,NAV,ARTICLE,ASIDE';
33 
34  // List of tags for these elements
35  // Internal, static:
36  // Set this to the pid of the record manipulated by the class.
40  public $recPid = 0;
41 
42  // Element reference [table]:[field], eg. "tt_content:bodytext"
46  public $elRef = '';
47 
48  // Relative path
52  public $relPath = '';
53 
54  // Relative back-path
58  public $relBackPath = '';
59 
60  // Current Page TSConfig
61  public $tsConfig = array();
62 
63  // Set to the TSconfig options coming from Page TSconfig
67  public $procOptions = array();
68 
69  // Internal, dynamic
70  // Run-away brake for recursive calls.
75 
76  // Parameters from TCA types configuration related to the RTE
80  public $rte_p = '';
81 
82  // Data caching for processing function
86  public $getKeepTags_cache = array();
87 
88  // Storage of the allowed CSS class names in the RTE
92  public $allowedClasses = array();
93 
94  // Set to tags to preserve from Page TSconfig configuration
98  public $preserveTags = '';
99 
108  public function init($elRef = '', $recPid = 0) {
109  $this->recPid = $recPid;
110  $this->elRef = $elRef;
111  }
112 
121  public function setRelPath($path) {
122  $path = trim($path);
123  $path = preg_replace('/^\\//', '', $path);
124  $path = preg_replace('/\\/$/', '', $path);
125  if ($path) {
126  $this->relPath = $path;
127  $this->relBackPath = '';
128  $partsC = count(explode('/', $this->relPath));
129  for ($a = 0; $a < $partsC; $a++) {
130  $this->relBackPath .= '../';
131  }
132  $this->relPath .= '/';
133  }
134  }
135 
145  static public function evalWriteFile($pArr, $currentRecord) {
146  // Write file configuration:
147  if (is_array($pArr)) {
148  if ($GLOBALS['TYPO3_CONF_VARS']['BE']['staticFileEditPath'] && substr($GLOBALS['TYPO3_CONF_VARS']['BE']['staticFileEditPath'], -1) == '/' && @is_dir((PATH_site . $GLOBALS['TYPO3_CONF_VARS']['BE']['staticFileEditPath']))) {
149  $SW_p = $pArr['parameters'];
150  $SW_editFileField = trim($SW_p[0]);
151  $SW_editFile = $currentRecord[$SW_editFileField];
152  if ($SW_editFileField && $SW_editFile && GeneralUtility::validPathStr($SW_editFile)) {
153  $SW_relpath = $GLOBALS['TYPO3_CONF_VARS']['BE']['staticFileEditPath'] . $SW_editFile;
154  $SW_editFile = PATH_site . $SW_relpath;
155  if (@is_file($SW_editFile)) {
156  return array(
157  'editFile' => $SW_editFile,
158  'relEditFile' => $SW_relpath,
159  'contentField' => trim($SW_p[1]),
160  'markerField' => trim($SW_p[2]),
161  'loadFromFileField' => trim($SW_p[3]),
162  'statusField' => trim($SW_p[4])
163  );
164  } else {
165  return 'ERROR: Editfile \'' . $SW_relpath . '\' did not exist';
166  }
167  } else {
168  return 'ERROR: Edit file name could not be found or was bad.';
169  }
170  } else {
171  return 'ERROR: staticFileEditPath was not set, not set correctly or did not exist!';
172  }
173  }
174  }
175 
176  /**********************************************
177  *
178  * Main function
179  *
180  **********************************************/
192  public function RTE_transform($value, $specConf, $direction = 'rte', $thisConfig = array()) {
193  // Init:
194  $this->tsConfig = $thisConfig;
195  $this->procOptions = (array) $thisConfig['proc.'];
196  $this->preserveTags = strtoupper(implode(',', GeneralUtility::trimExplode(',', $this->procOptions['preserveTags'])));
197  // dynamic configuration of blockElementList
198  if ($this->procOptions['blockElementList']) {
199  $this->blockElementList = $this->procOptions['blockElementList'];
200  }
201  // Get parameters for rte_transformation:
202  $p = ($this->rte_p = BackendUtility::getSpecConfParametersFromArray($specConf['rte_transform']['parameters']));
203  // Setting modes:
204  if ((string)$this->procOptions['overruleMode'] !== '') {
205  $modes = array_unique(GeneralUtility::trimExplode(',', $this->procOptions['overruleMode']));
206  } else {
207  $modes = array_unique(GeneralUtility::trimExplode('-', $p['mode']));
208  }
209  $revmodes = array_flip($modes);
210  // Find special modes and extract them:
211  if (isset($revmodes['ts'])) {
212  $modes[$revmodes['ts']] = 'ts_transform,ts_preserve,ts_images,ts_links';
213  }
214  // Find special modes and extract them:
215  if (isset($revmodes['ts_css'])) {
216  $modes[$revmodes['ts_css']] = 'css_transform,ts_images,ts_links';
217  }
218  // Make list unique
219  $modes = array_unique(GeneralUtility::trimExplode(',', implode(',', $modes), TRUE));
220  // Reverse order if direction is "rte"
221  if ($direction == 'rte') {
222  $modes = array_reverse($modes);
223  }
224  // Getting additional HTML cleaner configuration. These are applied either before or after the main transformation is done and is thus totally independant processing options you can set up:
225  $entry_HTMLparser = $this->procOptions['entryHTMLparser_' . $direction] ? $this->HTMLparserConfig($this->procOptions['entryHTMLparser_' . $direction . '.']) : '';
226  $exit_HTMLparser = $this->procOptions['exitHTMLparser_' . $direction] ? $this->HTMLparserConfig($this->procOptions['exitHTMLparser_' . $direction . '.']) : '';
227  // Line breaks of content is unified into char-10 only (removing char 13)
228  if (!$this->procOptions['disableUnifyLineBreaks']) {
229  $value = str_replace(CRLF, LF, $value);
230  }
231  // In an entry-cleaner was configured, pass value through the HTMLcleaner with that:
232  if (is_array($entry_HTMLparser)) {
233  $value = $this->HTMLcleaner($value, $entry_HTMLparser[0], $entry_HTMLparser[1], $entry_HTMLparser[2], $entry_HTMLparser[3]);
234  }
235  // Traverse modes:
236  foreach ($modes as $cmd) {
237  // ->DB
238  if ($direction == 'db') {
239  // Checking for user defined transformation:
240  if ($_classRef = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['transformation'][$cmd]) {
241  $_procObj = GeneralUtility::getUserObj($_classRef);
242  $_procObj->pObj = $this;
243  $_procObj->transformationKey = $cmd;
244  $value = $_procObj->transform_db($value, $this);
245  } else {
246  // ... else use defaults:
247  switch ($cmd) {
248  case 'ts_images':
249  $value = $this->TS_images_db($value);
250  break;
251  case 'ts_reglinks':
252  $value = $this->TS_reglinks($value, 'db');
253  break;
254  case 'ts_links':
255  $value = $this->TS_links_db($value);
256  break;
257  case 'ts_preserve':
258  $value = $this->TS_preserve_db($value);
259  break;
260  case 'ts_transform':
261 
262  case 'css_transform':
263  $this->allowedClasses = GeneralUtility::trimExplode(',', $this->procOptions['allowedClasses'], TRUE);
264  // CR has a very disturbing effect, so just remove all CR and rely on LF
265  $value = str_replace(CR, '', $value);
266  // Transform empty paragraphs into spacing paragraphs
267  $value = str_replace('<p></p>', '<p>&nbsp;</p>', $value);
268  // Double any trailing spacing paragraph so that it does not get removed by divideIntoLines()
269  $value = preg_replace('/<p>&nbsp;<\/p>$/', '<p>&nbsp;</p>' . '<p>&nbsp;</p>', $value);
270  $value = $this->TS_transform_db($value, $cmd == 'css_transform');
271  break;
272  case 'ts_strip':
273  $value = $this->TS_strip_db($value);
274  break;
275  default:
276  // Do nothing
277  }
278  }
279  }
280  // ->RTE
281  if ($direction == 'rte') {
282  // Checking for user defined transformation:
283  if ($_classRef = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['transformation'][$cmd]) {
284  $_procObj = GeneralUtility::getUserObj($_classRef);
285  $_procObj->pObj = $this;
286  $value = $_procObj->transform_rte($value, $this);
287  } else {
288  // ... else use defaults:
289  switch ($cmd) {
290  case 'ts_images':
291  $value = $this->TS_images_rte($value);
292  break;
293  case 'ts_reglinks':
294  $value = $this->TS_reglinks($value, 'rte');
295  break;
296  case 'ts_links':
297  $value = $this->TS_links_rte($value);
298  break;
299  case 'ts_preserve':
300  $value = $this->TS_preserve_rte($value);
301  break;
302  case 'ts_transform':
303 
304  case 'css_transform':
305  // Has a very disturbing effect, so just remove all '13' - depend on '10'
306  $value = str_replace(CR, '', $value);
307  $value = $this->TS_transform_rte($value, $cmd == 'css_transform');
308  break;
309  default:
310  // Do nothing
311  }
312  }
313  }
314  }
315  // In an exit-cleaner was configured, pass value through the HTMLcleaner with that:
316  if (is_array($exit_HTMLparser)) {
317  $value = $this->HTMLcleaner($value, $exit_HTMLparser[0], $exit_HTMLparser[1], $exit_HTMLparser[2], $exit_HTMLparser[3]);
318  }
319  // Final clean up of linebreaks:
320  if (!$this->procOptions['disableUnifyLineBreaks']) {
321  // Make sure no \r\n sequences has entered in the meantime...
322  $value = str_replace(CRLF, LF, $value);
323  // ... and then change all \n into \r\n
324  $value = str_replace(LF, CRLF, $value);
325  }
326  // Return value:
327  return $value;
328  }
329 
330  /************************************
331  *
332  * Specific RTE TRANSFORMATION functions
333  *
334  *************************************/
347  public function TS_images_db($value) {
348  // Split content by <img> tags and traverse the resulting array for processing:
349  $imgSplit = $this->splitTags('img', $value);
350  if (count($imgSplit) > 1) {
351  $siteUrl = $this->siteUrl();
352  $sitePath = str_replace(GeneralUtility::getIndpEnv('TYPO3_REQUEST_HOST'), '', $siteUrl);
354  $resourceFactory = Resource\ResourceFactory::getInstance();
356  $magicImageService = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Service\\MagicImageService');
357  $magicImageService->setMagicImageMaximumDimensions($this->tsConfig);
358  foreach ($imgSplit as $k => $v) {
359  // Image found, do processing:
360  if ($k % 2) {
361  // Get attributes
362  $attribArray = $this->get_tag_attributes_classic($v, 1);
363  // It's always an absolute URL coming from the RTE into the Database.
364  $absoluteUrl = trim($attribArray['src']);
365  // Make path absolute if it is relative and we have a site path which is not '/'
366  $pI = pathinfo($absoluteUrl);
367  if ($sitePath && !$pI['scheme'] && GeneralUtility::isFirstPartOfStr($absoluteUrl, $sitePath)) {
368  // If site is in a subpath (eg. /~user_jim/) this path needs to be removed because it will be added with $siteUrl
369  $absoluteUrl = substr($absoluteUrl, strlen($sitePath));
370  $absoluteUrl = $siteUrl . $absoluteUrl;
371  }
372  // Image dimensions set in the img tag, if any
373  $imgTagDimensions = $this->getWHFromAttribs($attribArray);
374  if ($imgTagDimensions[0]) {
375  $attribArray['width'] = $imgTagDimensions[0];
376  }
377  if ($imgTagDimensions[1]) {
378  $attribArray['height'] = $imgTagDimensions[1];
379  }
380  $originalImageFile = NULL;
381  if ($attribArray['data-htmlarea-file-uid']) {
382  // An original image file uid is available
383  try {
385  $originalImageFile = $resourceFactory->getFileObject(intval($attribArray['data-htmlarea-file-uid']));
386  } catch (Resource\Exception\FileDoesNotExistException $fileDoesNotExistException) {
387  // Log the fact the file could not be retrieved.
388  $message = sprintf('Could not find file with uid "%s"', $attribArray['data-htmlarea-file-uid']);
389  $this->getLogger()->error($message);
390  }
391  }
392  if ($originalImageFile instanceof Resource\File) {
393  // Public url of local file is relative to the site url, absolute otherwise
394  if ($absoluteUrl == $originalImageFile->getPublicUrl() || $absoluteUrl == $siteUrl . $originalImageFile->getPublicUrl()) {
395  // This is a plain image, i.e. reference to the original image
396  if ($this->procOptions['plainImageMode']) {
397  // "plain image mode" is configured
398  // Find the dimensions of the original image
399  $imageInfo = array(
400  $originalImageFile->getProperty('width'),
401  $originalImageFile->getProperty('height')
402  );
403  if (!$imageInfo[0] || !$imageInfo[1]) {
404  $filePath = $originalImageFile->getForLocalProcessing(FALSE);
405  $imageInfo = @getimagesize($filePath);
406  }
407  $attribArray = $this->applyPlainImageModeSettings($imageInfo, $attribArray);
408  }
409  } else {
410  // Magic image case: get a processed file with the requested configuration
411  $imageConfiguration = array(
412  'width' => $imgTagDimensions[0],
413  'height' => $imgTagDimensions[1]
414  );
415  $magicImage = $magicImageService->createMagicImage($originalImageFile, $imageConfiguration);
416  $attribArray['width'] = $magicImage->getProperty('width');
417  $attribArray['height'] = $magicImage->getProperty('height');
418  $attribArray['src'] = $magicImage->getPublicUrl();
419  }
420  } elseif (!GeneralUtility::isFirstPartOfStr($absoluteUrl, $siteUrl) && !$this->procOptions['dontFetchExtPictures'] && TYPO3_MODE === 'BE') {
421  // External image from another URL: in that case, fetch image, unless the feature is disabled or we are not in backend mode
422  // Fetch the external image
423  $externalFile = $this->getUrl($absoluteUrl);
424  if ($externalFile) {
425  $pU = parse_url($absoluteUrl);
426  $pI = pathinfo($pU['path']);
427  if (GeneralUtility::inList('gif,png,jpeg,jpg', strtolower($pI['extension']))) {
428  $fileName = GeneralUtility::shortMD5($absoluteUrl) . '.' . $pI['extension'];
429  // We insert this image into the user default upload folder
430  $folder = $GLOBALS['BE_USER']->getDefaultUploadFolder();
431  $fileObject = $folder->createFile($fileName)->setContents($externalFile);
432  $imageConfiguration = array(
433  'width' => $attribArray['width'],
434  'height' => $attribArray['height']
435  );
436  $magicImage = $magicImageService->createMagicImage($fileObject, $imageConfiguration);
437  $attribArray['width'] = $magicImage->getProperty('width');
438  $attribArray['height'] = $magicImage->getProperty('height');
439  $attribArray['data-htmlarea-file-uid'] = $fileObject->getUid();
440  $attribArray['data-htmlarea-file-table'] = 'sys_file';
441  $attribArray['src'] = $magicImage->getPublicUrl();
442  }
443  }
444  } elseif (GeneralUtility::isFirstPartOfStr($absoluteUrl, $siteUrl)) {
445  // Finally, check image as local file (siteURL equals the one of the image)
446  // Image has no data-htmlarea-file-uid attribute
447  // Relative path, rawurldecoded for special characters.
448  $path = rawurldecode(substr($absoluteUrl, strlen($siteUrl)));
449  // Absolute filepath, locked to relative path of this project
450  $filepath = GeneralUtility::getFileAbsFileName($path);
451  // Check file existence (in relative directory to this installation!)
452  if ($filepath && @is_file($filepath)) {
453  // Treat it as a plain image
454  if ($this->procOptions['plainImageMode']) {
455  // If "plain image mode" has been configured
456  // Find the original dimensions of the image
457  $imageInfo = @getimagesize($filepath);
458  $attribArray = $this->applyPlainImageModeSettings($imageInfo, $attribArray);
459  }
460  // Let's try to find a file uid for this image
461  try {
462  $fileOrFolderObject = $resourceFactory->retrieveFileOrFolderObject($path);
463  if ($fileOrFolderObject instanceof Resource\FileInterface) {
464  $fileIdentifier = $fileOrFolderObject->getIdentifier();
465  $fileObject = $fileOrFolderObject->getStorage()->getFile($fileIdentifier);
466  // TODO: if the retrieved file is a processed file, get the original file...
467  $attribArray['data-htmlarea-file-uid'] = $fileObject->getUid();
468  $attribArray['data-htmlarea-file-table'] = 'sys_file';
469  }
470  } catch (Resource\Exception\ResourceDoesNotExistException $resourceDoesNotExistException) {
471  // Nothing to be done if file/folder not found
472  }
473  }
474  }
475  // Remove width and heigth from style attribute
476  $attribArray['style'] = preg_replace('/((?:^|)\\s*(?:width|height)\\s*:[^;]*(?:$|;))/si', '', $attribArray['style']);
477  // Must have alt attribute
478  if (!isset($attribArray['alt'])) {
479  $attribArray['alt'] = '';
480  }
481  // Convert absolute to relative url
482  if (GeneralUtility::isFirstPartOfStr($attribArray['src'], $siteUrl)) {
483  $attribArray['src'] = $this->relBackPath . substr($attribArray['src'], strlen($siteUrl));
484  }
485  $imgSplit[$k] = '<img ' . GeneralUtility::implodeAttributes($attribArray, 1, 1) . ' />';
486  }
487  }
488  }
489  return implode('', $imgSplit);
490  }
491 
500  public function TS_images_rte($value) {
501  // Split content by <img> tags and traverse the resulting array for processing:
502  $imgSplit = $this->splitTags('img', $value);
503  if (count($imgSplit) > 1) {
504  $siteUrl = $this->siteUrl();
505  $sitePath = str_replace(GeneralUtility::getIndpEnv('TYPO3_REQUEST_HOST'), '', $siteUrl);
506  foreach ($imgSplit as $k => $v) {
507  // Image found
508  if ($k % 2) {
509  // Get the attributes of the img tag
510  $attribArray = $this->get_tag_attributes_classic($v, 1);
511  $absoluteUrl = trim($attribArray['src']);
512  // Transform the src attribute into an absolute url, if it not already
513  if (strtolower(substr($absoluteUrl, 0, 4)) !== 'http') {
514  $attribArray['src'] = substr($attribArray['src'], strlen($this->relBackPath));
515  // If site is in a subpath (eg. /~user_jim/) this path needs to be removed because it will be added with $siteUrl
516  $attribArray['src'] = preg_replace('#^' . preg_quote($sitePath, '#') . '#', '', $attribArray['src']);
517  $attribArray['src'] = $siteUrl . $attribArray['src'];
518  }
519  // Must have alt attribute
520  if (!isset($attribArray['alt'])) {
521  $attribArray['alt'] = '';
522  }
523  $imgSplit[$k] = '<img ' . GeneralUtility::implodeAttributes($attribArray, 1, 1) . ' />';
524  }
525  }
526  }
527  // Return processed content:
528  return implode('', $imgSplit);
529  }
530 
540  public function TS_reglinks($value, $direction) {
541  $retVal = '';
542  switch ($direction) {
543  case 'rte':
544  $retVal = $this->TS_AtagToAbs($value, 1);
545  break;
546  case 'db':
547  $siteURL = $this->siteUrl();
548  $blockSplit = $this->splitIntoBlock('A', $value);
549  foreach ($blockSplit as $k => $v) {
550  // Block
551  if ($k % 2) {
552  $attribArray = $this->get_tag_attributes_classic($this->getFirstTag($v), 1);
553  // If the url is local, remove url-prefix
554  if ($siteURL && substr($attribArray['href'], 0, strlen($siteURL)) == $siteURL) {
555  $attribArray['href'] = $this->relBackPath . substr($attribArray['href'], strlen($siteURL));
556  }
557  $bTag = '<a ' . GeneralUtility::implodeAttributes($attribArray, 1) . '>';
558  $eTag = '</a>';
559  $blockSplit[$k] = $bTag . $this->TS_reglinks($this->removeFirstAndLastTag($blockSplit[$k]), $direction) . $eTag;
560  }
561  }
562  $retVal = implode('', $blockSplit);
563  break;
564  }
565  return $retVal;
566  }
567 
577  public function TS_links_db($value) {
578  $conf = array();
579  // Split content into <a> tag blocks and process:
580  $blockSplit = $this->splitIntoBlock('A', $value);
581  foreach ($blockSplit as $k => $v) {
582  // If an A-tag was found:
583  if ($k % 2) {
584  $attribArray = $this->get_tag_attributes_classic($this->getFirstTag($v), 1);
585  $info = $this->urlInfoForLinkTags($attribArray['href']);
586  // Check options:
587  $attribArray_copy = $attribArray;
588  unset($attribArray_copy['href']);
589  unset($attribArray_copy['target']);
590  unset($attribArray_copy['class']);
591  unset($attribArray_copy['title']);
592  unset($attribArray_copy['data-htmlarea-external']);
593  // Unset "rteerror" and "style" attributes if "rteerror" is set!
594  if ($attribArray_copy['rteerror']) {
595  unset($attribArray_copy['style']);
596  unset($attribArray_copy['rteerror']);
597  }
598  // Remove additional parameters
599  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['removeParams_PostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['removeParams_PostProc'])) {
600  $parameters = array(
601  'conf' => &$conf,
602  'aTagParams' => &$attribArray_copy
603  );
604  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['removeParams_PostProc'] as $objRef) {
605  $processor = GeneralUtility::getUserObj($objRef);
606  $attribArray_copy = $processor->removeParams($parameters, $this);
607  }
608  }
609  // Only if href, target, class and tile are the only attributes, we can alter the link!
610  if (!count($attribArray_copy)) {
611  // Quoting class and title attributes if they contain spaces
612  $attribArray['class'] = preg_match('/ /', $attribArray['class']) ? '"' . $attribArray['class'] . '"' : $attribArray['class'];
613  $attribArray['title'] = preg_match('/ /', $attribArray['title']) ? '"' . $attribArray['title'] . '"' : $attribArray['title'];
614  // Creating the TYPO3 pseudo-tag "<LINK>" for the link (includes href/url, target and class attributes):
615  // If data-htmlarea-external attribute is set, keep the href unchanged
616  if ($attribArray['data-htmlarea-external']) {
617  $href = $attribArray['href'];
618  } else {
619  $href = $info['url'] . ($info['query'] ? ',0,' . $info['query'] : '');
620  }
621  $bTag = '<link ' . $href . ($attribArray['target'] ? ' ' . $attribArray['target'] : ($attribArray['class'] || $attribArray['title'] ? ' -' : '')) . ($attribArray['class'] ? ' ' . $attribArray['class'] : ($attribArray['title'] ? ' -' : '')) . ($attribArray['title'] ? ' ' . $attribArray['title'] : '') . '>';
622  $eTag = '</link>';
623  // Modify parameters
624  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksDb_PostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksDb_PostProc'])) {
625  $parameters = array(
626  'conf' => &$conf,
627  'currentBlock' => $v,
628  'url' => $href,
629  'attributes' => $attribArray
630  );
631  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksDb_PostProc'] as $objRef) {
632  $processor = GeneralUtility::getUserObj($objRef);
633  $blockSplit[$k] = $processor->modifyParamsLinksDb($parameters, $this);
634  }
635  } else {
636  $blockSplit[$k] = $bTag . $this->TS_links_db($this->removeFirstAndLastTag($blockSplit[$k])) . $eTag;
637  }
638  } else {
639  // ... otherwise store the link as a-tag.
640  // Unsetting 'rtekeep' attribute if that had been set.
641  unset($attribArray['rtekeep']);
642  if (!$attribArray['data-htmlarea-external']) {
643  $siteURL = $this->siteUrl();
644  // If the url is local, remove url-prefix
645  if ($siteURL && substr($attribArray['href'], 0, strlen($siteURL)) == $siteURL) {
646  $attribArray['href'] = $this->relBackPath . substr($attribArray['href'], strlen($siteURL));
647  }
648  // Check for FAL link-handler keyword
649  list($linkHandlerKeyword, $linkHandlerValue) = explode(':', $attribArray['href'], 2);
650  if ($linkHandlerKeyword === '?file') {
651  try {
652  $fileOrFolderObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->retrieveFileOrFolderObject(rawurldecode($linkHandlerValue));
653  if ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\FileInterface || $fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\Folder) {
654  $attribArray['href'] = $fileOrFolderObject->getPublicUrl();
655  }
656  } catch (\TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException $resourceDoesNotExistException) {
657  // The indentifier inserted in the RTE is already gone...
658  }
659  }
660  }
661  unset($attribArray['data-htmlarea-external']);
662  $bTag = '<a ' . GeneralUtility::implodeAttributes($attribArray, 1) . '>';
663  $eTag = '</a>';
664  $blockSplit[$k] = $bTag . $this->TS_links_db($this->removeFirstAndLastTag($blockSplit[$k])) . $eTag;
665  }
666  }
667  }
668  return implode('', $blockSplit);
669  }
670 
680  public function TS_links_rte($value) {
681  $conf = array();
682  $value = $this->TS_AtagToAbs($value);
683  // Split content by the TYPO3 pseudo tag "<link>":
684  $blockSplit = $this->splitIntoBlock('link', $value, 1);
685  $siteUrl = $this->siteUrl();
686  foreach ($blockSplit as $k => $v) {
687  $error = '';
688  $external = FALSE;
689  // Block
690  if ($k % 2) {
691  $tagCode = GeneralUtility::unQuoteFilenames(trim(substr($this->getFirstTag($v), 0, -1)), TRUE);
692  $link_param = $tagCode[1];
693  $href = '';
694  // Parsing the typolink data. This parsing is roughly done like in tslib_content->typolink()
695  // Parse URL:
696  $pU = parse_url($link_param);
697  if (strstr($link_param, '@') && (!$pU['scheme'] || $pU['scheme'] == 'mailto')) {
698  // mailadr
699  $href = 'mailto:' . preg_replace('/^mailto:/i', '', $link_param);
700  } elseif ($link_param[0] === '#') {
701  // check if anchor
702  $href = $siteUrl . $link_param;
703  } else {
704  // Check for FAL link-handler keyword:
705  list($linkHandlerKeyword, $linkHandlerValue) = explode(':', trim($link_param), 2);
706  if ($linkHandlerKeyword === 'file' && !GeneralUtility::isFirstPartOfStr($link_param, 'file://')) {
707  $href = $siteUrl . '?' . $linkHandlerKeyword . ':' . rawurlencode($linkHandlerValue);
708  } else {
709  $fileChar = (int)strpos($link_param, '/');
710  $urlChar = (int)strpos($link_param, '.');
711  // Detects if a file is found in site-root.
712  list($rootFileDat) = explode('?', $link_param);
713  $rFD_fI = pathinfo($rootFileDat);
714  if (trim($rootFileDat) && !strstr($link_param, '/') && (@is_file((PATH_site . $rootFileDat)) || GeneralUtility::inList('php,html,htm', strtolower($rFD_fI['extension'])))) {
715  $href = $siteUrl . $link_param;
716  } elseif (
717  (
718  $pU['scheme']
719  && !isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][$pU['scheme']])
720  )
721  || $urlChar && (!$fileChar || $urlChar < $fileChar)
722  ) {
723  // url (external): if has scheme or if a '.' comes before a '/'.
724  $href = $link_param;
725  if (!$pU['scheme']) {
726  $href = 'http://' . $href;
727  }
728  $external = TRUE;
729  } elseif ($fileChar) {
730  // It is an internal file or folder
731  // Try to transform the href into a FAL reference
732  try {
733  $fileOrFolderObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->retrieveFileOrFolderObject($link_param);
734  } catch (\TYPO3\CMS\Core\Resource\Exception $exception) {
735  // Nothing to be done if file/folder not found or path invalid
736  $fileOrFolderObject = NULL;
737  }
738  if ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\Folder) {
739  // It's a folder
740  $folderIdentifier = $fileOrFolderObject->getIdentifier();
741  $href = $siteUrl . '?file:' . rawurlencode($folderIdentifier);
742  } elseif ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\FileInterface) {
743  // It's a file
744  $fileIdentifier = $fileOrFolderObject->getIdentifier();
745  $fileObject = $fileOrFolderObject->getStorage()->getFile($fileIdentifier);
746  $href = $siteUrl . '?file:' . $fileObject->getUid();
747  } else {
748  $href = $siteUrl . $link_param;
749  }
750  } else {
751  // integer or alias (alias is without slashes or periods or commas, that is 'nospace,alphanum_x,lower,unique' according to tables.php!!)
752  // Splitting the parameter by ',' and if the array counts more than 1 element it's a id/type/parameters triplet
753  $pairParts = GeneralUtility::trimExplode(',', $link_param, TRUE);
754  $idPart = $pairParts[0];
755  $link_params_parts = explode('#', $idPart);
756  $idPart = trim($link_params_parts[0]);
757  $sectionMark = trim($link_params_parts[1]);
758  if ((string)$idPart === '') {
759  $idPart = $this->recPid;
760  }
761  // If no id or alias is given, set it to class record pid
762  // Checking if the id-parameter is an alias.
763  if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($idPart)) {
764  list($idPartR) = BackendUtility::getRecordsByField('pages', 'alias', $idPart);
765  $idPart = (int)$idPartR['uid'];
766  }
767  $page = BackendUtility::getRecord('pages', $idPart);
768  if (is_array($page)) {
769  // Page must exist...
770  $href = $siteUrl . '?id=' . $idPart . ($pairParts[2] ? $pairParts[2] : '') . ($sectionMark ? '#' . $sectionMark : '');
771  } elseif (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['typolinkLinkHandler'][array_shift(explode(':', $link_param))])) {
772  $href = $link_param;
773  } else {
774  $href = $siteUrl . '?id=' . $link_param;
775  $error = 'No page found: ' . $idPart;
776  }
777  }
778  }
779  }
780  // Setting the A-tag:
781  $bTag = '<a href="' . htmlspecialchars($href) . '"' . ($tagCode[2] && $tagCode[2] != '-' ? ' target="' . htmlspecialchars($tagCode[2]) . '"' : '') . ($tagCode[3] && $tagCode[3] != '-' ? ' class="' . htmlspecialchars($tagCode[3]) . '"' : '') . ($tagCode[4] ? ' title="' . htmlspecialchars($tagCode[4]) . '"' : '') . ($external ? ' data-htmlarea-external="1"' : '') . ($error ? ' rteerror="' . htmlspecialchars($error) . '" style="background-color: yellow; border:2px red solid; color: black;"' : '') . '>';
782  $eTag = '</a>';
783  // Modify parameters
784  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksRte_PostProc']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksRte_PostProc'])) {
785  $parameters = array(
786  'conf' => &$conf,
787  'currentBlock' => $v,
788  'url' => $href,
789  'tagCode' => $tagCode,
790  'external' => $external,
791  'error' => $error
792  );
793  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['modifyParams_LinksRte_PostProc'] as $objRef) {
794  $processor = GeneralUtility::getUserObj($objRef);
795  $blockSplit[$k] = $processor->modifyParamsLinksRte($parameters, $this);
796  }
797  } else {
798  $blockSplit[$k] = $bTag . $this->TS_links_rte($this->removeFirstAndLastTag($blockSplit[$k])) . $eTag;
799  }
800  }
801  }
802  // Return content:
803  return implode('', $blockSplit);
804  }
805 
813  public function TS_preserve_db($value) {
814  if (!$this->preserveTags) {
815  return $value;
816  }
817  // Splitting into blocks for processing (span-tags are used for special tags)
818  $blockSplit = $this->splitIntoBlock('span', $value);
819  foreach ($blockSplit as $k => $v) {
820  // Block
821  if ($k % 2) {
822  $attribArray = $this->get_tag_attributes_classic($this->getFirstTag($v));
823  if ($attribArray['specialtag']) {
824  $theTag = rawurldecode($attribArray['specialtag']);
825  $theTagName = $this->getFirstTagName($theTag);
826  $blockSplit[$k] = $theTag . $this->removeFirstAndLastTag($blockSplit[$k]) . '</' . $theTagName . '>';
827  }
828  }
829  }
830  return implode('', $blockSplit);
831  }
832 
840  public function TS_preserve_rte($value) {
841  if (!$this->preserveTags) {
842  return $value;
843  }
844  $blockSplit = $this->splitIntoBlock($this->preserveTags, $value);
845  foreach ($blockSplit as $k => $v) {
846  // Block
847  if ($k % 2) {
848  $blockSplit[$k] = '<span specialtag="' . rawurlencode($this->getFirstTag($v)) . '">' . $this->removeFirstAndLastTag($blockSplit[$k]) . '</span>';
849  }
850  }
851  return implode('', $blockSplit);
852  }
853 
864  public function TS_transform_db($value, $css = FALSE) {
865  // Safety... so forever loops are avoided (they should not occur, but an error would potentially do this...)
866  $this->TS_transform_db_safecounter--;
867  if ($this->TS_transform_db_safecounter < 0) {
868  return $value;
869  }
870  // Split the content from RTE by the occurence of these blocks:
871  $blockSplit = $this->splitIntoBlock('TABLE,BLOCKQUOTE,' . ($this->procOptions['preserveDIVSections'] ? 'DIV,' : '') . $this->blockElementList, $value);
872  $cc = 0;
873  $aC = count($blockSplit);
874  // Avoid superfluous linebreaks by transform_db after ending headListTag
875  while ($aC && trim($blockSplit[($aC - 1)]) === '') {
876  unset($blockSplit[$aC - 1]);
877  $aC = count($blockSplit);
878  }
879  // Traverse the blocks
880  foreach ($blockSplit as $k => $v) {
881  $cc++;
882  $lastBR = $cc == $aC ? '' : LF;
883  if ($k % 2) {
884  // Inside block:
885  // Init:
886  $tag = $this->getFirstTag($v);
887  $tagName = strtolower($this->getFirstTagName($v));
888  // Process based on the tag:
889  switch ($tagName) {
890  case 'blockquote':
891 
892  case 'dd':
893 
894  case 'div':
895 
896  case 'header':
897 
898  case 'section':
899 
900  case 'footer':
901 
902  case 'nav':
903 
904  case 'article':
905 
906  case 'aside':
907  $blockSplit[$k] = $tag . $this->TS_transform_db($this->removeFirstAndLastTag($blockSplit[$k]), $css) . '</' . $tagName . '>' . $lastBR;
908  break;
909  case 'ol':
910 
911  case 'ul':
912  // Transform lists into <typolist>-tags:
913  if (!$css) {
914  if (!isset($this->procOptions['typolist']) || $this->procOptions['typolist']) {
915  $parts = $this->getAllParts($this->splitIntoBlock('LI', $this->removeFirstAndLastTag($blockSplit[$k])), 1, 0);
916  foreach ($parts as $k2 => $value) {
917  $parts[$k2] = preg_replace('/[' . LF . CR . ']+/', '', $parts[$k2]);
918  // remove all linesbreaks!
919  $parts[$k2] = $this->defaultTStagMapping($parts[$k2], 'db');
920  $parts[$k2] = $this->cleanFontTags($parts[$k2], 0, 0, 0);
921  $parts[$k2] = $this->HTMLcleaner_db($parts[$k2], strtolower($this->procOptions['allowTagsInTypolists'] ? $this->procOptions['allowTagsInTypolists'] : 'br,font,b,i,u,a,img,span,strong,em'));
922  }
923  if ($tagName == 'ol') {
924  $params = ' type="1"';
925  } else {
926  $params = '';
927  }
928  $blockSplit[$k] = '<typolist' . $params . '>' . LF . implode(LF, $parts) . LF . '</typolist>' . $lastBR;
929  }
930  } else {
931  $blockSplit[$k] = preg_replace(('/[' . LF . CR . ']+/'), ' ', $this->transformStyledATags($blockSplit[$k])) . $lastBR;
932  }
933  break;
934  case 'table':
935  // Tables are NOT allowed in any form (unless preserveTables is set or CSS is the mode)
936  if (!$this->procOptions['preserveTables'] && !$css) {
937  $blockSplit[$k] = $this->TS_transform_db($this->removeTables($blockSplit[$k]));
938  } else {
939  $blockSplit[$k] = preg_replace(('/[' . LF . CR . ']+/'), ' ', $this->transformStyledATags($blockSplit[$k])) . $lastBR;
940  }
941  break;
942  case 'h1':
943 
944  case 'h2':
945 
946  case 'h3':
947 
948  case 'h4':
949 
950  case 'h5':
951 
952  case 'h6':
953  if (!$css) {
954  $attribArray = $this->get_tag_attributes_classic($tag);
955  // Processing inner content here:
956  $innerContent = $this->HTMLcleaner_db($this->removeFirstAndLastTag($blockSplit[$k]));
957  if (!isset($this->procOptions['typohead']) || $this->procOptions['typohead']) {
958  $type = (int)substr($tagName, 1);
959  $blockSplit[$k] = '<typohead' . ($type != 6 ? ' type="' . $type . '"' : '') . ($attribArray['align'] ? ' align="' . $attribArray['align'] . '"' : '') . ($attribArray['class'] ? ' class="' . $attribArray['class'] . '"' : '') . '>' . $innerContent . '</typohead>' . $lastBR;
960  } else {
961  $blockSplit[$k] = '<' . $tagName . ($attribArray['align'] ? ' align="' . htmlspecialchars($attribArray['align']) . '"' : '') . ($attribArray['class'] ? ' class="' . htmlspecialchars($attribArray['class']) . '"' : '') . '>' . $innerContent . '</' . $tagName . '>' . $lastBR;
962  }
963  } else {
964  // Eliminate true linebreaks inside Hx tags
965  $blockSplit[$k] = preg_replace(('/[' . LF . CR . ']+/'), ' ', $this->transformStyledATags($blockSplit[$k])) . $lastBR;
966  }
967  break;
968  default:
969  // Eliminate true linebreaks inside other headlist tags
970  $blockSplit[$k] = preg_replace(('/[' . LF . CR . ']+/'), ' ', $this->transformStyledATags($blockSplit[$k])) . $lastBR;
971  }
972  } else {
973  // NON-block:
974  if (trim($blockSplit[$k]) !== '') {
975  $blockSplit[$k] = preg_replace('/<hr\\/>/', '<hr />', $blockSplit[$k]);
976  // Remove linebreaks preceding hr tags
977  $blockSplit[$k] = preg_replace('/[' . LF . CR . ']+<(hr)(\\s[^>\\/]*)?[[:space:]]*\\/?>/', '<$1$2/>', $blockSplit[$k]);
978  // Remove linebreaks following hr tags
979  $blockSplit[$k] = preg_replace('/<(hr)(\\s[^>\\/]*)?[[:space:]]*\\/?>[' . LF . CR . ']+/', '<$1$2/>', $blockSplit[$k]);
980  // Replace other linebreaks with space
981  $blockSplit[$k] = preg_replace('/[' . LF . CR . ']+/', ' ', $blockSplit[$k]);
982  $blockSplit[$k] = $this->divideIntoLines($blockSplit[$k]) . $lastBR;
983  $blockSplit[$k] = $this->transformStyledATags($blockSplit[$k]);
984  } else {
985  unset($blockSplit[$k]);
986  }
987  }
988  }
989  $this->TS_transform_db_safecounter++;
990  return implode('', $blockSplit);
991  }
992 
1000  public function transformStyledATags($value) {
1001  $blockSplit = $this->splitIntoBlock('A', $value);
1002  foreach ($blockSplit as $k => $v) {
1003  // If an A-tag was found
1004  if ($k % 2) {
1005  $attribArray = $this->get_tag_attributes_classic($this->getFirstTag($v), 1);
1006  // If "style" attribute is set and rteerror is not set!
1007  if ($attribArray['style'] && !$attribArray['rteerror']) {
1008  $attribArray_copy['style'] = $attribArray['style'];
1009  unset($attribArray['style']);
1010  $bTag = '<span ' . GeneralUtility::implodeAttributes($attribArray_copy, 1) . '><a ' . GeneralUtility::implodeAttributes($attribArray, 1) . '>';
1011  $eTag = '</a></span>';
1012  $blockSplit[$k] = $bTag . $this->removeFirstAndLastTag($blockSplit[$k]) . $eTag;
1013  }
1014  }
1015  }
1016  return implode('', $blockSplit);
1017  }
1018 
1029  public function TS_transform_rte($value, $css = 0) {
1030  // Split the content from database by the occurence of the block elements
1031  $blockElementList = 'TABLE,BLOCKQUOTE,TYPOLIST,TYPOHEAD,' . ($this->procOptions['preserveDIVSections'] ? 'DIV,' : '') . $this->blockElementList;
1032  $blockSplit = $this->splitIntoBlock($blockElementList, $value);
1033  // Traverse the blocks
1034  foreach ($blockSplit as $k => $v) {
1035  if ($k % 2) {
1036  // Inside one of the blocks:
1037  // Init:
1038  $tag = $this->getFirstTag($v);
1039  $tagName = strtolower($this->getFirstTagName($v));
1040  $attribArray = $this->get_tag_attributes_classic($tag);
1041  // Based on tagname, we do transformations:
1042  switch ($tagName) {
1043  case 'blockquote':
1044 
1045  case 'dd':
1046 
1047  case 'div':
1048 
1049  case 'header':
1050 
1051  case 'section':
1052 
1053  case 'footer':
1054 
1055  case 'nav':
1056 
1057  case 'article':
1058 
1059  case 'aside':
1060  $blockSplit[$k] = $tag . $this->TS_transform_rte($this->removeFirstAndLastTag($blockSplit[$k]), $css) . '</' . $tagName . '>';
1061  break;
1062  case 'typolist':
1063  // Transform typolist blocks into OL/UL lists. Type 1 is expected to be numerical block
1064  if (!isset($this->procOptions['typolist']) || $this->procOptions['typolist']) {
1065  $tListContent = $this->removeFirstAndLastTag($blockSplit[$k]);
1066  $tListContent = preg_replace('/^[ ]*' . LF . '/', '', $tListContent);
1067  $tListContent = preg_replace('/' . LF . '[ ]*$/', '', $tListContent);
1068  $lines = explode(LF, $tListContent);
1069  $typ = $attribArray['type'] == 1 ? 'ol' : 'ul';
1070  $blockSplit[$k] = '<' . $typ . '>' . LF . '<li>' . implode(('</li>' . LF . '<li>'), $lines) . '</li>' . '</' . $typ . '>';
1071  }
1072  break;
1073  case 'typohead':
1074  // Transform typohead into Hx tags.
1075  if (!isset($this->procOptions['typohead']) || $this->procOptions['typohead']) {
1076  $tC = $this->removeFirstAndLastTag($blockSplit[$k]);
1077  $typ = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($attribArray['type'], 0, 6);
1078  if (!$typ) {
1079  $typ = 6;
1080  }
1081  $align = $attribArray['align'] ? ' align="' . $attribArray['align'] . '"' : '';
1082  $class = $attribArray['class'] ? ' class="' . $attribArray['class'] . '"' : '';
1083  $blockSplit[$k] = '<h' . $typ . $align . $class . '>' . $tC . '</h' . $typ . '>';
1084  }
1085  break;
1086  }
1087  $blockSplit[$k + 1] = preg_replace('/^[ ]*' . LF . '/', '', $blockSplit[$k + 1]);
1088  } else {
1089  // NON-block:
1090  $nextFTN = $this->getFirstTagName($blockSplit[$k + 1]);
1091  $onlyLineBreaks = (preg_match('/^[ ]*' . LF . '+[ ]*$/', $blockSplit[$k]) == 1);
1092  // If the line is followed by a block or is the last line:
1093  if (GeneralUtility::inList($blockElementList, $nextFTN) || !isset($blockSplit[$k + 1])) {
1094  // If the line contains more than just linebreaks, reduce the number of trailing linebreaks by 1
1095  if (!$onlyLineBreaks) {
1096  $blockSplit[$k] = preg_replace('/(' . LF . '*)' . LF . '[ ]*$/', '$1', $blockSplit[$k]);
1097  } else {
1098  // If the line contains only linebreaks, remove the leading linebreak
1099  $blockSplit[$k] = preg_replace('/^[ ]*' . LF . '/', '', $blockSplit[$k]);
1100  }
1101  }
1102  // If $blockSplit[$k] is blank then unset the line, unless the line only contained linebreaks
1103  if ((string)$blockSplit[$k] === '' && !$onlyLineBreaks) {
1104  unset($blockSplit[$k]);
1105  } else {
1106  $blockSplit[$k] = $this->setDivTags($blockSplit[$k], $this->procOptions['useDIVasParagraphTagForRTE'] ? 'div' : 'p');
1107  }
1108  }
1109  }
1110  return implode(LF, $blockSplit);
1111  }
1112 
1121  public function TS_strip_db($value) {
1122  $value = strip_tags($value, '<' . implode('><', explode(',', 'b,i,u,a,img,br,div,center,pre,font,hr,sub,sup,p,strong,em,li,ul,ol,blockquote')) . '>');
1123  return $value;
1124  }
1125 
1126  /***************************************************************
1127  *
1128  * Generic RTE transformation, analysis and helper functions
1129  *
1130  **************************************************************/
1139  public function getUrl($url) {
1140  return GeneralUtility::getUrl($url);
1141  }
1142 
1154  public function HTMLcleaner_db($content, $tagList = '') {
1155  if (!$tagList) {
1156  $keepTags = $this->getKeepTags('db');
1157  } else {
1158  $keepTags = $this->getKeepTags('db', $tagList);
1159  }
1160  // Default: remove unknown tags.
1161  $kUknown = $this->procOptions['dontRemoveUnknownTags_db'] ? 1 : 0;
1162  // Default: re-convert literals to characters (that is &lt; to <)
1163  $hSC = $this->procOptions['dontUndoHSC_db'] ? 0 : -1;
1164  // Create additional configuration in order to honor the setting RTE.default.proc.HTMLparser_db.xhtml_cleaning=1
1165  $addConfig = array();
1166  if (is_array($this->procOptions['HTMLparser_db.']) && $this->procOptions['HTMLparser_db.']['xhtml_cleaning'] || is_array($this->procOptions['entryHTMLparser_db.']) && $this->procOptions['entryHTMLparser_db.']['xhtml_cleaning'] || is_array($this->procOptions['exitHTMLparser_db.']) && $this->procOptions['exitHTMLparser_db.']['xhtml_cleaning']) {
1167  $addConfig['xhtml'] = 1;
1168  }
1169  return $this->HTMLcleaner($content, $keepTags, $kUknown, $hSC, $addConfig);
1170  }
1171 
1182  public function getKeepTags($direction = 'rte', $tagList = '') {
1183  if (!is_array($this->getKeepTags_cache[$direction]) || $tagList) {
1184  // Setting up allowed tags:
1185  // If the $tagList input var is set, this will take precedence
1186  if ((string)$tagList !== '') {
1187  $keepTags = array_flip(GeneralUtility::trimExplode(',', $tagList, TRUE));
1188  } else {
1189  // Default is to get allowed/denied tags from internal array of processing options:
1190  // Construct default list of tags to keep:
1191  $typoScript_list = 'b,i,u,a,img,br,div,center,pre,font,hr,sub,sup,p,strong,em,li,ul,ol,blockquote,strike,span';
1192  $keepTags = array_flip(GeneralUtility::trimExplode(',', $typoScript_list . ',' . strtolower($this->procOptions['allowTags']), TRUE));
1193  // For tags to deny, remove them from $keepTags array:
1194  $denyTags = GeneralUtility::trimExplode(',', $this->procOptions['denyTags'], TRUE);
1195  foreach ($denyTags as $dKe) {
1196  unset($keepTags[$dKe]);
1197  }
1198  }
1199  // Based on the direction of content, set further options:
1200  switch ($direction) {
1201  case 'rte':
1202  if (!isset($this->procOptions['transformBoldAndItalicTags']) || $this->procOptions['transformBoldAndItalicTags']) {
1203  // Transform bold/italics tags to strong/em
1204  if (isset($keepTags['b'])) {
1205  $keepTags['b'] = array('remap' => 'STRONG');
1206  }
1207  if (isset($keepTags['i'])) {
1208  $keepTags['i'] = array('remap' => 'EM');
1209  }
1210  }
1211  // Transforming keepTags array so it can be understood by the HTMLcleaner function. This basically converts the format of the array from TypoScript (having .'s) to plain multi-dimensional array.
1212  list($keepTags) = $this->HTMLparserConfig($this->procOptions['HTMLparser_rte.'], $keepTags);
1213  break;
1214  case 'db':
1215  if (!isset($this->procOptions['transformBoldAndItalicTags']) || $this->procOptions['transformBoldAndItalicTags']) {
1216  // Transform strong/em back to bold/italics:
1217  if (isset($keepTags['strong'])) {
1218  $keepTags['strong'] = array('remap' => 'b');
1219  }
1220  if (isset($keepTags['em'])) {
1221  $keepTags['em'] = array('remap' => 'i');
1222  }
1223  }
1224  // Setting up span tags if they are allowed:
1225  if (isset($keepTags['span'])) {
1226  $classes = array_merge(array(''), $this->allowedClasses);
1227  $keepTags['span'] = array(
1228  'allowedAttribs' => 'id,class,style,title,lang,xml:lang,dir,itemscope,itemtype,itemprop',
1229  'fixAttrib' => array(
1230  'class' => array(
1231  'list' => $classes,
1232  'removeIfFalse' => 1
1233  )
1234  ),
1235  'rmTagIfNoAttrib' => 1
1236  );
1237  if (!$this->procOptions['allowedClasses']) {
1238  unset($keepTags['span']['fixAttrib']['class']['list']);
1239  }
1240  }
1241  // Setting up font tags if they are allowed:
1242  if (isset($keepTags['font'])) {
1243  $colors = array_merge(array(''), GeneralUtility::trimExplode(',', $this->procOptions['allowedFontColors'], TRUE));
1244  $keepTags['font'] = array(
1245  'allowedAttribs' => 'face,color,size',
1246  'fixAttrib' => array(
1247  'face' => array(
1248  'removeIfFalse' => 1
1249  ),
1250  'color' => array(
1251  'removeIfFalse' => 1,
1252  'list' => $colors
1253  ),
1254  'size' => array(
1255  'removeIfFalse' => 1
1256  )
1257  ),
1258  'rmTagIfNoAttrib' => 1
1259  );
1260  if (!$this->procOptions['allowedFontColors']) {
1261  unset($keepTags['font']['fixAttrib']['color']['list']);
1262  }
1263  }
1264  // Setting further options, getting them from the processiong options:
1265  $TSc = $this->procOptions['HTMLparser_db.'];
1266  if (!$TSc['globalNesting']) {
1267  $TSc['globalNesting'] = 'b,i,u,a,center,font,sub,sup,strong,em,strike,span';
1268  }
1269  if (!$TSc['noAttrib']) {
1270  $TSc['noAttrib'] = 'b,i,u,br,center,hr,sub,sup,strong,em,li,ul,ol,blockquote,strike';
1271  }
1272  // Transforming the array from TypoScript to regular array:
1273  list($keepTags) = $this->HTMLparserConfig($TSc, $keepTags);
1274  break;
1275  }
1276  // Caching (internally, in object memory) the result unless tagList is set:
1277  if (!$tagList) {
1278  $this->getKeepTags_cache[$direction] = $keepTags;
1279  } else {
1280  return $keepTags;
1281  }
1282  }
1283  // Return result:
1284  return $this->getKeepTags_cache[$direction];
1285  }
1286 
1300  public function divideIntoLines($value, $count = 5, $returnArray = FALSE) {
1301  // Internalize font tags (move them from OUTSIDE p/div to inside it that is the case):
1302  if ($this->procOptions['internalizeFontTags']) {
1303  $value = $this->internalizeFontTags($value);
1304  }
1305  // Setting configuration for processing:
1306  $allowTagsOutside = GeneralUtility::trimExplode(',', strtolower($this->procOptions['allowTagsOutside'] ? 'hr,' . $this->procOptions['allowTagsOutside'] : 'hr,img'), TRUE);
1307  $remapParagraphTag = strtoupper($this->procOptions['remapParagraphTag']);
1308  $divSplit = $this->splitIntoBlock('div,p', $value, 1);
1309  // Setting the third param to 1 will eliminate false end-tags. Maybe this is a good thing to do...?
1310  if ($this->procOptions['keepPDIVattribs']) {
1311  $keepAttribListArr = GeneralUtility::trimExplode(',', strtolower($this->procOptions['keepPDIVattribs']), TRUE);
1312  } else {
1313  $keepAttribListArr = array();
1314  }
1315  // Returns plainly the value if there was no div/p sections in it
1316  if (count($divSplit) <= 1 || $count <= 0) {
1317  // Wrap hr tags with LF's
1318  $newValue = preg_replace('/<(hr)(\\s[^>\\/]*)?[[:space:]]*\\/?>/i', LF . '<$1$2/>' . LF, $value);
1319  $newValue = preg_replace('/' . LF . LF . '/i', LF, $newValue);
1320  $newValue = preg_replace('/(^' . LF . ')|(' . LF . '$)/i', '', $newValue);
1321  return $newValue;
1322  }
1323  // Traverse the splitted sections:
1324  foreach ($divSplit as $k => $v) {
1325  if ($k % 2) {
1326  // Inside
1327  $v = $this->removeFirstAndLastTag($v);
1328  // Fetching 'sub-lines' - which will explode any further p/div nesting...
1329  $subLines = $this->divideIntoLines($v, $count - 1, 1);
1330  // So, if there happend to be sub-nesting of p/div, this is written directly as the new content of THIS section. (This would be considered 'an error')
1331  if (is_array($subLines)) {
1332 
1333  } else {
1334  //... but if NO subsection was found, we process it as a TRUE line without erronous content:
1335  $subLines = array($subLines);
1336  // process break-tags, if configured for. Simply, the breaktags will here be treated like if each was a line of content...
1337  if (!$this->procOptions['dontConvBRtoParagraph']) {
1338  $subLines = preg_split('/<br[[:space:]]*[\\/]?>/i', $v);
1339  }
1340  // Traverse sublines (there is typically one, except if <br/> has been converted to lines as well!)
1341  foreach ($subLines as $sk => $value) {
1342  // Clear up the subline for DB.
1343  $subLines[$sk] = $this->HTMLcleaner_db($subLines[$sk]);
1344  // Get first tag, attributes etc:
1345  $fTag = $this->getFirstTag($divSplit[$k]);
1346  $tagName = strtolower($this->getFirstTagName($divSplit[$k]));
1347  $attribs = $this->get_tag_attributes($fTag);
1348  // Keep attributes (lowercase)
1349  $newAttribs = array();
1350  if (count($keepAttribListArr)) {
1351  foreach ($keepAttribListArr as $keepA) {
1352  if (isset($attribs[0][$keepA])) {
1353  $newAttribs[$keepA] = $attribs[0][$keepA];
1354  }
1355  }
1356  }
1357  // ALIGN attribute:
1358  if (!$this->procOptions['skipAlign'] && trim($attribs[0]['align']) !== '' && strtolower($attribs[0]['align']) != 'left') {
1359  // Set to value, but not 'left'
1360  $newAttribs['align'] = strtolower($attribs[0]['align']);
1361  }
1362  // CLASS attribute:
1363  // Set to whatever value
1364  if (!$this->procOptions['skipClass'] && trim($attribs[0]['class']) !== '') {
1365  if (!count($this->allowedClasses) || in_array($attribs[0]['class'], $this->allowedClasses)) {
1366  $newAttribs['class'] = $attribs[0]['class'];
1367  } else {
1368  $classes = GeneralUtility::trimExplode(' ', $attribs[0]['class'], TRUE);
1369  $newClasses = array();
1370  foreach ($classes as $class) {
1371  if (in_array($class, $this->allowedClasses)) {
1372  $newClasses[] = $class;
1373  }
1374  }
1375  if (count($newClasses)) {
1376  $newAttribs['class'] = implode(' ', $newClasses);
1377  }
1378  }
1379  }
1380  // Remove any line break char (10 or 13)
1381  $subLines[$sk] = preg_replace('/' . LF . '|' . CR . '/', '', $subLines[$sk]);
1382  // If there are any attributes or if we are supposed to remap the tag, then do so:
1383  if (count($newAttribs) && $remapParagraphTag !== '1') {
1384  if ($remapParagraphTag === 'P') {
1385  $tagName = 'p';
1386  }
1387  if ($remapParagraphTag === 'DIV') {
1388  $tagName = 'div';
1389  }
1390  $subLines[$sk] = '<' . trim(($tagName . ' ' . $this->compileTagAttribs($newAttribs))) . '>' . $subLines[$sk] . '</' . $tagName . '>';
1391  }
1392  }
1393  }
1394  // Add the processed line(s)
1395  $divSplit[$k] = implode(LF, $subLines);
1396  // If it turns out the line is just blank (containing a &nbsp; possibly) then just make it pure blank.
1397  // But, prevent filtering of lines that are blank in sense above, but whose tags contain attributes.
1398  // Those attributes should have been filtered before; if they are still there they must be considered as possible content.
1399  if (trim(strip_tags($divSplit[$k])) == '&nbsp;' && !preg_match('/\\<(img)(\\s[^>]*)?\\/?>/si', $divSplit[$k]) && !preg_match('/\\<([^>]*)?( align| class| style| id| title| dir| lang| xml:lang)([^>]*)?>/si', trim($divSplit[$k]))) {
1400  $divSplit[$k] = '';
1401  }
1402  } else {
1403  // outside div:
1404  // Remove positions which are outside div/p tags and without content
1405  $divSplit[$k] = trim(strip_tags($divSplit[$k], '<' . implode('><', $allowTagsOutside) . '>'));
1406  // Wrap hr tags with LF's
1407  $divSplit[$k] = preg_replace('/<(hr)(\\s[^>\\/]*)?[[:space:]]*\\/?>/i', LF . '<$1$2/>' . LF, $divSplit[$k]);
1408  $divSplit[$k] = preg_replace('/' . LF . LF . '/i', LF, $divSplit[$k]);
1409  $divSplit[$k] = preg_replace('/(^' . LF . ')|(' . LF . '$)/i', '', $divSplit[$k]);
1410  if ((string)$divSplit[$k] === '') {
1411  unset($divSplit[$k]);
1412  }
1413  }
1414  }
1415  // Return value:
1416  return $returnArray ? $divSplit : implode(LF, $divSplit);
1417  }
1418 
1429  public function setDivTags($value, $dT = 'p') {
1430  // First, setting configuration for the HTMLcleaner function. This will process each line between the <div>/<p> section on their way to the RTE
1431  $keepTags = $this->getKeepTags('rte');
1432  // Default: remove unknown tags.
1433  $kUknown = $this->procOptions['dontProtectUnknownTags_rte'] ? 0 : 'protect';
1434  // Default: re-convert literals to characters (that is &lt; to <)
1435  $hSC = $this->procOptions['dontHSC_rte'] ? 0 : 1;
1436  $convNBSP = !$this->procOptions['dontConvAmpInNBSP_rte'] ? 1 : 0;
1437  // Divide the content into lines, based on LF:
1438  $parts = explode(LF, $value);
1439  foreach ($parts as $k => $v) {
1440  // Processing of line content:
1441  // If the line is blank, set it to &nbsp;
1442  if (trim($parts[$k]) === '') {
1443  $parts[$k] = '&nbsp;';
1444  } else {
1445  // Clean the line content:
1446  $parts[$k] = $this->HTMLcleaner($parts[$k], $keepTags, $kUknown, $hSC);
1447  if ($convNBSP) {
1448  $parts[$k] = str_replace('&amp;nbsp;', '&nbsp;', $parts[$k]);
1449  }
1450  }
1451  // Wrapping the line in <$dT> if not already wrapped and does not contain an hr tag
1452  if (!preg_match('/<(hr)(\\s[^>\\/]*)?[[:space:]]*\\/?>/i', $parts[$k])) {
1453  $testStr = strtolower(trim($parts[$k]));
1454  if (substr($testStr, 0, 4) != '<div' || substr($testStr, -6) != '</div>') {
1455  if (substr($testStr, 0, 2) != '<p' || substr($testStr, -4) != '</p>') {
1456  // Only set p-tags if there is not already div or p tags:
1457  $parts[$k] = '<' . $dT . '>' . $parts[$k] . '</' . $dT . '>';
1458  }
1459  }
1460  }
1461  }
1462  // Implode result:
1463  return implode(LF, $parts);
1464  }
1465 
1478  public function internalizeFontTags($value) {
1479  // Splitting into font tag blocks:
1480  $fontSplit = $this->splitIntoBlock('font', $value);
1481  foreach ($fontSplit as $k => $v) {
1482  // Inside
1483  if ($k % 2) {
1484  // Fint font-tag
1485  $fTag = $this->getFirstTag($v);
1486  $divSplit_sub = $this->splitIntoBlock('div,p', $this->removeFirstAndLastTag($v), 1);
1487  // If there were div/p sections inside the font-tag, do something about it...
1488  if (count($divSplit_sub) > 1) {
1489  // Traverse those sections:
1490  foreach ($divSplit_sub as $k2 => $v2) {
1491  // Inside
1492  if ($k2 % 2) {
1493  // Fint font-tag
1494  $div_p = $this->getFirstTag($v2);
1495  // Fint font-tag
1496  $div_p_tagname = $this->getFirstTagName($v2);
1497  // ... and remove it from original.
1498  $v2 = $this->removeFirstAndLastTag($v2);
1499  $divSplit_sub[$k2] = $div_p . $fTag . $v2 . '</font>' . '</' . $div_p_tagname . '>';
1500  } elseif (trim(strip_tags($v2))) {
1501  $divSplit_sub[$k2] = $fTag . $v2 . '</font>';
1502  }
1503  }
1504  $fontSplit[$k] = implode('', $divSplit_sub);
1505  }
1506  }
1507  }
1508  return implode('', $fontSplit);
1509  }
1510 
1518  public function siteUrl() {
1519  return GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
1520  }
1521 
1528  public function rteImageStorageDir() {
1530  return $this->rte_p['imgpath'] ? $this->rte_p['imgpath'] : $GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_imageStorageDir'];
1531  }
1532 
1542  public function removeTables($value, $breakChar = '<br />') {
1543  // Splitting value into table blocks:
1544  $tableSplit = $this->splitIntoBlock('table', $value);
1545  // Traverse blocks of tables:
1546  foreach ($tableSplit as $k => $v) {
1547  if ($k % 2) {
1548  $tableSplit[$k] = '';
1549  $rowSplit = $this->splitIntoBlock('tr', $v);
1550  foreach ($rowSplit as $k2 => $v2) {
1551  if ($k2 % 2) {
1552  $cellSplit = $this->getAllParts($this->splitIntoBlock('td', $v2), 1, 0);
1553  foreach ($cellSplit as $k3 => $v3) {
1554  $tableSplit[$k] .= $v3 . $breakChar;
1555  }
1556  }
1557  }
1558  }
1559  }
1560  // Implode it all again:
1561  return implode($breakChar, $tableSplit);
1562  }
1563 
1572  public function defaultTStagMapping($code, $direction = 'rte') {
1573  if ($direction == 'db') {
1574  $code = $this->mapTags($code, array(
1575  // Map tags
1576  'strong' => 'b',
1577  'em' => 'i'
1578  ));
1579  }
1580  if ($direction == 'rte') {
1581  $code = $this->mapTags($code, array(
1582  // Map tags
1583  'b' => 'strong',
1584  'i' => 'em'
1585  ));
1586  }
1587  return $code;
1588  }
1589 
1598  public function getWHFromAttribs($attribArray) {
1599  $style = trim($attribArray['style']);
1600  if ($style) {
1601  $regex = '[[:space:]]*:[[:space:]]*([0-9]*)[[:space:]]*px';
1602  // Width
1603  $reg = array();
1604  preg_match('/width' . $regex . '/i', $style, $reg);
1605  $w = (int)$reg[1];
1606  // Height
1607  preg_match('/height' . $regex . '/i', $style, $reg);
1608  $h = (int)$reg[1];
1609  }
1610  if (!$w) {
1611  $w = $attribArray['width'];
1612  }
1613  if (!$h) {
1614  $h = $attribArray['height'];
1615  }
1616  return array((int)$w, (int)$h);
1617  }
1618 
1626  public function urlInfoForLinkTags($url) {
1627  $info = array();
1628  $url = trim($url);
1629  if (substr(strtolower($url), 0, 7) == 'mailto:') {
1630  $info['url'] = trim(substr($url, 7));
1631  $info['type'] = 'email';
1632  } elseif (strpos($url, '?file:') !== FALSE) {
1633  $info['type'] = 'file';
1634  $info['url'] = rawurldecode(substr($url, strpos($url, '?file:') + 1));
1635  } else {
1636  $curURL = $this->siteUrl();
1637  $urlLength = strlen($url);
1638  for ($a = 0; $a < $urlLength; $a++) {
1639  if ($url[$a] != $curURL[$a]) {
1640  break;
1641  }
1642  }
1643  $info['relScriptPath'] = substr($curURL, $a);
1644  $info['relUrl'] = substr($url, $a);
1645  $info['url'] = $url;
1646  $info['type'] = 'ext';
1647  $siteUrl_parts = parse_url($url);
1648  $curUrl_parts = parse_url($curURL);
1649  // Hosts should match
1650  if ($siteUrl_parts['host'] == $curUrl_parts['host'] && (!$info['relScriptPath'] || defined('TYPO3_mainDir') && substr($info['relScriptPath'], 0, strlen(TYPO3_mainDir)) == TYPO3_mainDir)) {
1651  // If the script path seems to match or is empty (FE-EDIT)
1652  // New processing order 100502
1653  $uP = parse_url($info['relUrl']);
1654  if ($info['relUrl'] === '#' . $siteUrl_parts['fragment']) {
1655  $info['url'] = $info['relUrl'];
1656  $info['type'] = 'anchor';
1657  } elseif (!trim($uP['path']) || $uP['path'] === 'index.php') {
1658  // URL is a page (id parameter)
1659  $pp = preg_split('/^id=/', $uP['query']);
1660  $pp[1] = preg_replace('/&id=[^&]*/', '', $pp[1]);
1661  $parameters = explode('&', $pp[1]);
1662  $id = array_shift($parameters);
1663  if ($id) {
1664  $info['pageid'] = $id;
1665  $info['cElement'] = $uP['fragment'];
1666  $info['url'] = $id . ($info['cElement'] ? '#' . $info['cElement'] : '');
1667  $info['type'] = 'page';
1668  $info['query'] = $parameters[0] ? '&' . implode('&', $parameters) : '';
1669  }
1670  } else {
1671  $info['url'] = $info['relUrl'];
1672  $info['type'] = 'file';
1673  }
1674  } else {
1675  unset($info['relScriptPath']);
1676  unset($info['relUrl']);
1677  }
1678  }
1679  return $info;
1680  }
1681 
1690  public function TS_AtagToAbs($value, $dontSetRTEKEEP = FALSE) {
1691  $blockSplit = $this->splitIntoBlock('A', $value);
1692  foreach ($blockSplit as $k => $v) {
1693  // Block
1694  if ($k % 2) {
1695  $attribArray = $this->get_tag_attributes_classic($this->getFirstTag($v), 1);
1696  // Checking if there is a scheme, and if not, prepend the current url.
1697  // ONLY do this if href has content - the <a> tag COULD be an anchor and if so, it should be preserved...
1698  if (strlen($attribArray['href'])) {
1699  $uP = parse_url(strtolower($attribArray['href']));
1700  if (!$uP['scheme']) {
1701  $attribArray['href'] = $this->siteUrl() . substr($attribArray['href'], strlen($this->relBackPath));
1702  } elseif ($uP['scheme'] != 'mailto') {
1703  $attribArray['data-htmlarea-external'] = 1;
1704  }
1705  } else {
1706  $attribArray['rtekeep'] = 1;
1707  }
1708  if (!$dontSetRTEKEEP) {
1709  $attribArray['rtekeep'] = 1;
1710  }
1711  $bTag = '<a ' . GeneralUtility::implodeAttributes($attribArray, 1) . '>';
1712  $eTag = '</a>';
1713  $blockSplit[$k] = $bTag . $this->TS_AtagToAbs($this->removeFirstAndLastTag($blockSplit[$k])) . $eTag;
1714  }
1715  }
1716  return implode('', $blockSplit);
1717  }
1718 
1727  protected function applyPlainImageModeSettings($imageInfo, $attribArray) {
1728  if ($this->procOptions['plainImageMode']) {
1729  // Perform corrections to aspect ratio based on configuration
1730  switch ((string) $this->procOptions['plainImageMode']) {
1731  case 'lockDimensions':
1732  $attribArray['width'] = $imageInfo[0];
1733  $attribArray['height'] = $imageInfo[1];
1734  break;
1735  case 'lockRatioWhenSmaller':
1736  if ($attribArray['width'] > $imageInfo[0]) {
1737  $attribArray['width'] = $imageInfo[0];
1738  }
1739  case 'lockRatio':
1740  if ($imageInfo[0] > 0) {
1741  $attribArray['height'] = round($attribArray['width'] * ($imageInfo[1] / $imageInfo[0]));
1742  }
1743  break;
1744  }
1745  }
1746  return $attribArray;
1747  }
1748 
1752  protected function getLogger() {
1753 
1755  $logManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager');
1756 
1757  return $logManager->getLogger(get_class($this));
1758  }
1759 
1760 }
getFirstTagName($str, $preserveCase=FALSE)
Definition: HtmlParser.php:514
TS_AtagToAbs($value, $dontSetRTEKEEP=FALSE)
splitIntoBlock($tag, $content, $eliminateExtraEndTags=FALSE)
Definition: HtmlParser.php:319
static implodeAttributes(array $arr, $xhtmlSafe=FALSE, $dontOmitBlankAttribs=FALSE)
$parameters
Definition: FileDumpEID.php:15
static getRecordsByField($theTable, $theField, $theValue, $whereClause='', $groupBy='', $orderBy='', $limit='', $useDeleteClause=TRUE)
HTMLcleaner_db($content, $tagList='')
static isFirstPartOfStr($str, $partStr)
static forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:32
removeTables($value, $breakChar='< br/>')
mapTags($value, $tags=array(), $ltChar='<', $ltChar2='<')
applyPlainImageModeSettings($imageInfo, $attribArray)
HTMLparserConfig($TSconfig, $keepTags=array())
const TYPO3_MODE
Definition: init.php:40
static getUserObj($classRef, $checkPrefix='', $silent=FALSE)
getAllParts($parts, $tag_parts=TRUE, $include_tag=TRUE)
Definition: HtmlParser.php:461
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
compileTagAttribs($tagAttrib, $meta=array(), $xhtmlClean=0)
get_tag_attributes($tag, $deHSC=0)
Definition: HtmlParser.php:534
static unQuoteFilenames($parameters, $unQuote=FALSE)
getKeepTags($direction='rte', $tagList='')
defaultTStagMapping($code, $direction='rte')
static getUrl($url, $includeHeader=0, $requestHeaders=FALSE, &$report=NULL)
divideIntoLines($value, $count=5, $returnArray=FALSE)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
cleanFontTags($value, $keepFace=0, $keepSize=0, $keepColor=0)
static getFileAbsFileName($filename, $onlyRelative=TRUE, $relToTYPO3_mainDir=FALSE)
TS_transform_db($value, $css=FALSE)
static evalWriteFile($pArr, $currentRecord)
get_tag_attributes_classic($tag, $deHSC=0)