"TYPO3 4.0.1: typo3_src-4.0.1/t3lib/class.t3lib_parsehtml_proc.php Source File", "datetime" => "Sat Dec 2 19:22:18 2006", "date" => "2 Dec 2006", "doxygenversion" => "1.4.6", "projectname" => "TYPO3 4.0.1", "projectnumber" => "4.0.1" ); get_header($doxygen_vars); ?>

class.t3lib_parsehtml_proc.php

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 &lt; 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 &nbsp; possibly) then just make it pure blank:
01283                                 if (trim(strip_tags($divSplit[$k]))=='&nbsp;' && !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 &lt; 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 &nbsp;
01320                                 $parts[$k]='&nbsp;';
01321                         } else {        // Clean the line content:
01322                                 $parts[$k]=$this->HTMLcleaner($parts[$k],$keepTags,$kUknown,$hSC);
01323                                 if ($convNBSP)  $parts[$k]=str_replace('&amp;nbsp;','&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 ?>