Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2006 Kasper Skaarhoj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00083 require_once (PATH_t3lib.'class.t3lib_parsehtml.php'); 00084 00085 00086 00087 00088 00089 00090 00091 00092 00093 00094 00095 00103 class t3lib_parsehtml_proc extends t3lib_parsehtml { 00104 00105 // Static: 00106 var $headListTags = 'PRE,UL,OL,H1,H2,H3,H4,H5,H6,HR,ADDRESS,DL'; // List of tags for these elements 00107 00108 // Internal, static: 00109 var $recPid = 0; // Set this to the pid of the record manipulated by the class. 00110 var $elRef = ''; // Element reference [table]:[field], eg. "tt_content:bodytext" 00111 var $relPath=''; // Relative path 00112 var $relBackPath=''; // Relative back-path 00113 var $procOptions = ''; // Set to the TSconfig options coming from Page TSconfig 00114 00115 // Internal, dynamic 00116 var $TS_transform_db_safecounter=100; // Run-away brake for recursive calls. 00117 var $rte_p=''; // Parameters from TCA types configuration related to the RTE 00118 var $getKeepTags_cache=array(); // Data caching for processing function 00119 var $allowedClasses=array(); // Storage of the allowed CSS class names in the RTE 00120 var $preserveTags = ''; // Set to tags to preserve from Page TSconfig configuration 00121 00122 00123 00124 00125 00126 00127 00128 00129 00130 00138 function init($elRef='',$recPid=0) { 00139 $this->recPid = $recPid; 00140 $this->elRef = $elRef; 00141 } 00142 00150 function setRelPath($path) { 00151 $path = trim($path); 00152 $path = ereg_replace('^/','',$path); 00153 $path = ereg_replace('/$','',$path); 00154 if ($path) { 00155 $this->relPath = $path; 00156 $this->relBackPath = ''; 00157 $partsC=count(explode('/',$this->relPath)); 00158 for ($a=0;$a<$partsC;$a++) { 00159 $this->relBackPath.='../'; 00160 } 00161 $this->relPath.='/'; 00162 } 00163 } 00164 00174 function evalWriteFile($pArr,$currentRecord) { 00175 00176 // Write file configuration: 00177 if (is_array($pArr)) { 00178 if ($GLOBALS['TYPO3_CONF_VARS']['BE']['staticFileEditPath'] 00179 && substr($GLOBALS['TYPO3_CONF_VARS']['BE']['staticFileEditPath'],-1)=='/' 00180 && @is_dir(PATH_site.$GLOBALS['TYPO3_CONF_VARS']['BE']['staticFileEditPath'])) { 00181 00182 $SW_p = $pArr['parameters']; 00183 $SW_editFileField = trim($SW_p[0]); 00184 $SW_editFile = $currentRecord[$SW_editFileField]; 00185 if ($SW_editFileField && $SW_editFile && t3lib_div::validPathStr($SW_editFile)) { 00186 $SW_relpath = $GLOBALS['TYPO3_CONF_VARS']['BE']['staticFileEditPath'].$SW_editFile; 00187 $SW_editFile = PATH_site.$SW_relpath; 00188 if (@is_file($SW_editFile)) { 00189 return array( 00190 'editFile' => $SW_editFile, 00191 'relEditFile' => $SW_relpath, 00192 'contentField' => trim($SW_p[1]), 00193 'markerField' => trim($SW_p[2]), 00194 'loadFromFileField' => trim($SW_p[3]), 00195 'statusField' => trim($SW_p[4]) 00196 ); 00197 } else return "ERROR: Editfile '".$SW_relpath."' did not exist"; 00198 } else return "ERROR: Edit file name could not be found or was bad."; 00199 } else return "ERROR: staticFileEditPath was not set, not set correctly or did not exist!"; 00200 } 00201 } 00202 00203 00204 00205 00206 00207 00208 00209 00210 00211 00212 00213 00214 00215 /********************************************** 00216 * 00217 * Main function 00218 * 00219 **********************************************/ 00220 00232 function RTE_transform($value,$specConf,$direction='rte',$thisConfig=array()) { 00233 00234 // Init: 00235 $this->procOptions = $thisConfig['proc.']; 00236 $this->preserveTags = strtoupper(implode(',',t3lib_div::trimExplode(',',$this->procOptions['preserveTags']))); 00237 00238 // Get parameters for rte_transformation: 00239 $p = $this->rte_p = t3lib_BEfunc::getSpecConfParametersFromArray($specConf['rte_transform']['parameters']); 00240 00241 // Setting modes: 00242 if (strcmp($this->procOptions['overruleMode'],'')) { 00243 $modes = array_unique(t3lib_div::trimExplode(',',$this->procOptions['overruleMode'])); 00244 } else { 00245 $modes = array_unique(t3lib_div::trimExplode('-',$p['mode'])); 00246 } 00247 $revmodes = array_flip($modes); 00248 00249 // Find special modes and extract them: 00250 if (isset($revmodes['ts'])) { 00251 $modes[$revmodes['ts']] = 'ts_transform,ts_preserve,ts_images,ts_links'; 00252 } 00253 // Find special modes and extract them: 00254 if (isset($revmodes['ts_css'])) { 00255 $modes[$revmodes['ts_css']] = 'css_transform,ts_images,ts_links'; 00256 } 00257 00258 // Make list unique 00259 $modes = array_unique(t3lib_div::trimExplode(',',implode(',',$modes),1)); 00260 00261 // Reverse order if direction is "rte" 00262 if ($direction=='rte') { 00263 $modes = array_reverse($modes); 00264 } 00265 00266 // 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: 00267 $entry_HTMLparser = $this->procOptions['entryHTMLparser_'.$direction] ? $this->HTMLparserConfig($this->procOptions['entryHTMLparser_'.$direction.'.']) : ''; 00268 $exit_HTMLparser = $this->procOptions['exitHTMLparser_'.$direction] ? $this->HTMLparserConfig($this->procOptions['exitHTMLparser_'.$direction.'.']) : ''; 00269 00270 // Line breaks of content is unified into char-10 only (removing char 13) 00271 if (!$this->procOptions['disableUnifyLineBreaks']) { 00272 $value = str_replace(chr(13).chr(10),chr(10),$value); 00273 } 00274 00275 // In an entry-cleaner was configured, pass value through the HTMLcleaner with that: 00276 if (is_array($entry_HTMLparser)) { 00277 $value = $this->HTMLcleaner($value,$entry_HTMLparser[0],$entry_HTMLparser[1],$entry_HTMLparser[2],$entry_HTMLparser[3]); 00278 } 00279 00280 // Traverse modes: 00281 foreach($modes as $cmd) { 00282 // ->DB 00283 if ($direction=='db') { 00284 // Checking for user defined transformation: 00285 if ($_classRef = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['transformation'][$cmd]) { 00286 $_procObj = &t3lib_div::getUserObj($_classRef); 00287 $_procObj->pObj = &$this; 00288 $_procObj->transformationKey = $cmd; 00289 $value = $_procObj->transform_db($value,$this); 00290 } else { // ... else use defaults: 00291 switch($cmd) { 00292 case 'ts_images': 00293 $value = $this->TS_images_db($value); 00294 break; 00295 case 'ts_reglinks': 00296 $value = $this->TS_reglinks($value,'db'); 00297 break; 00298 case 'ts_links': 00299 $value = $this->TS_links_db($value); 00300 break; 00301 case 'ts_preserve': 00302 $value = $this->TS_preserve_db($value); 00303 break; 00304 case 'ts_transform': 00305 case 'css_transform': 00306 $value = str_replace(chr(13),'',$value); // Has a very disturbing effect, so just remove all '13' - depend on '10' 00307 $this->allowedClasses = t3lib_div::trimExplode(',',strtoupper($this->procOptions['allowedClasses']),1); 00308 $value = $this->TS_transform_db($value,$cmd=='css_transform'); 00309 break; 00310 case 'ts_strip': 00311 $value = $this->TS_strip_db($value); 00312 break; 00313 default: 00314 break; 00315 } 00316 } 00317 } 00318 // ->RTE 00319 if ($direction=='rte') { 00320 // Checking for user defined transformation: 00321 if ($_classRef = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_parsehtml_proc.php']['transformation'][$cmd]) { 00322 $_procObj = &t3lib_div::getUserObj($_classRef); 00323 $_procObj->pObj = &$this; 00324 $value = $_procObj->transform_rte($value,$this); 00325 } else { // ... else use defaults: 00326 switch($cmd) { 00327 case 'ts_images': 00328 $value = $this->TS_images_rte($value); 00329 break; 00330 case 'ts_reglinks': 00331 $value = $this->TS_reglinks($value,'rte'); 00332 break; 00333 case 'ts_links': 00334 $value = $this->TS_links_rte($value); 00335 break; 00336 case 'ts_preserve': 00337 $value = $this->TS_preserve_rte($value); 00338 break; 00339 case 'ts_transform': 00340 case 'css_transform': 00341 $value = str_replace(chr(13),'',$value); // Has a very disturbing effect, so just remove all '13' - depend on '10' 00342 $value = $this->TS_transform_rte($value,$cmd=='css_transform'); 00343 break; 00344 default: 00345 break; 00346 } 00347 } 00348 } 00349 } 00350 00351 // In an exit-cleaner was configured, pass value through the HTMLcleaner with that: 00352 if (is_array($exit_HTMLparser)) { 00353 $value = $this->HTMLcleaner($value,$exit_HTMLparser[0],$exit_HTMLparser[1],$exit_HTMLparser[2],$exit_HTMLparser[3]); 00354 } 00355 00356 // Final clean up of linebreaks: 00357 if (!$this->procOptions['disableUnifyLineBreaks']) { 00358 $value = str_replace(chr(13).chr(10),chr(10),$value); // Make sure no \r\n sequences has entered in the meantime... 00359 $value = str_replace(chr(10),chr(13).chr(10),$value); // ... and then change all \n into \r\n 00360 } 00361 00362 // Return value: 00363 return $value; 00364 } 00365 00366 00367 00368 00369 00370 00371 00372 00373 00374 00375 00376 00377 00378 00379 00380 00381 /************************************ 00382 * 00383 * Specific RTE TRANSFORMATION functions 00384 * 00385 *************************************/ 00386 00398 function TS_images_db($value) { 00399 00400 // Split content by <img> tags and traverse the resulting array for processing: 00401 $imgSplit = $this->splitTags('img',$value); 00402 foreach($imgSplit as $k => $v) { 00403 if ($k%2) { // image found, do processing: 00404 00405 // Init 00406 $attribArray = $this->get_tag_attributes_classic($v,1); 00407 $siteUrl = $this->siteUrl(); 00408 $sitePath = str_replace (t3lib_div::getIndpEnv('TYPO3_REQUEST_HOST'), '', $siteUrl); 00409 00410 $absRef = trim($attribArray['src']); // It's always a absolute URL coming from the RTE into the Database. 00411 00412 // make path absolute if it is relative and we have a site path wich is not '/' 00413 $pI=pathinfo($absRef); 00414 if($sitePath AND !$pI['scheme'] && t3lib_div::isFirstPartOfStr($absRef,$sitePath)) { 00415 // if site is in a subpath (eg. /~user_jim/) this path needs to be removed because it will be added with $siteUrl 00416 $absRef = substr($absRef,strlen($sitePath)); 00417 $absRef = $siteUrl.$absRef; 00418 } 00419 00420 // External image from another URL? In that case, fetch image (unless disabled feature). 00421 if (!t3lib_div::isFirstPartOfStr($absRef,$siteUrl) && !$this->procOptions['dontFetchExtPictures']) { 00422 $externalFile = $this->getUrl($absRef); // Get it 00423 if ($externalFile) { 00424 $pU = parse_url($absRef); 00425 $pI=pathinfo($pU['path']); 00426 00427 if (t3lib_div::inList('gif,png,jpeg,jpg',strtolower($pI['extension']))) { 00428 $filename = t3lib_div::shortMD5($absRef).'.'.$pI['extension']; 00429 $origFilePath = PATH_site.$this->rteImageStorageDir().'RTEmagicP_'.$filename; 00430 $C_origFilePath = PATH_site.$this->rteImageStorageDir().'RTEmagicC_'.$filename.'.'.$pI['extension']; 00431 if (!@is_file($origFilePath)) { 00432 t3lib_div::writeFile($origFilePath,$externalFile); 00433 t3lib_div::writeFile($C_origFilePath,$externalFile); 00434 } 00435 $absRef = $siteUrl.$this->rteImageStorageDir().'RTEmagicC_'.$filename.'.'.$pI['extension']; 00436 00437 $attribArray['src']=$absRef; 00438 $params = t3lib_div::implodeAttributes($attribArray,1); 00439 $imgSplit[$k] = '<img '.$params.' />'; 00440 } 00441 } 00442 } 00443 00444 // Check image as local file (siteURL equals the one of the image) 00445 if (t3lib_div::isFirstPartOfStr($absRef,$siteUrl)) { 00446 $path = rawurldecode(substr($absRef,strlen($siteUrl))); // Rel-path, rawurldecoded for special characters. 00447 $filepath = t3lib_div::getFileAbsFileName($path); // Abs filepath, locked to relative path of this project. 00448 00449 // Check file existence (in relative dir to this installation!) 00450 if ($filepath && @is_file($filepath)) { 00451 00452 // If "magic image": 00453 $pathPre=$this->rteImageStorageDir().'RTEmagicC_'; 00454 if (t3lib_div::isFirstPartOfStr($path,$pathPre)) { 00455 // Find original file: 00456 $pI=pathinfo(substr($path,strlen($pathPre))); 00457 $filename = substr($pI['basename'],0,-strlen('.'.$pI['extension'])); 00458 $origFilePath = PATH_site.$this->rteImageStorageDir().'RTEmagicP_'.$filename; 00459 if (@is_file($origFilePath)) { 00460 $imgObj = t3lib_div::makeInstance('t3lib_stdGraphic'); 00461 $imgObj->init(); 00462 $imgObj->mayScaleUp=0; 00463 $imgObj->tempPath=PATH_site.$imgObj->tempPath; 00464 00465 $curInfo = $imgObj->getImageDimensions($filepath); // Image dimensions of the current image 00466 $curWH = $this->getWHFromAttribs($attribArray); // Image dimensions as set in the image tag 00467 // Compare dimensions: 00468 if ($curWH[0]!=$curInfo[0] || $curWH[1]!=$curInfo[1]) { 00469 $origImgInfo = $imgObj->getImageDimensions($origFilePath); // Image dimensions of the current image 00470 $cW = $curWH[0]; 00471 $cH = $curWH[1]; 00472 $cH = 1000; // Make the image based on the width solely... 00473 $imgI = $imgObj->imageMagickConvert($origFilePath,$pI['extension'],$cW.'m',$cH.'m'); 00474 if ($imgI[3]) { 00475 $fI=pathinfo($imgI[3]); 00476 @copy($imgI[3],$filepath); // Override the child file 00477 unset($attribArray['style']); 00478 $attribArray['width']=$imgI[0]; 00479 $attribArray['height']=$imgI[1]; 00480 if (!$attribArray['border']) $attribArray['border']=0; 00481 $params = t3lib_div::implodeAttributes($attribArray,1); 00482 $imgSplit[$k]='<img '.$params.' />'; 00483 } 00484 } 00485 } 00486 00487 } elseif ($this->procOptions['plainImageMode']) { // If "plain image" has been configured: 00488 00489 // Image dimensions as set in the image tag 00490 $curWH = $this->getWHFromAttribs($attribArray); 00491 $attribArray['width'] = $curWH[0]; 00492 $attribArray['height'] = $curWH[1]; 00493 00494 // Forcing values for style and border: 00495 unset($attribArray['style']); 00496 if (!$attribArray['border']) $attribArray['border'] = 0; 00497 00498 // Finding dimensions of image file: 00499 $fI = @getimagesize($filepath); 00500 00501 // Perform corrections to aspect ratio based on configuration: 00502 switch((string)$this->procOptions['plainImageMode']) { 00503 case 'lockDimensions': 00504 $attribArray['width']=$fI[0]; 00505 $attribArray['height']=$fI[1]; 00506 break; 00507 case 'lockRatioWhenSmaller': // If the ratio has to be smaller, then first set the width...: 00508 if ($attribArray['width']>$fI[0]) $attribArray['width'] = $fI[0]; 00509 case 'lockRatio': 00510 if ($fI[0]>0) { 00511 $attribArray['height']=round($attribArray['width']*($fI[1]/$fI[0])); 00512 } 00513 break; 00514 } 00515 00516 // Compile the image tag again: 00517 $params = t3lib_div::implodeAttributes($attribArray,1); 00518 $imgSplit[$k]='<img '.$params.' />'; 00519 } 00520 } else { // Remove image if it was not found in a proper position on the server! 00521 00522 // Commented out; removing the image tag might not be that logical... 00523 #$imgSplit[$k]=''; 00524 } 00525 } 00526 00527 // Convert abs to rel url 00528 if ($imgSplit[$k]) { 00529 $attribArray=$this->get_tag_attributes_classic($imgSplit[$k],1); 00530 $absRef = trim($attribArray['src']); 00531 if (t3lib_div::isFirstPartOfStr($absRef,$siteUrl)) { 00532 $attribArray['src'] = $this->relBackPath.substr($absRef,strlen($siteUrl)); 00533 if (!isset($attribArray['alt'])) $attribArray['alt']=''; // Must have alt-attribute for XHTML compliance. 00534 $imgSplit[$k]='<img '.t3lib_div::implodeAttributes($attribArray,1,1).' />'; 00535 } 00536 } 00537 } 00538 } 00539 return implode('',$imgSplit); 00540 } 00541 00550 function TS_images_rte($value) { 00551 00552 $siteUrl = $this->siteUrl(); 00553 $sitePath = str_replace (t3lib_div::getIndpEnv('TYPO3_REQUEST_HOST'), '', $siteUrl); 00554 00555 // Split content by <img> tags and traverse the resulting array for processing: 00556 $imgSplit = $this->splitTags('img',$value); 00557 foreach($imgSplit as $k => $v) { 00558 if ($k%2) { // image found: 00559 00560 // Init 00561 $attribArray=$this->get_tag_attributes_classic($v,1); 00562 $absRef = trim($attribArray['src']); 00563 00564 // Unless the src attribute is already pointing to an external URL: 00565 if (strtolower(substr($absRef,0,4))!='http') { 00566 $attribArray['src'] = substr($attribArray['src'],strlen($this->relBackPath)); 00567 // if site is in a subpath (eg. /~user_jim/) this path needs to be removed because it will be added with $siteUrl 00568 $attribArray['src'] = preg_replace('#^'.preg_quote($sitePath,'#').'#','',$attribArray['src']); 00569 $attribArray['src'] = $siteUrl.$attribArray['src']; 00570 if (!isset($attribArray['alt'])) $attribArray['alt']=''; 00571 $params = t3lib_div::implodeAttributes($attribArray); 00572 $imgSplit[$k]='<img '.$params.' />'; 00573 } 00574 } 00575 } 00576 00577 // return processed content: 00578 return implode('',$imgSplit); 00579 } 00580 00589 function TS_reglinks($value,$direction) { 00590 $retVal = ''; 00591 00592 switch($direction) { 00593 case 'rte': 00594 $retVal = $this->TS_AtagToAbs($value,1); 00595 break; 00596 case 'db': 00597 $siteURL = $this->siteUrl(); 00598 $blockSplit = $this->splitIntoBlock('A',$value); 00599 reset($blockSplit); 00600 while(list($k,$v)=each($blockSplit)) { 00601 if ($k%2) { // block: 00602 $attribArray=$this->get_tag_attributes_classic($this->getFirstTag($v),1); 00603 // If the url is local, remove url-prefix 00604 if ($siteURL && substr($attribArray['href'],0,strlen($siteURL))==$siteURL) { 00605 $attribArray['href']=$this->relBackPath.substr($attribArray['href'],strlen($siteURL)); 00606 } 00607 $bTag='<a '.t3lib_div::implodeAttributes($attribArray,1).'>'; 00608 $eTag='</a>'; 00609 $blockSplit[$k] = $bTag.$this->TS_reglinks($this->removeFirstAndLastTag($blockSplit[$k]),$direction).$eTag; 00610 } 00611 } 00612 $retVal = implode('',$blockSplit); 00613 break; 00614 } 00615 return $retVal; 00616 } 00617 00626 function TS_links_db($value) { 00627 00628 // Split content into <a> tag blocks and process: 00629 $blockSplit = $this->splitIntoBlock('A',$value); 00630 foreach($blockSplit as $k => $v) { 00631 if ($k%2) { // If an A-tag was found: 00632 $attribArray = $this->get_tag_attributes_classic($this->getFirstTag($v),1); 00633 $info = $this->urlInfoForLinkTags($attribArray['href']); 00634 00635 // Check options: 00636 $attribArray_copy = $attribArray; 00637 unset($attribArray_copy['href']); 00638 unset($attribArray_copy['target']); 00639 unset($attribArray_copy['class']); 00640 unset($attribArray_copy['title']); 00641 if ($attribArray_copy['rteerror']) { // Unset "rteerror" and "style" attributes if "rteerror" is set! 00642 unset($attribArray_copy['style']); 00643 unset($attribArray_copy['rteerror']); 00644 } 00645 if (!count($attribArray_copy)) { // Only if href, target and class are the only attributes, we can alter the link! 00646 // Creating the TYPO3 pseudo-tag "<LINK>" for the link (includes href/url, target and class attributes): 00647 $bTag='<link '.$info['url'].($attribArray['target']?' '.$attribArray['target']:(($attribArray['class'] || $attribArray['title'])?' -':'')).($attribArray['class']?' '.$attribArray['class']:($attribArray['title']?' -':'')).($attribArray['title']?' "'.$attribArray['title'].'"':'').'>'; 00648 $eTag='</link>'; 00649 $blockSplit[$k] = $bTag.$this->TS_links_db($this->removeFirstAndLastTag($blockSplit[$k])).$eTag; 00650 } else { // ... otherwise store the link as a-tag. 00651 // Unsetting 'rtekeep' attribute if that had been set. 00652 unset($attribArray['rtekeep']); 00653 // If the url is local, remove url-prefix 00654 $siteURL = $this->siteUrl(); 00655 if ($siteURL && substr($attribArray['href'],0,strlen($siteURL))==$siteURL) { 00656 $attribArray['href']=$this->relBackPath.substr($attribArray['href'],strlen($siteURL)); 00657 } 00658 $bTag='<a '.t3lib_div::implodeAttributes($attribArray,1).'>'; 00659 $eTag='</a>'; 00660 $blockSplit[$k] = $bTag.$this->TS_links_db($this->removeFirstAndLastTag($blockSplit[$k])).$eTag; 00661 } 00662 } 00663 } 00664 return implode('',$blockSplit); 00665 } 00666 00675 function TS_links_rte($value) { 00676 $value = $this->TS_AtagToAbs($value); 00677 00678 // Split content by the TYPO3 pseudo tag "<link>": 00679 $blockSplit = $this->splitIntoBlock('link',$value,1); 00680 foreach($blockSplit as $k => $v) { 00681 $error = ''; 00682 if ($k%2) { // block: 00683 $tagCode = t3lib_div::unQuoteFilenames(trim(substr($this->getFirstTag($v),0,-1)),true); 00684 $link_param = $tagCode[1]; 00685 $href = ''; 00686 $siteUrl = $this->siteUrl(); 00687 // Parsing the typolink data. This parsing is roughly done like in tslib_content->typolink() 00688 if(strstr($link_param,'@')) { // mailadr 00689 $href = 'mailto:'.eregi_replace('^mailto:','',$link_param); 00690 } elseif (substr($link_param,0,1)=='#') { // check if anchor 00691 $href = $siteUrl.$link_param; 00692 } else { 00693 $fileChar=intval(strpos($link_param, '/')); 00694 $urlChar=intval(strpos($link_param, '.')); 00695 00696 // Detects if a file is found in site-root OR is a simulateStaticDocument. 00697 list($rootFileDat) = explode('?',$link_param); 00698 $rFD_fI = pathinfo($rootFileDat); 00699 if (trim($rootFileDat) && !strstr($link_param,'/') && (@is_file(PATH_site.$rootFileDat) || t3lib_div::inList('php,html,htm',strtolower($rFD_fI['extension'])))) { 00700 $href = $siteUrl.$link_param; 00701 } elseif($urlChar && (strstr($link_param,'//') || !$fileChar || $urlChar<$fileChar)) { // url (external): If doubleSlash or if a '.' comes before a '/'. 00702 if (!ereg('^[a-z]*://',trim(strtolower($link_param)))) {$scheme='http://';} else {$scheme='';} 00703 $href = $scheme.$link_param; 00704 } elseif($fileChar) { // file (internal) 00705 $href = $siteUrl.$link_param; 00706 } else { // integer or alias (alias is without slashes or periods or commas, that is 'nospace,alphanum_x,lower,unique' according to tables.php!!) 00707 $link_params_parts = explode('#',$link_param); 00708 $idPart = trim($link_params_parts[0]); // Link-data del 00709 if (!strcmp($idPart,'')) { $idPart=$this->recPid; } // If no id or alias is given, set it to class record pid 00710 00711 // FIXME commented because useless - what is it for? 00712 // if ($link_params_parts[1] && !$sectionMark) { 00713 // $sectionMark = '#'.trim($link_params_parts[1]); 00714 // } 00715 00716 // Splitting the parameter by ',' and if the array counts more than 1 element it's a id/type/? pair 00717 $pairParts = t3lib_div::trimExplode(',',$idPart); 00718 if (count($pairParts)>1) { 00719 $idPart = $pairParts[0]; 00720 // Type ? future support for? 00721 } 00722 // Checking if the id-parameter is an alias. 00723 if (!t3lib_div::testInt($idPart)) { 00724 list($idPartR) = t3lib_BEfunc::getRecordsByField('pages','alias',$idPart); 00725 $idPart = intval($idPartR['uid']); 00726 } 00727 $page = t3lib_BEfunc::getRecord('pages', $idPart); 00728 if (is_array($page)) { // Page must exist... 00729 $href = $siteUrl.'?id='.$link_param; 00730 } else { 00731 #$href = ''; 00732 $href = $siteUrl.'?id='.$link_param; 00733 $error = 'No page found: '.$idPart; 00734 } 00735 } 00736 } 00737 00738 // Setting the A-tag: 00739 $bTag = '<a href="'.htmlspecialchars($href).'"'. 00740 ($tagCode[2]&&$tagCode[2]!='-' ? ' target="'.htmlspecialchars($tagCode[2]).'"' : ''). 00741 ($tagCode[3]&&$tagCode[3]!='-' ? ' class="'.htmlspecialchars($tagCode[3]).'"' : ''). 00742 ($tagCode[4] ? ' title="'.htmlspecialchars($tagCode[4]).'"' : ''). 00743 ($error ? ' rteerror="'.htmlspecialchars($error).'" style="background-color: yellow; border:2px red solid; color: black;"' : ''). // Should be OK to add the style; the transformation back to databsae will remove it... 00744 '>'; 00745 $eTag = '</a>'; 00746 $blockSplit[$k] = $bTag.$this->TS_links_rte($this->removeFirstAndLastTag($blockSplit[$k])).$eTag; 00747 } 00748 } 00749 00750 // Return content: 00751 return implode('',$blockSplit); 00752 } 00753 00760 function TS_preserve_db($value) { 00761 if (!$this->preserveTags) return $value; 00762 00763 // Splitting into blocks for processing (span-tags are used for special tags) 00764 $blockSplit = $this->splitIntoBlock('span',$value); 00765 foreach($blockSplit as $k => $v) { 00766 if ($k%2) { // block: 00767 $attribArray=$this->get_tag_attributes_classic($this->getFirstTag($v)); 00768 if ($attribArray['specialtag']) { 00769 $theTag = rawurldecode($attribArray['specialtag']); 00770 $theTagName = $this->getFirstTagName($theTag); 00771 $blockSplit[$k] = $theTag.$this->removeFirstAndLastTag($blockSplit[$k]).'</'.$theTagName.'>'; 00772 } 00773 } 00774 } 00775 return implode('',$blockSplit); 00776 } 00777 00784 function TS_preserve_rte($value) { 00785 if (!$this->preserveTags) return $value; 00786 00787 $blockSplit = $this->splitIntoBlock($this->preserveTags,$value); 00788 foreach($blockSplit as $k => $v) { 00789 if ($k%2) { // block: 00790 $blockSplit[$k] = '<span specialtag="'.rawurlencode($this->getFirstTag($v)).'">'.$this->removeFirstAndLastTag($blockSplit[$k]).'</span>'; 00791 } 00792 } 00793 return implode('',$blockSplit); 00794 } 00795 00805 function TS_transform_db($value,$css=FALSE) { 00806 00807 // safety... so forever loops are avoided (they should not occur, but an error would potentially do this...) 00808 $this->TS_transform_db_safecounter--; 00809 if ($this->TS_transform_db_safecounter<0) return $value; 00810 00811 // Split the content from RTE by the occurence of these blocks: 00812 $blockSplit = $this->splitIntoBlock('TABLE,BLOCKQUOTE,'.$this->headListTags,$value); 00813 00814 $cc=0; 00815 $aC = count($blockSplit); 00816 00817 // Avoid superfluous linebreaks by transform_db after ending headListTag 00818 while($aC && !strcmp(trim($blockSplit[$aC-1]),'')) { 00819 unset($blockSplit[$aC-1]); 00820 $aC = count($blockSplit); 00821 } 00822 00823 // Traverse the blocks 00824 foreach($blockSplit as $k => $v) { 00825 $cc++; 00826 $lastBR = $cc==$aC ? '' : chr(10); 00827 00828 if ($k%2) { // Inside block: 00829 00830 // Init: 00831 $tag=$this->getFirstTag($v); 00832 $tagName=strtolower($this->getFirstTagName($v)); 00833 00834 // Process based on the tag: 00835 switch($tagName) { 00836 case 'blockquote': // Keep blockquotes, but clean the inside recursively in the same manner as the main code 00837 $blockSplit[$k]='<'.$tagName.'>'.$this->TS_transform_db($this->removeFirstAndLastTag($blockSplit[$k]),$css).'</'.$tagName.'>'.$lastBR; 00838 break; 00839 case 'ol': 00840 case 'ul': // Transform lists into <typolist>-tags: 00841 if (!$css) { 00842 if (!isset($this->procOptions['typolist']) || $this->procOptions['typolist']) { 00843 $parts = $this->getAllParts($this->splitIntoBlock('LI',$this->removeFirstAndLastTag($blockSplit[$k])),1,0); 00844 while(list($k2)=each($parts)) { 00845 $parts[$k2]=preg_replace('/['.preg_quote(chr(10).chr(13)).']+/','',$parts[$k2]); // remove all linesbreaks! 00846 $parts[$k2]=$this->defaultTStagMapping($parts[$k2],'db'); 00847 $parts[$k2]=$this->cleanFontTags($parts[$k2],0,0,0); 00848 $parts[$k2] = $this->HTMLcleaner_db($parts[$k2],strtolower($this->procOptions['allowTagsInTypolists']?$this->procOptions['allowTagsInTypolists']:'br,font,b,i,u,a,img,span,strong,em')); 00849 } 00850 if ($tagName=='ol') { $params=' type="1"'; } else { $params=''; } 00851 $blockSplit[$k]='<typolist'.$params.'>'.chr(10).implode(chr(10),$parts).chr(10).'</typolist>'.$lastBR; 00852 } 00853 } else { 00854 $blockSplit[$k]=preg_replace('/['.preg_quote(chr(10).chr(13)).']+/',' ',$this->transformStyledATags($blockSplit[$k])).$lastBR; 00855 } 00856 break; 00857 case 'table': // Tables are NOT allowed in any form (unless preserveTables is set or CSS is the mode) 00858 if (!$this->procOptions['preserveTables'] && !$css) { 00859 $blockSplit[$k]=$this->TS_transform_db($this->removeTables($blockSplit[$k])); 00860 } else { 00861 $blockSplit[$k]=preg_replace('/['.preg_quote(chr(10).chr(13)).']+/',' ',$this->transformStyledATags($blockSplit[$k])).$lastBR; 00862 } 00863 break; 00864 case 'h1': 00865 case 'h2': 00866 case 'h3': 00867 case 'h4': 00868 case 'h5': 00869 case 'h6': 00870 if (!$css) { 00871 $attribArray=$this->get_tag_attributes_classic($tag); 00872 // Processing inner content here: 00873 $innerContent = $this->HTMLcleaner_db($this->removeFirstAndLastTag($blockSplit[$k])); 00874 00875 if (!isset($this->procOptions['typohead']) || $this->procOptions['typohead']) { 00876 $type = intval(substr($tagName,1)); 00877 $blockSplit[$k]='<typohead'. 00878 ($type!=6?' type="'.$type.'"':''). 00879 ($attribArray['align']?' align="'.$attribArray['align'].'"':''). 00880 ($attribArray['class']?' class="'.$attribArray['class'].'"':''). 00881 '>'. 00882 $innerContent. 00883 '</typohead>'. 00884 $lastBR; 00885 } else { 00886 $blockSplit[$k]='<'.$tagName. 00887 ($attribArray['align']?' align="'.htmlspecialchars($attribArray['align']).'"':''). 00888 ($attribArray['class']?' class="'.htmlspecialchars($attribArray['class']).'"':''). 00889 '>'. 00890 $innerContent. 00891 '</'.$tagName.'>'. 00892 $lastBR; 00893 } 00894 } else { 00895 // Eliminate true linebreaks inside Hx tags 00896 $blockSplit[$k]=preg_replace('/['.preg_quote(chr(10).chr(13)).']+/',' ',$this->transformStyledATags($blockSplit[$k])).$lastBR; 00897 } 00898 break; 00899 default: 00900 // Eliminate true linebreaks inside other headlist tags and after hr tag 00901 $blockSplit[$k]=preg_replace('/['.preg_quote(chr(10).chr(13)).']+/',' ',$this->transformStyledATags($blockSplit[$k])).$lastBR; 00902 break; 00903 } 00904 } else { // NON-block: 00905 if (strcmp(trim($blockSplit[$k]),'')) { 00906 $blockSplit[$k]=$this->divideIntoLines(preg_replace('/['.preg_quote(chr(10).chr(13)).']+/',' ',$blockSplit[$k])).$lastBR; 00907 $blockSplit[$k]=$this->transformStyledATags($blockSplit[$k]); 00908 } else unset($blockSplit[$k]); 00909 } 00910 } 00911 $this->TS_transform_db_safecounter++; 00912 00913 return implode('',$blockSplit); 00914 } 00915 00922 function transformStyledATags($value) { 00923 $blockSplit = $this->splitIntoBlock('A',$value); 00924 foreach($blockSplit as $k => $v) { 00925 if ($k%2) { // If an A-tag was found: 00926 $attribArray = $this->get_tag_attributes_classic($this->getFirstTag($v),1); 00927 if ($attribArray['style']) { // If "style" attribute is set! 00928 $attribArray_copy['style'] = $attribArray['style']; 00929 unset($attribArray['style']); 00930 $bTag='<span '.t3lib_div::implodeAttributes($attribArray_copy,1).'><a '.t3lib_div::implodeAttributes($attribArray,1).'>'; 00931 $eTag='</a></span>'; 00932 $blockSplit[$k] = $bTag.$this->removeFirstAndLastTag($blockSplit[$k]).$eTag; 00933 } 00934 } 00935 } 00936 return implode('',$blockSplit); 00937 } 00938 00948 function TS_transform_rte($value,$css=0) { 00949 00950 // Split the content from Database by the occurence of these blocks: 00951 $blockSplit = $this->splitIntoBlock('TABLE,BLOCKQUOTE,TYPOLIST,TYPOHEAD,'.$this->headListTags,$value); 00952 00953 // Traverse the blocks 00954 foreach($blockSplit as $k => $v) { 00955 if ($k%2) { // Inside one of the blocks: 00956 00957 // Init: 00958 $tag = $this->getFirstTag($v); 00959 $tagName = strtolower($this->getFirstTagName($v)); 00960 $attribArray = $this->get_tag_attributes_classic($tag); 00961 00962 // Based on tagname, we do transformations: 00963 switch($tagName) { 00964 case 'blockquote': // Keep blockquotes: 00965 $blockSplit[$k] = $tag. 00966 $this->TS_transform_rte($this->removeFirstAndLastTag($blockSplit[$k]),$css). 00967 '</'.$tagName.'>'; 00968 break; 00969 case 'typolist': // Transform typolist blocks into OL/UL lists. Type 1 is expected to be numerical block 00970 if (!isset($this->procOptions['typolist']) || $this->procOptions['typolist']) { 00971 $tListContent = $this->removeFirstAndLastTag($blockSplit[$k]); 00972 $tListContent = ereg_replace('^[ ]*'.chr(10),'',$tListContent); 00973 $tListContent = ereg_replace(chr(10).'[ ]*$','',$tListContent); 00974 $lines = explode(chr(10),$tListContent); 00975 $typ = $attribArray['type']==1 ? 'ol' : 'ul'; 00976 $blockSplit[$k] = '<'.$typ.'>'.chr(10). 00977 '<li>'.implode('</li>'.chr(10).'<li>',$lines).'</li>'. 00978 '</'.$typ.'>'; 00979 } 00980 break; 00981 case 'typohead': // Transform typohead into Hx tags. 00982 if (!isset($this->procOptions['typohead']) || $this->procOptions['typohead']) { 00983 $tC = $this->removeFirstAndLastTag($blockSplit[$k]); 00984 $typ = t3lib_div::intInRange($attribArray['type'],0,6); 00985 if (!$typ) $typ=6; 00986 $align = $attribArray['align']?' align="'.$attribArray['align'].'"': ''; 00987 $class = $attribArray['class']?' class="'.$attribArray['class'].'"': ''; 00988 $blockSplit[$k] = '<h'.$typ.$align.$class.'>'. 00989 $tC. 00990 '</h'.$typ.'>'; 00991 } 00992 break; 00993 } 00994 $blockSplit[$k+1] = ereg_replace('^[ ]*'.chr(10),'',$blockSplit[$k+1]); // Removing linebreak if typohead 00995 } else { // NON-block: 00996 $nextFTN = $this->getFirstTagName($blockSplit[$k+1]); 00997 $singleLineBreak = $blockSplit[$k]==chr(10); 00998 if (t3lib_div::inList('TABLE,BLOCKQUOTE,TYPOLIST,TYPOHEAD,'.$this->headListTags,$nextFTN)) { // Removing linebreak if typolist/typohead 00999 $blockSplit[$k] = ereg_replace(chr(10).'[ ]*$','',$blockSplit[$k]); 01000 } 01001 // If $blockSplit[$k] is blank then unset the line. UNLESS the line happend to be a single line break. 01002 if (!strcmp($blockSplit[$k],'') && !$singleLineBreak) { 01003 unset($blockSplit[$k]); 01004 } else { 01005 $blockSplit[$k] = $this->setDivTags($blockSplit[$k],($this->procOptions['useDIVasParagraphTagForRTE']?'div':'p')); 01006 } 01007 } 01008 } 01009 return implode(chr(10),$blockSplit); 01010 } 01011 01019 function TS_strip_db($value) { 01020 $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')).'>'); 01021 return $value; 01022 } 01023 01024 01025 01026 01027 01028 01029 01030 01031 01032 01033 01034 01035 01036 01037 /*************************************************************** 01038 * 01039 * Generic RTE transformation, analysis and helper functions 01040 * 01041 **************************************************************/ 01042 01050 function getURL($url) { 01051 return t3lib_div::getURL($url); 01052 } 01053 01064 function HTMLcleaner_db($content,$tagList='') { 01065 if (!$tagList) { 01066 $keepTags = $this->getKeepTags('db'); 01067 } else { 01068 $keepTags = $this->getKeepTags('db',$tagList); 01069 } 01070 $kUknown = $this->procOptions['dontRemoveUnknownTags_db'] ? 1 : 0; // Default: remove unknown tags. 01071 $hSC = $this->procOptions['dontUndoHSC_db'] ? 0 : -1; // Default: re-convert literals to characters (that is < to <) 01072 01073 // Create additional configuration in order to honor the setting RTE.default.proc.HTMLparser_db.xhtml_cleaning=1 01074 $addConfig=array(); 01075 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'])) { 01076 $addConfig['xhtml']=1; 01077 } 01078 01079 return $this->HTMLcleaner($content,$keepTags,$kUknown,$hSC,$addConfig); 01080 } 01081 01091 function getKeepTags($direction='rte',$tagList='') { 01092 if (!is_array($this->getKeepTags_cache[$direction]) || $tagList) { 01093 01094 // Setting up allowed tags: 01095 if (strcmp($tagList,'')) { // If the $tagList input var is set, this will take precedence 01096 $keepTags = array_flip(t3lib_div::trimExplode(',',$tagList,1)); 01097 } else { // Default is to get allowed/denied tags from internal array of processing options: 01098 // Construct default list of tags to keep: 01099 $typoScript_list = 'b,i,u,a,img,br,div,center,pre,font,hr,sub,sup,p,strong,em,li,ul,ol,blockquote,strike,span'; 01100 $keepTags = array_flip(t3lib_div::trimExplode(',',$typoScript_list.','.strtolower($this->procOptions['allowTags']),1)); 01101 01102 // For tags to deny, remove them from $keepTags array: 01103 $denyTags = t3lib_div::trimExplode(',',$this->procOptions['denyTags'],1); 01104 foreach($denyTags as $dKe) { 01105 unset($keepTags[$dKe]); 01106 } 01107 } 01108 01109 // Based on the direction of content, set further options: 01110 switch ($direction) { 01111 01112 // GOING from database to Rich Text Editor: 01113 case 'rte': 01114 // Transform bold/italics tags to strong/em 01115 if (isset($keepTags['b'])) {$keepTags['b']=array('remap'=>'STRONG');} 01116 if (isset($keepTags['i'])) {$keepTags['i']=array('remap'=>'EM');} 01117 01118 // 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. 01119 list($keepTags) = $this->HTMLparserConfig($this->procOptions['HTMLparser_rte.'],$keepTags); 01120 break; 01121 01122 // GOING from RTE to database: 01123 case 'db': 01124 // Transform strong/em back to bold/italics: 01125 if (isset($keepTags['strong'])) { $keepTags['strong']=array('remap'=>'b'); } 01126 if (isset($keepTags['em'])) { $keepTags['em']=array('remap'=>'i'); } 01127 01128 // Setting up span tags if they are allowed: 01129 if (isset($keepTags['span'])) { 01130 $classes=array_merge(array(''),$this->allowedClasses); 01131 $keepTags['span']=array( 01132 'allowedAttribs' => 'class,style,xml:lang', 01133 'fixAttrib' => Array( 01134 'class' => Array ( 01135 'list' => $classes, 01136 'removeIfFalse' => 1 01137 ) 01138 ), 01139 'rmTagIfNoAttrib' => 1 01140 ); 01141 if (!$this->procOptions['allowedClasses']) unset($keepTags['span']['fixAttrib']['class']['list']); 01142 } 01143 01144 // Setting up font tags if they are allowed: 01145 if (isset($keepTags['font'])) { 01146 $colors=array_merge(array(''),t3lib_div::trimExplode(',',$this->procOptions['allowedFontColors'],1)); 01147 $keepTags['font']=array( 01148 'allowedAttribs'=>'face,color,size', 01149 'fixAttrib' => Array( 01150 'face' => Array ( 01151 'removeIfFalse' => 1 01152 ), 01153 'color' => Array ( 01154 'removeIfFalse' => 1, 01155 'list'=>$colors 01156 ), 01157 'size' => Array ( 01158 'removeIfFalse' => 1, 01159 ) 01160 ), 01161 'rmTagIfNoAttrib' => 1 01162 ); 01163 if (!$this->procOptions['allowedFontColors']) unset($keepTags['font']['fixAttrib']['color']['list']); 01164 } 01165 01166 // Setting further options, getting them from the processiong options: 01167 $TSc = $this->procOptions['HTMLparser_db.']; 01168 if (!$TSc['globalNesting']) $TSc['globalNesting']='b,i,u,a,center,font,sub,sup,strong,em,strike,span'; 01169 if (!$TSc['noAttrib']) $TSc['noAttrib']='b,i,u,br,center,hr,sub,sup,strong,em,li,ul,ol,blockquote,strike'; 01170 01171 // Transforming the array from TypoScript to regular array: 01172 list($keepTags) = $this->HTMLparserConfig($TSc,$keepTags); 01173 break; 01174 } 01175 01176 // Caching (internally, in object memory) the result unless tagList is set: 01177 if (!$tagList) { 01178 $this->getKeepTags_cache[$direction] = $keepTags; 01179 } else { 01180 return $keepTags; 01181 } 01182 } 01183 01184 // Return result: 01185 return $this->getKeepTags_cache[$direction]; 01186 } 01187 01200 function divideIntoLines($value,$count=5,$returnArray=FALSE) { 01201 01202 // Internalize font tags (move them from OUTSIDE p/div to inside it that is the case): 01203 if ($this->procOptions['internalizeFontTags']) {$value = $this->internalizeFontTags($value);} 01204 01205 // Setting configuration for processing: 01206 $allowTagsOutside = t3lib_div::trimExplode(',',strtolower($this->procOptions['allowTagsOutside']?$this->procOptions['allowTagsOutside']:'img'),1); 01207 $remapParagraphTag = strtoupper($this->procOptions['remapParagraphTag']); 01208 $divSplit = $this->splitIntoBlock('div,p',$value,1); // Setting the third param to 1 will eliminate false end-tags. Maybe this is a good thing to do...? 01209 01210 if ($this->procOptions['keepPDIVattribs']) { 01211 $keepAttribListArr = t3lib_div::trimExplode(',',strtolower($this->procOptions['keepPDIVattribs']),1); 01212 } else { 01213 $keepAttribListArr = array(); 01214 } 01215 01216 // Returns plainly the value if there was no div/p sections in it 01217 if (count($divSplit)<=1 || $count<=0) { 01218 return $value; 01219 } 01220 01221 // Traverse the splitted sections: 01222 foreach($divSplit as $k => $v) { 01223 if ($k%2) { // Inside 01224 $v=$this->removeFirstAndLastTag($v); 01225 01226 // Fetching 'sub-lines' - which will explode any further p/div nesting... 01227 $subLines = $this->divideIntoLines($v,$count-1,1); 01228 if (is_array($subLines)) { // 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') 01229 // No noting. 01230 } else { //... but if NO subsection was found, we process it as a TRUE line without erronous content: 01231 $subLines = array($subLines); 01232 if (!$this->procOptions['dontConvBRtoParagraph']) { // process break-tags, if configured for. Simply, the breaktags will here be treated like if each was a line of content... 01233 $subLines = spliti('<br[[:space:]]*[\/]?>',$v); 01234 } 01235 01236 // Traverse sublines (there is typically one, except if <br/> has been converted to lines as well!) 01237 reset($subLines); 01238 while(list($sk)=each($subLines)) { 01239 01240 // Clear up the subline for DB. 01241 $subLines[$sk]=$this->HTMLcleaner_db($subLines[$sk]); 01242 01243 // Get first tag, attributes etc: 01244 $fTag = $this->getFirstTag($divSplit[$k]); 01245 $tagName=strtolower($this->getFirstTagName($divSplit[$k])); 01246 $attribs=$this->get_tag_attributes($fTag); 01247 01248 // Keep attributes (lowercase) 01249 $newAttribs=array(); 01250 if (count($keepAttribListArr)) { 01251 foreach($keepAttribListArr as $keepA) { 01252 if (isset($attribs[0][$keepA])) { $newAttribs[$keepA] = $attribs[0][$keepA]; } 01253 } 01254 } 01255 01256 // ALIGN attribute: 01257 if (!$this->procOptions['skipAlign'] && strcmp(trim($attribs[0]['align']),'') && strtolower($attribs[0]['align'])!='left') { // Set to value, but not 'left' 01258 $newAttribs['align']=strtolower($attribs[0]['align']); 01259 } 01260 01261 // CLASS attribute: 01262 if (!$this->procOptions['skipClass'] && strcmp(trim($attribs[0]['class']),'')) { // Set to whatever value 01263 if (!count($this->allowedClasses) || in_array(strtoupper($attribs[0]['class']),$this->allowedClasses)) { 01264 $newAttribs['class']=$attribs[0]['class']; 01265 } 01266 } 01267 01268 // Remove any line break char (10 or 13) 01269 $subLines[$sk]=ereg_replace(chr(10).'|'.chr(13),'',$subLines[$sk]); 01270 01271 // If there are any attributes or if we are supposed to remap the tag, then do so: 01272 if (count($newAttribs) && strcmp($remapParagraphTag,'1')) { 01273 if ($remapParagraphTag=='P') $tagName='p'; 01274 if ($remapParagraphTag=='DIV') $tagName='div'; 01275 $subLines[$sk]='<'.trim($tagName.' '.$this->compileTagAttribs($newAttribs)).'>'.$subLines[$sk].'</'.$tagName.'>'; 01276 } 01277 } 01278 } 01279 // Add the processed line(s) 01280 $divSplit[$k] = implode(chr(10),$subLines); 01281 01282 // If it turns out the line is just blank (containing a possibly) then just make it pure blank: 01283 if (trim(strip_tags($divSplit[$k]))==' ' && !preg_match('/\<(img)(\s[^>]*)?\/?>/si', $divSplit[$k])) { 01284 $divSplit[$k]=''; 01285 } 01286 } else { // outside div: 01287 // Remove positions which are outside div/p tags and without content 01288 $divSplit[$k]=trim(strip_tags($divSplit[$k],'<'.implode('><',$allowTagsOutside).'>')); 01289 if (!strcmp($divSplit[$k],'')) unset($divSplit[$k]); // Remove part if it's empty 01290 } 01291 } 01292 01293 // Return value: 01294 return $returnArray ? $divSplit : implode(chr(10),$divSplit); 01295 } 01296 01306 function setDivTags($value,$dT='p') { 01307 01308 // First, setting configuration for the HTMLcleaner function. This will process each line between the <div>/<p> section on their way to the RTE 01309 $keepTags = $this->getKeepTags('rte'); 01310 $kUknown = $this->procOptions['dontProtectUnknownTags_rte'] ? 0 : 'protect'; // Default: remove unknown tags. 01311 $hSC = $this->procOptions['dontHSC_rte'] ? 0 : 1; // Default: re-convert literals to characters (that is < to <) 01312 $convNBSP = !$this->procOptions['dontConvAmpInNBSP_rte']?1:0; 01313 01314 // Divide the content into lines, based on chr(10): 01315 $parts = explode(chr(10),$value); 01316 foreach($parts as $k => $v) { 01317 01318 // Processing of line content: 01319 if (!strcmp(trim($parts[$k]),'')) { // If the line is blank, set it to 01320 $parts[$k]=' '; 01321 } else { // Clean the line content: 01322 $parts[$k]=$this->HTMLcleaner($parts[$k],$keepTags,$kUknown,$hSC); 01323 if ($convNBSP) $parts[$k]=str_replace('&nbsp;',' ',$parts[$k]); 01324 } 01325 01326 // Wrapping the line in <$dT> is not already wrapped: 01327 $testStr = strtolower(trim($parts[$k])); 01328 if (substr($testStr,0,4)!='<div' || substr($testStr,-6)!='</div>') { 01329 if (substr($testStr,0,2)!='<p' || substr($testStr,-4)!='</p>') { 01330 // Only set p-tags if there is not already div or p tags: 01331 $parts[$k]='<'.$dT.'>'.$parts[$k].'</'.$dT.'>'; 01332 } 01333 } 01334 } 01335 01336 // Implode result: 01337 return implode(chr(10),$parts); 01338 } 01339 01351 function internalizeFontTags($value) { 01352 01353 // Splitting into font tag blocks: 01354 $fontSplit = $this->splitIntoBlock('font',$value); 01355 01356 foreach($fontSplit as $k => $v) { 01357 if ($k%2) { // Inside 01358 $fTag = $this->getFirstTag($v); // Fint font-tag 01359 01360 $divSplit_sub = $this->splitIntoBlock('div,p',$this->removeFirstAndLastTag($v),1); 01361 if (count($divSplit_sub)>1) { // If there were div/p sections inside the font-tag, do something about it... 01362 // traverse those sections: 01363 foreach($divSplit_sub as $k2 => $v2) { 01364 if ($k2%2) { // Inside 01365 $div_p = $this->getFirstTag($v2); // Fint font-tag 01366 $div_p_tagname = $this->getFirstTagName($v2); // Fint font-tag 01367 $v2=$this->removeFirstAndLastTag($v2); // ... and remove it from original. 01368 $divSplit_sub[$k2]=$div_p.$fTag.$v2.'</font>'.'</'.$div_p_tagname.'>'; 01369 } elseif (trim(strip_tags($v2))) { 01370 $divSplit_sub[$k2]=$fTag.$v2.'</font>'; 01371 } 01372 } 01373 $fontSplit[$k]=implode('',$divSplit_sub); 01374 } 01375 } 01376 } 01377 01378 return implode('',$fontSplit); 01379 } 01380 01387 function siteUrl() { 01388 return t3lib_div::getIndpEnv('TYPO3_SITE_URL'); 01389 } 01390 01397 function rteImageStorageDir() { 01398 return $this->rte_p['imgpath'] ? $this->rte_p['imgpath'] : $GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_imageStorageDir']; 01399 } 01400 01409 function removeTables($value,$breakChar='<br />') { 01410 01411 // Splitting value into table blocks: 01412 $tableSplit = $this->splitIntoBlock('table',$value); 01413 01414 // Traverse blocks of tables: 01415 foreach($tableSplit as $k => $v) { 01416 if ($k%2) { 01417 $tableSplit[$k]=''; 01418 $rowSplit = $this->splitIntoBlock('tr',$v); 01419 foreach($rowSplit as $k2 => $v2) { 01420 if ($k2%2) { 01421 $cellSplit = $this->getAllParts($this->splitIntoBlock('td',$v2),1,0); 01422 foreach($cellSplit as $k3 => $v3) { 01423 $tableSplit[$k].=$v3.$breakChar; 01424 } 01425 } 01426 } 01427 } 01428 } 01429 01430 // Implode it all again: 01431 return implode($breakChar,$tableSplit); 01432 } 01433 01441 function defaultTStagMapping($code,$direction='rte') { 01442 if ($direction=='db') { 01443 $code=$this->mapTags($code,array( // Map tags 01444 'strong' => 'b', 01445 'em' => 'i' 01446 )); 01447 } 01448 if ($direction=='rte') { 01449 $code=$this->mapTags($code,array( // Map tags 01450 'b' => 'strong', 01451 'i' => 'em' 01452 )); 01453 } 01454 return $code; 01455 } 01456 01464 function getWHFromAttribs($attribArray) { 01465 $style =trim($attribArray['style']); 01466 if ($style) { 01467 $regex='[[:space:]]*:[[:space:]]*([0-9]*)[[:space:]]*px'; 01468 // Width 01469 $reg = array(); 01470 eregi('width'.$regex,$style,$reg); 01471 $w = intval($reg[1]); 01472 // Height 01473 eregi('height'.$regex,$style,$reg); 01474 $h = intval($reg[1]); 01475 } 01476 if (!$w) { 01477 $w = $attribArray['width']; 01478 } 01479 if (!$h) { 01480 $h = $attribArray['height']; 01481 } 01482 return array(intval($w),intval($h)); 01483 } 01484 01491 function urlInfoForLinkTags($url) { 01492 $info = array(); 01493 $url = trim($url); 01494 if (substr(strtolower($url),0,7)=='mailto:') { 01495 $info['url']=trim(substr($url,7)); 01496 $info['type']='email'; 01497 } else { 01498 $curURL = $this->siteUrl(); // 100502, removed this: 'http://'.t3lib_div::getThisUrl(); Reason: The url returned had typo3/ in the end - should be only the site's url as far as I see... 01499 for($a=0;$a<strlen($url);$a++) { 01500 if ($url{$a}!=$curURL{$a}) { 01501 break; 01502 } 01503 } 01504 01505 $info['relScriptPath']=substr($curURL,$a); 01506 $info['relUrl']=substr($url,$a); 01507 $info['url']=$url; 01508 $info['type']='ext'; 01509 01510 $siteUrl_parts = parse_url($url); 01511 $curUrl_parts = parse_url($curURL); 01512 01513 if ($siteUrl_parts['host']==$curUrl_parts['host'] // Hosts should match 01514 && (!$info['relScriptPath'] || (defined('TYPO3_mainDir') && substr($info['relScriptPath'],0,strlen(TYPO3_mainDir))==TYPO3_mainDir))) { // If the script path seems to match or is empty (FE-EDIT) 01515 01516 // New processing order 100502 01517 $uP=parse_url($info['relUrl']); 01518 01519 if (!strcmp('#'.$siteUrl_parts['fragment'],$info['relUrl'])) { 01520 $info['url']=$info['relUrl']; 01521 $info['type']='anchor'; 01522 } elseif (!trim($uP['path']) || !strcmp($uP['path'],'index.php')) { 01523 $pp = explode('id=',$uP['query']); 01524 $id = trim($pp[1]); 01525 if ($id) { 01526 $info['pageid']=$id; 01527 $info['cElement']=$uP['fragment']; 01528 $info['url']=$id.($info['cElement']?'#'.$info['cElement']:''); 01529 $info['type']='page'; 01530 } 01531 } else { 01532 $info['url']=$info['relUrl']; 01533 $info['type']='file'; 01534 } 01535 } else { 01536 unset($info['relScriptPath']); 01537 unset($info['relUrl']); 01538 } 01539 } 01540 return $info; 01541 } 01542 01550 function TS_AtagToAbs($value,$dontSetRTEKEEP=FALSE) { 01551 $blockSplit = $this->splitIntoBlock('A',$value); 01552 reset($blockSplit); 01553 while(list($k,$v)=each($blockSplit)) { 01554 if ($k%2) { // block: 01555 $attribArray = $this->get_tag_attributes_classic($this->getFirstTag($v),1); 01556 01557 // Checking if there is a scheme, and if not, prepend the current url. 01558 if (strlen($attribArray['href'])) { // ONLY do this if href has content - the <a> tag COULD be an anchor and if so, it should be preserved... 01559 $uP = parse_url(strtolower($attribArray['href'])); 01560 if (!$uP['scheme']) { 01561 $attribArray['href'] = $this->siteUrl().substr($attribArray['href'],strlen($this->relBackPath)); 01562 } 01563 } else { 01564 $attribArray['rtekeep'] = 1; 01565 } 01566 if (!$dontSetRTEKEEP) $attribArray['rtekeep'] = 1; 01567 01568 $bTag='<a '.t3lib_div::implodeAttributes($attribArray,1).'>'; 01569 $eTag='</a>'; 01570 $blockSplit[$k] = $bTag.$this->TS_AtagToAbs($this->removeFirstAndLastTag($blockSplit[$k])).$eTag; 01571 } 01572 } 01573 return implode('',$blockSplit); 01574 } 01575 } 01576 01577 01578 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_parsehtml_proc.php']) { 01579 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_parsehtml_proc.php']); 01580 } 01581 ?>